• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * schemas.c : implementation of the XML Schema handling and
3  *             schema validity checking
4  *
5  * See Copyright for the status of this software.
6  *
7  * Daniel Veillard <veillard@redhat.com>
8  */
9 
10 /*
11  * TODO:
12  *   - when types are redefined in includes, check that all
13  *     types in the redef list are equal
14  *     -> need a type equality operation.
15  *   - if we don't intend to use the schema for schemas, we
16  *     need to validate all schema attributes (ref, type, name)
17  *     against their types.
18  *   - Eliminate item creation for: ??
19  *
20  * URGENT TODO:
21  *   - For xsi-driven schema acquisition, augment the IDCs after every
22  *     acquisition episode (xmlSchemaAugmentIDC).
23  *
24  * NOTES:
25  *   - Eliminated item creation for: <restriction>, <extension>,
26  *     <simpleContent>, <complexContent>, <list>, <union>
27  *
28  * PROBLEMS:
29  *   - http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0337.html
30  *     IDC XPath expression and chameleon includes: the targetNamespace is changed, so
31  *     XPath will have trouble to resolve to this namespace, since not known.
32  *
33  *
34  * CONSTRAINTS:
35  *
36  * Schema Component Constraint:
37  *   All Group Limited (cos-all-limited)
38  *   Status: complete
39  *   (1.2)
40  *     In xmlSchemaGroupDefReferenceTermFixup() and
41  *   (2)
42  *     In xmlSchemaParseModelGroup()
43  *     TODO: Actually this should go to component-level checks,
44  *     but is done here due to performance. Move it to an other layer
45  *     is schema construction via an API is implemented.
46  */
47 
48 /* To avoid EBCDIC trouble when parsing on zOS */
49 #if defined(__MVS__)
50 #pragma convert("ISO8859-1")
51 #endif
52 
53 #define IN_LIBXML
54 #include "libxml.h"
55 
56 #ifdef LIBXML_SCHEMAS_ENABLED
57 
58 #include <string.h>
59 #include <libxml/xmlmemory.h>
60 #include <libxml/parser.h>
61 #include <libxml/parserInternals.h>
62 #include <libxml/hash.h>
63 #include <libxml/uri.h>
64 #include <libxml/xmlschemas.h>
65 #include <libxml/schemasInternals.h>
66 #include <libxml/xmlschemastypes.h>
67 #include <libxml/xmlautomata.h>
68 #include <libxml/xmlregexp.h>
69 #include <libxml/dict.h>
70 #include <libxml/encoding.h>
71 #include <libxml/xmlIO.h>
72 #ifdef LIBXML_PATTERN_ENABLED
73 #include <libxml/pattern.h>
74 #endif
75 #ifdef LIBXML_READER_ENABLED
76 #include <libxml/xmlreader.h>
77 #endif
78 
79 /* #define DEBUG 1 */
80 
81 /* #define DEBUG_CONTENT 1 */
82 
83 /* #define DEBUG_TYPE 1 */
84 
85 /* #define DEBUG_CONTENT_REGEXP 1 */
86 
87 /* #define DEBUG_AUTOMATA 1 */
88 
89 /* #define DEBUG_IDC */
90 
91 /* #define DEBUG_IDC_NODE_TABLE */
92 
93 /* #define WXS_ELEM_DECL_CONS_ENABLED */
94 
95 #ifdef DEBUG_IDC
96  #ifndef DEBUG_IDC_NODE_TABLE
97   #define DEBUG_IDC_NODE_TABLE
98  #endif
99 #endif
100 
101 /* #define ENABLE_PARTICLE_RESTRICTION 1 */
102 
103 #define ENABLE_REDEFINE
104 
105 /* #define ENABLE_NAMED_LOCALS */
106 
107 /* #define ENABLE_IDC_NODE_TABLES_TEST */
108 
109 #define DUMP_CONTENT_MODEL
110 
111 #ifdef LIBXML_READER_ENABLED
112 /* #define XML_SCHEMA_READER_ENABLED */
113 #endif
114 
115 #define UNBOUNDED (1 << 30)
116 #define TODO								\
117     xmlGenericError(xmlGenericErrorContext,				\
118 	    "Unimplemented block at %s:%d\n",				\
119             __FILE__, __LINE__);
120 
121 #define XML_SCHEMAS_NO_NAMESPACE (const xmlChar *) "##"
122 
123 /*
124  * The XML Schemas namespaces
125  */
126 static const xmlChar *xmlSchemaNs = (const xmlChar *)
127     "http://www.w3.org/2001/XMLSchema";
128 
129 static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
130     "http://www.w3.org/2001/XMLSchema-instance";
131 
132 static const xmlChar *xmlNamespaceNs = (const xmlChar *)
133     "http://www.w3.org/2000/xmlns/";
134 
135 /*
136 * Come casting macros.
137 */
138 #define ACTXT_CAST (xmlSchemaAbstractCtxtPtr)
139 #define PCTXT_CAST (xmlSchemaParserCtxtPtr)
140 #define VCTXT_CAST (xmlSchemaValidCtxtPtr)
141 #define WXS_BASIC_CAST (xmlSchemaBasicItemPtr)
142 #define WXS_TREE_CAST (xmlSchemaTreeItemPtr)
143 #define WXS_PTC_CAST (xmlSchemaParticlePtr)
144 #define WXS_TYPE_CAST (xmlSchemaTypePtr)
145 #define WXS_ELEM_CAST (xmlSchemaElementPtr)
146 #define WXS_ATTR_GROUP_CAST (xmlSchemaAttributeGroupPtr)
147 #define WXS_ATTR_CAST (xmlSchemaAttributePtr)
148 #define WXS_ATTR_USE_CAST (xmlSchemaAttributeUsePtr)
149 #define WXS_ATTR_PROHIB_CAST (xmlSchemaAttributeUseProhibPtr)
150 #define WXS_MODEL_GROUPDEF_CAST (xmlSchemaModelGroupDefPtr)
151 #define WXS_MODEL_GROUP_CAST (xmlSchemaModelGroupPtr)
152 #define WXS_IDC_CAST (xmlSchemaIDCPtr)
153 #define WXS_QNAME_CAST (xmlSchemaQNameRefPtr)
154 #define WXS_LIST_CAST (xmlSchemaItemListPtr)
155 
156 /*
157 * Macros to query common properties of components.
158 */
159 #define WXS_ITEM_NODE(i) xmlSchemaGetComponentNode(WXS_BASIC_CAST (i))
160 
161 #define WXS_ITEM_TYPE_NAME(i) xmlSchemaGetComponentTypeStr(WXS_BASIC_CAST (i))
162 /*
163 * Macros for element declarations.
164 */
165 #define WXS_ELEM_TYPEDEF(e) (e)->subtypes
166 
167 #define WXS_SUBST_HEAD(item) (item)->refDecl
168 /*
169 * Macros for attribute declarations.
170 */
171 #define WXS_ATTR_TYPEDEF(a) (a)->subtypes
172 /*
173 * Macros for attribute uses.
174 */
175 #define WXS_ATTRUSE_DECL(au) (WXS_ATTR_USE_CAST (au))->attrDecl
176 
177 #define WXS_ATTRUSE_TYPEDEF(au) WXS_ATTR_TYPEDEF(WXS_ATTRUSE_DECL( WXS_ATTR_USE_CAST au))
178 
179 #define WXS_ATTRUSE_DECL_NAME(au) (WXS_ATTRUSE_DECL(au))->name
180 
181 #define WXS_ATTRUSE_DECL_TNS(au) (WXS_ATTRUSE_DECL(au))->targetNamespace
182 /*
183 * Macros for attribute groups.
184 */
185 #define WXS_ATTR_GROUP_HAS_REFS(ag) ((WXS_ATTR_GROUP_CAST (ag))->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS)
186 #define WXS_ATTR_GROUP_EXPANDED(ag) ((WXS_ATTR_GROUP_CAST (ag))->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED)
187 /*
188 * Macros for particles.
189 */
190 #define WXS_PARTICLE(p) WXS_PTC_CAST (p)
191 
192 #define WXS_PARTICLE_TERM(p) (WXS_PARTICLE(p))->children
193 
194 #define WXS_PARTICLE_TERM_AS_ELEM(p) (WXS_ELEM_CAST WXS_PARTICLE_TERM(p))
195 
196 #define WXS_PARTICLE_MODEL(p) WXS_MODEL_GROUP_CAST WXS_PARTICLE(p)->children
197 /*
198 * Macros for model groups definitions.
199 */
200 #define WXS_MODELGROUPDEF_MODEL(mgd) (WXS_MODEL_GROUP_CAST (mgd))->children
201 /*
202 * Macros for model groups.
203 */
204 #define WXS_IS_MODEL_GROUP(i) \
205     (((i)->type == XML_SCHEMA_TYPE_SEQUENCE) || \
206      ((i)->type == XML_SCHEMA_TYPE_CHOICE) || \
207      ((i)->type == XML_SCHEMA_TYPE_ALL))
208 
209 #define WXS_MODELGROUP_PARTICLE(mg) WXS_PTC_CAST (mg)->children
210 /*
211 * Macros for schema buckets.
212 */
213 #define WXS_IS_BUCKET_INCREDEF(t) (((t) == XML_SCHEMA_SCHEMA_INCLUDE) || \
214     ((t) == XML_SCHEMA_SCHEMA_REDEFINE))
215 
216 #define WXS_IS_BUCKET_IMPMAIN(t) (((t) == XML_SCHEMA_SCHEMA_MAIN) || \
217     ((t) == XML_SCHEMA_SCHEMA_IMPORT))
218 
219 #define WXS_IMPBUCKET(b) ((xmlSchemaImportPtr) (b))
220 
221 #define WXS_INCBUCKET(b) ((xmlSchemaIncludePtr) (b))
222 /*
223 * Macros for complex/simple types.
224 */
225 #define WXS_IS_ANYTYPE(i) \
226      (( (i)->type == XML_SCHEMA_TYPE_BASIC) && \
227       ( (WXS_TYPE_CAST (i))->builtInType == XML_SCHEMAS_ANYTYPE))
228 
229 #define WXS_IS_COMPLEX(i) \
230     (((i)->type == XML_SCHEMA_TYPE_COMPLEX) || \
231      ((i)->builtInType == XML_SCHEMAS_ANYTYPE))
232 
233 #define WXS_IS_SIMPLE(item) \
234     ((item->type == XML_SCHEMA_TYPE_SIMPLE) || \
235      ((item->type == XML_SCHEMA_TYPE_BASIC) && \
236       (item->builtInType != XML_SCHEMAS_ANYTYPE)))
237 
238 #define WXS_IS_ANY_SIMPLE_TYPE(i) \
239     (((i)->type == XML_SCHEMA_TYPE_BASIC) && \
240       ((i)->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
241 
242 #define WXS_IS_RESTRICTION(t) \
243     ((t)->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)
244 
245 #define WXS_IS_EXTENSION(t) \
246     ((t)->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)
247 
248 #define WXS_IS_TYPE_NOT_FIXED(i) \
249     (((i)->type != XML_SCHEMA_TYPE_BASIC) && \
250      (((i)->flags & XML_SCHEMAS_TYPE_INTERNAL_RESOLVED) == 0))
251 
252 #define WXS_IS_TYPE_NOT_FIXED_1(item) \
253     (((item)->type != XML_SCHEMA_TYPE_BASIC) && \
254      (((item)->flags & XML_SCHEMAS_TYPE_FIXUP_1) == 0))
255 
256 #define WXS_TYPE_IS_GLOBAL(t) ((t)->flags & XML_SCHEMAS_TYPE_GLOBAL)
257 
258 #define WXS_TYPE_IS_LOCAL(t) (((t)->flags & XML_SCHEMAS_TYPE_GLOBAL) == 0)
259 /*
260 * Macros for exclusively for complex types.
261 */
262 #define WXS_HAS_COMPLEX_CONTENT(item) \
263     ((item->contentType == XML_SCHEMA_CONTENT_MIXED) || \
264      (item->contentType == XML_SCHEMA_CONTENT_EMPTY) || \
265      (item->contentType == XML_SCHEMA_CONTENT_ELEMENTS))
266 
267 #define WXS_HAS_SIMPLE_CONTENT(item) \
268     ((item->contentType == XML_SCHEMA_CONTENT_SIMPLE) || \
269      (item->contentType == XML_SCHEMA_CONTENT_BASIC))
270 
271 #define WXS_HAS_MIXED_CONTENT(item) \
272     (item->contentType == XML_SCHEMA_CONTENT_MIXED)
273 
274 #define WXS_EMPTIABLE(t) \
275     (xmlSchemaIsParticleEmptiable(WXS_PTC_CAST (t)->subtypes))
276 
277 #define WXS_TYPE_CONTENTTYPE(t) (t)->subtypes
278 
279 #define WXS_TYPE_PARTICLE(t) WXS_PTC_CAST (t)->subtypes
280 
281 #define WXS_TYPE_PARTICLE_TERM(t) WXS_PARTICLE_TERM(WXS_TYPE_PARTICLE(t))
282 /*
283 * Macros for exclusively for simple types.
284 */
285 #define WXS_LIST_ITEMTYPE(t) (t)->subtypes
286 
287 #define WXS_IS_ATOMIC(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
288 
289 #define WXS_IS_LIST(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
290 
291 #define WXS_IS_UNION(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)
292 /*
293 * Misc parser context macros.
294 */
295 #define WXS_CONSTRUCTOR(ctx) (ctx)->constructor
296 
297 #define WXS_HAS_BUCKETS(ctx) \
298 ( (WXS_CONSTRUCTOR((ctx))->buckets != NULL) && \
299 (WXS_CONSTRUCTOR((ctx))->buckets->nbItems > 0) )
300 
301 #define WXS_SUBST_GROUPS(ctx) WXS_CONSTRUCTOR((ctx))->substGroups
302 
303 #define WXS_BUCKET(ctx) WXS_CONSTRUCTOR((ctx))->bucket
304 
305 #define WXS_SCHEMA(ctx) (ctx)->schema
306 
307 #define WXS_ADD_LOCAL(ctx, item) \
308     xmlSchemaAddItemSize(&(WXS_BUCKET(ctx)->locals), 10, item)
309 
310 #define WXS_ADD_GLOBAL(ctx, item) \
311     xmlSchemaAddItemSize(&(WXS_BUCKET(ctx)->globals), 5, item)
312 
313 #define WXS_ADD_PENDING(ctx, item) \
314     xmlSchemaAddItemSize(&((ctx)->constructor->pending), 10, item)
315 /*
316 * xmlSchemaItemList macros.
317 */
318 #define WXS_ILIST_IS_EMPTY(l) ((l == NULL) || ((l)->nbItems == 0))
319 /*
320 * Misc macros.
321 */
322 #define IS_SCHEMA(node, type) \
323    ((node != NULL) && (node->ns != NULL) && \
324     (xmlStrEqual(node->name, (const xmlChar *) type)) && \
325     (xmlStrEqual(node->ns->href, xmlSchemaNs)))
326 
327 #define FREE_AND_NULL(str) if ((str) != NULL) { xmlFree((xmlChar *) (str)); str = NULL; }
328 
329 /*
330 * Since we put the default/fixed values into the dict, we can
331 * use pointer comparison for those values.
332 * REMOVED: (xmlStrEqual((v1), (v2)))
333 */
334 #define WXS_ARE_DEFAULT_STR_EQUAL(v1, v2) ((v1) == (v2))
335 
336 #define INODE_NILLED(item) (item->flags & XML_SCHEMA_ELEM_INFO_NILLED)
337 
338 #define CAN_PARSE_SCHEMA(b) (((b)->doc != NULL) && ((b)->parsed == 0))
339 
340 #define HFAILURE if (res == -1) goto exit_failure;
341 
342 #define HERROR if (res != 0) goto exit_error;
343 
344 #define HSTOP(ctx) if ((ctx)->stop) goto exit;
345 /*
346 * Some flags used for various schema constraints.
347 */
348 #define SUBSET_RESTRICTION  1<<0
349 #define SUBSET_EXTENSION    1<<1
350 #define SUBSET_SUBSTITUTION 1<<2
351 #define SUBSET_LIST         1<<3
352 #define SUBSET_UNION        1<<4
353 
354 typedef struct _xmlSchemaNodeInfo xmlSchemaNodeInfo;
355 typedef xmlSchemaNodeInfo *xmlSchemaNodeInfoPtr;
356 
357 typedef struct _xmlSchemaItemList xmlSchemaItemList;
358 typedef xmlSchemaItemList *xmlSchemaItemListPtr;
359 struct _xmlSchemaItemList {
360     void **items;  /* used for dynamic addition of schemata */
361     int nbItems; /* used for dynamic addition of schemata */
362     int sizeItems; /* used for dynamic addition of schemata */
363 };
364 
365 #define XML_SCHEMA_CTXT_PARSER 1
366 #define XML_SCHEMA_CTXT_VALIDATOR 2
367 
368 typedef struct _xmlSchemaAbstractCtxt xmlSchemaAbstractCtxt;
369 typedef xmlSchemaAbstractCtxt *xmlSchemaAbstractCtxtPtr;
370 struct _xmlSchemaAbstractCtxt {
371     int type; /* E.g. XML_SCHEMA_CTXT_VALIDATOR */
372     void *dummy; /* Fix alignment issues */
373 };
374 
375 typedef struct _xmlSchemaBucket xmlSchemaBucket;
376 typedef xmlSchemaBucket *xmlSchemaBucketPtr;
377 
378 #define XML_SCHEMA_SCHEMA_MAIN 0
379 #define XML_SCHEMA_SCHEMA_IMPORT 1
380 #define XML_SCHEMA_SCHEMA_INCLUDE 2
381 #define XML_SCHEMA_SCHEMA_REDEFINE 3
382 
383 /**
384  * xmlSchemaSchemaRelation:
385  *
386  * Used to create a graph of schema relationships.
387  */
388 typedef struct _xmlSchemaSchemaRelation xmlSchemaSchemaRelation;
389 typedef xmlSchemaSchemaRelation *xmlSchemaSchemaRelationPtr;
390 struct _xmlSchemaSchemaRelation {
391     xmlSchemaSchemaRelationPtr next;
392     int type; /* E.g. XML_SCHEMA_SCHEMA_IMPORT */
393     const xmlChar *importNamespace;
394     xmlSchemaBucketPtr bucket;
395 };
396 
397 #define XML_SCHEMA_BUCKET_MARKED 1<<0
398 #define XML_SCHEMA_BUCKET_COMPS_ADDED 1<<1
399 
400 struct _xmlSchemaBucket {
401     int type;
402     int flags;
403     const xmlChar *schemaLocation;
404     const xmlChar *origTargetNamespace;
405     const xmlChar *targetNamespace;
406     xmlDocPtr doc;
407     xmlSchemaSchemaRelationPtr relations;
408     int located;
409     int parsed;
410     int imported;
411     int preserveDoc;
412     xmlSchemaItemListPtr globals; /* Global components. */
413     xmlSchemaItemListPtr locals; /* Local components. */
414 };
415 
416 /**
417  * xmlSchemaImport:
418  * (extends xmlSchemaBucket)
419  *
420  * Reflects a schema. Holds some information
421  * about the schema and its toplevel components. Duplicate
422  * toplevel components are not checked at this level.
423  */
424 typedef struct _xmlSchemaImport xmlSchemaImport;
425 typedef xmlSchemaImport *xmlSchemaImportPtr;
426 struct _xmlSchemaImport {
427     int type; /* Main OR import OR include. */
428     int flags;
429     const xmlChar *schemaLocation; /* The URI of the schema document. */
430     /* For chameleon includes, @origTargetNamespace will be NULL */
431     const xmlChar *origTargetNamespace;
432     /*
433     * For chameleon includes, @targetNamespace will be the
434     * targetNamespace of the including schema.
435     */
436     const xmlChar *targetNamespace;
437     xmlDocPtr doc; /* The schema node-tree. */
438     /* @relations will hold any included/imported/redefined schemas. */
439     xmlSchemaSchemaRelationPtr relations;
440     int located;
441     int parsed;
442     int imported;
443     int preserveDoc;
444     xmlSchemaItemListPtr globals;
445     xmlSchemaItemListPtr locals;
446     /* The imported schema. */
447     xmlSchemaPtr schema;
448 };
449 
450 /*
451 * (extends xmlSchemaBucket)
452 */
453 typedef struct _xmlSchemaInclude xmlSchemaInclude;
454 typedef xmlSchemaInclude *xmlSchemaIncludePtr;
455 struct _xmlSchemaInclude {
456     int type;
457     int flags;
458     const xmlChar *schemaLocation;
459     const xmlChar *origTargetNamespace;
460     const xmlChar *targetNamespace;
461     xmlDocPtr doc;
462     xmlSchemaSchemaRelationPtr relations;
463     int located;
464     int parsed;
465     int imported;
466     int preserveDoc;
467     xmlSchemaItemListPtr globals; /* Global components. */
468     xmlSchemaItemListPtr locals; /* Local components. */
469 
470     /* The owning main or import schema bucket. */
471     xmlSchemaImportPtr ownerImport;
472 };
473 
474 /**
475  * xmlSchemaBasicItem:
476  *
477  * The abstract base type for schema components.
478  */
479 typedef struct _xmlSchemaBasicItem xmlSchemaBasicItem;
480 typedef xmlSchemaBasicItem *xmlSchemaBasicItemPtr;
481 struct _xmlSchemaBasicItem {
482     xmlSchemaTypeType type;
483     void *dummy; /* Fix alignment issues */
484 };
485 
486 /**
487  * xmlSchemaAnnotItem:
488  *
489  * The abstract base type for annotated schema components.
490  * (Extends xmlSchemaBasicItem)
491  */
492 typedef struct _xmlSchemaAnnotItem xmlSchemaAnnotItem;
493 typedef xmlSchemaAnnotItem *xmlSchemaAnnotItemPtr;
494 struct _xmlSchemaAnnotItem {
495     xmlSchemaTypeType type;
496     xmlSchemaAnnotPtr annot;
497 };
498 
499 /**
500  * xmlSchemaTreeItem:
501  *
502  * The abstract base type for tree-like structured schema components.
503  * (Extends xmlSchemaAnnotItem)
504  */
505 typedef struct _xmlSchemaTreeItem xmlSchemaTreeItem;
506 typedef xmlSchemaTreeItem *xmlSchemaTreeItemPtr;
507 struct _xmlSchemaTreeItem {
508     xmlSchemaTypeType type;
509     xmlSchemaAnnotPtr annot;
510     xmlSchemaTreeItemPtr next;
511     xmlSchemaTreeItemPtr children;
512 };
513 
514 
515 #define XML_SCHEMA_ATTR_USE_FIXED 1<<0
516 /**
517  * xmlSchemaAttributeUsePtr:
518  *
519  * The abstract base type for tree-like structured schema components.
520  * (Extends xmlSchemaTreeItem)
521  */
522 typedef struct _xmlSchemaAttributeUse xmlSchemaAttributeUse;
523 typedef xmlSchemaAttributeUse *xmlSchemaAttributeUsePtr;
524 struct _xmlSchemaAttributeUse {
525     xmlSchemaTypeType type;
526     xmlSchemaAnnotPtr annot;
527     xmlSchemaAttributeUsePtr next; /* The next attr. use. */
528     /*
529     * The attr. decl. OR a QName-ref. to an attr. decl. OR
530     * a QName-ref. to an attribute group definition.
531     */
532     xmlSchemaAttributePtr attrDecl;
533 
534     int flags;
535     xmlNodePtr node;
536     int occurs; /* required, optional */
537     const xmlChar * defValue;
538     xmlSchemaValPtr defVal;
539 };
540 
541 /**
542  * xmlSchemaAttributeUseProhibPtr:
543  *
544  * A helper component to reflect attribute prohibitions.
545  * (Extends xmlSchemaBasicItem)
546  */
547 typedef struct _xmlSchemaAttributeUseProhib xmlSchemaAttributeUseProhib;
548 typedef xmlSchemaAttributeUseProhib *xmlSchemaAttributeUseProhibPtr;
549 struct _xmlSchemaAttributeUseProhib {
550     xmlSchemaTypeType type; /* == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB */
551     xmlNodePtr node;
552     const xmlChar *name;
553     const xmlChar *targetNamespace;
554     int isRef;
555 };
556 
557 /**
558  * xmlSchemaRedef:
559  */
560 typedef struct _xmlSchemaRedef xmlSchemaRedef;
561 typedef xmlSchemaRedef *xmlSchemaRedefPtr;
562 struct _xmlSchemaRedef {
563     xmlSchemaRedefPtr next;
564     xmlSchemaBasicItemPtr item; /* The redefining component. */
565     xmlSchemaBasicItemPtr reference; /* The referencing component. */
566     xmlSchemaBasicItemPtr target; /* The to-be-redefined component. */
567     const xmlChar *refName; /* The name of the to-be-redefined component. */
568     const xmlChar *refTargetNs; /* The target namespace of the
569                                    to-be-redefined comp. */
570     xmlSchemaBucketPtr targetBucket; /* The redefined schema. */
571 };
572 
573 /**
574  * xmlSchemaConstructionCtxt:
575  */
576 typedef struct _xmlSchemaConstructionCtxt xmlSchemaConstructionCtxt;
577 typedef xmlSchemaConstructionCtxt *xmlSchemaConstructionCtxtPtr;
578 struct _xmlSchemaConstructionCtxt {
579     xmlSchemaPtr mainSchema; /* The main schema. */
580     xmlSchemaBucketPtr mainBucket; /* The main schema bucket */
581     xmlDictPtr dict;
582     xmlSchemaItemListPtr buckets; /* List of schema buckets. */
583     /* xmlSchemaItemListPtr relations; */ /* List of schema relations. */
584     xmlSchemaBucketPtr bucket; /* The current schema bucket */
585     xmlSchemaItemListPtr pending; /* All Components of all schemas that
586                                      need to be fixed. */
587     xmlHashTablePtr substGroups;
588     xmlSchemaRedefPtr redefs;
589     xmlSchemaRedefPtr lastRedef;
590 };
591 
592 #define XML_SCHEMAS_PARSE_ERROR		1
593 #define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
594 
595 struct _xmlSchemaParserCtxt {
596     int type;
597     void *errCtxt;             /* user specific error context */
598     xmlSchemaValidityErrorFunc error;   /* the callback in case of errors */
599     xmlSchemaValidityWarningFunc warning;       /* the callback in case of warning */
600     int err;
601     int nberrors;
602     xmlStructuredErrorFunc serror;
603 
604     xmlSchemaConstructionCtxtPtr constructor;
605     int ownsConstructor; /* TODO: Move this to parser *flags*. */
606 
607     /* xmlSchemaPtr topschema;	*/
608     /* xmlHashTablePtr namespaces;  */
609 
610     xmlSchemaPtr schema;        /* The main schema in use */
611     int counter;
612 
613     const xmlChar *URL;
614     xmlDocPtr doc;
615     int preserve;		/* Whether the doc should be freed  */
616 
617     const char *buffer;
618     int size;
619 
620     /*
621      * Used to build complex element content models
622      */
623     xmlAutomataPtr am;
624     xmlAutomataStatePtr start;
625     xmlAutomataStatePtr end;
626     xmlAutomataStatePtr state;
627 
628     xmlDictPtr dict;		/* dictionary for interned string names */
629     xmlSchemaTypePtr ctxtType; /* The current context simple/complex type */
630     int options;
631     xmlSchemaValidCtxtPtr vctxt;
632     int isS4S;
633     int isRedefine;
634     int xsiAssemble;
635     int stop; /* If the parser should stop; i.e. a critical error. */
636     const xmlChar *targetNamespace;
637     xmlSchemaBucketPtr redefined; /* The schema to be redefined. */
638 
639     xmlSchemaRedefPtr redef; /* Used for redefinitions. */
640     int redefCounter; /* Used for redefinitions. */
641     xmlSchemaItemListPtr attrProhibs;
642 };
643 
644 /**
645  * xmlSchemaQNameRef:
646  *
647  * A component reference item (not a schema component)
648  * (Extends xmlSchemaBasicItem)
649  */
650 typedef struct _xmlSchemaQNameRef xmlSchemaQNameRef;
651 typedef xmlSchemaQNameRef *xmlSchemaQNameRefPtr;
652 struct _xmlSchemaQNameRef {
653     xmlSchemaTypeType type;
654     xmlSchemaBasicItemPtr item; /* The resolved referenced item. */
655     xmlSchemaTypeType itemType;
656     const xmlChar *name;
657     const xmlChar *targetNamespace;
658     xmlNodePtr node;
659 };
660 
661 /**
662  * xmlSchemaParticle:
663  *
664  * A particle component.
665  * (Extends xmlSchemaTreeItem)
666  */
667 typedef struct _xmlSchemaParticle xmlSchemaParticle;
668 typedef xmlSchemaParticle *xmlSchemaParticlePtr;
669 struct _xmlSchemaParticle {
670     xmlSchemaTypeType type;
671     xmlSchemaAnnotPtr annot;
672     xmlSchemaTreeItemPtr next; /* next particle */
673     xmlSchemaTreeItemPtr children; /* the "term" (e.g. a model group,
674 	a group definition, a XML_SCHEMA_EXTRA_QNAMEREF (if a reference),
675         etc.) */
676     int minOccurs;
677     int maxOccurs;
678     xmlNodePtr node;
679 };
680 
681 /**
682  * xmlSchemaModelGroup:
683  *
684  * A model group component.
685  * (Extends xmlSchemaTreeItem)
686  */
687 typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
688 typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
689 struct _xmlSchemaModelGroup {
690     xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_SEQUENCE, XML_SCHEMA_TYPE_CHOICE, XML_SCHEMA_TYPE_ALL */
691     xmlSchemaAnnotPtr annot;
692     xmlSchemaTreeItemPtr next; /* not used */
693     xmlSchemaTreeItemPtr children; /* first particle (OR "element decl" OR "wildcard") */
694     xmlNodePtr node;
695 };
696 
697 #define XML_SCHEMA_MODEL_GROUP_DEF_MARKED 1<<0
698 #define XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED 1<<1
699 /**
700  * xmlSchemaModelGroupDef:
701  *
702  * A model group definition component.
703  * (Extends xmlSchemaTreeItem)
704  */
705 typedef struct _xmlSchemaModelGroupDef xmlSchemaModelGroupDef;
706 typedef xmlSchemaModelGroupDef *xmlSchemaModelGroupDefPtr;
707 struct _xmlSchemaModelGroupDef {
708     xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_GROUP */
709     xmlSchemaAnnotPtr annot;
710     xmlSchemaTreeItemPtr next; /* not used */
711     xmlSchemaTreeItemPtr children; /* the "model group" */
712     const xmlChar *name;
713     const xmlChar *targetNamespace;
714     xmlNodePtr node;
715     int flags;
716 };
717 
718 typedef struct _xmlSchemaIDC xmlSchemaIDC;
719 typedef xmlSchemaIDC *xmlSchemaIDCPtr;
720 
721 /**
722  * xmlSchemaIDCSelect:
723  *
724  * The identity-constraint "field" and "selector" item, holding the
725  * XPath expression.
726  */
727 typedef struct _xmlSchemaIDCSelect xmlSchemaIDCSelect;
728 typedef xmlSchemaIDCSelect *xmlSchemaIDCSelectPtr;
729 struct _xmlSchemaIDCSelect {
730     xmlSchemaIDCSelectPtr next;
731     xmlSchemaIDCPtr idc;
732     int index; /* an index position if significant for IDC key-sequences */
733     const xmlChar *xpath; /* the XPath expression */
734     void *xpathComp; /* the compiled XPath expression */
735 };
736 
737 /**
738  * xmlSchemaIDC:
739  *
740  * The identity-constraint definition component.
741  * (Extends xmlSchemaAnnotItem)
742  */
743 
744 struct _xmlSchemaIDC {
745     xmlSchemaTypeType type;
746     xmlSchemaAnnotPtr annot;
747     xmlSchemaIDCPtr next;
748     xmlNodePtr node;
749     const xmlChar *name;
750     const xmlChar *targetNamespace;
751     xmlSchemaIDCSelectPtr selector;
752     xmlSchemaIDCSelectPtr fields;
753     int nbFields;
754     xmlSchemaQNameRefPtr ref;
755 };
756 
757 /**
758  * xmlSchemaIDCAug:
759  *
760  * The augmented IDC information used for validation.
761  */
762 typedef struct _xmlSchemaIDCAug xmlSchemaIDCAug;
763 typedef xmlSchemaIDCAug *xmlSchemaIDCAugPtr;
764 struct _xmlSchemaIDCAug {
765     xmlSchemaIDCAugPtr next; /* next in a list */
766     xmlSchemaIDCPtr def; /* the IDC definition */
767     int keyrefDepth; /* the lowest tree level to which IDC
768                         tables need to be bubbled upwards */
769 };
770 
771 /**
772  * xmlSchemaPSVIIDCKeySequence:
773  *
774  * The key sequence of a node table item.
775  */
776 typedef struct _xmlSchemaPSVIIDCKey xmlSchemaPSVIIDCKey;
777 typedef xmlSchemaPSVIIDCKey *xmlSchemaPSVIIDCKeyPtr;
778 struct _xmlSchemaPSVIIDCKey {
779     xmlSchemaTypePtr type;
780     xmlSchemaValPtr val;
781 };
782 
783 /**
784  * xmlSchemaPSVIIDCNode:
785  *
786  * The node table item of a node table.
787  */
788 typedef struct _xmlSchemaPSVIIDCNode xmlSchemaPSVIIDCNode;
789 typedef xmlSchemaPSVIIDCNode *xmlSchemaPSVIIDCNodePtr;
790 struct _xmlSchemaPSVIIDCNode {
791     xmlNodePtr node;
792     xmlSchemaPSVIIDCKeyPtr *keys;
793     int nodeLine;
794     int nodeQNameID;
795 
796 };
797 
798 /**
799  * xmlSchemaPSVIIDCBinding:
800  *
801  * The identity-constraint binding item of the [identity-constraint table].
802  */
803 typedef struct _xmlSchemaPSVIIDCBinding xmlSchemaPSVIIDCBinding;
804 typedef xmlSchemaPSVIIDCBinding *xmlSchemaPSVIIDCBindingPtr;
805 struct _xmlSchemaPSVIIDCBinding {
806     xmlSchemaPSVIIDCBindingPtr next; /* next binding of a specific node */
807     xmlSchemaIDCPtr definition; /* the IDC definition */
808     xmlSchemaPSVIIDCNodePtr *nodeTable; /* array of key-sequences */
809     int nbNodes; /* number of entries in the node table */
810     int sizeNodes; /* size of the node table */
811     xmlSchemaItemListPtr dupls;
812 };
813 
814 
815 #define XPATH_STATE_OBJ_TYPE_IDC_SELECTOR 1
816 #define XPATH_STATE_OBJ_TYPE_IDC_FIELD 2
817 
818 #define XPATH_STATE_OBJ_MATCHES -2
819 #define XPATH_STATE_OBJ_BLOCKED -3
820 
821 typedef struct _xmlSchemaIDCMatcher xmlSchemaIDCMatcher;
822 typedef xmlSchemaIDCMatcher *xmlSchemaIDCMatcherPtr;
823 
824 /**
825  * xmlSchemaIDCStateObj:
826  *
827  * The state object used to evaluate XPath expressions.
828  */
829 typedef struct _xmlSchemaIDCStateObj xmlSchemaIDCStateObj;
830 typedef xmlSchemaIDCStateObj *xmlSchemaIDCStateObjPtr;
831 struct _xmlSchemaIDCStateObj {
832     int type;
833     xmlSchemaIDCStateObjPtr next; /* next if in a list */
834     int depth; /* depth of creation */
835     int *history; /* list of (depth, state-id) tuples */
836     int nbHistory;
837     int sizeHistory;
838     xmlSchemaIDCMatcherPtr matcher; /* the correspondent field/selector
839                                        matcher */
840     xmlSchemaIDCSelectPtr sel;
841     void *xpathCtxt;
842 };
843 
844 #define IDC_MATCHER 0
845 
846 /**
847  * xmlSchemaIDCMatcher:
848  *
849  * Used to evaluate IDC selectors (and fields).
850  */
851 struct _xmlSchemaIDCMatcher {
852     int type;
853     int depth; /* the tree depth at creation time */
854     xmlSchemaIDCMatcherPtr next; /* next in the list */
855     xmlSchemaIDCMatcherPtr nextCached; /* next in the cache list */
856     xmlSchemaIDCAugPtr aidc; /* the augmented IDC item */
857     int idcType;
858     xmlSchemaPSVIIDCKeyPtr **keySeqs; /* the key-sequences of the target
859                                          elements */
860     int sizeKeySeqs;
861     xmlSchemaItemListPtr targets; /* list of target-node
862                                      (xmlSchemaPSVIIDCNodePtr) entries */
863     xmlHashTablePtr htab;
864 };
865 
866 /*
867 * Element info flags.
868 */
869 #define XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES  1<<0
870 #define XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES 1<<1
871 #define XML_SCHEMA_ELEM_INFO_NILLED	       1<<2
872 #define XML_SCHEMA_ELEM_INFO_LOCAL_TYPE	       1<<3
873 
874 #define XML_SCHEMA_NODE_INFO_VALUE_NEEDED      1<<4
875 #define XML_SCHEMA_ELEM_INFO_EMPTY             1<<5
876 #define XML_SCHEMA_ELEM_INFO_HAS_CONTENT       1<<6
877 
878 #define XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT  1<<7
879 #define XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT  1<<8
880 #define XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED  1<<9
881 #define XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE  1<<10
882 
883 /**
884  * xmlSchemaNodeInfo:
885  *
886  * Holds information of an element node.
887  */
888 struct _xmlSchemaNodeInfo {
889     int nodeType;
890     xmlNodePtr node;
891     int nodeLine;
892     const xmlChar *localName;
893     const xmlChar *nsName;
894     const xmlChar *value;
895     xmlSchemaValPtr val; /* the pre-computed value if any */
896     xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
897 
898     int flags; /* combination of node info flags */
899 
900     int valNeeded;
901     int normVal;
902 
903     xmlSchemaElementPtr decl; /* the element/attribute declaration */
904     int depth;
905     xmlSchemaPSVIIDCBindingPtr idcTable; /* the table of PSVI IDC bindings
906                                             for the scope element*/
907     xmlSchemaIDCMatcherPtr idcMatchers; /* the IDC matchers for the scope
908                                            element */
909     xmlRegExecCtxtPtr regexCtxt;
910 
911     const xmlChar **nsBindings; /* Namespace bindings on this element */
912     int nbNsBindings;
913     int sizeNsBindings;
914 
915     int hasKeyrefs;
916     int appliedXPath; /* Indicates that an XPath has been applied. */
917 };
918 
919 #define XML_SCHEMAS_ATTR_UNKNOWN 1
920 #define XML_SCHEMAS_ATTR_ASSESSED 2
921 #define XML_SCHEMAS_ATTR_PROHIBITED 3
922 #define XML_SCHEMAS_ATTR_ERR_MISSING 4
923 #define XML_SCHEMAS_ATTR_INVALID_VALUE 5
924 #define XML_SCHEMAS_ATTR_ERR_NO_TYPE 6
925 #define XML_SCHEMAS_ATTR_ERR_FIXED_VALUE 7
926 #define XML_SCHEMAS_ATTR_DEFAULT 8
927 #define XML_SCHEMAS_ATTR_VALIDATE_VALUE 9
928 #define XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL 10
929 #define XML_SCHEMAS_ATTR_HAS_ATTR_USE 11
930 #define XML_SCHEMAS_ATTR_HAS_ATTR_DECL 12
931 #define XML_SCHEMAS_ATTR_WILD_SKIP 13
932 #define XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL 14
933 #define XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID 15
934 #define XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID 16
935 #define XML_SCHEMAS_ATTR_META 17
936 /*
937 * @metaType values of xmlSchemaAttrInfo.
938 */
939 #define XML_SCHEMA_ATTR_INFO_META_XSI_TYPE 1
940 #define XML_SCHEMA_ATTR_INFO_META_XSI_NIL 2
941 #define XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC 3
942 #define XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC 4
943 #define XML_SCHEMA_ATTR_INFO_META_XMLNS 5
944 
945 typedef struct _xmlSchemaAttrInfo xmlSchemaAttrInfo;
946 typedef xmlSchemaAttrInfo *xmlSchemaAttrInfoPtr;
947 struct _xmlSchemaAttrInfo {
948     int nodeType;
949     xmlNodePtr node;
950     int nodeLine;
951     const xmlChar *localName;
952     const xmlChar *nsName;
953     const xmlChar *value;
954     xmlSchemaValPtr val; /* the pre-computed value if any */
955     xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
956     int flags; /* combination of node info flags */
957 
958     xmlSchemaAttributePtr decl; /* the attribute declaration */
959     xmlSchemaAttributeUsePtr use;  /* the attribute use */
960     int state;
961     int metaType;
962     const xmlChar *vcValue; /* the value constraint value */
963     xmlSchemaNodeInfoPtr parent;
964 };
965 
966 
967 #define XML_SCHEMA_VALID_CTXT_FLAG_STREAM 1
968 /**
969  * xmlSchemaValidCtxt:
970  *
971  * A Schemas validation context
972  */
973 struct _xmlSchemaValidCtxt {
974     int type;
975     void *errCtxt;             /* user specific data block */
976     xmlSchemaValidityErrorFunc error;   /* the callback in case of errors */
977     xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
978     xmlStructuredErrorFunc serror;
979 
980     xmlSchemaPtr schema;        /* The schema in use */
981     xmlDocPtr doc;
982     xmlParserInputBufferPtr input;
983     xmlCharEncoding enc;
984     xmlSAXHandlerPtr sax;
985     xmlParserCtxtPtr parserCtxt;
986     void *user_data; /* TODO: What is this for? */
987     char *filename;
988 
989     int err;
990     int nberrors;
991 
992     xmlNodePtr node;
993     xmlNodePtr cur;
994     /* xmlSchemaTypePtr type; */
995 
996     xmlRegExecCtxtPtr regexp;
997     xmlSchemaValPtr value;
998 
999     int valueWS;
1000     int options;
1001     xmlNodePtr validationRoot;
1002     xmlSchemaParserCtxtPtr pctxt;
1003     int xsiAssemble;
1004 
1005     int depth;
1006     xmlSchemaNodeInfoPtr *elemInfos; /* array of element information */
1007     int sizeElemInfos;
1008     xmlSchemaNodeInfoPtr inode; /* the current element information */
1009 
1010     xmlSchemaIDCAugPtr aidcs; /* a list of augmented IDC information */
1011 
1012     xmlSchemaIDCStateObjPtr xpathStates; /* first active state object. */
1013     xmlSchemaIDCStateObjPtr xpathStatePool; /* first stored state object. */
1014     xmlSchemaIDCMatcherPtr idcMatcherCache; /* Cache for IDC matcher objects. */
1015 
1016     xmlSchemaPSVIIDCNodePtr *idcNodes; /* list of all IDC node-table entries*/
1017     int nbIdcNodes;
1018     int sizeIdcNodes;
1019 
1020     xmlSchemaPSVIIDCKeyPtr *idcKeys; /* list of all IDC node-table entries */
1021     int nbIdcKeys;
1022     int sizeIdcKeys;
1023 
1024     int flags;
1025 
1026     xmlDictPtr dict;
1027 
1028 #ifdef LIBXML_READER_ENABLED
1029     xmlTextReaderPtr reader;
1030 #endif
1031 
1032     xmlSchemaAttrInfoPtr *attrInfos;
1033     int nbAttrInfos;
1034     int sizeAttrInfos;
1035 
1036     int skipDepth;
1037     xmlSchemaItemListPtr nodeQNames;
1038     int hasKeyrefs;
1039     int createIDCNodeTables;
1040     int psviExposeIDCNodeTables;
1041 
1042     /* Locator for error reporting in streaming mode */
1043     xmlSchemaValidityLocatorFunc locFunc;
1044     void *locCtxt;
1045 };
1046 
1047 /**
1048  * xmlSchemaSubstGroup:
1049  *
1050  *
1051  */
1052 typedef struct _xmlSchemaSubstGroup xmlSchemaSubstGroup;
1053 typedef xmlSchemaSubstGroup *xmlSchemaSubstGroupPtr;
1054 struct _xmlSchemaSubstGroup {
1055     xmlSchemaElementPtr head;
1056     xmlSchemaItemListPtr members;
1057 };
1058 
1059 /**
1060  * xmlIDCHashEntry:
1061  *
1062  * an entry in hash tables to quickly look up keys/uniques
1063  */
1064 typedef struct _xmlIDCHashEntry xmlIDCHashEntry;
1065 typedef xmlIDCHashEntry *xmlIDCHashEntryPtr;
1066 struct _xmlIDCHashEntry {
1067     xmlIDCHashEntryPtr next; /* next item with same hash */
1068     int index;               /* index into associated item list */
1069 };
1070 
1071 /************************************************************************
1072  *									*
1073  *			Some predeclarations				*
1074  *									*
1075  ************************************************************************/
1076 
1077 static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
1078                                  xmlSchemaPtr schema,
1079                                  xmlNodePtr node);
1080 static int xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr ctxt,
1081                                  xmlSchemaPtr schema,
1082                                  xmlNodePtr node);
1083 static int
1084 xmlSchemaTypeFixup(xmlSchemaTypePtr type,
1085                    xmlSchemaAbstractCtxtPtr ctxt);
1086 static const xmlChar *
1087 xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
1088 static int
1089 xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1090                      xmlNodePtr node);
1091 static int
1092 xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
1093                        xmlSchemaParserCtxtPtr ctxt);
1094 static void
1095 xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt);
1096 static xmlSchemaWhitespaceValueType
1097 xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type);
1098 static xmlSchemaTreeItemPtr
1099 xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1100 			 xmlNodePtr node, xmlSchemaTypeType type,
1101 			 int withParticle);
1102 static const xmlChar *
1103 xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item);
1104 static xmlSchemaTypeLinkPtr
1105 xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type);
1106 static void
1107 xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
1108 		     const char *funcName,
1109 		     const char *message) LIBXML_ATTR_FORMAT(3,0);
1110 static int
1111 xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr ctxt,
1112 			     xmlSchemaTypePtr type,
1113 			     xmlSchemaTypePtr baseType,
1114 			     int subset);
1115 static void
1116 xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
1117 				   xmlSchemaParserCtxtPtr ctxt);
1118 static void
1119 xmlSchemaComponentListFree(xmlSchemaItemListPtr list);
1120 static xmlSchemaQNameRefPtr
1121 xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,
1122 				xmlSchemaPtr schema,
1123 				xmlNodePtr node);
1124 
1125 /************************************************************************
1126  *									*
1127  *			Helper functions			        *
1128  *									*
1129  ************************************************************************/
1130 
1131 /**
1132  * xmlSchemaItemTypeToStr:
1133  * @type: the type of the schema item
1134  *
1135  * Returns the component name of a schema item.
1136  */
1137 static const xmlChar *
xmlSchemaItemTypeToStr(xmlSchemaTypeType type)1138 xmlSchemaItemTypeToStr(xmlSchemaTypeType type)
1139 {
1140     switch (type) {
1141 	case XML_SCHEMA_TYPE_BASIC:
1142 	    return(BAD_CAST "simple type definition");
1143 	case XML_SCHEMA_TYPE_SIMPLE:
1144 	    return(BAD_CAST "simple type definition");
1145 	case XML_SCHEMA_TYPE_COMPLEX:
1146 	    return(BAD_CAST "complex type definition");
1147 	case XML_SCHEMA_TYPE_ELEMENT:
1148 	    return(BAD_CAST "element declaration");
1149 	case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1150 	    return(BAD_CAST "attribute use");
1151 	case XML_SCHEMA_TYPE_ATTRIBUTE:
1152 	    return(BAD_CAST "attribute declaration");
1153 	case XML_SCHEMA_TYPE_GROUP:
1154 	    return(BAD_CAST "model group definition");
1155 	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1156 	    return(BAD_CAST "attribute group definition");
1157 	case XML_SCHEMA_TYPE_NOTATION:
1158 	    return(BAD_CAST "notation declaration");
1159 	case XML_SCHEMA_TYPE_SEQUENCE:
1160 	    return(BAD_CAST "model group (sequence)");
1161 	case XML_SCHEMA_TYPE_CHOICE:
1162 	    return(BAD_CAST "model group (choice)");
1163 	case XML_SCHEMA_TYPE_ALL:
1164 	    return(BAD_CAST "model group (all)");
1165 	case XML_SCHEMA_TYPE_PARTICLE:
1166 	    return(BAD_CAST "particle");
1167 	case XML_SCHEMA_TYPE_IDC_UNIQUE:
1168 	    return(BAD_CAST "unique identity-constraint");
1169 	    /* return(BAD_CAST "IDC (unique)"); */
1170 	case XML_SCHEMA_TYPE_IDC_KEY:
1171 	    return(BAD_CAST "key identity-constraint");
1172 	    /* return(BAD_CAST "IDC (key)"); */
1173 	case XML_SCHEMA_TYPE_IDC_KEYREF:
1174 	    return(BAD_CAST "keyref identity-constraint");
1175 	    /* return(BAD_CAST "IDC (keyref)"); */
1176 	case XML_SCHEMA_TYPE_ANY:
1177 	    return(BAD_CAST "wildcard (any)");
1178 	case XML_SCHEMA_EXTRA_QNAMEREF:
1179 	    return(BAD_CAST "[helper component] QName reference");
1180 	case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
1181 	    return(BAD_CAST "[helper component] attribute use prohibition");
1182 	default:
1183 	    return(BAD_CAST "Not a schema component");
1184     }
1185 }
1186 
1187 /**
1188  * xmlSchemaGetComponentTypeStr:
1189  * @type: the type of the schema item
1190  *
1191  * Returns the component name of a schema item.
1192  */
1193 static const xmlChar *
xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item)1194 xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item)
1195 {
1196     switch (item->type) {
1197 	case XML_SCHEMA_TYPE_BASIC:
1198 	    if (WXS_IS_COMPLEX(WXS_TYPE_CAST item))
1199 		return(BAD_CAST "complex type definition");
1200 	    else
1201 		return(BAD_CAST "simple type definition");
1202 	default:
1203 	    return(xmlSchemaItemTypeToStr(item->type));
1204     }
1205 }
1206 
1207 /**
1208  * xmlSchemaGetComponentNode:
1209  * @item: a schema component
1210  *
1211  * Returns node associated with the schema component.
1212  * NOTE that such a node need not be available; plus, a component's
1213  * node need not to reflect the component directly, since there is no
1214  * one-to-one relationship between the XML Schema representation and
1215  * the component representation.
1216  */
1217 static xmlNodePtr
xmlSchemaGetComponentNode(xmlSchemaBasicItemPtr item)1218 xmlSchemaGetComponentNode(xmlSchemaBasicItemPtr item)
1219 {
1220     switch (item->type) {
1221 	case XML_SCHEMA_TYPE_ELEMENT:
1222 	    return (((xmlSchemaElementPtr) item)->node);
1223 	case XML_SCHEMA_TYPE_ATTRIBUTE:
1224 	    return (((xmlSchemaAttributePtr) item)->node);
1225 	case XML_SCHEMA_TYPE_COMPLEX:
1226 	case XML_SCHEMA_TYPE_SIMPLE:
1227 	    return (((xmlSchemaTypePtr) item)->node);
1228 	case XML_SCHEMA_TYPE_ANY:
1229 	case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1230 	    return (((xmlSchemaWildcardPtr) item)->node);
1231 	case XML_SCHEMA_TYPE_PARTICLE:
1232 	    return (((xmlSchemaParticlePtr) item)->node);
1233 	case XML_SCHEMA_TYPE_SEQUENCE:
1234 	case XML_SCHEMA_TYPE_CHOICE:
1235 	case XML_SCHEMA_TYPE_ALL:
1236 	    return (((xmlSchemaModelGroupPtr) item)->node);
1237 	case XML_SCHEMA_TYPE_GROUP:
1238 	    return (((xmlSchemaModelGroupDefPtr) item)->node);
1239 	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1240 	    return (((xmlSchemaAttributeGroupPtr) item)->node);
1241 	case XML_SCHEMA_TYPE_IDC_UNIQUE:
1242 	case XML_SCHEMA_TYPE_IDC_KEY:
1243 	case XML_SCHEMA_TYPE_IDC_KEYREF:
1244 	    return (((xmlSchemaIDCPtr) item)->node);
1245 	case XML_SCHEMA_EXTRA_QNAMEREF:
1246 	    return(((xmlSchemaQNameRefPtr) item)->node);
1247 	/* TODO: What to do with NOTATIONs?
1248 	case XML_SCHEMA_TYPE_NOTATION:
1249 	    return (((xmlSchemaNotationPtr) item)->node);
1250 	*/
1251 	case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1252 	    return (((xmlSchemaAttributeUsePtr) item)->node);
1253 	default:
1254 	    return (NULL);
1255     }
1256 }
1257 
1258 #if 0
1259 /**
1260  * xmlSchemaGetNextComponent:
1261  * @item: a schema component
1262  *
1263  * Returns the next sibling of the schema component.
1264  */
1265 static xmlSchemaBasicItemPtr
1266 xmlSchemaGetNextComponent(xmlSchemaBasicItemPtr item)
1267 {
1268     switch (item->type) {
1269 	case XML_SCHEMA_TYPE_ELEMENT:
1270 	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaElementPtr) item)->next);
1271 	case XML_SCHEMA_TYPE_ATTRIBUTE:
1272 	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributePtr) item)->next);
1273 	case XML_SCHEMA_TYPE_COMPLEX:
1274 	case XML_SCHEMA_TYPE_SIMPLE:
1275 	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaTypePtr) item)->next);
1276 	case XML_SCHEMA_TYPE_ANY:
1277 	case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1278 	    return (NULL);
1279 	case XML_SCHEMA_TYPE_PARTICLE:
1280 	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaParticlePtr) item)->next);
1281 	case XML_SCHEMA_TYPE_SEQUENCE:
1282 	case XML_SCHEMA_TYPE_CHOICE:
1283 	case XML_SCHEMA_TYPE_ALL:
1284 	    return (NULL);
1285 	case XML_SCHEMA_TYPE_GROUP:
1286 	    return (NULL);
1287 	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1288 	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributeGroupPtr) item)->next);
1289 	case XML_SCHEMA_TYPE_IDC_UNIQUE:
1290 	case XML_SCHEMA_TYPE_IDC_KEY:
1291 	case XML_SCHEMA_TYPE_IDC_KEYREF:
1292 	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaIDCPtr) item)->next);
1293 	default:
1294 	    return (NULL);
1295     }
1296 }
1297 #endif
1298 
1299 
1300 /**
1301  * xmlSchemaFormatQName:
1302  * @buf: the string buffer
1303  * @namespaceName:  the namespace name
1304  * @localName: the local name
1305  *
1306  * Returns the given QName in the format "{namespaceName}localName" or
1307  * just "localName" if @namespaceName is NULL.
1308  *
1309  * Returns the localName if @namespaceName is NULL, a formatted
1310  * string otherwise.
1311  */
1312 static const xmlChar*
xmlSchemaFormatQName(xmlChar ** buf,const xmlChar * namespaceName,const xmlChar * localName)1313 xmlSchemaFormatQName(xmlChar **buf,
1314 		     const xmlChar *namespaceName,
1315 		     const xmlChar *localName)
1316 {
1317     FREE_AND_NULL(*buf)
1318     if (namespaceName != NULL) {
1319 	*buf = xmlStrdup(BAD_CAST "{");
1320 	*buf = xmlStrcat(*buf, namespaceName);
1321 	*buf = xmlStrcat(*buf, BAD_CAST "}");
1322     }
1323     if (localName != NULL) {
1324 	if (namespaceName == NULL)
1325 	    return(localName);
1326 	*buf = xmlStrcat(*buf, localName);
1327     } else {
1328 	*buf = xmlStrcat(*buf, BAD_CAST "(NULL)");
1329     }
1330     return ((const xmlChar *) *buf);
1331 }
1332 
1333 static const xmlChar*
xmlSchemaFormatQNameNs(xmlChar ** buf,xmlNsPtr ns,const xmlChar * localName)1334 xmlSchemaFormatQNameNs(xmlChar **buf, xmlNsPtr ns, const xmlChar *localName)
1335 {
1336     if (ns != NULL)
1337 	return (xmlSchemaFormatQName(buf, ns->href, localName));
1338     else
1339 	return (xmlSchemaFormatQName(buf, NULL, localName));
1340 }
1341 
1342 static const xmlChar *
xmlSchemaGetComponentName(xmlSchemaBasicItemPtr item)1343 xmlSchemaGetComponentName(xmlSchemaBasicItemPtr item)
1344 {
1345     if (item == NULL) {
1346         return (NULL);
1347     }
1348     switch (item->type) {
1349 	case XML_SCHEMA_TYPE_ELEMENT:
1350 	    return (((xmlSchemaElementPtr) item)->name);
1351 	case XML_SCHEMA_TYPE_ATTRIBUTE:
1352 	    return (((xmlSchemaAttributePtr) item)->name);
1353 	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1354 	    return (((xmlSchemaAttributeGroupPtr) item)->name);
1355 	case XML_SCHEMA_TYPE_BASIC:
1356 	case XML_SCHEMA_TYPE_SIMPLE:
1357 	case XML_SCHEMA_TYPE_COMPLEX:
1358 	    return (((xmlSchemaTypePtr) item)->name);
1359 	case XML_SCHEMA_TYPE_GROUP:
1360 	    return (((xmlSchemaModelGroupDefPtr) item)->name);
1361 	case XML_SCHEMA_TYPE_IDC_KEY:
1362 	case XML_SCHEMA_TYPE_IDC_UNIQUE:
1363 	case XML_SCHEMA_TYPE_IDC_KEYREF:
1364 	    return (((xmlSchemaIDCPtr) item)->name);
1365 	case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1366 	    if (WXS_ATTRUSE_DECL(item) != NULL) {
1367 		return(xmlSchemaGetComponentName(
1368 		    WXS_BASIC_CAST WXS_ATTRUSE_DECL(item)));
1369 	    } else
1370 		return(NULL);
1371 	case XML_SCHEMA_EXTRA_QNAMEREF:
1372 	    return (((xmlSchemaQNameRefPtr) item)->name);
1373 	case XML_SCHEMA_TYPE_NOTATION:
1374 	    return (((xmlSchemaNotationPtr) item)->name);
1375 	default:
1376 	    /*
1377 	    * Other components cannot have names.
1378 	    */
1379 	    break;
1380     }
1381     return (NULL);
1382 }
1383 
1384 #define xmlSchemaGetQNameRefName(r) (WXS_QNAME_CAST (r))->name
1385 #define xmlSchemaGetQNameRefTargetNs(r) (WXS_QNAME_CAST (r))->targetNamespace
1386 /*
1387 static const xmlChar *
1388 xmlSchemaGetQNameRefName(void *ref)
1389 {
1390     return(((xmlSchemaQNameRefPtr) ref)->name);
1391 }
1392 
1393 static const xmlChar *
1394 xmlSchemaGetQNameRefTargetNs(void *ref)
1395 {
1396     return(((xmlSchemaQNameRefPtr) ref)->targetNamespace);
1397 }
1398 */
1399 
1400 static const xmlChar *
xmlSchemaGetComponentTargetNs(xmlSchemaBasicItemPtr item)1401 xmlSchemaGetComponentTargetNs(xmlSchemaBasicItemPtr item)
1402 {
1403     if (item == NULL) {
1404         return (NULL);
1405     }
1406     switch (item->type) {
1407 	case XML_SCHEMA_TYPE_ELEMENT:
1408 	    return (((xmlSchemaElementPtr) item)->targetNamespace);
1409 	case XML_SCHEMA_TYPE_ATTRIBUTE:
1410 	    return (((xmlSchemaAttributePtr) item)->targetNamespace);
1411 	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1412 	    return (((xmlSchemaAttributeGroupPtr) item)->targetNamespace);
1413 	case XML_SCHEMA_TYPE_BASIC:
1414 	    return (BAD_CAST "http://www.w3.org/2001/XMLSchema");
1415 	case XML_SCHEMA_TYPE_SIMPLE:
1416 	case XML_SCHEMA_TYPE_COMPLEX:
1417 	    return (((xmlSchemaTypePtr) item)->targetNamespace);
1418 	case XML_SCHEMA_TYPE_GROUP:
1419 	    return (((xmlSchemaModelGroupDefPtr) item)->targetNamespace);
1420 	case XML_SCHEMA_TYPE_IDC_KEY:
1421 	case XML_SCHEMA_TYPE_IDC_UNIQUE:
1422 	case XML_SCHEMA_TYPE_IDC_KEYREF:
1423 	    return (((xmlSchemaIDCPtr) item)->targetNamespace);
1424 	case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1425 	    if (WXS_ATTRUSE_DECL(item) != NULL) {
1426 		return(xmlSchemaGetComponentTargetNs(
1427 		    WXS_BASIC_CAST WXS_ATTRUSE_DECL(item)));
1428 	    }
1429 	    /* TODO: Will returning NULL break something? */
1430 	    break;
1431 	case XML_SCHEMA_EXTRA_QNAMEREF:
1432 	    return (((xmlSchemaQNameRefPtr) item)->targetNamespace);
1433 	case XML_SCHEMA_TYPE_NOTATION:
1434 	    return (((xmlSchemaNotationPtr) item)->targetNamespace);
1435 	default:
1436 	    /*
1437 	    * Other components cannot have names.
1438 	    */
1439 	    break;
1440     }
1441     return (NULL);
1442 }
1443 
1444 static const xmlChar*
xmlSchemaGetComponentQName(xmlChar ** buf,void * item)1445 xmlSchemaGetComponentQName(xmlChar **buf,
1446 			   void *item)
1447 {
1448     return (xmlSchemaFormatQName(buf,
1449 	xmlSchemaGetComponentTargetNs((xmlSchemaBasicItemPtr) item),
1450 	xmlSchemaGetComponentName((xmlSchemaBasicItemPtr) item)));
1451 }
1452 
1453 static const xmlChar*
xmlSchemaGetComponentDesignation(xmlChar ** buf,void * item)1454 xmlSchemaGetComponentDesignation(xmlChar **buf, void *item)
1455 {
1456     xmlChar *str = NULL;
1457 
1458     *buf = xmlStrcat(*buf, WXS_ITEM_TYPE_NAME(item));
1459     *buf = xmlStrcat(*buf, BAD_CAST " '");
1460     *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str,
1461 	(xmlSchemaBasicItemPtr) item));
1462     *buf = xmlStrcat(*buf, BAD_CAST "'");
1463     FREE_AND_NULL(str);
1464     return(*buf);
1465 }
1466 
1467 static const xmlChar*
xmlSchemaGetIDCDesignation(xmlChar ** buf,xmlSchemaIDCPtr idc)1468 xmlSchemaGetIDCDesignation(xmlChar **buf, xmlSchemaIDCPtr idc)
1469 {
1470     return(xmlSchemaGetComponentDesignation(buf, idc));
1471 }
1472 
1473 /**
1474  * xmlSchemaWildcardPCToString:
1475  * @pc: the type of processContents
1476  *
1477  * Returns a string representation of the type of
1478  * processContents.
1479  */
1480 static const xmlChar *
xmlSchemaWildcardPCToString(int pc)1481 xmlSchemaWildcardPCToString(int pc)
1482 {
1483     switch (pc) {
1484 	case XML_SCHEMAS_ANY_SKIP:
1485 	    return (BAD_CAST "skip");
1486 	case XML_SCHEMAS_ANY_LAX:
1487 	    return (BAD_CAST "lax");
1488 	case XML_SCHEMAS_ANY_STRICT:
1489 	    return (BAD_CAST "strict");
1490 	default:
1491 	    return (BAD_CAST "invalid process contents");
1492     }
1493 }
1494 
1495 /**
1496  * xmlSchemaGetCanonValueWhtspExt:
1497  * @val: the precomputed value
1498  * @retValue: the returned value
1499  * @ws: the whitespace type of the value
1500  * @for_hash: non-zero if this is supposed to generate a string for hashing
1501  *
1502  * Get a the canonical representation of the value.
1503  * The caller has to free the returned retValue.
1504  *
1505  * Returns 0 if the value could be built and -1 in case of
1506  *         API errors or if the value type is not supported yet.
1507  */
1508 static int
xmlSchemaGetCanonValueWhtspExt_1(xmlSchemaValPtr val,xmlSchemaWhitespaceValueType ws,xmlChar ** retValue,int for_hash)1509 xmlSchemaGetCanonValueWhtspExt_1(xmlSchemaValPtr val,
1510 			         xmlSchemaWhitespaceValueType ws,
1511 			         xmlChar **retValue,
1512 				 int for_hash)
1513 {
1514     int list;
1515     xmlSchemaValType valType;
1516     const xmlChar *value, *value2 = NULL;
1517 
1518 
1519     if ((retValue == NULL) || (val == NULL))
1520 	return (-1);
1521     list = xmlSchemaValueGetNext(val) ? 1 : 0;
1522     *retValue = NULL;
1523     do {
1524 	value = NULL;
1525 	valType = xmlSchemaGetValType(val);
1526 	switch (valType) {
1527 	    case XML_SCHEMAS_STRING:
1528 	    case XML_SCHEMAS_NORMSTRING:
1529 	    case XML_SCHEMAS_ANYSIMPLETYPE:
1530 		value = xmlSchemaValueGetAsString(val);
1531 		if (value != NULL) {
1532 		    if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
1533 			value2 = xmlSchemaCollapseString(value);
1534 		    else if (ws == XML_SCHEMA_WHITESPACE_REPLACE)
1535 			value2 = xmlSchemaWhiteSpaceReplace(value);
1536 		    if (value2 != NULL)
1537 			value = value2;
1538 		}
1539 		break;
1540 	    default:
1541 		if (xmlSchemaGetCanonValue(val, &value2) == -1) {
1542 		    if (value2 != NULL)
1543 			xmlFree((xmlChar *) value2);
1544 		    goto internal_error;
1545 		}
1546 		if (for_hash && valType == XML_SCHEMAS_DECIMAL) {
1547 		    /* We can mostly use the canonical value for hashing,
1548 		       except in the case of decimal.  There the canonical
1549 		       representation requires a trailing '.0' even for
1550 		       non-fractional numbers, but for the derived integer
1551 		       types it forbids any decimal point.  Nevertheless they
1552 		       compare equal if the value is equal.  We need to generate
1553 		       the same hash value for this to work, and it's easiest
1554 		       to just cut off the useless '.0' suffix for the
1555 		       decimal type.  */
1556 		    int len = xmlStrlen(value2);
1557 		    if (len > 2 && value2[len-1] == '0' && value2[len-2] == '.')
1558 		      ((xmlChar*)value2)[len-2] = 0;
1559 		}
1560 		value = value2;
1561 	}
1562 	if (*retValue == NULL)
1563 	    if (value == NULL) {
1564 		if (! list)
1565 		    *retValue = xmlStrdup(BAD_CAST "");
1566 	    } else
1567 		*retValue = xmlStrdup(value);
1568 	else if (value != NULL) {
1569 	    /* List. */
1570 	    *retValue = xmlStrcat((xmlChar *) *retValue, BAD_CAST " ");
1571 	    *retValue = xmlStrcat((xmlChar *) *retValue, value);
1572 	}
1573 	FREE_AND_NULL(value2)
1574 	val = xmlSchemaValueGetNext(val);
1575     } while (val != NULL);
1576 
1577     return (0);
1578 internal_error:
1579     if (*retValue != NULL)
1580 	xmlFree((xmlChar *) (*retValue));
1581     if (value2 != NULL)
1582 	xmlFree((xmlChar *) value2);
1583     return (-1);
1584 }
1585 
1586 static int
xmlSchemaGetCanonValueWhtspExt(xmlSchemaValPtr val,xmlSchemaWhitespaceValueType ws,xmlChar ** retValue)1587 xmlSchemaGetCanonValueWhtspExt(xmlSchemaValPtr val,
1588 			       xmlSchemaWhitespaceValueType ws,
1589 			       xmlChar **retValue)
1590 {
1591     return xmlSchemaGetCanonValueWhtspExt_1(val, ws, retValue, 0);
1592 }
1593 
1594 static int
xmlSchemaGetCanonValueHash(xmlSchemaValPtr val,xmlChar ** retValue)1595 xmlSchemaGetCanonValueHash(xmlSchemaValPtr val,
1596 			   xmlChar **retValue)
1597 {
1598     return xmlSchemaGetCanonValueWhtspExt_1(val, XML_SCHEMA_WHITESPACE_COLLAPSE,
1599 					    retValue, 1);
1600 }
1601 
1602 /**
1603  * xmlSchemaFormatItemForReport:
1604  * @buf: the string buffer
1605  * @itemDes: the designation of the item
1606  * @itemName: the name of the item
1607  * @item: the item as an object
1608  * @itemNode: the node of the item
1609  * @local: the local name
1610  * @parsing: if the function is used during the parse
1611  *
1612  * Returns a representation of the given item used
1613  * for error reports.
1614  *
1615  * The following order is used to build the resulting
1616  * designation if the arguments are not NULL:
1617  * 1a. If itemDes not NULL -> itemDes
1618  * 1b. If (itemDes not NULL) and (itemName not NULL)
1619  *     -> itemDes + itemName
1620  * 2. If the preceding was NULL and (item not NULL) -> item
1621  * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
1622  *
1623  * If the itemNode is an attribute node, the name of the attribute
1624  * will be appended to the result.
1625  *
1626  * Returns the formatted string and sets @buf to the resulting value.
1627  */
1628 static xmlChar*
xmlSchemaFormatItemForReport(xmlChar ** buf,const xmlChar * itemDes,xmlSchemaBasicItemPtr item,xmlNodePtr itemNode)1629 xmlSchemaFormatItemForReport(xmlChar **buf,
1630 		     const xmlChar *itemDes,
1631 		     xmlSchemaBasicItemPtr item,
1632 		     xmlNodePtr itemNode)
1633 {
1634     xmlChar *str = NULL;
1635     int named = 1;
1636 
1637     if (*buf != NULL) {
1638 	xmlFree(*buf);
1639 	*buf = NULL;
1640     }
1641 
1642     if (itemDes != NULL) {
1643 	*buf = xmlStrdup(itemDes);
1644     } else if (item != NULL) {
1645 	switch (item->type) {
1646 	case XML_SCHEMA_TYPE_BASIC: {
1647 	    xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1648 
1649 	    if (WXS_IS_ATOMIC(type))
1650 		*buf = xmlStrdup(BAD_CAST "atomic type 'xs:");
1651 	    else if (WXS_IS_LIST(type))
1652 		*buf = xmlStrdup(BAD_CAST "list type 'xs:");
1653 	    else if (WXS_IS_UNION(type))
1654 		*buf = xmlStrdup(BAD_CAST "union type 'xs:");
1655 	    else
1656 		*buf = xmlStrdup(BAD_CAST "simple type 'xs:");
1657 	    *buf = xmlStrcat(*buf, type->name);
1658 	    *buf = xmlStrcat(*buf, BAD_CAST "'");
1659 	    }
1660 	    break;
1661 	case XML_SCHEMA_TYPE_SIMPLE: {
1662 	    xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1663 
1664 	    if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1665 		*buf = xmlStrdup(BAD_CAST"");
1666 	    } else {
1667 		*buf = xmlStrdup(BAD_CAST "local ");
1668 	    }
1669 	    if (WXS_IS_ATOMIC(type))
1670 		*buf = xmlStrcat(*buf, BAD_CAST "atomic type");
1671 	    else if (WXS_IS_LIST(type))
1672 		*buf = xmlStrcat(*buf, BAD_CAST "list type");
1673 	    else if (WXS_IS_UNION(type))
1674 		*buf = xmlStrcat(*buf, BAD_CAST "union type");
1675 	    else
1676 		*buf = xmlStrcat(*buf, BAD_CAST "simple type");
1677 	    if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1678 		*buf = xmlStrcat(*buf, BAD_CAST " '");
1679 		*buf = xmlStrcat(*buf, type->name);
1680 		*buf = xmlStrcat(*buf, BAD_CAST "'");
1681 	    }
1682 	    }
1683 	    break;
1684 	case XML_SCHEMA_TYPE_COMPLEX: {
1685 	    xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1686 
1687 	    if (type->flags & XML_SCHEMAS_TYPE_GLOBAL)
1688 		*buf = xmlStrdup(BAD_CAST "");
1689 	    else
1690 		*buf = xmlStrdup(BAD_CAST "local ");
1691 	    *buf = xmlStrcat(*buf, BAD_CAST "complex type");
1692 	    if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1693 		*buf = xmlStrcat(*buf, BAD_CAST " '");
1694 		*buf = xmlStrcat(*buf, type->name);
1695 		*buf = xmlStrcat(*buf, BAD_CAST "'");
1696 	    }
1697 	    }
1698 	    break;
1699 	case XML_SCHEMA_TYPE_ATTRIBUTE_USE: {
1700 		xmlSchemaAttributeUsePtr ause;
1701 
1702 		ause = WXS_ATTR_USE_CAST item;
1703 		*buf = xmlStrdup(BAD_CAST "attribute use ");
1704 		if (WXS_ATTRUSE_DECL(ause) != NULL) {
1705 		    *buf = xmlStrcat(*buf, BAD_CAST "'");
1706 		    *buf = xmlStrcat(*buf,
1707 			xmlSchemaGetComponentQName(&str, WXS_ATTRUSE_DECL(ause)));
1708 		    FREE_AND_NULL(str)
1709 			*buf = xmlStrcat(*buf, BAD_CAST "'");
1710 		} else {
1711 		    *buf = xmlStrcat(*buf, BAD_CAST "(unknown)");
1712 		}
1713 	    }
1714 	    break;
1715 	case XML_SCHEMA_TYPE_ATTRIBUTE: {
1716 		xmlSchemaAttributePtr attr;
1717 
1718 		attr = (xmlSchemaAttributePtr) item;
1719 		*buf = xmlStrdup(BAD_CAST "attribute decl.");
1720 		*buf = xmlStrcat(*buf, BAD_CAST " '");
1721 		*buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1722 		    attr->targetNamespace, attr->name));
1723 		FREE_AND_NULL(str)
1724 		    *buf = xmlStrcat(*buf, BAD_CAST "'");
1725 	    }
1726 	    break;
1727 	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1728 	    xmlSchemaGetComponentDesignation(buf, item);
1729 	    break;
1730 	case XML_SCHEMA_TYPE_ELEMENT: {
1731 		xmlSchemaElementPtr elem;
1732 
1733 		elem = (xmlSchemaElementPtr) item;
1734 		*buf = xmlStrdup(BAD_CAST "element decl.");
1735 		*buf = xmlStrcat(*buf, BAD_CAST " '");
1736 		*buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1737 		    elem->targetNamespace, elem->name));
1738 		*buf = xmlStrcat(*buf, BAD_CAST "'");
1739 	    }
1740 	    break;
1741 	case XML_SCHEMA_TYPE_IDC_UNIQUE:
1742 	case XML_SCHEMA_TYPE_IDC_KEY:
1743 	case XML_SCHEMA_TYPE_IDC_KEYREF:
1744 	    if (item->type == XML_SCHEMA_TYPE_IDC_UNIQUE)
1745 		*buf = xmlStrdup(BAD_CAST "unique '");
1746 	    else if (item->type == XML_SCHEMA_TYPE_IDC_KEY)
1747 		*buf = xmlStrdup(BAD_CAST "key '");
1748 	    else
1749 		*buf = xmlStrdup(BAD_CAST "keyRef '");
1750 	    *buf = xmlStrcat(*buf, ((xmlSchemaIDCPtr) item)->name);
1751 	    *buf = xmlStrcat(*buf, BAD_CAST "'");
1752 	    break;
1753 	case XML_SCHEMA_TYPE_ANY:
1754 	case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1755 	    *buf = xmlStrdup(xmlSchemaWildcardPCToString(
1756 		    ((xmlSchemaWildcardPtr) item)->processContents));
1757 	    *buf = xmlStrcat(*buf, BAD_CAST " wildcard");
1758 	    break;
1759 	case XML_SCHEMA_FACET_MININCLUSIVE:
1760 	case XML_SCHEMA_FACET_MINEXCLUSIVE:
1761 	case XML_SCHEMA_FACET_MAXINCLUSIVE:
1762 	case XML_SCHEMA_FACET_MAXEXCLUSIVE:
1763 	case XML_SCHEMA_FACET_TOTALDIGITS:
1764 	case XML_SCHEMA_FACET_FRACTIONDIGITS:
1765 	case XML_SCHEMA_FACET_PATTERN:
1766 	case XML_SCHEMA_FACET_ENUMERATION:
1767 	case XML_SCHEMA_FACET_WHITESPACE:
1768 	case XML_SCHEMA_FACET_LENGTH:
1769 	case XML_SCHEMA_FACET_MAXLENGTH:
1770 	case XML_SCHEMA_FACET_MINLENGTH:
1771 	    *buf = xmlStrdup(BAD_CAST "facet '");
1772 	    *buf = xmlStrcat(*buf, xmlSchemaFacetTypeToString(item->type));
1773 	    *buf = xmlStrcat(*buf, BAD_CAST "'");
1774 	    break;
1775 	case XML_SCHEMA_TYPE_GROUP: {
1776 		*buf = xmlStrdup(BAD_CAST "model group def.");
1777 		*buf = xmlStrcat(*buf, BAD_CAST " '");
1778 		*buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, item));
1779 		*buf = xmlStrcat(*buf, BAD_CAST "'");
1780 		FREE_AND_NULL(str)
1781 	    }
1782 	    break;
1783 	case XML_SCHEMA_TYPE_SEQUENCE:
1784 	case XML_SCHEMA_TYPE_CHOICE:
1785 	case XML_SCHEMA_TYPE_ALL:
1786 	case XML_SCHEMA_TYPE_PARTICLE:
1787 	    *buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item));
1788 	    break;
1789 	case XML_SCHEMA_TYPE_NOTATION: {
1790 		*buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item));
1791 		*buf = xmlStrcat(*buf, BAD_CAST " '");
1792 		*buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, item));
1793 		*buf = xmlStrcat(*buf, BAD_CAST "'");
1794 		FREE_AND_NULL(str);
1795 	    }
1796             /* Falls through. */
1797 	default:
1798 	    named = 0;
1799 	}
1800     } else
1801 	named = 0;
1802 
1803     if ((named == 0) && (itemNode != NULL)) {
1804 	xmlNodePtr elem;
1805 
1806 	if (itemNode->type == XML_ATTRIBUTE_NODE)
1807 	    elem = itemNode->parent;
1808 	else
1809 	    elem = itemNode;
1810 	*buf = xmlStrdup(BAD_CAST "Element '");
1811 	if (elem->ns != NULL) {
1812 	    *buf = xmlStrcat(*buf,
1813 		xmlSchemaFormatQName(&str, elem->ns->href, elem->name));
1814 	    FREE_AND_NULL(str)
1815 	} else
1816 	    *buf = xmlStrcat(*buf, elem->name);
1817 	*buf = xmlStrcat(*buf, BAD_CAST "'");
1818 
1819     }
1820     if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
1821 	*buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
1822 	if (itemNode->ns != NULL) {
1823 	    *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1824 		itemNode->ns->href, itemNode->name));
1825 	    FREE_AND_NULL(str)
1826 	} else
1827 	    *buf = xmlStrcat(*buf, itemNode->name);
1828 	*buf = xmlStrcat(*buf, BAD_CAST "'");
1829     }
1830     FREE_AND_NULL(str)
1831 
1832     return (xmlEscapeFormatString(buf));
1833 }
1834 
1835 /**
1836  * xmlSchemaFormatFacetEnumSet:
1837  * @buf: the string buffer
1838  * @type: the type holding the enumeration facets
1839  *
1840  * Builds a string consisting of all enumeration elements.
1841  *
1842  * Returns a string of all enumeration elements.
1843  */
1844 static const xmlChar *
xmlSchemaFormatFacetEnumSet(xmlSchemaAbstractCtxtPtr actxt,xmlChar ** buf,xmlSchemaTypePtr type)1845 xmlSchemaFormatFacetEnumSet(xmlSchemaAbstractCtxtPtr actxt,
1846 			    xmlChar **buf, xmlSchemaTypePtr type)
1847 {
1848     xmlSchemaFacetPtr facet;
1849     xmlSchemaWhitespaceValueType ws;
1850     xmlChar *value = NULL;
1851     int res, found = 0;
1852 
1853     if (*buf != NULL)
1854 	xmlFree(*buf);
1855     *buf = NULL;
1856 
1857     do {
1858 	/*
1859 	* Use the whitespace type of the base type.
1860 	*/
1861 	ws = xmlSchemaGetWhiteSpaceFacetValue(type->baseType);
1862 	for (facet = type->facets; facet != NULL; facet = facet->next) {
1863 	    if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
1864 		continue;
1865 	    found = 1;
1866 	    res = xmlSchemaGetCanonValueWhtspExt(facet->val,
1867 		ws, &value);
1868 	    if (res == -1) {
1869 		xmlSchemaInternalErr(actxt,
1870 		    "xmlSchemaFormatFacetEnumSet",
1871 		    "compute the canonical lexical representation");
1872 		if (*buf != NULL)
1873 		    xmlFree(*buf);
1874 		*buf = NULL;
1875 		return (NULL);
1876 	    }
1877 	    if (*buf == NULL)
1878 		*buf = xmlStrdup(BAD_CAST "'");
1879 	    else
1880 		*buf = xmlStrcat(*buf, BAD_CAST ", '");
1881 	    *buf = xmlStrcat(*buf, BAD_CAST value);
1882 	    *buf = xmlStrcat(*buf, BAD_CAST "'");
1883 	    if (value != NULL) {
1884 		xmlFree((xmlChar *)value);
1885 		value = NULL;
1886 	    }
1887 	}
1888 	/*
1889 	* The enumeration facet of a type restricts the enumeration
1890 	* facet of the ancestor type; i.e., such restricted enumerations
1891 	* do not belong to the set of the given type. Thus we break
1892 	* on the first found enumeration.
1893 	*/
1894 	if (found)
1895 	    break;
1896 	type = type->baseType;
1897     } while ((type != NULL) && (type->type != XML_SCHEMA_TYPE_BASIC));
1898 
1899     return ((const xmlChar *) *buf);
1900 }
1901 
1902 /************************************************************************
1903  *									*
1904  *			Error functions				        *
1905  *									*
1906  ************************************************************************/
1907 
1908 #if 0
1909 static void
1910 xmlSchemaErrMemory(const char *msg)
1911 {
1912     __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
1913                      msg);
1914 }
1915 #endif
1916 
1917 static void
xmlSchemaPSimpleErr(const char * msg)1918 xmlSchemaPSimpleErr(const char *msg)
1919 {
1920     __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
1921                      msg);
1922 }
1923 
1924 /**
1925  * xmlSchemaPErrMemory:
1926  * @node: a context node
1927  * @extra:  extra information
1928  *
1929  * Handle an out of memory condition
1930  */
1931 static void
xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,const char * extra,xmlNodePtr node)1932 xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
1933                     const char *extra, xmlNodePtr node)
1934 {
1935     if (ctxt != NULL)
1936         ctxt->nberrors++;
1937     __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
1938                      extra);
1939 }
1940 
1941 /**
1942  * xmlSchemaPErr:
1943  * @ctxt: the parsing context
1944  * @node: the context node
1945  * @error: the error code
1946  * @msg: the error message
1947  * @str1: extra data
1948  * @str2: extra data
1949  *
1950  * Handle a parser error
1951  */
1952 static void LIBXML_ATTR_FORMAT(4,0)
xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,int error,const char * msg,const xmlChar * str1,const xmlChar * str2)1953 xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1954               const char *msg, const xmlChar * str1, const xmlChar * str2)
1955 {
1956     xmlGenericErrorFunc channel = NULL;
1957     xmlStructuredErrorFunc schannel = NULL;
1958     void *data = NULL;
1959 
1960     if (ctxt != NULL) {
1961         ctxt->nberrors++;
1962 	ctxt->err = error;
1963         channel = ctxt->error;
1964         data = ctxt->errCtxt;
1965 	schannel = ctxt->serror;
1966     }
1967     __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
1968                     error, XML_ERR_ERROR, NULL, 0,
1969                     (const char *) str1, (const char *) str2, NULL, 0, 0,
1970                     msg, str1, str2);
1971 }
1972 
1973 /**
1974  * xmlSchemaPErr2:
1975  * @ctxt: the parsing context
1976  * @node: the context node
1977  * @node: the current child
1978  * @error: the error code
1979  * @msg: the error message
1980  * @str1: extra data
1981  * @str2: extra data
1982  *
1983  * Handle a parser error
1984  */
1985 static void LIBXML_ATTR_FORMAT(5,0)
xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,xmlNodePtr child,int error,const char * msg,const xmlChar * str1,const xmlChar * str2)1986 xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
1987                xmlNodePtr child, int error,
1988                const char *msg, const xmlChar * str1, const xmlChar * str2)
1989 {
1990     if (child != NULL)
1991         xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
1992     else
1993         xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
1994 }
1995 
1996 
1997 /**
1998  * xmlSchemaPErrExt:
1999  * @ctxt: the parsing context
2000  * @node: the context node
2001  * @error: the error code
2002  * @strData1: extra data
2003  * @strData2: extra data
2004  * @strData3: extra data
2005  * @msg: the message
2006  * @str1:  extra parameter for the message display
2007  * @str2:  extra parameter for the message display
2008  * @str3:  extra parameter for the message display
2009  * @str4:  extra parameter for the message display
2010  * @str5:  extra parameter for the message display
2011  *
2012  * Handle a parser error
2013  */
2014 static void LIBXML_ATTR_FORMAT(7,0)
xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,int error,const xmlChar * strData1,const xmlChar * strData2,const xmlChar * strData3,const char * msg,const xmlChar * str1,const xmlChar * str2,const xmlChar * str3,const xmlChar * str4,const xmlChar * str5)2015 xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
2016 		const xmlChar * strData1, const xmlChar * strData2,
2017 		const xmlChar * strData3, const char *msg, const xmlChar * str1,
2018 		const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
2019 		const xmlChar * str5)
2020 {
2021 
2022     xmlGenericErrorFunc channel = NULL;
2023     xmlStructuredErrorFunc schannel = NULL;
2024     void *data = NULL;
2025 
2026     if (ctxt != NULL) {
2027         ctxt->nberrors++;
2028 	ctxt->err = error;
2029         channel = ctxt->error;
2030         data = ctxt->errCtxt;
2031 	schannel = ctxt->serror;
2032     }
2033     __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
2034                     error, XML_ERR_ERROR, NULL, 0,
2035                     (const char *) strData1, (const char *) strData2,
2036 		    (const char *) strData3, 0, 0, msg, str1, str2,
2037 		    str3, str4, str5);
2038 }
2039 
2040 /************************************************************************
2041  *									*
2042  *			Allround error functions			*
2043  *									*
2044  ************************************************************************/
2045 
2046 /**
2047  * xmlSchemaVTypeErrMemory:
2048  * @node: a context node
2049  * @extra:  extra information
2050  *
2051  * Handle an out of memory condition
2052  */
2053 static void
xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,const char * extra,xmlNodePtr node)2054 xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
2055                     const char *extra, xmlNodePtr node)
2056 {
2057     if (ctxt != NULL) {
2058         ctxt->nberrors++;
2059         ctxt->err = XML_SCHEMAV_INTERNAL;
2060     }
2061     __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
2062                      extra);
2063 }
2064 
2065 static void LIBXML_ATTR_FORMAT(2,0)
xmlSchemaPSimpleInternalErr(xmlNodePtr node,const char * msg,const xmlChar * str)2066 xmlSchemaPSimpleInternalErr(xmlNodePtr node,
2067 			    const char *msg, const xmlChar *str)
2068 {
2069      __xmlSimpleError(XML_FROM_SCHEMASP, XML_SCHEMAP_INTERNAL, node,
2070 	 msg, (const char *) str);
2071 }
2072 
2073 #define WXS_ERROR_TYPE_ERROR 1
2074 #define WXS_ERROR_TYPE_WARNING 2
2075 /**
2076  * xmlSchemaErr4Line:
2077  * @ctxt: the validation context
2078  * @errorLevel: the error level
2079  * @error: the error code
2080  * @node: the context node
2081  * @line: the line number
2082  * @msg: the error message
2083  * @str1: extra data
2084  * @str2: extra data
2085  * @str3: extra data
2086  * @str4: extra data
2087  *
2088  * Handle a validation error
2089  */
2090 static void LIBXML_ATTR_FORMAT(6,0)
xmlSchemaErr4Line(xmlSchemaAbstractCtxtPtr ctxt,xmlErrorLevel errorLevel,int error,xmlNodePtr node,int line,const char * msg,const xmlChar * str1,const xmlChar * str2,const xmlChar * str3,const xmlChar * str4)2091 xmlSchemaErr4Line(xmlSchemaAbstractCtxtPtr ctxt,
2092 		  xmlErrorLevel errorLevel,
2093 		  int error, xmlNodePtr node, int line, const char *msg,
2094 		  const xmlChar *str1, const xmlChar *str2,
2095 		  const xmlChar *str3, const xmlChar *str4)
2096 {
2097     xmlStructuredErrorFunc schannel = NULL;
2098     xmlGenericErrorFunc channel = NULL;
2099     void *data = NULL;
2100 
2101     if (ctxt != NULL) {
2102 	if (ctxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
2103 	    xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctxt;
2104 	    const char *file = NULL;
2105 	    int col = 0;
2106 	    if (errorLevel != XML_ERR_WARNING) {
2107 		vctxt->nberrors++;
2108 		vctxt->err = error;
2109 		channel = vctxt->error;
2110 	    } else {
2111 		channel = vctxt->warning;
2112 	    }
2113 	    schannel = vctxt->serror;
2114 	    data = vctxt->errCtxt;
2115 
2116 	    /*
2117 	    * Error node. If we specify a line number, then
2118 	    * do not channel any node to the error function.
2119 	    */
2120 	    if (line == 0) {
2121 		if ((node == NULL) &&
2122 		    (vctxt->depth >= 0) &&
2123 		    (vctxt->inode != NULL)) {
2124 		    node = vctxt->inode->node;
2125 		}
2126 		/*
2127 		* Get filename and line if no node-tree.
2128 		*/
2129 		if ((node == NULL) &&
2130 		    (vctxt->parserCtxt != NULL) &&
2131 		    (vctxt->parserCtxt->input != NULL)) {
2132 		    file = vctxt->parserCtxt->input->filename;
2133 		    line = vctxt->parserCtxt->input->line;
2134 		    col = vctxt->parserCtxt->input->col;
2135 		}
2136 	    } else {
2137 		/*
2138 		* Override the given node's (if any) position
2139 		* and channel only the given line number.
2140 		*/
2141 		node = NULL;
2142 		/*
2143 		* Get filename.
2144 		*/
2145 		if (vctxt->doc != NULL)
2146 		    file = (const char *) vctxt->doc->URL;
2147 		else if ((vctxt->parserCtxt != NULL) &&
2148 		    (vctxt->parserCtxt->input != NULL))
2149 		    file = vctxt->parserCtxt->input->filename;
2150 	    }
2151 	    if (vctxt->locFunc != NULL) {
2152 	        if ((file == NULL) || (line == 0)) {
2153 		    unsigned long l;
2154 		    const char *f;
2155 		    vctxt->locFunc(vctxt->locCtxt, &f, &l);
2156 		    if (file == NULL)
2157 		        file = f;
2158 		    if (line == 0)
2159 		        line = (int) l;
2160 		}
2161 	    }
2162 	    if ((file == NULL) && (vctxt->filename != NULL))
2163 	        file = vctxt->filename;
2164 
2165 	    __xmlRaiseError(schannel, channel, data, ctxt,
2166 		node, XML_FROM_SCHEMASV,
2167 		error, errorLevel, file, line,
2168 		(const char *) str1, (const char *) str2,
2169 		(const char *) str3, 0, col, msg, str1, str2, str3, str4);
2170 
2171 	} else if (ctxt->type == XML_SCHEMA_CTXT_PARSER) {
2172 	    xmlSchemaParserCtxtPtr pctxt = (xmlSchemaParserCtxtPtr) ctxt;
2173 	    if (errorLevel != XML_ERR_WARNING) {
2174 		pctxt->nberrors++;
2175 		pctxt->err = error;
2176 		channel = pctxt->error;
2177 	    } else {
2178 		channel = pctxt->warning;
2179 	    }
2180 	    schannel = pctxt->serror;
2181 	    data = pctxt->errCtxt;
2182 	    __xmlRaiseError(schannel, channel, data, ctxt,
2183 		node, XML_FROM_SCHEMASP, error,
2184 		errorLevel, NULL, 0,
2185 		(const char *) str1, (const char *) str2,
2186 		(const char *) str3, 0, 0, msg, str1, str2, str3, str4);
2187 	} else {
2188 	    TODO
2189 	}
2190     }
2191 }
2192 
2193 /**
2194  * xmlSchemaErr3:
2195  * @ctxt: the validation context
2196  * @node: the context node
2197  * @error: the error code
2198  * @msg: the error message
2199  * @str1: extra data
2200  * @str2: extra data
2201  * @str3: extra data
2202  *
2203  * Handle a validation error
2204  */
2205 static void LIBXML_ATTR_FORMAT(4,0)
xmlSchemaErr3(xmlSchemaAbstractCtxtPtr actxt,int error,xmlNodePtr node,const char * msg,const xmlChar * str1,const xmlChar * str2,const xmlChar * str3)2206 xmlSchemaErr3(xmlSchemaAbstractCtxtPtr actxt,
2207 	      int error, xmlNodePtr node, const char *msg,
2208 	      const xmlChar *str1, const xmlChar *str2, const xmlChar *str3)
2209 {
2210     xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0,
2211 	msg, str1, str2, str3, NULL);
2212 }
2213 
2214 static void LIBXML_ATTR_FORMAT(4,0)
xmlSchemaErr4(xmlSchemaAbstractCtxtPtr actxt,int error,xmlNodePtr node,const char * msg,const xmlChar * str1,const xmlChar * str2,const xmlChar * str3,const xmlChar * str4)2215 xmlSchemaErr4(xmlSchemaAbstractCtxtPtr actxt,
2216 	      int error, xmlNodePtr node, const char *msg,
2217 	      const xmlChar *str1, const xmlChar *str2,
2218 	      const xmlChar *str3, const xmlChar *str4)
2219 {
2220     xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0,
2221 	msg, str1, str2, str3, str4);
2222 }
2223 
2224 static void LIBXML_ATTR_FORMAT(4,0)
xmlSchemaErr(xmlSchemaAbstractCtxtPtr actxt,int error,xmlNodePtr node,const char * msg,const xmlChar * str1,const xmlChar * str2)2225 xmlSchemaErr(xmlSchemaAbstractCtxtPtr actxt,
2226 	     int error, xmlNodePtr node, const char *msg,
2227 	     const xmlChar *str1, const xmlChar *str2)
2228 {
2229     xmlSchemaErr4(actxt, error, node, msg, str1, str2, NULL, NULL);
2230 }
2231 
2232 static xmlChar *
xmlSchemaFormatNodeForError(xmlChar ** msg,xmlSchemaAbstractCtxtPtr actxt,xmlNodePtr node)2233 xmlSchemaFormatNodeForError(xmlChar ** msg,
2234 			    xmlSchemaAbstractCtxtPtr actxt,
2235 			    xmlNodePtr node)
2236 {
2237     xmlChar *str = NULL;
2238 
2239     *msg = NULL;
2240     if ((node != NULL) &&
2241 	(node->type != XML_ELEMENT_NODE) &&
2242 	(node->type != XML_ATTRIBUTE_NODE))
2243     {
2244 	/*
2245 	* Don't try to format other nodes than element and
2246 	* attribute nodes.
2247 	* Play safe and return an empty string.
2248 	*/
2249 	*msg = xmlStrdup(BAD_CAST "");
2250 	return(*msg);
2251     }
2252     if (node != NULL) {
2253 	/*
2254 	* Work on tree nodes.
2255 	*/
2256 	if (node->type == XML_ATTRIBUTE_NODE) {
2257 	    xmlNodePtr elem = node->parent;
2258 
2259 	    *msg = xmlStrdup(BAD_CAST "Element '");
2260 	    if (elem->ns != NULL)
2261 		*msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2262 		    elem->ns->href, elem->name));
2263 	    else
2264 		*msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2265 		    NULL, elem->name));
2266 	    FREE_AND_NULL(str);
2267 	    *msg = xmlStrcat(*msg, BAD_CAST "', ");
2268 	    *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
2269 	} else {
2270 	    *msg = xmlStrdup(BAD_CAST "Element '");
2271 	}
2272 	if (node->ns != NULL)
2273 	    *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2274 	    node->ns->href, node->name));
2275 	else
2276 	    *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2277 	    NULL, node->name));
2278 	FREE_AND_NULL(str);
2279 	*msg = xmlStrcat(*msg, BAD_CAST "': ");
2280     } else if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
2281 	xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) actxt;
2282 	/*
2283 	* Work on node infos.
2284 	*/
2285 	if (vctxt->inode->nodeType == XML_ATTRIBUTE_NODE) {
2286 	    xmlSchemaNodeInfoPtr ielem =
2287 		vctxt->elemInfos[vctxt->depth];
2288 
2289 	    *msg = xmlStrdup(BAD_CAST "Element '");
2290 	    *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2291 		ielem->nsName, ielem->localName));
2292 	    FREE_AND_NULL(str);
2293 	    *msg = xmlStrcat(*msg, BAD_CAST "', ");
2294 	    *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
2295 	} else {
2296 	    *msg = xmlStrdup(BAD_CAST "Element '");
2297 	}
2298 	*msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2299 	    vctxt->inode->nsName, vctxt->inode->localName));
2300 	FREE_AND_NULL(str);
2301 	*msg = xmlStrcat(*msg, BAD_CAST "': ");
2302     } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
2303 	/*
2304 	* Hmm, no node while parsing?
2305 	* Return an empty string, in case NULL will break something.
2306 	*/
2307 	*msg = xmlStrdup(BAD_CAST "");
2308     } else {
2309 	TODO
2310 	return (NULL);
2311     }
2312 
2313     /*
2314      * xmlSchemaFormatItemForReport() also returns an escaped format
2315      * string, so do this before calling it below (in the future).
2316      */
2317     xmlEscapeFormatString(msg);
2318 
2319     /*
2320     * VAL TODO: The output of the given schema component is currently
2321     * disabled.
2322     */
2323 #if 0
2324     if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
2325 	*msg = xmlStrcat(*msg, BAD_CAST " [");
2326 	*msg = xmlStrcat(*msg, xmlSchemaFormatItemForReport(&str,
2327 	    NULL, type, NULL, 0));
2328 	FREE_AND_NULL(str)
2329 	*msg = xmlStrcat(*msg, BAD_CAST "]");
2330     }
2331 #endif
2332     return (*msg);
2333 }
2334 
2335 static void LIBXML_ATTR_FORMAT(3,0)
xmlSchemaInternalErr2(xmlSchemaAbstractCtxtPtr actxt,const char * funcName,const char * message,const xmlChar * str1,const xmlChar * str2)2336 xmlSchemaInternalErr2(xmlSchemaAbstractCtxtPtr actxt,
2337 		     const char *funcName,
2338 		     const char *message,
2339 		     const xmlChar *str1,
2340 		     const xmlChar *str2)
2341 {
2342     xmlChar *msg = NULL;
2343 
2344     if (actxt == NULL)
2345         return;
2346     msg = xmlStrdup(BAD_CAST "Internal error: %s, ");
2347     msg = xmlStrcat(msg, BAD_CAST message);
2348     msg = xmlStrcat(msg, BAD_CAST ".\n");
2349 
2350     if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR)
2351 	xmlSchemaErr3(actxt, XML_SCHEMAV_INTERNAL, NULL,
2352 	    (const char *) msg, (const xmlChar *) funcName, str1, str2);
2353     else if (actxt->type == XML_SCHEMA_CTXT_PARSER)
2354 	xmlSchemaErr3(actxt, XML_SCHEMAP_INTERNAL, NULL,
2355 	    (const char *) msg, (const xmlChar *) funcName, str1, str2);
2356 
2357     FREE_AND_NULL(msg)
2358 }
2359 
2360 static void LIBXML_ATTR_FORMAT(3,0)
xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,const char * funcName,const char * message)2361 xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
2362 		     const char *funcName,
2363 		     const char *message)
2364 {
2365     xmlSchemaInternalErr2(actxt, funcName, message, NULL, NULL);
2366 }
2367 
2368 #if 0
2369 static void LIBXML_ATTR_FORMAT(3,0)
2370 xmlSchemaPInternalErr(xmlSchemaParserCtxtPtr pctxt,
2371 		     const char *funcName,
2372 		     const char *message,
2373 		     const xmlChar *str1,
2374 		     const xmlChar *str2)
2375 {
2376     xmlSchemaInternalErr2(ACTXT_CAST pctxt, funcName, message,
2377 	str1, str2);
2378 }
2379 #endif
2380 
2381 static void LIBXML_ATTR_FORMAT(5,0)
xmlSchemaCustomErr4(xmlSchemaAbstractCtxtPtr actxt,xmlParserErrors error,xmlNodePtr node,xmlSchemaBasicItemPtr item,const char * message,const xmlChar * str1,const xmlChar * str2,const xmlChar * str3,const xmlChar * str4)2382 xmlSchemaCustomErr4(xmlSchemaAbstractCtxtPtr actxt,
2383 		   xmlParserErrors error,
2384 		   xmlNodePtr node,
2385 		   xmlSchemaBasicItemPtr item,
2386 		   const char *message,
2387 		   const xmlChar *str1, const xmlChar *str2,
2388 		   const xmlChar *str3, const xmlChar *str4)
2389 {
2390     xmlChar *msg = NULL;
2391 
2392     if ((node == NULL) && (item != NULL) &&
2393 	(actxt->type == XML_SCHEMA_CTXT_PARSER)) {
2394 	node = WXS_ITEM_NODE(item);
2395 	xmlSchemaFormatItemForReport(&msg, NULL, item, NULL);
2396 	msg = xmlStrcat(msg, BAD_CAST ": ");
2397     } else
2398 	xmlSchemaFormatNodeForError(&msg, actxt, node);
2399     msg = xmlStrcat(msg, (const xmlChar *) message);
2400     msg = xmlStrcat(msg, BAD_CAST ".\n");
2401     xmlSchemaErr4(actxt, error, node,
2402 	(const char *) msg, str1, str2, str3, str4);
2403     FREE_AND_NULL(msg)
2404 }
2405 
2406 static void LIBXML_ATTR_FORMAT(5,0)
xmlSchemaCustomErr(xmlSchemaAbstractCtxtPtr actxt,xmlParserErrors error,xmlNodePtr node,xmlSchemaBasicItemPtr item,const char * message,const xmlChar * str1,const xmlChar * str2)2407 xmlSchemaCustomErr(xmlSchemaAbstractCtxtPtr actxt,
2408 		   xmlParserErrors error,
2409 		   xmlNodePtr node,
2410 		   xmlSchemaBasicItemPtr item,
2411 		   const char *message,
2412 		   const xmlChar *str1,
2413 		   const xmlChar *str2)
2414 {
2415     xmlSchemaCustomErr4(actxt, error, node, item,
2416 	message, str1, str2, NULL, NULL);
2417 }
2418 
2419 
2420 
2421 static void LIBXML_ATTR_FORMAT(5,0)
xmlSchemaCustomWarning(xmlSchemaAbstractCtxtPtr actxt,xmlParserErrors error,xmlNodePtr node,xmlSchemaTypePtr type ATTRIBUTE_UNUSED,const char * message,const xmlChar * str1,const xmlChar * str2,const xmlChar * str3)2422 xmlSchemaCustomWarning(xmlSchemaAbstractCtxtPtr actxt,
2423 		   xmlParserErrors error,
2424 		   xmlNodePtr node,
2425 		   xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2426 		   const char *message,
2427 		   const xmlChar *str1,
2428 		   const xmlChar *str2,
2429 		   const xmlChar *str3)
2430 {
2431     xmlChar *msg = NULL;
2432 
2433     xmlSchemaFormatNodeForError(&msg, actxt, node);
2434     msg = xmlStrcat(msg, (const xmlChar *) message);
2435     msg = xmlStrcat(msg, BAD_CAST ".\n");
2436 
2437     /* URGENT TODO: Set the error code to something sane. */
2438     xmlSchemaErr4Line(actxt, XML_ERR_WARNING, error, node, 0,
2439 	(const char *) msg, str1, str2, str3, NULL);
2440 
2441     FREE_AND_NULL(msg)
2442 }
2443 
2444 
2445 
2446 static void LIBXML_ATTR_FORMAT(5,0)
xmlSchemaKeyrefErr(xmlSchemaValidCtxtPtr vctxt,xmlParserErrors error,xmlSchemaPSVIIDCNodePtr idcNode,xmlSchemaTypePtr type ATTRIBUTE_UNUSED,const char * message,const xmlChar * str1,const xmlChar * str2)2447 xmlSchemaKeyrefErr(xmlSchemaValidCtxtPtr vctxt,
2448 		   xmlParserErrors error,
2449 		   xmlSchemaPSVIIDCNodePtr idcNode,
2450 		   xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2451 		   const char *message,
2452 		   const xmlChar *str1,
2453 		   const xmlChar *str2)
2454 {
2455     xmlChar *msg = NULL, *qname = NULL;
2456 
2457     msg = xmlStrdup(BAD_CAST "Element '%s': ");
2458     msg = xmlStrcat(msg, (const xmlChar *) message);
2459     msg = xmlStrcat(msg, BAD_CAST ".\n");
2460     xmlSchemaErr4Line(ACTXT_CAST vctxt, XML_ERR_ERROR,
2461 	error, NULL, idcNode->nodeLine, (const char *) msg,
2462 	xmlSchemaFormatQName(&qname,
2463 	    vctxt->nodeQNames->items[idcNode->nodeQNameID +1],
2464 	    vctxt->nodeQNames->items[idcNode->nodeQNameID]),
2465 	str1, str2, NULL);
2466     FREE_AND_NULL(qname);
2467     FREE_AND_NULL(msg);
2468 }
2469 
2470 static int
xmlSchemaEvalErrorNodeType(xmlSchemaAbstractCtxtPtr actxt,xmlNodePtr node)2471 xmlSchemaEvalErrorNodeType(xmlSchemaAbstractCtxtPtr actxt,
2472 			   xmlNodePtr node)
2473 {
2474     if (node != NULL)
2475 	return (node->type);
2476     if ((actxt->type == XML_SCHEMA_CTXT_VALIDATOR) &&
2477 	(((xmlSchemaValidCtxtPtr) actxt)->inode != NULL))
2478 	return ( ((xmlSchemaValidCtxtPtr) actxt)->inode->nodeType);
2479     return (-1);
2480 }
2481 
2482 static int
xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)2483 xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
2484 {
2485     switch (item->type) {
2486 	case XML_SCHEMA_TYPE_COMPLEX:
2487 	case XML_SCHEMA_TYPE_SIMPLE:
2488 	    if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
2489 		return(1);
2490 	    break;
2491 	case XML_SCHEMA_TYPE_GROUP:
2492 	    return (1);
2493 	case XML_SCHEMA_TYPE_ELEMENT:
2494 	    if ( ((xmlSchemaElementPtr) item)->flags &
2495 		XML_SCHEMAS_ELEM_GLOBAL)
2496 		return(1);
2497 	    break;
2498 	case XML_SCHEMA_TYPE_ATTRIBUTE:
2499 	    if ( ((xmlSchemaAttributePtr) item)->flags &
2500 		XML_SCHEMAS_ATTR_GLOBAL)
2501 		return(1);
2502 	    break;
2503 	/* Note that attribute groups are always global. */
2504 	default:
2505 	    return(1);
2506     }
2507     return (0);
2508 }
2509 
2510 static void
xmlSchemaSimpleTypeErr(xmlSchemaAbstractCtxtPtr actxt,xmlParserErrors error,xmlNodePtr node,const xmlChar * value,xmlSchemaTypePtr type,int displayValue)2511 xmlSchemaSimpleTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2512 		       xmlParserErrors error,
2513 		       xmlNodePtr node,
2514 		       const xmlChar *value,
2515 		       xmlSchemaTypePtr type,
2516 		       int displayValue)
2517 {
2518     xmlChar *msg = NULL;
2519 
2520     xmlSchemaFormatNodeForError(&msg, actxt, node);
2521 
2522     if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2523 	    XML_ATTRIBUTE_NODE))
2524 	msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
2525     else
2526 	msg = xmlStrcat(msg, BAD_CAST "The character content is not a valid "
2527 	    "value of ");
2528 
2529     if (! xmlSchemaIsGlobalItem(type))
2530 	msg = xmlStrcat(msg, BAD_CAST "the local ");
2531     else
2532 	msg = xmlStrcat(msg, BAD_CAST "the ");
2533 
2534     if (WXS_IS_ATOMIC(type))
2535 	msg = xmlStrcat(msg, BAD_CAST "atomic type");
2536     else if (WXS_IS_LIST(type))
2537 	msg = xmlStrcat(msg, BAD_CAST "list type");
2538     else if (WXS_IS_UNION(type))
2539 	msg = xmlStrcat(msg, BAD_CAST "union type");
2540 
2541     if (xmlSchemaIsGlobalItem(type)) {
2542 	xmlChar *str = NULL;
2543 	msg = xmlStrcat(msg, BAD_CAST " '");
2544 	if (type->builtInType != 0) {
2545 	    msg = xmlStrcat(msg, BAD_CAST "xs:");
2546 	    str = xmlStrdup(type->name);
2547 	} else {
2548 	    const xmlChar *qName = xmlSchemaFormatQName(&str, type->targetNamespace, type->name);
2549 	    if (!str)
2550 		str = xmlStrdup(qName);
2551 	}
2552 	msg = xmlStrcat(msg, xmlEscapeFormatString(&str));
2553 	msg = xmlStrcat(msg, BAD_CAST "'");
2554 	FREE_AND_NULL(str);
2555     }
2556     msg = xmlStrcat(msg, BAD_CAST ".\n");
2557     if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2558 	    XML_ATTRIBUTE_NODE))
2559 	xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2560     else
2561 	xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2562     FREE_AND_NULL(msg)
2563 }
2564 
2565 static const xmlChar *
xmlSchemaFormatErrorNodeQName(xmlChar ** str,xmlSchemaNodeInfoPtr ni,xmlNodePtr node)2566 xmlSchemaFormatErrorNodeQName(xmlChar ** str,
2567 			      xmlSchemaNodeInfoPtr ni,
2568 			      xmlNodePtr node)
2569 {
2570     if (node != NULL) {
2571 	if (node->ns != NULL)
2572 	    return (xmlSchemaFormatQName(str, node->ns->href, node->name));
2573 	else
2574 	    return (xmlSchemaFormatQName(str, NULL, node->name));
2575     } else if (ni != NULL)
2576 	return (xmlSchemaFormatQName(str, ni->nsName, ni->localName));
2577     return (NULL);
2578 }
2579 
2580 static void
xmlSchemaIllegalAttrErr(xmlSchemaAbstractCtxtPtr actxt,xmlParserErrors error,xmlSchemaAttrInfoPtr ni,xmlNodePtr node)2581 xmlSchemaIllegalAttrErr(xmlSchemaAbstractCtxtPtr actxt,
2582 			xmlParserErrors error,
2583 			xmlSchemaAttrInfoPtr ni,
2584 			xmlNodePtr node)
2585 {
2586     xmlChar *msg = NULL, *str = NULL;
2587 
2588     xmlSchemaFormatNodeForError(&msg, actxt, node);
2589     msg = xmlStrcat(msg, BAD_CAST "The attribute '%s' is not allowed.\n");
2590     xmlSchemaErr(actxt, error, node, (const char *) msg,
2591 	xmlSchemaFormatErrorNodeQName(&str, (xmlSchemaNodeInfoPtr) ni, node),
2592 	NULL);
2593     FREE_AND_NULL(str)
2594     FREE_AND_NULL(msg)
2595 }
2596 
2597 static void LIBXML_ATTR_FORMAT(5,0)
xmlSchemaComplexTypeErr(xmlSchemaAbstractCtxtPtr actxt,xmlParserErrors error,xmlNodePtr node,xmlSchemaTypePtr type ATTRIBUTE_UNUSED,const char * message,int nbval,int nbneg,xmlChar ** values)2598 xmlSchemaComplexTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2599 		        xmlParserErrors error,
2600 		        xmlNodePtr node,
2601 			xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2602 			const char *message,
2603 			int nbval,
2604 			int nbneg,
2605 			xmlChar **values)
2606 {
2607     xmlChar *str = NULL, *msg = NULL;
2608     xmlChar *localName, *nsName;
2609     const xmlChar *cur, *end;
2610     int i;
2611 
2612     xmlSchemaFormatNodeForError(&msg, actxt, node);
2613     msg = xmlStrcat(msg, (const xmlChar *) message);
2614     msg = xmlStrcat(msg, BAD_CAST ".");
2615     /*
2616     * Note that is does not make sense to report that we have a
2617     * wildcard here, since the wildcard might be unfolded into
2618     * multiple transitions.
2619     */
2620     if (nbval + nbneg > 0) {
2621 	if (nbval + nbneg > 1) {
2622 	    str = xmlStrdup(BAD_CAST " Expected is one of ( ");
2623 	} else
2624 	    str = xmlStrdup(BAD_CAST " Expected is ( ");
2625 	nsName = NULL;
2626 
2627 	for (i = 0; i < nbval + nbneg; i++) {
2628 	    cur = values[i];
2629 	    if (cur == NULL)
2630 	        continue;
2631 	    if ((cur[0] == 'n') && (cur[1] == 'o') && (cur[2] == 't') &&
2632 	        (cur[3] == ' ')) {
2633 		cur += 4;
2634 		str = xmlStrcat(str, BAD_CAST "##other");
2635 	    }
2636 	    /*
2637 	    * Get the local name.
2638 	    */
2639 	    localName = NULL;
2640 
2641 	    end = cur;
2642 	    if (*end == '*') {
2643 		localName = xmlStrdup(BAD_CAST "*");
2644 		end++;
2645 	    } else {
2646 		while ((*end != 0) && (*end != '|'))
2647 		    end++;
2648 		localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
2649 	    }
2650 	    if (*end != 0) {
2651 		end++;
2652 		/*
2653 		* Skip "*|*" if they come with negated expressions, since
2654 		* they represent the same negated wildcard.
2655 		*/
2656 		if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
2657 		    /*
2658 		    * Get the namespace name.
2659 		    */
2660 		    cur = end;
2661 		    if (*end == '*') {
2662 			nsName = xmlStrdup(BAD_CAST "{*}");
2663 		    } else {
2664 			while (*end != 0)
2665 			    end++;
2666 
2667 			if (i >= nbval)
2668 			    nsName = xmlStrdup(BAD_CAST "{##other:");
2669 			else
2670 			    nsName = xmlStrdup(BAD_CAST "{");
2671 
2672 			nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
2673 			nsName = xmlStrcat(nsName, BAD_CAST "}");
2674 		    }
2675 		    str = xmlStrcat(str, BAD_CAST nsName);
2676 		    FREE_AND_NULL(nsName)
2677 		} else {
2678 		    FREE_AND_NULL(localName);
2679 		    continue;
2680 		}
2681 	    }
2682 	    str = xmlStrcat(str, BAD_CAST localName);
2683 	    FREE_AND_NULL(localName);
2684 
2685 	    if (i < nbval + nbneg -1)
2686 		str = xmlStrcat(str, BAD_CAST ", ");
2687 	}
2688 	str = xmlStrcat(str, BAD_CAST " ).\n");
2689 	msg = xmlStrcat(msg, xmlEscapeFormatString(&str));
2690 	FREE_AND_NULL(str)
2691     } else
2692       msg = xmlStrcat(msg, BAD_CAST "\n");
2693     xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2694     xmlFree(msg);
2695 }
2696 
2697 static void LIBXML_ATTR_FORMAT(8,0)
xmlSchemaFacetErr(xmlSchemaAbstractCtxtPtr actxt,xmlParserErrors error,xmlNodePtr node,const xmlChar * value,unsigned long length,xmlSchemaTypePtr type,xmlSchemaFacetPtr facet,const char * message,const xmlChar * str1,const xmlChar * str2)2698 xmlSchemaFacetErr(xmlSchemaAbstractCtxtPtr actxt,
2699 		  xmlParserErrors error,
2700 		  xmlNodePtr node,
2701 		  const xmlChar *value,
2702 		  unsigned long length,
2703 		  xmlSchemaTypePtr type,
2704 		  xmlSchemaFacetPtr facet,
2705 		  const char *message,
2706 		  const xmlChar *str1,
2707 		  const xmlChar *str2)
2708 {
2709     xmlChar *str = NULL, *msg = NULL;
2710     xmlSchemaTypeType facetType;
2711     int nodeType = xmlSchemaEvalErrorNodeType(actxt, node);
2712 
2713     xmlSchemaFormatNodeForError(&msg, actxt, node);
2714     if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
2715 	facetType = XML_SCHEMA_FACET_ENUMERATION;
2716 	/*
2717 	* If enumerations are validated, one must not expect the
2718 	* facet to be given.
2719 	*/
2720     } else
2721 	facetType = facet->type;
2722     msg = xmlStrcat(msg, BAD_CAST "[");
2723     msg = xmlStrcat(msg, BAD_CAST "facet '");
2724     msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facetType));
2725     msg = xmlStrcat(msg, BAD_CAST "'] ");
2726     if (message == NULL) {
2727 	/*
2728 	* Use a default message.
2729 	*/
2730 	if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
2731 	    (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
2732 	    (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
2733 
2734 	    char len[25], actLen[25];
2735 
2736 	    /* FIXME, TODO: What is the max expected string length of the
2737 	    * this value?
2738 	    */
2739 	    if (nodeType == XML_ATTRIBUTE_NODE)
2740 		msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
2741 	    else
2742 		msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
2743 
2744 	    snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
2745 	    snprintf(actLen, 24, "%lu", length);
2746 
2747 	    if (facetType == XML_SCHEMA_FACET_LENGTH)
2748 		msg = xmlStrcat(msg,
2749 		BAD_CAST "this differs from the allowed length of '%s'.\n");
2750 	    else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
2751 		msg = xmlStrcat(msg,
2752 		BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
2753 	    else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
2754 		msg = xmlStrcat(msg,
2755 		BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
2756 
2757 	    if (nodeType == XML_ATTRIBUTE_NODE)
2758 		xmlSchemaErr3(actxt, error, node, (const char *) msg,
2759 		    value, (const xmlChar *) actLen, (const xmlChar *) len);
2760 	    else
2761 		xmlSchemaErr(actxt, error, node, (const char *) msg,
2762 		    (const xmlChar *) actLen, (const xmlChar *) len);
2763 
2764 	} else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
2765 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
2766 		"of the set {%s}.\n");
2767 	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2768 		xmlSchemaFormatFacetEnumSet(actxt, &str, type));
2769 	} else if (facetType == XML_SCHEMA_FACET_PATTERN) {
2770 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
2771 		"by the pattern '%s'.\n");
2772 	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2773 		facet->value);
2774 	} else if (facetType == XML_SCHEMA_FACET_MININCLUSIVE) {
2775 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' is less than the "
2776 		"minimum value allowed ('%s').\n");
2777 	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2778 		facet->value);
2779 	} else if (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) {
2780 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' is greater than the "
2781 		"maximum value allowed ('%s').\n");
2782 	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2783 		facet->value);
2784 	} else if (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE) {
2785 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be greater than "
2786 		"'%s'.\n");
2787 	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2788 		facet->value);
2789 	} else if (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) {
2790 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be less than "
2791 		"'%s'.\n");
2792 	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2793 		facet->value);
2794 	} else if (facetType == XML_SCHEMA_FACET_TOTALDIGITS) {
2795 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more "
2796 		"digits than are allowed ('%s').\n");
2797 	    xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2798 		facet->value);
2799 	} else if (facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) {
2800 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more fractional "
2801 		"digits than are allowed ('%s').\n");
2802 	    xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2803 		facet->value);
2804 	} else if (nodeType == XML_ATTRIBUTE_NODE) {
2805 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
2806 	    xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2807 	} else {
2808 	    msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
2809 	    xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2810 	}
2811     } else {
2812 	msg = xmlStrcat(msg, (const xmlChar *) message);
2813 	msg = xmlStrcat(msg, BAD_CAST ".\n");
2814 	xmlSchemaErr(actxt, error, node, (const char *) msg, str1, str2);
2815     }
2816     FREE_AND_NULL(str)
2817     xmlFree(msg);
2818 }
2819 
2820 #define VERROR(err, type, msg) \
2821     xmlSchemaCustomErr(ACTXT_CAST vctxt, err, NULL, type, msg, NULL, NULL);
2822 
2823 #define VERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST vctxt, func, msg);
2824 
2825 #define PERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST pctxt, func, msg);
2826 #define PERROR_INT2(func, msg) xmlSchemaInternalErr(ACTXT_CAST ctxt, func, msg);
2827 
2828 #define AERROR_INT(func, msg) xmlSchemaInternalErr(actxt, func, msg);
2829 
2830 
2831 /**
2832  * xmlSchemaPMissingAttrErr:
2833  * @ctxt: the schema validation context
2834  * @ownerItem: the owner as a schema object
2835  * @ownerElem: the owner as an element node
2836  * @node: the parent element node of the missing attribute node
2837  * @type: the corresponding type of the attribute node
2838  *
2839  * Reports an illegal attribute.
2840  */
2841 static void
xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaBasicItemPtr ownerItem,xmlNodePtr ownerElem,const char * name,const char * message)2842 xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
2843 			 xmlParserErrors error,
2844 			 xmlSchemaBasicItemPtr ownerItem,
2845 			 xmlNodePtr ownerElem,
2846 			 const char *name,
2847 			 const char *message)
2848 {
2849     xmlChar *des = NULL;
2850 
2851     xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2852 
2853     if (message != NULL)
2854 	xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
2855     else
2856 	xmlSchemaPErr(ctxt, ownerElem, error,
2857 	    "%s: The attribute '%s' is required but missing.\n",
2858 	    BAD_CAST des, BAD_CAST name);
2859     FREE_AND_NULL(des);
2860 }
2861 
2862 
2863 /**
2864  * xmlSchemaPResCompAttrErr:
2865  * @ctxt: the schema validation context
2866  * @error: the error code
2867  * @ownerItem: the owner as a schema object
2868  * @ownerElem: the owner as an element node
2869  * @name: the name of the attribute holding the QName
2870  * @refName: the referenced local name
2871  * @refURI: the referenced namespace URI
2872  * @message: optional message
2873  *
2874  * Used to report QName attribute values that failed to resolve
2875  * to schema components.
2876  */
2877 static void
xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaBasicItemPtr ownerItem,xmlNodePtr ownerElem,const char * name,const xmlChar * refName,const xmlChar * refURI,xmlSchemaTypeType refType,const char * refTypeStr)2878 xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
2879 			 xmlParserErrors error,
2880 			 xmlSchemaBasicItemPtr ownerItem,
2881 			 xmlNodePtr ownerElem,
2882 			 const char *name,
2883 			 const xmlChar *refName,
2884 			 const xmlChar *refURI,
2885 			 xmlSchemaTypeType refType,
2886 			 const char *refTypeStr)
2887 {
2888     xmlChar *des = NULL, *strA = NULL;
2889 
2890     xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2891     if (refTypeStr == NULL)
2892 	refTypeStr = (const char *) xmlSchemaItemTypeToStr(refType);
2893     xmlSchemaPErrExt(ctxt, ownerElem, error,
2894 	    NULL, NULL, NULL,
2895 	    "%s, attribute '%s': The QName value '%s' does not resolve to a(n) "
2896 	    "%s.\n", BAD_CAST des, BAD_CAST name,
2897 	    xmlSchemaFormatQName(&strA, refURI, refName),
2898 	    BAD_CAST refTypeStr, NULL);
2899     FREE_AND_NULL(des)
2900     FREE_AND_NULL(strA)
2901 }
2902 
2903 /**
2904  * xmlSchemaPCustomAttrErr:
2905  * @ctxt: the schema parser context
2906  * @error: the error code
2907  * @ownerDes: the designation of the owner
2908  * @ownerItem: the owner as a schema object
2909  * @attr: the illegal attribute node
2910  *
2911  * Reports an illegal attribute during the parse.
2912  */
2913 static void
xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlChar ** ownerDes,xmlSchemaBasicItemPtr ownerItem,xmlAttrPtr attr,const char * msg)2914 xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
2915 			xmlParserErrors error,
2916 			xmlChar **ownerDes,
2917 			xmlSchemaBasicItemPtr ownerItem,
2918 			xmlAttrPtr attr,
2919 			const char *msg)
2920 {
2921     xmlChar *des = NULL;
2922 
2923     if (ownerDes == NULL)
2924 	xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
2925     else if (*ownerDes == NULL) {
2926 	xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
2927 	des = *ownerDes;
2928     } else
2929 	des = *ownerDes;
2930     if (attr == NULL) {
2931 	xmlSchemaPErrExt(ctxt, NULL, error, NULL, NULL, NULL,
2932 	    "%s, attribute '%s': %s.\n",
2933 	    BAD_CAST des, (const xmlChar *) "Unknown",
2934 	    (const xmlChar *) msg, NULL, NULL);
2935     } else {
2936 	xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
2937 	    "%s, attribute '%s': %s.\n",
2938 	    BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
2939     }
2940     if (ownerDes == NULL)
2941 	FREE_AND_NULL(des);
2942 }
2943 
2944 /**
2945  * xmlSchemaPIllegalAttrErr:
2946  * @ctxt: the schema parser context
2947  * @error: the error code
2948  * @ownerItem: the attribute's owner item
2949  * @attr: the illegal attribute node
2950  *
2951  * Reports an illegal attribute during the parse.
2952  */
2953 static void
xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaBasicItemPtr ownerComp ATTRIBUTE_UNUSED,xmlAttrPtr attr)2954 xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
2955 			 xmlParserErrors error,
2956 			 xmlSchemaBasicItemPtr ownerComp ATTRIBUTE_UNUSED,
2957 			 xmlAttrPtr attr)
2958 {
2959     xmlChar *strA = NULL, *strB = NULL;
2960 
2961     xmlSchemaFormatNodeForError(&strA, ACTXT_CAST ctxt, attr->parent);
2962     xmlSchemaErr4(ACTXT_CAST ctxt, error, (xmlNodePtr) attr,
2963 	"%sThe attribute '%s' is not allowed.\n", BAD_CAST strA,
2964 	xmlSchemaFormatQNameNs(&strB, attr->ns, attr->name),
2965 	NULL, NULL);
2966     FREE_AND_NULL(strA);
2967     FREE_AND_NULL(strB);
2968 }
2969 
2970 /**
2971  * xmlSchemaPCustomErr:
2972  * @ctxt: the schema parser context
2973  * @error: the error code
2974  * @itemDes: the designation of the schema item
2975  * @item: the schema item
2976  * @itemElem: the node of the schema item
2977  * @message: the error message
2978  * @str1: an optional param for the error message
2979  * @str2: an optional param for the error message
2980  * @str3: an optional param for the error message
2981  *
2982  * Reports an error during parsing.
2983  */
2984 static void LIBXML_ATTR_FORMAT(5,0)
xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaBasicItemPtr item,xmlNodePtr itemElem,const char * message,const xmlChar * str1,const xmlChar * str2,const xmlChar * str3)2985 xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
2986 		    xmlParserErrors error,
2987 		    xmlSchemaBasicItemPtr item,
2988 		    xmlNodePtr itemElem,
2989 		    const char *message,
2990 		    const xmlChar *str1,
2991 		    const xmlChar *str2,
2992 		    const xmlChar *str3)
2993 {
2994     xmlChar *des = NULL, *msg = NULL;
2995 
2996     xmlSchemaFormatItemForReport(&des, NULL, item, itemElem);
2997     msg = xmlStrdup(BAD_CAST "%s: ");
2998     msg = xmlStrcat(msg, (const xmlChar *) message);
2999     msg = xmlStrcat(msg, BAD_CAST ".\n");
3000     if ((itemElem == NULL) && (item != NULL))
3001 	itemElem = WXS_ITEM_NODE(item);
3002     xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
3003 	(const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
3004     FREE_AND_NULL(des);
3005     FREE_AND_NULL(msg);
3006 }
3007 
3008 /**
3009  * xmlSchemaPCustomErr:
3010  * @ctxt: the schema parser context
3011  * @error: the error code
3012  * @itemDes: the designation of the schema item
3013  * @item: the schema item
3014  * @itemElem: the node of the schema item
3015  * @message: the error message
3016  * @str1: the optional param for the error message
3017  *
3018  * Reports an error during parsing.
3019  */
3020 static void LIBXML_ATTR_FORMAT(5,0)
xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaBasicItemPtr item,xmlNodePtr itemElem,const char * message,const xmlChar * str1)3021 xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
3022 		    xmlParserErrors error,
3023 		    xmlSchemaBasicItemPtr item,
3024 		    xmlNodePtr itemElem,
3025 		    const char *message,
3026 		    const xmlChar *str1)
3027 {
3028     xmlSchemaPCustomErrExt(ctxt, error, item, itemElem, message,
3029 	str1, NULL, NULL);
3030 }
3031 
3032 /**
3033  * xmlSchemaPAttrUseErr:
3034  * @ctxt: the schema parser context
3035  * @error: the error code
3036  * @itemDes: the designation of the schema type
3037  * @item: the schema type
3038  * @itemElem: the node of the schema type
3039  * @attr: the invalid schema attribute
3040  * @message: the error message
3041  * @str1: the optional param for the error message
3042  *
3043  * Reports an attribute use error during parsing.
3044  */
3045 static void LIBXML_ATTR_FORMAT(6,0)
xmlSchemaPAttrUseErr4(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlNodePtr node,xmlSchemaBasicItemPtr ownerItem,const xmlSchemaAttributeUsePtr attruse,const char * message,const xmlChar * str1,const xmlChar * str2,const xmlChar * str3,const xmlChar * str4)3046 xmlSchemaPAttrUseErr4(xmlSchemaParserCtxtPtr ctxt,
3047 		    xmlParserErrors error,
3048 		    xmlNodePtr node,
3049 		    xmlSchemaBasicItemPtr ownerItem,
3050 		    const xmlSchemaAttributeUsePtr attruse,
3051 		    const char *message,
3052 		    const xmlChar *str1, const xmlChar *str2,
3053 		    const xmlChar *str3,const xmlChar *str4)
3054 {
3055     xmlChar *str = NULL, *msg = NULL;
3056 
3057     xmlSchemaFormatItemForReport(&msg, NULL, ownerItem, NULL);
3058     msg = xmlStrcat(msg, BAD_CAST ", ");
3059     msg = xmlStrcat(msg,
3060 	BAD_CAST xmlSchemaFormatItemForReport(&str, NULL,
3061 	WXS_BASIC_CAST attruse, NULL));
3062     FREE_AND_NULL(str);
3063     msg = xmlStrcat(msg, BAD_CAST ": ");
3064     msg = xmlStrcat(msg, (const xmlChar *) message);
3065     msg = xmlStrcat(msg, BAD_CAST ".\n");
3066     xmlSchemaErr4(ACTXT_CAST ctxt, error, node,
3067 	(const char *) msg, str1, str2, str3, str4);
3068     xmlFree(msg);
3069 }
3070 
3071 /**
3072  * xmlSchemaPIllegalFacetAtomicErr:
3073  * @ctxt: the schema parser context
3074  * @error: the error code
3075  * @type: the schema type
3076  * @baseType: the base type of type
3077  * @facet: the illegal facet
3078  *
3079  * Reports an illegal facet for atomic simple types.
3080  */
3081 static void
xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaTypePtr type,xmlSchemaTypePtr baseType,xmlSchemaFacetPtr facet)3082 xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
3083 			  xmlParserErrors error,
3084 			  xmlSchemaTypePtr type,
3085 			  xmlSchemaTypePtr baseType,
3086 			  xmlSchemaFacetPtr facet)
3087 {
3088     xmlChar *des = NULL, *strT = NULL;
3089 
3090     xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type, type->node);
3091     xmlSchemaPErrExt(ctxt, type->node, error, NULL, NULL, NULL,
3092 	"%s: The facet '%s' is not allowed on types derived from the "
3093 	"type %s.\n",
3094 	BAD_CAST des, xmlSchemaFacetTypeToString(facet->type),
3095 	xmlSchemaFormatItemForReport(&strT, NULL, WXS_BASIC_CAST baseType, NULL),
3096 	NULL, NULL);
3097     FREE_AND_NULL(des);
3098     FREE_AND_NULL(strT);
3099 }
3100 
3101 /**
3102  * xmlSchemaPIllegalFacetListUnionErr:
3103  * @ctxt: the schema parser context
3104  * @error: the error code
3105  * @itemDes: the designation of the schema item involved
3106  * @item: the schema item involved
3107  * @facet: the illegal facet
3108  *
3109  * Reports an illegal facet for <list> and <union>.
3110  */
3111 static void
xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaTypePtr type,xmlSchemaFacetPtr facet)3112 xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
3113 			  xmlParserErrors error,
3114 			  xmlSchemaTypePtr type,
3115 			  xmlSchemaFacetPtr facet)
3116 {
3117     xmlChar *des = NULL;
3118 
3119     xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type,
3120 	type->node);
3121     xmlSchemaPErr(ctxt, type->node, error,
3122 	"%s: The facet '%s' is not allowed.\n",
3123 	BAD_CAST des, xmlSchemaFacetTypeToString(facet->type));
3124     FREE_AND_NULL(des);
3125 }
3126 
3127 /**
3128  * xmlSchemaPMutualExclAttrErr:
3129  * @ctxt: the schema validation context
3130  * @error: the error code
3131  * @elemDes: the designation of the parent element node
3132  * @attr: the bad attribute node
3133  * @type: the corresponding type of the attribute node
3134  *
3135  * Reports an illegal attribute.
3136  */
3137 static void
xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaBasicItemPtr ownerItem,xmlAttrPtr attr,const char * name1,const char * name2)3138 xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
3139 			 xmlParserErrors error,
3140 			 xmlSchemaBasicItemPtr ownerItem,
3141 			 xmlAttrPtr attr,
3142 			 const char *name1,
3143 			 const char *name2)
3144 {
3145     xmlChar *des = NULL;
3146 
3147     xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST ownerItem, attr->parent);
3148     xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
3149 	"%s: The attributes '%s' and '%s' are mutually exclusive.\n",
3150 	BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
3151     FREE_AND_NULL(des);
3152 }
3153 
3154 /**
3155  * xmlSchemaPSimpleTypeErr:
3156  * @ctxt:  the schema validation context
3157  * @error: the error code
3158  * @type: the type specifier
3159  * @ownerItem: the schema object if existent
3160  * @node: the validated node
3161  * @value: the validated value
3162  *
3163  * Reports a simple type validation error.
3164  * TODO: Should this report the value of an element as well?
3165  */
3166 static void LIBXML_ATTR_FORMAT(8,0)
xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaBasicItemPtr ownerItem ATTRIBUTE_UNUSED,xmlNodePtr node,xmlSchemaTypePtr type,const char * expected,const xmlChar * value,const char * message,const xmlChar * str1,const xmlChar * str2)3167 xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
3168 			xmlParserErrors error,
3169 			xmlSchemaBasicItemPtr ownerItem ATTRIBUTE_UNUSED,
3170 			xmlNodePtr node,
3171 			xmlSchemaTypePtr type,
3172 			const char *expected,
3173 			const xmlChar *value,
3174 			const char *message,
3175 			const xmlChar *str1,
3176 			const xmlChar *str2)
3177 {
3178     xmlChar *msg = NULL;
3179 
3180     xmlSchemaFormatNodeForError(&msg, ACTXT_CAST ctxt, node);
3181     if (message == NULL) {
3182 	/*
3183 	* Use default messages.
3184 	*/
3185 	if (type != NULL) {
3186 	    if (node->type == XML_ATTRIBUTE_NODE)
3187 		msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
3188 	    else
3189 		msg = xmlStrcat(msg, BAD_CAST "The character content is not a "
3190 		"valid value of ");
3191 	    if (! xmlSchemaIsGlobalItem(type))
3192 		msg = xmlStrcat(msg, BAD_CAST "the local ");
3193 	    else
3194 		msg = xmlStrcat(msg, BAD_CAST "the ");
3195 
3196 	    if (WXS_IS_ATOMIC(type))
3197 		msg = xmlStrcat(msg, BAD_CAST "atomic type");
3198 	    else if (WXS_IS_LIST(type))
3199 		msg = xmlStrcat(msg, BAD_CAST "list type");
3200 	    else if (WXS_IS_UNION(type))
3201 		msg = xmlStrcat(msg, BAD_CAST "union type");
3202 
3203 	    if (xmlSchemaIsGlobalItem(type)) {
3204 		xmlChar *str = NULL;
3205 		msg = xmlStrcat(msg, BAD_CAST " '");
3206 		if (type->builtInType != 0) {
3207 		    msg = xmlStrcat(msg, BAD_CAST "xs:");
3208 		    str = xmlStrdup(type->name);
3209 		} else {
3210 		    const xmlChar *qName = xmlSchemaFormatQName(&str, type->targetNamespace, type->name);
3211 		    if (!str)
3212 			str = xmlStrdup(qName);
3213 		}
3214 		msg = xmlStrcat(msg, xmlEscapeFormatString(&str));
3215 		msg = xmlStrcat(msg, BAD_CAST "'.");
3216 		FREE_AND_NULL(str);
3217 	    }
3218 	} else {
3219 	    if (node->type == XML_ATTRIBUTE_NODE)
3220 		msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not valid.");
3221 	    else
3222 		msg = xmlStrcat(msg, BAD_CAST "The character content is not "
3223 		"valid.");
3224 	}
3225 	if (expected) {
3226 	    xmlChar *expectedEscaped = xmlCharStrdup(expected);
3227 	    msg = xmlStrcat(msg, BAD_CAST " Expected is '");
3228 	    msg = xmlStrcat(msg, xmlEscapeFormatString(&expectedEscaped));
3229 	    FREE_AND_NULL(expectedEscaped);
3230 	    msg = xmlStrcat(msg, BAD_CAST "'.\n");
3231 	} else
3232 	    msg = xmlStrcat(msg, BAD_CAST "\n");
3233 	if (node->type == XML_ATTRIBUTE_NODE)
3234 	    xmlSchemaPErr(ctxt, node, error, (const char *) msg, value, NULL);
3235 	else
3236 	    xmlSchemaPErr(ctxt, node, error, (const char *) msg, NULL, NULL);
3237     } else {
3238 	msg = xmlStrcat(msg, BAD_CAST message);
3239 	msg = xmlStrcat(msg, BAD_CAST ".\n");
3240 	xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
3241 	     (const char*) msg, str1, str2, NULL, NULL, NULL);
3242     }
3243     /* Cleanup. */
3244     FREE_AND_NULL(msg)
3245 }
3246 
3247 /**
3248  * xmlSchemaPContentErr:
3249  * @ctxt: the schema parser context
3250  * @error: the error code
3251  * @ownerItem: the owner item of the holder of the content
3252  * @ownerElem: the node of the holder of the content
3253  * @child: the invalid child node
3254  * @message: the optional error message
3255  * @content: the optional string describing the correct content
3256  *
3257  * Reports an error concerning the content of a schema element.
3258  */
3259 static void
xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaBasicItemPtr ownerItem,xmlNodePtr ownerElem,xmlNodePtr child,const char * message,const char * content)3260 xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
3261 		     xmlParserErrors error,
3262 		     xmlSchemaBasicItemPtr ownerItem,
3263 		     xmlNodePtr ownerElem,
3264 		     xmlNodePtr child,
3265 		     const char *message,
3266 		     const char *content)
3267 {
3268     xmlChar *des = NULL;
3269 
3270     xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
3271     if (message != NULL)
3272 	xmlSchemaPErr2(ctxt, ownerElem, child, error,
3273 	    "%s: %s.\n",
3274 	    BAD_CAST des, BAD_CAST message);
3275     else {
3276 	if (content != NULL) {
3277 	    xmlSchemaPErr2(ctxt, ownerElem, child, error,
3278 		"%s: The content is not valid. Expected is %s.\n",
3279 		BAD_CAST des, BAD_CAST content);
3280 	} else {
3281 	    xmlSchemaPErr2(ctxt, ownerElem, child, error,
3282 		"%s: The content is not valid.\n",
3283 		BAD_CAST des, NULL);
3284 	}
3285     }
3286     FREE_AND_NULL(des)
3287 }
3288 
3289 /************************************************************************
3290  *									*
3291  *			Streamable error functions                      *
3292  *									*
3293  ************************************************************************/
3294 
3295 
3296 
3297 
3298 /************************************************************************
3299  *									*
3300  *			Validation helper functions			*
3301  *									*
3302  ************************************************************************/
3303 
3304 
3305 /************************************************************************
3306  *									*
3307  *			Allocation functions				*
3308  *									*
3309  ************************************************************************/
3310 
3311 /**
3312  * xmlSchemaNewSchemaForParserCtxt:
3313  * @ctxt:  a schema validation context
3314  *
3315  * Allocate a new Schema structure.
3316  *
3317  * Returns the newly allocated structure or NULL in case or error
3318  */
3319 static xmlSchemaPtr
xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)3320 xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
3321 {
3322     xmlSchemaPtr ret;
3323 
3324     ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
3325     if (ret == NULL) {
3326         xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
3327         return (NULL);
3328     }
3329     memset(ret, 0, sizeof(xmlSchema));
3330     ret->dict = ctxt->dict;
3331     xmlDictReference(ret->dict);
3332 
3333     return (ret);
3334 }
3335 
3336 /**
3337  * xmlSchemaNewFacet:
3338  *
3339  * Allocate a new Facet structure.
3340  *
3341  * Returns the newly allocated structure or NULL in case or error
3342  */
3343 xmlSchemaFacetPtr
xmlSchemaNewFacet(void)3344 xmlSchemaNewFacet(void)
3345 {
3346     xmlSchemaFacetPtr ret;
3347 
3348     ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
3349     if (ret == NULL) {
3350         return (NULL);
3351     }
3352     memset(ret, 0, sizeof(xmlSchemaFacet));
3353 
3354     return (ret);
3355 }
3356 
3357 /**
3358  * xmlSchemaNewAnnot:
3359  * @ctxt:  a schema validation context
3360  * @node:  a node
3361  *
3362  * Allocate a new annotation structure.
3363  *
3364  * Returns the newly allocated structure or NULL in case or error
3365  */
3366 static xmlSchemaAnnotPtr
xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node)3367 xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3368 {
3369     xmlSchemaAnnotPtr ret;
3370 
3371     ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
3372     if (ret == NULL) {
3373         xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
3374         return (NULL);
3375     }
3376     memset(ret, 0, sizeof(xmlSchemaAnnot));
3377     ret->content = node;
3378     return (ret);
3379 }
3380 
3381 static xmlSchemaItemListPtr
xmlSchemaItemListCreate(void)3382 xmlSchemaItemListCreate(void)
3383 {
3384     xmlSchemaItemListPtr ret;
3385 
3386     ret = xmlMalloc(sizeof(xmlSchemaItemList));
3387     if (ret == NULL) {
3388 	xmlSchemaPErrMemory(NULL,
3389 	    "allocating an item list structure", NULL);
3390 	return (NULL);
3391     }
3392     memset(ret, 0, sizeof(xmlSchemaItemList));
3393     return (ret);
3394 }
3395 
3396 static void
xmlSchemaItemListClear(xmlSchemaItemListPtr list)3397 xmlSchemaItemListClear(xmlSchemaItemListPtr list)
3398 {
3399     if (list->items != NULL) {
3400 	xmlFree(list->items);
3401 	list->items = NULL;
3402     }
3403     list->nbItems = 0;
3404     list->sizeItems = 0;
3405 }
3406 
3407 static int
xmlSchemaItemListAdd(xmlSchemaItemListPtr list,void * item)3408 xmlSchemaItemListAdd(xmlSchemaItemListPtr list, void *item)
3409 {
3410     if (list->items == NULL) {
3411 	list->items = (void **) xmlMalloc(
3412 	    20 * sizeof(void *));
3413 	if (list->items == NULL) {
3414 	    xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3415 	    return(-1);
3416 	}
3417 	list->sizeItems = 20;
3418     } else if (list->sizeItems <= list->nbItems) {
3419 	list->sizeItems *= 2;
3420 	list->items = (void **) xmlRealloc(list->items,
3421 	    list->sizeItems * sizeof(void *));
3422 	if (list->items == NULL) {
3423 	    xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3424 	    list->sizeItems = 0;
3425 	    return(-1);
3426 	}
3427     }
3428     list->items[list->nbItems++] = item;
3429     return(0);
3430 }
3431 
3432 static int
xmlSchemaItemListAddSize(xmlSchemaItemListPtr list,int initialSize,void * item)3433 xmlSchemaItemListAddSize(xmlSchemaItemListPtr list,
3434 			 int initialSize,
3435 			 void *item)
3436 {
3437     if (list->items == NULL) {
3438 	if (initialSize <= 0)
3439 	    initialSize = 1;
3440 	list->items = (void **) xmlMalloc(
3441 	    initialSize * sizeof(void *));
3442 	if (list->items == NULL) {
3443 	    xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3444 	    return(-1);
3445 	}
3446 	list->sizeItems = initialSize;
3447     } else if (list->sizeItems <= list->nbItems) {
3448 	list->sizeItems *= 2;
3449 	list->items = (void **) xmlRealloc(list->items,
3450 	    list->sizeItems * sizeof(void *));
3451 	if (list->items == NULL) {
3452 	    xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3453 	    list->sizeItems = 0;
3454 	    return(-1);
3455 	}
3456     }
3457     list->items[list->nbItems++] = item;
3458     return(0);
3459 }
3460 
3461 static int
xmlSchemaItemListInsert(xmlSchemaItemListPtr list,void * item,int idx)3462 xmlSchemaItemListInsert(xmlSchemaItemListPtr list, void *item, int idx)
3463 {
3464     if (list->items == NULL) {
3465 	list->items = (void **) xmlMalloc(
3466 	    20 * sizeof(void *));
3467 	if (list->items == NULL) {
3468 	    xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3469 	    return(-1);
3470 	}
3471 	list->sizeItems = 20;
3472     } else if (list->sizeItems <= list->nbItems) {
3473 	list->sizeItems *= 2;
3474 	list->items = (void **) xmlRealloc(list->items,
3475 	    list->sizeItems * sizeof(void *));
3476 	if (list->items == NULL) {
3477 	    xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3478 	    list->sizeItems = 0;
3479 	    return(-1);
3480 	}
3481     }
3482     /*
3483     * Just append if the index is greater/equal than the item count.
3484     */
3485     if (idx >= list->nbItems) {
3486 	list->items[list->nbItems++] = item;
3487     } else {
3488 	int i;
3489 	for (i = list->nbItems; i > idx; i--)
3490 	    list->items[i] = list->items[i-1];
3491 	list->items[idx] = item;
3492 	list->nbItems++;
3493     }
3494     return(0);
3495 }
3496 
3497 #if 0 /* enable if ever needed */
3498 static int
3499 xmlSchemaItemListInsertSize(xmlSchemaItemListPtr list,
3500 			    int initialSize,
3501 			    void *item,
3502 			    int idx)
3503 {
3504     if (list->items == NULL) {
3505 	if (initialSize <= 0)
3506 	    initialSize = 1;
3507 	list->items = (void **) xmlMalloc(
3508 	    initialSize * sizeof(void *));
3509 	if (list->items == NULL) {
3510 	    xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3511 	    return(-1);
3512 	}
3513 	list->sizeItems = initialSize;
3514     } else if (list->sizeItems <= list->nbItems) {
3515 	list->sizeItems *= 2;
3516 	list->items = (void **) xmlRealloc(list->items,
3517 	    list->sizeItems * sizeof(void *));
3518 	if (list->items == NULL) {
3519 	    xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3520 	    list->sizeItems = 0;
3521 	    return(-1);
3522 	}
3523     }
3524     /*
3525     * Just append if the index is greater/equal than the item count.
3526     */
3527     if (idx >= list->nbItems) {
3528 	list->items[list->nbItems++] = item;
3529     } else {
3530 	int i;
3531 	for (i = list->nbItems; i > idx; i--)
3532 	    list->items[i] = list->items[i-1];
3533 	list->items[idx] = item;
3534 	list->nbItems++;
3535     }
3536     return(0);
3537 }
3538 #endif
3539 
3540 static int
xmlSchemaItemListRemove(xmlSchemaItemListPtr list,int idx)3541 xmlSchemaItemListRemove(xmlSchemaItemListPtr list, int idx)
3542 {
3543     int i;
3544     if ((list->items == NULL) || (idx >= list->nbItems)) {
3545 	xmlSchemaPSimpleErr("Internal error: xmlSchemaItemListRemove, "
3546 	    "index error.\n");
3547 	return(-1);
3548     }
3549 
3550     if (list->nbItems == 1) {
3551 	/* TODO: Really free the list? */
3552 	xmlFree(list->items);
3553 	list->items = NULL;
3554 	list->nbItems = 0;
3555 	list->sizeItems = 0;
3556     } else if (list->nbItems -1 == idx) {
3557 	list->nbItems--;
3558     } else {
3559 	for (i = idx; i < list->nbItems -1; i++)
3560 	    list->items[i] = list->items[i+1];
3561 	list->nbItems--;
3562     }
3563     return(0);
3564 }
3565 
3566 /**
3567  * xmlSchemaItemListFree:
3568  * @annot:  a schema type structure
3569  *
3570  * Deallocate a annotation structure
3571  */
3572 static void
xmlSchemaItemListFree(xmlSchemaItemListPtr list)3573 xmlSchemaItemListFree(xmlSchemaItemListPtr list)
3574 {
3575     if (list == NULL)
3576 	return;
3577     if (list->items != NULL)
3578 	xmlFree(list->items);
3579     xmlFree(list);
3580 }
3581 
3582 static void
xmlSchemaBucketFree(xmlSchemaBucketPtr bucket)3583 xmlSchemaBucketFree(xmlSchemaBucketPtr bucket)
3584 {
3585     if (bucket == NULL)
3586 	return;
3587     if (bucket->globals != NULL) {
3588 	xmlSchemaComponentListFree(bucket->globals);
3589 	xmlSchemaItemListFree(bucket->globals);
3590     }
3591     if (bucket->locals != NULL) {
3592 	xmlSchemaComponentListFree(bucket->locals);
3593 	xmlSchemaItemListFree(bucket->locals);
3594     }
3595     if (bucket->relations != NULL) {
3596 	xmlSchemaSchemaRelationPtr prev, cur = bucket->relations;
3597 	do {
3598 	    prev = cur;
3599 	    cur = cur->next;
3600 	    xmlFree(prev);
3601 	} while (cur != NULL);
3602     }
3603     if ((! bucket->preserveDoc) && (bucket->doc != NULL)) {
3604 	xmlFreeDoc(bucket->doc);
3605     }
3606     if (bucket->type == XML_SCHEMA_SCHEMA_IMPORT) {
3607 	if (WXS_IMPBUCKET(bucket)->schema != NULL)
3608 	    xmlSchemaFree(WXS_IMPBUCKET(bucket)->schema);
3609     }
3610     xmlFree(bucket);
3611 }
3612 
3613 static void
xmlSchemaBucketFreeEntry(void * bucket,const xmlChar * name ATTRIBUTE_UNUSED)3614 xmlSchemaBucketFreeEntry(void *bucket, const xmlChar *name ATTRIBUTE_UNUSED)
3615 {
3616     xmlSchemaBucketFree((xmlSchemaBucketPtr) bucket);
3617 }
3618 
3619 static xmlSchemaBucketPtr
xmlSchemaBucketCreate(xmlSchemaParserCtxtPtr pctxt,int type,const xmlChar * targetNamespace)3620 xmlSchemaBucketCreate(xmlSchemaParserCtxtPtr pctxt,
3621 			 int type, const xmlChar *targetNamespace)
3622 {
3623     xmlSchemaBucketPtr ret;
3624     int size;
3625     xmlSchemaPtr mainSchema;
3626 
3627     if (WXS_CONSTRUCTOR(pctxt)->mainSchema == NULL) {
3628 	PERROR_INT("xmlSchemaBucketCreate",
3629 	    "no main schema on constructor");
3630 	return(NULL);
3631     }
3632     mainSchema = WXS_CONSTRUCTOR(pctxt)->mainSchema;
3633     /* Create the schema bucket. */
3634     if (WXS_IS_BUCKET_INCREDEF(type))
3635 	size = sizeof(xmlSchemaInclude);
3636     else
3637 	size = sizeof(xmlSchemaImport);
3638     ret = (xmlSchemaBucketPtr) xmlMalloc(size);
3639     if (ret == NULL) {
3640 	xmlSchemaPErrMemory(NULL, "allocating schema bucket", NULL);
3641 	return(NULL);
3642     }
3643     memset(ret, 0, size);
3644     ret->targetNamespace = targetNamespace;
3645     ret->type = type;
3646     ret->globals = xmlSchemaItemListCreate();
3647     if (ret->globals == NULL) {
3648 	xmlFree(ret);
3649 	return(NULL);
3650     }
3651     ret->locals = xmlSchemaItemListCreate();
3652     if (ret->locals == NULL) {
3653 	xmlFree(ret);
3654 	return(NULL);
3655     }
3656     /*
3657     * The following will assure that only the first bucket is marked as
3658     * XML_SCHEMA_SCHEMA_MAIN and it points to the *main* schema.
3659     * For each following import buckets an xmlSchema will be created.
3660     * An xmlSchema will be created for every distinct targetNamespace.
3661     * We assign the targetNamespace to the schemata here.
3662     */
3663     if (! WXS_HAS_BUCKETS(pctxt)) {
3664 	if (WXS_IS_BUCKET_INCREDEF(type)) {
3665 	    PERROR_INT("xmlSchemaBucketCreate",
3666 		"first bucket but it's an include or redefine");
3667 	    xmlSchemaBucketFree(ret);
3668 	    return(NULL);
3669 	}
3670 	/* Force the type to be XML_SCHEMA_SCHEMA_MAIN. */
3671 	ret->type = XML_SCHEMA_SCHEMA_MAIN;
3672 	/* Point to the *main* schema. */
3673 	WXS_CONSTRUCTOR(pctxt)->mainBucket = ret;
3674 	WXS_IMPBUCKET(ret)->schema = mainSchema;
3675 	/*
3676 	* Ensure that the main schema gets a targetNamespace.
3677 	*/
3678 	mainSchema->targetNamespace = targetNamespace;
3679     } else {
3680 	if (type == XML_SCHEMA_SCHEMA_MAIN) {
3681 	    PERROR_INT("xmlSchemaBucketCreate",
3682 		"main bucket but it's not the first one");
3683 	    xmlSchemaBucketFree(ret);
3684 	    return(NULL);
3685 	} else if (type == XML_SCHEMA_SCHEMA_IMPORT) {
3686 	    /*
3687 	    * Create a schema for imports and assign the
3688 	    * targetNamespace.
3689 	    */
3690 	    WXS_IMPBUCKET(ret)->schema = xmlSchemaNewSchema(pctxt);
3691 	    if (WXS_IMPBUCKET(ret)->schema == NULL) {
3692 		xmlSchemaBucketFree(ret);
3693 		return(NULL);
3694 	    }
3695 	    WXS_IMPBUCKET(ret)->schema->targetNamespace = targetNamespace;
3696 	}
3697     }
3698     if (WXS_IS_BUCKET_IMPMAIN(type)) {
3699 	int res;
3700 	/*
3701 	* Imports go into the "schemasImports" slot of the main *schema*.
3702 	* Note that we create an import entry for the main schema as well; i.e.,
3703 	* even if there's only one schema, we'll get an import.
3704 	*/
3705 	if (mainSchema->schemasImports == NULL) {
3706 	    mainSchema->schemasImports = xmlHashCreateDict(5,
3707 		WXS_CONSTRUCTOR(pctxt)->dict);
3708 	    if (mainSchema->schemasImports == NULL) {
3709 		xmlSchemaBucketFree(ret);
3710 		return(NULL);
3711 	    }
3712 	}
3713 	if (targetNamespace == NULL)
3714 	    res = xmlHashAddEntry(mainSchema->schemasImports,
3715 		XML_SCHEMAS_NO_NAMESPACE, ret);
3716 	else
3717 	    res = xmlHashAddEntry(mainSchema->schemasImports,
3718 		targetNamespace, ret);
3719 	if (res != 0) {
3720 	    PERROR_INT("xmlSchemaBucketCreate",
3721 		"failed to add the schema bucket to the hash");
3722 	    xmlSchemaBucketFree(ret);
3723 	    return(NULL);
3724 	}
3725     } else {
3726 	/* Set the @ownerImport of an include bucket. */
3727 	if (WXS_IS_BUCKET_IMPMAIN(WXS_CONSTRUCTOR(pctxt)->bucket->type))
3728 	    WXS_INCBUCKET(ret)->ownerImport =
3729 		WXS_IMPBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket);
3730 	else
3731 	    WXS_INCBUCKET(ret)->ownerImport =
3732 		WXS_INCBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket)->ownerImport;
3733 
3734 	/* Includes got into the "includes" slot of the *main* schema. */
3735 	if (mainSchema->includes == NULL) {
3736 	    mainSchema->includes = xmlSchemaItemListCreate();
3737 	    if (mainSchema->includes == NULL) {
3738 		xmlSchemaBucketFree(ret);
3739 		return(NULL);
3740 	    }
3741 	}
3742 	xmlSchemaItemListAdd(mainSchema->includes, ret);
3743     }
3744     /*
3745     * Add to list of all buckets; this is used for lookup
3746     * during schema construction time only.
3747     */
3748     if (xmlSchemaItemListAdd(WXS_CONSTRUCTOR(pctxt)->buckets, ret) == -1)
3749 	return(NULL);
3750     return(ret);
3751 }
3752 
3753 static int
xmlSchemaAddItemSize(xmlSchemaItemListPtr * list,int initialSize,void * item)3754 xmlSchemaAddItemSize(xmlSchemaItemListPtr *list, int initialSize, void *item)
3755 {
3756     if (*list == NULL) {
3757 	*list = xmlSchemaItemListCreate();
3758 	if (*list == NULL)
3759 	    return(-1);
3760     }
3761     xmlSchemaItemListAddSize(*list, initialSize, item);
3762     return(0);
3763 }
3764 
3765 /**
3766  * xmlSchemaFreeAnnot:
3767  * @annot:  a schema type structure
3768  *
3769  * Deallocate a annotation structure
3770  */
3771 static void
xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)3772 xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
3773 {
3774     if (annot == NULL)
3775         return;
3776     if (annot->next == NULL) {
3777 	xmlFree(annot);
3778     } else {
3779 	xmlSchemaAnnotPtr prev;
3780 
3781 	do {
3782 	    prev = annot;
3783 	    annot = annot->next;
3784 	    xmlFree(prev);
3785 	} while (annot != NULL);
3786     }
3787 }
3788 
3789 /**
3790  * xmlSchemaFreeNotation:
3791  * @schema:  a schema notation structure
3792  *
3793  * Deallocate a Schema Notation structure.
3794  */
3795 static void
xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)3796 xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
3797 {
3798     if (nota == NULL)
3799         return;
3800     xmlFree(nota);
3801 }
3802 
3803 /**
3804  * xmlSchemaFreeAttribute:
3805  * @attr:  an attribute declaration
3806  *
3807  * Deallocates an attribute declaration structure.
3808  */
3809 static void
xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)3810 xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
3811 {
3812     if (attr == NULL)
3813         return;
3814     if (attr->annot != NULL)
3815 	xmlSchemaFreeAnnot(attr->annot);
3816     if (attr->defVal != NULL)
3817 	xmlSchemaFreeValue(attr->defVal);
3818     xmlFree(attr);
3819 }
3820 
3821 /**
3822  * xmlSchemaFreeAttributeUse:
3823  * @use:  an attribute use
3824  *
3825  * Deallocates an attribute use structure.
3826  */
3827 static void
xmlSchemaFreeAttributeUse(xmlSchemaAttributeUsePtr use)3828 xmlSchemaFreeAttributeUse(xmlSchemaAttributeUsePtr use)
3829 {
3830     if (use == NULL)
3831         return;
3832     if (use->annot != NULL)
3833 	xmlSchemaFreeAnnot(use->annot);
3834     if (use->defVal != NULL)
3835 	xmlSchemaFreeValue(use->defVal);
3836     xmlFree(use);
3837 }
3838 
3839 /**
3840  * xmlSchemaFreeAttributeUseProhib:
3841  * @prohib:  an attribute use prohibition
3842  *
3843  * Deallocates an attribute use structure.
3844  */
3845 static void
xmlSchemaFreeAttributeUseProhib(xmlSchemaAttributeUseProhibPtr prohib)3846 xmlSchemaFreeAttributeUseProhib(xmlSchemaAttributeUseProhibPtr prohib)
3847 {
3848     if (prohib == NULL)
3849         return;
3850     xmlFree(prohib);
3851 }
3852 
3853 /**
3854  * xmlSchemaFreeWildcardNsSet:
3855  * set:  a schema wildcard namespace
3856  *
3857  * Deallocates a list of wildcard constraint structures.
3858  */
3859 static void
xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)3860 xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
3861 {
3862     xmlSchemaWildcardNsPtr next;
3863 
3864     while (set != NULL) {
3865 	next = set->next;
3866 	xmlFree(set);
3867 	set = next;
3868     }
3869 }
3870 
3871 /**
3872  * xmlSchemaFreeWildcard:
3873  * @wildcard:  a wildcard structure
3874  *
3875  * Deallocates a wildcard structure.
3876  */
3877 void
xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)3878 xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
3879 {
3880     if (wildcard == NULL)
3881         return;
3882     if (wildcard->annot != NULL)
3883         xmlSchemaFreeAnnot(wildcard->annot);
3884     if (wildcard->nsSet != NULL)
3885 	xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
3886     if (wildcard->negNsSet != NULL)
3887 	xmlFree(wildcard->negNsSet);
3888     xmlFree(wildcard);
3889 }
3890 
3891 /**
3892  * xmlSchemaFreeAttributeGroup:
3893  * @schema:  a schema attribute group structure
3894  *
3895  * Deallocate a Schema Attribute Group structure.
3896  */
3897 static void
xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attrGr)3898 xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attrGr)
3899 {
3900     if (attrGr == NULL)
3901         return;
3902     if (attrGr->annot != NULL)
3903         xmlSchemaFreeAnnot(attrGr->annot);
3904     if (attrGr->attrUses != NULL)
3905 	xmlSchemaItemListFree(WXS_LIST_CAST attrGr->attrUses);
3906     xmlFree(attrGr);
3907 }
3908 
3909 /**
3910  * xmlSchemaFreeQNameRef:
3911  * @item: a QName reference structure
3912  *
3913  * Deallocatea a QName reference structure.
3914  */
3915 static void
xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item)3916 xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item)
3917 {
3918     xmlFree(item);
3919 }
3920 
3921 /**
3922  * xmlSchemaFreeTypeLinkList:
3923  * @alink: a type link
3924  *
3925  * Deallocate a list of types.
3926  */
3927 static void
xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)3928 xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
3929 {
3930     xmlSchemaTypeLinkPtr next;
3931 
3932     while (link != NULL) {
3933 	next = link->next;
3934 	xmlFree(link);
3935 	link = next;
3936     }
3937 }
3938 
3939 static void
xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)3940 xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
3941 {
3942     xmlSchemaIDCStateObjPtr next;
3943     while (sto != NULL) {
3944 	next = sto->next;
3945 	if (sto->history != NULL)
3946 	    xmlFree(sto->history);
3947 	if (sto->xpathCtxt != NULL)
3948 	    xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
3949 	xmlFree(sto);
3950 	sto = next;
3951     }
3952 }
3953 
3954 /**
3955  * xmlSchemaFreeIDC:
3956  * @idc: a identity-constraint definition
3957  *
3958  * Deallocates an identity-constraint definition.
3959  */
3960 static void
xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)3961 xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)
3962 {
3963     xmlSchemaIDCSelectPtr cur, prev;
3964 
3965     if (idcDef == NULL)
3966 	return;
3967     if (idcDef->annot != NULL)
3968         xmlSchemaFreeAnnot(idcDef->annot);
3969     /* Selector */
3970     if (idcDef->selector != NULL) {
3971 	if (idcDef->selector->xpathComp != NULL)
3972 	    xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp);
3973 	xmlFree(idcDef->selector);
3974     }
3975     /* Fields */
3976     if (idcDef->fields != NULL) {
3977 	cur = idcDef->fields;
3978 	do {
3979 	    prev = cur;
3980 	    cur = cur->next;
3981 	    if (prev->xpathComp != NULL)
3982 		xmlFreePattern((xmlPatternPtr) prev->xpathComp);
3983 	    xmlFree(prev);
3984 	} while (cur != NULL);
3985     }
3986     xmlFree(idcDef);
3987 }
3988 
3989 /**
3990  * xmlSchemaFreeElement:
3991  * @schema:  a schema element structure
3992  *
3993  * Deallocate a Schema Element structure.
3994  */
3995 static void
xmlSchemaFreeElement(xmlSchemaElementPtr elem)3996 xmlSchemaFreeElement(xmlSchemaElementPtr elem)
3997 {
3998     if (elem == NULL)
3999         return;
4000     if (elem->annot != NULL)
4001         xmlSchemaFreeAnnot(elem->annot);
4002     if (elem->contModel != NULL)
4003         xmlRegFreeRegexp(elem->contModel);
4004     if (elem->defVal != NULL)
4005 	xmlSchemaFreeValue(elem->defVal);
4006     xmlFree(elem);
4007 }
4008 
4009 /**
4010  * xmlSchemaFreeFacet:
4011  * @facet:  a schema facet structure
4012  *
4013  * Deallocate a Schema Facet structure.
4014  */
4015 void
xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)4016 xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
4017 {
4018     if (facet == NULL)
4019         return;
4020     if (facet->val != NULL)
4021         xmlSchemaFreeValue(facet->val);
4022     if (facet->regexp != NULL)
4023         xmlRegFreeRegexp(facet->regexp);
4024     if (facet->annot != NULL)
4025         xmlSchemaFreeAnnot(facet->annot);
4026     xmlFree(facet);
4027 }
4028 
4029 /**
4030  * xmlSchemaFreeType:
4031  * @type:  a schema type structure
4032  *
4033  * Deallocate a Schema Type structure.
4034  */
4035 void
xmlSchemaFreeType(xmlSchemaTypePtr type)4036 xmlSchemaFreeType(xmlSchemaTypePtr type)
4037 {
4038     if (type == NULL)
4039         return;
4040     if (type->annot != NULL)
4041         xmlSchemaFreeAnnot(type->annot);
4042     if (type->facets != NULL) {
4043         xmlSchemaFacetPtr facet, next;
4044 
4045         facet = type->facets;
4046         while (facet != NULL) {
4047             next = facet->next;
4048             xmlSchemaFreeFacet(facet);
4049             facet = next;
4050         }
4051     }
4052     if (type->attrUses != NULL)
4053 	xmlSchemaItemListFree((xmlSchemaItemListPtr) type->attrUses);
4054     if (type->memberTypes != NULL)
4055 	xmlSchemaFreeTypeLinkList(type->memberTypes);
4056     if (type->facetSet != NULL) {
4057 	xmlSchemaFacetLinkPtr next, link;
4058 
4059 	link = type->facetSet;
4060 	do {
4061 	    next = link->next;
4062 	    xmlFree(link);
4063 	    link = next;
4064 	} while (link != NULL);
4065     }
4066     if (type->contModel != NULL)
4067         xmlRegFreeRegexp(type->contModel);
4068     xmlFree(type);
4069 }
4070 
4071 /**
4072  * xmlSchemaFreeModelGroupDef:
4073  * @item:  a schema model group definition
4074  *
4075  * Deallocates a schema model group definition.
4076  */
4077 static void
xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item)4078 xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item)
4079 {
4080     if (item->annot != NULL)
4081 	xmlSchemaFreeAnnot(item->annot);
4082     xmlFree(item);
4083 }
4084 
4085 /**
4086  * xmlSchemaFreeModelGroup:
4087  * @item:  a schema model group
4088  *
4089  * Deallocates a schema model group structure.
4090  */
4091 static void
xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item)4092 xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item)
4093 {
4094     if (item->annot != NULL)
4095 	xmlSchemaFreeAnnot(item->annot);
4096     xmlFree(item);
4097 }
4098 
4099 static void
xmlSchemaComponentListFree(xmlSchemaItemListPtr list)4100 xmlSchemaComponentListFree(xmlSchemaItemListPtr list)
4101 {
4102     if ((list == NULL) || (list->nbItems == 0))
4103 	return;
4104     {
4105 	xmlSchemaTreeItemPtr item;
4106 	xmlSchemaTreeItemPtr *items = (xmlSchemaTreeItemPtr *) list->items;
4107 	int i;
4108 
4109 	for (i = 0; i < list->nbItems; i++) {
4110 	    item = items[i];
4111 	    if (item == NULL)
4112 		continue;
4113 	    switch (item->type) {
4114 		case XML_SCHEMA_TYPE_SIMPLE:
4115 		case XML_SCHEMA_TYPE_COMPLEX:
4116 		    xmlSchemaFreeType((xmlSchemaTypePtr) item);
4117 		    break;
4118 		case XML_SCHEMA_TYPE_ATTRIBUTE:
4119 		    xmlSchemaFreeAttribute((xmlSchemaAttributePtr) item);
4120 		    break;
4121 		case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
4122 		    xmlSchemaFreeAttributeUse((xmlSchemaAttributeUsePtr) item);
4123 		    break;
4124 		case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
4125 		    xmlSchemaFreeAttributeUseProhib(
4126 			(xmlSchemaAttributeUseProhibPtr) item);
4127 		    break;
4128 		case XML_SCHEMA_TYPE_ELEMENT:
4129 		    xmlSchemaFreeElement((xmlSchemaElementPtr) item);
4130 		    break;
4131 		case XML_SCHEMA_TYPE_PARTICLE:
4132 		    if (item->annot != NULL)
4133 			xmlSchemaFreeAnnot(item->annot);
4134 		    xmlFree(item);
4135 		    break;
4136 		case XML_SCHEMA_TYPE_SEQUENCE:
4137 		case XML_SCHEMA_TYPE_CHOICE:
4138 		case XML_SCHEMA_TYPE_ALL:
4139 		    xmlSchemaFreeModelGroup((xmlSchemaModelGroupPtr) item);
4140 		    break;
4141 		case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
4142 		    xmlSchemaFreeAttributeGroup(
4143 			(xmlSchemaAttributeGroupPtr) item);
4144 		    break;
4145 		case XML_SCHEMA_TYPE_GROUP:
4146 		    xmlSchemaFreeModelGroupDef(
4147 			(xmlSchemaModelGroupDefPtr) item);
4148 		    break;
4149 		case XML_SCHEMA_TYPE_ANY:
4150 		case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
4151 		    xmlSchemaFreeWildcard((xmlSchemaWildcardPtr) item);
4152 		    break;
4153 		case XML_SCHEMA_TYPE_IDC_KEY:
4154 		case XML_SCHEMA_TYPE_IDC_UNIQUE:
4155 		case XML_SCHEMA_TYPE_IDC_KEYREF:
4156 		    xmlSchemaFreeIDC((xmlSchemaIDCPtr) item);
4157 		    break;
4158 		case XML_SCHEMA_TYPE_NOTATION:
4159 		    xmlSchemaFreeNotation((xmlSchemaNotationPtr) item);
4160 		    break;
4161 		case XML_SCHEMA_EXTRA_QNAMEREF:
4162 		    xmlSchemaFreeQNameRef((xmlSchemaQNameRefPtr) item);
4163 		    break;
4164 		default: {
4165 		    /* TODO: This should never be hit. */
4166 		    xmlSchemaPSimpleInternalErr(NULL,
4167 			"Internal error: xmlSchemaComponentListFree, "
4168 			"unexpected component type '%s'\n",
4169 			(const xmlChar *) WXS_ITEM_TYPE_NAME(item));
4170 			 }
4171 		    break;
4172 	    }
4173 	}
4174 	list->nbItems = 0;
4175     }
4176 }
4177 
4178 /**
4179  * xmlSchemaFree:
4180  * @schema:  a schema structure
4181  *
4182  * Deallocate a Schema structure.
4183  */
4184 void
xmlSchemaFree(xmlSchemaPtr schema)4185 xmlSchemaFree(xmlSchemaPtr schema)
4186 {
4187     if (schema == NULL)
4188         return;
4189     /* @volatiles is not used anymore :-/ */
4190     if (schema->volatiles != NULL)
4191 	TODO
4192     /*
4193     * Note that those slots are not responsible for freeing
4194     * schema components anymore; this will now be done by
4195     * the schema buckets.
4196     */
4197     if (schema->notaDecl != NULL)
4198         xmlHashFree(schema->notaDecl, NULL);
4199     if (schema->attrDecl != NULL)
4200         xmlHashFree(schema->attrDecl, NULL);
4201     if (schema->attrgrpDecl != NULL)
4202         xmlHashFree(schema->attrgrpDecl, NULL);
4203     if (schema->elemDecl != NULL)
4204         xmlHashFree(schema->elemDecl, NULL);
4205     if (schema->typeDecl != NULL)
4206         xmlHashFree(schema->typeDecl, NULL);
4207     if (schema->groupDecl != NULL)
4208         xmlHashFree(schema->groupDecl, NULL);
4209     if (schema->idcDef != NULL)
4210         xmlHashFree(schema->idcDef, NULL);
4211 
4212     if (schema->schemasImports != NULL)
4213 	xmlHashFree(schema->schemasImports, xmlSchemaBucketFreeEntry);
4214     if (schema->includes != NULL) {
4215 	xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) schema->includes;
4216 	int i;
4217 	for (i = 0; i < list->nbItems; i++) {
4218 	    xmlSchemaBucketFree((xmlSchemaBucketPtr) list->items[i]);
4219 	}
4220 	xmlSchemaItemListFree(list);
4221     }
4222     if (schema->annot != NULL)
4223         xmlSchemaFreeAnnot(schema->annot);
4224     /* Never free the doc here, since this will be done by the buckets. */
4225 
4226     xmlDictFree(schema->dict);
4227     xmlFree(schema);
4228 }
4229 
4230 /************************************************************************
4231  *									*
4232  *			Debug functions					*
4233  *									*
4234  ************************************************************************/
4235 
4236 #ifdef LIBXML_OUTPUT_ENABLED
4237 
4238 static void
4239 xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output); /* forward */
4240 
4241 /**
4242  * xmlSchemaElementDump:
4243  * @elem:  an element
4244  * @output:  the file output
4245  *
4246  * Dump the element
4247  */
4248 static void
xmlSchemaElementDump(void * payload,void * data,const xmlChar * name ATTRIBUTE_UNUSED,const xmlChar * namespace ATTRIBUTE_UNUSED,const xmlChar * context ATTRIBUTE_UNUSED)4249 xmlSchemaElementDump(void *payload, void *data,
4250                      const xmlChar * name ATTRIBUTE_UNUSED,
4251 		     const xmlChar * namespace ATTRIBUTE_UNUSED,
4252                      const xmlChar * context ATTRIBUTE_UNUSED)
4253 {
4254     xmlSchemaElementPtr elem = (xmlSchemaElementPtr) payload;
4255     FILE *output = (FILE *) data;
4256     if (elem == NULL)
4257         return;
4258 
4259 
4260     fprintf(output, "Element");
4261     if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
4262 	fprintf(output, " (global)");
4263     fprintf(output, ": '%s' ", elem->name);
4264     if (namespace != NULL)
4265 	fprintf(output, "ns '%s'", namespace);
4266     fprintf(output, "\n");
4267 #if 0
4268     if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
4269 	fprintf(output, "  min %d ", elem->minOccurs);
4270         if (elem->maxOccurs >= UNBOUNDED)
4271             fprintf(output, "max: unbounded\n");
4272         else if (elem->maxOccurs != 1)
4273             fprintf(output, "max: %d\n", elem->maxOccurs);
4274         else
4275             fprintf(output, "\n");
4276     }
4277 #endif
4278     /*
4279     * Misc other properties.
4280     */
4281     if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
4282 	(elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
4283 	(elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
4284 	(elem->flags & XML_SCHEMAS_ELEM_DEFAULT)) {
4285 	fprintf(output, "  props: ");
4286 	if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
4287 	    fprintf(output, "[fixed] ");
4288 	if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
4289 	    fprintf(output, "[default] ");
4290 	if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
4291 	    fprintf(output, "[abstract] ");
4292 	if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
4293 	    fprintf(output, "[nillable] ");
4294 	fprintf(output, "\n");
4295     }
4296     /*
4297     * Default/fixed value.
4298     */
4299     if (elem->value != NULL)
4300 	fprintf(output, "  value: '%s'\n", elem->value);
4301     /*
4302     * Type.
4303     */
4304     if (elem->namedType != NULL) {
4305 	fprintf(output, "  type: '%s' ", elem->namedType);
4306 	if (elem->namedTypeNs != NULL)
4307 	    fprintf(output, "ns '%s'\n", elem->namedTypeNs);
4308 	else
4309 	    fprintf(output, "\n");
4310     } else if (elem->subtypes != NULL) {
4311 	/*
4312 	* Dump local types.
4313 	*/
4314 	xmlSchemaTypeDump(elem->subtypes, output);
4315     }
4316     /*
4317     * Substitution group.
4318     */
4319     if (elem->substGroup != NULL) {
4320 	fprintf(output, "  substitutionGroup: '%s' ", elem->substGroup);
4321 	if (elem->substGroupNs != NULL)
4322 	    fprintf(output, "ns '%s'\n", elem->substGroupNs);
4323 	else
4324 	    fprintf(output, "\n");
4325     }
4326 }
4327 
4328 /**
4329  * xmlSchemaAnnotDump:
4330  * @output:  the file output
4331  * @annot:  a annotation
4332  *
4333  * Dump the annotation
4334  */
4335 static void
xmlSchemaAnnotDump(FILE * output,xmlSchemaAnnotPtr annot)4336 xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
4337 {
4338     xmlChar *content;
4339 
4340     if (annot == NULL)
4341         return;
4342 
4343     content = xmlNodeGetContent(annot->content);
4344     if (content != NULL) {
4345         fprintf(output, "  Annot: %s\n", content);
4346         xmlFree(content);
4347     } else
4348         fprintf(output, "  Annot: empty\n");
4349 }
4350 
4351 /**
4352  * xmlSchemaContentModelDump:
4353  * @particle: the schema particle
4354  * @output: the file output
4355  * @depth: the depth used for indentation
4356  *
4357  * Dump a SchemaType structure
4358  */
4359 static void
xmlSchemaContentModelDump(xmlSchemaParticlePtr particle,FILE * output,int depth)4360 xmlSchemaContentModelDump(xmlSchemaParticlePtr particle, FILE * output, int depth)
4361 {
4362     xmlChar *str = NULL;
4363     xmlSchemaTreeItemPtr term;
4364     char shift[100];
4365     int i;
4366 
4367     if (particle == NULL)
4368 	return;
4369     for (i = 0;((i < depth) && (i < 25));i++)
4370         shift[2 * i] = shift[2 * i + 1] = ' ';
4371     shift[2 * i] = shift[2 * i + 1] = 0;
4372     fprintf(output, "%s", shift);
4373     if (particle->children == NULL) {
4374 	fprintf(output, "MISSING particle term\n");
4375 	return;
4376     }
4377     term = particle->children;
4378     if (term == NULL) {
4379 	fprintf(output, "(NULL)");
4380     } else {
4381 	switch (term->type) {
4382 	    case XML_SCHEMA_TYPE_ELEMENT:
4383 		fprintf(output, "ELEM '%s'", xmlSchemaFormatQName(&str,
4384 		    ((xmlSchemaElementPtr)term)->targetNamespace,
4385 		    ((xmlSchemaElementPtr)term)->name));
4386 		FREE_AND_NULL(str);
4387 		break;
4388 	    case XML_SCHEMA_TYPE_SEQUENCE:
4389 		fprintf(output, "SEQUENCE");
4390 		break;
4391 	    case XML_SCHEMA_TYPE_CHOICE:
4392 		fprintf(output, "CHOICE");
4393 		break;
4394 	    case XML_SCHEMA_TYPE_ALL:
4395 		fprintf(output, "ALL");
4396 		break;
4397 	    case XML_SCHEMA_TYPE_ANY:
4398 		fprintf(output, "ANY");
4399 		break;
4400 	    default:
4401 		fprintf(output, "UNKNOWN\n");
4402 		return;
4403 	}
4404     }
4405     if (particle->minOccurs != 1)
4406 	fprintf(output, " min: %d", particle->minOccurs);
4407     if (particle->maxOccurs >= UNBOUNDED)
4408 	fprintf(output, " max: unbounded");
4409     else if (particle->maxOccurs != 1)
4410 	fprintf(output, " max: %d", particle->maxOccurs);
4411     fprintf(output, "\n");
4412     if (term &&
4413 	((term->type == XML_SCHEMA_TYPE_SEQUENCE) ||
4414 	 (term->type == XML_SCHEMA_TYPE_CHOICE) ||
4415 	 (term->type == XML_SCHEMA_TYPE_ALL)) &&
4416 	 (term->children != NULL)) {
4417 	xmlSchemaContentModelDump((xmlSchemaParticlePtr) term->children,
4418 	    output, depth +1);
4419     }
4420     if (particle->next != NULL)
4421 	xmlSchemaContentModelDump((xmlSchemaParticlePtr) particle->next,
4422 		output, depth);
4423 }
4424 
4425 /**
4426  * xmlSchemaAttrUsesDump:
4427  * @uses:  attribute uses list
4428  * @output:  the file output
4429  *
4430  * Dumps a list of attribute use components.
4431  */
4432 static void
xmlSchemaAttrUsesDump(xmlSchemaItemListPtr uses,FILE * output)4433 xmlSchemaAttrUsesDump(xmlSchemaItemListPtr uses, FILE * output)
4434 {
4435     xmlSchemaAttributeUsePtr use;
4436     xmlSchemaAttributeUseProhibPtr prohib;
4437     xmlSchemaQNameRefPtr ref;
4438     const xmlChar *name, *tns;
4439     xmlChar *str = NULL;
4440     int i;
4441 
4442     if ((uses == NULL) || (uses->nbItems == 0))
4443         return;
4444 
4445     fprintf(output, "  attributes:\n");
4446     for (i = 0; i < uses->nbItems; i++) {
4447 	use = uses->items[i];
4448 	if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
4449 	    fprintf(output, "  [prohibition] ");
4450 	    prohib = (xmlSchemaAttributeUseProhibPtr) use;
4451 	    name = prohib->name;
4452 	    tns = prohib->targetNamespace;
4453 	} else if (use->type == XML_SCHEMA_EXTRA_QNAMEREF) {
4454 	    fprintf(output, "  [reference] ");
4455 	    ref = (xmlSchemaQNameRefPtr) use;
4456 	    name = ref->name;
4457 	    tns = ref->targetNamespace;
4458 	} else {
4459 	    fprintf(output, "  [use] ");
4460 	    name = WXS_ATTRUSE_DECL_NAME(use);
4461 	    tns = WXS_ATTRUSE_DECL_TNS(use);
4462 	}
4463 	fprintf(output, "'%s'\n",
4464 	    (const char *) xmlSchemaFormatQName(&str, tns, name));
4465 	FREE_AND_NULL(str);
4466     }
4467 }
4468 
4469 /**
4470  * xmlSchemaTypeDump:
4471  * @output:  the file output
4472  * @type:  a type structure
4473  *
4474  * Dump a SchemaType structure
4475  */
4476 static void
xmlSchemaTypeDump(xmlSchemaTypePtr type,FILE * output)4477 xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
4478 {
4479     if (type == NULL) {
4480         fprintf(output, "Type: NULL\n");
4481         return;
4482     }
4483     fprintf(output, "Type: ");
4484     if (type->name != NULL)
4485         fprintf(output, "'%s' ", type->name);
4486     else
4487         fprintf(output, "(no name) ");
4488     if (type->targetNamespace != NULL)
4489 	fprintf(output, "ns '%s' ", type->targetNamespace);
4490     switch (type->type) {
4491         case XML_SCHEMA_TYPE_BASIC:
4492             fprintf(output, "[basic] ");
4493             break;
4494         case XML_SCHEMA_TYPE_SIMPLE:
4495             fprintf(output, "[simple] ");
4496             break;
4497         case XML_SCHEMA_TYPE_COMPLEX:
4498             fprintf(output, "[complex] ");
4499             break;
4500         case XML_SCHEMA_TYPE_SEQUENCE:
4501             fprintf(output, "[sequence] ");
4502             break;
4503         case XML_SCHEMA_TYPE_CHOICE:
4504             fprintf(output, "[choice] ");
4505             break;
4506         case XML_SCHEMA_TYPE_ALL:
4507             fprintf(output, "[all] ");
4508             break;
4509         case XML_SCHEMA_TYPE_UR:
4510             fprintf(output, "[ur] ");
4511             break;
4512         case XML_SCHEMA_TYPE_RESTRICTION:
4513             fprintf(output, "[restriction] ");
4514             break;
4515         case XML_SCHEMA_TYPE_EXTENSION:
4516             fprintf(output, "[extension] ");
4517             break;
4518         default:
4519             fprintf(output, "[unknown type %d] ", type->type);
4520             break;
4521     }
4522     fprintf(output, "content: ");
4523     switch (type->contentType) {
4524         case XML_SCHEMA_CONTENT_UNKNOWN:
4525             fprintf(output, "[unknown] ");
4526             break;
4527         case XML_SCHEMA_CONTENT_EMPTY:
4528             fprintf(output, "[empty] ");
4529             break;
4530         case XML_SCHEMA_CONTENT_ELEMENTS:
4531             fprintf(output, "[element] ");
4532             break;
4533         case XML_SCHEMA_CONTENT_MIXED:
4534             fprintf(output, "[mixed] ");
4535             break;
4536         case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
4537 	/* not used. */
4538             break;
4539         case XML_SCHEMA_CONTENT_BASIC:
4540             fprintf(output, "[basic] ");
4541             break;
4542         case XML_SCHEMA_CONTENT_SIMPLE:
4543             fprintf(output, "[simple] ");
4544             break;
4545         case XML_SCHEMA_CONTENT_ANY:
4546             fprintf(output, "[any] ");
4547             break;
4548     }
4549     fprintf(output, "\n");
4550     if (type->base != NULL) {
4551         fprintf(output, "  base type: '%s'", type->base);
4552 	if (type->baseNs != NULL)
4553 	    fprintf(output, " ns '%s'\n", type->baseNs);
4554 	else
4555 	    fprintf(output, "\n");
4556     }
4557     if (type->attrUses != NULL)
4558 	xmlSchemaAttrUsesDump(type->attrUses, output);
4559     if (type->annot != NULL)
4560         xmlSchemaAnnotDump(output, type->annot);
4561 #ifdef DUMP_CONTENT_MODEL
4562     if ((type->type == XML_SCHEMA_TYPE_COMPLEX) &&
4563 	(type->subtypes != NULL)) {
4564 	xmlSchemaContentModelDump((xmlSchemaParticlePtr) type->subtypes,
4565 	    output, 1);
4566     }
4567 #endif
4568 }
4569 
4570 static void
xmlSchemaTypeDumpEntry(void * type,void * output,const xmlChar * name ATTRIBUTE_UNUSED)4571 xmlSchemaTypeDumpEntry(void *type, void *output,
4572                        const xmlChar *name ATTRIBUTE_UNUSED)
4573 {
4574     xmlSchemaTypeDump((xmlSchemaTypePtr) type, (FILE *) output);
4575 }
4576 
4577 /**
4578  * xmlSchemaDump:
4579  * @output:  the file output
4580  * @schema:  a schema structure
4581  *
4582  * Dump a Schema structure.
4583  */
4584 void
xmlSchemaDump(FILE * output,xmlSchemaPtr schema)4585 xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
4586 {
4587     if (output == NULL)
4588         return;
4589     if (schema == NULL) {
4590         fprintf(output, "Schemas: NULL\n");
4591         return;
4592     }
4593     fprintf(output, "Schemas: ");
4594     if (schema->name != NULL)
4595         fprintf(output, "%s, ", schema->name);
4596     else
4597         fprintf(output, "no name, ");
4598     if (schema->targetNamespace != NULL)
4599         fprintf(output, "%s", (const char *) schema->targetNamespace);
4600     else
4601         fprintf(output, "no target namespace");
4602     fprintf(output, "\n");
4603     if (schema->annot != NULL)
4604         xmlSchemaAnnotDump(output, schema->annot);
4605     xmlHashScan(schema->typeDecl, xmlSchemaTypeDumpEntry, output);
4606     xmlHashScanFull(schema->elemDecl, xmlSchemaElementDump, output);
4607 }
4608 
4609 #ifdef DEBUG_IDC_NODE_TABLE
4610 /**
4611  * xmlSchemaDebugDumpIDCTable:
4612  * @vctxt: the WXS validation context
4613  *
4614  * Displays the current IDC table for debug purposes.
4615  */
4616 static void
xmlSchemaDebugDumpIDCTable(FILE * output,const xmlChar * namespaceName,const xmlChar * localName,xmlSchemaPSVIIDCBindingPtr bind)4617 xmlSchemaDebugDumpIDCTable(FILE * output,
4618 			   const xmlChar *namespaceName,
4619 			   const xmlChar *localName,
4620 			   xmlSchemaPSVIIDCBindingPtr bind)
4621 {
4622     xmlChar *str = NULL;
4623     const xmlChar *value;
4624     xmlSchemaPSVIIDCNodePtr tab;
4625     xmlSchemaPSVIIDCKeyPtr key;
4626     int i, j, res;
4627 
4628     fprintf(output, "IDC: TABLES on '%s'\n",
4629 	xmlSchemaFormatQName(&str, namespaceName, localName));
4630     FREE_AND_NULL(str)
4631 
4632     if (bind == NULL)
4633 	return;
4634     do {
4635 	fprintf(output, "IDC:   BINDING '%s' (%d)\n",
4636 	    xmlSchemaGetComponentQName(&str,
4637 		bind->definition), bind->nbNodes);
4638 	FREE_AND_NULL(str)
4639 	for (i = 0; i < bind->nbNodes; i++) {
4640 	    tab = bind->nodeTable[i];
4641 	    fprintf(output, "         ( ");
4642 	    for (j = 0; j < bind->definition->nbFields; j++) {
4643 		key = tab->keys[j];
4644 		if ((key != NULL) && (key->val != NULL)) {
4645 		    res = xmlSchemaGetCanonValue(key->val, &value);
4646 		    if (res >= 0)
4647 			fprintf(output, "'%s' ", value);
4648 		    else
4649 			fprintf(output, "CANON-VALUE-FAILED ");
4650 		    if (res == 0)
4651 			FREE_AND_NULL(value)
4652 		} else if (key != NULL)
4653 		    fprintf(output, "(no val), ");
4654 		else
4655 		    fprintf(output, "(key missing), ");
4656 	    }
4657 	    fprintf(output, ")\n");
4658 	}
4659 	if (bind->dupls && bind->dupls->nbItems) {
4660 	    fprintf(output, "IDC:     dupls (%d):\n", bind->dupls->nbItems);
4661 	    for (i = 0; i < bind->dupls->nbItems; i++) {
4662 		tab = bind->dupls->items[i];
4663 		fprintf(output, "         ( ");
4664 		for (j = 0; j < bind->definition->nbFields; j++) {
4665 		    key = tab->keys[j];
4666 		    if ((key != NULL) && (key->val != NULL)) {
4667 			res = xmlSchemaGetCanonValue(key->val, &value);
4668 			if (res >= 0)
4669 			    fprintf(output, "'%s' ", value);
4670 			else
4671 			    fprintf(output, "CANON-VALUE-FAILED ");
4672 			if (res == 0)
4673 			    FREE_AND_NULL(value)
4674 		    } else if (key != NULL)
4675 		    fprintf(output, "(no val), ");
4676 			else
4677 			    fprintf(output, "(key missing), ");
4678 		}
4679 		fprintf(output, ")\n");
4680 	    }
4681 	}
4682 	bind = bind->next;
4683     } while (bind != NULL);
4684 }
4685 #endif /* DEBUG_IDC */
4686 #endif /* LIBXML_OUTPUT_ENABLED */
4687 
4688 /************************************************************************
4689  *									*
4690  *			Utilities					*
4691  *									*
4692  ************************************************************************/
4693 
4694 /**
4695  * xmlSchemaGetPropNode:
4696  * @node: the element node
4697  * @name: the name of the attribute
4698  *
4699  * Seeks an attribute with a name of @name in
4700  * no namespace.
4701  *
4702  * Returns the attribute or NULL if not present.
4703  */
4704 static xmlAttrPtr
xmlSchemaGetPropNode(xmlNodePtr node,const char * name)4705 xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
4706 {
4707     xmlAttrPtr prop;
4708 
4709     if ((node == NULL) || (name == NULL))
4710 	return(NULL);
4711     prop = node->properties;
4712     while (prop != NULL) {
4713         if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
4714 	    return(prop);
4715 	prop = prop->next;
4716     }
4717     return (NULL);
4718 }
4719 
4720 /**
4721  * xmlSchemaGetPropNodeNs:
4722  * @node: the element node
4723  * @uri: the uri
4724  * @name: the name of the attribute
4725  *
4726  * Seeks an attribute with a local name of @name and
4727  * a namespace URI of @uri.
4728  *
4729  * Returns the attribute or NULL if not present.
4730  */
4731 static xmlAttrPtr
xmlSchemaGetPropNodeNs(xmlNodePtr node,const char * uri,const char * name)4732 xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
4733 {
4734     xmlAttrPtr prop;
4735 
4736     if ((node == NULL) || (name == NULL))
4737 	return(NULL);
4738     prop = node->properties;
4739     while (prop != NULL) {
4740 	if ((prop->ns != NULL) &&
4741 	    xmlStrEqual(prop->name, BAD_CAST name) &&
4742 	    xmlStrEqual(prop->ns->href, BAD_CAST uri))
4743 	    return(prop);
4744 	prop = prop->next;
4745     }
4746     return (NULL);
4747 }
4748 
4749 static const xmlChar *
xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node)4750 xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
4751 {
4752     xmlChar *val;
4753     const xmlChar *ret;
4754 
4755     val = xmlNodeGetContent(node);
4756     if (val == NULL)
4757 	val = xmlStrdup((xmlChar *)"");
4758     ret = xmlDictLookup(ctxt->dict, val, -1);
4759     xmlFree(val);
4760     return(ret);
4761 }
4762 
4763 static const xmlChar *
xmlSchemaGetNodeContentNoDict(xmlNodePtr node)4764 xmlSchemaGetNodeContentNoDict(xmlNodePtr node)
4765 {
4766     return((const xmlChar*) xmlNodeGetContent(node));
4767 }
4768 
4769 /**
4770  * xmlSchemaGetProp:
4771  * @ctxt: the parser context
4772  * @node: the node
4773  * @name: the property name
4774  *
4775  * Read a attribute value and internalize the string
4776  *
4777  * Returns the string or NULL if not present.
4778  */
4779 static const xmlChar *
xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,const char * name)4780 xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
4781                  const char *name)
4782 {
4783     xmlChar *val;
4784     const xmlChar *ret;
4785 
4786     val = xmlGetNoNsProp(node, BAD_CAST name);
4787     if (val == NULL)
4788         return(NULL);
4789     ret = xmlDictLookup(ctxt->dict, val, -1);
4790     xmlFree(val);
4791     return(ret);
4792 }
4793 
4794 /************************************************************************
4795  *									*
4796  *			Parsing functions				*
4797  *									*
4798  ************************************************************************/
4799 
4800 #define WXS_FIND_GLOBAL_ITEM(slot)			\
4801     if (xmlStrEqual(nsName, schema->targetNamespace)) { \
4802 	ret = xmlHashLookup(schema->slot, name); \
4803 	if (ret != NULL) goto exit; \
4804     } \
4805     if (xmlHashSize(schema->schemasImports) > 1) { \
4806 	xmlSchemaImportPtr import; \
4807 	if (nsName == NULL) \
4808 	    import = xmlHashLookup(schema->schemasImports, \
4809 		XML_SCHEMAS_NO_NAMESPACE); \
4810 	else \
4811 	    import = xmlHashLookup(schema->schemasImports, nsName); \
4812 	if (import == NULL) \
4813 	    goto exit; \
4814 	ret = xmlHashLookup(import->schema->slot, name); \
4815     }
4816 
4817 /**
4818  * xmlSchemaGetElem:
4819  * @schema:  the schema context
4820  * @name:  the element name
4821  * @ns:  the element namespace
4822  *
4823  * Lookup a global element declaration in the schema.
4824  *
4825  * Returns the element declaration or NULL if not found.
4826  */
4827 static xmlSchemaElementPtr
xmlSchemaGetElem(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName)4828 xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
4829                  const xmlChar * nsName)
4830 {
4831     xmlSchemaElementPtr ret = NULL;
4832 
4833     if ((name == NULL) || (schema == NULL))
4834         return(NULL);
4835     if (schema != NULL) {
4836 	WXS_FIND_GLOBAL_ITEM(elemDecl)
4837     }
4838 exit:
4839 #ifdef DEBUG
4840     if (ret == NULL) {
4841         if (nsName == NULL)
4842             fprintf(stderr, "Unable to lookup element decl. %s", name);
4843         else
4844             fprintf(stderr, "Unable to lookup element decl. %s:%s", name,
4845                     nsName);
4846     }
4847 #endif
4848     return (ret);
4849 }
4850 
4851 /**
4852  * xmlSchemaGetType:
4853  * @schema:  the main schema
4854  * @name:  the type's name
4855  * nsName:  the type's namespace
4856  *
4857  * Lookup a type in the schemas or the predefined types
4858  *
4859  * Returns the group definition or NULL if not found.
4860  */
4861 static xmlSchemaTypePtr
xmlSchemaGetType(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName)4862 xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
4863                  const xmlChar * nsName)
4864 {
4865     xmlSchemaTypePtr ret = NULL;
4866 
4867     if (name == NULL)
4868         return (NULL);
4869     /* First try the built-in types. */
4870     if ((nsName != NULL) && xmlStrEqual(nsName, xmlSchemaNs)) {
4871 	ret = xmlSchemaGetPredefinedType(name, nsName);
4872 	if (ret != NULL)
4873 	    goto exit;
4874 	/*
4875 	* Note that we try the parsed schemas as well here
4876 	* since one might have parsed the S4S, which contain more
4877 	* than the built-in types.
4878 	* TODO: Can we optimize this?
4879 	*/
4880     }
4881     if (schema != NULL) {
4882 	WXS_FIND_GLOBAL_ITEM(typeDecl)
4883     }
4884 exit:
4885 
4886 #ifdef DEBUG
4887     if (ret == NULL) {
4888         if (nsName == NULL)
4889             fprintf(stderr, "Unable to lookup type %s", name);
4890         else
4891             fprintf(stderr, "Unable to lookup type %s:%s", name,
4892                     nsName);
4893     }
4894 #endif
4895     return (ret);
4896 }
4897 
4898 /**
4899  * xmlSchemaGetAttributeDecl:
4900  * @schema:  the context of the schema
4901  * @name:  the name of the attribute
4902  * @ns:  the target namespace of the attribute
4903  *
4904  * Lookup a an attribute in the schema or imported schemas
4905  *
4906  * Returns the attribute declaration or NULL if not found.
4907  */
4908 static xmlSchemaAttributePtr
xmlSchemaGetAttributeDecl(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName)4909 xmlSchemaGetAttributeDecl(xmlSchemaPtr schema, const xmlChar * name,
4910                  const xmlChar * nsName)
4911 {
4912     xmlSchemaAttributePtr ret = NULL;
4913 
4914     if ((name == NULL) || (schema == NULL))
4915         return (NULL);
4916     if (schema != NULL) {
4917 	WXS_FIND_GLOBAL_ITEM(attrDecl)
4918     }
4919 exit:
4920 #ifdef DEBUG
4921     if (ret == NULL) {
4922         if (nsName == NULL)
4923             fprintf(stderr, "Unable to lookup attribute %s", name);
4924         else
4925             fprintf(stderr, "Unable to lookup attribute %s:%s", name,
4926                     nsName);
4927     }
4928 #endif
4929     return (ret);
4930 }
4931 
4932 /**
4933  * xmlSchemaGetAttributeGroup:
4934  * @schema:  the context of the schema
4935  * @name:  the name of the attribute group
4936  * @ns:  the target namespace of the attribute group
4937  *
4938  * Lookup a an attribute group in the schema or imported schemas
4939  *
4940  * Returns the attribute group definition or NULL if not found.
4941  */
4942 static xmlSchemaAttributeGroupPtr
xmlSchemaGetAttributeGroup(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName)4943 xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
4944                  const xmlChar * nsName)
4945 {
4946     xmlSchemaAttributeGroupPtr ret = NULL;
4947 
4948     if ((name == NULL) || (schema == NULL))
4949         return (NULL);
4950     if (schema != NULL) {
4951 	WXS_FIND_GLOBAL_ITEM(attrgrpDecl)
4952     }
4953 exit:
4954     /* TODO:
4955     if ((ret != NULL) && (ret->redef != NULL)) {
4956 	* Return the last redefinition. *
4957 	ret = ret->redef;
4958     }
4959     */
4960 #ifdef DEBUG
4961     if (ret == NULL) {
4962         if (nsName == NULL)
4963             fprintf(stderr, "Unable to lookup attribute group %s", name);
4964         else
4965             fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
4966                     nsName);
4967     }
4968 #endif
4969     return (ret);
4970 }
4971 
4972 /**
4973  * xmlSchemaGetGroup:
4974  * @schema:  the context of the schema
4975  * @name:  the name of the group
4976  * @ns:  the target namespace of the group
4977  *
4978  * Lookup a group in the schema or imported schemas
4979  *
4980  * Returns the group definition or NULL if not found.
4981  */
4982 static xmlSchemaModelGroupDefPtr
xmlSchemaGetGroup(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName)4983 xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
4984                  const xmlChar * nsName)
4985 {
4986     xmlSchemaModelGroupDefPtr ret = NULL;
4987 
4988     if ((name == NULL) || (schema == NULL))
4989         return (NULL);
4990     if (schema != NULL) {
4991 	WXS_FIND_GLOBAL_ITEM(groupDecl)
4992     }
4993 exit:
4994 
4995 #ifdef DEBUG
4996     if (ret == NULL) {
4997         if (nsName == NULL)
4998             fprintf(stderr, "Unable to lookup group %s", name);
4999         else
5000             fprintf(stderr, "Unable to lookup group %s:%s", name,
5001                     nsName);
5002     }
5003 #endif
5004     return (ret);
5005 }
5006 
5007 static xmlSchemaNotationPtr
xmlSchemaGetNotation(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName)5008 xmlSchemaGetNotation(xmlSchemaPtr schema,
5009 		     const xmlChar *name,
5010 		     const xmlChar *nsName)
5011 {
5012     xmlSchemaNotationPtr ret = NULL;
5013 
5014     if ((name == NULL) || (schema == NULL))
5015         return (NULL);
5016     if (schema != NULL) {
5017 	WXS_FIND_GLOBAL_ITEM(notaDecl)
5018     }
5019 exit:
5020     return (ret);
5021 }
5022 
5023 static xmlSchemaIDCPtr
xmlSchemaGetIDC(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName)5024 xmlSchemaGetIDC(xmlSchemaPtr schema,
5025 		const xmlChar *name,
5026 		const xmlChar *nsName)
5027 {
5028     xmlSchemaIDCPtr ret = NULL;
5029 
5030     if ((name == NULL) || (schema == NULL))
5031         return (NULL);
5032     if (schema != NULL) {
5033 	WXS_FIND_GLOBAL_ITEM(idcDef)
5034     }
5035 exit:
5036     return (ret);
5037 }
5038 
5039 /**
5040  * xmlSchemaGetNamedComponent:
5041  * @schema:  the schema
5042  * @name:  the name of the group
5043  * @ns:  the target namespace of the group
5044  *
5045  * Lookup a group in the schema or imported schemas
5046  *
5047  * Returns the group definition or NULL if not found.
5048  */
5049 static xmlSchemaBasicItemPtr
xmlSchemaGetNamedComponent(xmlSchemaPtr schema,xmlSchemaTypeType itemType,const xmlChar * name,const xmlChar * targetNs)5050 xmlSchemaGetNamedComponent(xmlSchemaPtr schema,
5051 			   xmlSchemaTypeType itemType,
5052 			   const xmlChar *name,
5053 			   const xmlChar *targetNs)
5054 {
5055     switch (itemType) {
5056 	case XML_SCHEMA_TYPE_GROUP:
5057 	    return ((xmlSchemaBasicItemPtr) xmlSchemaGetGroup(schema,
5058 		name, targetNs));
5059 	case XML_SCHEMA_TYPE_ELEMENT:
5060 	    return ((xmlSchemaBasicItemPtr) xmlSchemaGetElem(schema,
5061 		name, targetNs));
5062 	default:
5063 	    TODO
5064 	    return (NULL);
5065     }
5066 }
5067 
5068 /************************************************************************
5069  *									*
5070  *			Parsing functions				*
5071  *									*
5072  ************************************************************************/
5073 
5074 #define IS_BLANK_NODE(n)						\
5075     (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content, -1)))
5076 
5077 /**
5078  * xmlSchemaIsBlank:
5079  * @str:  a string
5080  * @len: the length of the string or -1
5081  *
5082  * Check if a string is ignorable
5083  *
5084  * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
5085  */
5086 static int
xmlSchemaIsBlank(xmlChar * str,int len)5087 xmlSchemaIsBlank(xmlChar * str, int len)
5088 {
5089     if (str == NULL)
5090         return (1);
5091     if (len < 0) {
5092 	while (*str != 0) {
5093 	    if (!(IS_BLANK_CH(*str)))
5094 		return (0);
5095 	    str++;
5096 	}
5097     } else while ((*str != 0) && (len != 0)) {
5098 	if (!(IS_BLANK_CH(*str)))
5099 	    return (0);
5100 	str++;
5101 	len--;
5102     }
5103 
5104     return (1);
5105 }
5106 
5107 #define WXS_COMP_NAME(c, t) ((t) (c))->name
5108 #define WXS_COMP_TNS(c, t) ((t) (c))->targetNamespace
5109 /*
5110 * xmlSchemaFindRedefCompInGraph:
5111 * ATTENTION TODO: This uses pointer comp. for strings.
5112 */
5113 static xmlSchemaBasicItemPtr
xmlSchemaFindRedefCompInGraph(xmlSchemaBucketPtr bucket,xmlSchemaTypeType type,const xmlChar * name,const xmlChar * nsName)5114 xmlSchemaFindRedefCompInGraph(xmlSchemaBucketPtr bucket,
5115 			      xmlSchemaTypeType type,
5116 			      const xmlChar *name,
5117 			      const xmlChar *nsName)
5118 {
5119     xmlSchemaBasicItemPtr ret;
5120     int i;
5121 
5122     if ((bucket == NULL) || (name == NULL))
5123 	return(NULL);
5124     if ((bucket->globals == NULL) ||
5125 	(bucket->globals->nbItems == 0))
5126 	goto subschemas;
5127     /*
5128     * Search in global components.
5129     */
5130     for (i = 0; i < bucket->globals->nbItems; i++) {
5131 	ret = bucket->globals->items[i];
5132 	if (ret->type == type) {
5133 	    switch (type) {
5134 		case XML_SCHEMA_TYPE_COMPLEX:
5135 		case XML_SCHEMA_TYPE_SIMPLE:
5136 		    if ((WXS_COMP_NAME(ret, xmlSchemaTypePtr) == name) &&
5137 			(WXS_COMP_TNS(ret, xmlSchemaTypePtr) ==
5138 			nsName))
5139 		    {
5140 			return(ret);
5141 		    }
5142 		    break;
5143 		case XML_SCHEMA_TYPE_GROUP:
5144 		    if ((WXS_COMP_NAME(ret,
5145 			    xmlSchemaModelGroupDefPtr) == name) &&
5146 			(WXS_COMP_TNS(ret,
5147 			    xmlSchemaModelGroupDefPtr) == nsName))
5148 		    {
5149 			return(ret);
5150 		    }
5151 		    break;
5152 		case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
5153 		    if ((WXS_COMP_NAME(ret,
5154 			    xmlSchemaAttributeGroupPtr) == name) &&
5155 			(WXS_COMP_TNS(ret,
5156 			    xmlSchemaAttributeGroupPtr) == nsName))
5157 		    {
5158 			return(ret);
5159 		    }
5160 		    break;
5161 		default:
5162 		    /* Should not be hit. */
5163 		    return(NULL);
5164 	    }
5165 	}
5166     }
5167 subschemas:
5168     /*
5169     * Process imported/included schemas.
5170     */
5171     if (bucket->relations != NULL) {
5172 	xmlSchemaSchemaRelationPtr rel = bucket->relations;
5173 
5174 	/*
5175 	* TODO: Marking the bucket will not avoid multiple searches
5176 	* in the same schema, but avoids at least circularity.
5177 	*/
5178 	bucket->flags |= XML_SCHEMA_BUCKET_MARKED;
5179 	do {
5180 	    if ((rel->bucket != NULL) &&
5181 		((rel->bucket->flags & XML_SCHEMA_BUCKET_MARKED) == 0)) {
5182 		ret = xmlSchemaFindRedefCompInGraph(rel->bucket,
5183 		    type, name, nsName);
5184 		if (ret != NULL)
5185 		    return(ret);
5186 	    }
5187 	    rel = rel->next;
5188 	} while (rel != NULL);
5189 	 bucket->flags ^= XML_SCHEMA_BUCKET_MARKED;
5190     }
5191     return(NULL);
5192 }
5193 
5194 /**
5195  * xmlSchemaAddNotation:
5196  * @ctxt:  a schema parser context
5197  * @schema:  the schema being built
5198  * @name:  the item name
5199  *
5200  * Add an XML schema annotation declaration
5201  * *WARNING* this interface is highly subject to change
5202  *
5203  * Returns the new structure or NULL in case of error
5204  */
5205 static xmlSchemaNotationPtr
xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName,xmlNodePtr node ATTRIBUTE_UNUSED)5206 xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5207                      const xmlChar *name, const xmlChar *nsName,
5208 		     xmlNodePtr node ATTRIBUTE_UNUSED)
5209 {
5210     xmlSchemaNotationPtr ret = NULL;
5211 
5212     if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5213         return (NULL);
5214 
5215     ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
5216     if (ret == NULL) {
5217         xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
5218         return (NULL);
5219     }
5220     memset(ret, 0, sizeof(xmlSchemaNotation));
5221     ret->type = XML_SCHEMA_TYPE_NOTATION;
5222     ret->name = name;
5223     ret->targetNamespace = nsName;
5224     /* TODO: do we need the node to be set?
5225     * ret->node = node;*/
5226     WXS_ADD_GLOBAL(ctxt, ret);
5227     return (ret);
5228 }
5229 
5230 /**
5231  * xmlSchemaAddAttribute:
5232  * @ctxt:  a schema parser context
5233  * @schema:  the schema being built
5234  * @name:  the item name
5235  * @namespace:  the namespace
5236  *
5237  * Add an XML schema Attribute declaration
5238  * *WARNING* this interface is highly subject to change
5239  *
5240  * Returns the new structure or NULL in case of error
5241  */
5242 static xmlSchemaAttributePtr
xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName,xmlNodePtr node,int topLevel)5243 xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5244                       const xmlChar * name, const xmlChar * nsName,
5245 		      xmlNodePtr node, int topLevel)
5246 {
5247     xmlSchemaAttributePtr ret = NULL;
5248 
5249     if ((ctxt == NULL) || (schema == NULL))
5250         return (NULL);
5251 
5252     ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
5253     if (ret == NULL) {
5254         xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
5255         return (NULL);
5256     }
5257     memset(ret, 0, sizeof(xmlSchemaAttribute));
5258     ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
5259     ret->node = node;
5260     ret->name = name;
5261     ret->targetNamespace = nsName;
5262 
5263     if (topLevel)
5264 	WXS_ADD_GLOBAL(ctxt, ret);
5265     else
5266 	WXS_ADD_LOCAL(ctxt, ret);
5267     WXS_ADD_PENDING(ctxt, ret);
5268     return (ret);
5269 }
5270 
5271 /**
5272  * xmlSchemaAddAttributeUse:
5273  * @ctxt:  a schema parser context
5274  * @schema:  the schema being built
5275  * @name:  the item name
5276  * @namespace:  the namespace
5277  *
5278  * Add an XML schema Attribute declaration
5279  * *WARNING* this interface is highly subject to change
5280  *
5281  * Returns the new structure or NULL in case of error
5282  */
5283 static xmlSchemaAttributeUsePtr
xmlSchemaAddAttributeUse(xmlSchemaParserCtxtPtr pctxt,xmlNodePtr node)5284 xmlSchemaAddAttributeUse(xmlSchemaParserCtxtPtr pctxt,
5285 			 xmlNodePtr node)
5286 {
5287     xmlSchemaAttributeUsePtr ret = NULL;
5288 
5289     if (pctxt == NULL)
5290         return (NULL);
5291 
5292     ret = (xmlSchemaAttributeUsePtr) xmlMalloc(sizeof(xmlSchemaAttributeUse));
5293     if (ret == NULL) {
5294         xmlSchemaPErrMemory(pctxt, "allocating attribute", NULL);
5295         return (NULL);
5296     }
5297     memset(ret, 0, sizeof(xmlSchemaAttributeUse));
5298     ret->type = XML_SCHEMA_TYPE_ATTRIBUTE_USE;
5299     ret->node = node;
5300 
5301     WXS_ADD_LOCAL(pctxt, ret);
5302     return (ret);
5303 }
5304 
5305 /*
5306 * xmlSchemaAddRedef:
5307 *
5308 * Adds a redefinition information. This is used at a later stage to:
5309 * resolve references to the redefined components and to check constraints.
5310 */
5311 static xmlSchemaRedefPtr
xmlSchemaAddRedef(xmlSchemaParserCtxtPtr pctxt,xmlSchemaBucketPtr targetBucket,void * item,const xmlChar * refName,const xmlChar * refTargetNs)5312 xmlSchemaAddRedef(xmlSchemaParserCtxtPtr pctxt,
5313 		  xmlSchemaBucketPtr targetBucket,
5314 		  void *item,
5315 		  const xmlChar *refName,
5316 		  const xmlChar *refTargetNs)
5317 {
5318     xmlSchemaRedefPtr ret;
5319 
5320     ret = (xmlSchemaRedefPtr)
5321 	xmlMalloc(sizeof(xmlSchemaRedef));
5322     if (ret == NULL) {
5323 	xmlSchemaPErrMemory(pctxt,
5324 	    "allocating redefinition info", NULL);
5325 	return (NULL);
5326     }
5327     memset(ret, 0, sizeof(xmlSchemaRedef));
5328     ret->item = item;
5329     ret->targetBucket = targetBucket;
5330     ret->refName = refName;
5331     ret->refTargetNs = refTargetNs;
5332     if (WXS_CONSTRUCTOR(pctxt)->redefs == NULL)
5333 	WXS_CONSTRUCTOR(pctxt)->redefs = ret;
5334     else
5335 	WXS_CONSTRUCTOR(pctxt)->lastRedef->next = ret;
5336     WXS_CONSTRUCTOR(pctxt)->lastRedef = ret;
5337 
5338     return (ret);
5339 }
5340 
5341 /**
5342  * xmlSchemaAddAttributeGroupDefinition:
5343  * @ctxt:  a schema parser context
5344  * @schema:  the schema being built
5345  * @name:  the item name
5346  * @nsName:  the target namespace
5347  * @node: the corresponding node
5348  *
5349  * Add an XML schema Attribute Group definition.
5350  *
5351  * Returns the new structure or NULL in case of error
5352  */
5353 static xmlSchemaAttributeGroupPtr
xmlSchemaAddAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema ATTRIBUTE_UNUSED,const xmlChar * name,const xmlChar * nsName,xmlNodePtr node)5354 xmlSchemaAddAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
5355                            xmlSchemaPtr schema ATTRIBUTE_UNUSED,
5356 			   const xmlChar *name,
5357 			   const xmlChar *nsName,
5358 			   xmlNodePtr node)
5359 {
5360     xmlSchemaAttributeGroupPtr ret = NULL;
5361 
5362     if ((pctxt == NULL) || (name == NULL))
5363         return (NULL);
5364 
5365     ret = (xmlSchemaAttributeGroupPtr)
5366         xmlMalloc(sizeof(xmlSchemaAttributeGroup));
5367     if (ret == NULL) {
5368 	xmlSchemaPErrMemory(pctxt, "allocating attribute group", NULL);
5369 	return (NULL);
5370     }
5371     memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
5372     ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5373     ret->name = name;
5374     ret->targetNamespace = nsName;
5375     ret->node = node;
5376 
5377     /* TODO: Remove the flag. */
5378     ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
5379     if (pctxt->isRedefine) {
5380 	pctxt->redef = xmlSchemaAddRedef(pctxt, pctxt->redefined,
5381 	    ret, name, nsName);
5382 	if (pctxt->redef == NULL) {
5383 	    xmlFree(ret);
5384 	    return(NULL);
5385 	}
5386 	pctxt->redefCounter = 0;
5387     }
5388     WXS_ADD_GLOBAL(pctxt, ret);
5389     WXS_ADD_PENDING(pctxt, ret);
5390     return (ret);
5391 }
5392 
5393 /**
5394  * xmlSchemaAddElement:
5395  * @ctxt:  a schema parser context
5396  * @schema:  the schema being built
5397  * @name:  the type name
5398  * @namespace:  the type namespace
5399  *
5400  * Add an XML schema Element declaration
5401  * *WARNING* this interface is highly subject to change
5402  *
5403  * Returns the new structure or NULL in case of error
5404  */
5405 static xmlSchemaElementPtr
xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt,const xmlChar * name,const xmlChar * nsName,xmlNodePtr node,int topLevel)5406 xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt,
5407                     const xmlChar * name, const xmlChar * nsName,
5408 		    xmlNodePtr node, int topLevel)
5409 {
5410     xmlSchemaElementPtr ret = NULL;
5411 
5412     if ((ctxt == NULL) || (name == NULL))
5413         return (NULL);
5414 
5415     ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
5416     if (ret == NULL) {
5417         xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
5418         return (NULL);
5419     }
5420     memset(ret, 0, sizeof(xmlSchemaElement));
5421     ret->type = XML_SCHEMA_TYPE_ELEMENT;
5422     ret->name = name;
5423     ret->targetNamespace = nsName;
5424     ret->node = node;
5425 
5426     if (topLevel)
5427 	WXS_ADD_GLOBAL(ctxt, ret);
5428     else
5429 	WXS_ADD_LOCAL(ctxt, ret);
5430     WXS_ADD_PENDING(ctxt, ret);
5431     return (ret);
5432 }
5433 
5434 /**
5435  * xmlSchemaAddType:
5436  * @ctxt:  a schema parser context
5437  * @schema:  the schema being built
5438  * @name:  the item name
5439  * @namespace:  the namespace
5440  *
5441  * Add an XML schema item
5442  * *WARNING* this interface is highly subject to change
5443  *
5444  * Returns the new structure or NULL in case of error
5445  */
5446 static xmlSchemaTypePtr
xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlSchemaTypeType type,const xmlChar * name,const xmlChar * nsName,xmlNodePtr node,int topLevel)5447 xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5448 		 xmlSchemaTypeType type,
5449                  const xmlChar * name, const xmlChar * nsName,
5450 		 xmlNodePtr node, int topLevel)
5451 {
5452     xmlSchemaTypePtr ret = NULL;
5453 
5454     if ((ctxt == NULL) || (schema == NULL))
5455         return (NULL);
5456 
5457     ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
5458     if (ret == NULL) {
5459         xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
5460         return (NULL);
5461     }
5462     memset(ret, 0, sizeof(xmlSchemaType));
5463     ret->type = type;
5464     ret->name = name;
5465     ret->targetNamespace = nsName;
5466     ret->node = node;
5467     if (topLevel) {
5468 	if (ctxt->isRedefine) {
5469 	    ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5470 		ret, name, nsName);
5471 	    if (ctxt->redef == NULL) {
5472 		xmlFree(ret);
5473 		return(NULL);
5474 	    }
5475 	    ctxt->redefCounter = 0;
5476 	}
5477 	WXS_ADD_GLOBAL(ctxt, ret);
5478     } else
5479 	WXS_ADD_LOCAL(ctxt, ret);
5480     WXS_ADD_PENDING(ctxt, ret);
5481     return (ret);
5482 }
5483 
5484 static xmlSchemaQNameRefPtr
xmlSchemaNewQNameRef(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypeType refType,const xmlChar * refName,const xmlChar * refNs)5485 xmlSchemaNewQNameRef(xmlSchemaParserCtxtPtr pctxt,
5486 		     xmlSchemaTypeType refType,
5487 		     const xmlChar *refName,
5488 		     const xmlChar *refNs)
5489 {
5490     xmlSchemaQNameRefPtr ret;
5491 
5492     ret = (xmlSchemaQNameRefPtr)
5493 	xmlMalloc(sizeof(xmlSchemaQNameRef));
5494     if (ret == NULL) {
5495 	xmlSchemaPErrMemory(pctxt,
5496 	    "allocating QName reference item", NULL);
5497 	return (NULL);
5498     }
5499     ret->node = NULL;
5500     ret->type = XML_SCHEMA_EXTRA_QNAMEREF;
5501     ret->name = refName;
5502     ret->targetNamespace = refNs;
5503     ret->item = NULL;
5504     ret->itemType = refType;
5505     /*
5506     * Store the reference item in the schema.
5507     */
5508     WXS_ADD_LOCAL(pctxt, ret);
5509     return (ret);
5510 }
5511 
5512 static xmlSchemaAttributeUseProhibPtr
xmlSchemaAddAttributeUseProhib(xmlSchemaParserCtxtPtr pctxt)5513 xmlSchemaAddAttributeUseProhib(xmlSchemaParserCtxtPtr pctxt)
5514 {
5515     xmlSchemaAttributeUseProhibPtr ret;
5516 
5517     ret = (xmlSchemaAttributeUseProhibPtr)
5518 	xmlMalloc(sizeof(xmlSchemaAttributeUseProhib));
5519     if (ret == NULL) {
5520 	xmlSchemaPErrMemory(pctxt,
5521 	    "allocating attribute use prohibition", NULL);
5522 	return (NULL);
5523     }
5524     memset(ret, 0, sizeof(xmlSchemaAttributeUseProhib));
5525     ret->type = XML_SCHEMA_EXTRA_ATTR_USE_PROHIB;
5526     WXS_ADD_LOCAL(pctxt, ret);
5527     return (ret);
5528 }
5529 
5530 
5531 /**
5532  * xmlSchemaAddModelGroup:
5533  * @ctxt:  a schema parser context
5534  * @schema:  the schema being built
5535  * @type: the "compositor" type of the model group
5536  * @node: the node in the schema doc
5537  *
5538  * Adds a schema model group
5539  * *WARNING* this interface is highly subject to change
5540  *
5541  * Returns the new structure or NULL in case of error
5542  */
5543 static xmlSchemaModelGroupPtr
xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlSchemaTypeType type,xmlNodePtr node)5544 xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt,
5545 		       xmlSchemaPtr schema,
5546 		       xmlSchemaTypeType type,
5547 		       xmlNodePtr node)
5548 {
5549     xmlSchemaModelGroupPtr ret = NULL;
5550 
5551     if ((ctxt == NULL) || (schema == NULL))
5552         return (NULL);
5553 
5554     ret = (xmlSchemaModelGroupPtr)
5555 	xmlMalloc(sizeof(xmlSchemaModelGroup));
5556     if (ret == NULL) {
5557 	xmlSchemaPErrMemory(ctxt, "allocating model group component",
5558 	    NULL);
5559 	return (NULL);
5560     }
5561     memset(ret, 0, sizeof(xmlSchemaModelGroup));
5562     ret->type = type;
5563     ret->node = node;
5564     WXS_ADD_LOCAL(ctxt, ret);
5565     if ((type == XML_SCHEMA_TYPE_SEQUENCE) ||
5566 	(type == XML_SCHEMA_TYPE_CHOICE))
5567 	WXS_ADD_PENDING(ctxt, ret);
5568     return (ret);
5569 }
5570 
5571 
5572 /**
5573  * xmlSchemaAddParticle:
5574  * @ctxt:  a schema parser context
5575  * @schema:  the schema being built
5576  * @node: the corresponding node in the schema doc
5577  * @min: the minOccurs
5578  * @max: the maxOccurs
5579  *
5580  * Adds an XML schema particle component.
5581  * *WARNING* this interface is highly subject to change
5582  *
5583  * Returns the new structure or NULL in case of error
5584  */
5585 static xmlSchemaParticlePtr
xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,int min,int max)5586 xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt,
5587 		     xmlNodePtr node, int min, int max)
5588 {
5589     xmlSchemaParticlePtr ret = NULL;
5590     if (ctxt == NULL)
5591         return (NULL);
5592 
5593 #ifdef DEBUG
5594     fprintf(stderr, "Adding particle component\n");
5595 #endif
5596     ret = (xmlSchemaParticlePtr)
5597 	xmlMalloc(sizeof(xmlSchemaParticle));
5598     if (ret == NULL) {
5599 	xmlSchemaPErrMemory(ctxt, "allocating particle component",
5600 	    NULL);
5601 	return (NULL);
5602     }
5603     ret->type = XML_SCHEMA_TYPE_PARTICLE;
5604     ret->annot = NULL;
5605     ret->node = node;
5606     ret->minOccurs = min;
5607     ret->maxOccurs = max;
5608     ret->next = NULL;
5609     ret->children = NULL;
5610 
5611     WXS_ADD_LOCAL(ctxt, ret);
5612     /*
5613     * Note that addition to pending components will be done locally
5614     * to the specific parsing function, since the most particles
5615     * need not to be fixed up (i.e. the reference to be resolved).
5616     * REMOVED: WXS_ADD_PENDING(ctxt, ret);
5617     */
5618     return (ret);
5619 }
5620 
5621 /**
5622  * xmlSchemaAddModelGroupDefinition:
5623  * @ctxt:  a schema validation context
5624  * @schema:  the schema being built
5625  * @name:  the group name
5626  *
5627  * Add an XML schema Group definition
5628  *
5629  * Returns the new structure or NULL in case of error
5630  */
5631 static xmlSchemaModelGroupDefPtr
xmlSchemaAddModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName,xmlNodePtr node)5632 xmlSchemaAddModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
5633 				 xmlSchemaPtr schema,
5634 				 const xmlChar *name,
5635 				 const xmlChar *nsName,
5636 				 xmlNodePtr node)
5637 {
5638     xmlSchemaModelGroupDefPtr ret = NULL;
5639 
5640     if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5641         return (NULL);
5642 
5643     ret = (xmlSchemaModelGroupDefPtr)
5644 	xmlMalloc(sizeof(xmlSchemaModelGroupDef));
5645     if (ret == NULL) {
5646         xmlSchemaPErrMemory(ctxt, "adding group", NULL);
5647         return (NULL);
5648     }
5649     memset(ret, 0, sizeof(xmlSchemaModelGroupDef));
5650     ret->name = name;
5651     ret->type = XML_SCHEMA_TYPE_GROUP;
5652     ret->node = node;
5653     ret->targetNamespace = nsName;
5654 
5655     if (ctxt->isRedefine) {
5656 	ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5657 	    ret, name, nsName);
5658 	if (ctxt->redef == NULL) {
5659 	    xmlFree(ret);
5660 	    return(NULL);
5661 	}
5662 	ctxt->redefCounter = 0;
5663     }
5664     WXS_ADD_GLOBAL(ctxt, ret);
5665     WXS_ADD_PENDING(ctxt, ret);
5666     return (ret);
5667 }
5668 
5669 /**
5670  * xmlSchemaNewWildcardNs:
5671  * @ctxt:  a schema validation context
5672  *
5673  * Creates a new wildcard namespace constraint.
5674  *
5675  * Returns the new structure or NULL in case of error
5676  */
5677 static xmlSchemaWildcardNsPtr
xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)5678 xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
5679 {
5680     xmlSchemaWildcardNsPtr ret;
5681 
5682     ret = (xmlSchemaWildcardNsPtr)
5683 	xmlMalloc(sizeof(xmlSchemaWildcardNs));
5684     if (ret == NULL) {
5685 	xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
5686 	return (NULL);
5687     }
5688     ret->value = NULL;
5689     ret->next = NULL;
5690     return (ret);
5691 }
5692 
5693 static xmlSchemaIDCPtr
xmlSchemaAddIDC(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName,int category,xmlNodePtr node)5694 xmlSchemaAddIDC(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5695                   const xmlChar *name, const xmlChar *nsName,
5696 		  int category, xmlNodePtr node)
5697 {
5698     xmlSchemaIDCPtr ret = NULL;
5699 
5700     if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5701         return (NULL);
5702 
5703     ret = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
5704     if (ret == NULL) {
5705         xmlSchemaPErrMemory(ctxt,
5706 	    "allocating an identity-constraint definition", NULL);
5707         return (NULL);
5708     }
5709     memset(ret, 0, sizeof(xmlSchemaIDC));
5710     /* The target namespace of the parent element declaration. */
5711     ret->targetNamespace = nsName;
5712     ret->name = name;
5713     ret->type = category;
5714     ret->node = node;
5715 
5716     WXS_ADD_GLOBAL(ctxt, ret);
5717     /*
5718     * Only keyrefs need to be fixup up.
5719     */
5720     if (category == XML_SCHEMA_TYPE_IDC_KEYREF)
5721 	WXS_ADD_PENDING(ctxt, ret);
5722     return (ret);
5723 }
5724 
5725 /**
5726  * xmlSchemaAddWildcard:
5727  * @ctxt:  a schema validation context
5728  * @schema: a schema
5729  *
5730  * Adds a wildcard.
5731  * It corresponds to a xsd:anyAttribute and xsd:any.
5732  *
5733  * Returns the new structure or NULL in case of error
5734  */
5735 static xmlSchemaWildcardPtr
xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlSchemaTypeType type,xmlNodePtr node)5736 xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5737 		     xmlSchemaTypeType type, xmlNodePtr node)
5738 {
5739     xmlSchemaWildcardPtr ret = NULL;
5740 
5741     if ((ctxt == NULL) || (schema == NULL))
5742         return (NULL);
5743 
5744     ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
5745     if (ret == NULL) {
5746         xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
5747         return (NULL);
5748     }
5749     memset(ret, 0, sizeof(xmlSchemaWildcard));
5750     ret->type = type;
5751     ret->node = node;
5752     WXS_ADD_LOCAL(ctxt, ret);
5753     return (ret);
5754 }
5755 
5756 static void
xmlSchemaSubstGroupFree(xmlSchemaSubstGroupPtr group)5757 xmlSchemaSubstGroupFree(xmlSchemaSubstGroupPtr group)
5758 {
5759     if (group == NULL)
5760 	return;
5761     if (group->members != NULL)
5762 	xmlSchemaItemListFree(group->members);
5763     xmlFree(group);
5764 }
5765 
5766 static void
xmlSchemaSubstGroupFreeEntry(void * group,const xmlChar * name ATTRIBUTE_UNUSED)5767 xmlSchemaSubstGroupFreeEntry(void *group, const xmlChar *name ATTRIBUTE_UNUSED)
5768 {
5769     xmlSchemaSubstGroupFree((xmlSchemaSubstGroupPtr) group);
5770 }
5771 
5772 static xmlSchemaSubstGroupPtr
xmlSchemaSubstGroupAdd(xmlSchemaParserCtxtPtr pctxt,xmlSchemaElementPtr head)5773 xmlSchemaSubstGroupAdd(xmlSchemaParserCtxtPtr pctxt,
5774 		       xmlSchemaElementPtr head)
5775 {
5776     xmlSchemaSubstGroupPtr ret;
5777 
5778     /* Init subst group hash. */
5779     if (WXS_SUBST_GROUPS(pctxt) == NULL) {
5780 	WXS_SUBST_GROUPS(pctxt) = xmlHashCreateDict(10, pctxt->dict);
5781 	if (WXS_SUBST_GROUPS(pctxt) == NULL)
5782 	    return(NULL);
5783     }
5784     /* Create a new substitution group. */
5785     ret = (xmlSchemaSubstGroupPtr) xmlMalloc(sizeof(xmlSchemaSubstGroup));
5786     if (ret == NULL) {
5787 	xmlSchemaPErrMemory(NULL,
5788 	    "allocating a substitution group container", NULL);
5789 	return(NULL);
5790     }
5791     memset(ret, 0, sizeof(xmlSchemaSubstGroup));
5792     ret->head = head;
5793     /* Create list of members. */
5794     ret->members = xmlSchemaItemListCreate();
5795     if (ret->members == NULL) {
5796 	xmlSchemaSubstGroupFree(ret);
5797 	return(NULL);
5798     }
5799     /* Add subst group to hash. */
5800     if (xmlHashAddEntry2(WXS_SUBST_GROUPS(pctxt),
5801 	head->name, head->targetNamespace, ret) != 0) {
5802 	PERROR_INT("xmlSchemaSubstGroupAdd",
5803 	    "failed to add a new substitution container");
5804 	xmlSchemaSubstGroupFree(ret);
5805 	return(NULL);
5806     }
5807     return(ret);
5808 }
5809 
5810 static xmlSchemaSubstGroupPtr
xmlSchemaSubstGroupGet(xmlSchemaParserCtxtPtr pctxt,xmlSchemaElementPtr head)5811 xmlSchemaSubstGroupGet(xmlSchemaParserCtxtPtr pctxt,
5812 		       xmlSchemaElementPtr head)
5813 {
5814     if (WXS_SUBST_GROUPS(pctxt) == NULL)
5815 	return(NULL);
5816     return(xmlHashLookup2(WXS_SUBST_GROUPS(pctxt),
5817 	head->name, head->targetNamespace));
5818 
5819 }
5820 
5821 /**
5822  * xmlSchemaAddElementSubstitutionMember:
5823  * @pctxt:  a schema parser context
5824  * @head:  the head of the substitution group
5825  * @member: the new member of the substitution group
5826  *
5827  * Allocate a new annotation structure.
5828  *
5829  * Returns the newly allocated structure or NULL in case or error
5830  */
5831 static int
xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt,xmlSchemaElementPtr head,xmlSchemaElementPtr member)5832 xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt,
5833 				      xmlSchemaElementPtr head,
5834 				      xmlSchemaElementPtr member)
5835 {
5836     xmlSchemaSubstGroupPtr substGroup = NULL;
5837 
5838     if ((pctxt == NULL) || (head == NULL) || (member == NULL))
5839 	return (-1);
5840 
5841     substGroup = xmlSchemaSubstGroupGet(pctxt, head);
5842     if (substGroup == NULL)
5843 	substGroup = xmlSchemaSubstGroupAdd(pctxt, head);
5844     if (substGroup == NULL)
5845 	return(-1);
5846     if (xmlSchemaItemListAdd(substGroup->members, member) == -1)
5847 	return(-1);
5848     return(0);
5849 }
5850 
5851 /************************************************************************
5852  *									*
5853  *		Utilities for parsing					*
5854  *									*
5855  ************************************************************************/
5856 
5857 /**
5858  * xmlSchemaPValAttrNodeQNameValue:
5859  * @ctxt:  a schema parser context
5860  * @schema: the schema context
5861  * @ownerItem: the parent as a schema object
5862  * @value:  the QName value
5863  * @uri:  the resulting namespace URI if found
5864  * @local: the resulting local part if found, the attribute value otherwise
5865  *
5866  * Extracts the local name and the URI of a QName value and validates it.
5867  * This one is intended to be used on attribute values that
5868  * should resolve to schema components.
5869  *
5870  * Returns 0, in case the QName is valid, a positive error code
5871  * if not valid and -1 if an internal error occurs.
5872  */
5873 static int
xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlSchemaBasicItemPtr ownerItem,xmlAttrPtr attr,const xmlChar * value,const xmlChar ** uri,const xmlChar ** local)5874 xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
5875 				       xmlSchemaPtr schema,
5876 				       xmlSchemaBasicItemPtr ownerItem,
5877 				       xmlAttrPtr attr,
5878 				       const xmlChar *value,
5879 				       const xmlChar **uri,
5880 				       const xmlChar **local)
5881 {
5882     const xmlChar *pref;
5883     xmlNsPtr ns;
5884     int len, ret;
5885 
5886     *uri = NULL;
5887     *local = NULL;
5888     ret = xmlValidateQName(value, 1);
5889     if (ret > 0) {
5890 	xmlSchemaPSimpleTypeErr(ctxt,
5891 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5892 	    ownerItem, (xmlNodePtr) attr,
5893 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
5894 	    NULL, value, NULL, NULL, NULL);
5895 	*local = value;
5896 	return (ctxt->err);
5897     } else if (ret < 0)
5898 	return (-1);
5899 
5900     if (!strchr((char *) value, ':')) {
5901 	ns = xmlSearchNs(attr->doc, attr->parent, NULL);
5902 	if (ns && ns->href && ns->href[0])
5903 	    *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5904 	else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
5905 	    /* TODO: move XML_SCHEMAS_INCLUDING_CONVERT_NS to the
5906 	    * parser context. */
5907 	    /*
5908 	    * This one takes care of included schemas with no
5909 	    * target namespace.
5910 	    */
5911 	    *uri = ctxt->targetNamespace;
5912 	}
5913 	*local = xmlDictLookup(ctxt->dict, value, -1);
5914 	return (0);
5915     }
5916     /*
5917     * At this point xmlSplitQName3 has to return a local name.
5918     */
5919     *local = xmlSplitQName3(value, &len);
5920     *local = xmlDictLookup(ctxt->dict, *local, -1);
5921     pref = xmlDictLookup(ctxt->dict, value, len);
5922     ns = xmlSearchNs(attr->doc, attr->parent, pref);
5923     if (ns == NULL) {
5924 	xmlSchemaPSimpleTypeErr(ctxt,
5925 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5926 	    ownerItem, (xmlNodePtr) attr,
5927 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, value,
5928 	    "The value '%s' of simple type 'xs:QName' has no "
5929 	    "corresponding namespace declaration in scope", value, NULL);
5930 	return (ctxt->err);
5931     } else {
5932         *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5933     }
5934     return (0);
5935 }
5936 
5937 /**
5938  * xmlSchemaPValAttrNodeQName:
5939  * @ctxt:  a schema parser context
5940  * @schema: the schema context
5941  * @ownerItem: the owner as a schema object
5942  * @attr:  the attribute node
5943  * @uri:  the resulting namespace URI if found
5944  * @local: the resulting local part if found, the attribute value otherwise
5945  *
5946  * Extracts and validates the QName of an attribute value.
5947  * This one is intended to be used on attribute values that
5948  * should resolve to schema components.
5949  *
5950  * Returns 0, in case the QName is valid, a positive error code
5951  * if not valid and -1 if an internal error occurs.
5952  */
5953 static int
xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlSchemaBasicItemPtr ownerItem,xmlAttrPtr attr,const xmlChar ** uri,const xmlChar ** local)5954 xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
5955 				       xmlSchemaPtr schema,
5956 				       xmlSchemaBasicItemPtr ownerItem,
5957 				       xmlAttrPtr attr,
5958 				       const xmlChar **uri,
5959 				       const xmlChar **local)
5960 {
5961     const xmlChar *value;
5962 
5963     value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5964     return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
5965 	ownerItem, attr, value, uri, local));
5966 }
5967 
5968 /**
5969  * xmlSchemaPValAttrQName:
5970  * @ctxt:  a schema parser context
5971  * @schema: the schema context
5972  * @ownerItem: the owner as a schema object
5973  * @ownerElem:  the parent node of the attribute
5974  * @name:  the name of the attribute
5975  * @uri:  the resulting namespace URI if found
5976  * @local: the resulting local part if found, the attribute value otherwise
5977  *
5978  * Extracts and validates the QName of an attribute value.
5979  *
5980  * Returns 0, in case the QName is valid, a positive error code
5981  * if not valid and -1 if an internal error occurs.
5982  */
5983 static int
xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlSchemaBasicItemPtr ownerItem,xmlNodePtr ownerElem,const char * name,const xmlChar ** uri,const xmlChar ** local)5984 xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
5985 				   xmlSchemaPtr schema,
5986 				   xmlSchemaBasicItemPtr ownerItem,
5987 				   xmlNodePtr ownerElem,
5988 				   const char *name,
5989 				   const xmlChar **uri,
5990 				   const xmlChar **local)
5991 {
5992     xmlAttrPtr attr;
5993 
5994     attr = xmlSchemaGetPropNode(ownerElem, name);
5995     if (attr == NULL) {
5996 	*local = NULL;
5997 	*uri = NULL;
5998 	return (0);
5999     }
6000     return (xmlSchemaPValAttrNodeQName(ctxt, schema,
6001 	ownerItem, attr, uri, local));
6002 }
6003 
6004 /**
6005  * xmlSchemaPValAttrID:
6006  * @ctxt:  a schema parser context
6007  *
6008  * Extracts and validates the ID of an attribute value.
6009  *
6010  * Returns 0, in case the ID is valid, a positive error code
6011  * if not valid and -1 if an internal error occurs.
6012  */
6013 static int
xmlSchemaPValAttrNodeID(xmlSchemaParserCtxtPtr ctxt,xmlAttrPtr attr)6014 xmlSchemaPValAttrNodeID(xmlSchemaParserCtxtPtr ctxt, xmlAttrPtr attr)
6015 {
6016     int ret;
6017     const xmlChar *value;
6018 
6019     if (attr == NULL)
6020 	return(0);
6021     value = xmlSchemaGetNodeContentNoDict((xmlNodePtr) attr);
6022     ret = xmlValidateNCName(value, 1);
6023     if (ret == 0) {
6024 	/*
6025 	* NOTE: the IDness might have already be declared in the DTD
6026 	*/
6027 	if (attr->atype != XML_ATTRIBUTE_ID) {
6028 	    xmlIDPtr res;
6029 	    xmlChar *strip;
6030 
6031 	    /*
6032 	    * TODO: Use xmlSchemaStrip here; it's not exported at this
6033 	    * moment.
6034 	    */
6035 	    strip = xmlSchemaCollapseString(value);
6036 	    if (strip != NULL) {
6037 		xmlFree((xmlChar *) value);
6038 		value = strip;
6039 	    }
6040 	    res = xmlAddID(NULL, attr->doc, value, attr);
6041 	    if (res == NULL) {
6042 		ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
6043 		xmlSchemaPSimpleTypeErr(ctxt,
6044 		    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6045 		    NULL, (xmlNodePtr) attr,
6046 		    xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
6047 		    NULL, NULL, "Duplicate value '%s' of simple "
6048 		    "type 'xs:ID'", value, NULL);
6049 	    } else
6050 		attr->atype = XML_ATTRIBUTE_ID;
6051 	}
6052     } else if (ret > 0) {
6053 	ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
6054 	xmlSchemaPSimpleTypeErr(ctxt,
6055 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6056 	    NULL, (xmlNodePtr) attr,
6057 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
6058 	    NULL, NULL, "The value '%s' of simple type 'xs:ID' is "
6059 	    "not a valid 'xs:NCName'",
6060 	    value, NULL);
6061     }
6062     if (value != NULL)
6063 	xmlFree((xmlChar *)value);
6064 
6065     return (ret);
6066 }
6067 
6068 static int
xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr ownerElem,const xmlChar * name)6069 xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,
6070 		    xmlNodePtr ownerElem,
6071 		    const xmlChar *name)
6072 {
6073     xmlAttrPtr attr;
6074 
6075     attr = xmlSchemaGetPropNode(ownerElem, (const char *) name);
6076     if (attr == NULL)
6077 	return(0);
6078     return(xmlSchemaPValAttrNodeID(ctxt, attr));
6079 
6080 }
6081 
6082 /**
6083  * xmlGetMaxOccurs:
6084  * @ctxt:  a schema validation context
6085  * @node:  a subtree containing XML Schema information
6086  *
6087  * Get the maxOccurs property
6088  *
6089  * Returns the default if not found, or the value
6090  */
6091 static int
xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,int min,int max,int def,const char * expected)6092 xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
6093 		int min, int max, int def, const char *expected)
6094 {
6095     const xmlChar *val, *cur;
6096     int ret = 0;
6097     xmlAttrPtr attr;
6098 
6099     attr = xmlSchemaGetPropNode(node, "maxOccurs");
6100     if (attr == NULL)
6101 	return (def);
6102     val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6103 
6104     if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
6105 	if (max != UNBOUNDED) {
6106 	    xmlSchemaPSimpleTypeErr(ctxt,
6107 		XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6108 		/* XML_SCHEMAP_INVALID_MINOCCURS, */
6109 		NULL, (xmlNodePtr) attr, NULL, expected,
6110 		val, NULL, NULL, NULL);
6111 	    return (def);
6112 	} else
6113 	    return (UNBOUNDED);  /* encoding it with -1 might be another option */
6114     }
6115 
6116     cur = val;
6117     while (IS_BLANK_CH(*cur))
6118         cur++;
6119     if (*cur == 0) {
6120         xmlSchemaPSimpleTypeErr(ctxt,
6121 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6122 	    /* XML_SCHEMAP_INVALID_MINOCCURS, */
6123 	    NULL, (xmlNodePtr) attr, NULL, expected,
6124 	    val, NULL, NULL, NULL);
6125 	return (def);
6126     }
6127     while ((*cur >= '0') && (*cur <= '9')) {
6128         if (ret > INT_MAX / 10) {
6129             ret = INT_MAX;
6130         } else {
6131             int digit = *cur - '0';
6132             ret *= 10;
6133             if (ret > INT_MAX - digit)
6134                 ret = INT_MAX;
6135             else
6136                 ret += digit;
6137         }
6138         cur++;
6139     }
6140     while (IS_BLANK_CH(*cur))
6141         cur++;
6142     /*
6143     * TODO: Restrict the maximal value to Integer.
6144     */
6145     if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
6146 	xmlSchemaPSimpleTypeErr(ctxt,
6147 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6148 	    /* XML_SCHEMAP_INVALID_MINOCCURS, */
6149 	    NULL, (xmlNodePtr) attr, NULL, expected,
6150 	    val, NULL, NULL, NULL);
6151         return (def);
6152     }
6153     return (ret);
6154 }
6155 
6156 /**
6157  * xmlGetMinOccurs:
6158  * @ctxt:  a schema validation context
6159  * @node:  a subtree containing XML Schema information
6160  *
6161  * Get the minOccurs property
6162  *
6163  * Returns the default if not found, or the value
6164  */
6165 static int
xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,int min,int max,int def,const char * expected)6166 xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
6167 		int min, int max, int def, const char *expected)
6168 {
6169     const xmlChar *val, *cur;
6170     int ret = 0;
6171     xmlAttrPtr attr;
6172 
6173     attr = xmlSchemaGetPropNode(node, "minOccurs");
6174     if (attr == NULL)
6175 	return (def);
6176     val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6177     cur = val;
6178     while (IS_BLANK_CH(*cur))
6179         cur++;
6180     if (*cur == 0) {
6181         xmlSchemaPSimpleTypeErr(ctxt,
6182 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6183 	    /* XML_SCHEMAP_INVALID_MINOCCURS, */
6184 	    NULL, (xmlNodePtr) attr, NULL, expected,
6185 	    val, NULL, NULL, NULL);
6186         return (def);
6187     }
6188     while ((*cur >= '0') && (*cur <= '9')) {
6189         if (ret > INT_MAX / 10) {
6190             ret = INT_MAX;
6191         } else {
6192             int digit = *cur - '0';
6193             ret *= 10;
6194             if (ret > INT_MAX - digit)
6195                 ret = INT_MAX;
6196             else
6197                 ret += digit;
6198         }
6199         cur++;
6200     }
6201     while (IS_BLANK_CH(*cur))
6202         cur++;
6203     /*
6204     * TODO: Restrict the maximal value to Integer.
6205     */
6206     if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
6207 	xmlSchemaPSimpleTypeErr(ctxt,
6208 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6209 	    /* XML_SCHEMAP_INVALID_MINOCCURS, */
6210 	    NULL, (xmlNodePtr) attr, NULL, expected,
6211 	    val, NULL, NULL, NULL);
6212         return (def);
6213     }
6214     return (ret);
6215 }
6216 
6217 /**
6218  * xmlSchemaPGetBoolNodeValue:
6219  * @ctxt:  a schema validation context
6220  * @ownerItem:  the owner as a schema item
6221  * @node: the node holding the value
6222  *
6223  * Converts a boolean string value into 1 or 0.
6224  *
6225  * Returns 0 or 1.
6226  */
6227 static int
xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,xmlSchemaBasicItemPtr ownerItem,xmlNodePtr node)6228 xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
6229 			   xmlSchemaBasicItemPtr ownerItem,
6230 			   xmlNodePtr node)
6231 {
6232     xmlChar *value = NULL;
6233     int res = 0;
6234 
6235     value = xmlNodeGetContent(node);
6236     /*
6237     * 3.2.2.1 Lexical representation
6238     * An instance of a datatype that is defined as `boolean`
6239     * can have the following legal literals {true, false, 1, 0}.
6240     */
6241     if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
6242         res = 1;
6243     else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
6244         res = 0;
6245     else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
6246 	res = 1;
6247     else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
6248         res = 0;
6249     else {
6250         xmlSchemaPSimpleTypeErr(ctxt,
6251 	    XML_SCHEMAP_INVALID_BOOLEAN,
6252 	    ownerItem, node,
6253 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6254 	    NULL, BAD_CAST value,
6255 	    NULL, NULL, NULL);
6256     }
6257     if (value != NULL)
6258 	xmlFree(value);
6259     return (res);
6260 }
6261 
6262 /**
6263  * xmlGetBooleanProp:
6264  * @ctxt:  a schema validation context
6265  * @node:  a subtree containing XML Schema information
6266  * @name:  the attribute name
6267  * @def:  the default value
6268  *
6269  * Evaluate if a boolean property is set
6270  *
6271  * Returns the default if not found, 0 if found to be false,
6272  * 1 if found to be true
6273  */
6274 static int
xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,const char * name,int def)6275 xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
6276 		  xmlNodePtr node,
6277                   const char *name, int def)
6278 {
6279     const xmlChar *val;
6280 
6281     val = xmlSchemaGetProp(ctxt, node, name);
6282     if (val == NULL)
6283         return (def);
6284     /*
6285     * 3.2.2.1 Lexical representation
6286     * An instance of a datatype that is defined as `boolean`
6287     * can have the following legal literals {true, false, 1, 0}.
6288     */
6289     if (xmlStrEqual(val, BAD_CAST "true"))
6290         def = 1;
6291     else if (xmlStrEqual(val, BAD_CAST "false"))
6292         def = 0;
6293     else if (xmlStrEqual(val, BAD_CAST "1"))
6294 	def = 1;
6295     else if (xmlStrEqual(val, BAD_CAST "0"))
6296         def = 0;
6297     else {
6298         xmlSchemaPSimpleTypeErr(ctxt,
6299 	    XML_SCHEMAP_INVALID_BOOLEAN,
6300 	    NULL,
6301 	    (xmlNodePtr) xmlSchemaGetPropNode(node, name),
6302 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6303 	    NULL, val, NULL, NULL, NULL);
6304     }
6305     return (def);
6306 }
6307 
6308 /************************************************************************
6309  *									*
6310  *		Schema extraction from an Infoset			*
6311  *									*
6312  ************************************************************************/
6313 static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
6314                                                  ctxt, xmlSchemaPtr schema,
6315                                                  xmlNodePtr node,
6316 						 int topLevel);
6317 static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
6318                                                   ctxt,
6319                                                   xmlSchemaPtr schema,
6320                                                   xmlNodePtr node,
6321 						  int topLevel);
6322 static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
6323                                                   ctxt,
6324                                                   xmlSchemaPtr schema,
6325                                                   xmlNodePtr node,
6326 						  xmlSchemaTypeType parentType);
6327 static xmlSchemaBasicItemPtr
6328 xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
6329 			     xmlSchemaPtr schema,
6330 			     xmlNodePtr node,
6331 			     xmlSchemaItemListPtr uses,
6332 			     int parentType);
6333 static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
6334                                            xmlSchemaPtr schema,
6335                                            xmlNodePtr node);
6336 static xmlSchemaWildcardPtr
6337 xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
6338                            xmlSchemaPtr schema, xmlNodePtr node);
6339 
6340 /**
6341  * xmlSchemaPValAttrNodeValue:
6342  *
6343  * @pctxt:  a schema parser context
6344  * @ownerItem: the schema object owner if existent
6345  * @attr:  the schema attribute node being validated
6346  * @value: the value
6347  * @type: the built-in type to be validated against
6348  *
6349  * Validates a value against the given built-in type.
6350  * This one is intended to be used internally for validation
6351  * of schema attribute values during parsing of the schema.
6352  *
6353  * Returns 0 if the value is valid, a positive error code
6354  * number otherwise and -1 in case of an internal or API error.
6355  */
6356 static int
xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr pctxt,xmlSchemaBasicItemPtr ownerItem,xmlAttrPtr attr,const xmlChar * value,xmlSchemaTypePtr type)6357 xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr pctxt,
6358 			   xmlSchemaBasicItemPtr ownerItem,
6359 			   xmlAttrPtr attr,
6360 			   const xmlChar *value,
6361 			   xmlSchemaTypePtr type)
6362 {
6363 
6364     int ret = 0;
6365 
6366     /*
6367     * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
6368     * one is really meant to be used internally, so better not.
6369     */
6370     if ((pctxt == NULL) || (type == NULL) || (attr == NULL))
6371 	return (-1);
6372     if (type->type != XML_SCHEMA_TYPE_BASIC) {
6373 	PERROR_INT("xmlSchemaPValAttrNodeValue",
6374 	    "the given type is not a built-in type");
6375 	return (-1);
6376     }
6377     switch (type->builtInType) {
6378 	case XML_SCHEMAS_NCNAME:
6379 	case XML_SCHEMAS_QNAME:
6380 	case XML_SCHEMAS_ANYURI:
6381 	case XML_SCHEMAS_TOKEN:
6382 	case XML_SCHEMAS_LANGUAGE:
6383 	    ret = xmlSchemaValPredefTypeNode(type, value, NULL,
6384 		(xmlNodePtr) attr);
6385 	    break;
6386 	default: {
6387 	    PERROR_INT("xmlSchemaPValAttrNodeValue",
6388 		"validation using the given type is not supported while "
6389 		"parsing a schema");
6390 	    return (-1);
6391 	}
6392     }
6393     /*
6394     * TODO: Should we use the S4S error codes instead?
6395     */
6396     if (ret < 0) {
6397 	PERROR_INT("xmlSchemaPValAttrNodeValue",
6398 	    "failed to validate a schema attribute value");
6399 	return (-1);
6400     } else if (ret > 0) {
6401 	if (WXS_IS_LIST(type))
6402 	    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
6403 	else
6404 	    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
6405 	xmlSchemaPSimpleTypeErr(pctxt,
6406 	    ret, ownerItem, (xmlNodePtr) attr,
6407 	    type, NULL, value, NULL, NULL, NULL);
6408     }
6409     return (ret);
6410 }
6411 
6412 /**
6413  * xmlSchemaPValAttrNode:
6414  *
6415  * @ctxt:  a schema parser context
6416  * @ownerItem: the schema object owner if existent
6417  * @attr:  the schema attribute node being validated
6418  * @type: the built-in type to be validated against
6419  * @value: the resulting value if any
6420  *
6421  * Extracts and validates a value against the given built-in type.
6422  * This one is intended to be used internally for validation
6423  * of schema attribute values during parsing of the schema.
6424  *
6425  * Returns 0 if the value is valid, a positive error code
6426  * number otherwise and -1 in case of an internal or API error.
6427  */
6428 static int
xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,xmlSchemaBasicItemPtr ownerItem,xmlAttrPtr attr,xmlSchemaTypePtr type,const xmlChar ** value)6429 xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
6430 			   xmlSchemaBasicItemPtr ownerItem,
6431 			   xmlAttrPtr attr,
6432 			   xmlSchemaTypePtr type,
6433 			   const xmlChar **value)
6434 {
6435     const xmlChar *val;
6436 
6437     if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
6438 	return (-1);
6439 
6440     val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6441     if (value != NULL)
6442 	*value = val;
6443 
6444     return (xmlSchemaPValAttrNodeValue(ctxt, ownerItem, attr,
6445 	val, type));
6446 }
6447 
6448 /**
6449  * xmlSchemaPValAttr:
6450  *
6451  * @ctxt:  a schema parser context
6452  * @node: the element node of the attribute
6453  * @ownerItem: the schema object owner if existent
6454  * @ownerElem: the owner element node
6455  * @name:  the name of the schema attribute node
6456  * @type: the built-in type to be validated against
6457  * @value: the resulting value if any
6458  *
6459  * Extracts and validates a value against the given built-in type.
6460  * This one is intended to be used internally for validation
6461  * of schema attribute values during parsing of the schema.
6462  *
6463  * Returns 0 if the value is valid, a positive error code
6464  * number otherwise and -1 in case of an internal or API error.
6465  */
6466 static int
xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,xmlSchemaBasicItemPtr ownerItem,xmlNodePtr ownerElem,const char * name,xmlSchemaTypePtr type,const xmlChar ** value)6467 xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
6468 		       xmlSchemaBasicItemPtr ownerItem,
6469 		       xmlNodePtr ownerElem,
6470 		       const char *name,
6471 		       xmlSchemaTypePtr type,
6472 		       const xmlChar **value)
6473 {
6474     xmlAttrPtr attr;
6475 
6476     if ((ctxt == NULL) || (type == NULL)) {
6477 	if (value != NULL)
6478 	    *value = NULL;
6479 	return (-1);
6480     }
6481     if (type->type != XML_SCHEMA_TYPE_BASIC) {
6482 	if (value != NULL)
6483 	    *value = NULL;
6484 	xmlSchemaPErr(ctxt, ownerElem,
6485 	    XML_SCHEMAP_INTERNAL,
6486 	    "Internal error: xmlSchemaPValAttr, the given "
6487 	    "type '%s' is not a built-in type.\n",
6488 	    type->name, NULL);
6489 	return (-1);
6490     }
6491     attr = xmlSchemaGetPropNode(ownerElem, name);
6492     if (attr == NULL) {
6493 	if (value != NULL)
6494 	    *value = NULL;
6495 	return (0);
6496     }
6497     return (xmlSchemaPValAttrNode(ctxt, ownerItem, attr,
6498 	type, value));
6499 }
6500 
6501 static int
xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema ATTRIBUTE_UNUSED,xmlNodePtr node,xmlAttrPtr attr,const xmlChar * namespaceName)6502 xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,
6503 		  xmlSchemaPtr schema ATTRIBUTE_UNUSED,
6504 		  xmlNodePtr node,
6505 		  xmlAttrPtr attr,
6506 		  const xmlChar *namespaceName)
6507 {
6508     /* TODO: Pointer comparison instead? */
6509     if (xmlStrEqual(pctxt->targetNamespace, namespaceName))
6510 	return (0);
6511     if (xmlStrEqual(xmlSchemaNs, namespaceName))
6512 	return (0);
6513     /*
6514     * Check if the referenced namespace was <import>ed.
6515     */
6516     if (WXS_BUCKET(pctxt)->relations != NULL) {
6517 	xmlSchemaSchemaRelationPtr rel;
6518 
6519 	rel = WXS_BUCKET(pctxt)->relations;
6520 	do {
6521 	    if (WXS_IS_BUCKET_IMPMAIN(rel->type) &&
6522 		xmlStrEqual(namespaceName, rel->importNamespace))
6523 		return (0);
6524 	    rel = rel->next;
6525 	} while (rel != NULL);
6526     }
6527     /*
6528     * No matching <import>ed namespace found.
6529     */
6530     {
6531 	xmlNodePtr n = (attr != NULL) ? (xmlNodePtr) attr : node;
6532 
6533 	if (namespaceName == NULL)
6534 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
6535 		XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6536 		"References from this schema to components in no "
6537 		"namespace are not allowed, since not indicated by an "
6538 		"import statement", NULL, NULL);
6539 	else
6540 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
6541 		XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6542 		"References from this schema to components in the "
6543 		"namespace '%s' are not allowed, since not indicated by an "
6544 		"import statement", namespaceName, NULL);
6545     }
6546     return (XML_SCHEMAP_SRC_RESOLVE);
6547 }
6548 
6549 /**
6550  * xmlSchemaParseLocalAttributes:
6551  * @ctxt:  a schema validation context
6552  * @schema:  the schema being built
6553  * @node:  a subtree containing XML Schema information
6554  * @type:  the hosting type where the attributes will be anchored
6555  *
6556  * Parses attribute uses and attribute declarations and
6557  * attribute group references.
6558  */
6559 static int
xmlSchemaParseLocalAttributes(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr * child,xmlSchemaItemListPtr * list,int parentType,int * hasRefs)6560 xmlSchemaParseLocalAttributes(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6561                         xmlNodePtr *child, xmlSchemaItemListPtr *list,
6562 			int parentType, int *hasRefs)
6563 {
6564     void *item;
6565 
6566     while ((IS_SCHEMA((*child), "attribute")) ||
6567            (IS_SCHEMA((*child), "attributeGroup"))) {
6568         if (IS_SCHEMA((*child), "attribute")) {
6569 	    item = xmlSchemaParseLocalAttribute(ctxt, schema, *child,
6570 		*list, parentType);
6571         } else {
6572             item = xmlSchemaParseAttributeGroupRef(ctxt, schema, *child);
6573 	    if ((item != NULL) && (hasRefs != NULL))
6574 		*hasRefs = 1;
6575         }
6576 	if (item != NULL) {
6577 	    if (*list == NULL) {
6578 		/* TODO: Customize grow factor. */
6579 		*list = xmlSchemaItemListCreate();
6580 		if (*list == NULL)
6581 		    return(-1);
6582 	    }
6583 	    if (xmlSchemaItemListAddSize(*list, 2, item) == -1)
6584 		return(-1);
6585 	}
6586         *child = (*child)->next;
6587     }
6588     return (0);
6589 }
6590 
6591 /**
6592  * xmlSchemaParseAnnotation:
6593  * @ctxt:  a schema validation context
6594  * @schema:  the schema being built
6595  * @node:  a subtree containing XML Schema information
6596  *
6597  * parse a XML schema Attribute declaration
6598  * *WARNING* this interface is highly subject to change
6599  *
6600  * Returns -1 in case of error, 0 if the declaration is improper and
6601  *         1 in case of success.
6602  */
6603 static xmlSchemaAnnotPtr
xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,int needed)6604 xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int needed)
6605 {
6606     xmlSchemaAnnotPtr ret;
6607     xmlNodePtr child = NULL;
6608     xmlAttrPtr attr;
6609     int barked = 0;
6610 
6611     /*
6612     * INFO: S4S completed.
6613     */
6614     /*
6615     * id = ID
6616     * {any attributes with non-schema namespace . . .}>
6617     * Content: (appinfo | documentation)*
6618     */
6619     if ((ctxt == NULL) || (node == NULL))
6620         return (NULL);
6621     if (needed)
6622 	ret = xmlSchemaNewAnnot(ctxt, node);
6623     else
6624 	ret = NULL;
6625     attr = node->properties;
6626     while (attr != NULL) {
6627 	if (((attr->ns == NULL) &&
6628 	    (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
6629 	    ((attr->ns != NULL) &&
6630 	    xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
6631 
6632 	    xmlSchemaPIllegalAttrErr(ctxt,
6633 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6634 	}
6635 	attr = attr->next;
6636     }
6637     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6638     /*
6639     * And now for the children...
6640     */
6641     child = node->children;
6642     while (child != NULL) {
6643 	if (IS_SCHEMA(child, "appinfo")) {
6644 	    /* TODO: make available the content of "appinfo". */
6645 	    /*
6646 	    * source = anyURI
6647 	    * {any attributes with non-schema namespace . . .}>
6648 	    * Content: ({any})*
6649 	    */
6650 	    attr = child->properties;
6651 	    while (attr != NULL) {
6652 		if (((attr->ns == NULL) &&
6653 		     (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
6654 		     ((attr->ns != NULL) &&
6655 		      xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
6656 
6657 		    xmlSchemaPIllegalAttrErr(ctxt,
6658 			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6659 		}
6660 		attr = attr->next;
6661 	    }
6662 	    xmlSchemaPValAttr(ctxt, NULL, child, "source",
6663 		xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
6664 	    child = child->next;
6665 	} else if (IS_SCHEMA(child, "documentation")) {
6666 	    /* TODO: make available the content of "documentation". */
6667 	    /*
6668 	    * source = anyURI
6669 	    * {any attributes with non-schema namespace . . .}>
6670 	    * Content: ({any})*
6671 	    */
6672 	    attr = child->properties;
6673 	    while (attr != NULL) {
6674 		if (attr->ns == NULL) {
6675 		    if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
6676 			xmlSchemaPIllegalAttrErr(ctxt,
6677 			    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6678 		    }
6679 		} else {
6680 		    if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
6681 			(xmlStrEqual(attr->name, BAD_CAST "lang") &&
6682 			(!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
6683 
6684 			xmlSchemaPIllegalAttrErr(ctxt,
6685 			    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6686 		    }
6687 		}
6688 		attr = attr->next;
6689 	    }
6690 	    /*
6691 	    * Attribute "xml:lang".
6692 	    */
6693 	    attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
6694 	    if (attr != NULL)
6695 		xmlSchemaPValAttrNode(ctxt, NULL, attr,
6696 		xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
6697 	    child = child->next;
6698 	} else {
6699 	    if (!barked)
6700 		xmlSchemaPContentErr(ctxt,
6701 		    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6702 		    NULL, node, child, NULL, "(appinfo | documentation)*");
6703 	    barked = 1;
6704 	    child = child->next;
6705 	}
6706     }
6707 
6708     return (ret);
6709 }
6710 
6711 /**
6712  * xmlSchemaParseFacet:
6713  * @ctxt:  a schema validation context
6714  * @schema:  the schema being built
6715  * @node:  a subtree containing XML Schema information
6716  *
6717  * parse a XML schema Facet declaration
6718  * *WARNING* this interface is highly subject to change
6719  *
6720  * Returns the new type structure or NULL in case of error
6721  */
6722 static xmlSchemaFacetPtr
xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)6723 xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6724                     xmlNodePtr node)
6725 {
6726     xmlSchemaFacetPtr facet;
6727     xmlNodePtr child = NULL;
6728     const xmlChar *value;
6729 
6730     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6731         return (NULL);
6732 
6733     facet = xmlSchemaNewFacet();
6734     if (facet == NULL) {
6735         xmlSchemaPErrMemory(ctxt, "allocating facet", node);
6736         return (NULL);
6737     }
6738     facet->node = node;
6739     value = xmlSchemaGetProp(ctxt, node, "value");
6740     if (value == NULL) {
6741         xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
6742                        "Facet %s has no value\n", node->name, NULL);
6743         xmlSchemaFreeFacet(facet);
6744         return (NULL);
6745     }
6746     if (IS_SCHEMA(node, "minInclusive")) {
6747         facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
6748     } else if (IS_SCHEMA(node, "minExclusive")) {
6749         facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
6750     } else if (IS_SCHEMA(node, "maxInclusive")) {
6751         facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
6752     } else if (IS_SCHEMA(node, "maxExclusive")) {
6753         facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
6754     } else if (IS_SCHEMA(node, "totalDigits")) {
6755         facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
6756     } else if (IS_SCHEMA(node, "fractionDigits")) {
6757         facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
6758     } else if (IS_SCHEMA(node, "pattern")) {
6759         facet->type = XML_SCHEMA_FACET_PATTERN;
6760     } else if (IS_SCHEMA(node, "enumeration")) {
6761         facet->type = XML_SCHEMA_FACET_ENUMERATION;
6762     } else if (IS_SCHEMA(node, "whiteSpace")) {
6763         facet->type = XML_SCHEMA_FACET_WHITESPACE;
6764     } else if (IS_SCHEMA(node, "length")) {
6765         facet->type = XML_SCHEMA_FACET_LENGTH;
6766     } else if (IS_SCHEMA(node, "maxLength")) {
6767         facet->type = XML_SCHEMA_FACET_MAXLENGTH;
6768     } else if (IS_SCHEMA(node, "minLength")) {
6769         facet->type = XML_SCHEMA_FACET_MINLENGTH;
6770     } else {
6771         xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
6772                        "Unknown facet type %s\n", node->name, NULL);
6773         xmlSchemaFreeFacet(facet);
6774         return (NULL);
6775     }
6776     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6777     facet->value = value;
6778     if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
6779 	(facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
6780 	const xmlChar *fixed;
6781 
6782 	fixed = xmlSchemaGetProp(ctxt, node, "fixed");
6783 	if (fixed != NULL) {
6784 	    if (xmlStrEqual(fixed, BAD_CAST "true"))
6785 		facet->fixed = 1;
6786 	}
6787     }
6788     child = node->children;
6789 
6790     if (IS_SCHEMA(child, "annotation")) {
6791         facet->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
6792         child = child->next;
6793     }
6794     if (child != NULL) {
6795         xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
6796                        "Facet %s has unexpected child content\n",
6797                        node->name, NULL);
6798     }
6799     return (facet);
6800 }
6801 
6802 /**
6803  * xmlSchemaParseWildcardNs:
6804  * @ctxt:  a schema parser context
6805  * @wildc:  the wildcard, already created
6806  * @node:  a subtree containing XML Schema information
6807  *
6808  * Parses the attribute "processContents" and "namespace"
6809  * of a xsd:anyAttribute and xsd:any.
6810  * *WARNING* this interface is highly subject to change
6811  *
6812  * Returns 0 if everything goes fine, a positive error code
6813  * if something is not valid and -1 if an internal error occurs.
6814  */
6815 static int
xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema ATTRIBUTE_UNUSED,xmlSchemaWildcardPtr wildc,xmlNodePtr node)6816 xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
6817 			 xmlSchemaPtr schema ATTRIBUTE_UNUSED,
6818 			 xmlSchemaWildcardPtr wildc,
6819 			 xmlNodePtr node)
6820 {
6821     const xmlChar *pc, *ns, *dictnsItem;
6822     int ret = 0;
6823     xmlChar *nsItem;
6824     xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
6825     xmlAttrPtr attr;
6826 
6827     pc = xmlSchemaGetProp(ctxt, node, "processContents");
6828     if ((pc == NULL)
6829         || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
6830         wildc->processContents = XML_SCHEMAS_ANY_STRICT;
6831     } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
6832         wildc->processContents = XML_SCHEMAS_ANY_SKIP;
6833     } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
6834         wildc->processContents = XML_SCHEMAS_ANY_LAX;
6835     } else {
6836         xmlSchemaPSimpleTypeErr(ctxt,
6837 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6838 	    NULL, node,
6839 	    NULL, "(strict | skip | lax)", pc,
6840 	    NULL, NULL, NULL);
6841         wildc->processContents = XML_SCHEMAS_ANY_STRICT;
6842 	ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
6843     }
6844     /*
6845      * Build the namespace constraints.
6846      */
6847     attr = xmlSchemaGetPropNode(node, "namespace");
6848     ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6849     if ((attr == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
6850 	wildc->any = 1;
6851     else if (xmlStrEqual(ns, BAD_CAST "##other")) {
6852 	wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
6853 	if (wildc->negNsSet == NULL) {
6854 	    return (-1);
6855 	}
6856 	wildc->negNsSet->value = ctxt->targetNamespace;
6857     } else {
6858 	const xmlChar *end, *cur;
6859 
6860 	cur = ns;
6861 	do {
6862 	    while (IS_BLANK_CH(*cur))
6863 		cur++;
6864 	    end = cur;
6865 	    while ((*end != 0) && (!(IS_BLANK_CH(*end))))
6866 		end++;
6867 	    if (end == cur)
6868 		break;
6869 	    nsItem = xmlStrndup(cur, end - cur);
6870 	    if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
6871 		    (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
6872 		xmlSchemaPSimpleTypeErr(ctxt,
6873 		    XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
6874 		    NULL, (xmlNodePtr) attr,
6875 		    NULL,
6876 		    "((##any | ##other) | List of (xs:anyURI | "
6877 		    "(##targetNamespace | ##local)))",
6878 		    nsItem, NULL, NULL, NULL);
6879 		ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
6880 	    } else {
6881 		if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
6882 		    dictnsItem = ctxt->targetNamespace;
6883 		} else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
6884 		    dictnsItem = NULL;
6885 		} else {
6886 		    /*
6887 		    * Validate the item (anyURI).
6888 		    */
6889 		    xmlSchemaPValAttrNodeValue(ctxt, NULL, attr,
6890 			nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
6891 		    dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
6892 		}
6893 		/*
6894 		* Avoid duplicate namespaces.
6895 		*/
6896 		tmp = wildc->nsSet;
6897 		while (tmp != NULL) {
6898 		    if (dictnsItem == tmp->value)
6899 			break;
6900 		    tmp = tmp->next;
6901 		}
6902 		if (tmp == NULL) {
6903 		    tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
6904 		    if (tmp == NULL) {
6905 			xmlFree(nsItem);
6906 			return (-1);
6907 		    }
6908 		    tmp->value = dictnsItem;
6909 		    tmp->next = NULL;
6910 		    if (wildc->nsSet == NULL)
6911 			wildc->nsSet = tmp;
6912 		    else if (lastNs != NULL)
6913 			lastNs->next = tmp;
6914 		    lastNs = tmp;
6915 		}
6916 
6917 	    }
6918 	    xmlFree(nsItem);
6919 	    cur = end;
6920 	} while (*cur != 0);
6921     }
6922     return (ret);
6923 }
6924 
6925 static int
xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr item ATTRIBUTE_UNUSED,xmlNodePtr node,int minOccurs,int maxOccurs)6926 xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
6927 				 xmlSchemaParticlePtr item ATTRIBUTE_UNUSED,
6928 				 xmlNodePtr node,
6929 				 int minOccurs,
6930 				 int maxOccurs) {
6931 
6932     if ((maxOccurs == 0) && ( minOccurs == 0))
6933 	return (0);
6934     if (maxOccurs != UNBOUNDED) {
6935 	/*
6936 	* TODO: Maybe we should better not create the particle,
6937 	* if min/max is invalid, since it could confuse the build of the
6938 	* content model.
6939 	*/
6940 	/*
6941 	* 3.9.6 Schema Component Constraint: Particle Correct
6942 	*
6943 	*/
6944 	if (maxOccurs < 1) {
6945 	    /*
6946 	    * 2.2 {max occurs} must be greater than or equal to 1.
6947 	    */
6948 	    xmlSchemaPCustomAttrErr(ctxt,
6949 		XML_SCHEMAP_P_PROPS_CORRECT_2_2,
6950 		NULL, NULL,
6951 		xmlSchemaGetPropNode(node, "maxOccurs"),
6952 		"The value must be greater than or equal to 1");
6953 	    return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
6954 	} else if (minOccurs > maxOccurs) {
6955 	    /*
6956 	    * 2.1 {min occurs} must not be greater than {max occurs}.
6957 	    */
6958 	    xmlSchemaPCustomAttrErr(ctxt,
6959 		XML_SCHEMAP_P_PROPS_CORRECT_2_1,
6960 		NULL, NULL,
6961 		xmlSchemaGetPropNode(node, "minOccurs"),
6962 		"The value must not be greater than the value of 'maxOccurs'");
6963 	    return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
6964 	}
6965     }
6966     return (0);
6967 }
6968 
6969 /**
6970  * xmlSchemaParseAny:
6971  * @ctxt:  a schema validation context
6972  * @schema:  the schema being built
6973  * @node:  a subtree containing XML Schema information
6974  *
6975  * Parsea a XML schema <any> element. A particle and wildcard
6976  * will be created (except if minOccurs==maxOccurs==0, in this case
6977  * nothing will be created).
6978  * *WARNING* this interface is highly subject to change
6979  *
6980  * Returns the particle or NULL in case of error or if minOccurs==maxOccurs==0
6981  */
6982 static xmlSchemaParticlePtr
xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)6983 xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6984                   xmlNodePtr node)
6985 {
6986     xmlSchemaParticlePtr particle;
6987     xmlNodePtr child = NULL;
6988     xmlSchemaWildcardPtr wild;
6989     int min, max;
6990     xmlAttrPtr attr;
6991     xmlSchemaAnnotPtr annot = NULL;
6992 
6993     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6994         return (NULL);
6995     /*
6996     * Check for illegal attributes.
6997     */
6998     attr = node->properties;
6999     while (attr != NULL) {
7000 	if (attr->ns == NULL) {
7001 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7002 		(!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
7003 		(!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
7004 	        (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
7005 		(!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
7006 		xmlSchemaPIllegalAttrErr(ctxt,
7007 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7008 	    }
7009 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7010 	    xmlSchemaPIllegalAttrErr(ctxt,
7011 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7012 	}
7013 	attr = attr->next;
7014     }
7015     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
7016     /*
7017     * minOccurs/maxOccurs.
7018     */
7019     max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
7020 	"(xs:nonNegativeInteger | unbounded)");
7021     min = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
7022 	"xs:nonNegativeInteger");
7023     xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
7024     /*
7025     * Create & parse the wildcard.
7026     */
7027     wild = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY, node);
7028     if (wild == NULL)
7029 	return (NULL);
7030     xmlSchemaParseWildcardNs(ctxt, schema, wild, node);
7031     /*
7032     * And now for the children...
7033     */
7034     child = node->children;
7035     if (IS_SCHEMA(child, "annotation")) {
7036         annot = xmlSchemaParseAnnotation(ctxt, child, 1);
7037         child = child->next;
7038     }
7039     if (child != NULL) {
7040 	xmlSchemaPContentErr(ctxt,
7041 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7042 	    NULL, node, child,
7043 	    NULL, "(annotation?)");
7044     }
7045     /*
7046     * No component if minOccurs==maxOccurs==0.
7047     */
7048     if ((min == 0) && (max == 0)) {
7049 	/* Don't free the wildcard, since it's already on the list. */
7050 	return (NULL);
7051     }
7052     /*
7053     * Create the particle.
7054     */
7055     particle = xmlSchemaAddParticle(ctxt, node, min, max);
7056     if (particle == NULL)
7057         return (NULL);
7058     particle->annot = annot;
7059     particle->children = (xmlSchemaTreeItemPtr) wild;
7060 
7061     return (particle);
7062 }
7063 
7064 /**
7065  * xmlSchemaParseNotation:
7066  * @ctxt:  a schema validation context
7067  * @schema:  the schema being built
7068  * @node:  a subtree containing XML Schema information
7069  *
7070  * parse a XML schema Notation declaration
7071  *
7072  * Returns the new structure or NULL in case of error
7073  */
7074 static xmlSchemaNotationPtr
xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)7075 xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
7076                        xmlNodePtr node)
7077 {
7078     const xmlChar *name;
7079     xmlSchemaNotationPtr ret;
7080     xmlNodePtr child = NULL;
7081 
7082     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7083         return (NULL);
7084     name = xmlSchemaGetProp(ctxt, node, "name");
7085     if (name == NULL) {
7086         xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
7087                        "Notation has no name\n", NULL, NULL);
7088         return (NULL);
7089     }
7090     ret = xmlSchemaAddNotation(ctxt, schema, name,
7091 	ctxt->targetNamespace, node);
7092     if (ret == NULL)
7093         return (NULL);
7094     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
7095 
7096     child = node->children;
7097     if (IS_SCHEMA(child, "annotation")) {
7098         ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
7099         child = child->next;
7100     }
7101     if (child != NULL) {
7102 	xmlSchemaPContentErr(ctxt,
7103 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7104 	    NULL, node, child,
7105 	    NULL, "(annotation?)");
7106     }
7107 
7108     return (ret);
7109 }
7110 
7111 /**
7112  * xmlSchemaParseAnyAttribute:
7113  * @ctxt:  a schema validation context
7114  * @schema:  the schema being built
7115  * @node:  a subtree containing XML Schema information
7116  *
7117  * parse a XML schema AnyAttribute declaration
7118  * *WARNING* this interface is highly subject to change
7119  *
7120  * Returns a wildcard or NULL.
7121  */
7122 static xmlSchemaWildcardPtr
xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)7123 xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
7124                            xmlSchemaPtr schema, xmlNodePtr node)
7125 {
7126     xmlSchemaWildcardPtr ret;
7127     xmlNodePtr child = NULL;
7128     xmlAttrPtr attr;
7129 
7130     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7131         return (NULL);
7132 
7133     ret = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
7134 	node);
7135     if (ret == NULL) {
7136         return (NULL);
7137     }
7138     /*
7139     * Check for illegal attributes.
7140     */
7141     attr = node->properties;
7142     while (attr != NULL) {
7143 	if (attr->ns == NULL) {
7144 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7145 	        (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
7146 		(!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
7147 		xmlSchemaPIllegalAttrErr(ctxt,
7148 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7149 	    }
7150 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7151 	    xmlSchemaPIllegalAttrErr(ctxt,
7152 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7153 	}
7154 	attr = attr->next;
7155     }
7156     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
7157     /*
7158     * Parse the namespace list.
7159     */
7160     if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0)
7161 	return (NULL);
7162     /*
7163     * And now for the children...
7164     */
7165     child = node->children;
7166     if (IS_SCHEMA(child, "annotation")) {
7167         ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
7168         child = child->next;
7169     }
7170     if (child != NULL) {
7171 	xmlSchemaPContentErr(ctxt,
7172 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7173 	    NULL, node, child,
7174 	    NULL, "(annotation?)");
7175     }
7176 
7177     return (ret);
7178 }
7179 
7180 
7181 /**
7182  * xmlSchemaParseAttribute:
7183  * @ctxt:  a schema validation context
7184  * @schema:  the schema being built
7185  * @node:  a subtree containing XML Schema information
7186  *
7187  * parse a XML schema Attribute declaration
7188  * *WARNING* this interface is highly subject to change
7189  *
7190  * Returns the attribute declaration.
7191  */
7192 static xmlSchemaBasicItemPtr
xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node,xmlSchemaItemListPtr uses,int parentType)7193 xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
7194 			     xmlSchemaPtr schema,
7195 			     xmlNodePtr node,
7196 			     xmlSchemaItemListPtr uses,
7197 			     int parentType)
7198 {
7199     const xmlChar *attrValue, *name = NULL, *ns = NULL;
7200     xmlSchemaAttributeUsePtr use = NULL;
7201     xmlNodePtr child = NULL;
7202     xmlAttrPtr attr;
7203     const xmlChar *tmpNs = NULL, *tmpName = NULL, *defValue = NULL;
7204     int isRef = 0, occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7205     int	nberrors, hasForm = 0, defValueType = 0;
7206 
7207 #define WXS_ATTR_DEF_VAL_DEFAULT 1
7208 #define WXS_ATTR_DEF_VAL_FIXED 2
7209 
7210     /*
7211      * 3.2.3 Constraints on XML Representations of Attribute Declarations
7212      */
7213 
7214     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7215         return (NULL);
7216     attr = xmlSchemaGetPropNode(node, "ref");
7217     if (attr != NULL) {
7218 	if (xmlSchemaPValAttrNodeQName(pctxt, schema,
7219 	    NULL, attr, &tmpNs, &tmpName) != 0) {
7220 	    return (NULL);
7221 	}
7222 	if (xmlSchemaCheckReference(pctxt, schema, node, attr, tmpNs) != 0)
7223 	    return(NULL);
7224 	isRef = 1;
7225     }
7226     nberrors = pctxt->nberrors;
7227     /*
7228     * Check for illegal attributes.
7229     */
7230     attr = node->properties;
7231     while (attr != NULL) {
7232 	if (attr->ns == NULL) {
7233 	    if (isRef) {
7234 		if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7235 		    xmlSchemaPValAttrNodeID(pctxt, attr);
7236 		    goto attr_next;
7237 		} else if (xmlStrEqual(attr->name, BAD_CAST "ref")) {
7238 		    goto attr_next;
7239 		}
7240 	    } else {
7241 		if (xmlStrEqual(attr->name, BAD_CAST "name")) {
7242 		    goto attr_next;
7243 		} else if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7244 		    xmlSchemaPValAttrNodeID(pctxt, attr);
7245 		    goto attr_next;
7246 		} else if (xmlStrEqual(attr->name, BAD_CAST "type")) {
7247 		    xmlSchemaPValAttrNodeQName(pctxt, schema, NULL,
7248 			attr, &tmpNs, &tmpName);
7249 		    goto attr_next;
7250 		} else if (xmlStrEqual(attr->name, BAD_CAST "form")) {
7251 		    /*
7252 		    * Evaluate the target namespace
7253 		    */
7254 		    hasForm = 1;
7255 		    attrValue = xmlSchemaGetNodeContent(pctxt,
7256 			(xmlNodePtr) attr);
7257 		    if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
7258 			ns = pctxt->targetNamespace;
7259 		    } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified"))
7260 		    {
7261 			xmlSchemaPSimpleTypeErr(pctxt,
7262 			    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7263 			    NULL, (xmlNodePtr) attr,
7264 			    NULL, "(qualified | unqualified)",
7265 			    attrValue, NULL, NULL, NULL);
7266 		    }
7267 		    goto attr_next;
7268 		}
7269 	    }
7270 	    if (xmlStrEqual(attr->name, BAD_CAST "use")) {
7271 
7272 		attrValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7273 		/* TODO: Maybe we need to normalize the value beforehand. */
7274 		if (xmlStrEqual(attrValue, BAD_CAST "optional"))
7275 		    occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7276 		else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
7277 		    occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
7278 		else if (xmlStrEqual(attrValue, BAD_CAST "required"))
7279 		    occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
7280 		else {
7281 		    xmlSchemaPSimpleTypeErr(pctxt,
7282 			XML_SCHEMAP_INVALID_ATTR_USE,
7283 			NULL, (xmlNodePtr) attr,
7284 			NULL, "(optional | prohibited | required)",
7285 			attrValue, NULL, NULL, NULL);
7286 		}
7287 		goto attr_next;
7288 	    } else if (xmlStrEqual(attr->name, BAD_CAST "default")) {
7289 		/*
7290 		* 3.2.3 : 1
7291 		* default and fixed must not both be present.
7292 		*/
7293 		if (defValue) {
7294 		    xmlSchemaPMutualExclAttrErr(pctxt,
7295 			XML_SCHEMAP_SRC_ATTRIBUTE_1,
7296 			NULL, attr, "default", "fixed");
7297 		} else {
7298 		    defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7299 		    defValueType = WXS_ATTR_DEF_VAL_DEFAULT;
7300 		}
7301 		goto attr_next;
7302 	    } else if (xmlStrEqual(attr->name, BAD_CAST "fixed")) {
7303 		/*
7304 		* 3.2.3 : 1
7305 		* default and fixed must not both be present.
7306 		*/
7307 		if (defValue) {
7308 		    xmlSchemaPMutualExclAttrErr(pctxt,
7309 			XML_SCHEMAP_SRC_ATTRIBUTE_1,
7310 			NULL, attr, "default", "fixed");
7311 		} else {
7312 		    defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7313 		    defValueType = WXS_ATTR_DEF_VAL_FIXED;
7314 		}
7315 		goto attr_next;
7316 	    }
7317 	} else if (! xmlStrEqual(attr->ns->href, xmlSchemaNs))
7318 	    goto attr_next;
7319 
7320 	xmlSchemaPIllegalAttrErr(pctxt,
7321 	    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7322 
7323 attr_next:
7324 	attr = attr->next;
7325     }
7326     /*
7327     * 3.2.3 : 2
7328     * If default and use are both present, use must have
7329     * the actual value optional.
7330     */
7331     if ((defValueType == WXS_ATTR_DEF_VAL_DEFAULT) &&
7332 	(occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL)) {
7333 	xmlSchemaPSimpleTypeErr(pctxt,
7334 	    XML_SCHEMAP_SRC_ATTRIBUTE_2,
7335 	    NULL, node, NULL,
7336 	    "(optional | prohibited | required)", NULL,
7337 	    "The value of the attribute 'use' must be 'optional' "
7338 	    "if the attribute 'default' is present",
7339 	    NULL, NULL);
7340     }
7341     /*
7342     * We want correct attributes.
7343     */
7344     if (nberrors != pctxt->nberrors)
7345 	return(NULL);
7346     if (! isRef) {
7347 	xmlSchemaAttributePtr attrDecl;
7348 
7349 	/* TODO: move XML_SCHEMAS_QUALIF_ATTR to the parser. */
7350 	if ((! hasForm) && (schema->flags & XML_SCHEMAS_QUALIF_ATTR))
7351 	    ns = pctxt->targetNamespace;
7352 	/*
7353 	* 3.2.6 Schema Component Constraint: xsi: Not Allowed
7354 	* TODO: Move this to the component layer.
7355 	*/
7356 	if (xmlStrEqual(ns, xmlSchemaInstanceNs)) {
7357 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
7358 		XML_SCHEMAP_NO_XSI,
7359 		node, NULL,
7360 		"The target namespace must not match '%s'",
7361 		xmlSchemaInstanceNs, NULL);
7362 	}
7363 	attr = xmlSchemaGetPropNode(node, "name");
7364 	if (attr == NULL) {
7365 	    xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7366 		NULL, node, "name", NULL);
7367 	    return (NULL);
7368 	}
7369 	if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7370 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7371 	    return (NULL);
7372 	}
7373 	/*
7374 	* 3.2.6 Schema Component Constraint: xmlns Not Allowed
7375 	* TODO: Move this to the component layer.
7376 	*/
7377 	if (xmlStrEqual(name, BAD_CAST "xmlns")) {
7378 	    xmlSchemaPSimpleTypeErr(pctxt,
7379 		XML_SCHEMAP_NO_XMLNS,
7380 		NULL, (xmlNodePtr) attr,
7381 		xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7382 		"The value of the attribute must not match 'xmlns'",
7383 		NULL, NULL);
7384 	    return (NULL);
7385 	}
7386 	if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED)
7387 	    goto check_children;
7388 	/*
7389 	* Create the attribute use component.
7390 	*/
7391 	use = xmlSchemaAddAttributeUse(pctxt, node);
7392 	if (use == NULL)
7393 	    return(NULL);
7394 	use->occurs = occurs;
7395 	/*
7396 	* Create the attribute declaration.
7397 	*/
7398 	attrDecl = xmlSchemaAddAttribute(pctxt, schema, name, ns, node, 0);
7399 	if (attrDecl == NULL)
7400 	    return (NULL);
7401 	if (tmpName != NULL) {
7402 	    attrDecl->typeName = tmpName;
7403 	    attrDecl->typeNs = tmpNs;
7404 	}
7405 	use->attrDecl = attrDecl;
7406 	/*
7407 	* Value constraint.
7408 	*/
7409 	if (defValue != NULL) {
7410 	    attrDecl->defValue = defValue;
7411 	    if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7412 		attrDecl->flags |= XML_SCHEMAS_ATTR_FIXED;
7413 	}
7414     } else if (occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7415 	xmlSchemaQNameRefPtr ref;
7416 
7417 	/*
7418 	* Create the attribute use component.
7419 	*/
7420 	use = xmlSchemaAddAttributeUse(pctxt, node);
7421 	if (use == NULL)
7422 	    return(NULL);
7423 	/*
7424 	* We need to resolve the reference at later stage.
7425 	*/
7426 	WXS_ADD_PENDING(pctxt, use);
7427 	use->occurs = occurs;
7428 	/*
7429 	* Create a QName reference to the attribute declaration.
7430 	*/
7431 	ref = xmlSchemaNewQNameRef(pctxt, XML_SCHEMA_TYPE_ATTRIBUTE,
7432 	    tmpName, tmpNs);
7433 	if (ref == NULL)
7434 	    return(NULL);
7435 	/*
7436 	* Assign the reference. This will be substituted for the
7437 	* referenced attribute declaration when the QName is resolved.
7438 	*/
7439 	use->attrDecl = WXS_ATTR_CAST ref;
7440 	/*
7441 	* Value constraint.
7442 	*/
7443 	if (defValue != NULL)
7444 	    use->defValue = defValue;
7445 	if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7446 	    use->flags |= XML_SCHEMA_ATTR_USE_FIXED;
7447     }
7448 
7449 check_children:
7450     /*
7451     * And now for the children...
7452     */
7453     child = node->children;
7454     if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7455 	xmlSchemaAttributeUseProhibPtr prohib;
7456 
7457 	if (IS_SCHEMA(child, "annotation")) {
7458 	    xmlSchemaParseAnnotation(pctxt, child, 0);
7459 	    child = child->next;
7460 	}
7461 	if (child != NULL) {
7462 	    xmlSchemaPContentErr(pctxt,
7463 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7464 		NULL, node, child, NULL,
7465 		"(annotation?)");
7466 	}
7467 	/*
7468 	* Check for pointlessness of attribute prohibitions.
7469 	*/
7470 	if (parentType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
7471 	    xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7472 		XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7473 		node, NULL,
7474 		"Skipping attribute use prohibition, since it is "
7475 		"pointless inside an <attributeGroup>",
7476 		NULL, NULL, NULL);
7477 	    return(NULL);
7478 	} else if (parentType == XML_SCHEMA_TYPE_EXTENSION) {
7479 	    xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7480 		XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7481 		node, NULL,
7482 		"Skipping attribute use prohibition, since it is "
7483 		"pointless when extending a type",
7484 		NULL, NULL, NULL);
7485 	    return(NULL);
7486 	}
7487 	if (! isRef) {
7488 	    tmpName = name;
7489 	    tmpNs = ns;
7490 	}
7491 	/*
7492 	* Check for duplicate attribute prohibitions.
7493 	*/
7494 	if (uses) {
7495 	    int i;
7496 
7497 	    for (i = 0; i < uses->nbItems; i++) {
7498 		use = uses->items[i];
7499 		if ((use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) &&
7500 		    (tmpName == (WXS_ATTR_PROHIB_CAST use)->name) &&
7501 		    (tmpNs == (WXS_ATTR_PROHIB_CAST use)->targetNamespace))
7502 		{
7503 		    xmlChar *str = NULL;
7504 
7505 		    xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7506 			XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7507 			node, NULL,
7508 			"Skipping duplicate attribute use prohibition '%s'",
7509 			xmlSchemaFormatQName(&str, tmpNs, tmpName),
7510 			NULL, NULL);
7511 		    FREE_AND_NULL(str)
7512 		    return(NULL);
7513 		}
7514 	    }
7515 	}
7516 	/*
7517 	* Create the attribute prohibition helper component.
7518 	*/
7519 	prohib = xmlSchemaAddAttributeUseProhib(pctxt);
7520 	if (prohib == NULL)
7521 	    return(NULL);
7522 	prohib->node = node;
7523 	prohib->name = tmpName;
7524 	prohib->targetNamespace = tmpNs;
7525 	if (isRef) {
7526 	    /*
7527 	    * We need at least to resolve to the attribute declaration.
7528 	    */
7529 	    WXS_ADD_PENDING(pctxt, prohib);
7530 	}
7531 	return(WXS_BASIC_CAST prohib);
7532     } else {
7533 	if (IS_SCHEMA(child, "annotation")) {
7534 	    /*
7535 	    * TODO: Should this go into the attr decl?
7536 	    */
7537 	    use->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7538 	    child = child->next;
7539 	}
7540 	if (isRef) {
7541 	    if (child != NULL) {
7542 		if (IS_SCHEMA(child, "simpleType"))
7543 		    /*
7544 		    * 3.2.3 : 3.2
7545 		    * If ref is present, then all of <simpleType>,
7546 		    * form and type must be absent.
7547 		    */
7548 		    xmlSchemaPContentErr(pctxt,
7549 			XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
7550 			NULL, node, child, NULL,
7551 			"(annotation?)");
7552 		else
7553 		    xmlSchemaPContentErr(pctxt,
7554 			XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7555 			NULL, node, child, NULL,
7556 			"(annotation?)");
7557 	    }
7558 	} else {
7559 	    if (IS_SCHEMA(child, "simpleType")) {
7560 		if (WXS_ATTRUSE_DECL(use)->typeName != NULL) {
7561 		    /*
7562 		    * 3.2.3 : 4
7563 		    * type and <simpleType> must not both be present.
7564 		    */
7565 		    xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7566 			NULL, node, child,
7567 			"The attribute 'type' and the <simpleType> child "
7568 			"are mutually exclusive", NULL);
7569 		} else
7570 		    WXS_ATTRUSE_TYPEDEF(use) =
7571 			xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7572 		child = child->next;
7573 	    }
7574 	    if (child != NULL)
7575 		xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7576 		NULL, node, child, NULL,
7577 		"(annotation?, simpleType?)");
7578 	}
7579     }
7580     return (WXS_BASIC_CAST use);
7581 }
7582 
7583 
7584 static xmlSchemaAttributePtr
xmlSchemaParseGlobalAttribute(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node)7585 xmlSchemaParseGlobalAttribute(xmlSchemaParserCtxtPtr pctxt,
7586 			      xmlSchemaPtr schema,
7587 			      xmlNodePtr node)
7588 {
7589     const xmlChar *attrValue;
7590     xmlSchemaAttributePtr ret;
7591     xmlNodePtr child = NULL;
7592     xmlAttrPtr attr;
7593 
7594     /*
7595      * Note that the w3c spec assumes the schema to be validated with schema
7596      * for schemas beforehand.
7597      *
7598      * 3.2.3 Constraints on XML Representations of Attribute Declarations
7599      */
7600     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7601         return (NULL);
7602     /*
7603     * 3.2.3 : 3.1
7604     * One of ref or name must be present, but not both
7605     */
7606     attr = xmlSchemaGetPropNode(node, "name");
7607     if (attr == NULL) {
7608 	xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7609 	    NULL, node, "name", NULL);
7610 	return (NULL);
7611     }
7612     if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7613 	xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
7614 	return (NULL);
7615     }
7616     /*
7617     * 3.2.6 Schema Component Constraint: xmlns Not Allowed
7618     * TODO: Move this to the component layer.
7619     */
7620     if (xmlStrEqual(attrValue, BAD_CAST "xmlns")) {
7621 	xmlSchemaPSimpleTypeErr(pctxt,
7622 	    XML_SCHEMAP_NO_XMLNS,
7623 	    NULL, (xmlNodePtr) attr,
7624 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7625 	    "The value of the attribute must not match 'xmlns'",
7626 	    NULL, NULL);
7627 	return (NULL);
7628     }
7629     /*
7630     * 3.2.6 Schema Component Constraint: xsi: Not Allowed
7631     * TODO: Move this to the component layer.
7632     *       Or better leave it here and add it to the component layer
7633     *       if we have a schema construction API.
7634     */
7635     if (xmlStrEqual(pctxt->targetNamespace, xmlSchemaInstanceNs)) {
7636 	xmlSchemaCustomErr(ACTXT_CAST pctxt,
7637 	    XML_SCHEMAP_NO_XSI, node, NULL,
7638 	    "The target namespace must not match '%s'",
7639 	    xmlSchemaInstanceNs, NULL);
7640     }
7641 
7642     ret = xmlSchemaAddAttribute(pctxt, schema, attrValue,
7643 	pctxt->targetNamespace, node, 1);
7644     if (ret == NULL)
7645 	return (NULL);
7646     ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
7647 
7648     /*
7649     * Check for illegal attributes.
7650     */
7651     attr = node->properties;
7652     while (attr != NULL) {
7653 	if (attr->ns == NULL) {
7654 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7655 		(!xmlStrEqual(attr->name, BAD_CAST "default")) &&
7656 		(!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
7657 		(!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7658 		(!xmlStrEqual(attr->name, BAD_CAST "type")))
7659 	    {
7660 		xmlSchemaPIllegalAttrErr(pctxt,
7661 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7662 	    }
7663 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7664 	    xmlSchemaPIllegalAttrErr(pctxt,
7665 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7666 	}
7667 	attr = attr->next;
7668     }
7669     xmlSchemaPValAttrQName(pctxt, schema, NULL,
7670 	node, "type", &ret->typeNs, &ret->typeName);
7671 
7672     xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7673     /*
7674     * Attribute "fixed".
7675     */
7676     ret->defValue = xmlSchemaGetProp(pctxt, node, "fixed");
7677     if (ret->defValue != NULL)
7678 	ret->flags |= XML_SCHEMAS_ATTR_FIXED;
7679     /*
7680     * Attribute "default".
7681     */
7682     attr = xmlSchemaGetPropNode(node, "default");
7683     if (attr != NULL) {
7684 	/*
7685 	* 3.2.3 : 1
7686 	* default and fixed must not both be present.
7687 	*/
7688 	if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
7689 	    xmlSchemaPMutualExclAttrErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
7690 		WXS_BASIC_CAST ret, attr, "default", "fixed");
7691 	} else
7692 	    ret->defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7693     }
7694     /*
7695     * And now for the children...
7696     */
7697     child = node->children;
7698     if (IS_SCHEMA(child, "annotation")) {
7699         ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7700         child = child->next;
7701     }
7702     if (IS_SCHEMA(child, "simpleType")) {
7703 	if (ret->typeName != NULL) {
7704 	    /*
7705 	    * 3.2.3 : 4
7706 	    * type and <simpleType> must not both be present.
7707 	    */
7708 	    xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7709 		NULL, node, child,
7710 		"The attribute 'type' and the <simpleType> child "
7711 		"are mutually exclusive", NULL);
7712 	} else
7713 	    ret->subtypes = xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7714 	child = child->next;
7715     }
7716     if (child != NULL)
7717 	xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7718 	    NULL, node, child, NULL,
7719 	    "(annotation?, simpleType?)");
7720 
7721     return (ret);
7722 }
7723 
7724 /**
7725  * xmlSchemaParseAttributeGroupRef:
7726  * @ctxt:  a schema validation context
7727  * @schema:  the schema being built
7728  * @node:  a subtree containing XML Schema information
7729  *
7730  * Parse an attribute group definition reference.
7731  * Note that a reference to an attribute group does not
7732  * correspond to any component at all.
7733  * *WARNING* this interface is highly subject to change
7734  *
7735  * Returns the attribute group or NULL in case of error.
7736  */
7737 static xmlSchemaQNameRefPtr
xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node)7738 xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,
7739 				xmlSchemaPtr schema,
7740 				xmlNodePtr node)
7741 {
7742     xmlSchemaQNameRefPtr ret;
7743     xmlNodePtr child = NULL;
7744     xmlAttrPtr attr;
7745     const xmlChar *refNs = NULL, *ref = NULL;
7746 
7747     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7748         return (NULL);
7749 
7750     attr = xmlSchemaGetPropNode(node, "ref");
7751     if (attr == NULL) {
7752 	xmlSchemaPMissingAttrErr(pctxt,
7753 	    XML_SCHEMAP_S4S_ATTR_MISSING,
7754 	    NULL, node, "ref", NULL);
7755 	return (NULL);
7756     }
7757     xmlSchemaPValAttrNodeQName(pctxt, schema,
7758 	NULL, attr, &refNs, &ref);
7759     if (xmlSchemaCheckReference(pctxt, schema, node, attr, refNs) != 0)
7760 	return(NULL);
7761 
7762     /*
7763     * Check for illegal attributes.
7764     */
7765     attr = node->properties;
7766     while (attr != NULL) {
7767 	if (attr->ns == NULL) {
7768 	    if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
7769 		(!xmlStrEqual(attr->name, BAD_CAST "id")))
7770 	    {
7771 		xmlSchemaPIllegalAttrErr(pctxt,
7772 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7773 	    }
7774 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7775 	    xmlSchemaPIllegalAttrErr(pctxt,
7776 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7777 	}
7778 	attr = attr->next;
7779     }
7780     /* Attribute ID */
7781     xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7782 
7783     /*
7784     * And now for the children...
7785     */
7786     child = node->children;
7787     if (IS_SCHEMA(child, "annotation")) {
7788 	/*
7789 	* TODO: We do not have a place to store the annotation, do we?
7790 	*/
7791         xmlSchemaParseAnnotation(pctxt, child, 0);
7792         child = child->next;
7793     }
7794     if (child != NULL) {
7795 	xmlSchemaPContentErr(pctxt,
7796 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7797 	    NULL, node, child, NULL,
7798 	    "(annotation?)");
7799     }
7800 
7801     /*
7802     * Handle attribute group redefinitions.
7803     */
7804     if (pctxt->isRedefine && pctxt->redef &&
7805 	(pctxt->redef->item->type ==
7806 	    XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
7807 	(ref == pctxt->redef->refName) &&
7808 	(refNs == pctxt->redef->refTargetNs))
7809     {
7810 	/*
7811 	* SPEC src-redefine:
7812 	* (7.1) "If it has an <attributeGroup> among its contents
7813 	* the `actual value` of whose ref [attribute] is the same
7814 	* as the `actual value` of its own name attribute plus
7815 	* target namespace, then it must have exactly one such group."
7816 	*/
7817 	if (pctxt->redefCounter != 0) {
7818 	    xmlChar *str = NULL;
7819 
7820 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
7821 		XML_SCHEMAP_SRC_REDEFINE, node, NULL,
7822 		"The redefining attribute group definition "
7823 		"'%s' must not contain more than one "
7824 		"reference to the redefined definition",
7825 		xmlSchemaFormatQName(&str, refNs, ref), NULL);
7826 	    FREE_AND_NULL(str);
7827 	    return(NULL);
7828 	}
7829 	pctxt->redefCounter++;
7830 	/*
7831 	* URGENT TODO: How to ensure that the reference will not be
7832 	* handled by the normal component resolution mechanism?
7833 	*/
7834 	ret = xmlSchemaNewQNameRef(pctxt,
7835 	    XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7836 	if (ret == NULL)
7837 	    return(NULL);
7838 	ret->node = node;
7839 	pctxt->redef->reference = WXS_BASIC_CAST ret;
7840     } else {
7841 	/*
7842 	* Create a QName-reference helper component. We will substitute this
7843 	* component for the attribute uses of the referenced attribute group
7844 	* definition.
7845 	*/
7846 	ret = xmlSchemaNewQNameRef(pctxt,
7847 	    XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7848 	if (ret == NULL)
7849 	    return(NULL);
7850 	ret->node = node;
7851 	/* Add to pending items, to be able to resolve the reference. */
7852 	WXS_ADD_PENDING(pctxt, ret);
7853     }
7854     return (ret);
7855 }
7856 
7857 /**
7858  * xmlSchemaParseAttributeGroupDefinition:
7859  * @pctxt:  a schema validation context
7860  * @schema:  the schema being built
7861  * @node:  a subtree containing XML Schema information
7862  *
7863  * parse a XML schema Attribute Group declaration
7864  * *WARNING* this interface is highly subject to change
7865  *
7866  * Returns the attribute group definition or NULL in case of error.
7867  */
7868 static xmlSchemaAttributeGroupPtr
xmlSchemaParseAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node)7869 xmlSchemaParseAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
7870 				       xmlSchemaPtr schema,
7871 				       xmlNodePtr node)
7872 {
7873     const xmlChar *name;
7874     xmlSchemaAttributeGroupPtr ret;
7875     xmlNodePtr child = NULL;
7876     xmlAttrPtr attr;
7877     int hasRefs = 0;
7878 
7879     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7880         return (NULL);
7881 
7882     attr = xmlSchemaGetPropNode(node, "name");
7883     if (attr == NULL) {
7884 	xmlSchemaPMissingAttrErr(pctxt,
7885 	    XML_SCHEMAP_S4S_ATTR_MISSING,
7886 	    NULL, node, "name", NULL);
7887 	return (NULL);
7888     }
7889     /*
7890     * The name is crucial, exit if invalid.
7891     */
7892     if (xmlSchemaPValAttrNode(pctxt,
7893 	NULL, attr,
7894 	xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7895 	return (NULL);
7896     }
7897     ret = xmlSchemaAddAttributeGroupDefinition(pctxt, schema,
7898 	name, pctxt->targetNamespace, node);
7899     if (ret == NULL)
7900 	return (NULL);
7901     /*
7902     * Check for illegal attributes.
7903     */
7904     attr = node->properties;
7905     while (attr != NULL) {
7906 	if (attr->ns == NULL) {
7907 	    if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7908 		(!xmlStrEqual(attr->name, BAD_CAST "id")))
7909 	    {
7910 		xmlSchemaPIllegalAttrErr(pctxt,
7911 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7912 	    }
7913 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7914 	    xmlSchemaPIllegalAttrErr(pctxt,
7915 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7916 	}
7917 	attr = attr->next;
7918     }
7919     /* Attribute ID */
7920     xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7921     /*
7922     * And now for the children...
7923     */
7924     child = node->children;
7925     if (IS_SCHEMA(child, "annotation")) {
7926         ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7927         child = child->next;
7928     }
7929     /*
7930     * Parse contained attribute decls/refs.
7931     */
7932     if (xmlSchemaParseLocalAttributes(pctxt, schema, &child,
7933 	(xmlSchemaItemListPtr *) &(ret->attrUses),
7934 	XML_SCHEMA_TYPE_ATTRIBUTEGROUP, &hasRefs) == -1)
7935 	return(NULL);
7936     if (hasRefs)
7937 	ret->flags |= XML_SCHEMAS_ATTRGROUP_HAS_REFS;
7938     /*
7939     * Parse the attribute wildcard.
7940     */
7941     if (IS_SCHEMA(child, "anyAttribute")) {
7942 	ret->attributeWildcard = xmlSchemaParseAnyAttribute(pctxt,
7943 	    schema, child);
7944 	child = child->next;
7945     }
7946     if (child != NULL) {
7947 	xmlSchemaPContentErr(pctxt,
7948 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7949 	    NULL, node, child, NULL,
7950 	    "(annotation?, ((attribute | attributeGroup)*, anyAttribute?))");
7951     }
7952     return (ret);
7953 }
7954 
7955 /**
7956  * xmlSchemaPValAttrFormDefault:
7957  * @value:  the value
7958  * @flags: the flags to be modified
7959  * @flagQualified: the specific flag for "qualified"
7960  *
7961  * Returns 0 if the value is valid, 1 otherwise.
7962  */
7963 static int
xmlSchemaPValAttrFormDefault(const xmlChar * value,int * flags,int flagQualified)7964 xmlSchemaPValAttrFormDefault(const xmlChar *value,
7965 			     int *flags,
7966 			     int flagQualified)
7967 {
7968     if (xmlStrEqual(value, BAD_CAST "qualified")) {
7969 	if  ((*flags & flagQualified) == 0)
7970 	    *flags |= flagQualified;
7971     } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
7972 	return (1);
7973 
7974     return (0);
7975 }
7976 
7977 /**
7978  * xmlSchemaPValAttrBlockFinal:
7979  * @value:  the value
7980  * @flags: the flags to be modified
7981  * @flagAll: the specific flag for "#all"
7982  * @flagExtension: the specific flag for "extension"
7983  * @flagRestriction: the specific flag for "restriction"
7984  * @flagSubstitution: the specific flag for "substitution"
7985  * @flagList: the specific flag for "list"
7986  * @flagUnion: the specific flag for "union"
7987  *
7988  * Validates the value of the attribute "final" and "block". The value
7989  * is converted into the specified flag values and returned in @flags.
7990  *
7991  * Returns 0 if the value is valid, 1 otherwise.
7992  */
7993 
7994 static int
xmlSchemaPValAttrBlockFinal(const xmlChar * value,int * flags,int flagAll,int flagExtension,int flagRestriction,int flagSubstitution,int flagList,int flagUnion)7995 xmlSchemaPValAttrBlockFinal(const xmlChar *value,
7996 			    int *flags,
7997 			    int flagAll,
7998 			    int flagExtension,
7999 			    int flagRestriction,
8000 			    int flagSubstitution,
8001 			    int flagList,
8002 			    int flagUnion)
8003 {
8004     int ret = 0;
8005 
8006     /*
8007     * TODO: This does not check for duplicate entries.
8008     */
8009     if ((flags == NULL) || (value == NULL))
8010 	return (-1);
8011     if (value[0] == 0)
8012 	return (0);
8013     if (xmlStrEqual(value, BAD_CAST "#all")) {
8014 	if (flagAll != -1)
8015 	    *flags |= flagAll;
8016 	else {
8017 	    if (flagExtension != -1)
8018 		*flags |= flagExtension;
8019 	    if (flagRestriction != -1)
8020 		*flags |= flagRestriction;
8021 	    if (flagSubstitution != -1)
8022 		*flags |= flagSubstitution;
8023 	    if (flagList != -1)
8024 		*flags |= flagList;
8025 	    if (flagUnion != -1)
8026 		*flags |= flagUnion;
8027 	}
8028     } else {
8029 	const xmlChar *end, *cur = value;
8030 	xmlChar *item;
8031 
8032 	do {
8033 	    while (IS_BLANK_CH(*cur))
8034 		cur++;
8035 	    end = cur;
8036 	    while ((*end != 0) && (!(IS_BLANK_CH(*end))))
8037 		end++;
8038 	    if (end == cur)
8039 		break;
8040 	    item = xmlStrndup(cur, end - cur);
8041 	    if (xmlStrEqual(item, BAD_CAST "extension")) {
8042 		if (flagExtension != -1) {
8043 		    if ((*flags & flagExtension) == 0)
8044 			*flags |= flagExtension;
8045 		} else
8046 		    ret = 1;
8047 	    } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
8048 		if (flagRestriction != -1) {
8049 		    if ((*flags & flagRestriction) == 0)
8050 			*flags |= flagRestriction;
8051 		} else
8052 		    ret = 1;
8053 	    } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
8054 		if (flagSubstitution != -1) {
8055 		    if ((*flags & flagSubstitution) == 0)
8056 			*flags |= flagSubstitution;
8057 		} else
8058 		    ret = 1;
8059 	    } else if (xmlStrEqual(item, BAD_CAST "list")) {
8060 		if (flagList != -1) {
8061 		    if ((*flags & flagList) == 0)
8062 			*flags |= flagList;
8063 		} else
8064 		    ret = 1;
8065 	    } else if (xmlStrEqual(item, BAD_CAST "union")) {
8066 		if (flagUnion != -1) {
8067 		    if ((*flags & flagUnion) == 0)
8068 			*flags |= flagUnion;
8069 		} else
8070 		    ret = 1;
8071 	    } else
8072 		ret = 1;
8073 	    if (item != NULL)
8074 		xmlFree(item);
8075 	    cur = end;
8076 	} while ((ret == 0) && (*cur != 0));
8077     }
8078 
8079     return (ret);
8080 }
8081 
8082 static int
xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,xmlSchemaIDCPtr idc,xmlSchemaIDCSelectPtr selector,xmlAttrPtr attr,int isField)8083 xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
8084 			     xmlSchemaIDCPtr idc,
8085 			     xmlSchemaIDCSelectPtr selector,
8086 			     xmlAttrPtr attr,
8087 			     int isField)
8088 {
8089     xmlNodePtr node;
8090 
8091     /*
8092     * c-selector-xpath:
8093     * Schema Component Constraint: Selector Value OK
8094     *
8095     * TODO: 1 The {selector} must be a valid XPath expression, as defined
8096     * in [XPath].
8097     */
8098     if (selector == NULL) {
8099 	xmlSchemaPErr(ctxt, idc->node,
8100 	    XML_SCHEMAP_INTERNAL,
8101 	    "Internal error: xmlSchemaCheckCSelectorXPath, "
8102 	    "the selector is not specified.\n", NULL, NULL);
8103 	return (-1);
8104     }
8105     if (attr == NULL)
8106 	node = idc->node;
8107     else
8108 	node = (xmlNodePtr) attr;
8109     if (selector->xpath == NULL) {
8110 	xmlSchemaPCustomErr(ctxt,
8111 	    /* TODO: Adjust error code. */
8112 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8113 	    NULL, node,
8114 	    "The XPath expression of the selector is not valid", NULL);
8115 	return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
8116     } else {
8117 	const xmlChar **nsArray = NULL;
8118 	xmlNsPtr *nsList = NULL;
8119 	/*
8120 	* Compile the XPath expression.
8121 	*/
8122 	/*
8123 	* TODO: We need the array of in-scope namespaces for compilation.
8124 	* TODO: Call xmlPatterncompile with different options for selector/
8125 	* field.
8126 	*/
8127 	if (attr == NULL)
8128 	    nsList = NULL;
8129 	else
8130 	    nsList = xmlGetNsList(attr->doc, attr->parent);
8131 	/*
8132 	* Build an array of prefixes and namespaces.
8133 	*/
8134 	if (nsList != NULL) {
8135 	    int i, count = 0;
8136 
8137 	    for (i = 0; nsList[i] != NULL; i++)
8138 		count++;
8139 
8140 	    nsArray = (const xmlChar **) xmlMalloc(
8141 		(count * 2 + 1) * sizeof(const xmlChar *));
8142 	    if (nsArray == NULL) {
8143 		xmlSchemaPErrMemory(ctxt, "allocating a namespace array",
8144 		    NULL);
8145 		xmlFree(nsList);
8146 		return (-1);
8147 	    }
8148 	    for (i = 0; i < count; i++) {
8149 		nsArray[2 * i] = nsList[i]->href;
8150 		nsArray[2 * i + 1] = nsList[i]->prefix;
8151 	    }
8152 	    nsArray[count * 2] = NULL;
8153 	    xmlFree(nsList);
8154 	}
8155 	/*
8156 	* TODO: Differentiate between "selector" and "field".
8157 	*/
8158 	if (isField)
8159 	    selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
8160 		NULL, XML_PATTERN_XSFIELD, nsArray);
8161 	else
8162 	    selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
8163 		NULL, XML_PATTERN_XSSEL, nsArray);
8164 	if (nsArray != NULL)
8165 	    xmlFree((xmlChar **) nsArray);
8166 
8167 	if (selector->xpathComp == NULL) {
8168 	    xmlSchemaPCustomErr(ctxt,
8169 		/* TODO: Adjust error code? */
8170 		XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8171 		NULL, node,
8172 		"The XPath expression '%s' could not be "
8173 		"compiled", selector->xpath);
8174 	    return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
8175 	}
8176     }
8177     return (0);
8178 }
8179 
8180 #define ADD_ANNOTATION(annot)   \
8181     xmlSchemaAnnotPtr cur = item->annot; \
8182     if (item->annot == NULL) {  \
8183 	item->annot = annot;    \
8184 	return (annot);         \
8185     }                           \
8186     cur = item->annot;          \
8187     if (cur->next != NULL) {    \
8188 	cur = cur->next;	\
8189     }                           \
8190     cur->next = annot;
8191 
8192 /**
8193  * xmlSchemaAssignAnnotation:
8194  * @item: the schema component
8195  * @annot: the annotation
8196  *
8197  * Adds the annotation to the given schema component.
8198  *
8199  * Returns the given annotation.
8200  */
8201 static xmlSchemaAnnotPtr
xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem,xmlSchemaAnnotPtr annot)8202 xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem,
8203 		       xmlSchemaAnnotPtr annot)
8204 {
8205     if ((annItem == NULL) || (annot == NULL))
8206 	return (NULL);
8207     switch (annItem->type) {
8208 	case XML_SCHEMA_TYPE_ELEMENT: {
8209 		xmlSchemaElementPtr item = (xmlSchemaElementPtr) annItem;
8210 		ADD_ANNOTATION(annot)
8211 	    }
8212 	    break;
8213 	case XML_SCHEMA_TYPE_ATTRIBUTE: {
8214 		xmlSchemaAttributePtr item = (xmlSchemaAttributePtr) annItem;
8215 		ADD_ANNOTATION(annot)
8216 	    }
8217 	    break;
8218 	case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
8219 	case XML_SCHEMA_TYPE_ANY: {
8220 		xmlSchemaWildcardPtr item = (xmlSchemaWildcardPtr) annItem;
8221 		ADD_ANNOTATION(annot)
8222 	    }
8223 	    break;
8224 	case XML_SCHEMA_TYPE_PARTICLE:
8225 	case XML_SCHEMA_TYPE_IDC_KEY:
8226 	case XML_SCHEMA_TYPE_IDC_KEYREF:
8227 	case XML_SCHEMA_TYPE_IDC_UNIQUE: {
8228 		xmlSchemaAnnotItemPtr item = (xmlSchemaAnnotItemPtr) annItem;
8229 		ADD_ANNOTATION(annot)
8230 	    }
8231 	    break;
8232 	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: {
8233 		xmlSchemaAttributeGroupPtr item =
8234 		    (xmlSchemaAttributeGroupPtr) annItem;
8235 		ADD_ANNOTATION(annot)
8236 	    }
8237 	    break;
8238 	case XML_SCHEMA_TYPE_NOTATION: {
8239 		xmlSchemaNotationPtr item = (xmlSchemaNotationPtr) annItem;
8240 		ADD_ANNOTATION(annot)
8241 	    }
8242 	    break;
8243 	case XML_SCHEMA_FACET_MININCLUSIVE:
8244 	case XML_SCHEMA_FACET_MINEXCLUSIVE:
8245 	case XML_SCHEMA_FACET_MAXINCLUSIVE:
8246 	case XML_SCHEMA_FACET_MAXEXCLUSIVE:
8247 	case XML_SCHEMA_FACET_TOTALDIGITS:
8248 	case XML_SCHEMA_FACET_FRACTIONDIGITS:
8249 	case XML_SCHEMA_FACET_PATTERN:
8250 	case XML_SCHEMA_FACET_ENUMERATION:
8251 	case XML_SCHEMA_FACET_WHITESPACE:
8252 	case XML_SCHEMA_FACET_LENGTH:
8253 	case XML_SCHEMA_FACET_MAXLENGTH:
8254 	case XML_SCHEMA_FACET_MINLENGTH: {
8255 		xmlSchemaFacetPtr item = (xmlSchemaFacetPtr) annItem;
8256 		ADD_ANNOTATION(annot)
8257 	    }
8258 	    break;
8259 	case XML_SCHEMA_TYPE_SIMPLE:
8260 	case XML_SCHEMA_TYPE_COMPLEX: {
8261 		xmlSchemaTypePtr item = (xmlSchemaTypePtr) annItem;
8262 		ADD_ANNOTATION(annot)
8263 	    }
8264 	    break;
8265 	case XML_SCHEMA_TYPE_GROUP: {
8266 		xmlSchemaModelGroupDefPtr item = (xmlSchemaModelGroupDefPtr) annItem;
8267 		ADD_ANNOTATION(annot)
8268 	    }
8269 	    break;
8270 	case XML_SCHEMA_TYPE_SEQUENCE:
8271 	case XML_SCHEMA_TYPE_CHOICE:
8272 	case XML_SCHEMA_TYPE_ALL: {
8273 		xmlSchemaModelGroupPtr item = (xmlSchemaModelGroupPtr) annItem;
8274 		ADD_ANNOTATION(annot)
8275 	    }
8276 	    break;
8277 	default:
8278 	     xmlSchemaPCustomErr(NULL,
8279 		XML_SCHEMAP_INTERNAL,
8280 		NULL, NULL,
8281 		"Internal error: xmlSchemaAddAnnotation, "
8282 		"The item is not a annotated schema component", NULL);
8283 	     break;
8284     }
8285     return (annot);
8286 }
8287 
8288 /**
8289  * xmlSchemaParseIDCSelectorAndField:
8290  * @ctxt:  a schema validation context
8291  * @schema:  the schema being built
8292  * @node:  a subtree containing XML Schema information
8293  *
8294  * Parses a XML Schema identity-constraint definition's
8295  * <selector> and <field> elements.
8296  *
8297  * Returns the parsed identity-constraint definition.
8298  */
8299 static xmlSchemaIDCSelectPtr
xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,xmlSchemaIDCPtr idc,xmlNodePtr node,int isField)8300 xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
8301 			  xmlSchemaIDCPtr idc,
8302 			  xmlNodePtr node,
8303 			  int isField)
8304 {
8305     xmlSchemaIDCSelectPtr item;
8306     xmlNodePtr child = NULL;
8307     xmlAttrPtr attr;
8308 
8309     /*
8310     * Check for illegal attributes.
8311     */
8312     attr = node->properties;
8313     while (attr != NULL) {
8314 	if (attr->ns == NULL) {
8315 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8316 		(!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
8317 		xmlSchemaPIllegalAttrErr(ctxt,
8318 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8319 	    }
8320 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8321 	    xmlSchemaPIllegalAttrErr(ctxt,
8322 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8323 	}
8324 	attr = attr->next;
8325     }
8326     /*
8327     * Create the item.
8328     */
8329     item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
8330     if (item == NULL) {
8331         xmlSchemaPErrMemory(ctxt,
8332 	    "allocating a 'selector' of an identity-constraint definition",
8333 	    NULL);
8334         return (NULL);
8335     }
8336     memset(item, 0, sizeof(xmlSchemaIDCSelect));
8337     /*
8338     * Attribute "xpath" (mandatory).
8339     */
8340     attr = xmlSchemaGetPropNode(node, "xpath");
8341     if (attr == NULL) {
8342 	xmlSchemaPMissingAttrErr(ctxt,
8343 	    XML_SCHEMAP_S4S_ATTR_MISSING,
8344 	    NULL, node,
8345 	    "name", NULL);
8346     } else {
8347 	item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8348 	/*
8349 	* URGENT TODO: "field"s have an other syntax than "selector"s.
8350 	*/
8351 
8352 	if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr,
8353 	    isField) == -1) {
8354 	    xmlSchemaPErr(ctxt,
8355 		(xmlNodePtr) attr,
8356 		XML_SCHEMAP_INTERNAL,
8357 		"Internal error: xmlSchemaParseIDCSelectorAndField, "
8358 		"validating the XPath expression of a IDC selector.\n",
8359 		NULL, NULL);
8360 	}
8361 
8362     }
8363     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8364     /*
8365     * And now for the children...
8366     */
8367     child = node->children;
8368     if (IS_SCHEMA(child, "annotation")) {
8369 	/*
8370 	* Add the annotation to the parent IDC.
8371 	*/
8372 	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) idc,
8373 	    xmlSchemaParseAnnotation(ctxt, child, 1));
8374 	child = child->next;
8375     }
8376     if (child != NULL) {
8377 	xmlSchemaPContentErr(ctxt,
8378 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8379 	    NULL, node, child,
8380 	    NULL, "(annotation?)");
8381     }
8382 
8383     return (item);
8384 }
8385 
8386 /**
8387  * xmlSchemaParseIDC:
8388  * @ctxt:  a schema validation context
8389  * @schema:  the schema being built
8390  * @node:  a subtree containing XML Schema information
8391  *
8392  * Parses a XML Schema identity-constraint definition.
8393  *
8394  * Returns the parsed identity-constraint definition.
8395  */
8396 static xmlSchemaIDCPtr
xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,xmlSchemaTypeType idcCategory,const xmlChar * targetNamespace)8397 xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
8398 		  xmlSchemaPtr schema,
8399 		  xmlNodePtr node,
8400 		  xmlSchemaTypeType idcCategory,
8401 		  const xmlChar *targetNamespace)
8402 {
8403     xmlSchemaIDCPtr item = NULL;
8404     xmlNodePtr child = NULL;
8405     xmlAttrPtr attr;
8406     const xmlChar *name = NULL;
8407     xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
8408 
8409     /*
8410     * Check for illegal attributes.
8411     */
8412     attr = node->properties;
8413     while (attr != NULL) {
8414 	if (attr->ns == NULL) {
8415 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8416 		(!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8417 		((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
8418 		 (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
8419 		xmlSchemaPIllegalAttrErr(ctxt,
8420 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8421 	    }
8422 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8423 	    xmlSchemaPIllegalAttrErr(ctxt,
8424 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8425 	}
8426 	attr = attr->next;
8427     }
8428     /*
8429     * Attribute "name" (mandatory).
8430     */
8431     attr = xmlSchemaGetPropNode(node, "name");
8432     if (attr == NULL) {
8433 	xmlSchemaPMissingAttrErr(ctxt,
8434 	    XML_SCHEMAP_S4S_ATTR_MISSING,
8435 	    NULL, node,
8436 	    "name", NULL);
8437 	return (NULL);
8438     } else if (xmlSchemaPValAttrNode(ctxt,
8439 	NULL, attr,
8440 	xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
8441 	return (NULL);
8442     }
8443     /* Create the component. */
8444     item = xmlSchemaAddIDC(ctxt, schema, name, targetNamespace,
8445 	idcCategory, node);
8446     if (item == NULL)
8447 	return(NULL);
8448 
8449     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8450     if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
8451 	/*
8452 	* Attribute "refer" (mandatory).
8453 	*/
8454 	attr = xmlSchemaGetPropNode(node, "refer");
8455 	if (attr == NULL) {
8456 	    xmlSchemaPMissingAttrErr(ctxt,
8457 		XML_SCHEMAP_S4S_ATTR_MISSING,
8458 		NULL, node,
8459 		"refer", NULL);
8460 	} else {
8461 	    /*
8462 	    * Create a reference item.
8463 	    */
8464 	    item->ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_IDC_KEY,
8465 		NULL, NULL);
8466 	    if (item->ref == NULL)
8467 		return (NULL);
8468 	    xmlSchemaPValAttrNodeQName(ctxt, schema,
8469 		NULL, attr,
8470 		&(item->ref->targetNamespace),
8471 		&(item->ref->name));
8472 	    xmlSchemaCheckReference(ctxt, schema, node, attr,
8473 		item->ref->targetNamespace);
8474 	}
8475     }
8476     /*
8477     * And now for the children...
8478     */
8479     child = node->children;
8480     if (IS_SCHEMA(child, "annotation")) {
8481 	item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
8482 	child = child->next;
8483     }
8484     if (child == NULL) {
8485 	xmlSchemaPContentErr(ctxt,
8486 		XML_SCHEMAP_S4S_ELEM_MISSING,
8487 		NULL, node, child,
8488 		"A child element is missing",
8489 		"(annotation?, (selector, field+))");
8490     }
8491     /*
8492     * Child element <selector>.
8493     */
8494     if (IS_SCHEMA(child, "selector")) {
8495 	item->selector = xmlSchemaParseIDCSelectorAndField(ctxt,
8496 	    item, child, 0);
8497 	child = child->next;
8498 	/*
8499 	* Child elements <field>.
8500 	*/
8501 	if (IS_SCHEMA(child, "field")) {
8502 	    do {
8503 		field = xmlSchemaParseIDCSelectorAndField(ctxt,
8504 		    item, child, 1);
8505 		if (field != NULL) {
8506 		    field->index = item->nbFields;
8507 		    item->nbFields++;
8508 		    if (lastField != NULL)
8509 			lastField->next = field;
8510 		    else
8511 			item->fields = field;
8512 		    lastField = field;
8513 		}
8514 		child = child->next;
8515 	    } while (IS_SCHEMA(child, "field"));
8516 	} else {
8517 	    xmlSchemaPContentErr(ctxt,
8518 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8519 		NULL, node, child,
8520 		NULL, "(annotation?, (selector, field+))");
8521 	}
8522     }
8523     if (child != NULL) {
8524 	xmlSchemaPContentErr(ctxt,
8525 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8526 	    NULL, node, child,
8527 	    NULL, "(annotation?, (selector, field+))");
8528     }
8529 
8530     return (item);
8531 }
8532 
8533 /**
8534  * xmlSchemaParseElement:
8535  * @ctxt:  a schema validation context
8536  * @schema:  the schema being built
8537  * @node:  a subtree containing XML Schema information
8538  * @topLevel: indicates if this is global declaration
8539  *
8540  * Parses a XML schema element declaration.
8541  * *WARNING* this interface is highly subject to change
8542  *
8543  * Returns the element declaration or a particle; NULL in case
8544  * of an error or if the particle has minOccurs==maxOccurs==0.
8545  */
8546 static xmlSchemaBasicItemPtr
xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,int * isElemRef,int topLevel)8547 xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
8548                       xmlNodePtr node, int *isElemRef, int topLevel)
8549 {
8550     xmlSchemaElementPtr decl = NULL;
8551     xmlSchemaParticlePtr particle = NULL;
8552     xmlSchemaAnnotPtr annot = NULL;
8553     xmlNodePtr child = NULL;
8554     xmlAttrPtr attr, nameAttr;
8555     int min, max, isRef = 0;
8556     xmlChar *des = NULL;
8557 
8558     /* 3.3.3 Constraints on XML Representations of Element Declarations */
8559     /* TODO: Complete implementation of 3.3.6 */
8560 
8561     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8562         return (NULL);
8563 
8564     if (isElemRef != NULL)
8565 	*isElemRef = 0;
8566     /*
8567     * If we get a "ref" attribute on a local <element> we will assume it's
8568     * a reference - even if there's a "name" attribute; this seems to be more
8569     * robust.
8570     */
8571     nameAttr = xmlSchemaGetPropNode(node, "name");
8572     attr = xmlSchemaGetPropNode(node, "ref");
8573     if ((topLevel) || (attr == NULL)) {
8574 	if (nameAttr == NULL) {
8575 	    xmlSchemaPMissingAttrErr(ctxt,
8576 		XML_SCHEMAP_S4S_ATTR_MISSING,
8577 		NULL, node, "name", NULL);
8578 	    return (NULL);
8579 	}
8580     } else
8581 	isRef = 1;
8582 
8583     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8584     child = node->children;
8585     if (IS_SCHEMA(child, "annotation")) {
8586 	annot = xmlSchemaParseAnnotation(ctxt, child, 1);
8587 	child = child->next;
8588     }
8589     /*
8590     * Skip particle part if a global declaration.
8591     */
8592     if (topLevel)
8593 	goto declaration_part;
8594     /*
8595     * The particle part ==================================================
8596     */
8597     min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
8598     max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(xs:nonNegativeInteger | unbounded)");
8599     xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
8600     particle = xmlSchemaAddParticle(ctxt, node, min, max);
8601     if (particle == NULL)
8602 	goto return_null;
8603 
8604     /* ret->flags |= XML_SCHEMAS_ELEM_REF; */
8605 
8606     if (isRef) {
8607 	const xmlChar *refNs = NULL, *ref = NULL;
8608 	xmlSchemaQNameRefPtr refer = NULL;
8609 	/*
8610 	* The reference part =============================================
8611 	*/
8612 	if (isElemRef != NULL)
8613 	    *isElemRef = 1;
8614 
8615 	xmlSchemaPValAttrNodeQName(ctxt, schema,
8616 	    NULL, attr, &refNs, &ref);
8617 	xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
8618 	/*
8619 	* SPEC (3.3.3 : 2.1) "One of ref or name must be present, but not both"
8620 	*/
8621 	if (nameAttr != NULL) {
8622 	    xmlSchemaPMutualExclAttrErr(ctxt,
8623 		XML_SCHEMAP_SRC_ELEMENT_2_1, NULL, nameAttr, "ref", "name");
8624 	}
8625 	/*
8626 	* Check for illegal attributes.
8627 	*/
8628 	attr = node->properties;
8629 	while (attr != NULL) {
8630 	    if (attr->ns == NULL) {
8631 		if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
8632 		    xmlStrEqual(attr->name, BAD_CAST "name") ||
8633 		    xmlStrEqual(attr->name, BAD_CAST "id") ||
8634 		    xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
8635 		    xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
8636 		{
8637 		    attr = attr->next;
8638 		    continue;
8639 		} else {
8640 		    /* SPEC (3.3.3 : 2.2) */
8641 		    xmlSchemaPCustomAttrErr(ctxt,
8642 			XML_SCHEMAP_SRC_ELEMENT_2_2,
8643 			NULL, NULL, attr,
8644 			"Only the attributes 'minOccurs', 'maxOccurs' and "
8645 			"'id' are allowed in addition to 'ref'");
8646 		    break;
8647 		}
8648 	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8649 		xmlSchemaPIllegalAttrErr(ctxt,
8650 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8651 	    }
8652 	    attr = attr->next;
8653 	}
8654 	/*
8655 	* No children except <annotation> expected.
8656 	*/
8657 	if (child != NULL) {
8658 	    xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8659 		NULL, node, child, NULL, "(annotation?)");
8660 	}
8661 	if ((min == 0) && (max == 0))
8662 	    goto return_null;
8663 	/*
8664 	* Create the reference item and attach it to the particle.
8665 	*/
8666 	refer = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_ELEMENT,
8667 	    ref, refNs);
8668 	if (refer == NULL)
8669 	    goto return_null;
8670 	particle->children = (xmlSchemaTreeItemPtr) refer;
8671 	particle->annot = annot;
8672 	/*
8673 	* Add the particle to pending components, since the reference
8674 	* need to be resolved.
8675 	*/
8676 	WXS_ADD_PENDING(ctxt, particle);
8677 	return ((xmlSchemaBasicItemPtr) particle);
8678     }
8679     /*
8680     * The declaration part ===============================================
8681     */
8682 declaration_part:
8683     {
8684 	const xmlChar *ns = NULL, *fixed, *name, *attrValue;
8685 	xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;
8686 
8687 	if (xmlSchemaPValAttrNode(ctxt, NULL, nameAttr,
8688 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
8689 	    goto return_null;
8690 	/*
8691 	* Evaluate the target namespace.
8692 	*/
8693 	if (topLevel) {
8694 	    ns = ctxt->targetNamespace;
8695 	} else {
8696 	    attr = xmlSchemaGetPropNode(node, "form");
8697 	    if (attr != NULL) {
8698 		attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8699 		if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
8700 		    ns = ctxt->targetNamespace;
8701 		} else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
8702 		    xmlSchemaPSimpleTypeErr(ctxt,
8703 			XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8704 			NULL, (xmlNodePtr) attr,
8705 			NULL, "(qualified | unqualified)",
8706 			attrValue, NULL, NULL, NULL);
8707 		}
8708 	    } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
8709 		ns = ctxt->targetNamespace;
8710 	}
8711 	decl = xmlSchemaAddElement(ctxt, name, ns, node, topLevel);
8712 	if (decl == NULL) {
8713 	    goto return_null;
8714 	}
8715 	/*
8716 	* Check for illegal attributes.
8717 	*/
8718 	attr = node->properties;
8719 	while (attr != NULL) {
8720 	    if (attr->ns == NULL) {
8721 		if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8722 		    (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
8723 		    (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8724 		    (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
8725 		    (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
8726 		    (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
8727 		    (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
8728 		{
8729 		    if (topLevel == 0) {
8730 			if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
8731 			    (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
8732 			    (!xmlStrEqual(attr->name, BAD_CAST "form")))
8733 			{
8734 			    xmlSchemaPIllegalAttrErr(ctxt,
8735 				XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8736 			}
8737 		    } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
8738 			(!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
8739 			(!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
8740 
8741 			xmlSchemaPIllegalAttrErr(ctxt,
8742 			    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8743 		    }
8744 		}
8745 	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8746 
8747 		xmlSchemaPIllegalAttrErr(ctxt,
8748 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8749 	    }
8750 	    attr = attr->next;
8751 	}
8752 	/*
8753 	* Extract/validate attributes.
8754 	*/
8755 	if (topLevel) {
8756 	    /*
8757 	    * Process top attributes of global element declarations here.
8758 	    */
8759 	    decl->flags |= XML_SCHEMAS_ELEM_GLOBAL;
8760 	    decl->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
8761 	    xmlSchemaPValAttrQName(ctxt, schema,
8762 		NULL, node, "substitutionGroup",
8763 		&(decl->substGroupNs), &(decl->substGroup));
8764 	    if (xmlGetBooleanProp(ctxt, node, "abstract", 0))
8765 		decl->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
8766 	    /*
8767 	    * Attribute "final".
8768 	    */
8769 	    attr = xmlSchemaGetPropNode(node, "final");
8770 	    if (attr == NULL) {
8771 		if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
8772 		    decl->flags |= XML_SCHEMAS_ELEM_FINAL_EXTENSION;
8773 		if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8774 		    decl->flags |= XML_SCHEMAS_ELEM_FINAL_RESTRICTION;
8775 	    } else {
8776 		attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8777 		if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
8778 		    -1,
8779 		    XML_SCHEMAS_ELEM_FINAL_EXTENSION,
8780 		    XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
8781 		    xmlSchemaPSimpleTypeErr(ctxt,
8782 			XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8783 			NULL, (xmlNodePtr) attr,
8784 			NULL, "(#all | List of (extension | restriction))",
8785 			attrValue, NULL, NULL, NULL);
8786 		}
8787 	    }
8788 	}
8789 	/*
8790 	* Attribute "block".
8791 	*/
8792 	attr = xmlSchemaGetPropNode(node, "block");
8793 	if (attr == NULL) {
8794 	    /*
8795 	    * Apply default "block" values.
8796 	    */
8797 	    if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
8798 		decl->flags |= XML_SCHEMAS_ELEM_BLOCK_RESTRICTION;
8799 	    if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
8800 		decl->flags |= XML_SCHEMAS_ELEM_BLOCK_EXTENSION;
8801 	    if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
8802 		decl->flags |= XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION;
8803 	} else {
8804 	    attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8805 	    if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
8806 		-1,
8807 		XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
8808 		XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
8809 		XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
8810 		xmlSchemaPSimpleTypeErr(ctxt,
8811 		    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8812 		    NULL, (xmlNodePtr) attr,
8813 		    NULL, "(#all | List of (extension | "
8814 		    "restriction | substitution))", attrValue,
8815 		    NULL, NULL, NULL);
8816 	    }
8817 	}
8818 	if (xmlGetBooleanProp(ctxt, node, "nillable", 0))
8819 	    decl->flags |= XML_SCHEMAS_ELEM_NILLABLE;
8820 
8821 	attr = xmlSchemaGetPropNode(node, "type");
8822 	if (attr != NULL) {
8823 	    xmlSchemaPValAttrNodeQName(ctxt, schema,
8824 		NULL, attr,
8825 		&(decl->namedTypeNs), &(decl->namedType));
8826 	    xmlSchemaCheckReference(ctxt, schema, node,
8827 		attr, decl->namedTypeNs);
8828 	}
8829 	decl->value = xmlSchemaGetProp(ctxt, node, "default");
8830 	attr = xmlSchemaGetPropNode(node, "fixed");
8831 	if (attr != NULL) {
8832 	    fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8833 	    if (decl->value != NULL) {
8834 		/*
8835 		* 3.3.3 : 1
8836 		* default and fixed must not both be present.
8837 		*/
8838 		xmlSchemaPMutualExclAttrErr(ctxt,
8839 		    XML_SCHEMAP_SRC_ELEMENT_1,
8840 		    NULL, attr, "default", "fixed");
8841 	    } else {
8842 		decl->flags |= XML_SCHEMAS_ELEM_FIXED;
8843 		decl->value = fixed;
8844 	    }
8845 	}
8846 	/*
8847 	* And now for the children...
8848 	*/
8849 	if (IS_SCHEMA(child, "complexType")) {
8850 	    /*
8851 	    * 3.3.3 : 3
8852 	    * "type" and either <simpleType> or <complexType> are mutually
8853 	    * exclusive
8854 	    */
8855 	    if (decl->namedType != NULL) {
8856 		xmlSchemaPContentErr(ctxt,
8857 		    XML_SCHEMAP_SRC_ELEMENT_3,
8858 		    NULL, node, child,
8859 		    "The attribute 'type' and the <complexType> child are "
8860 		    "mutually exclusive", NULL);
8861 	    } else
8862 		WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseComplexType(ctxt, schema, child, 0);
8863 	    child = child->next;
8864 	} else if (IS_SCHEMA(child, "simpleType")) {
8865 	    /*
8866 	    * 3.3.3 : 3
8867 	    * "type" and either <simpleType> or <complexType> are
8868 	    * mutually exclusive
8869 	    */
8870 	    if (decl->namedType != NULL) {
8871 		xmlSchemaPContentErr(ctxt,
8872 		    XML_SCHEMAP_SRC_ELEMENT_3,
8873 		    NULL, node, child,
8874 		    "The attribute 'type' and the <simpleType> child are "
8875 		    "mutually exclusive", NULL);
8876 	    } else
8877 		WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8878 	    child = child->next;
8879 	}
8880 	while ((IS_SCHEMA(child, "unique")) ||
8881 	    (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
8882 	    if (IS_SCHEMA(child, "unique")) {
8883 		curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8884 		    XML_SCHEMA_TYPE_IDC_UNIQUE, decl->targetNamespace);
8885 	    } else if (IS_SCHEMA(child, "key")) {
8886 		curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8887 		    XML_SCHEMA_TYPE_IDC_KEY, decl->targetNamespace);
8888 	    } else if (IS_SCHEMA(child, "keyref")) {
8889 		curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8890 		    XML_SCHEMA_TYPE_IDC_KEYREF, decl->targetNamespace);
8891 	    }
8892 	    if (lastIDC != NULL)
8893 		lastIDC->next = curIDC;
8894 	    else
8895 		decl->idcs = (void *) curIDC;
8896 	    lastIDC = curIDC;
8897 	    child = child->next;
8898 	}
8899 	if (child != NULL) {
8900 	    xmlSchemaPContentErr(ctxt,
8901 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8902 		NULL, node, child,
8903 		NULL, "(annotation?, ((simpleType | complexType)?, "
8904 		"(unique | key | keyref)*))");
8905 	}
8906 	decl->annot = annot;
8907     }
8908     /*
8909     * NOTE: Element Declaration Representation OK 4. will be checked at a
8910     * different layer.
8911     */
8912     FREE_AND_NULL(des)
8913     if (topLevel)
8914 	return ((xmlSchemaBasicItemPtr) decl);
8915     else {
8916 	particle->children = (xmlSchemaTreeItemPtr) decl;
8917 	return ((xmlSchemaBasicItemPtr) particle);
8918     }
8919 
8920 return_null:
8921     FREE_AND_NULL(des);
8922     if (annot != NULL) {
8923 	if (particle != NULL)
8924 	    particle->annot = NULL;
8925 	if (decl != NULL)
8926 	    decl->annot = NULL;
8927 	xmlSchemaFreeAnnot(annot);
8928     }
8929     return (NULL);
8930 }
8931 
8932 /**
8933  * xmlSchemaParseUnion:
8934  * @ctxt:  a schema validation context
8935  * @schema:  the schema being built
8936  * @node:  a subtree containing XML Schema information
8937  *
8938  * parse a XML schema Union definition
8939  * *WARNING* this interface is highly subject to change
8940  *
8941  * Returns -1 in case of internal error, 0 in case of success and a positive
8942  * error code otherwise.
8943  */
8944 static int
xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)8945 xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
8946                     xmlNodePtr node)
8947 {
8948     xmlSchemaTypePtr type;
8949     xmlNodePtr child = NULL;
8950     xmlAttrPtr attr;
8951     const xmlChar *cur = NULL;
8952 
8953     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8954         return (-1);
8955     /* Not a component, don't create it. */
8956     type = ctxt->ctxtType;
8957     /*
8958     * Mark the simple type as being of variety "union".
8959     */
8960     type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
8961     /*
8962     * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
8963     * then the `simple ur-type definition`."
8964     */
8965     type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
8966     /*
8967     * Check for illegal attributes.
8968     */
8969     attr = node->properties;
8970     while (attr != NULL) {
8971 	if (attr->ns == NULL) {
8972 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8973 		(!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
8974 		xmlSchemaPIllegalAttrErr(ctxt,
8975 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8976 	    }
8977 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8978 	    xmlSchemaPIllegalAttrErr(ctxt,
8979 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8980 	}
8981 	attr = attr->next;
8982     }
8983     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8984     /*
8985     * Attribute "memberTypes". This is a list of QNames.
8986     * TODO: Check the value to contain anything.
8987     */
8988     attr = xmlSchemaGetPropNode(node, "memberTypes");
8989     if (attr != NULL) {
8990 	const xmlChar *end;
8991 	xmlChar *tmp;
8992 	const xmlChar *localName, *nsName;
8993 	xmlSchemaTypeLinkPtr link, lastLink = NULL;
8994 	xmlSchemaQNameRefPtr ref;
8995 
8996 	cur = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8997 	type->base = cur;
8998 	do {
8999 	    while (IS_BLANK_CH(*cur))
9000 		cur++;
9001 	    end = cur;
9002 	    while ((*end != 0) && (!(IS_BLANK_CH(*end))))
9003 		end++;
9004 	    if (end == cur)
9005 		break;
9006 	    tmp = xmlStrndup(cur, end - cur);
9007 	    if (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
9008 		NULL, attr, BAD_CAST tmp, &nsName, &localName) == 0) {
9009 		/*
9010 		* Create the member type link.
9011 		*/
9012 		link = (xmlSchemaTypeLinkPtr)
9013 		    xmlMalloc(sizeof(xmlSchemaTypeLink));
9014 		if (link == NULL) {
9015 		    xmlSchemaPErrMemory(ctxt, "xmlSchemaParseUnion, "
9016 			"allocating a type link", NULL);
9017 		    return (-1);
9018 		}
9019 		link->type = NULL;
9020 		link->next = NULL;
9021 		if (lastLink == NULL)
9022 		    type->memberTypes = link;
9023 		else
9024 		    lastLink->next = link;
9025 		lastLink = link;
9026 		/*
9027 		* Create a reference item.
9028 		*/
9029 		ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_SIMPLE,
9030 		    localName, nsName);
9031 		if (ref == NULL) {
9032 		    FREE_AND_NULL(tmp)
9033 		    return (-1);
9034 		}
9035 		/*
9036 		* Assign the reference to the link, it will be resolved
9037 		* later during fixup of the union simple type.
9038 		*/
9039 		link->type = (xmlSchemaTypePtr) ref;
9040 	    }
9041 	    FREE_AND_NULL(tmp)
9042 	    cur = end;
9043 	} while (*cur != 0);
9044 
9045     }
9046     /*
9047     * And now for the children...
9048     */
9049     child = node->children;
9050     if (IS_SCHEMA(child, "annotation")) {
9051 	/*
9052 	* Add the annotation to the simple type ancestor.
9053 	*/
9054 	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
9055 	    xmlSchemaParseAnnotation(ctxt, child, 1));
9056         child = child->next;
9057     }
9058     if (IS_SCHEMA(child, "simpleType")) {
9059 	xmlSchemaTypePtr subtype, last = NULL;
9060 
9061 	/*
9062 	* Anchor the member types in the "subtypes" field of the
9063 	* simple type.
9064 	*/
9065 	while (IS_SCHEMA(child, "simpleType")) {
9066 	    subtype = (xmlSchemaTypePtr)
9067 		xmlSchemaParseSimpleType(ctxt, schema, child, 0);
9068 	    if (subtype != NULL) {
9069 		if (last == NULL) {
9070 		    type->subtypes = subtype;
9071 		    last = subtype;
9072 		} else {
9073 		    last->next = subtype;
9074 		    last = subtype;
9075 		}
9076 		last->next = NULL;
9077 	    }
9078 	    child = child->next;
9079 	}
9080     }
9081     if (child != NULL) {
9082 	xmlSchemaPContentErr(ctxt,
9083 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9084 	    NULL, node, child, NULL, "(annotation?, simpleType*)");
9085     }
9086     if ((attr == NULL) && (type->subtypes == NULL)) {
9087 	 /*
9088 	* src-union-memberTypes-or-simpleTypes
9089 	* Either the memberTypes [attribute] of the <union> element must
9090 	* be non-empty or there must be at least one simpleType [child].
9091 	*/
9092 	xmlSchemaPCustomErr(ctxt,
9093 	    XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
9094 	    NULL, node,
9095 	    "Either the attribute 'memberTypes' or "
9096 	    "at least one <simpleType> child must be present", NULL);
9097     }
9098     return (0);
9099 }
9100 
9101 /**
9102  * xmlSchemaParseList:
9103  * @ctxt:  a schema validation context
9104  * @schema:  the schema being built
9105  * @node:  a subtree containing XML Schema information
9106  *
9107  * parse a XML schema List definition
9108  * *WARNING* this interface is highly subject to change
9109  *
9110  * Returns -1 in case of error, 0 if the declaration is improper and
9111  *         1 in case of success.
9112  */
9113 static xmlSchemaTypePtr
xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)9114 xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9115                    xmlNodePtr node)
9116 {
9117     xmlSchemaTypePtr type;
9118     xmlNodePtr child = NULL;
9119     xmlAttrPtr attr;
9120 
9121     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9122         return (NULL);
9123     /* Not a component, don't create it. */
9124     type = ctxt->ctxtType;
9125     /*
9126     * Mark the type as being of variety "list".
9127     */
9128     type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
9129     /*
9130     * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
9131     * then the `simple ur-type definition`."
9132     */
9133     type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
9134     /*
9135     * Check for illegal attributes.
9136     */
9137     attr = node->properties;
9138     while (attr != NULL) {
9139 	if (attr->ns == NULL) {
9140 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9141 		(!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
9142 		xmlSchemaPIllegalAttrErr(ctxt,
9143 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9144 	    }
9145 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9146 	    xmlSchemaPIllegalAttrErr(ctxt,
9147 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9148 	}
9149 	attr = attr->next;
9150     }
9151 
9152     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9153 
9154     /*
9155     * Attribute "itemType". NOTE that we will use the "ref" and "refNs"
9156     * fields for holding the reference to the itemType.
9157     *
9158     * REVAMP TODO: Use the "base" and "baseNs" fields, since we will remove
9159     * the "ref" fields.
9160     */
9161     xmlSchemaPValAttrQName(ctxt, schema, NULL,
9162 	node, "itemType", &(type->baseNs), &(type->base));
9163     /*
9164     * And now for the children...
9165     */
9166     child = node->children;
9167     if (IS_SCHEMA(child, "annotation")) {
9168 	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
9169 	    xmlSchemaParseAnnotation(ctxt, child, 1));
9170         child = child->next;
9171     }
9172     if (IS_SCHEMA(child, "simpleType")) {
9173 	/*
9174 	* src-list-itemType-or-simpleType
9175 	* Either the itemType [attribute] or the <simpleType> [child] of
9176 	* the <list> element must be present, but not both.
9177 	*/
9178 	if (type->base != NULL) {
9179 	    xmlSchemaPCustomErr(ctxt,
9180 		XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9181 		NULL, node,
9182 		"The attribute 'itemType' and the <simpleType> child "
9183 		"are mutually exclusive", NULL);
9184 	} else {
9185 	    type->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
9186 	}
9187         child = child->next;
9188     } else if (type->base == NULL) {
9189 	xmlSchemaPCustomErr(ctxt,
9190 	    XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9191 	    NULL, node,
9192 	    "Either the attribute 'itemType' or the <simpleType> child "
9193 	    "must be present", NULL);
9194     }
9195     if (child != NULL) {
9196 	xmlSchemaPContentErr(ctxt,
9197 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9198 	    NULL, node, child, NULL, "(annotation?, simpleType?)");
9199     }
9200     if ((type->base == NULL) &&
9201 	(type->subtypes == NULL) &&
9202 	(xmlSchemaGetPropNode(node, "itemType") == NULL)) {
9203 	xmlSchemaPCustomErr(ctxt,
9204 	    XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9205 	    NULL, node,
9206 	    "Either the attribute 'itemType' or the <simpleType> child "
9207 	    "must be present", NULL);
9208     }
9209     return (NULL);
9210 }
9211 
9212 /**
9213  * xmlSchemaParseSimpleType:
9214  * @ctxt:  a schema validation context
9215  * @schema:  the schema being built
9216  * @node:  a subtree containing XML Schema information
9217  *
9218  * parse a XML schema Simple Type definition
9219  * *WARNING* this interface is highly subject to change
9220  *
9221  * Returns -1 in case of error, 0 if the declaration is improper and
9222  * 1 in case of success.
9223  */
9224 static xmlSchemaTypePtr
xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,int topLevel)9225 xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9226                          xmlNodePtr node, int topLevel)
9227 {
9228     xmlSchemaTypePtr type, oldCtxtType;
9229     xmlNodePtr child = NULL;
9230     const xmlChar *attrValue = NULL;
9231     xmlAttrPtr attr;
9232     int hasRestriction = 0;
9233 
9234     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9235         return (NULL);
9236 
9237     if (topLevel) {
9238 	attr = xmlSchemaGetPropNode(node, "name");
9239 	if (attr == NULL) {
9240 	    xmlSchemaPMissingAttrErr(ctxt,
9241 		XML_SCHEMAP_S4S_ATTR_MISSING,
9242 		NULL, node,
9243 		"name", NULL);
9244 	    return (NULL);
9245 	} else {
9246 	    if (xmlSchemaPValAttrNode(ctxt,
9247 		NULL, attr,
9248 		xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0)
9249 		return (NULL);
9250 	    /*
9251 	    * Skip built-in types.
9252 	    */
9253 	    if (ctxt->isS4S) {
9254 		xmlSchemaTypePtr biType;
9255 
9256 		if (ctxt->isRedefine) {
9257 		    /*
9258 		    * REDEFINE: Disallow redefinition of built-in-types.
9259 		    * TODO: It seems that the spec does not say anything
9260 		    * about this case.
9261 		    */
9262 		    xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
9263 			NULL, node,
9264 			"Redefinition of built-in simple types is not "
9265 			"supported", NULL);
9266 		    return(NULL);
9267 		}
9268 		biType = xmlSchemaGetPredefinedType(attrValue, xmlSchemaNs);
9269 		if (biType != NULL)
9270 		    return (biType);
9271 	    }
9272 	}
9273     }
9274     /*
9275     * TargetNamespace:
9276     * SPEC "The `actual value` of the targetNamespace [attribute]
9277     * of the <schema> ancestor element information item if present,
9278     * otherwise `absent`.
9279     */
9280     if (topLevel == 0) {
9281 #ifdef ENABLE_NAMED_LOCALS
9282         char buf[40];
9283 #endif
9284 	/*
9285 	* Parse as local simple type definition.
9286 	*/
9287 #ifdef ENABLE_NAMED_LOCALS
9288         snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
9289 	type = xmlSchemaAddType(ctxt, schema,
9290 	    XML_SCHEMA_TYPE_SIMPLE,
9291 	    xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
9292 	    ctxt->targetNamespace, node, 0);
9293 #else
9294 	type = xmlSchemaAddType(ctxt, schema,
9295 	    XML_SCHEMA_TYPE_SIMPLE,
9296 	    NULL, ctxt->targetNamespace, node, 0);
9297 #endif
9298 	if (type == NULL)
9299 	    return (NULL);
9300 	type->type = XML_SCHEMA_TYPE_SIMPLE;
9301 	type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
9302 	/*
9303 	* Check for illegal attributes.
9304 	*/
9305 	attr = node->properties;
9306 	while (attr != NULL) {
9307 	    if (attr->ns == NULL) {
9308 		if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
9309 		    xmlSchemaPIllegalAttrErr(ctxt,
9310 			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9311 		}
9312 	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9313 		    xmlSchemaPIllegalAttrErr(ctxt,
9314 			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9315 	    }
9316 	    attr = attr->next;
9317 	}
9318     } else {
9319 	/*
9320 	* Parse as global simple type definition.
9321 	*
9322 	* Note that attrValue is the value of the attribute "name" here.
9323 	*/
9324 	type = xmlSchemaAddType(ctxt, schema, XML_SCHEMA_TYPE_SIMPLE,
9325 	    attrValue, ctxt->targetNamespace, node, 1);
9326 	if (type == NULL)
9327 	    return (NULL);
9328 	type->type = XML_SCHEMA_TYPE_SIMPLE;
9329 	type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
9330 	type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
9331 	/*
9332 	* Check for illegal attributes.
9333 	*/
9334 	attr = node->properties;
9335 	while (attr != NULL) {
9336 	    if (attr->ns == NULL) {
9337 		if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9338 		    (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
9339 		    (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
9340 		    xmlSchemaPIllegalAttrErr(ctxt,
9341 			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9342 		}
9343 	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9344 		xmlSchemaPIllegalAttrErr(ctxt,
9345 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9346 	    }
9347 	    attr = attr->next;
9348 	}
9349 	/*
9350 	* Attribute "final".
9351 	*/
9352 	attr = xmlSchemaGetPropNode(node, "final");
9353 	if (attr == NULL) {
9354 	    if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9355 		type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
9356 	    if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9357 		type->flags |= XML_SCHEMAS_TYPE_FINAL_LIST;
9358 	    if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9359 		type->flags |= XML_SCHEMAS_TYPE_FINAL_UNION;
9360 	} else {
9361 	    attrValue = xmlSchemaGetProp(ctxt, node, "final");
9362 	    if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
9363 		-1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
9364 		XML_SCHEMAS_TYPE_FINAL_LIST,
9365 		XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
9366 
9367 		xmlSchemaPSimpleTypeErr(ctxt,
9368 		    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9369 		    WXS_BASIC_CAST type, (xmlNodePtr) attr,
9370 		    NULL, "(#all | List of (list | union | restriction)",
9371 		    attrValue, NULL, NULL, NULL);
9372 	    }
9373 	}
9374     }
9375     type->targetNamespace = ctxt->targetNamespace;
9376     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9377     /*
9378     * And now for the children...
9379     */
9380     oldCtxtType = ctxt->ctxtType;
9381 
9382     ctxt->ctxtType = type;
9383 
9384     child = node->children;
9385     if (IS_SCHEMA(child, "annotation")) {
9386         type->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9387         child = child->next;
9388     }
9389     if (child == NULL) {
9390 	xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_MISSING,
9391 	    NULL, node, child, NULL,
9392 	    "(annotation?, (restriction | list | union))");
9393     } else if (IS_SCHEMA(child, "restriction")) {
9394         xmlSchemaParseRestriction(ctxt, schema, child,
9395 	    XML_SCHEMA_TYPE_SIMPLE);
9396 	hasRestriction = 1;
9397         child = child->next;
9398     } else if (IS_SCHEMA(child, "list")) {
9399         xmlSchemaParseList(ctxt, schema, child);
9400         child = child->next;
9401     } else if (IS_SCHEMA(child, "union")) {
9402         xmlSchemaParseUnion(ctxt, schema, child);
9403         child = child->next;
9404     }
9405     if (child != NULL) {
9406 	xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9407 	    NULL, node, child, NULL,
9408 	    "(annotation?, (restriction | list | union))");
9409     }
9410     /*
9411     * REDEFINE: SPEC src-redefine (5)
9412     * "Within the [children], each <simpleType> must have a
9413     * <restriction> among its [children] ... the `actual value` of whose
9414     * base [attribute] must be the same as the `actual value` of its own
9415     * name attribute plus target namespace;"
9416     */
9417     if (topLevel && ctxt->isRedefine && (! hasRestriction)) {
9418 	xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
9419 	    NULL, node, "This is a redefinition, thus the "
9420 	    "<simpleType> must have a <restriction> child", NULL);
9421     }
9422 
9423     ctxt->ctxtType = oldCtxtType;
9424     return (type);
9425 }
9426 
9427 /**
9428  * xmlSchemaParseModelGroupDefRef:
9429  * @ctxt:  the parser context
9430  * @schema: the schema being built
9431  * @node:  the node
9432  *
9433  * Parses a reference to a model group definition.
9434  *
9435  * We will return a particle component with a qname-component or
9436  * NULL in case of an error.
9437  */
9438 static xmlSchemaTreeItemPtr
xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)9439 xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt,
9440 			       xmlSchemaPtr schema,
9441 			       xmlNodePtr node)
9442 {
9443     xmlSchemaParticlePtr item;
9444     xmlNodePtr child = NULL;
9445     xmlAttrPtr attr;
9446     const xmlChar *ref = NULL, *refNs = NULL;
9447     int min, max;
9448 
9449     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9450         return (NULL);
9451 
9452     attr = xmlSchemaGetPropNode(node, "ref");
9453     if (attr == NULL) {
9454 	xmlSchemaPMissingAttrErr(ctxt,
9455 	    XML_SCHEMAP_S4S_ATTR_MISSING,
9456 	    NULL, node, "ref", NULL);
9457 	return (NULL);
9458     } else if (xmlSchemaPValAttrNodeQName(ctxt, schema, NULL,
9459 	attr, &refNs, &ref) != 0) {
9460 	return (NULL);
9461     }
9462     xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
9463     min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
9464     max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
9465 	"(xs:nonNegativeInteger | unbounded)");
9466     /*
9467     * Check for illegal attributes.
9468     */
9469     attr = node->properties;
9470     while (attr != NULL) {
9471 	if (attr->ns == NULL) {
9472 	    if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
9473 		(!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9474 		(!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
9475 		(!xmlStrEqual(attr->name, BAD_CAST "maxOccurs"))) {
9476 		xmlSchemaPIllegalAttrErr(ctxt,
9477 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9478 	    }
9479 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9480 	    xmlSchemaPIllegalAttrErr(ctxt,
9481 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9482 	}
9483 	attr = attr->next;
9484     }
9485     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9486     item = xmlSchemaAddParticle(ctxt, node, min, max);
9487     if (item == NULL)
9488 	return (NULL);
9489     /*
9490     * Create a qname-reference and set as the term; it will be substituted
9491     * for the model group after the reference has been resolved.
9492     */
9493     item->children = (xmlSchemaTreeItemPtr)
9494 	xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_GROUP, ref, refNs);
9495     xmlSchemaPCheckParticleCorrect_2(ctxt, item, node, min, max);
9496     /*
9497     * And now for the children...
9498     */
9499     child = node->children;
9500     /* TODO: Is annotation even allowed for a model group reference? */
9501     if (IS_SCHEMA(child, "annotation")) {
9502 	/*
9503 	* TODO: What to do exactly with the annotation?
9504 	*/
9505 	item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9506 	child = child->next;
9507     }
9508     if (child != NULL) {
9509 	xmlSchemaPContentErr(ctxt,
9510 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9511 	    NULL, node, child, NULL,
9512 	    "(annotation?)");
9513     }
9514     /*
9515     * Corresponds to no component at all if minOccurs==maxOccurs==0.
9516     */
9517     if ((min == 0) && (max == 0))
9518 	return (NULL);
9519 
9520     return ((xmlSchemaTreeItemPtr) item);
9521 }
9522 
9523 /**
9524  * xmlSchemaParseModelGroupDefinition:
9525  * @ctxt:  a schema validation context
9526  * @schema:  the schema being built
9527  * @node:  a subtree containing XML Schema information
9528  *
9529  * Parses a XML schema model group definition.
9530  *
9531  * Note that the constraint src-redefine (6.2) can't be applied until
9532  * references have been resolved. So we will do this at the
9533  * component fixup level.
9534  *
9535  * *WARNING* this interface is highly subject to change
9536  *
9537  * Returns -1 in case of error, 0 if the declaration is improper and
9538  *         1 in case of success.
9539  */
9540 static xmlSchemaModelGroupDefPtr
xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)9541 xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
9542 				   xmlSchemaPtr schema,
9543 				   xmlNodePtr node)
9544 {
9545     xmlSchemaModelGroupDefPtr item;
9546     xmlNodePtr child = NULL;
9547     xmlAttrPtr attr;
9548     const xmlChar *name;
9549 
9550     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9551         return (NULL);
9552 
9553     attr = xmlSchemaGetPropNode(node, "name");
9554     if (attr == NULL) {
9555 	xmlSchemaPMissingAttrErr(ctxt,
9556 	    XML_SCHEMAP_S4S_ATTR_MISSING,
9557 	    NULL, node,
9558 	    "name", NULL);
9559 	return (NULL);
9560     } else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
9561 	xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
9562 	return (NULL);
9563     }
9564     item = xmlSchemaAddModelGroupDefinition(ctxt, schema, name,
9565 	ctxt->targetNamespace, node);
9566     if (item == NULL)
9567 	return (NULL);
9568     /*
9569     * Check for illegal attributes.
9570     */
9571     attr = node->properties;
9572     while (attr != NULL) {
9573 	if (attr->ns == NULL) {
9574 	    if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
9575 		(!xmlStrEqual(attr->name, BAD_CAST "id"))) {
9576 		xmlSchemaPIllegalAttrErr(ctxt,
9577 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9578 	    }
9579 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9580 	    xmlSchemaPIllegalAttrErr(ctxt,
9581 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9582 	}
9583 	attr = attr->next;
9584     }
9585     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9586     /*
9587     * And now for the children...
9588     */
9589     child = node->children;
9590     if (IS_SCHEMA(child, "annotation")) {
9591 	item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9592 	child = child->next;
9593     }
9594     if (IS_SCHEMA(child, "all")) {
9595 	item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9596 	    XML_SCHEMA_TYPE_ALL, 0);
9597 	child = child->next;
9598     } else if (IS_SCHEMA(child, "choice")) {
9599 	item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9600 	    XML_SCHEMA_TYPE_CHOICE, 0);
9601 	child = child->next;
9602     } else if (IS_SCHEMA(child, "sequence")) {
9603 	item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9604 	    XML_SCHEMA_TYPE_SEQUENCE, 0);
9605 	child = child->next;
9606     }
9607 
9608 
9609 
9610     if (child != NULL) {
9611 	xmlSchemaPContentErr(ctxt,
9612 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9613 	    NULL, node, child, NULL,
9614 	    "(annotation?, (all | choice | sequence)?)");
9615     }
9616     return (item);
9617 }
9618 
9619 /**
9620  * xmlSchemaCleanupDoc:
9621  * @ctxt:  a schema validation context
9622  * @node:  the root of the document.
9623  *
9624  * removes unwanted nodes in a schemas document tree
9625  */
9626 static void
xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr root)9627 xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
9628 {
9629     xmlNodePtr delete, cur;
9630 
9631     if ((ctxt == NULL) || (root == NULL)) return;
9632 
9633     /*
9634      * Remove all the blank text nodes
9635      */
9636     delete = NULL;
9637     cur = root;
9638     while (cur != NULL) {
9639         if (delete != NULL) {
9640             xmlUnlinkNode(delete);
9641             xmlFreeNode(delete);
9642             delete = NULL;
9643         }
9644         if (cur->type == XML_TEXT_NODE) {
9645             if (IS_BLANK_NODE(cur)) {
9646                 if (xmlNodeGetSpacePreserve(cur) != 1) {
9647                     delete = cur;
9648                 }
9649             }
9650         } else if ((cur->type != XML_ELEMENT_NODE) &&
9651                    (cur->type != XML_CDATA_SECTION_NODE)) {
9652             delete = cur;
9653             goto skip_children;
9654         }
9655 
9656         /*
9657          * Skip to next node
9658          */
9659         if (cur->children != NULL) {
9660             if ((cur->children->type != XML_ENTITY_DECL) &&
9661                 (cur->children->type != XML_ENTITY_REF_NODE) &&
9662                 (cur->children->type != XML_ENTITY_NODE)) {
9663                 cur = cur->children;
9664                 continue;
9665             }
9666         }
9667       skip_children:
9668         if (cur->next != NULL) {
9669             cur = cur->next;
9670             continue;
9671         }
9672 
9673         do {
9674             cur = cur->parent;
9675             if (cur == NULL)
9676                 break;
9677             if (cur == root) {
9678                 cur = NULL;
9679                 break;
9680             }
9681             if (cur->next != NULL) {
9682                 cur = cur->next;
9683                 break;
9684             }
9685         } while (cur != NULL);
9686     }
9687     if (delete != NULL) {
9688         xmlUnlinkNode(delete);
9689         xmlFreeNode(delete);
9690         delete = NULL;
9691     }
9692 }
9693 
9694 
9695 static void
xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)9696 xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
9697 {
9698     if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
9699 	schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
9700 
9701     if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
9702 	schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
9703 
9704     if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
9705 	schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
9706     if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9707 	schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
9708     if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9709 	schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
9710     if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9711 	schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
9712 
9713     if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
9714 	schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
9715     if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
9716 	schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
9717     if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
9718 	schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
9719 }
9720 
9721 static int
xmlSchemaParseSchemaElement(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)9722 xmlSchemaParseSchemaElement(xmlSchemaParserCtxtPtr ctxt,
9723 			     xmlSchemaPtr schema,
9724 			     xmlNodePtr node)
9725 {
9726     xmlAttrPtr attr;
9727     const xmlChar *val;
9728     int res = 0, oldErrs = ctxt->nberrors;
9729 
9730     /*
9731     * Those flags should be moved to the parser context flags,
9732     * since they are not visible at the component level. I.e.
9733     * they are used if processing schema *documents* only.
9734     */
9735     res = xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9736     HFAILURE;
9737 
9738     /*
9739     * Since the version is of type xs:token, we won't bother to
9740     * check it.
9741     */
9742     /* REMOVED:
9743     attr = xmlSchemaGetPropNode(node, "version");
9744     if (attr != NULL) {
9745 	res = xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
9746 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &val);
9747 	HFAILURE;
9748     }
9749     */
9750     attr = xmlSchemaGetPropNode(node, "targetNamespace");
9751     if (attr != NULL) {
9752 	res = xmlSchemaPValAttrNode(ctxt, NULL, attr,
9753 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
9754 	HFAILURE;
9755 	if (res != 0) {
9756 	    ctxt->stop = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
9757 	    goto exit;
9758 	}
9759     }
9760     attr = xmlSchemaGetPropNode(node, "elementFormDefault");
9761     if (attr != NULL) {
9762 	val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9763 	res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9764 	    XML_SCHEMAS_QUALIF_ELEM);
9765 	HFAILURE;
9766 	if (res != 0) {
9767 	    xmlSchemaPSimpleTypeErr(ctxt,
9768 		XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
9769 		NULL, (xmlNodePtr) attr, NULL,
9770 		"(qualified | unqualified)", val, NULL, NULL, NULL);
9771 	}
9772     }
9773     attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
9774     if (attr != NULL) {
9775 	val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9776 	res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9777 	    XML_SCHEMAS_QUALIF_ATTR);
9778 	HFAILURE;
9779 	if (res != 0) {
9780 	    xmlSchemaPSimpleTypeErr(ctxt,
9781 		XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
9782 		NULL, (xmlNodePtr) attr, NULL,
9783 		"(qualified | unqualified)", val, NULL, NULL, NULL);
9784 	}
9785     }
9786     attr = xmlSchemaGetPropNode(node, "finalDefault");
9787     if (attr != NULL) {
9788 	val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9789 	res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
9790 	    XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
9791 	    XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
9792 	    -1,
9793 	    XML_SCHEMAS_FINAL_DEFAULT_LIST,
9794 	    XML_SCHEMAS_FINAL_DEFAULT_UNION);
9795 	HFAILURE;
9796 	if (res != 0) {
9797 	    xmlSchemaPSimpleTypeErr(ctxt,
9798 		XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9799 		NULL, (xmlNodePtr) attr, NULL,
9800 		"(#all | List of (extension | restriction | list | union))",
9801 		val, NULL, NULL, NULL);
9802 	}
9803     }
9804     attr = xmlSchemaGetPropNode(node, "blockDefault");
9805     if (attr != NULL) {
9806 	val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9807 	res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
9808 	    XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
9809 	    XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
9810 	    XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1);
9811 	HFAILURE;
9812 	if (res != 0) {
9813 	    xmlSchemaPSimpleTypeErr(ctxt,
9814 		XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9815 		NULL, (xmlNodePtr) attr, NULL,
9816 		"(#all | List of (extension | restriction | substitution))",
9817 		val, NULL, NULL, NULL);
9818 	}
9819     }
9820 
9821 exit:
9822     if (oldErrs != ctxt->nberrors)
9823 	res = ctxt->err;
9824     return(res);
9825 exit_failure:
9826     return(-1);
9827 }
9828 
9829 /**
9830  * xmlSchemaParseSchemaTopLevel:
9831  * @ctxt:  a schema validation context
9832  * @schema:  the schemas
9833  * @nodes:  the list of top level nodes
9834  *
9835  * Returns the internal XML Schema structure built from the resource or
9836  *         NULL in case of error
9837  */
9838 static int
xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr nodes)9839 xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
9840                              xmlSchemaPtr schema, xmlNodePtr nodes)
9841 {
9842     xmlNodePtr child;
9843     xmlSchemaAnnotPtr annot;
9844     int res = 0, oldErrs, tmpOldErrs;
9845 
9846     if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
9847         return(-1);
9848 
9849     oldErrs = ctxt->nberrors;
9850     child = nodes;
9851     while ((IS_SCHEMA(child, "include")) ||
9852 	   (IS_SCHEMA(child, "import")) ||
9853 	   (IS_SCHEMA(child, "redefine")) ||
9854 	   (IS_SCHEMA(child, "annotation"))) {
9855 	if (IS_SCHEMA(child, "annotation")) {
9856 	    annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9857 	    if (schema->annot == NULL)
9858 		schema->annot = annot;
9859 	    else
9860 		xmlSchemaFreeAnnot(annot);
9861 	} else if (IS_SCHEMA(child, "import")) {
9862 	    tmpOldErrs = ctxt->nberrors;
9863 	    res = xmlSchemaParseImport(ctxt, schema, child);
9864 	    HFAILURE;
9865 	    HSTOP(ctxt);
9866 	    if (tmpOldErrs != ctxt->nberrors)
9867 		goto exit;
9868 	} else if (IS_SCHEMA(child, "include")) {
9869 	    tmpOldErrs = ctxt->nberrors;
9870 	    res = xmlSchemaParseInclude(ctxt, schema, child);
9871 	    HFAILURE;
9872 	    HSTOP(ctxt);
9873 	    if (tmpOldErrs != ctxt->nberrors)
9874 		goto exit;
9875 	} else if (IS_SCHEMA(child, "redefine")) {
9876 	    tmpOldErrs = ctxt->nberrors;
9877 	    res = xmlSchemaParseRedefine(ctxt, schema, child);
9878 	    HFAILURE;
9879 	    HSTOP(ctxt);
9880 	    if (tmpOldErrs != ctxt->nberrors)
9881 		goto exit;
9882 	}
9883 	child = child->next;
9884     }
9885     /*
9886     * URGENT TODO: Change the functions to return int results.
9887     * We need especially to catch internal errors.
9888     */
9889     while (child != NULL) {
9890 	if (IS_SCHEMA(child, "complexType")) {
9891 	    xmlSchemaParseComplexType(ctxt, schema, child, 1);
9892 	    child = child->next;
9893 	} else if (IS_SCHEMA(child, "simpleType")) {
9894 	    xmlSchemaParseSimpleType(ctxt, schema, child, 1);
9895 	    child = child->next;
9896 	} else if (IS_SCHEMA(child, "element")) {
9897 	    xmlSchemaParseElement(ctxt, schema, child, NULL, 1);
9898 	    child = child->next;
9899 	} else if (IS_SCHEMA(child, "attribute")) {
9900 	    xmlSchemaParseGlobalAttribute(ctxt, schema, child);
9901 	    child = child->next;
9902 	} else if (IS_SCHEMA(child, "attributeGroup")) {
9903 	    xmlSchemaParseAttributeGroupDefinition(ctxt, schema, child);
9904 	    child = child->next;
9905 	} else if (IS_SCHEMA(child, "group")) {
9906 	    xmlSchemaParseModelGroupDefinition(ctxt, schema, child);
9907 	    child = child->next;
9908 	} else if (IS_SCHEMA(child, "notation")) {
9909 	    xmlSchemaParseNotation(ctxt, schema, child);
9910 	    child = child->next;
9911 	} else {
9912 	    xmlSchemaPContentErr(ctxt,
9913 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9914 		NULL, child->parent, child,
9915 		NULL, "((include | import | redefine | annotation)*, "
9916 		"(((simpleType | complexType | group | attributeGroup) "
9917 		"| element | attribute | notation), annotation*)*)");
9918 	    child = child->next;
9919 	}
9920 	while (IS_SCHEMA(child, "annotation")) {
9921 	    /*
9922 	    * TODO: We should add all annotations.
9923 	    */
9924 	    annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9925 	    if (schema->annot == NULL)
9926 		schema->annot = annot;
9927 	    else
9928 		xmlSchemaFreeAnnot(annot);
9929 	    child = child->next;
9930 	}
9931     }
9932 exit:
9933     ctxt->ctxtType = NULL;
9934     if (oldErrs != ctxt->nberrors)
9935 	res = ctxt->err;
9936     return(res);
9937 exit_failure:
9938     return(-1);
9939 }
9940 
9941 static xmlSchemaSchemaRelationPtr
xmlSchemaSchemaRelationCreate(void)9942 xmlSchemaSchemaRelationCreate(void)
9943 {
9944     xmlSchemaSchemaRelationPtr ret;
9945 
9946     ret = (xmlSchemaSchemaRelationPtr)
9947 	xmlMalloc(sizeof(xmlSchemaSchemaRelation));
9948     if (ret == NULL) {
9949 	xmlSchemaPErrMemory(NULL, "allocating schema relation", NULL);
9950 	return(NULL);
9951     }
9952     memset(ret, 0, sizeof(xmlSchemaSchemaRelation));
9953     return(ret);
9954 }
9955 
9956 #if 0
9957 static void
9958 xmlSchemaSchemaRelationFree(xmlSchemaSchemaRelationPtr rel)
9959 {
9960     xmlFree(rel);
9961 }
9962 #endif
9963 
9964 static void
xmlSchemaRedefListFree(xmlSchemaRedefPtr redef)9965 xmlSchemaRedefListFree(xmlSchemaRedefPtr redef)
9966 {
9967     xmlSchemaRedefPtr prev;
9968 
9969     while (redef != NULL) {
9970 	prev = redef;
9971 	redef = redef->next;
9972 	xmlFree(prev);
9973     }
9974 }
9975 
9976 static void
xmlSchemaConstructionCtxtFree(xmlSchemaConstructionCtxtPtr con)9977 xmlSchemaConstructionCtxtFree(xmlSchemaConstructionCtxtPtr con)
9978 {
9979     /*
9980     * After the construction context has been freed, there will be
9981     * no schema graph available any more. Only the schema buckets
9982     * will stay alive, which are put into the "schemasImports" and
9983     * "includes" slots of the xmlSchema.
9984     */
9985     if (con->buckets != NULL)
9986 	xmlSchemaItemListFree(con->buckets);
9987     if (con->pending != NULL)
9988 	xmlSchemaItemListFree(con->pending);
9989     if (con->substGroups != NULL)
9990 	xmlHashFree(con->substGroups, xmlSchemaSubstGroupFreeEntry);
9991     if (con->redefs != NULL)
9992 	xmlSchemaRedefListFree(con->redefs);
9993     if (con->dict != NULL)
9994 	xmlDictFree(con->dict);
9995     xmlFree(con);
9996 }
9997 
9998 static xmlSchemaConstructionCtxtPtr
xmlSchemaConstructionCtxtCreate(xmlDictPtr dict)9999 xmlSchemaConstructionCtxtCreate(xmlDictPtr dict)
10000 {
10001     xmlSchemaConstructionCtxtPtr ret;
10002 
10003     ret = (xmlSchemaConstructionCtxtPtr)
10004 	xmlMalloc(sizeof(xmlSchemaConstructionCtxt));
10005     if (ret == NULL) {
10006         xmlSchemaPErrMemory(NULL,
10007 	    "allocating schema construction context", NULL);
10008         return (NULL);
10009     }
10010     memset(ret, 0, sizeof(xmlSchemaConstructionCtxt));
10011 
10012     ret->buckets = xmlSchemaItemListCreate();
10013     if (ret->buckets == NULL) {
10014 	xmlSchemaPErrMemory(NULL,
10015 	    "allocating list of schema buckets", NULL);
10016 	xmlFree(ret);
10017         return (NULL);
10018     }
10019     ret->pending = xmlSchemaItemListCreate();
10020     if (ret->pending == NULL) {
10021 	xmlSchemaPErrMemory(NULL,
10022 	    "allocating list of pending global components", NULL);
10023 	xmlSchemaConstructionCtxtFree(ret);
10024         return (NULL);
10025     }
10026     ret->dict = dict;
10027     xmlDictReference(dict);
10028     return(ret);
10029 }
10030 
10031 static xmlSchemaParserCtxtPtr
xmlSchemaParserCtxtCreate(void)10032 xmlSchemaParserCtxtCreate(void)
10033 {
10034     xmlSchemaParserCtxtPtr ret;
10035 
10036     ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
10037     if (ret == NULL) {
10038         xmlSchemaPErrMemory(NULL, "allocating schema parser context",
10039                             NULL);
10040         return (NULL);
10041     }
10042     memset(ret, 0, sizeof(xmlSchemaParserCtxt));
10043     ret->type = XML_SCHEMA_CTXT_PARSER;
10044     ret->attrProhibs = xmlSchemaItemListCreate();
10045     if (ret->attrProhibs == NULL) {
10046 	xmlFree(ret);
10047 	return(NULL);
10048     }
10049     return(ret);
10050 }
10051 
10052 /**
10053  * xmlSchemaNewParserCtxtUseDict:
10054  * @URL:  the location of the schema
10055  * @dict: the dictionary to be used
10056  *
10057  * Create an XML Schemas parse context for that file/resource expected
10058  * to contain an XML Schemas file.
10059  *
10060  * Returns the parser context or NULL in case of error
10061  */
10062 static xmlSchemaParserCtxtPtr
xmlSchemaNewParserCtxtUseDict(const char * URL,xmlDictPtr dict)10063 xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
10064 {
10065     xmlSchemaParserCtxtPtr ret;
10066 
10067     ret = xmlSchemaParserCtxtCreate();
10068     if (ret == NULL)
10069         return (NULL);
10070     ret->dict = dict;
10071     xmlDictReference(dict);
10072     if (URL != NULL)
10073 	ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
10074     return (ret);
10075 }
10076 
10077 static int
xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)10078 xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
10079 {
10080     if (vctxt->pctxt == NULL) {
10081         if (vctxt->schema != NULL)
10082 	    vctxt->pctxt =
10083 		xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
10084 	else
10085 	    vctxt->pctxt = xmlSchemaNewParserCtxt("*");
10086 	if (vctxt->pctxt == NULL) {
10087 	    VERROR_INT("xmlSchemaCreatePCtxtOnVCtxt",
10088 		"failed to create a temp. parser context");
10089 	    return (-1);
10090 	}
10091 	/* TODO: Pass user data. */
10092 	xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error,
10093 	    vctxt->warning, vctxt->errCtxt);
10094 	xmlSchemaSetParserStructuredErrors(vctxt->pctxt, vctxt->serror,
10095 	    vctxt->errCtxt);
10096     }
10097     return (0);
10098 }
10099 
10100 /**
10101  * xmlSchemaGetSchemaBucket:
10102  * @pctxt: the schema parser context
10103  * @schemaLocation: the URI of the schema document
10104  *
10105  * Returns a schema bucket if it was already parsed.
10106  *
10107  * Returns a schema bucket if it was already parsed from
10108  *         @schemaLocation, NULL otherwise.
10109  */
10110 static xmlSchemaBucketPtr
xmlSchemaGetSchemaBucket(xmlSchemaParserCtxtPtr pctxt,const xmlChar * schemaLocation)10111 xmlSchemaGetSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
10112 			    const xmlChar *schemaLocation)
10113 {
10114     xmlSchemaBucketPtr cur;
10115     xmlSchemaItemListPtr list;
10116 
10117     list = pctxt->constructor->buckets;
10118     if (list->nbItems == 0)
10119 	return(NULL);
10120     else {
10121 	int i;
10122 	for (i = 0; i < list->nbItems; i++) {
10123 	    cur = (xmlSchemaBucketPtr) list->items[i];
10124 	    /* Pointer comparison! */
10125 	    if (cur->schemaLocation == schemaLocation)
10126 		return(cur);
10127 	}
10128     }
10129     return(NULL);
10130 }
10131 
10132 static xmlSchemaBucketPtr
xmlSchemaGetChameleonSchemaBucket(xmlSchemaParserCtxtPtr pctxt,const xmlChar * schemaLocation,const xmlChar * targetNamespace)10133 xmlSchemaGetChameleonSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
10134 				     const xmlChar *schemaLocation,
10135 				     const xmlChar *targetNamespace)
10136 {
10137     xmlSchemaBucketPtr cur;
10138     xmlSchemaItemListPtr list;
10139 
10140     list = pctxt->constructor->buckets;
10141     if (list->nbItems == 0)
10142 	return(NULL);
10143     else {
10144 	int i;
10145 	for (i = 0; i < list->nbItems; i++) {
10146 	    cur = (xmlSchemaBucketPtr) list->items[i];
10147 	    /* Pointer comparison! */
10148 	    if ((cur->origTargetNamespace == NULL) &&
10149 		(cur->schemaLocation == schemaLocation) &&
10150 		(cur->targetNamespace == targetNamespace))
10151 		return(cur);
10152 	}
10153     }
10154     return(NULL);
10155 }
10156 
10157 
10158 #define IS_BAD_SCHEMA_DOC(b) \
10159     (((b)->doc == NULL) && ((b)->schemaLocation != NULL))
10160 
10161 static xmlSchemaBucketPtr
xmlSchemaGetSchemaBucketByTNS(xmlSchemaParserCtxtPtr pctxt,const xmlChar * targetNamespace,int imported)10162 xmlSchemaGetSchemaBucketByTNS(xmlSchemaParserCtxtPtr pctxt,
10163 				 const xmlChar *targetNamespace,
10164 				 int imported)
10165 {
10166     xmlSchemaBucketPtr cur;
10167     xmlSchemaItemListPtr list;
10168 
10169     list = pctxt->constructor->buckets;
10170     if (list->nbItems == 0)
10171 	return(NULL);
10172     else {
10173 	int i;
10174 	for (i = 0; i < list->nbItems; i++) {
10175 	    cur = (xmlSchemaBucketPtr) list->items[i];
10176 	    if ((! IS_BAD_SCHEMA_DOC(cur)) &&
10177 		(cur->origTargetNamespace == targetNamespace) &&
10178 		((imported && cur->imported) ||
10179 		 ((!imported) && (!cur->imported))))
10180 		return(cur);
10181 	}
10182     }
10183     return(NULL);
10184 }
10185 
10186 static int
xmlSchemaParseNewDocWithContext(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlSchemaBucketPtr bucket)10187 xmlSchemaParseNewDocWithContext(xmlSchemaParserCtxtPtr pctxt,
10188 		     xmlSchemaPtr schema,
10189 		     xmlSchemaBucketPtr bucket)
10190 {
10191     int oldFlags;
10192     xmlDocPtr oldDoc;
10193     xmlNodePtr node;
10194     int ret, oldErrs;
10195     xmlSchemaBucketPtr oldbucket = pctxt->constructor->bucket;
10196 
10197     /*
10198     * Save old values; reset the *main* schema.
10199     * URGENT TODO: This is not good; move the per-document information
10200     * to the parser. Get rid of passing the main schema to the
10201     * parsing functions.
10202     */
10203     oldFlags = schema->flags;
10204     oldDoc = schema->doc;
10205     if (schema->flags != 0)
10206 	xmlSchemaClearSchemaDefaults(schema);
10207     schema->doc = bucket->doc;
10208     pctxt->schema = schema;
10209     /*
10210     * Keep the current target namespace on the parser *not* on the
10211     * main schema.
10212     */
10213     pctxt->targetNamespace = bucket->targetNamespace;
10214     WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
10215 
10216     if ((bucket->targetNamespace != NULL) &&
10217 	xmlStrEqual(bucket->targetNamespace, xmlSchemaNs)) {
10218 	/*
10219 	* We are parsing the schema for schemas!
10220 	*/
10221 	pctxt->isS4S = 1;
10222     }
10223     /* Mark it as parsed, even if parsing fails. */
10224     bucket->parsed++;
10225     /* Compile the schema doc. */
10226     node = xmlDocGetRootElement(bucket->doc);
10227     ret = xmlSchemaParseSchemaElement(pctxt, schema, node);
10228     if (ret != 0)
10229 	goto exit;
10230     /* An empty schema; just get out. */
10231     if (node->children == NULL)
10232 	goto exit;
10233     oldErrs = pctxt->nberrors;
10234     ret = xmlSchemaParseSchemaTopLevel(pctxt, schema, node->children);
10235     if (ret != 0)
10236 	goto exit;
10237     /*
10238     * TODO: Not nice, but I'm not 100% sure we will get always an error
10239     * as a result of the above functions; so better rely on pctxt->err
10240     * as well.
10241     */
10242     if ((ret == 0) && (oldErrs != pctxt->nberrors)) {
10243 	ret = pctxt->err;
10244 	goto exit;
10245     }
10246 
10247 exit:
10248     WXS_CONSTRUCTOR(pctxt)->bucket = oldbucket;
10249     /* Restore schema values. */
10250     schema->doc = oldDoc;
10251     schema->flags = oldFlags;
10252     return(ret);
10253 }
10254 
10255 static int
xmlSchemaParseNewDoc(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlSchemaBucketPtr bucket)10256 xmlSchemaParseNewDoc(xmlSchemaParserCtxtPtr pctxt,
10257 		     xmlSchemaPtr schema,
10258 		     xmlSchemaBucketPtr bucket)
10259 {
10260     xmlSchemaParserCtxtPtr newpctxt;
10261     int res = 0;
10262 
10263     if (bucket == NULL)
10264 	return(0);
10265     if (bucket->parsed) {
10266 	PERROR_INT("xmlSchemaParseNewDoc",
10267 	    "reparsing a schema doc");
10268 	return(-1);
10269     }
10270     if (bucket->doc == NULL) {
10271 	PERROR_INT("xmlSchemaParseNewDoc",
10272 	    "parsing a schema doc, but there's no doc");
10273 	return(-1);
10274     }
10275     if (pctxt->constructor == NULL) {
10276 	PERROR_INT("xmlSchemaParseNewDoc",
10277 	    "no constructor");
10278 	return(-1);
10279     }
10280     /* Create and init the temporary parser context. */
10281     newpctxt = xmlSchemaNewParserCtxtUseDict(
10282 	(const char *) bucket->schemaLocation, pctxt->dict);
10283     if (newpctxt == NULL)
10284 	return(-1);
10285     newpctxt->constructor = pctxt->constructor;
10286     /*
10287     * TODO: Can we avoid that the parser knows about the main schema?
10288     * It would be better if he knows about the current schema bucket
10289     * only.
10290     */
10291     newpctxt->schema = schema;
10292     xmlSchemaSetParserErrors(newpctxt, pctxt->error, pctxt->warning,
10293 	pctxt->errCtxt);
10294     xmlSchemaSetParserStructuredErrors(newpctxt, pctxt->serror,
10295 	pctxt->errCtxt);
10296     newpctxt->counter = pctxt->counter;
10297 
10298 
10299     res = xmlSchemaParseNewDocWithContext(newpctxt, schema, bucket);
10300 
10301     /* Channel back errors and cleanup the temporary parser context. */
10302     if (res != 0)
10303 	pctxt->err = res;
10304     pctxt->nberrors += newpctxt->nberrors;
10305     pctxt->counter = newpctxt->counter;
10306     newpctxt->constructor = NULL;
10307     /* Free the parser context. */
10308     xmlSchemaFreeParserCtxt(newpctxt);
10309     return(res);
10310 }
10311 
10312 static void
xmlSchemaSchemaRelationAddChild(xmlSchemaBucketPtr bucket,xmlSchemaSchemaRelationPtr rel)10313 xmlSchemaSchemaRelationAddChild(xmlSchemaBucketPtr bucket,
10314 				xmlSchemaSchemaRelationPtr rel)
10315 {
10316     xmlSchemaSchemaRelationPtr cur = bucket->relations;
10317 
10318     if (cur == NULL) {
10319 	bucket->relations = rel;
10320 	return;
10321     }
10322     while (cur->next != NULL)
10323 	cur = cur->next;
10324     cur->next = rel;
10325 }
10326 
10327 
10328 static const xmlChar *
xmlSchemaBuildAbsoluteURI(xmlDictPtr dict,const xmlChar * location,xmlNodePtr ctxtNode)10329 xmlSchemaBuildAbsoluteURI(xmlDictPtr dict, const xmlChar* location,
10330 			  xmlNodePtr ctxtNode)
10331 {
10332     /*
10333     * Build an absolute location URI.
10334     */
10335     if (location != NULL) {
10336 	if (ctxtNode == NULL)
10337 	    return(location);
10338 	else {
10339 	    xmlChar *base, *URI;
10340 	    const xmlChar *ret = NULL;
10341 
10342 	    base = xmlNodeGetBase(ctxtNode->doc, ctxtNode);
10343 	    if (base == NULL) {
10344 		URI = xmlBuildURI(location, ctxtNode->doc->URL);
10345 	    } else {
10346 		URI = xmlBuildURI(location, base);
10347 		xmlFree(base);
10348 	    }
10349 	    if (URI != NULL) {
10350 		ret = xmlDictLookup(dict, URI, -1);
10351 		xmlFree(URI);
10352 		return(ret);
10353 	    }
10354 	}
10355     }
10356     return(NULL);
10357 }
10358 
10359 
10360 
10361 /**
10362  * xmlSchemaAddSchemaDoc:
10363  * @pctxt:  a schema validation context
10364  * @schema:  the schema being built
10365  * @node:  a subtree containing XML Schema information
10366  *
10367  * Parse an included (and to-be-redefined) XML schema document.
10368  *
10369  * Returns 0 on success, a positive error code on errors and
10370  *         -1 in case of an internal or API error.
10371  */
10372 
10373 static int
xmlSchemaAddSchemaDoc(xmlSchemaParserCtxtPtr pctxt,int type,const xmlChar * schemaLocation,xmlDocPtr schemaDoc,const char * schemaBuffer,int schemaBufferLen,xmlNodePtr invokingNode,const xmlChar * sourceTargetNamespace,const xmlChar * importNamespace,xmlSchemaBucketPtr * bucket)10374 xmlSchemaAddSchemaDoc(xmlSchemaParserCtxtPtr pctxt,
10375 		int type, /* import or include or redefine */
10376 		const xmlChar *schemaLocation,
10377 		xmlDocPtr schemaDoc,
10378 		const char *schemaBuffer,
10379 		int schemaBufferLen,
10380 		xmlNodePtr invokingNode,
10381 		const xmlChar *sourceTargetNamespace,
10382 		const xmlChar *importNamespace,
10383 		xmlSchemaBucketPtr *bucket)
10384 {
10385     const xmlChar *targetNamespace = NULL;
10386     xmlSchemaSchemaRelationPtr relation = NULL;
10387     xmlDocPtr doc = NULL;
10388     int res = 0, err = 0, located = 0, preserveDoc = 0;
10389     xmlSchemaBucketPtr bkt = NULL;
10390 
10391     if (bucket != NULL)
10392 	*bucket = NULL;
10393 
10394     switch (type) {
10395 	case XML_SCHEMA_SCHEMA_IMPORT:
10396 	case XML_SCHEMA_SCHEMA_MAIN:
10397 	    err = XML_SCHEMAP_SRC_IMPORT;
10398 	    break;
10399 	case XML_SCHEMA_SCHEMA_INCLUDE:
10400 	    err = XML_SCHEMAP_SRC_INCLUDE;
10401 	    break;
10402 	case XML_SCHEMA_SCHEMA_REDEFINE:
10403 	    err = XML_SCHEMAP_SRC_REDEFINE;
10404 	    break;
10405     }
10406 
10407 
10408     /* Special handling for the main schema:
10409     * skip the location and relation logic and just parse the doc.
10410     * We need just a bucket to be returned in this case.
10411     */
10412     if ((type == XML_SCHEMA_SCHEMA_MAIN) || (! WXS_HAS_BUCKETS(pctxt)))
10413 	goto doc_load;
10414 
10415     /* Note that we expect the location to be an absolute URI. */
10416     if (schemaLocation != NULL) {
10417 	bkt = xmlSchemaGetSchemaBucket(pctxt, schemaLocation);
10418 	if ((bkt != NULL) &&
10419 	    (pctxt->constructor->bucket == bkt)) {
10420 	    /* Report self-imports/inclusions/redefinitions. */
10421 
10422 	    xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10423 		invokingNode, NULL,
10424 		"The schema must not import/include/redefine itself",
10425 		NULL, NULL);
10426 	    goto exit;
10427 	}
10428     }
10429     /*
10430     * Create a relation for the graph of schemas.
10431     */
10432     relation = xmlSchemaSchemaRelationCreate();
10433     if (relation == NULL)
10434 	return(-1);
10435     xmlSchemaSchemaRelationAddChild(pctxt->constructor->bucket,
10436 	relation);
10437     relation->type = type;
10438 
10439     /*
10440     * Save the namespace import information.
10441     */
10442     if (WXS_IS_BUCKET_IMPMAIN(type)) {
10443 	relation->importNamespace = importNamespace;
10444 	if (schemaLocation == NULL) {
10445 	    /*
10446 	    * No location; this is just an import of the namespace.
10447 	    * Note that we don't assign a bucket to the relation
10448 	    * in this case.
10449 	    */
10450 	    goto exit;
10451 	}
10452 	targetNamespace = importNamespace;
10453     }
10454 
10455     /* Did we already fetch the doc? */
10456     if (bkt != NULL) {
10457 	if ((WXS_IS_BUCKET_IMPMAIN(type)) && (! bkt->imported)) {
10458 	    /*
10459 	    * We included/redefined and then try to import a schema,
10460 	    * but the new location provided for import was different.
10461 	    */
10462 	    if (schemaLocation == NULL)
10463 		schemaLocation = BAD_CAST "in_memory_buffer";
10464 	    if (!xmlStrEqual(schemaLocation,
10465 		bkt->schemaLocation)) {
10466 		xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10467 		    invokingNode, NULL,
10468 		    "The schema document '%s' cannot be imported, since "
10469 		    "it was already included or redefined",
10470 		    schemaLocation, NULL);
10471 		goto exit;
10472 	    }
10473 	} else if ((! WXS_IS_BUCKET_IMPMAIN(type)) && (bkt->imported)) {
10474 	    /*
10475 	    * We imported and then try to include/redefine a schema,
10476 	    * but the new location provided for the include/redefine
10477 	    * was different.
10478 	    */
10479 	    if (schemaLocation == NULL)
10480 		schemaLocation = BAD_CAST "in_memory_buffer";
10481 	    if (!xmlStrEqual(schemaLocation,
10482 		bkt->schemaLocation)) {
10483 		xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10484 		    invokingNode, NULL,
10485 		    "The schema document '%s' cannot be included or "
10486 		    "redefined, since it was already imported",
10487 		    schemaLocation, NULL);
10488 		goto exit;
10489 	    }
10490 	}
10491     }
10492 
10493     if (WXS_IS_BUCKET_IMPMAIN(type)) {
10494 	/*
10495 	* Given that the schemaLocation [attribute] is only a hint, it is open
10496 	* to applications to ignore all but the first <import> for a given
10497 	* namespace, regardless of the `actual value` of schemaLocation, but
10498 	* such a strategy risks missing useful information when new
10499 	* schemaLocations are offered.
10500 	*
10501 	* We will use the first <import> that comes with a location.
10502 	* Further <import>s *with* a location, will result in an error.
10503 	* TODO: Better would be to just report a warning here, but
10504 	* we'll try it this way until someone complains.
10505 	*
10506 	* Schema Document Location Strategy:
10507 	* 3 Based on the namespace name, identify an existing schema document,
10508 	* either as a resource which is an XML document or a <schema> element
10509 	* information item, in some local schema repository;
10510 	* 5 Attempt to resolve the namespace name to locate such a resource.
10511 	*
10512 	* NOTE: (3) and (5) are not supported.
10513 	*/
10514 	if (bkt != NULL) {
10515 	    relation->bucket = bkt;
10516 	    goto exit;
10517 	}
10518 	bkt = xmlSchemaGetSchemaBucketByTNS(pctxt,
10519 	    importNamespace, 1);
10520 
10521 	if (bkt != NULL) {
10522 	    relation->bucket = bkt;
10523 	    if (bkt->schemaLocation == NULL) {
10524 		/* First given location of the schema; load the doc. */
10525 		bkt->schemaLocation = schemaLocation;
10526 	    } else {
10527 		if (!xmlStrEqual(schemaLocation,
10528 		    bkt->schemaLocation)) {
10529 		    /*
10530 		    * Additional location given; just skip it.
10531 		    * URGENT TODO: We should report a warning here.
10532 		    * res = XML_SCHEMAP_SRC_IMPORT;
10533 		    */
10534 		    if (schemaLocation == NULL)
10535 			schemaLocation = BAD_CAST "in_memory_buffer";
10536 
10537 		    xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10538 			XML_SCHEMAP_WARN_SKIP_SCHEMA,
10539 			invokingNode, NULL,
10540 			"Skipping import of schema located at '%s' for the "
10541 			"namespace '%s', since this namespace was already "
10542 			"imported with the schema located at '%s'",
10543 			schemaLocation, importNamespace, bkt->schemaLocation);
10544 		}
10545 		goto exit;
10546 	    }
10547 	}
10548 	/*
10549 	* No bucket + first location: load the doc and create a
10550 	* bucket.
10551 	*/
10552     } else {
10553 	/* <include> and <redefine> */
10554 	if (bkt != NULL) {
10555 
10556 	    if ((bkt->origTargetNamespace == NULL) &&
10557 		(bkt->targetNamespace != sourceTargetNamespace)) {
10558 		xmlSchemaBucketPtr chamel;
10559 
10560 		/*
10561 		* Chameleon include/redefine: skip loading only if it was
10562 		* already build for the targetNamespace of the including
10563 		* schema.
10564 		*/
10565 		/*
10566 		* URGENT TODO: If the schema is a chameleon-include then copy
10567 		* the components into the including schema and modify the
10568 		* targetNamespace of those components, do nothing otherwise.
10569 		* NOTE: This is currently worked-around by compiling the
10570 		* chameleon for every distinct including targetNamespace; thus
10571 		* not performant at the moment.
10572 		* TODO: Check when the namespace in wildcards for chameleons
10573 		* needs to be converted: before we built wildcard intersections
10574 		* or after.
10575 		*   Answer: after!
10576 		*/
10577 		chamel = xmlSchemaGetChameleonSchemaBucket(pctxt,
10578 		    schemaLocation, sourceTargetNamespace);
10579 		if (chamel != NULL) {
10580 		    /* A fitting chameleon was already parsed; NOP. */
10581 		    relation->bucket = chamel;
10582 		    goto exit;
10583 		}
10584 		/*
10585 		* We need to parse the chameleon again for a different
10586 		* targetNamespace.
10587 		* CHAMELEON TODO: Optimize this by only parsing the
10588 		* chameleon once, and then copying the components to
10589 		* the new targetNamespace.
10590 		*/
10591 		bkt = NULL;
10592 	    } else {
10593 		relation->bucket = bkt;
10594 		goto exit;
10595 	    }
10596 	}
10597     }
10598     if ((bkt != NULL) && (bkt->doc != NULL)) {
10599 	PERROR_INT("xmlSchemaAddSchemaDoc",
10600 	    "trying to load a schema doc, but a doc is already "
10601 	    "assigned to the schema bucket");
10602 	goto exit_failure;
10603     }
10604 
10605 doc_load:
10606     /*
10607     * Load the document.
10608     */
10609     if (schemaDoc != NULL) {
10610 	doc = schemaDoc;
10611 	/* Don' free this one, since it was provided by the caller. */
10612 	preserveDoc = 1;
10613 	/* TODO: Does the context or the doc hold the location? */
10614 	if (schemaDoc->URL != NULL)
10615 	    schemaLocation = xmlDictLookup(pctxt->dict,
10616 		schemaDoc->URL, -1);
10617         else
10618 	    schemaLocation = BAD_CAST "in_memory_buffer";
10619     } else if ((schemaLocation != NULL) || (schemaBuffer != NULL)) {
10620 	xmlParserCtxtPtr parserCtxt;
10621 
10622 	parserCtxt = xmlNewParserCtxt();
10623 	if (parserCtxt == NULL) {
10624 	    xmlSchemaPErrMemory(NULL, "xmlSchemaGetDoc, "
10625 		"allocating a parser context", NULL);
10626 	    goto exit_failure;
10627 	}
10628 	if ((pctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
10629 	    /*
10630 	    * TODO: Do we have to burden the schema parser dict with all
10631 	    * the content of the schema doc?
10632 	    */
10633 	    xmlDictFree(parserCtxt->dict);
10634 	    parserCtxt->dict = pctxt->dict;
10635 	    xmlDictReference(parserCtxt->dict);
10636 	}
10637 	if (schemaLocation != NULL) {
10638 	    /* Parse from file. */
10639 	    doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
10640 		NULL, SCHEMAS_PARSE_OPTIONS);
10641 	} else if (schemaBuffer != NULL) {
10642 	    /* Parse from memory buffer. */
10643 	    doc = xmlCtxtReadMemory(parserCtxt, schemaBuffer, schemaBufferLen,
10644 		NULL, NULL, SCHEMAS_PARSE_OPTIONS);
10645 	    schemaLocation = BAD_CAST "in_memory_buffer";
10646 	    if (doc != NULL)
10647 		doc->URL = xmlStrdup(schemaLocation);
10648 	}
10649 	/*
10650 	* For <import>:
10651 	* 2.1 The referent is (a fragment of) a resource which is an
10652 	* XML document (see clause 1.1), which in turn corresponds to
10653 	* a <schema> element information item in a well-formed information
10654 	* set, which in turn corresponds to a valid schema.
10655 	* TODO: (2.1) fragments of XML documents are not supported.
10656 	*
10657 	* 2.2 The referent is a <schema> element information item in
10658 	* a well-formed information set, which in turn corresponds
10659 	* to a valid schema.
10660 	* TODO: (2.2) is not supported.
10661 	*/
10662 	if (doc == NULL) {
10663 	    xmlErrorPtr lerr;
10664 	    lerr = xmlGetLastError();
10665 	    /*
10666 	    * Check if this a parser error, or if the document could
10667 	    * just not be located.
10668 	    * TODO: Try to find specific error codes to react only on
10669 	    * localisation failures.
10670 	    */
10671 	    if ((lerr == NULL) || (lerr->domain != XML_FROM_IO)) {
10672 		/*
10673 		* We assume a parser error here.
10674 		*/
10675 		located = 1;
10676 		/* TODO: Error code ?? */
10677 		res = XML_SCHEMAP_SRC_IMPORT_2_1;
10678 		xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10679 		    invokingNode, NULL,
10680 		    "Failed to parse the XML resource '%s'",
10681 		    schemaLocation, NULL);
10682 	    }
10683 	}
10684 	xmlFreeParserCtxt(parserCtxt);
10685 	if ((doc == NULL) && located)
10686 	    goto exit_error;
10687     } else {
10688 	xmlSchemaPErr(pctxt, NULL,
10689 	    XML_SCHEMAP_NOTHING_TO_PARSE,
10690 	    "No information for parsing was provided with the "
10691 	    "given schema parser context.\n",
10692 	    NULL, NULL);
10693 	goto exit_failure;
10694     }
10695     /*
10696     * Preprocess the document.
10697     */
10698     if (doc != NULL) {
10699 	xmlNodePtr docElem = NULL;
10700 
10701 	located = 1;
10702 	docElem = xmlDocGetRootElement(doc);
10703 	if (docElem == NULL) {
10704 	    xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOROOT,
10705 		invokingNode, NULL,
10706 		"The document '%s' has no document element",
10707 		schemaLocation, NULL);
10708 	    goto exit_error;
10709 	}
10710 	/*
10711 	* Remove all the blank text nodes.
10712 	*/
10713 	xmlSchemaCleanupDoc(pctxt, docElem);
10714 	/*
10715 	* Check the schema's top level element.
10716 	*/
10717 	if (!IS_SCHEMA(docElem, "schema")) {
10718 	    xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOT_SCHEMA,
10719 		invokingNode, NULL,
10720 		"The XML document '%s' is not a schema document",
10721 		schemaLocation, NULL);
10722 	    goto exit_error;
10723 	}
10724 	/*
10725 	* Note that we don't apply a type check for the
10726 	* targetNamespace value here.
10727 	*/
10728 	targetNamespace = xmlSchemaGetProp(pctxt, docElem,
10729 	    "targetNamespace");
10730     }
10731 
10732 /* after_doc_loading: */
10733     if ((bkt == NULL) && located) {
10734 	/* Only create a bucket if the schema was located. */
10735         bkt = xmlSchemaBucketCreate(pctxt, type,
10736 	    targetNamespace);
10737 	if (bkt == NULL)
10738 	    goto exit_failure;
10739     }
10740     if (bkt != NULL) {
10741 	bkt->schemaLocation = schemaLocation;
10742 	bkt->located = located;
10743 	if (doc != NULL) {
10744 	    bkt->doc = doc;
10745 	    bkt->targetNamespace = targetNamespace;
10746 	    bkt->origTargetNamespace = targetNamespace;
10747 	    if (preserveDoc)
10748 		bkt->preserveDoc = 1;
10749 	}
10750 	if (WXS_IS_BUCKET_IMPMAIN(type))
10751 	    bkt->imported++;
10752 	    /*
10753 	    * Add it to the graph of schemas.
10754 	    */
10755 	if (relation != NULL)
10756 	    relation->bucket = bkt;
10757     }
10758 
10759 exit:
10760     /*
10761     * Return the bucket explicitly; this is needed for the
10762     * main schema.
10763     */
10764     if (bucket != NULL)
10765 	*bucket = bkt;
10766     return (0);
10767 
10768 exit_error:
10769     if ((doc != NULL) && (! preserveDoc)) {
10770 	xmlFreeDoc(doc);
10771 	if (bkt != NULL)
10772 	    bkt->doc = NULL;
10773     }
10774     return(pctxt->err);
10775 
10776 exit_failure:
10777     if ((doc != NULL) && (! preserveDoc)) {
10778 	xmlFreeDoc(doc);
10779 	if (bkt != NULL)
10780 	    bkt->doc = NULL;
10781     }
10782     return (-1);
10783 }
10784 
10785 /**
10786  * xmlSchemaParseImport:
10787  * @ctxt:  a schema validation context
10788  * @schema:  the schema being built
10789  * @node:  a subtree containing XML Schema information
10790  *
10791  * parse a XML schema Import definition
10792  * *WARNING* this interface is highly subject to change
10793  *
10794  * Returns 0 in case of success, a positive error code if
10795  * not valid and -1 in case of an internal error.
10796  */
10797 static int
xmlSchemaParseImport(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node)10798 xmlSchemaParseImport(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
10799                      xmlNodePtr node)
10800 {
10801     xmlNodePtr child;
10802     const xmlChar *namespaceName = NULL, *schemaLocation = NULL;
10803     const xmlChar *thisTargetNamespace;
10804     xmlAttrPtr attr;
10805     int ret = 0;
10806     xmlSchemaBucketPtr bucket = NULL;
10807 
10808     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
10809         return (-1);
10810 
10811     /*
10812     * Check for illegal attributes.
10813     */
10814     attr = node->properties;
10815     while (attr != NULL) {
10816 	if (attr->ns == NULL) {
10817 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10818 		(!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
10819 		(!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
10820 		xmlSchemaPIllegalAttrErr(pctxt,
10821 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10822 	    }
10823 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10824 	    xmlSchemaPIllegalAttrErr(pctxt,
10825 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10826 	}
10827 	attr = attr->next;
10828     }
10829     /*
10830     * Extract and validate attributes.
10831     */
10832     if (xmlSchemaPValAttr(pctxt, NULL, node,
10833 	"namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10834 	&namespaceName) != 0) {
10835 	xmlSchemaPSimpleTypeErr(pctxt,
10836 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
10837 	    NULL, node,
10838 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10839 	    NULL, namespaceName, NULL, NULL, NULL);
10840 	return (pctxt->err);
10841     }
10842 
10843     if (xmlSchemaPValAttr(pctxt, NULL, node,
10844 	"schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10845 	&schemaLocation) != 0) {
10846 	xmlSchemaPSimpleTypeErr(pctxt,
10847 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
10848 	    NULL, node,
10849 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10850 	    NULL, schemaLocation, NULL, NULL, NULL);
10851 	return (pctxt->err);
10852     }
10853     /*
10854     * And now for the children...
10855     */
10856     child = node->children;
10857     if (IS_SCHEMA(child, "annotation")) {
10858         /*
10859          * the annotation here is simply discarded ...
10860 	 * TODO: really?
10861          */
10862         child = child->next;
10863     }
10864     if (child != NULL) {
10865 	xmlSchemaPContentErr(pctxt,
10866 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10867 	    NULL, node, child, NULL,
10868 	    "(annotation?)");
10869     }
10870     /*
10871     * Apply additional constraints.
10872     *
10873     * Note that it is important to use the original @targetNamespace
10874     * (or none at all), to rule out imports of schemas _with_ a
10875     * @targetNamespace if the importing schema is a chameleon schema
10876     * (with no @targetNamespace).
10877     */
10878     thisTargetNamespace = WXS_BUCKET(pctxt)->origTargetNamespace;
10879     if (namespaceName != NULL) {
10880 	/*
10881 	* 1.1 If the namespace [attribute] is present, then its `actual value`
10882 	* must not match the `actual value` of the enclosing <schema>'s
10883 	* targetNamespace [attribute].
10884 	*/
10885 	if (xmlStrEqual(thisTargetNamespace, namespaceName)) {
10886 	    xmlSchemaPCustomErr(pctxt,
10887 		XML_SCHEMAP_SRC_IMPORT_1_1,
10888 		NULL, node,
10889 		"The value of the attribute 'namespace' must not match "
10890 		"the target namespace '%s' of the importing schema",
10891 		thisTargetNamespace);
10892 	    return (pctxt->err);
10893 	}
10894     } else {
10895 	/*
10896 	* 1.2 If the namespace [attribute] is not present, then the enclosing
10897 	* <schema> must have a targetNamespace [attribute].
10898 	*/
10899 	if (thisTargetNamespace == NULL) {
10900 	    xmlSchemaPCustomErr(pctxt,
10901 		XML_SCHEMAP_SRC_IMPORT_1_2,
10902 		NULL, node,
10903 		"The attribute 'namespace' must be existent if "
10904 		"the importing schema has no target namespace",
10905 		NULL);
10906 	    return (pctxt->err);
10907 	}
10908     }
10909     /*
10910     * Locate and acquire the schema document.
10911     */
10912     if (schemaLocation != NULL)
10913 	schemaLocation = xmlSchemaBuildAbsoluteURI(pctxt->dict,
10914 	    schemaLocation, node);
10915     ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
10916 	schemaLocation, NULL, NULL, 0, node, thisTargetNamespace,
10917 	namespaceName, &bucket);
10918 
10919     if (ret != 0)
10920 	return(ret);
10921 
10922     /*
10923     * For <import>: "It is *not* an error for the application
10924     * schema reference strategy to fail."
10925     * So just don't parse if no schema document was found.
10926     * Note that we will get no bucket if the schema could not be
10927     * located or if there was no schemaLocation.
10928     */
10929     if ((bucket == NULL) && (schemaLocation != NULL)) {
10930 	xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10931 	    XML_SCHEMAP_WARN_UNLOCATED_SCHEMA,
10932 	    node, NULL,
10933 	    "Failed to locate a schema at location '%s'. "
10934 	    "Skipping the import", schemaLocation, NULL, NULL);
10935     }
10936 
10937     if ((bucket != NULL) && CAN_PARSE_SCHEMA(bucket)) {
10938 	ret = xmlSchemaParseNewDoc(pctxt, schema, bucket);
10939     }
10940 
10941     return (ret);
10942 }
10943 
10944 static int
xmlSchemaParseIncludeOrRedefineAttrs(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node,xmlChar ** schemaLocation,int type)10945 xmlSchemaParseIncludeOrRedefineAttrs(xmlSchemaParserCtxtPtr pctxt,
10946 				     xmlSchemaPtr schema,
10947 				     xmlNodePtr node,
10948 				     xmlChar **schemaLocation,
10949 				     int type)
10950 {
10951     xmlAttrPtr attr;
10952 
10953     if ((pctxt == NULL) || (schema == NULL) || (node == NULL) ||
10954 	(schemaLocation == NULL))
10955         return (-1);
10956 
10957     *schemaLocation = NULL;
10958     /*
10959     * Check for illegal attributes.
10960     * Applies for both <include> and <redefine>.
10961     */
10962     attr = node->properties;
10963     while (attr != NULL) {
10964 	if (attr->ns == NULL) {
10965 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10966 		(!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
10967 		xmlSchemaPIllegalAttrErr(pctxt,
10968 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10969 	    }
10970 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10971 	    xmlSchemaPIllegalAttrErr(pctxt,
10972 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10973 	}
10974 	attr = attr->next;
10975     }
10976     xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
10977     /*
10978     * Preliminary step, extract the URI-Reference and make an URI
10979     * from the base.
10980     */
10981     /*
10982     * Attribute "schemaLocation" is mandatory.
10983     */
10984     attr = xmlSchemaGetPropNode(node, "schemaLocation");
10985     if (attr != NULL) {
10986         xmlChar *base = NULL;
10987         xmlChar *uri = NULL;
10988 
10989 	if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
10990 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10991 	    (const xmlChar **) schemaLocation) != 0)
10992 	    goto exit_error;
10993 	base = xmlNodeGetBase(node->doc, node);
10994 	if (base == NULL) {
10995 	    uri = xmlBuildURI(*schemaLocation, node->doc->URL);
10996 	} else {
10997 	    uri = xmlBuildURI(*schemaLocation, base);
10998 	    xmlFree(base);
10999 	}
11000 	if (uri == NULL) {
11001 	    PERROR_INT("xmlSchemaParseIncludeOrRedefine",
11002 		"could not build an URI from the schemaLocation")
11003 	    goto exit_failure;
11004 	}
11005 	(*schemaLocation) = (xmlChar *) xmlDictLookup(pctxt->dict, uri, -1);
11006 	xmlFree(uri);
11007     } else {
11008 	xmlSchemaPMissingAttrErr(pctxt,
11009 	    XML_SCHEMAP_S4S_ATTR_MISSING,
11010 	    NULL, node, "schemaLocation", NULL);
11011 	goto exit_error;
11012     }
11013     /*
11014     * Report self-inclusion and self-redefinition.
11015     */
11016     if (xmlStrEqual(*schemaLocation, pctxt->URL)) {
11017 	if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
11018 	    xmlSchemaPCustomErr(pctxt,
11019 		XML_SCHEMAP_SRC_REDEFINE,
11020 		NULL, node,
11021 		"The schema document '%s' cannot redefine itself.",
11022 		*schemaLocation);
11023 	} else {
11024 	    xmlSchemaPCustomErr(pctxt,
11025 		XML_SCHEMAP_SRC_INCLUDE,
11026 		NULL, node,
11027 		"The schema document '%s' cannot include itself.",
11028 		*schemaLocation);
11029 	}
11030 	goto exit_error;
11031     }
11032 
11033     return(0);
11034 exit_error:
11035     return(pctxt->err);
11036 exit_failure:
11037     return(-1);
11038 }
11039 
11040 static int
xmlSchemaParseIncludeOrRedefine(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node,int type)11041 xmlSchemaParseIncludeOrRedefine(xmlSchemaParserCtxtPtr pctxt,
11042 				xmlSchemaPtr schema,
11043 				xmlNodePtr node,
11044 				int type)
11045 {
11046     xmlNodePtr child = NULL;
11047     const xmlChar *schemaLocation = NULL;
11048     int res = 0; /* hasRedefinitions = 0 */
11049     int isChameleon = 0, wasChameleon = 0;
11050     xmlSchemaBucketPtr bucket = NULL;
11051 
11052     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
11053         return (-1);
11054 
11055     /*
11056     * Parse attributes. Note that the returned schemaLocation will
11057     * be already converted to an absolute URI.
11058     */
11059     res = xmlSchemaParseIncludeOrRedefineAttrs(pctxt, schema,
11060 	node, (xmlChar **) (&schemaLocation), type);
11061     if (res != 0)
11062 	return(res);
11063     /*
11064     * Load and add the schema document.
11065     */
11066     res = xmlSchemaAddSchemaDoc(pctxt, type, schemaLocation, NULL,
11067 	NULL, 0, node, pctxt->targetNamespace, NULL, &bucket);
11068     if (res != 0)
11069 	return(res);
11070     /*
11071     * If we get no schema bucket back, then this means that the schema
11072     * document could not be located or was broken XML or was not
11073     * a schema document.
11074     */
11075     if ((bucket == NULL) || (bucket->doc == NULL)) {
11076 	if (type == XML_SCHEMA_SCHEMA_INCLUDE) {
11077 	    /*
11078 	    * WARNING for <include>:
11079 	    * We will raise an error if the schema cannot be located
11080 	    * for inclusions, since the that was the feedback from the
11081 	    * schema people. I.e. the following spec piece will *not* be
11082 	    * satisfied:
11083 	    * SPEC src-include: "It is not an error for the `actual value` of the
11084 	    * schemaLocation [attribute] to fail to resolve it all, in which
11085 	    * case no corresponding inclusion is performed.
11086 	    * So do we need a warning report here?"
11087 	    */
11088 	    res = XML_SCHEMAP_SRC_INCLUDE;
11089 	    xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
11090 		node, NULL,
11091 		"Failed to load the document '%s' for inclusion",
11092 		schemaLocation, NULL);
11093 	} else {
11094 	    /*
11095 	    * NOTE: This was changed to raise an error even if no redefinitions
11096 	    * are specified.
11097 	    *
11098 	    * SPEC src-redefine (1)
11099 	    * "If there are any element information items among the [children]
11100 	    * other than <annotation> then the `actual value` of the
11101 	    * schemaLocation [attribute] must successfully resolve."
11102 	    * TODO: Ask the WG if a the location has always to resolve
11103 	    * here as well!
11104 	    */
11105 	    res = XML_SCHEMAP_SRC_REDEFINE;
11106 	    xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
11107 		node, NULL,
11108 		"Failed to load the document '%s' for redefinition",
11109 		schemaLocation, NULL);
11110 	}
11111     } else {
11112 	/*
11113 	* Check targetNamespace sanity before parsing the new schema.
11114 	* TODO: Note that we won't check further content if the
11115 	* targetNamespace was bad.
11116 	*/
11117 	if (bucket->origTargetNamespace != NULL) {
11118 	    /*
11119 	    * SPEC src-include (2.1)
11120 	    * "SII has a targetNamespace [attribute], and its `actual
11121 	    * value` is identical to the `actual value` of the targetNamespace
11122 	    * [attribute] of SII' (which must have such an [attribute])."
11123 	    */
11124 	    if (pctxt->targetNamespace == NULL) {
11125 		xmlSchemaCustomErr(ACTXT_CAST pctxt,
11126 		    XML_SCHEMAP_SRC_INCLUDE,
11127 		    node, NULL,
11128 		    "The target namespace of the included/redefined schema "
11129 		    "'%s' has to be absent, since the including/redefining "
11130 		    "schema has no target namespace",
11131 		    schemaLocation, NULL);
11132 		goto exit_error;
11133 	    } else if (!xmlStrEqual(bucket->origTargetNamespace,
11134 		pctxt->targetNamespace)) {
11135 		/* TODO: Change error function. */
11136 		xmlSchemaPCustomErrExt(pctxt,
11137 		    XML_SCHEMAP_SRC_INCLUDE,
11138 		    NULL, node,
11139 		    "The target namespace '%s' of the included/redefined "
11140 		    "schema '%s' differs from '%s' of the "
11141 		    "including/redefining schema",
11142 		    bucket->origTargetNamespace, schemaLocation,
11143 		    pctxt->targetNamespace);
11144 		goto exit_error;
11145 	    }
11146 	} else if (pctxt->targetNamespace != NULL) {
11147 	    /*
11148 	    * Chameleons: the original target namespace will
11149 	    * differ from the resulting namespace.
11150 	    */
11151 	    isChameleon = 1;
11152 	    if (bucket->parsed &&
11153 		bucket->origTargetNamespace != NULL) {
11154 		xmlSchemaCustomErr(ACTXT_CAST pctxt,
11155 		    XML_SCHEMAP_SRC_INCLUDE,
11156 		    node, NULL,
11157 		    "The target namespace of the included/redefined schema "
11158 		    "'%s' has to be absent or the same as the "
11159 		    "including/redefining schema's target namespace",
11160 		    schemaLocation, NULL);
11161 		goto exit_error;
11162 	    }
11163 	    bucket->targetNamespace = pctxt->targetNamespace;
11164 	}
11165     }
11166     /*
11167     * Parse the schema.
11168     */
11169     if (bucket && (!bucket->parsed) && (bucket->doc != NULL)) {
11170 	if (isChameleon) {
11171 	    /* TODO: Get rid of this flag on the schema itself. */
11172 	    if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
11173 		schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11174 	    } else
11175 		wasChameleon = 1;
11176 	}
11177 	xmlSchemaParseNewDoc(pctxt, schema, bucket);
11178 	/* Restore chameleon flag. */
11179 	if (isChameleon && (!wasChameleon))
11180 	    schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11181     }
11182     /*
11183     * And now for the children...
11184     */
11185     child = node->children;
11186     if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
11187 	/*
11188 	* Parse (simpleType | complexType | group | attributeGroup))*
11189 	*/
11190 	pctxt->redefined = bucket;
11191 	/*
11192 	* How to proceed if the redefined schema was not located?
11193 	*/
11194 	pctxt->isRedefine = 1;
11195 	while (IS_SCHEMA(child, "annotation") ||
11196 	    IS_SCHEMA(child, "simpleType") ||
11197 	    IS_SCHEMA(child, "complexType") ||
11198 	    IS_SCHEMA(child, "group") ||
11199 	    IS_SCHEMA(child, "attributeGroup")) {
11200 	    if (IS_SCHEMA(child, "annotation")) {
11201 		/*
11202 		* TODO: discard or not?
11203 		*/
11204 	    } else if (IS_SCHEMA(child, "simpleType")) {
11205 		xmlSchemaParseSimpleType(pctxt, schema, child, 1);
11206 	    } else if (IS_SCHEMA(child, "complexType")) {
11207 		xmlSchemaParseComplexType(pctxt, schema, child, 1);
11208 		/* hasRedefinitions = 1; */
11209 	    } else if (IS_SCHEMA(child, "group")) {
11210 		/* hasRedefinitions = 1; */
11211 		xmlSchemaParseModelGroupDefinition(pctxt,
11212 		    schema, child);
11213 	    } else if (IS_SCHEMA(child, "attributeGroup")) {
11214 		/* hasRedefinitions = 1; */
11215 		xmlSchemaParseAttributeGroupDefinition(pctxt, schema,
11216 		    child);
11217 	    }
11218 	    child = child->next;
11219 	}
11220 	pctxt->redefined = NULL;
11221 	pctxt->isRedefine = 0;
11222     } else {
11223 	if (IS_SCHEMA(child, "annotation")) {
11224 	    /*
11225 	    * TODO: discard or not?
11226 	    */
11227 	    child = child->next;
11228 	}
11229     }
11230     if (child != NULL) {
11231 	res = XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED;
11232 	if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
11233 	    xmlSchemaPContentErr(pctxt, res,
11234 		NULL, node, child, NULL,
11235 		"(annotation | (simpleType | complexType | group | attributeGroup))*");
11236 	} else {
11237 	     xmlSchemaPContentErr(pctxt, res,
11238 		NULL, node, child, NULL,
11239 		"(annotation?)");
11240 	}
11241     }
11242     return(res);
11243 
11244 exit_error:
11245     return(pctxt->err);
11246 }
11247 
11248 static int
xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node)11249 xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11250                        xmlNodePtr node)
11251 {
11252     int res;
11253 #ifndef ENABLE_REDEFINE
11254     TODO
11255     return(0);
11256 #endif
11257     res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11258 	XML_SCHEMA_SCHEMA_REDEFINE);
11259     if (res != 0)
11260 	return(res);
11261     return(0);
11262 }
11263 
11264 static int
xmlSchemaParseInclude(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node)11265 xmlSchemaParseInclude(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11266                        xmlNodePtr node)
11267 {
11268     int res;
11269 
11270     res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11271 	XML_SCHEMA_SCHEMA_INCLUDE);
11272     if (res != 0)
11273 	return(res);
11274     return(0);
11275 }
11276 
11277 /**
11278  * xmlSchemaParseModelGroup:
11279  * @ctxt:  a schema validation context
11280  * @schema:  the schema being built
11281  * @node:  a subtree containing XML Schema information
11282  * @type: the "compositor" type
11283  * @particleNeeded: if a a model group with a particle
11284  *
11285  * parse a XML schema Sequence definition.
11286  * Applies parts of:
11287  *   Schema Representation Constraint:
11288  *     Redefinition Constraints and Semantics (src-redefine)
11289  *     (6.1), (6.1.1), (6.1.2)
11290  *
11291  *   Schema Component Constraint:
11292  *     All Group Limited (cos-all-limited) (2)
11293  *     TODO: Actually this should go to component-level checks,
11294  *     but is done here due to performance. Move it to an other layer
11295  *     is schema construction via an API is implemented.
11296  *
11297  * *WARNING* this interface is highly subject to change
11298  *
11299  * Returns -1 in case of error, 0 if the declaration is improper and
11300  *         1 in case of success.
11301  */
11302 static xmlSchemaTreeItemPtr
xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,xmlSchemaTypeType type,int withParticle)11303 xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11304 			 xmlNodePtr node, xmlSchemaTypeType type,
11305 			 int withParticle)
11306 {
11307     xmlSchemaModelGroupPtr item;
11308     xmlSchemaParticlePtr particle = NULL;
11309     xmlNodePtr child = NULL;
11310     xmlAttrPtr attr;
11311     int min = 1, max = 1, isElemRef, hasRefs = 0;
11312 
11313     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11314         return (NULL);
11315     /*
11316     * Create a model group with the given compositor.
11317     */
11318     item = xmlSchemaAddModelGroup(ctxt, schema, type, node);
11319     if (item == NULL)
11320 	return (NULL);
11321 
11322     if (withParticle) {
11323 	if (type == XML_SCHEMA_TYPE_ALL) {
11324 	    min = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
11325 	    max = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
11326 	} else {
11327 	    /* choice + sequence */
11328 	    min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
11329 	    max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
11330 		"(xs:nonNegativeInteger | unbounded)");
11331 	}
11332 	xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
11333 	/*
11334 	* Create a particle
11335 	*/
11336 	particle = xmlSchemaAddParticle(ctxt, node, min, max);
11337 	if (particle == NULL)
11338 	    return (NULL);
11339 	particle->children = (xmlSchemaTreeItemPtr) item;
11340 	/*
11341 	* Check for illegal attributes.
11342 	*/
11343 	attr = node->properties;
11344 	while (attr != NULL) {
11345 	    if (attr->ns == NULL) {
11346 		if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11347 		    (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
11348 		    (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
11349 		    xmlSchemaPIllegalAttrErr(ctxt,
11350 			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11351 		}
11352 	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11353 		xmlSchemaPIllegalAttrErr(ctxt,
11354 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11355 	    }
11356 	    attr = attr->next;
11357 	}
11358     } else {
11359 	/*
11360 	* Check for illegal attributes.
11361 	*/
11362 	attr = node->properties;
11363 	while (attr != NULL) {
11364 	    if (attr->ns == NULL) {
11365 		if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
11366 		    xmlSchemaPIllegalAttrErr(ctxt,
11367 			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11368 		}
11369 	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11370 		xmlSchemaPIllegalAttrErr(ctxt,
11371 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11372 	    }
11373 	    attr = attr->next;
11374 	}
11375     }
11376 
11377     /*
11378     * Extract and validate attributes.
11379     */
11380     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11381     /*
11382     * And now for the children...
11383     */
11384     child = node->children;
11385     if (IS_SCHEMA(child, "annotation")) {
11386         item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
11387         child = child->next;
11388     }
11389     if (type == XML_SCHEMA_TYPE_ALL) {
11390 	xmlSchemaParticlePtr part, last = NULL;
11391 
11392 	while (IS_SCHEMA(child, "element")) {
11393 	    part = (xmlSchemaParticlePtr) xmlSchemaParseElement(ctxt,
11394 		schema, child, &isElemRef, 0);
11395 	    /*
11396 	    * SPEC cos-all-limited (2)
11397 	    * "The {max occurs} of all the particles in the {particles}
11398 	    * of the ('all') group must be 0 or 1.
11399 	    */
11400 	    if (part != NULL) {
11401 		if (isElemRef)
11402 		    hasRefs++;
11403 		if (part->minOccurs > 1) {
11404 		    xmlSchemaPCustomErr(ctxt,
11405 			XML_SCHEMAP_COS_ALL_LIMITED,
11406 			NULL, child,
11407 			"Invalid value for minOccurs (must be 0 or 1)",
11408 			NULL);
11409 		    /* Reset to 1. */
11410 		    part->minOccurs = 1;
11411 		}
11412 		if (part->maxOccurs > 1) {
11413 		    xmlSchemaPCustomErr(ctxt,
11414 			XML_SCHEMAP_COS_ALL_LIMITED,
11415 			NULL, child,
11416 			"Invalid value for maxOccurs (must be 0 or 1)",
11417 			NULL);
11418 		    /* Reset to 1. */
11419 		    part->maxOccurs = 1;
11420 		}
11421 		if (last == NULL)
11422 		    item->children = (xmlSchemaTreeItemPtr) part;
11423 		else
11424 		    last->next = (xmlSchemaTreeItemPtr) part;
11425 		last = part;
11426 	    }
11427 	    child = child->next;
11428 	}
11429 	if (child != NULL) {
11430 	    xmlSchemaPContentErr(ctxt,
11431 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11432 		NULL, node, child, NULL,
11433 		"(annotation?, (annotation?, element*)");
11434 	}
11435     } else {
11436 	/* choice + sequence */
11437 	xmlSchemaTreeItemPtr part = NULL, last = NULL;
11438 
11439 	while ((IS_SCHEMA(child, "element")) ||
11440 	    (IS_SCHEMA(child, "group")) ||
11441 	    (IS_SCHEMA(child, "any")) ||
11442 	    (IS_SCHEMA(child, "choice")) ||
11443 	    (IS_SCHEMA(child, "sequence"))) {
11444 
11445 	    if (IS_SCHEMA(child, "element")) {
11446 		part = (xmlSchemaTreeItemPtr)
11447 		    xmlSchemaParseElement(ctxt, schema, child, &isElemRef, 0);
11448 		if (part && isElemRef)
11449 		    hasRefs++;
11450 	    } else if (IS_SCHEMA(child, "group")) {
11451 		part =
11452 		    xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11453 		if (part != NULL)
11454 		    hasRefs++;
11455 		/*
11456 		* Handle redefinitions.
11457 		*/
11458 		if (ctxt->isRedefine && ctxt->redef &&
11459 		    (ctxt->redef->item->type == XML_SCHEMA_TYPE_GROUP) &&
11460 		    part && part->children)
11461 		{
11462 		    if ((xmlSchemaGetQNameRefName(part->children) ==
11463 			    ctxt->redef->refName) &&
11464 			(xmlSchemaGetQNameRefTargetNs(part->children) ==
11465 			    ctxt->redef->refTargetNs))
11466 		    {
11467 			/*
11468 			* SPEC src-redefine:
11469 			* (6.1) "If it has a <group> among its contents at
11470 			* some level the `actual value` of whose ref
11471 			* [attribute] is the same as the `actual value` of
11472 			* its own name attribute plus target namespace, then
11473 			* all of the following must be true:"
11474 			* (6.1.1) "It must have exactly one such group."
11475 			*/
11476 			if (ctxt->redefCounter != 0) {
11477 			    xmlChar *str = NULL;
11478 
11479 			    xmlSchemaCustomErr(ACTXT_CAST ctxt,
11480 				XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11481 				"The redefining model group definition "
11482 				"'%s' must not contain more than one "
11483 				"reference to the redefined definition",
11484 				xmlSchemaFormatQName(&str,
11485 				    ctxt->redef->refTargetNs,
11486 				    ctxt->redef->refName),
11487 				NULL);
11488 			    FREE_AND_NULL(str)
11489 			    part = NULL;
11490 			} else if (((WXS_PARTICLE(part))->minOccurs != 1) ||
11491 			    ((WXS_PARTICLE(part))->maxOccurs != 1))
11492 			{
11493 			    xmlChar *str = NULL;
11494 			    /*
11495 			    * SPEC src-redefine:
11496 			    * (6.1.2) "The `actual value` of both that
11497 			    * group's minOccurs and maxOccurs [attribute]
11498 			    * must be 1 (or `absent`).
11499 			    */
11500 			    xmlSchemaCustomErr(ACTXT_CAST ctxt,
11501 				XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11502 				"The redefining model group definition "
11503 				"'%s' must not contain a reference to the "
11504 				"redefined definition with a "
11505 				"maxOccurs/minOccurs other than 1",
11506 				xmlSchemaFormatQName(&str,
11507 				    ctxt->redef->refTargetNs,
11508 				    ctxt->redef->refName),
11509 				NULL);
11510 			    FREE_AND_NULL(str)
11511 			    part = NULL;
11512 			}
11513 			ctxt->redef->reference = WXS_BASIC_CAST part;
11514 			ctxt->redefCounter++;
11515 		    }
11516 		}
11517 	    } else if (IS_SCHEMA(child, "any")) {
11518 		part = (xmlSchemaTreeItemPtr)
11519 		    xmlSchemaParseAny(ctxt, schema, child);
11520 	    } else if (IS_SCHEMA(child, "choice")) {
11521 		part = xmlSchemaParseModelGroup(ctxt, schema, child,
11522 		    XML_SCHEMA_TYPE_CHOICE, 1);
11523 	    } else if (IS_SCHEMA(child, "sequence")) {
11524 		part = xmlSchemaParseModelGroup(ctxt, schema, child,
11525 		    XML_SCHEMA_TYPE_SEQUENCE, 1);
11526 	    }
11527 	    if (part != NULL) {
11528 		if (last == NULL)
11529 		    item->children = part;
11530 		else
11531 		    last->next = part;
11532 		last = part;
11533 	    }
11534 	    child = child->next;
11535 	}
11536 	if (child != NULL) {
11537 	    xmlSchemaPContentErr(ctxt,
11538 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11539 		NULL, node, child, NULL,
11540 		"(annotation?, (element | group | choice | sequence | any)*)");
11541 	}
11542     }
11543     if ((max == 0) && (min == 0))
11544 	return (NULL);
11545     if (hasRefs) {
11546 	/*
11547 	* We need to resolve references.
11548 	*/
11549 	WXS_ADD_PENDING(ctxt, item);
11550     }
11551     if (withParticle)
11552 	return ((xmlSchemaTreeItemPtr) particle);
11553     else
11554 	return ((xmlSchemaTreeItemPtr) item);
11555 }
11556 
11557 /**
11558  * xmlSchemaParseRestriction:
11559  * @ctxt:  a schema validation context
11560  * @schema:  the schema being built
11561  * @node:  a subtree containing XML Schema information
11562  *
11563  * parse a XML schema Restriction definition
11564  * *WARNING* this interface is highly subject to change
11565  *
11566  * Returns the type definition or NULL in case of error
11567  */
11568 static xmlSchemaTypePtr
xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,xmlSchemaTypeType parentType)11569 xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11570                           xmlNodePtr node, xmlSchemaTypeType parentType)
11571 {
11572     xmlSchemaTypePtr type;
11573     xmlNodePtr child = NULL;
11574     xmlAttrPtr attr;
11575 
11576     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11577         return (NULL);
11578     /* Not a component, don't create it. */
11579     type = ctxt->ctxtType;
11580     type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
11581 
11582     /*
11583     * Check for illegal attributes.
11584     */
11585     attr = node->properties;
11586     while (attr != NULL) {
11587 	if (attr->ns == NULL) {
11588 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11589 		(!xmlStrEqual(attr->name, BAD_CAST "base"))) {
11590 		xmlSchemaPIllegalAttrErr(ctxt,
11591 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11592 	    }
11593 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11594 	    xmlSchemaPIllegalAttrErr(ctxt,
11595 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11596 	}
11597 	attr = attr->next;
11598     }
11599     /*
11600     * Extract and validate attributes.
11601     */
11602     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11603     /*
11604     * Attribute
11605     */
11606     /*
11607     * Extract the base type. The "base" attribute is mandatory if inside
11608     * a complex type or if redefining.
11609     *
11610     * SPEC (1.2) "...otherwise (<restriction> has no <simpleType> "
11611     * among its [children]), the simple type definition which is
11612     * the {content type} of the type definition `resolved` to by
11613     * the `actual value` of the base [attribute]"
11614     */
11615     if (xmlSchemaPValAttrQName(ctxt, schema, NULL, node, "base",
11616 	&(type->baseNs), &(type->base)) == 0)
11617     {
11618 	if ((type->base == NULL) && (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
11619 	    xmlSchemaPMissingAttrErr(ctxt,
11620 		XML_SCHEMAP_S4S_ATTR_MISSING,
11621 		NULL, node, "base", NULL);
11622 	} else if ((ctxt->isRedefine) &&
11623 	    (type->flags & XML_SCHEMAS_TYPE_GLOBAL))
11624 	{
11625 	    if (type->base == NULL) {
11626 		xmlSchemaPMissingAttrErr(ctxt,
11627 		    XML_SCHEMAP_S4S_ATTR_MISSING,
11628 		    NULL, node, "base", NULL);
11629 	    } else if ((! xmlStrEqual(type->base, type->name)) ||
11630 		(! xmlStrEqual(type->baseNs, type->targetNamespace)))
11631 	    {
11632 		xmlChar *str1 = NULL, *str2 = NULL;
11633 		/*
11634 		* REDEFINE: SPEC src-redefine (5)
11635 		* "Within the [children], each <simpleType> must have a
11636 		* <restriction> among its [children] ... the `actual value` of
11637 		* whose base [attribute] must be the same as the `actual value`
11638 		* of its own name attribute plus target namespace;"
11639 		*/
11640 		xmlSchemaPCustomErrExt(ctxt, XML_SCHEMAP_SRC_REDEFINE,
11641 		    NULL, node, "This is a redefinition, but the QName "
11642 		    "value '%s' of the 'base' attribute does not match the "
11643 		    "type's designation '%s'",
11644 		    xmlSchemaFormatQName(&str1, type->baseNs, type->base),
11645 		    xmlSchemaFormatQName(&str2, type->targetNamespace,
11646 			type->name), NULL);
11647 		FREE_AND_NULL(str1);
11648 		FREE_AND_NULL(str2);
11649 		/* Avoid confusion and erase the values. */
11650 		type->base = NULL;
11651 		type->baseNs = NULL;
11652 	    }
11653 	}
11654     }
11655     /*
11656     * And now for the children...
11657     */
11658     child = node->children;
11659     if (IS_SCHEMA(child, "annotation")) {
11660 	/*
11661 	* Add the annotation to the simple type ancestor.
11662 	*/
11663 	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11664 	    xmlSchemaParseAnnotation(ctxt, child, 1));
11665         child = child->next;
11666     }
11667     if (parentType == XML_SCHEMA_TYPE_SIMPLE) {
11668 	/*
11669 	* Corresponds to <simpleType><restriction><simpleType>.
11670 	*/
11671 	if (IS_SCHEMA(child, "simpleType")) {
11672 	    if (type->base != NULL) {
11673 		/*
11674 		* src-restriction-base-or-simpleType
11675 		* Either the base [attribute] or the simpleType [child] of the
11676 		* <restriction> element must be present, but not both.
11677 		*/
11678 		xmlSchemaPContentErr(ctxt,
11679 		    XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
11680 		    NULL, node, child,
11681 		    "The attribute 'base' and the <simpleType> child are "
11682 		    "mutually exclusive", NULL);
11683 	    } else {
11684 		type->baseType = (xmlSchemaTypePtr)
11685 		    xmlSchemaParseSimpleType(ctxt, schema, child, 0);
11686 	    }
11687 	    child = child->next;
11688 	} else if (type->base == NULL) {
11689 	    xmlSchemaPContentErr(ctxt,
11690 		XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
11691 		NULL, node, child,
11692 		"Either the attribute 'base' or a <simpleType> child "
11693 		"must be present", NULL);
11694 	}
11695     } else if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11696 	/*
11697 	* Corresponds to <complexType><complexContent><restriction>...
11698 	* followed by:
11699 	*
11700 	* Model groups <all>, <choice> and <sequence>.
11701 	*/
11702 	if (IS_SCHEMA(child, "all")) {
11703 	    type->subtypes = (xmlSchemaTypePtr)
11704 		xmlSchemaParseModelGroup(ctxt, schema, child,
11705 		    XML_SCHEMA_TYPE_ALL, 1);
11706 	    child = child->next;
11707 	} else if (IS_SCHEMA(child, "choice")) {
11708 	    type->subtypes = (xmlSchemaTypePtr)
11709 		xmlSchemaParseModelGroup(ctxt,
11710 		    schema, child, XML_SCHEMA_TYPE_CHOICE, 1);
11711 	    child = child->next;
11712 	} else if (IS_SCHEMA(child, "sequence")) {
11713 	    type->subtypes = (xmlSchemaTypePtr)
11714 		xmlSchemaParseModelGroup(ctxt, schema, child,
11715 		    XML_SCHEMA_TYPE_SEQUENCE, 1);
11716 	    child = child->next;
11717 	/*
11718 	* Model group reference <group>.
11719 	*/
11720 	} else if (IS_SCHEMA(child, "group")) {
11721 	    type->subtypes = (xmlSchemaTypePtr)
11722 		xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11723 	    /*
11724 	    * Note that the reference will be resolved in
11725 	    * xmlSchemaResolveTypeReferences();
11726 	    */
11727 	    child = child->next;
11728 	}
11729     } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
11730 	/*
11731 	* Corresponds to <complexType><simpleContent><restriction>...
11732 	*
11733 	* "1.1 the simple type definition corresponding to the <simpleType>
11734 	* among the [children] of <restriction> if there is one;"
11735 	*/
11736 	if (IS_SCHEMA(child, "simpleType")) {
11737 	    /*
11738 	    * We will store the to-be-restricted simple type in
11739 	    * type->contentTypeDef *temporarily*.
11740 	    */
11741 	    type->contentTypeDef = (xmlSchemaTypePtr)
11742 		xmlSchemaParseSimpleType(ctxt, schema, child, 0);
11743 	    if ( type->contentTypeDef == NULL)
11744 		return (NULL);
11745 	    child = child->next;
11746 	}
11747     }
11748 
11749     if ((parentType == XML_SCHEMA_TYPE_SIMPLE) ||
11750 	(parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
11751 	xmlSchemaFacetPtr facet, lastfacet = NULL;
11752 	/*
11753 	* Corresponds to <complexType><simpleContent><restriction>...
11754 	* <simpleType><restriction>...
11755 	*/
11756 
11757 	/*
11758 	* Add the facets to the simple type ancestor.
11759 	*/
11760 	/*
11761 	* TODO: Datatypes: 4.1.3 Constraints on XML Representation of
11762 	* Simple Type Definition Schema Representation Constraint:
11763 	* *Single Facet Value*
11764 	*/
11765 	while ((IS_SCHEMA(child, "minInclusive")) ||
11766 	    (IS_SCHEMA(child, "minExclusive")) ||
11767 	    (IS_SCHEMA(child, "maxInclusive")) ||
11768 	    (IS_SCHEMA(child, "maxExclusive")) ||
11769 	    (IS_SCHEMA(child, "totalDigits")) ||
11770 	    (IS_SCHEMA(child, "fractionDigits")) ||
11771 	    (IS_SCHEMA(child, "pattern")) ||
11772 	    (IS_SCHEMA(child, "enumeration")) ||
11773 	    (IS_SCHEMA(child, "whiteSpace")) ||
11774 	    (IS_SCHEMA(child, "length")) ||
11775 	    (IS_SCHEMA(child, "maxLength")) ||
11776 	    (IS_SCHEMA(child, "minLength"))) {
11777 	    facet = xmlSchemaParseFacet(ctxt, schema, child);
11778 	    if (facet != NULL) {
11779 		if (lastfacet == NULL)
11780 		    type->facets = facet;
11781 		else
11782 		    lastfacet->next = facet;
11783 		lastfacet = facet;
11784 		lastfacet->next = NULL;
11785 	    }
11786 	    child = child->next;
11787 	}
11788 	/*
11789 	* Create links for derivation and validation.
11790 	*/
11791 	if (type->facets != NULL) {
11792 	    xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
11793 
11794 	    facet = type->facets;
11795 	    do {
11796 		facetLink = (xmlSchemaFacetLinkPtr)
11797 		    xmlMalloc(sizeof(xmlSchemaFacetLink));
11798 		if (facetLink == NULL) {
11799 		    xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
11800 		    xmlFree(facetLink);
11801 		    return (NULL);
11802 		}
11803 		facetLink->facet = facet;
11804 		facetLink->next = NULL;
11805 		if (lastFacetLink == NULL)
11806 		    type->facetSet = facetLink;
11807 		else
11808 		    lastFacetLink->next = facetLink;
11809 		lastFacetLink = facetLink;
11810 		facet = facet->next;
11811 	    } while (facet != NULL);
11812 	}
11813     }
11814     if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
11815 	/*
11816 	* Attribute uses/declarations.
11817 	*/
11818 	if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11819 	    (xmlSchemaItemListPtr *) &(type->attrUses),
11820 	    XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
11821 	    return(NULL);
11822 	/*
11823 	* Attribute wildcard.
11824 	*/
11825 	if (IS_SCHEMA(child, "anyAttribute")) {
11826 	    type->attributeWildcard =
11827 		xmlSchemaParseAnyAttribute(ctxt, schema, child);
11828 	    child = child->next;
11829 	}
11830     }
11831     if (child != NULL) {
11832 	if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11833 	    xmlSchemaPContentErr(ctxt,
11834 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11835 		NULL, node, child, NULL,
11836 		"annotation?, (group | all | choice | sequence)?, "
11837 		"((attribute | attributeGroup)*, anyAttribute?))");
11838 	} else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
11839 	     xmlSchemaPContentErr(ctxt,
11840 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11841 		NULL, node, child, NULL,
11842 		"(annotation?, (simpleType?, (minExclusive | minInclusive | "
11843 		"maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11844 		"length | minLength | maxLength | enumeration | whiteSpace | "
11845 		"pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
11846 	} else {
11847 	    /* Simple type */
11848 	    xmlSchemaPContentErr(ctxt,
11849 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11850 		NULL, node, child, NULL,
11851 		"(annotation?, (simpleType?, (minExclusive | minInclusive | "
11852 		"maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11853 		"length | minLength | maxLength | enumeration | whiteSpace | "
11854 		"pattern)*))");
11855 	}
11856     }
11857     return (NULL);
11858 }
11859 
11860 /**
11861  * xmlSchemaParseExtension:
11862  * @ctxt:  a schema validation context
11863  * @schema:  the schema being built
11864  * @node:  a subtree containing XML Schema information
11865  *
11866  * Parses an <extension>, which is found inside a
11867  * <simpleContent> or <complexContent>.
11868  * *WARNING* this interface is highly subject to change.
11869  *
11870  * TODO: Returns the type definition or NULL in case of error
11871  */
11872 static xmlSchemaTypePtr
xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,xmlSchemaTypeType parentType)11873 xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11874                         xmlNodePtr node, xmlSchemaTypeType parentType)
11875 {
11876     xmlSchemaTypePtr type;
11877     xmlNodePtr child = NULL;
11878     xmlAttrPtr attr;
11879 
11880     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11881         return (NULL);
11882     /* Not a component, don't create it. */
11883     type = ctxt->ctxtType;
11884     type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
11885 
11886     /*
11887     * Check for illegal attributes.
11888     */
11889     attr = node->properties;
11890     while (attr != NULL) {
11891 	if (attr->ns == NULL) {
11892 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11893 		(!xmlStrEqual(attr->name, BAD_CAST "base"))) {
11894 		xmlSchemaPIllegalAttrErr(ctxt,
11895 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11896 	    }
11897 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11898 	    xmlSchemaPIllegalAttrErr(ctxt,
11899 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11900 	}
11901 	attr = attr->next;
11902     }
11903 
11904     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11905 
11906     /*
11907     * Attribute "base" - mandatory.
11908     */
11909     if ((xmlSchemaPValAttrQName(ctxt, schema, NULL, node,
11910 	"base", &(type->baseNs), &(type->base)) == 0) &&
11911 	(type->base == NULL)) {
11912 	xmlSchemaPMissingAttrErr(ctxt,
11913 	    XML_SCHEMAP_S4S_ATTR_MISSING,
11914 	    NULL, node, "base", NULL);
11915     }
11916     /*
11917     * And now for the children...
11918     */
11919     child = node->children;
11920     if (IS_SCHEMA(child, "annotation")) {
11921 	/*
11922 	* Add the annotation to the type ancestor.
11923 	*/
11924 	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11925 	    xmlSchemaParseAnnotation(ctxt, child, 1));
11926         child = child->next;
11927     }
11928     if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11929 	/*
11930 	* Corresponds to <complexType><complexContent><extension>... and:
11931 	*
11932 	* Model groups <all>, <choice>, <sequence> and <group>.
11933 	*/
11934 	if (IS_SCHEMA(child, "all")) {
11935 	    type->subtypes = (xmlSchemaTypePtr)
11936 		xmlSchemaParseModelGroup(ctxt, schema,
11937 		    child, XML_SCHEMA_TYPE_ALL, 1);
11938 	    child = child->next;
11939 	} else if (IS_SCHEMA(child, "choice")) {
11940 	    type->subtypes = (xmlSchemaTypePtr)
11941 		xmlSchemaParseModelGroup(ctxt, schema,
11942 		    child, XML_SCHEMA_TYPE_CHOICE, 1);
11943 	    child = child->next;
11944 	} else if (IS_SCHEMA(child, "sequence")) {
11945 	    type->subtypes = (xmlSchemaTypePtr)
11946 		xmlSchemaParseModelGroup(ctxt, schema,
11947 		child, XML_SCHEMA_TYPE_SEQUENCE, 1);
11948 	    child = child->next;
11949 	} else if (IS_SCHEMA(child, "group")) {
11950 	    type->subtypes = (xmlSchemaTypePtr)
11951 		xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11952 	    /*
11953 	    * Note that the reference will be resolved in
11954 	    * xmlSchemaResolveTypeReferences();
11955 	    */
11956 	    child = child->next;
11957 	}
11958     }
11959     if (child != NULL) {
11960 	/*
11961 	* Attribute uses/declarations.
11962 	*/
11963 	if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11964 	    (xmlSchemaItemListPtr *) &(type->attrUses),
11965 	    XML_SCHEMA_TYPE_EXTENSION, NULL) == -1)
11966 	    return(NULL);
11967 	/*
11968 	* Attribute wildcard.
11969 	*/
11970 	if (IS_SCHEMA(child, "anyAttribute")) {
11971 	    ctxt->ctxtType->attributeWildcard =
11972 		xmlSchemaParseAnyAttribute(ctxt, schema, child);
11973 	    child = child->next;
11974 	}
11975     }
11976     if (child != NULL) {
11977 	if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11978 	    /* Complex content extension. */
11979 	    xmlSchemaPContentErr(ctxt,
11980 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11981 		NULL, node, child, NULL,
11982 		"(annotation?, ((group | all | choice | sequence)?, "
11983 		"((attribute | attributeGroup)*, anyAttribute?)))");
11984 	} else {
11985 	    /* Simple content extension. */
11986 	    xmlSchemaPContentErr(ctxt,
11987 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11988 		NULL, node, child, NULL,
11989 		"(annotation?, ((attribute | attributeGroup)*, "
11990 		"anyAttribute?))");
11991 	}
11992     }
11993     return (NULL);
11994 }
11995 
11996 /**
11997  * xmlSchemaParseSimpleContent:
11998  * @ctxt:  a schema validation context
11999  * @schema:  the schema being built
12000  * @node:  a subtree containing XML Schema information
12001  *
12002  * parse a XML schema SimpleContent definition
12003  * *WARNING* this interface is highly subject to change
12004  *
12005  * Returns the type definition or NULL in case of error
12006  */
12007 static int
xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,int * hasRestrictionOrExtension)12008 xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
12009                             xmlSchemaPtr schema, xmlNodePtr node,
12010 			    int *hasRestrictionOrExtension)
12011 {
12012     xmlSchemaTypePtr type;
12013     xmlNodePtr child = NULL;
12014     xmlAttrPtr attr;
12015 
12016     if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
12017 	(hasRestrictionOrExtension == NULL))
12018         return (-1);
12019     *hasRestrictionOrExtension = 0;
12020     /* Not a component, don't create it. */
12021     type = ctxt->ctxtType;
12022     type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
12023     /*
12024     * Check for illegal attributes.
12025     */
12026     attr = node->properties;
12027     while (attr != NULL) {
12028 	if (attr->ns == NULL) {
12029 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id"))) {
12030 		xmlSchemaPIllegalAttrErr(ctxt,
12031 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12032 	    }
12033 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
12034 	    xmlSchemaPIllegalAttrErr(ctxt,
12035 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12036 	}
12037 	attr = attr->next;
12038     }
12039 
12040     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
12041 
12042     /*
12043     * And now for the children...
12044     */
12045     child = node->children;
12046     if (IS_SCHEMA(child, "annotation")) {
12047 	/*
12048 	* Add the annotation to the complex type ancestor.
12049 	*/
12050 	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
12051 	    xmlSchemaParseAnnotation(ctxt, child, 1));
12052         child = child->next;
12053     }
12054     if (child == NULL) {
12055 	xmlSchemaPContentErr(ctxt,
12056 	    XML_SCHEMAP_S4S_ELEM_MISSING,
12057 	    NULL, node, NULL, NULL,
12058 	    "(annotation?, (restriction | extension))");
12059     }
12060     if (child == NULL) {
12061 	xmlSchemaPContentErr(ctxt,
12062 	    XML_SCHEMAP_S4S_ELEM_MISSING,
12063 	    NULL, node, NULL, NULL,
12064 	    "(annotation?, (restriction | extension))");
12065     }
12066     if (IS_SCHEMA(child, "restriction")) {
12067         xmlSchemaParseRestriction(ctxt, schema, child,
12068 	    XML_SCHEMA_TYPE_SIMPLE_CONTENT);
12069 	(*hasRestrictionOrExtension) = 1;
12070         child = child->next;
12071     } else if (IS_SCHEMA(child, "extension")) {
12072         xmlSchemaParseExtension(ctxt, schema, child,
12073 	    XML_SCHEMA_TYPE_SIMPLE_CONTENT);
12074 	(*hasRestrictionOrExtension) = 1;
12075         child = child->next;
12076     }
12077     if (child != NULL) {
12078 	xmlSchemaPContentErr(ctxt,
12079 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
12080 	    NULL, node, child, NULL,
12081 	    "(annotation?, (restriction | extension))");
12082     }
12083     return (0);
12084 }
12085 
12086 /**
12087  * xmlSchemaParseComplexContent:
12088  * @ctxt:  a schema validation context
12089  * @schema:  the schema being built
12090  * @node:  a subtree containing XML Schema information
12091  *
12092  * parse a XML schema ComplexContent definition
12093  * *WARNING* this interface is highly subject to change
12094  *
12095  * Returns the type definition or NULL in case of error
12096  */
12097 static int
xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,int * hasRestrictionOrExtension)12098 xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
12099                              xmlSchemaPtr schema, xmlNodePtr node,
12100 			     int *hasRestrictionOrExtension)
12101 {
12102     xmlSchemaTypePtr type;
12103     xmlNodePtr child = NULL;
12104     xmlAttrPtr attr;
12105 
12106     if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
12107 	(hasRestrictionOrExtension == NULL))
12108         return (-1);
12109     *hasRestrictionOrExtension = 0;
12110     /* Not a component, don't create it. */
12111     type = ctxt->ctxtType;
12112     /*
12113     * Check for illegal attributes.
12114     */
12115     attr = node->properties;
12116     while (attr != NULL) {
12117 	if (attr->ns == NULL) {
12118 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
12119 		(!xmlStrEqual(attr->name, BAD_CAST "mixed")))
12120 	    {
12121 		xmlSchemaPIllegalAttrErr(ctxt,
12122 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12123 	    }
12124 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
12125 	    xmlSchemaPIllegalAttrErr(ctxt,
12126 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12127 	}
12128 	attr = attr->next;
12129     }
12130 
12131     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
12132 
12133     /*
12134     * Set the 'mixed' on the complex type ancestor.
12135     */
12136     if (xmlGetBooleanProp(ctxt, node, "mixed", 0))  {
12137 	if ((type->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
12138 	    type->flags |= XML_SCHEMAS_TYPE_MIXED;
12139     }
12140     child = node->children;
12141     if (IS_SCHEMA(child, "annotation")) {
12142 	/*
12143 	* Add the annotation to the complex type ancestor.
12144 	*/
12145 	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
12146 	    xmlSchemaParseAnnotation(ctxt, child, 1));
12147         child = child->next;
12148     }
12149     if (child == NULL) {
12150 	xmlSchemaPContentErr(ctxt,
12151 	    XML_SCHEMAP_S4S_ELEM_MISSING,
12152 	    NULL, node, NULL,
12153 	    NULL, "(annotation?, (restriction | extension))");
12154     }
12155     if (child == NULL) {
12156 	xmlSchemaPContentErr(ctxt,
12157 	    XML_SCHEMAP_S4S_ELEM_MISSING,
12158 	    NULL, node, NULL,
12159 	    NULL, "(annotation?, (restriction | extension))");
12160     }
12161     if (IS_SCHEMA(child, "restriction")) {
12162         xmlSchemaParseRestriction(ctxt, schema, child,
12163 	    XML_SCHEMA_TYPE_COMPLEX_CONTENT);
12164 	(*hasRestrictionOrExtension) = 1;
12165         child = child->next;
12166     } else if (IS_SCHEMA(child, "extension")) {
12167         xmlSchemaParseExtension(ctxt, schema, child,
12168 	    XML_SCHEMA_TYPE_COMPLEX_CONTENT);
12169 	(*hasRestrictionOrExtension) = 1;
12170         child = child->next;
12171     }
12172     if (child != NULL) {
12173 	xmlSchemaPContentErr(ctxt,
12174 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
12175 	    NULL, node, child,
12176 	    NULL, "(annotation?, (restriction | extension))");
12177     }
12178     return (0);
12179 }
12180 
12181 /**
12182  * xmlSchemaParseComplexType:
12183  * @ctxt:  a schema validation context
12184  * @schema:  the schema being built
12185  * @node:  a subtree containing XML Schema information
12186  *
12187  * parse a XML schema Complex Type definition
12188  * *WARNING* this interface is highly subject to change
12189  *
12190  * Returns the type definition or NULL in case of error
12191  */
12192 static xmlSchemaTypePtr
xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,int topLevel)12193 xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
12194                           xmlNodePtr node, int topLevel)
12195 {
12196     xmlSchemaTypePtr type, ctxtType;
12197     xmlNodePtr child = NULL;
12198     const xmlChar *name = NULL;
12199     xmlAttrPtr attr;
12200     const xmlChar *attrValue;
12201 #ifdef ENABLE_NAMED_LOCALS
12202     char buf[40];
12203 #endif
12204     int final = 0, block = 0, hasRestrictionOrExtension = 0;
12205 
12206 
12207     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
12208         return (NULL);
12209 
12210     ctxtType = ctxt->ctxtType;
12211 
12212     if (topLevel) {
12213 	attr = xmlSchemaGetPropNode(node, "name");
12214 	if (attr == NULL) {
12215 	    xmlSchemaPMissingAttrErr(ctxt,
12216 		XML_SCHEMAP_S4S_ATTR_MISSING, NULL, node, "name", NULL);
12217 	    return (NULL);
12218 	} else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
12219 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
12220 	    return (NULL);
12221 	}
12222     }
12223 
12224     if (topLevel == 0) {
12225 	/*
12226 	* Parse as local complex type definition.
12227 	*/
12228 #ifdef ENABLE_NAMED_LOCALS
12229         snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
12230 	type = xmlSchemaAddType(ctxt, schema,
12231 	    XML_SCHEMA_TYPE_COMPLEX,
12232 	    xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
12233 	    ctxt->targetNamespace, node, 0);
12234 #else
12235 	type = xmlSchemaAddType(ctxt, schema,
12236 	    XML_SCHEMA_TYPE_COMPLEX,
12237 	    NULL, ctxt->targetNamespace, node, 0);
12238 #endif
12239 	if (type == NULL)
12240 	    return (NULL);
12241 	name = type->name;
12242 	type->node = node;
12243 	type->type = XML_SCHEMA_TYPE_COMPLEX;
12244 	/*
12245 	* TODO: We need the target namespace.
12246 	*/
12247     } else {
12248 	/*
12249 	* Parse as global complex type definition.
12250 	*/
12251 	type = xmlSchemaAddType(ctxt, schema,
12252 	    XML_SCHEMA_TYPE_COMPLEX,
12253 	    name, ctxt->targetNamespace, node, 1);
12254 	if (type == NULL)
12255 	    return (NULL);
12256 	type->node = node;
12257 	type->type = XML_SCHEMA_TYPE_COMPLEX;
12258 	type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
12259     }
12260     type->targetNamespace = ctxt->targetNamespace;
12261     /*
12262     * Handle attributes.
12263     */
12264     attr = node->properties;
12265     while (attr != NULL) {
12266 	if (attr->ns == NULL) {
12267 	    if (xmlStrEqual(attr->name, BAD_CAST "id")) {
12268 		/*
12269 		* Attribute "id".
12270 		*/
12271 		xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
12272 	    } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
12273 		/*
12274 		* Attribute "mixed".
12275 		*/
12276 		if (xmlSchemaPGetBoolNodeValue(ctxt,
12277 			NULL, (xmlNodePtr) attr))
12278 		    type->flags |= XML_SCHEMAS_TYPE_MIXED;
12279 	    } else if (topLevel) {
12280 		/*
12281 		* Attributes of global complex type definitions.
12282 		*/
12283 		if (xmlStrEqual(attr->name, BAD_CAST "name")) {
12284 		    /* Pass. */
12285 		} else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
12286 		    /*
12287 		    * Attribute "abstract".
12288 		    */
12289 		    if (xmlSchemaPGetBoolNodeValue(ctxt,
12290 			    NULL, (xmlNodePtr) attr))
12291 			type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
12292 		} else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
12293 		    /*
12294 		    * Attribute "final".
12295 		    */
12296 		    attrValue = xmlSchemaGetNodeContent(ctxt,
12297 			(xmlNodePtr) attr);
12298 		    if (xmlSchemaPValAttrBlockFinal(attrValue,
12299 			&(type->flags),
12300 			-1,
12301 			XML_SCHEMAS_TYPE_FINAL_EXTENSION,
12302 			XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
12303 			-1, -1, -1) != 0)
12304 		    {
12305 			xmlSchemaPSimpleTypeErr(ctxt,
12306 			    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
12307 			    NULL, (xmlNodePtr) attr, NULL,
12308 			    "(#all | List of (extension | restriction))",
12309 			    attrValue, NULL, NULL, NULL);
12310 		    } else
12311 			final = 1;
12312 		} else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
12313 		    /*
12314 		    * Attribute "block".
12315 		    */
12316 		    attrValue = xmlSchemaGetNodeContent(ctxt,
12317 			(xmlNodePtr) attr);
12318 		    if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
12319 			-1,
12320 			XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
12321 			XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
12322 			-1, -1, -1) != 0) {
12323 			xmlSchemaPSimpleTypeErr(ctxt,
12324 			    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
12325 			    NULL, (xmlNodePtr) attr, NULL,
12326 			    "(#all | List of (extension | restriction)) ",
12327 			    attrValue, NULL, NULL, NULL);
12328 		    } else
12329 			block = 1;
12330 		} else {
12331 			xmlSchemaPIllegalAttrErr(ctxt,
12332 			    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12333 		}
12334 	    } else {
12335 		xmlSchemaPIllegalAttrErr(ctxt,
12336 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12337 	    }
12338 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
12339 	    xmlSchemaPIllegalAttrErr(ctxt,
12340 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12341 	}
12342 	attr = attr->next;
12343     }
12344     if (! block) {
12345 	/*
12346 	* Apply default "block" values.
12347 	*/
12348 	if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
12349 	    type->flags |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
12350 	if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
12351 	    type->flags |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
12352     }
12353     if (! final) {
12354 	/*
12355 	* Apply default "block" values.
12356 	*/
12357 	if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
12358 	    type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
12359 	if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
12360 	    type->flags |= XML_SCHEMAS_TYPE_FINAL_EXTENSION;
12361     }
12362     /*
12363     * And now for the children...
12364     */
12365     child = node->children;
12366     if (IS_SCHEMA(child, "annotation")) {
12367         type->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
12368         child = child->next;
12369     }
12370     ctxt->ctxtType = type;
12371     if (IS_SCHEMA(child, "simpleContent")) {
12372 	/*
12373 	* <complexType><simpleContent>...
12374 	* 3.4.3 : 2.2
12375 	* Specifying mixed='true' when the <simpleContent>
12376 	* alternative is chosen has no effect
12377 	*/
12378 	if (type->flags & XML_SCHEMAS_TYPE_MIXED)
12379 	    type->flags ^= XML_SCHEMAS_TYPE_MIXED;
12380         xmlSchemaParseSimpleContent(ctxt, schema, child,
12381 	    &hasRestrictionOrExtension);
12382         child = child->next;
12383     } else if (IS_SCHEMA(child, "complexContent")) {
12384 	/*
12385 	* <complexType><complexContent>...
12386 	*/
12387 	type->contentType = XML_SCHEMA_CONTENT_EMPTY;
12388         xmlSchemaParseComplexContent(ctxt, schema, child,
12389 	    &hasRestrictionOrExtension);
12390         child = child->next;
12391     } else {
12392 	/*
12393 	* E.g <complexType><sequence>... or <complexType><attribute>... etc.
12394 	*
12395 	* SPEC
12396 	* "...the third alternative (neither <simpleContent> nor
12397 	* <complexContent>) is chosen. This case is understood as shorthand
12398 	* for complex content restricting the `ur-type definition`, and the
12399 	* details of the mappings should be modified as necessary.
12400 	*/
12401 	type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
12402 	type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
12403 	/*
12404 	* Parse model groups.
12405 	*/
12406         if (IS_SCHEMA(child, "all")) {
12407             type->subtypes = (xmlSchemaTypePtr)
12408 		xmlSchemaParseModelGroup(ctxt, schema, child,
12409 		    XML_SCHEMA_TYPE_ALL, 1);
12410             child = child->next;
12411         } else if (IS_SCHEMA(child, "choice")) {
12412             type->subtypes = (xmlSchemaTypePtr)
12413 		xmlSchemaParseModelGroup(ctxt, schema, child,
12414 		    XML_SCHEMA_TYPE_CHOICE, 1);
12415             child = child->next;
12416         } else if (IS_SCHEMA(child, "sequence")) {
12417             type->subtypes = (xmlSchemaTypePtr)
12418 		xmlSchemaParseModelGroup(ctxt, schema, child,
12419 		    XML_SCHEMA_TYPE_SEQUENCE, 1);
12420             child = child->next;
12421         } else if (IS_SCHEMA(child, "group")) {
12422             type->subtypes = (xmlSchemaTypePtr)
12423 		xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
12424 	    /*
12425 	    * Note that the reference will be resolved in
12426 	    * xmlSchemaResolveTypeReferences();
12427 	    */
12428             child = child->next;
12429         }
12430 	/*
12431 	* Parse attribute decls/refs.
12432 	*/
12433         if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
12434 	    (xmlSchemaItemListPtr *) &(type->attrUses),
12435 	    XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
12436 	    return(NULL);
12437 	/*
12438 	* Parse attribute wildcard.
12439 	*/
12440 	if (IS_SCHEMA(child, "anyAttribute")) {
12441 	    type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
12442 	    child = child->next;
12443 	}
12444     }
12445     if (child != NULL) {
12446 	xmlSchemaPContentErr(ctxt,
12447 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
12448 	    NULL, node, child,
12449 	    NULL, "(annotation?, (simpleContent | complexContent | "
12450 	    "((group | all | choice | sequence)?, ((attribute | "
12451 	    "attributeGroup)*, anyAttribute?))))");
12452     }
12453     /*
12454     * REDEFINE: SPEC src-redefine (5)
12455     */
12456     if (topLevel && ctxt->isRedefine && (! hasRestrictionOrExtension)) {
12457 	xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
12458 	    NULL, node, "This is a redefinition, thus the "
12459 	    "<complexType> must have a <restriction> or <extension> "
12460 	    "grand-child", NULL);
12461     }
12462     ctxt->ctxtType = ctxtType;
12463     return (type);
12464 }
12465 
12466 /************************************************************************
12467  *									*
12468  *			Validating using Schemas			*
12469  *									*
12470  ************************************************************************/
12471 
12472 /************************************************************************
12473  *									*
12474  *			Reading/Writing Schemas				*
12475  *									*
12476  ************************************************************************/
12477 
12478 #if 0 /* Will be enabled if it is clear what options are needed. */
12479 /**
12480  * xmlSchemaParserCtxtSetOptions:
12481  * @ctxt:	a schema parser context
12482  * @options: a combination of xmlSchemaParserOption
12483  *
12484  * Sets the options to be used during the parse.
12485  *
12486  * Returns 0 in case of success, -1 in case of an
12487  * API error.
12488  */
12489 static int
12490 xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
12491 			      int options)
12492 
12493 {
12494     int i;
12495 
12496     if (ctxt == NULL)
12497 	return (-1);
12498     /*
12499     * WARNING: Change the start value if adding to the
12500     * xmlSchemaParseOption.
12501     */
12502     for (i = 1; i < (int) sizeof(int) * 8; i++) {
12503         if (options & 1<<i) {
12504 	    return (-1);
12505         }
12506     }
12507     ctxt->options = options;
12508     return (0);
12509 }
12510 
12511 /**
12512  * xmlSchemaValidCtxtGetOptions:
12513  * @ctxt: a schema parser context
12514  *
12515  * Returns the option combination of the parser context.
12516  */
12517 static int
12518 xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
12519 
12520 {
12521     if (ctxt == NULL)
12522 	return (-1);
12523     else
12524 	return (ctxt->options);
12525 }
12526 #endif
12527 
12528 /**
12529  * xmlSchemaNewParserCtxt:
12530  * @URL:  the location of the schema
12531  *
12532  * Create an XML Schemas parse context for that file/resource expected
12533  * to contain an XML Schemas file.
12534  *
12535  * Returns the parser context or NULL in case of error
12536  */
12537 xmlSchemaParserCtxtPtr
xmlSchemaNewParserCtxt(const char * URL)12538 xmlSchemaNewParserCtxt(const char *URL)
12539 {
12540     xmlSchemaParserCtxtPtr ret;
12541 
12542     if (URL == NULL)
12543         return (NULL);
12544 
12545     ret = xmlSchemaParserCtxtCreate();
12546     if (ret == NULL)
12547 	return(NULL);
12548     ret->dict = xmlDictCreate();
12549     ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
12550     return (ret);
12551 }
12552 
12553 /**
12554  * xmlSchemaNewMemParserCtxt:
12555  * @buffer:  a pointer to a char array containing the schemas
12556  * @size:  the size of the array
12557  *
12558  * Create an XML Schemas parse context for that memory buffer expected
12559  * to contain an XML Schemas file.
12560  *
12561  * Returns the parser context or NULL in case of error
12562  */
12563 xmlSchemaParserCtxtPtr
xmlSchemaNewMemParserCtxt(const char * buffer,int size)12564 xmlSchemaNewMemParserCtxt(const char *buffer, int size)
12565 {
12566     xmlSchemaParserCtxtPtr ret;
12567 
12568     if ((buffer == NULL) || (size <= 0))
12569         return (NULL);
12570     ret = xmlSchemaParserCtxtCreate();
12571     if (ret == NULL)
12572 	return(NULL);
12573     ret->buffer = buffer;
12574     ret->size = size;
12575     ret->dict = xmlDictCreate();
12576     return (ret);
12577 }
12578 
12579 /**
12580  * xmlSchemaNewDocParserCtxt:
12581  * @doc:  a preparsed document tree
12582  *
12583  * Create an XML Schemas parse context for that document.
12584  * NB. The document may be modified during the parsing process.
12585  *
12586  * Returns the parser context or NULL in case of error
12587  */
12588 xmlSchemaParserCtxtPtr
xmlSchemaNewDocParserCtxt(xmlDocPtr doc)12589 xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
12590 {
12591     xmlSchemaParserCtxtPtr ret;
12592 
12593     if (doc == NULL)
12594       return (NULL);
12595     ret = xmlSchemaParserCtxtCreate();
12596     if (ret == NULL)
12597 	return(NULL);
12598     ret->doc = doc;
12599     ret->dict = xmlDictCreate();
12600     /* The application has responsibility for the document */
12601     ret->preserve = 1;
12602 
12603     return (ret);
12604 }
12605 
12606 /**
12607  * xmlSchemaFreeParserCtxt:
12608  * @ctxt:  the schema parser context
12609  *
12610  * Free the resources associated to the schema parser context
12611  */
12612 void
xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)12613 xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
12614 {
12615     if (ctxt == NULL)
12616         return;
12617     if (ctxt->doc != NULL && !ctxt->preserve)
12618         xmlFreeDoc(ctxt->doc);
12619     if (ctxt->vctxt != NULL) {
12620 	xmlSchemaFreeValidCtxt(ctxt->vctxt);
12621     }
12622     if (ctxt->ownsConstructor && (ctxt->constructor != NULL)) {
12623 	xmlSchemaConstructionCtxtFree(ctxt->constructor);
12624 	ctxt->constructor = NULL;
12625 	ctxt->ownsConstructor = 0;
12626     }
12627     if (ctxt->attrProhibs != NULL)
12628 	xmlSchemaItemListFree(ctxt->attrProhibs);
12629     xmlDictFree(ctxt->dict);
12630     xmlFree(ctxt);
12631 }
12632 
12633 /************************************************************************
12634  *									*
12635  *			Building the content models			*
12636  *									*
12637  ************************************************************************/
12638 
12639 /**
12640  * xmlSchemaBuildContentModelForSubstGroup:
12641  *
12642  * Returns 1 if nillable, 0 otherwise
12643  */
12644 static int
xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,xmlSchemaParticlePtr particle,int counter,xmlAutomataStatePtr end)12645 xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,
12646 	xmlSchemaParticlePtr particle, int counter, xmlAutomataStatePtr end)
12647 {
12648     xmlAutomataStatePtr start, tmp;
12649     xmlSchemaElementPtr elemDecl, member;
12650     xmlSchemaSubstGroupPtr substGroup;
12651     int i;
12652     int ret = 0;
12653 
12654     elemDecl = (xmlSchemaElementPtr) particle->children;
12655     /*
12656     * Wrap the substitution group with a CHOICE.
12657     */
12658     start = pctxt->state;
12659     if (end == NULL)
12660 	end = xmlAutomataNewState(pctxt->am);
12661     substGroup = xmlSchemaSubstGroupGet(pctxt, elemDecl);
12662     if (substGroup == NULL) {
12663 	xmlSchemaPErr(pctxt, WXS_ITEM_NODE(particle),
12664 	    XML_SCHEMAP_INTERNAL,
12665 	    "Internal error: xmlSchemaBuildContentModelForSubstGroup, "
12666 	    "declaration is marked having a subst. group but none "
12667 	    "available.\n", elemDecl->name, NULL);
12668 	return(0);
12669     }
12670     if (counter >= 0) {
12671 	/*
12672 	* NOTE that we put the declaration in, even if it's abstract.
12673 	* However, an error will be raised during *validation* if an element
12674 	* information item shall be validated against an abstract element
12675 	* declaration.
12676 	*/
12677 	tmp = xmlAutomataNewCountedTrans(pctxt->am, start, NULL, counter);
12678         xmlAutomataNewTransition2(pctxt->am, tmp, end,
12679 	            elemDecl->name, elemDecl->targetNamespace, elemDecl);
12680 	/*
12681 	* Add subst. group members.
12682 	*/
12683 	for (i = 0; i < substGroup->members->nbItems; i++) {
12684 	    member = (xmlSchemaElementPtr) substGroup->members->items[i];
12685             xmlAutomataNewTransition2(pctxt->am, tmp, end,
12686 		               member->name, member->targetNamespace, member);
12687 	}
12688     } else if (particle->maxOccurs == 1) {
12689 	/*
12690 	* NOTE that we put the declaration in, even if it's abstract,
12691 	*/
12692 	xmlAutomataNewEpsilon(pctxt->am,
12693 	    xmlAutomataNewTransition2(pctxt->am,
12694 	    start, NULL,
12695 	    elemDecl->name, elemDecl->targetNamespace, elemDecl), end);
12696 	/*
12697 	* Add subst. group members.
12698 	*/
12699 	for (i = 0; i < substGroup->members->nbItems; i++) {
12700 	    member = (xmlSchemaElementPtr) substGroup->members->items[i];
12701 	    /*
12702 	    * NOTE: This fixes bug #341150. xmlAutomataNewOnceTrans2()
12703 	    *  was incorrectly used instead of xmlAutomataNewTransition2()
12704 	    *  (seems like a copy&paste bug from the XML_SCHEMA_TYPE_ALL
12705 	    *  section in xmlSchemaBuildAContentModel() ).
12706 	    * TODO: Check if xmlAutomataNewOnceTrans2() was instead
12707 	    *  intended for the above "counter" section originally. I.e.,
12708 	    *  check xs:all with subst-groups.
12709 	    *
12710 	    * tmp = xmlAutomataNewOnceTrans2(pctxt->am, start, NULL,
12711 	    *	               member->name, member->targetNamespace,
12712 	    *		       1, 1, member);
12713 	    */
12714 	    tmp = xmlAutomataNewTransition2(pctxt->am, start, NULL,
12715 		member->name, member->targetNamespace, member);
12716 	    xmlAutomataNewEpsilon(pctxt->am, tmp, end);
12717 	}
12718     } else {
12719 	xmlAutomataStatePtr hop;
12720 	int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12721 	    UNBOUNDED : particle->maxOccurs - 1;
12722 	int minOccurs = particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12723 
12724 	counter =
12725 	    xmlAutomataNewCounter(pctxt->am, minOccurs,
12726 	    maxOccurs);
12727 	hop = xmlAutomataNewState(pctxt->am);
12728 
12729 	xmlAutomataNewEpsilon(pctxt->am,
12730 	    xmlAutomataNewTransition2(pctxt->am,
12731 	    start, NULL,
12732 	    elemDecl->name, elemDecl->targetNamespace, elemDecl),
12733 	    hop);
12734 	/*
12735 	 * Add subst. group members.
12736 	 */
12737 	for (i = 0; i < substGroup->members->nbItems; i++) {
12738 	    member = (xmlSchemaElementPtr) substGroup->members->items[i];
12739 	    xmlAutomataNewEpsilon(pctxt->am,
12740 		xmlAutomataNewTransition2(pctxt->am,
12741 		start, NULL,
12742 		member->name, member->targetNamespace, member),
12743 		hop);
12744 	}
12745 	xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12746 	xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12747     }
12748     if (particle->minOccurs == 0) {
12749 	xmlAutomataNewEpsilon(pctxt->am, start, end);
12750         ret = 1;
12751     }
12752     pctxt->state = end;
12753     return(ret);
12754 }
12755 
12756 /**
12757  * xmlSchemaBuildContentModelForElement:
12758  *
12759  * Returns 1 if nillable, 0 otherwise
12760  */
12761 static int
xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr particle)12762 xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,
12763 				     xmlSchemaParticlePtr particle)
12764 {
12765     int ret = 0;
12766 
12767     if (((xmlSchemaElementPtr) particle->children)->flags &
12768 	XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
12769 	/*
12770 	* Substitution groups.
12771 	*/
12772 	ret = xmlSchemaBuildContentModelForSubstGroup(ctxt, particle, -1, NULL);
12773     } else {
12774 	xmlSchemaElementPtr elemDecl;
12775 	xmlAutomataStatePtr start;
12776 
12777 	elemDecl = (xmlSchemaElementPtr) particle->children;
12778 
12779 	if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT)
12780 	    return(0);
12781 	if (particle->maxOccurs == 1) {
12782 	    start = ctxt->state;
12783 	    ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12784 		    elemDecl->name, elemDecl->targetNamespace, elemDecl);
12785 	} else if ((particle->maxOccurs >= UNBOUNDED) &&
12786 	           (particle->minOccurs < 2)) {
12787 	    /* Special case. */
12788 	    start = ctxt->state;
12789 	    ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12790 		elemDecl->name, elemDecl->targetNamespace, elemDecl);
12791 	    ctxt->state = xmlAutomataNewTransition2(ctxt->am, ctxt->state, ctxt->state,
12792 		elemDecl->name, elemDecl->targetNamespace, elemDecl);
12793 	} else {
12794 	    int counter;
12795 	    int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12796 			    UNBOUNDED : particle->maxOccurs - 1;
12797 	    int minOccurs = particle->minOccurs < 1 ?
12798 			    0 : particle->minOccurs - 1;
12799 
12800 	    start = xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
12801 	    counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
12802 	    ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12803 		elemDecl->name, elemDecl->targetNamespace, elemDecl);
12804 	    xmlAutomataNewCountedTrans(ctxt->am, ctxt->state, start, counter);
12805 	    ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, ctxt->state,
12806 		NULL, counter);
12807 	}
12808 	if (particle->minOccurs == 0) {
12809 	    xmlAutomataNewEpsilon(ctxt->am, start, ctxt->state);
12810             ret = 1;
12811         }
12812     }
12813     return(ret);
12814 }
12815 
12816 /**
12817  * xmlSchemaBuildAContentModel:
12818  * @ctxt:  the schema parser context
12819  * @particle:  the particle component
12820  * @name:  the complex type's name whose content is being built
12821  *
12822  * Create the automaton for the {content type} of a complex type.
12823  *
12824  * Returns 1 if the content is nillable, 0 otherwise
12825  */
12826 static int
xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,xmlSchemaParticlePtr particle)12827 xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,
12828 			    xmlSchemaParticlePtr particle)
12829 {
12830     int ret = 0, tmp2;
12831 
12832     if (particle == NULL) {
12833 	PERROR_INT("xmlSchemaBuildAContentModel", "particle is NULL");
12834 	return(1);
12835     }
12836     if (particle->children == NULL) {
12837 	/*
12838 	* Just return in this case. A missing "term" of the particle
12839 	* might arise due to an invalid "term" component.
12840 	*/
12841 	return(1);
12842     }
12843 
12844     switch (particle->children->type) {
12845 	case XML_SCHEMA_TYPE_ANY: {
12846 	    xmlAutomataStatePtr start, end;
12847 	    xmlSchemaWildcardPtr wild;
12848 	    xmlSchemaWildcardNsPtr ns;
12849 
12850 	    wild = (xmlSchemaWildcardPtr) particle->children;
12851 
12852 	    start = pctxt->state;
12853 	    end = xmlAutomataNewState(pctxt->am);
12854 
12855 	    if (particle->maxOccurs == 1) {
12856 		if (wild->any == 1) {
12857 		    /*
12858 		    * We need to add both transitions:
12859 		    *
12860 		    * 1. the {"*", "*"} for elements in a namespace.
12861 		    */
12862 		    pctxt->state =
12863 			xmlAutomataNewTransition2(pctxt->am,
12864 			start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
12865 		    xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12866 		    /*
12867 		    * 2. the {"*"} for elements in no namespace.
12868 		    */
12869 		    pctxt->state =
12870 			xmlAutomataNewTransition2(pctxt->am,
12871 			start, NULL, BAD_CAST "*", NULL, wild);
12872 		    xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12873 
12874 		} else if (wild->nsSet != NULL) {
12875 		    ns = wild->nsSet;
12876 		    do {
12877 			pctxt->state = start;
12878 			pctxt->state = xmlAutomataNewTransition2(pctxt->am,
12879 			    pctxt->state, NULL, BAD_CAST "*", ns->value, wild);
12880 			xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12881 			ns = ns->next;
12882 		    } while (ns != NULL);
12883 
12884 		} else if (wild->negNsSet != NULL) {
12885 		    pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
12886 			start, end, BAD_CAST "*", wild->negNsSet->value,
12887 			wild);
12888 		}
12889 	    } else {
12890 		int counter;
12891 		xmlAutomataStatePtr hop;
12892 		int maxOccurs =
12893 		    particle->maxOccurs == UNBOUNDED ? UNBOUNDED :
12894                                            particle->maxOccurs - 1;
12895 		int minOccurs =
12896 		    particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12897 
12898 		counter = xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
12899 		hop = xmlAutomataNewState(pctxt->am);
12900 		if (wild->any == 1) {
12901 		    pctxt->state =
12902 			xmlAutomataNewTransition2(pctxt->am,
12903 			start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
12904 		    xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12905 		    pctxt->state =
12906 			xmlAutomataNewTransition2(pctxt->am,
12907 			start, NULL, BAD_CAST "*", NULL, wild);
12908 		    xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12909 		} else if (wild->nsSet != NULL) {
12910 		    ns = wild->nsSet;
12911 		    do {
12912 			pctxt->state =
12913 			    xmlAutomataNewTransition2(pctxt->am,
12914 				start, NULL, BAD_CAST "*", ns->value, wild);
12915 			xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12916 			ns = ns->next;
12917 		    } while (ns != NULL);
12918 
12919 		} else if (wild->negNsSet != NULL) {
12920 		    pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
12921 			start, hop, BAD_CAST "*", wild->negNsSet->value,
12922 			wild);
12923 		}
12924 		xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12925 		xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12926 	    }
12927 	    if (particle->minOccurs == 0) {
12928 		xmlAutomataNewEpsilon(pctxt->am, start, end);
12929                 ret = 1;
12930 	    }
12931 	    pctxt->state = end;
12932             break;
12933 	}
12934         case XML_SCHEMA_TYPE_ELEMENT:
12935 	    ret = xmlSchemaBuildContentModelForElement(pctxt, particle);
12936 	    break;
12937         case XML_SCHEMA_TYPE_SEQUENCE:{
12938             xmlSchemaTreeItemPtr sub;
12939 
12940             ret = 1;
12941             /*
12942              * If max and min occurrences are default (1) then
12943              * simply iterate over the particles of the <sequence>.
12944              */
12945             if ((particle->minOccurs == 1) && (particle->maxOccurs == 1)) {
12946                 sub = particle->children->children;
12947 
12948                 while (sub != NULL) {
12949                     tmp2 = xmlSchemaBuildAContentModel(pctxt,
12950                                         (xmlSchemaParticlePtr) sub);
12951                     if (tmp2 != 1) ret = 0;
12952                     sub = sub->next;
12953                 }
12954             } else {
12955                 xmlAutomataStatePtr oldstate = pctxt->state;
12956 
12957                 if (particle->maxOccurs >= UNBOUNDED) {
12958                     if (particle->minOccurs > 1) {
12959                         xmlAutomataStatePtr tmp;
12960                         int counter;
12961 
12962                         pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12963                             oldstate, NULL);
12964                         oldstate = pctxt->state;
12965 
12966                         counter = xmlAutomataNewCounter(pctxt->am,
12967                             particle->minOccurs - 1, UNBOUNDED);
12968 
12969                         sub = particle->children->children;
12970                         while (sub != NULL) {
12971                             tmp2 = xmlSchemaBuildAContentModel(pctxt,
12972                                             (xmlSchemaParticlePtr) sub);
12973                             if (tmp2 != 1) ret = 0;
12974                             sub = sub->next;
12975                         }
12976                         tmp = pctxt->state;
12977                         xmlAutomataNewCountedTrans(pctxt->am, tmp,
12978                                                    oldstate, counter);
12979                         pctxt->state =
12980                             xmlAutomataNewCounterTrans(pctxt->am, tmp,
12981                                                        NULL, counter);
12982                         if (ret == 1)
12983                             xmlAutomataNewEpsilon(pctxt->am,
12984                                                 oldstate, pctxt->state);
12985 
12986                     } else {
12987                         pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12988                             oldstate, NULL);
12989                         oldstate = pctxt->state;
12990 
12991                         sub = particle->children->children;
12992                         while (sub != NULL) {
12993                             tmp2 = xmlSchemaBuildAContentModel(pctxt,
12994                                         (xmlSchemaParticlePtr) sub);
12995                             if (tmp2 != 1) ret = 0;
12996                             sub = sub->next;
12997                         }
12998                         xmlAutomataNewEpsilon(pctxt->am, pctxt->state,
12999                                               oldstate);
13000                         /*
13001                          * epsilon needed to block previous trans from
13002                          * being allowed to enter back from another
13003                          * construct
13004                          */
13005                         pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
13006                                             pctxt->state, NULL);
13007                         if (particle->minOccurs == 0) {
13008                             xmlAutomataNewEpsilon(pctxt->am,
13009                                 oldstate, pctxt->state);
13010                             ret = 1;
13011                         }
13012                     }
13013                 } else if ((particle->maxOccurs > 1)
13014                            || (particle->minOccurs > 1)) {
13015                     xmlAutomataStatePtr tmp;
13016                     int counter;
13017 
13018                     pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
13019                         oldstate, NULL);
13020                     oldstate = pctxt->state;
13021 
13022                     counter = xmlAutomataNewCounter(pctxt->am,
13023                         particle->minOccurs - 1,
13024                         particle->maxOccurs - 1);
13025 
13026                     sub = particle->children->children;
13027                     while (sub != NULL) {
13028                         tmp2 = xmlSchemaBuildAContentModel(pctxt,
13029                                         (xmlSchemaParticlePtr) sub);
13030                         if (tmp2 != 1) ret = 0;
13031                         sub = sub->next;
13032                     }
13033                     tmp = pctxt->state;
13034                     xmlAutomataNewCountedTrans(pctxt->am,
13035                         tmp, oldstate, counter);
13036                     pctxt->state =
13037                         xmlAutomataNewCounterTrans(pctxt->am, tmp, NULL,
13038                                                    counter);
13039                     if ((particle->minOccurs == 0) || (ret == 1)) {
13040                         xmlAutomataNewEpsilon(pctxt->am,
13041                                             oldstate, pctxt->state);
13042                         ret = 1;
13043                     }
13044                 } else {
13045                     sub = particle->children->children;
13046                     while (sub != NULL) {
13047                         tmp2 = xmlSchemaBuildAContentModel(pctxt,
13048                                         (xmlSchemaParticlePtr) sub);
13049                         if (tmp2 != 1) ret = 0;
13050                         sub = sub->next;
13051                     }
13052 
13053 		    /*
13054 		     * epsilon needed to block previous trans from
13055 		     * being allowed to enter back from another
13056 		     * construct
13057 		     */
13058 		    pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
13059 					pctxt->state, NULL);
13060 
13061                     if (particle->minOccurs == 0) {
13062                         xmlAutomataNewEpsilon(pctxt->am, oldstate,
13063                                               pctxt->state);
13064                         ret = 1;
13065                     }
13066                 }
13067             }
13068             break;
13069         }
13070         case XML_SCHEMA_TYPE_CHOICE:{
13071             xmlSchemaTreeItemPtr sub;
13072             xmlAutomataStatePtr start, end;
13073 
13074             ret = 0;
13075             start = pctxt->state;
13076             end = xmlAutomataNewState(pctxt->am);
13077 
13078             /*
13079              * iterate over the subtypes and remerge the end with an
13080              * epsilon transition
13081              */
13082             if (particle->maxOccurs == 1) {
13083                 sub = particle->children->children;
13084                 while (sub != NULL) {
13085                     pctxt->state = start;
13086                     tmp2 = xmlSchemaBuildAContentModel(pctxt,
13087                                         (xmlSchemaParticlePtr) sub);
13088                     if (tmp2 == 1) ret = 1;
13089                     xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
13090                     sub = sub->next;
13091                 }
13092             } else {
13093                 int counter;
13094                 xmlAutomataStatePtr hop, base;
13095                 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
13096                     UNBOUNDED : particle->maxOccurs - 1;
13097                 int minOccurs =
13098                     particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
13099 
13100                 /*
13101                  * use a counter to keep track of the number of transitions
13102                  * which went through the choice.
13103                  */
13104                 counter =
13105                     xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
13106                 hop = xmlAutomataNewState(pctxt->am);
13107                 base = xmlAutomataNewState(pctxt->am);
13108 
13109                 sub = particle->children->children;
13110                 while (sub != NULL) {
13111                     pctxt->state = base;
13112                     tmp2 = xmlSchemaBuildAContentModel(pctxt,
13113                                         (xmlSchemaParticlePtr) sub);
13114                     if (tmp2 == 1) ret = 1;
13115                     xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
13116                     sub = sub->next;
13117                 }
13118                 xmlAutomataNewEpsilon(pctxt->am, start, base);
13119                 xmlAutomataNewCountedTrans(pctxt->am, hop, base, counter);
13120                 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
13121                 if (ret == 1)
13122                     xmlAutomataNewEpsilon(pctxt->am, base, end);
13123             }
13124             if (particle->minOccurs == 0) {
13125                 xmlAutomataNewEpsilon(pctxt->am, start, end);
13126                 ret = 1;
13127             }
13128             pctxt->state = end;
13129             break;
13130         }
13131         case XML_SCHEMA_TYPE_ALL:{
13132             xmlAutomataStatePtr start, tmp;
13133             xmlSchemaParticlePtr sub;
13134             xmlSchemaElementPtr elemDecl;
13135 
13136             ret = 1;
13137 
13138             sub = (xmlSchemaParticlePtr) particle->children->children;
13139             if (sub == NULL)
13140                 break;
13141 
13142             ret = 0;
13143 
13144             start = pctxt->state;
13145             tmp = xmlAutomataNewState(pctxt->am);
13146             xmlAutomataNewEpsilon(pctxt->am, pctxt->state, tmp);
13147             pctxt->state = tmp;
13148             while (sub != NULL) {
13149                 pctxt->state = tmp;
13150 
13151                 elemDecl = (xmlSchemaElementPtr) sub->children;
13152                 if (elemDecl == NULL) {
13153                     PERROR_INT("xmlSchemaBuildAContentModel",
13154                         "<element> particle has no term");
13155                     return(ret);
13156                 };
13157                 /*
13158                 * NOTE: The {max occurs} of all the particles in the
13159                 * {particles} of the group must be 0 or 1; this is
13160                 * already ensured during the parse of the content of
13161                 * <all>.
13162                 */
13163                 if (elemDecl->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
13164                     int counter;
13165 
13166                     /*
13167                      * This is an abstract group, we need to share
13168                      * the same counter for all the element transitions
13169                      * derived from the group
13170                      */
13171                     counter = xmlAutomataNewCounter(pctxt->am,
13172                                        sub->minOccurs, sub->maxOccurs);
13173                     xmlSchemaBuildContentModelForSubstGroup(pctxt,
13174                                        sub, counter, pctxt->state);
13175                 } else {
13176                     if ((sub->minOccurs == 1) &&
13177                         (sub->maxOccurs == 1)) {
13178                         xmlAutomataNewOnceTrans2(pctxt->am, pctxt->state,
13179                                                 pctxt->state,
13180                                                 elemDecl->name,
13181                                                 elemDecl->targetNamespace,
13182                                                 1, 1, elemDecl);
13183                     } else if ((sub->minOccurs == 0) &&
13184                         (sub->maxOccurs == 1)) {
13185 
13186                         xmlAutomataNewCountTrans2(pctxt->am, pctxt->state,
13187                                                  pctxt->state,
13188                                                  elemDecl->name,
13189                                                  elemDecl->targetNamespace,
13190                                                  0,
13191                                                  1,
13192                                                  elemDecl);
13193                     }
13194                 }
13195                 sub = (xmlSchemaParticlePtr) sub->next;
13196             }
13197             pctxt->state =
13198                 xmlAutomataNewAllTrans(pctxt->am, pctxt->state, NULL, 0);
13199             if (particle->minOccurs == 0) {
13200                 xmlAutomataNewEpsilon(pctxt->am, start, pctxt->state);
13201                 ret = 1;
13202             }
13203             break;
13204         }
13205 	case XML_SCHEMA_TYPE_GROUP:
13206 	    /*
13207 	    * If we hit a model group definition, then this means that
13208 	    * it was empty, thus was not substituted for the containing
13209 	    * model group. Just do nothing in this case.
13210 	    * TODO: But the group should be substituted and not occur at
13211 	    * all in the content model at this point. Fix this.
13212 	    */
13213             ret = 1;
13214 	    break;
13215         default:
13216 	    xmlSchemaInternalErr2(ACTXT_CAST pctxt,
13217 		"xmlSchemaBuildAContentModel",
13218 		"found unexpected term of type '%s' in content model",
13219 		WXS_ITEM_TYPE_NAME(particle->children), NULL);
13220             return(ret);
13221     }
13222     return(ret);
13223 }
13224 
13225 /**
13226  * xmlSchemaBuildContentModel:
13227  * @ctxt:  the schema parser context
13228  * @type:  the complex type definition
13229  * @name:  the element name
13230  *
13231  * Builds the content model of the complex type.
13232  */
13233 static void
xmlSchemaBuildContentModel(xmlSchemaTypePtr type,xmlSchemaParserCtxtPtr ctxt)13234 xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
13235 			   xmlSchemaParserCtxtPtr ctxt)
13236 {
13237     if ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
13238 	(type->contModel != NULL) ||
13239 	((type->contentType != XML_SCHEMA_CONTENT_ELEMENTS) &&
13240 	(type->contentType != XML_SCHEMA_CONTENT_MIXED)))
13241 	return;
13242 
13243 #ifdef DEBUG_CONTENT
13244     xmlGenericError(xmlGenericErrorContext,
13245                     "Building content model for %s\n", name);
13246 #endif
13247     ctxt->am = NULL;
13248     ctxt->am = xmlNewAutomata();
13249     if (ctxt->am == NULL) {
13250         xmlGenericError(xmlGenericErrorContext,
13251 	    "Cannot create automata for complex type %s\n", type->name);
13252         return;
13253     }
13254     ctxt->state = xmlAutomataGetInitState(ctxt->am);
13255     /*
13256     * Build the automaton.
13257     */
13258     xmlSchemaBuildAContentModel(ctxt, WXS_TYPE_PARTICLE(type));
13259     xmlAutomataSetFinalState(ctxt->am, ctxt->state);
13260     type->contModel = xmlAutomataCompile(ctxt->am);
13261     if (type->contModel == NULL) {
13262         xmlSchemaPCustomErr(ctxt,
13263 	    XML_SCHEMAP_INTERNAL,
13264 	    WXS_BASIC_CAST type, type->node,
13265 	    "Failed to compile the content model", NULL);
13266     } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
13267         xmlSchemaPCustomErr(ctxt,
13268 	    XML_SCHEMAP_NOT_DETERMINISTIC,
13269 	    /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
13270 	    WXS_BASIC_CAST type, type->node,
13271 	    "The content model is not determinist", NULL);
13272     } else {
13273 #ifdef DEBUG_CONTENT_REGEXP
13274         xmlGenericError(xmlGenericErrorContext,
13275                         "Content model of %s:\n", type->name);
13276         xmlRegexpPrint(stderr, type->contModel);
13277 #endif
13278     }
13279     ctxt->state = NULL;
13280     xmlFreeAutomata(ctxt->am);
13281     ctxt->am = NULL;
13282 }
13283 
13284 /**
13285  * xmlSchemaResolveElementReferences:
13286  * @elem:  the schema element context
13287  * @ctxt:  the schema parser context
13288  *
13289  * Resolves the references of an element declaration
13290  * or particle, which has an element declaration as it's
13291  * term.
13292  */
13293 static void
xmlSchemaResolveElementReferences(xmlSchemaElementPtr elemDecl,xmlSchemaParserCtxtPtr ctxt)13294 xmlSchemaResolveElementReferences(xmlSchemaElementPtr elemDecl,
13295 				  xmlSchemaParserCtxtPtr ctxt)
13296 {
13297     if ((ctxt == NULL) || (elemDecl == NULL) ||
13298 	((elemDecl != NULL) &&
13299 	(elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
13300         return;
13301     elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
13302 
13303     if ((elemDecl->subtypes == NULL) && (elemDecl->namedType != NULL)) {
13304 	xmlSchemaTypePtr type;
13305 
13306 	/* (type definition) ... otherwise the type definition `resolved`
13307 	* to by the `actual value` of the type [attribute] ...
13308 	*/
13309 	type = xmlSchemaGetType(ctxt->schema, elemDecl->namedType,
13310 	    elemDecl->namedTypeNs);
13311 	if (type == NULL) {
13312 	    xmlSchemaPResCompAttrErr(ctxt,
13313 		XML_SCHEMAP_SRC_RESOLVE,
13314 		WXS_BASIC_CAST elemDecl, elemDecl->node,
13315 		"type", elemDecl->namedType, elemDecl->namedTypeNs,
13316 		XML_SCHEMA_TYPE_BASIC, "type definition");
13317 	} else
13318 	    elemDecl->subtypes = type;
13319     }
13320     if (elemDecl->substGroup != NULL) {
13321 	xmlSchemaElementPtr substHead;
13322 
13323 	/*
13324 	* FIXME TODO: Do we need a new field in _xmlSchemaElement for
13325 	* substitutionGroup?
13326 	*/
13327 	substHead = xmlSchemaGetElem(ctxt->schema, elemDecl->substGroup,
13328 	    elemDecl->substGroupNs);
13329 	if (substHead == NULL) {
13330 	    xmlSchemaPResCompAttrErr(ctxt,
13331 		XML_SCHEMAP_SRC_RESOLVE,
13332 		WXS_BASIC_CAST elemDecl, NULL,
13333 		"substitutionGroup", elemDecl->substGroup,
13334 		elemDecl->substGroupNs, XML_SCHEMA_TYPE_ELEMENT, NULL);
13335 	} else {
13336 	    xmlSchemaResolveElementReferences(substHead, ctxt);
13337 	    /*
13338 	    * Set the "substitution group affiliation".
13339 	    * NOTE that now we use the "refDecl" field for this.
13340 	    */
13341 	    WXS_SUBST_HEAD(elemDecl) = substHead;
13342 	    /*
13343 	    * The type definitions is set to:
13344 	    * SPEC "...the {type definition} of the element
13345 	    * declaration `resolved` to by the `actual value`
13346 	    * of the substitutionGroup [attribute], if present"
13347 	    */
13348 	    if (elemDecl->subtypes == NULL)
13349 		elemDecl->subtypes = substHead->subtypes;
13350 	}
13351     }
13352     /*
13353     * SPEC "The definition of anyType serves as the default type definition
13354     * for element declarations whose XML representation does not specify one."
13355     */
13356     if ((elemDecl->subtypes == NULL) &&
13357 	(elemDecl->namedType == NULL) &&
13358 	(elemDecl->substGroup == NULL))
13359 	elemDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
13360 }
13361 
13362 /**
13363  * xmlSchemaResolveUnionMemberTypes:
13364  * @ctxt:  the schema parser context
13365  * @type:  the schema simple type definition
13366  *
13367  * Checks and builds the "member type definitions" property of the union
13368  * simple type. This handles part (1), part (2) is done in
13369  * xmlSchemaFinishMemberTypeDefinitionsProperty()
13370  *
13371  * Returns -1 in case of an internal error, 0 otherwise.
13372  */
13373 static int
xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,xmlSchemaTypePtr type)13374 xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,
13375 				 xmlSchemaTypePtr type)
13376 {
13377 
13378     xmlSchemaTypeLinkPtr link, lastLink, newLink;
13379     xmlSchemaTypePtr memberType;
13380 
13381     /*
13382     * SPEC (1) "If the <union> alternative is chosen, then [Definition:]
13383     * define the explicit members as the type definitions `resolved`
13384     * to by the items in the `actual value` of the memberTypes [attribute],
13385     * if any, followed by the type definitions corresponding to the
13386     * <simpleType>s among the [children] of <union>, if any."
13387     */
13388     /*
13389     * Resolve references.
13390     */
13391     link = type->memberTypes;
13392     lastLink = NULL;
13393     while (link != NULL) {
13394 	const xmlChar *name, *nsName;
13395 
13396 	name = ((xmlSchemaQNameRefPtr) link->type)->name;
13397 	nsName = ((xmlSchemaQNameRefPtr) link->type)->targetNamespace;
13398 
13399 	memberType = xmlSchemaGetType(ctxt->schema, name, nsName);
13400 	if ((memberType == NULL) || (! WXS_IS_SIMPLE(memberType))) {
13401 	    xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
13402 		WXS_BASIC_CAST type, type->node, "memberTypes",
13403 		name, nsName, XML_SCHEMA_TYPE_SIMPLE, NULL);
13404 	    /*
13405 	    * Remove the member type link.
13406 	    */
13407 	    if (lastLink == NULL)
13408 		type->memberTypes = link->next;
13409 	    else
13410 		lastLink->next = link->next;
13411 	    newLink = link;
13412 	    link = link->next;
13413 	    xmlFree(newLink);
13414 	} else {
13415 	    link->type = memberType;
13416 	    lastLink = link;
13417 	    link = link->next;
13418 	}
13419     }
13420     /*
13421     * Add local simple types,
13422     */
13423     memberType = type->subtypes;
13424     while (memberType != NULL) {
13425 	link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
13426 	if (link == NULL) {
13427 	    xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
13428 	    return (-1);
13429 	}
13430 	link->type = memberType;
13431 	link->next = NULL;
13432 	if (lastLink == NULL)
13433 	    type->memberTypes = link;
13434 	else
13435 	    lastLink->next = link;
13436 	lastLink = link;
13437 	memberType = memberType->next;
13438     }
13439     return (0);
13440 }
13441 
13442 /**
13443  * xmlSchemaIsDerivedFromBuiltInType:
13444  * @ctxt:  the schema parser context
13445  * @type:  the type definition
13446  * @valType: the value type
13447  *
13448  *
13449  * Returns 1 if the type has the given value type, or
13450  * is derived from such a type.
13451  */
13452 static int
xmlSchemaIsDerivedFromBuiltInType(xmlSchemaTypePtr type,int valType)13453 xmlSchemaIsDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
13454 {
13455     if (type == NULL)
13456 	return (0);
13457     if (WXS_IS_COMPLEX(type))
13458 	return (0);
13459     if (type->type == XML_SCHEMA_TYPE_BASIC) {
13460 	if (type->builtInType == valType)
13461 	    return(1);
13462 	if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13463 	    (type->builtInType == XML_SCHEMAS_ANYTYPE))
13464 	    return (0);
13465 	return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13466     }
13467     return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13468 }
13469 
13470 #if 0
13471 /**
13472  * xmlSchemaIsDerivedFromBuiltInType:
13473  * @ctxt:  the schema parser context
13474  * @type:  the type definition
13475  * @valType: the value type
13476  *
13477  *
13478  * Returns 1 if the type has the given value type, or
13479  * is derived from such a type.
13480  */
13481 static int
13482 xmlSchemaIsUserDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
13483 {
13484     if (type == NULL)
13485 	return (0);
13486     if (WXS_IS_COMPLEX(type))
13487 	return (0);
13488     if (type->type == XML_SCHEMA_TYPE_BASIC) {
13489 	if (type->builtInType == valType)
13490 	    return(1);
13491 	return (0);
13492     } else
13493 	return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13494 
13495     return (0);
13496 }
13497 
13498 static xmlSchemaTypePtr
13499 xmlSchemaQueryBuiltInType(xmlSchemaTypePtr type)
13500 {
13501     if (type == NULL)
13502 	return (NULL);
13503     if (WXS_IS_COMPLEX(type))
13504 	return (NULL);
13505     if (type->type == XML_SCHEMA_TYPE_BASIC)
13506 	return(type);
13507     return(xmlSchemaQueryBuiltInType(type->subtypes));
13508 }
13509 #endif
13510 
13511 /**
13512  * xmlSchemaGetPrimitiveType:
13513  * @type:  the simpleType definition
13514  *
13515  * Returns the primitive type of the given type or
13516  * NULL in case of error.
13517  */
13518 static xmlSchemaTypePtr
xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)13519 xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
13520 {
13521 
13522     while (type != NULL) {
13523 	/*
13524 	* Note that anySimpleType is actually not a primitive type
13525 	* but we need that here.
13526 	*/
13527 	if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13528 	   (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
13529 	    return (type);
13530 	type = type->baseType;
13531     }
13532 
13533     return (NULL);
13534 }
13535 
13536 #if 0
13537 /**
13538  * xmlSchemaGetBuiltInTypeAncestor:
13539  * @type:  the simpleType definition
13540  *
13541  * Returns the primitive type of the given type or
13542  * NULL in case of error.
13543  */
13544 static xmlSchemaTypePtr
13545 xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
13546 {
13547     if (WXS_IS_LIST(type) || WXS_IS_UNION(type))
13548 	return (0);
13549     while (type != NULL) {
13550 	if (type->type == XML_SCHEMA_TYPE_BASIC)
13551 	    return (type);
13552 	type = type->baseType;
13553     }
13554 
13555     return (NULL);
13556 }
13557 #endif
13558 
13559 /**
13560  * xmlSchemaCloneWildcardNsConstraints:
13561  * @ctxt:  the schema parser context
13562  * @dest:  the destination wildcard
13563  * @source: the source wildcard
13564  *
13565  * Clones the namespace constraints of source
13566  * and assigns them to dest.
13567  * Returns -1 on internal error, 0 otherwise.
13568  */
13569 static int
xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,xmlSchemaWildcardPtr dest,xmlSchemaWildcardPtr source)13570 xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
13571 				    xmlSchemaWildcardPtr dest,
13572 				    xmlSchemaWildcardPtr source)
13573 {
13574     xmlSchemaWildcardNsPtr cur, tmp, last;
13575 
13576     if ((source == NULL) || (dest == NULL))
13577 	return(-1);
13578     dest->any = source->any;
13579     cur = source->nsSet;
13580     last = NULL;
13581     while (cur != NULL) {
13582 	tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
13583 	if (tmp == NULL)
13584 	    return(-1);
13585 	tmp->value = cur->value;
13586 	if (last == NULL)
13587 	    dest->nsSet = tmp;
13588 	else
13589 	    last->next = tmp;
13590 	last = tmp;
13591 	cur = cur->next;
13592     }
13593     if (dest->negNsSet != NULL)
13594 	xmlSchemaFreeWildcardNsSet(dest->negNsSet);
13595     if (source->negNsSet != NULL) {
13596 	dest->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13597 	if (dest->negNsSet == NULL)
13598 	    return(-1);
13599 	dest->negNsSet->value = source->negNsSet->value;
13600     } else
13601 	dest->negNsSet = NULL;
13602     return(0);
13603 }
13604 
13605 /**
13606  * xmlSchemaUnionWildcards:
13607  * @ctxt:  the schema parser context
13608  * @completeWild:  the first wildcard
13609  * @curWild: the second wildcard
13610  *
13611  * Unions the namespace constraints of the given wildcards.
13612  * @completeWild will hold the resulting union.
13613  * Returns a positive error code on failure, -1 in case of an
13614  * internal error, 0 otherwise.
13615  */
13616 static int
xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,xmlSchemaWildcardPtr completeWild,xmlSchemaWildcardPtr curWild)13617 xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
13618 			    xmlSchemaWildcardPtr completeWild,
13619 			    xmlSchemaWildcardPtr curWild)
13620 {
13621     xmlSchemaWildcardNsPtr cur, curB, tmp;
13622 
13623     /*
13624     * 1 If O1 and O2 are the same value, then that value must be the
13625     * value.
13626     */
13627     if ((completeWild->any == curWild->any) &&
13628 	((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13629 	((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
13630 
13631 	if ((completeWild->negNsSet == NULL) ||
13632 	    (completeWild->negNsSet->value == curWild->negNsSet->value)) {
13633 
13634 	    if (completeWild->nsSet != NULL) {
13635 		int found = 0;
13636 
13637 		/*
13638 		* Check equality of sets.
13639 		*/
13640 		cur = completeWild->nsSet;
13641 		while (cur != NULL) {
13642 		    found = 0;
13643 		    curB = curWild->nsSet;
13644 		    while (curB != NULL) {
13645 			if (cur->value == curB->value) {
13646 			    found = 1;
13647 			    break;
13648 			}
13649 			curB = curB->next;
13650 		    }
13651 		    if (!found)
13652 			break;
13653 		    cur = cur->next;
13654 		}
13655 		if (found)
13656 		    return(0);
13657 	    } else
13658 		return(0);
13659 	}
13660     }
13661     /*
13662     * 2 If either O1 or O2 is any, then any must be the value
13663     */
13664     if (completeWild->any != curWild->any) {
13665 	if (completeWild->any == 0) {
13666 	    completeWild->any = 1;
13667 	    if (completeWild->nsSet != NULL) {
13668 		xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13669 		completeWild->nsSet = NULL;
13670 	    }
13671 	    if (completeWild->negNsSet != NULL) {
13672 		xmlFree(completeWild->negNsSet);
13673 		completeWild->negNsSet = NULL;
13674 	    }
13675 	}
13676 	return (0);
13677     }
13678     /*
13679     * 3 If both O1 and O2 are sets of (namespace names or `absent`),
13680     * then the union of those sets must be the value.
13681     */
13682     if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
13683 	int found;
13684 	xmlSchemaWildcardNsPtr start;
13685 
13686 	cur = curWild->nsSet;
13687 	start = completeWild->nsSet;
13688 	while (cur != NULL) {
13689 	    found = 0;
13690 	    curB = start;
13691 	    while (curB != NULL) {
13692 		if (cur->value == curB->value) {
13693 		    found = 1;
13694 		    break;
13695 		}
13696 		curB = curB->next;
13697 	    }
13698 	    if (!found) {
13699 		tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
13700 		if (tmp == NULL)
13701 		    return (-1);
13702 		tmp->value = cur->value;
13703 		tmp->next = completeWild->nsSet;
13704 		completeWild->nsSet = tmp;
13705 	    }
13706 	    cur = cur->next;
13707 	}
13708 
13709 	return(0);
13710     }
13711     /*
13712     * 4 If the two are negations of different values (namespace names
13713     * or `absent`), then a pair of not and `absent` must be the value.
13714     */
13715     if ((completeWild->negNsSet != NULL) &&
13716 	(curWild->negNsSet != NULL) &&
13717 	(completeWild->negNsSet->value != curWild->negNsSet->value)) {
13718 	completeWild->negNsSet->value = NULL;
13719 
13720 	return(0);
13721     }
13722     /*
13723      * 5.
13724      */
13725     if (((completeWild->negNsSet != NULL) &&
13726 	(completeWild->negNsSet->value != NULL) &&
13727 	(curWild->nsSet != NULL)) ||
13728 	((curWild->negNsSet != NULL) &&
13729 	(curWild->negNsSet->value != NULL) &&
13730 	(completeWild->nsSet != NULL))) {
13731 
13732 	int nsFound, absentFound = 0;
13733 
13734 	if (completeWild->nsSet != NULL) {
13735 	    cur = completeWild->nsSet;
13736 	    curB = curWild->negNsSet;
13737 	} else {
13738 	    cur = curWild->nsSet;
13739 	    curB = completeWild->negNsSet;
13740 	}
13741 	nsFound = 0;
13742 	while (cur != NULL) {
13743 	    if (cur->value == NULL)
13744 		absentFound = 1;
13745 	    else if (cur->value == curB->value)
13746 		nsFound = 1;
13747 	    if (nsFound && absentFound)
13748 		break;
13749 	    cur = cur->next;
13750 	}
13751 
13752 	if (nsFound && absentFound) {
13753 	    /*
13754 	    * 5.1 If the set S includes both the negated namespace
13755 	    * name and `absent`, then any must be the value.
13756 	    */
13757 	    completeWild->any = 1;
13758 	    if (completeWild->nsSet != NULL) {
13759 		xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13760 		completeWild->nsSet = NULL;
13761 	    }
13762 	    if (completeWild->negNsSet != NULL) {
13763 		xmlFree(completeWild->negNsSet);
13764 		completeWild->negNsSet = NULL;
13765 	    }
13766 	} else if (nsFound && (!absentFound)) {
13767 	    /*
13768 	    * 5.2 If the set S includes the negated namespace name
13769 	    * but not `absent`, then a pair of not and `absent` must
13770 	    * be the value.
13771 	    */
13772 	    if (completeWild->nsSet != NULL) {
13773 		xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13774 		completeWild->nsSet = NULL;
13775 	    }
13776 	    if (completeWild->negNsSet == NULL) {
13777 		completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13778 		if (completeWild->negNsSet == NULL)
13779 		    return (-1);
13780 	    }
13781 	    completeWild->negNsSet->value = NULL;
13782 	} else if ((!nsFound) && absentFound) {
13783 	    /*
13784 	    * 5.3 If the set S includes `absent` but not the negated
13785 	    * namespace name, then the union is not expressible.
13786 	    */
13787 	    xmlSchemaPErr(ctxt, completeWild->node,
13788 		XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
13789 		"The union of the wildcard is not expressible.\n",
13790 		NULL, NULL);
13791 	    return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
13792 	} else if ((!nsFound) && (!absentFound)) {
13793 	    /*
13794 	    * 5.4 If the set S does not include either the negated namespace
13795 	    * name or `absent`, then whichever of O1 or O2 is a pair of not
13796 	    * and a namespace name must be the value.
13797 	    */
13798 	    if (completeWild->negNsSet == NULL) {
13799 		if (completeWild->nsSet != NULL) {
13800 		    xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13801 		    completeWild->nsSet = NULL;
13802 		}
13803 		completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13804 		if (completeWild->negNsSet == NULL)
13805 		    return (-1);
13806 		completeWild->negNsSet->value = curWild->negNsSet->value;
13807 	    }
13808 	}
13809 	return (0);
13810     }
13811     /*
13812      * 6.
13813      */
13814     if (((completeWild->negNsSet != NULL) &&
13815 	(completeWild->negNsSet->value == NULL) &&
13816 	(curWild->nsSet != NULL)) ||
13817 	((curWild->negNsSet != NULL) &&
13818 	(curWild->negNsSet->value == NULL) &&
13819 	(completeWild->nsSet != NULL))) {
13820 
13821 	if (completeWild->nsSet != NULL) {
13822 	    cur = completeWild->nsSet;
13823 	} else {
13824 	    cur = curWild->nsSet;
13825 	}
13826 	while (cur != NULL) {
13827 	    if (cur->value == NULL) {
13828 		/*
13829 		* 6.1 If the set S includes `absent`, then any must be the
13830 		* value.
13831 		*/
13832 		completeWild->any = 1;
13833 		if (completeWild->nsSet != NULL) {
13834 		    xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13835 		    completeWild->nsSet = NULL;
13836 		}
13837 		if (completeWild->negNsSet != NULL) {
13838 		    xmlFree(completeWild->negNsSet);
13839 		    completeWild->negNsSet = NULL;
13840 		}
13841 		return (0);
13842 	    }
13843 	    cur = cur->next;
13844 	}
13845 	if (completeWild->negNsSet == NULL) {
13846 	    /*
13847 	    * 6.2 If the set S does not include `absent`, then a pair of not
13848 	    * and `absent` must be the value.
13849 	    */
13850 	    if (completeWild->nsSet != NULL) {
13851 		xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13852 		completeWild->nsSet = NULL;
13853 	    }
13854 	    completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13855 	    if (completeWild->negNsSet == NULL)
13856 		return (-1);
13857 	    completeWild->negNsSet->value = NULL;
13858 	}
13859 	return (0);
13860     }
13861     return (0);
13862 
13863 }
13864 
13865 /**
13866  * xmlSchemaIntersectWildcards:
13867  * @ctxt:  the schema parser context
13868  * @completeWild:  the first wildcard
13869  * @curWild: the second wildcard
13870  *
13871  * Intersects the namespace constraints of the given wildcards.
13872  * @completeWild will hold the resulting intersection.
13873  * Returns a positive error code on failure, -1 in case of an
13874  * internal error, 0 otherwise.
13875  */
13876 static int
xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,xmlSchemaWildcardPtr completeWild,xmlSchemaWildcardPtr curWild)13877 xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
13878 			    xmlSchemaWildcardPtr completeWild,
13879 			    xmlSchemaWildcardPtr curWild)
13880 {
13881     xmlSchemaWildcardNsPtr cur, curB, prev,  tmp;
13882 
13883     /*
13884     * 1 If O1 and O2 are the same value, then that value must be the
13885     * value.
13886     */
13887     if ((completeWild->any == curWild->any) &&
13888 	((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13889 	((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
13890 
13891 	if ((completeWild->negNsSet == NULL) ||
13892 	    (completeWild->negNsSet->value == curWild->negNsSet->value)) {
13893 
13894 	    if (completeWild->nsSet != NULL) {
13895 		int found = 0;
13896 
13897 		/*
13898 		* Check equality of sets.
13899 		*/
13900 		cur = completeWild->nsSet;
13901 		while (cur != NULL) {
13902 		    found = 0;
13903 		    curB = curWild->nsSet;
13904 		    while (curB != NULL) {
13905 			if (cur->value == curB->value) {
13906 			    found = 1;
13907 			    break;
13908 			}
13909 			curB = curB->next;
13910 		    }
13911 		    if (!found)
13912 			break;
13913 		    cur = cur->next;
13914 		}
13915 		if (found)
13916 		    return(0);
13917 	    } else
13918 		return(0);
13919 	}
13920     }
13921     /*
13922     * 2 If either O1 or O2 is any, then the other must be the value.
13923     */
13924     if ((completeWild->any != curWild->any) && (completeWild->any)) {
13925 	if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
13926 	    return(-1);
13927 	return(0);
13928     }
13929     /*
13930     * 3 If either O1 or O2 is a pair of not and a value (a namespace
13931     * name or `absent`) and the other is a set of (namespace names or
13932     * `absent`), then that set, minus the negated value if it was in
13933     * the set, minus `absent` if it was in the set, must be the value.
13934     */
13935     if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
13936 	((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
13937 	const xmlChar *neg;
13938 
13939 	if (completeWild->nsSet == NULL) {
13940 	    neg = completeWild->negNsSet->value;
13941 	    if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
13942 		return(-1);
13943 	} else
13944 	    neg = curWild->negNsSet->value;
13945 	/*
13946 	* Remove absent and negated.
13947 	*/
13948 	prev = NULL;
13949 	cur = completeWild->nsSet;
13950 	while (cur != NULL) {
13951 	    if (cur->value == NULL) {
13952 		if (prev == NULL)
13953 		    completeWild->nsSet = cur->next;
13954 		else
13955 		    prev->next = cur->next;
13956 		xmlFree(cur);
13957 		break;
13958 	    }
13959 	    prev = cur;
13960 	    cur = cur->next;
13961 	}
13962 	if (neg != NULL) {
13963 	    prev = NULL;
13964 	    cur = completeWild->nsSet;
13965 	    while (cur != NULL) {
13966 		if (cur->value == neg) {
13967 		    if (prev == NULL)
13968 			completeWild->nsSet = cur->next;
13969 		    else
13970 			prev->next = cur->next;
13971 		    xmlFree(cur);
13972 		    break;
13973 		}
13974 		prev = cur;
13975 		cur = cur->next;
13976 	    }
13977 	}
13978 
13979 	return(0);
13980     }
13981     /*
13982     * 4 If both O1 and O2 are sets of (namespace names or `absent`),
13983     * then the intersection of those sets must be the value.
13984     */
13985     if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
13986 	int found;
13987 
13988 	cur = completeWild->nsSet;
13989 	prev = NULL;
13990 	while (cur != NULL) {
13991 	    found = 0;
13992 	    curB = curWild->nsSet;
13993 	    while (curB != NULL) {
13994 		if (cur->value == curB->value) {
13995 		    found = 1;
13996 		    break;
13997 		}
13998 		curB = curB->next;
13999 	    }
14000 	    if (!found) {
14001 		if (prev == NULL)
14002 		    completeWild->nsSet = cur->next;
14003 		else
14004 		    prev->next = cur->next;
14005 		tmp = cur->next;
14006 		xmlFree(cur);
14007 		cur = tmp;
14008 		continue;
14009 	    }
14010 	    prev = cur;
14011 	    cur = cur->next;
14012 	}
14013 
14014 	return(0);
14015     }
14016     /* 5 If the two are negations of different namespace names,
14017     * then the intersection is not expressible
14018     */
14019     if ((completeWild->negNsSet != NULL) &&
14020 	(curWild->negNsSet != NULL) &&
14021 	(completeWild->negNsSet->value != curWild->negNsSet->value) &&
14022 	(completeWild->negNsSet->value != NULL) &&
14023 	(curWild->negNsSet->value != NULL)) {
14024 
14025 	xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
14026 	    "The intersection of the wildcard is not expressible.\n",
14027 	    NULL, NULL);
14028 	return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
14029     }
14030     /*
14031     * 6 If the one is a negation of a namespace name and the other
14032     * is a negation of `absent`, then the one which is the negation
14033     * of a namespace name must be the value.
14034     */
14035     if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
14036 	(completeWild->negNsSet->value != curWild->negNsSet->value) &&
14037 	(completeWild->negNsSet->value == NULL)) {
14038 	completeWild->negNsSet->value =  curWild->negNsSet->value;
14039     }
14040     return(0);
14041 }
14042 
14043 /**
14044  * xmlSchemaIsWildcardNsConstraintSubset:
14045  * @ctxt:  the schema parser context
14046  * @sub:  the first wildcard
14047  * @super: the second wildcard
14048  *
14049  * Schema Component Constraint: Wildcard Subset (cos-ns-subset)
14050  *
14051  * Returns 0 if the namespace constraint of @sub is an intensional
14052  * subset of @super, 1 otherwise.
14053  */
14054 static int
xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub,xmlSchemaWildcardPtr super)14055 xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub,
14056 			  xmlSchemaWildcardPtr super)
14057 {
14058     /*
14059     * 1 super must be any.
14060     */
14061     if (super->any)
14062 	return (0);
14063     /*
14064     * 2.1 sub must be a pair of not and a namespace name or `absent`.
14065     * 2.2 super must be a pair of not and the same value.
14066     */
14067     if ((sub->negNsSet != NULL) &&
14068 	(super->negNsSet != NULL) &&
14069 	(sub->negNsSet->value == super->negNsSet->value))
14070 	return (0);
14071     /*
14072     * 3.1 sub must be a set whose members are either namespace names or `absent`.
14073     */
14074     if (sub->nsSet != NULL) {
14075 	/*
14076 	* 3.2.1 super must be the same set or a superset thereof.
14077 	*/
14078 	if (super->nsSet != NULL) {
14079 	    xmlSchemaWildcardNsPtr cur, curB;
14080 	    int found = 0;
14081 
14082 	    cur = sub->nsSet;
14083 	    while (cur != NULL) {
14084 		found = 0;
14085 		curB = super->nsSet;
14086 		while (curB != NULL) {
14087 		    if (cur->value == curB->value) {
14088 			found = 1;
14089 			break;
14090 		    }
14091 		    curB = curB->next;
14092 		}
14093 		if (!found)
14094 		    return (1);
14095 		cur = cur->next;
14096 	    }
14097 	    if (found)
14098 		return (0);
14099 	} else if (super->negNsSet != NULL) {
14100 	    xmlSchemaWildcardNsPtr cur;
14101 	    /*
14102 	    * 3.2.2 super must be a pair of not and a namespace name or
14103 	    * `absent` and that value must not be in sub's set.
14104 	    */
14105 	    cur = sub->nsSet;
14106 	    while (cur != NULL) {
14107 		if (cur->value == super->negNsSet->value)
14108 		    return (1);
14109 		cur = cur->next;
14110 	    }
14111 	    return (0);
14112 	}
14113     }
14114     return (1);
14115 }
14116 
14117 static int
xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributeUsePtr attruse,int * fixed,const xmlChar ** value,xmlSchemaValPtr * val)14118 xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributeUsePtr attruse,
14119 				     int *fixed,
14120 				     const xmlChar **value,
14121 				     xmlSchemaValPtr *val)
14122 {
14123     *fixed = 0;
14124     *value = NULL;
14125     if (val != 0)
14126 	*val = NULL;
14127 
14128     if (attruse->defValue != NULL) {
14129 	*value = attruse->defValue;
14130 	if (val != NULL)
14131 	    *val = attruse->defVal;
14132 	if (attruse->flags & XML_SCHEMA_ATTR_USE_FIXED)
14133 	    *fixed = 1;
14134 	return(1);
14135     } else if ((attruse->attrDecl != NULL) &&
14136 	(attruse->attrDecl->defValue != NULL)) {
14137 	*value = attruse->attrDecl->defValue;
14138 	if (val != NULL)
14139 	    *val = attruse->attrDecl->defVal;
14140 	if (attruse->attrDecl->flags & XML_SCHEMAS_ATTR_FIXED)
14141 	    *fixed = 1;
14142 	return(1);
14143     }
14144     return(0);
14145 }
14146 /**
14147  * xmlSchemaCheckCVCWildcardNamespace:
14148  * @wild:  the wildcard
14149  * @ns:  the namespace
14150  *
14151  * Validation Rule: Wildcard allows Namespace Name
14152  * (cvc-wildcard-namespace)
14153  *
14154  * Returns 0 if the given namespace matches the wildcard,
14155  * 1 otherwise and -1 on API errors.
14156  */
14157 static int
xmlSchemaCheckCVCWildcardNamespace(xmlSchemaWildcardPtr wild,const xmlChar * ns)14158 xmlSchemaCheckCVCWildcardNamespace(xmlSchemaWildcardPtr wild,
14159 				   const xmlChar* ns)
14160 {
14161     if (wild == NULL)
14162 	return(-1);
14163 
14164     if (wild->any)
14165 	return(0);
14166     else if (wild->nsSet != NULL) {
14167 	xmlSchemaWildcardNsPtr cur;
14168 
14169 	cur = wild->nsSet;
14170 	while (cur != NULL) {
14171 	    if (xmlStrEqual(cur->value, ns))
14172 		return(0);
14173 	    cur = cur->next;
14174 	}
14175     } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
14176 	(!xmlStrEqual(wild->negNsSet->value, ns)))
14177 	return(0);
14178 
14179     return(1);
14180 }
14181 
14182 #define XML_SCHEMA_ACTION_DERIVE 0
14183 #define XML_SCHEMA_ACTION_REDEFINE 1
14184 
14185 #define WXS_ACTION_STR(a) \
14186 ((a) == XML_SCHEMA_ACTION_DERIVE) ? (const xmlChar *) "base" : (const xmlChar *) "redefined"
14187 
14188 /*
14189 * Schema Component Constraint:
14190 *   Derivation Valid (Restriction, Complex)
14191 *   derivation-ok-restriction (2) - (4)
14192 *
14193 * ATTENTION:
14194 * In XML Schema 1.1 this will be:
14195 * Validation Rule:
14196 *     Checking complex type subsumption (practicalSubsumption) (1, 2 and 3)
14197 *
14198 */
14199 static int
xmlSchemaCheckDerivationOKRestriction2to4(xmlSchemaParserCtxtPtr pctxt,int action,xmlSchemaBasicItemPtr item,xmlSchemaBasicItemPtr baseItem,xmlSchemaItemListPtr uses,xmlSchemaItemListPtr baseUses,xmlSchemaWildcardPtr wild,xmlSchemaWildcardPtr baseWild)14200 xmlSchemaCheckDerivationOKRestriction2to4(xmlSchemaParserCtxtPtr pctxt,
14201 				       int action,
14202 				       xmlSchemaBasicItemPtr item,
14203 				       xmlSchemaBasicItemPtr baseItem,
14204 				       xmlSchemaItemListPtr uses,
14205 				       xmlSchemaItemListPtr baseUses,
14206 				       xmlSchemaWildcardPtr wild,
14207 				       xmlSchemaWildcardPtr baseWild)
14208 {
14209     xmlSchemaAttributeUsePtr cur = NULL, bcur;
14210     int i, j, found; /* err = 0; */
14211     const xmlChar *bEffValue;
14212     int effFixed;
14213 
14214     if (uses != NULL) {
14215 	for (i = 0; i < uses->nbItems; i++) {
14216 	    cur = uses->items[i];
14217 	    found = 0;
14218 	    if (baseUses == NULL)
14219 		goto not_found;
14220 	    for (j = 0; j < baseUses->nbItems; j++) {
14221 		bcur = baseUses->items[j];
14222 		if ((WXS_ATTRUSE_DECL_NAME(cur) ==
14223 			WXS_ATTRUSE_DECL_NAME(bcur)) &&
14224 		    (WXS_ATTRUSE_DECL_TNS(cur) ==
14225 			WXS_ATTRUSE_DECL_TNS(bcur)))
14226 		{
14227 		    /*
14228 		    * (2.1) "If there is an attribute use in the {attribute
14229 		    * uses} of the {base type definition} (call this B) whose
14230 		    * {attribute declaration} has the same {name} and {target
14231 		    * namespace}, then  all of the following must be true:"
14232 		    */
14233 		    found = 1;
14234 
14235 		    if ((cur->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
14236 			(bcur->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED))
14237 		    {
14238 			xmlChar *str = NULL;
14239 			/*
14240 			* (2.1.1) "one of the following must be true:"
14241 			* (2.1.1.1) "B's {required} is false."
14242 			* (2.1.1.2) "R's {required} is true."
14243 			*/
14244 			xmlSchemaPAttrUseErr4(pctxt,
14245 			    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
14246 			    WXS_ITEM_NODE(item), item, cur,
14247 			    "The 'optional' attribute use is inconsistent "
14248 			    "with the corresponding 'required' attribute use of "
14249 			    "the %s %s",
14250 			    WXS_ACTION_STR(action),
14251 			    xmlSchemaGetComponentDesignation(&str, baseItem),
14252 			    NULL, NULL);
14253 			FREE_AND_NULL(str);
14254 			/* err = pctxt->err; */
14255 		    } else if (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
14256 			WXS_ATTRUSE_TYPEDEF(cur),
14257 			WXS_ATTRUSE_TYPEDEF(bcur), 0) != 0)
14258 		    {
14259 			xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
14260 
14261 			/*
14262 			* SPEC (2.1.2) "R's {attribute declaration}'s
14263 			* {type definition} must be validly derived from
14264 			* B's {type definition} given the empty set as
14265 			* defined in Type Derivation OK (Simple) ($3.14.6)."
14266 			*/
14267 			xmlSchemaPAttrUseErr4(pctxt,
14268 			    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_2,
14269 			    WXS_ITEM_NODE(item), item, cur,
14270 			    "The attribute declaration's %s "
14271 			    "is not validly derived from "
14272 			    "the corresponding %s of the "
14273 			    "attribute declaration in the %s %s",
14274 			    xmlSchemaGetComponentDesignation(&strA,
14275 				WXS_ATTRUSE_TYPEDEF(cur)),
14276 			    xmlSchemaGetComponentDesignation(&strB,
14277 				WXS_ATTRUSE_TYPEDEF(bcur)),
14278 			    WXS_ACTION_STR(action),
14279 			    xmlSchemaGetComponentDesignation(&strC, baseItem));
14280 			    /* xmlSchemaGetComponentDesignation(&str, baseItem), */
14281 			FREE_AND_NULL(strA);
14282 			FREE_AND_NULL(strB);
14283 			FREE_AND_NULL(strC);
14284 			/* err = pctxt->err; */
14285 		    } else {
14286 			/*
14287 			* 2.1.3 [Definition:]  Let the effective value
14288 			* constraint of an attribute use be its {value
14289 			* constraint}, if present, otherwise its {attribute
14290 			* declaration}'s {value constraint} .
14291 			*/
14292 			xmlSchemaGetEffectiveValueConstraint(bcur,
14293 			    &effFixed, &bEffValue, NULL);
14294 			/*
14295 			* 2.1.3 ... one of the following must be true
14296 			*
14297 			* 2.1.3.1 B's `effective value constraint` is
14298 			* `absent` or default.
14299 			*/
14300 			if ((bEffValue != NULL) &&
14301 			    (effFixed == 1)) {
14302 			    const xmlChar *rEffValue = NULL;
14303 
14304 			    xmlSchemaGetEffectiveValueConstraint(bcur,
14305 				&effFixed, &rEffValue, NULL);
14306 			    /*
14307 			    * 2.1.3.2 R's `effective value constraint` is
14308 			    * fixed with the same string as B's.
14309 			    * MAYBE TODO: Compare the computed values.
14310 			    *       Hmm, it says "same string" so
14311 			    *       string-equality might really be sufficient.
14312 			    */
14313 			    if ((effFixed == 0) ||
14314 				(! WXS_ARE_DEFAULT_STR_EQUAL(rEffValue, bEffValue)))
14315 			    {
14316 				xmlChar *str = NULL;
14317 
14318 				xmlSchemaPAttrUseErr4(pctxt,
14319 				    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
14320 				    WXS_ITEM_NODE(item), item, cur,
14321 				    "The effective value constraint of the "
14322 				    "attribute use is inconsistent with "
14323 				    "its correspondent in the %s %s",
14324 				    WXS_ACTION_STR(action),
14325 				    xmlSchemaGetComponentDesignation(&str,
14326 					baseItem),
14327 				    NULL, NULL);
14328 				FREE_AND_NULL(str);
14329 				/* err = pctxt->err; */
14330 			    }
14331 			}
14332 		    }
14333 		    break;
14334 		}
14335 	    }
14336 not_found:
14337 	    if (!found) {
14338 		/*
14339 		* (2.2) "otherwise the {base type definition} must have an
14340 		* {attribute wildcard} and the {target namespace} of the
14341 		* R's {attribute declaration} must be `valid` with respect
14342 		* to that wildcard, as defined in Wildcard allows Namespace
14343 		* Name ($3.10.4)."
14344 		*/
14345 		if ((baseWild == NULL) ||
14346 		    (xmlSchemaCheckCVCWildcardNamespace(baseWild,
14347 		    (WXS_ATTRUSE_DECL(cur))->targetNamespace) != 0))
14348 		{
14349 		    xmlChar *str = NULL;
14350 
14351 		    xmlSchemaPAttrUseErr4(pctxt,
14352 			XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
14353 			WXS_ITEM_NODE(item), item, cur,
14354 			"Neither a matching attribute use, "
14355 			"nor a matching wildcard exists in the %s %s",
14356 			WXS_ACTION_STR(action),
14357 			xmlSchemaGetComponentDesignation(&str, baseItem),
14358 			NULL, NULL);
14359 		    FREE_AND_NULL(str);
14360 		    /* err = pctxt->err; */
14361 		}
14362 	    }
14363 	}
14364     }
14365     /*
14366     * SPEC derivation-ok-restriction (3):
14367     * (3) "For each attribute use in the {attribute uses} of the {base type
14368     * definition} whose {required} is true, there must be an attribute
14369     * use with an {attribute declaration} with the same {name} and
14370     * {target namespace} as its {attribute declaration} in the {attribute
14371     * uses} of the complex type definition itself whose {required} is true.
14372     */
14373     if (baseUses != NULL) {
14374 	for (j = 0; j < baseUses->nbItems; j++) {
14375 	    bcur = baseUses->items[j];
14376 	    if (bcur->occurs != XML_SCHEMAS_ATTR_USE_REQUIRED)
14377 		continue;
14378 	    found = 0;
14379 	    if (uses != NULL) {
14380 		for (i = 0; i < uses->nbItems; i++) {
14381 		    cur = uses->items[i];
14382 		    if ((WXS_ATTRUSE_DECL_NAME(cur) ==
14383 			WXS_ATTRUSE_DECL_NAME(bcur)) &&
14384 			(WXS_ATTRUSE_DECL_TNS(cur) ==
14385 			WXS_ATTRUSE_DECL_TNS(bcur))) {
14386 			found = 1;
14387 			break;
14388 		    }
14389 		}
14390 	    }
14391 	    if (!found) {
14392 		xmlChar *strA = NULL, *strB = NULL;
14393 
14394 		xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14395 		    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
14396 		    NULL, item,
14397 		    "A matching attribute use for the "
14398 		    "'required' %s of the %s %s is missing",
14399 		    xmlSchemaGetComponentDesignation(&strA, bcur),
14400 		    WXS_ACTION_STR(action),
14401 		    xmlSchemaGetComponentDesignation(&strB, baseItem),
14402 		    NULL);
14403 		FREE_AND_NULL(strA);
14404 		FREE_AND_NULL(strB);
14405 	    }
14406 	}
14407     }
14408     /*
14409     * derivation-ok-restriction (4)
14410     */
14411     if (wild != NULL) {
14412 	/*
14413 	* (4) "If there is an {attribute wildcard}, all of the
14414 	* following must be true:"
14415 	*/
14416 	if (baseWild == NULL) {
14417 	    xmlChar *str = NULL;
14418 
14419 	    /*
14420 	    * (4.1) "The {base type definition} must also have one."
14421 	    */
14422 	    xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14423 		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
14424 		NULL, item,
14425 		"The %s has an attribute wildcard, "
14426 		"but the %s %s '%s' does not have one",
14427 		WXS_ITEM_TYPE_NAME(item),
14428 		WXS_ACTION_STR(action),
14429 		WXS_ITEM_TYPE_NAME(baseItem),
14430 		xmlSchemaGetComponentQName(&str, baseItem));
14431 	    FREE_AND_NULL(str);
14432 	    return(pctxt->err);
14433 	} else if ((baseWild->any == 0) &&
14434 		xmlSchemaCheckCOSNSSubset(wild, baseWild))
14435 	{
14436 	    xmlChar *str = NULL;
14437 	    /*
14438 	    * (4.2) "The complex type definition's {attribute wildcard}'s
14439 	    * {namespace constraint} must be a subset of the {base type
14440 	    * definition}'s {attribute wildcard}'s {namespace constraint},
14441 	    * as defined by Wildcard Subset ($3.10.6)."
14442 	    */
14443 	    xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14444 		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
14445 		NULL, item,
14446 		"The attribute wildcard is not a valid "
14447 		"subset of the wildcard in the %s %s '%s'",
14448 		WXS_ACTION_STR(action),
14449 		WXS_ITEM_TYPE_NAME(baseItem),
14450 		xmlSchemaGetComponentQName(&str, baseItem),
14451 		NULL);
14452 	    FREE_AND_NULL(str);
14453 	    return(pctxt->err);
14454 	}
14455 	/* 4.3 Unless the {base type definition} is the `ur-type
14456 	* definition`, the complex type definition's {attribute
14457 	* wildcard}'s {process contents} must be identical to or
14458 	* stronger than the {base type definition}'s {attribute
14459 	* wildcard}'s {process contents}, where strict is stronger
14460 	* than lax is stronger than skip.
14461 	*/
14462 	if ((! WXS_IS_ANYTYPE(baseItem)) &&
14463 	    (wild->processContents < baseWild->processContents)) {
14464 	    xmlChar *str = NULL;
14465 	    xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14466 		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
14467 		NULL, baseItem,
14468 		"The {process contents} of the attribute wildcard is "
14469 		"weaker than the one in the %s %s '%s'",
14470 		WXS_ACTION_STR(action),
14471 		WXS_ITEM_TYPE_NAME(baseItem),
14472 		xmlSchemaGetComponentQName(&str, baseItem),
14473 		NULL);
14474 	    FREE_AND_NULL(str)
14475 		return(pctxt->err);
14476 	}
14477     }
14478     return(0);
14479 }
14480 
14481 
14482 static int
14483 xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
14484 				  xmlSchemaBasicItemPtr item,
14485 				  xmlSchemaWildcardPtr *completeWild,
14486 				  xmlSchemaItemListPtr list,
14487 				  xmlSchemaItemListPtr prohibs);
14488 /**
14489  * xmlSchemaFixupTypeAttributeUses:
14490  * @ctxt:  the schema parser context
14491  * @type:  the complex type definition
14492  *
14493  *
14494  * Builds the wildcard and the attribute uses on the given complex type.
14495  * Returns -1 if an internal error occurs, 0 otherwise.
14496  *
14497  * ATTENTION TODO: Experimentally this uses pointer comparisons for
14498  * strings, so recheck this if we start to hardcode some schemata, since
14499  * they might not be in the same dict.
14500  * NOTE: It is allowed to "extend" the xs:anyType type.
14501  */
14502 static int
xmlSchemaFixupTypeAttributeUses(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)14503 xmlSchemaFixupTypeAttributeUses(xmlSchemaParserCtxtPtr pctxt,
14504 				  xmlSchemaTypePtr type)
14505 {
14506     xmlSchemaTypePtr baseType = NULL;
14507     xmlSchemaAttributeUsePtr use;
14508     xmlSchemaItemListPtr uses, baseUses, prohibs = NULL;
14509 
14510     if (type->baseType == NULL) {
14511 	PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14512 	    "no base type");
14513         return (-1);
14514     }
14515     baseType = type->baseType;
14516     if (WXS_IS_TYPE_NOT_FIXED(baseType))
14517 	if (xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt) == -1)
14518 	    return(-1);
14519 
14520     uses = type->attrUses;
14521     baseUses = baseType->attrUses;
14522     /*
14523     * Expand attribute group references. And build the 'complete'
14524     * wildcard, i.e. intersect multiple wildcards.
14525     * Move attribute prohibitions into a separate list.
14526     */
14527     if (uses != NULL) {
14528 	if (WXS_IS_RESTRICTION(type)) {
14529 	    /*
14530 	    * This one will transfer all attr. prohibitions
14531 	    * into pctxt->attrProhibs.
14532 	    */
14533 	    if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14534 		WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14535 		pctxt->attrProhibs) == -1)
14536 	    {
14537 		PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14538 		"failed to expand attributes");
14539 	    }
14540 	    if (pctxt->attrProhibs->nbItems != 0)
14541 		prohibs = pctxt->attrProhibs;
14542 	} else {
14543 	    if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14544 		WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14545 		NULL) == -1)
14546 	    {
14547 		PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14548 		"failed to expand attributes");
14549 	    }
14550 	}
14551     }
14552     /*
14553     * Inherit the attribute uses of the base type.
14554     */
14555     if (baseUses != NULL) {
14556 	int i, j;
14557 	xmlSchemaAttributeUseProhibPtr pro;
14558 
14559 	if (WXS_IS_RESTRICTION(type)) {
14560 	    int usesCount;
14561 	    xmlSchemaAttributeUsePtr tmp;
14562 
14563 	    if (uses != NULL)
14564 		usesCount = uses->nbItems;
14565 	    else
14566 		usesCount = 0;
14567 
14568 	    /* Restriction. */
14569 	    for (i = 0; i < baseUses->nbItems; i++) {
14570 		use = baseUses->items[i];
14571 		if (prohibs) {
14572 		    /*
14573 		    * Filter out prohibited uses.
14574 		    */
14575 		    for (j = 0; j < prohibs->nbItems; j++) {
14576 			pro = prohibs->items[j];
14577 			if ((WXS_ATTRUSE_DECL_NAME(use) == pro->name) &&
14578 			    (WXS_ATTRUSE_DECL_TNS(use) ==
14579 				pro->targetNamespace))
14580 			{
14581 			    goto inherit_next;
14582 			}
14583 		    }
14584 		}
14585 		if (usesCount) {
14586 		    /*
14587 		    * Filter out existing uses.
14588 		    */
14589 		    for (j = 0; j < usesCount; j++) {
14590 			tmp = uses->items[j];
14591 			if ((WXS_ATTRUSE_DECL_NAME(use) ==
14592 				WXS_ATTRUSE_DECL_NAME(tmp)) &&
14593 			    (WXS_ATTRUSE_DECL_TNS(use) ==
14594 				WXS_ATTRUSE_DECL_TNS(tmp)))
14595 			{
14596 			    goto inherit_next;
14597 			}
14598 		    }
14599 		}
14600 		if (uses == NULL) {
14601 		    type->attrUses = xmlSchemaItemListCreate();
14602 		    if (type->attrUses == NULL)
14603 			goto exit_failure;
14604 		    uses = type->attrUses;
14605 		}
14606 		xmlSchemaItemListAddSize(uses, 2, use);
14607 inherit_next: {}
14608 	    }
14609 	} else {
14610 	    /* Extension. */
14611 	    for (i = 0; i < baseUses->nbItems; i++) {
14612 		use = baseUses->items[i];
14613 		if (uses == NULL) {
14614 		    type->attrUses = xmlSchemaItemListCreate();
14615 		    if (type->attrUses == NULL)
14616 			goto exit_failure;
14617 		    uses = type->attrUses;
14618 		}
14619 		xmlSchemaItemListAddSize(uses, baseUses->nbItems, use);
14620 	    }
14621 	}
14622     }
14623     /*
14624     * Shrink attr. uses.
14625     */
14626     if (uses) {
14627 	if (uses->nbItems == 0) {
14628 	    xmlSchemaItemListFree(uses);
14629 	    type->attrUses = NULL;
14630 	}
14631 	/*
14632 	* TODO: We could shrink the size of the array
14633 	* to fit the actual number of items.
14634 	*/
14635     }
14636     /*
14637     * Compute the complete wildcard.
14638     */
14639     if (WXS_IS_EXTENSION(type)) {
14640 	if (baseType->attributeWildcard != NULL) {
14641 	    /*
14642 	    * (3.2.2.1) "If the `base wildcard` is non-`absent`, then
14643 	    * the appropriate case among the following:"
14644 	    */
14645 	    if (type->attributeWildcard != NULL) {
14646 		/*
14647 		* Union the complete wildcard with the base wildcard.
14648 		* SPEC {attribute wildcard}
14649 		* (3.2.2.1.2) "otherwise a wildcard whose {process contents}
14650 		* and {annotation} are those of the `complete wildcard`,
14651 		* and whose {namespace constraint} is the intensional union
14652 		* of the {namespace constraint} of the `complete wildcard`
14653 		* and of the `base wildcard`, as defined in Attribute
14654 		* Wildcard Union ($3.10.6)."
14655 		*/
14656 		if (xmlSchemaUnionWildcards(pctxt, type->attributeWildcard,
14657 		    baseType->attributeWildcard) == -1)
14658 		    goto exit_failure;
14659 	    } else {
14660 		/*
14661 		* (3.2.2.1.1) "If the `complete wildcard` is `absent`,
14662 		* then the `base wildcard`."
14663 		*/
14664 		type->attributeWildcard = baseType->attributeWildcard;
14665 	    }
14666 	} else {
14667 	    /*
14668 	    * (3.2.2.2) "otherwise (the `base wildcard` is `absent`) the
14669 	    * `complete wildcard`"
14670 	    * NOOP
14671 	    */
14672 	}
14673     } else {
14674 	/*
14675 	* SPEC {attribute wildcard}
14676 	* (3.1) "If the <restriction> alternative is chosen, then the
14677 	* `complete wildcard`;"
14678 	* NOOP
14679 	*/
14680     }
14681 
14682     return (0);
14683 
14684 exit_failure:
14685     return(-1);
14686 }
14687 
14688 /**
14689  * xmlSchemaTypeFinalContains:
14690  * @schema:  the schema
14691  * @type:  the type definition
14692  * @final: the final
14693  *
14694  * Evaluates if a type definition contains the given "final".
14695  * This does take "finalDefault" into account as well.
14696  *
14697  * Returns 1 if the type does contain the given "final",
14698  * 0 otherwise.
14699  */
14700 static int
xmlSchemaTypeFinalContains(xmlSchemaTypePtr type,int final)14701 xmlSchemaTypeFinalContains(xmlSchemaTypePtr type, int final)
14702 {
14703     if (type == NULL)
14704 	return (0);
14705     if (type->flags & final)
14706 	return (1);
14707     else
14708 	return (0);
14709 }
14710 
14711 /**
14712  * xmlSchemaGetUnionSimpleTypeMemberTypes:
14713  * @type:  the Union Simple Type
14714  *
14715  * Returns a list of member types of @type if existing,
14716  * returns NULL otherwise.
14717  */
14718 static xmlSchemaTypeLinkPtr
xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)14719 xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
14720 {
14721     while ((type != NULL) && (type->type == XML_SCHEMA_TYPE_SIMPLE)) {
14722 	if (type->memberTypes != NULL)
14723 	    return (type->memberTypes);
14724 	else
14725 	    type = type->baseType;
14726     }
14727     return (NULL);
14728 }
14729 
14730 #if 0
14731 /**
14732  * xmlSchemaGetParticleTotalRangeMin:
14733  * @particle: the particle
14734  *
14735  * Schema Component Constraint: Effective Total Range
14736  * (all and sequence) + (choice)
14737  *
14738  * Returns the minimum Effective Total Range.
14739  */
14740 static int
14741 xmlSchemaGetParticleTotalRangeMin(xmlSchemaParticlePtr particle)
14742 {
14743     if ((particle->children == NULL) ||
14744 	(particle->minOccurs == 0))
14745 	return (0);
14746     if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14747 	int min = -1, cur;
14748 	xmlSchemaParticlePtr part =
14749 	    (xmlSchemaParticlePtr) particle->children->children;
14750 
14751 	if (part == NULL)
14752 	    return (0);
14753 	while (part != NULL) {
14754 	    if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14755 		(part->children->type == XML_SCHEMA_TYPE_ANY))
14756 		cur = part->minOccurs;
14757 	    else
14758 		cur = xmlSchemaGetParticleTotalRangeMin(part);
14759 	    if (cur == 0)
14760 		return (0);
14761 	    if ((min > cur) || (min == -1))
14762 		min = cur;
14763 	    part = (xmlSchemaParticlePtr) part->next;
14764 	}
14765 	return (particle->minOccurs * min);
14766     } else {
14767 	/* <all> and <sequence> */
14768 	int sum = 0;
14769 	xmlSchemaParticlePtr part =
14770 	    (xmlSchemaParticlePtr) particle->children->children;
14771 
14772 	if (part == NULL)
14773 	    return (0);
14774 	do {
14775 	    if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14776 		(part->children->type == XML_SCHEMA_TYPE_ANY))
14777 		sum += part->minOccurs;
14778 	    else
14779 		sum += xmlSchemaGetParticleTotalRangeMin(part);
14780 	    part = (xmlSchemaParticlePtr) part->next;
14781 	} while (part != NULL);
14782 	return (particle->minOccurs * sum);
14783     }
14784 }
14785 
14786 /**
14787  * xmlSchemaGetParticleTotalRangeMax:
14788  * @particle: the particle
14789  *
14790  * Schema Component Constraint: Effective Total Range
14791  * (all and sequence) + (choice)
14792  *
14793  * Returns the maximum Effective Total Range.
14794  */
14795 static int
14796 xmlSchemaGetParticleTotalRangeMax(xmlSchemaParticlePtr particle)
14797 {
14798     if ((particle->children == NULL) ||
14799 	(particle->children->children == NULL))
14800 	return (0);
14801     if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14802 	int max = -1, cur;
14803 	xmlSchemaParticlePtr part =
14804 	    (xmlSchemaParticlePtr) particle->children->children;
14805 
14806 	for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14807 	    if (part->children == NULL)
14808 		continue;
14809 	    if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14810 		(part->children->type == XML_SCHEMA_TYPE_ANY))
14811 		cur = part->maxOccurs;
14812 	    else
14813 		cur = xmlSchemaGetParticleTotalRangeMax(part);
14814 	    if (cur == UNBOUNDED)
14815 		return (UNBOUNDED);
14816 	    if ((max < cur) || (max == -1))
14817 		max = cur;
14818 	}
14819 	/* TODO: Handle overflows? */
14820 	return (particle->maxOccurs * max);
14821     } else {
14822 	/* <all> and <sequence> */
14823 	int sum = 0, cur;
14824 	xmlSchemaParticlePtr part =
14825 	    (xmlSchemaParticlePtr) particle->children->children;
14826 
14827 	for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14828 	    if (part->children == NULL)
14829 		continue;
14830 	    if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14831 		(part->children->type == XML_SCHEMA_TYPE_ANY))
14832 		cur = part->maxOccurs;
14833 	    else
14834 		cur = xmlSchemaGetParticleTotalRangeMax(part);
14835 	    if (cur == UNBOUNDED)
14836 		return (UNBOUNDED);
14837 	    if ((cur > 0) && (particle->maxOccurs == UNBOUNDED))
14838 		return (UNBOUNDED);
14839 	    sum += cur;
14840 	}
14841 	/* TODO: Handle overflows? */
14842 	return (particle->maxOccurs * sum);
14843     }
14844 }
14845 #endif
14846 
14847 /**
14848  * xmlSchemaGetParticleEmptiable:
14849  * @particle: the particle
14850  *
14851  * Returns 1 if emptiable, 0 otherwise.
14852  */
14853 static int
xmlSchemaGetParticleEmptiable(xmlSchemaParticlePtr particle)14854 xmlSchemaGetParticleEmptiable(xmlSchemaParticlePtr particle)
14855 {
14856     xmlSchemaParticlePtr part;
14857     int emptiable;
14858 
14859     if ((particle->children == NULL) || (particle->minOccurs == 0))
14860 	return (1);
14861 
14862     part = (xmlSchemaParticlePtr) particle->children->children;
14863     if (part == NULL)
14864         return (1);
14865 
14866     while (part != NULL) {
14867         if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14868             (part->children->type == XML_SCHEMA_TYPE_ANY))
14869             emptiable = (part->minOccurs == 0);
14870         else
14871             emptiable = xmlSchemaGetParticleEmptiable(part);
14872         if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14873             if (emptiable)
14874                 return (1);
14875         } else {
14876 	    /* <all> and <sequence> */
14877             if (!emptiable)
14878                 return (0);
14879         }
14880         part = (xmlSchemaParticlePtr) part->next;
14881     }
14882 
14883     if (particle->children->type == XML_SCHEMA_TYPE_CHOICE)
14884         return (0);
14885     else
14886         return (1);
14887 }
14888 
14889 /**
14890  * xmlSchemaIsParticleEmptiable:
14891  * @particle: the particle
14892  *
14893  * Schema Component Constraint: Particle Emptiable
14894  * Checks whether the given particle is emptiable.
14895  *
14896  * Returns 1 if emptiable, 0 otherwise.
14897  */
14898 static int
xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)14899 xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)
14900 {
14901     /*
14902     * SPEC (1) "Its {min occurs} is 0."
14903     */
14904     if ((particle == NULL) || (particle->minOccurs == 0) ||
14905 	(particle->children == NULL))
14906 	return (1);
14907     /*
14908     * SPEC (2) "Its {term} is a group and the minimum part of the
14909     * effective total range of that group, [...] is 0."
14910     */
14911     if (WXS_IS_MODEL_GROUP(particle->children))
14912 	return (xmlSchemaGetParticleEmptiable(particle));
14913     return (0);
14914 }
14915 
14916 /**
14917  * xmlSchemaCheckCOSSTDerivedOK:
14918  * @actxt: a context
14919  * @type:  the derived simple type definition
14920  * @baseType:  the base type definition
14921  * @subset: the subset of ('restriction', etc.)
14922  *
14923  * Schema Component Constraint:
14924  * Type Derivation OK (Simple) (cos-st-derived-OK)
14925  *
14926  * Checks whether @type can be validly
14927  * derived from @baseType.
14928  *
14929  * Returns 0 on success, an positive error code otherwise.
14930  */
14931 static int
xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,xmlSchemaTypePtr type,xmlSchemaTypePtr baseType,int subset)14932 xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
14933 			     xmlSchemaTypePtr type,
14934 			     xmlSchemaTypePtr baseType,
14935 			     int subset)
14936 {
14937     /*
14938     * 1 They are the same type definition.
14939     * TODO: The identity check might have to be more complex than this.
14940     */
14941     if (type == baseType)
14942 	return (0);
14943     /*
14944     * 2.1 restriction is not in the subset, or in the {final}
14945     * of its own {base type definition};
14946     *
14947     * NOTE that this will be used also via "xsi:type".
14948     *
14949     * TODO: Revise this, it looks strange. How can the "type"
14950     * not be fixed or *in* fixing?
14951     */
14952     if (WXS_IS_TYPE_NOT_FIXED(type))
14953 	if (xmlSchemaTypeFixup(type, actxt) == -1)
14954 	    return(-1);
14955     if (WXS_IS_TYPE_NOT_FIXED(baseType))
14956 	if (xmlSchemaTypeFixup(baseType, actxt) == -1)
14957 	    return(-1);
14958     if ((subset & SUBSET_RESTRICTION) ||
14959 	(xmlSchemaTypeFinalContains(type->baseType,
14960 	    XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
14961 	return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
14962     }
14963     /* 2.2 */
14964     if (type->baseType == baseType) {
14965 	/*
14966 	* 2.2.1 D's `base type definition` is B.
14967 	*/
14968 	return (0);
14969     }
14970     /*
14971     * 2.2.2 D's `base type definition` is not the `ur-type definition`
14972     * and is validly derived from B given the subset, as defined by this
14973     * constraint.
14974     */
14975     if ((! WXS_IS_ANYTYPE(type->baseType)) &&
14976 	(xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
14977 	    baseType, subset) == 0)) {
14978 	return (0);
14979     }
14980     /*
14981     * 2.2.3 D's {variety} is list or union and B is the `simple ur-type
14982     * definition`.
14983     */
14984     if (WXS_IS_ANY_SIMPLE_TYPE(baseType) &&
14985 	(WXS_IS_LIST(type) || WXS_IS_UNION(type))) {
14986 	return (0);
14987     }
14988     /*
14989     * 2.2.4 B's {variety} is union and D is validly derived from a type
14990     * definition in B's {member type definitions} given the subset, as
14991     * defined by this constraint.
14992     *
14993     * NOTE: This seems not to involve built-in types, since there is no
14994     * built-in Union Simple Type.
14995     */
14996     if (WXS_IS_UNION(baseType)) {
14997 	xmlSchemaTypeLinkPtr cur;
14998 
14999 	cur = baseType->memberTypes;
15000 	while (cur != NULL) {
15001 	    if (WXS_IS_TYPE_NOT_FIXED(cur->type))
15002 		if (xmlSchemaTypeFixup(cur->type, actxt) == -1)
15003 		    return(-1);
15004 	    if (xmlSchemaCheckCOSSTDerivedOK(actxt,
15005 		    type, cur->type, subset) == 0)
15006 	    {
15007 		/*
15008 		* It just has to be validly derived from at least one
15009 		* member-type.
15010 		*/
15011 		return (0);
15012 	    }
15013 	    cur = cur->next;
15014 	}
15015     }
15016     return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
15017 }
15018 
15019 /**
15020  * xmlSchemaCheckTypeDefCircularInternal:
15021  * @pctxt:  the schema parser context
15022  * @ctxtType:  the type definition
15023  * @ancestor: an ancestor of @ctxtType
15024  *
15025  * Checks st-props-correct (2) + ct-props-correct (3).
15026  * Circular type definitions are not allowed.
15027  *
15028  * Returns XML_SCHEMAP_ST_PROPS_CORRECT_2 if the given type is
15029  * circular, 0 otherwise.
15030  */
15031 static int
xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr ctxtType,xmlSchemaTypePtr ancestor)15032 xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,
15033 			   xmlSchemaTypePtr ctxtType,
15034 			   xmlSchemaTypePtr ancestor)
15035 {
15036     int ret;
15037 
15038     if ((ancestor == NULL) || (ancestor->type == XML_SCHEMA_TYPE_BASIC))
15039 	return (0);
15040 
15041     if (ctxtType == ancestor) {
15042 	xmlSchemaPCustomErr(pctxt,
15043 	    XML_SCHEMAP_ST_PROPS_CORRECT_2,
15044 	    WXS_BASIC_CAST ctxtType, WXS_ITEM_NODE(ctxtType),
15045 	    "The definition is circular", NULL);
15046 	return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
15047     }
15048     if (ancestor->flags & XML_SCHEMAS_TYPE_MARKED) {
15049 	/*
15050 	* Avoid infinite recursion on circular types not yet checked.
15051 	*/
15052 	return (0);
15053     }
15054     ancestor->flags |= XML_SCHEMAS_TYPE_MARKED;
15055     ret = xmlSchemaCheckTypeDefCircularInternal(pctxt, ctxtType,
15056 	ancestor->baseType);
15057     ancestor->flags ^= XML_SCHEMAS_TYPE_MARKED;
15058     return (ret);
15059 }
15060 
15061 /**
15062  * xmlSchemaCheckTypeDefCircular:
15063  * @item:  the complex/simple type definition
15064  * @ctxt:  the parser context
15065  * @name:  the name
15066  *
15067  * Checks for circular type definitions.
15068  */
15069 static void
xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,xmlSchemaParserCtxtPtr ctxt)15070 xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,
15071 			      xmlSchemaParserCtxtPtr ctxt)
15072 {
15073     if ((item == NULL) ||
15074 	(item->type == XML_SCHEMA_TYPE_BASIC) ||
15075 	(item->baseType == NULL))
15076 	return;
15077     xmlSchemaCheckTypeDefCircularInternal(ctxt, item,
15078 	item->baseType);
15079 }
15080 
15081 /*
15082 * Simple Type Definition Representation OK (src-simple-type) 4
15083 *
15084 * "4 Circular union type definition is disallowed. That is, if the
15085 * <union> alternative is chosen, there must not be any entries in the
15086 * memberTypes [attribute] at any depth which resolve to the component
15087 * corresponding to the <simpleType>."
15088 *
15089 * Note that this should work on the *representation* of a component,
15090 * thus assumes any union types in the member types not being yet
15091 * substituted. At this stage we need the variety of the types
15092 * to be already computed.
15093 */
15094 static int
xmlSchemaCheckUnionTypeDefCircularRecur(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr ctxType,xmlSchemaTypeLinkPtr members)15095 xmlSchemaCheckUnionTypeDefCircularRecur(xmlSchemaParserCtxtPtr pctxt,
15096 					xmlSchemaTypePtr ctxType,
15097 					xmlSchemaTypeLinkPtr members)
15098 {
15099     xmlSchemaTypeLinkPtr member;
15100     xmlSchemaTypePtr memberType;
15101 
15102     member = members;
15103     while (member != NULL) {
15104 	memberType = member->type;
15105 	while ((memberType != NULL) &&
15106 	    (memberType->type != XML_SCHEMA_TYPE_BASIC)) {
15107 	    if (memberType == ctxType) {
15108 		xmlSchemaPCustomErr(pctxt,
15109 		    XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
15110 		    WXS_BASIC_CAST ctxType, NULL,
15111 		    "The union type definition is circular", NULL);
15112 		return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
15113 	    }
15114 	    if ((WXS_IS_UNION(memberType)) &&
15115 		((memberType->flags & XML_SCHEMAS_TYPE_MARKED) == 0))
15116 	    {
15117 		int res;
15118 		memberType->flags |= XML_SCHEMAS_TYPE_MARKED;
15119 		res = xmlSchemaCheckUnionTypeDefCircularRecur(pctxt,
15120 		    ctxType,
15121 		    xmlSchemaGetUnionSimpleTypeMemberTypes(memberType));
15122 		memberType->flags ^= XML_SCHEMAS_TYPE_MARKED;
15123 		if (res != 0)
15124 		    return(res);
15125 	    }
15126 	    memberType = memberType->baseType;
15127 	}
15128 	member = member->next;
15129     }
15130     return(0);
15131 }
15132 
15133 static int
xmlSchemaCheckUnionTypeDefCircular(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)15134 xmlSchemaCheckUnionTypeDefCircular(xmlSchemaParserCtxtPtr pctxt,
15135 				   xmlSchemaTypePtr type)
15136 {
15137     if (! WXS_IS_UNION(type))
15138 	return(0);
15139     return(xmlSchemaCheckUnionTypeDefCircularRecur(pctxt, type,
15140 	type->memberTypes));
15141 }
15142 
15143 /**
15144  * xmlSchemaResolveTypeReferences:
15145  * @item:  the complex/simple type definition
15146  * @ctxt:  the parser context
15147  * @name:  the name
15148  *
15149  * Resolves type definition references
15150  */
15151 static void
xmlSchemaResolveTypeReferences(xmlSchemaTypePtr typeDef,xmlSchemaParserCtxtPtr ctxt)15152 xmlSchemaResolveTypeReferences(xmlSchemaTypePtr typeDef,
15153 			 xmlSchemaParserCtxtPtr ctxt)
15154 {
15155     if (typeDef == NULL)
15156 	return;
15157 
15158     /*
15159     * Resolve the base type.
15160     */
15161     if (typeDef->baseType == NULL) {
15162 	typeDef->baseType = xmlSchemaGetType(ctxt->schema,
15163 	    typeDef->base, typeDef->baseNs);
15164 	if (typeDef->baseType == NULL) {
15165 	    xmlSchemaPResCompAttrErr(ctxt,
15166 		XML_SCHEMAP_SRC_RESOLVE,
15167 		WXS_BASIC_CAST typeDef, typeDef->node,
15168 		"base", typeDef->base, typeDef->baseNs,
15169 		XML_SCHEMA_TYPE_SIMPLE, NULL);
15170 	    return;
15171 	}
15172     }
15173     if (WXS_IS_SIMPLE(typeDef)) {
15174 	if (WXS_IS_UNION(typeDef)) {
15175 	    /*
15176 	    * Resolve the memberTypes.
15177 	    */
15178 	    xmlSchemaResolveUnionMemberTypes(ctxt, typeDef);
15179 	    return;
15180 	} else if (WXS_IS_LIST(typeDef)) {
15181 	    /*
15182 	    * Resolve the itemType.
15183 	    */
15184 	    if ((typeDef->subtypes == NULL) && (typeDef->base != NULL)) {
15185 
15186 		typeDef->subtypes = xmlSchemaGetType(ctxt->schema,
15187 		    typeDef->base, typeDef->baseNs);
15188 
15189 		if ((typeDef->subtypes == NULL) ||
15190 		    (! WXS_IS_SIMPLE(typeDef->subtypes)))
15191 		{
15192 		    typeDef->subtypes = NULL;
15193 		    xmlSchemaPResCompAttrErr(ctxt,
15194 			XML_SCHEMAP_SRC_RESOLVE,
15195 			WXS_BASIC_CAST typeDef, typeDef->node,
15196 			"itemType", typeDef->base, typeDef->baseNs,
15197 			XML_SCHEMA_TYPE_SIMPLE, NULL);
15198 		}
15199 	    }
15200 	    return;
15201 	}
15202     }
15203     /*
15204     * The ball of letters below means, that if we have a particle
15205     * which has a QName-helper component as its {term}, we want
15206     * to resolve it...
15207     */
15208     else if ((WXS_TYPE_CONTENTTYPE(typeDef) != NULL) &&
15209 	((WXS_TYPE_CONTENTTYPE(typeDef))->type ==
15210 	    XML_SCHEMA_TYPE_PARTICLE) &&
15211 	(WXS_TYPE_PARTICLE_TERM(typeDef) != NULL) &&
15212 	((WXS_TYPE_PARTICLE_TERM(typeDef))->type ==
15213 	    XML_SCHEMA_EXTRA_QNAMEREF))
15214     {
15215 	xmlSchemaQNameRefPtr ref =
15216 	    WXS_QNAME_CAST WXS_TYPE_PARTICLE_TERM(typeDef);
15217 	xmlSchemaModelGroupDefPtr groupDef;
15218 
15219 	/*
15220 	* URGENT TODO: Test this.
15221 	*/
15222 	WXS_TYPE_PARTICLE_TERM(typeDef) = NULL;
15223 	/*
15224 	* Resolve the MG definition reference.
15225 	*/
15226 	groupDef =
15227 	    WXS_MODEL_GROUPDEF_CAST xmlSchemaGetNamedComponent(ctxt->schema,
15228 		ref->itemType, ref->name, ref->targetNamespace);
15229 	if (groupDef == NULL) {
15230 	    xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
15231 		NULL, WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)),
15232 		"ref", ref->name, ref->targetNamespace, ref->itemType,
15233 		NULL);
15234 	    /* Remove the particle. */
15235 	    WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
15236 	} else if (WXS_MODELGROUPDEF_MODEL(groupDef) == NULL)
15237 	    /* Remove the particle. */
15238 	    WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
15239 	else {
15240 	    /*
15241 	    * Assign the MG definition's {model group} to the
15242 	    * particle's {term}.
15243 	    */
15244 	    WXS_TYPE_PARTICLE_TERM(typeDef) = WXS_MODELGROUPDEF_MODEL(groupDef);
15245 
15246 	    if (WXS_MODELGROUPDEF_MODEL(groupDef)->type == XML_SCHEMA_TYPE_ALL) {
15247 		/*
15248 		* SPEC cos-all-limited (1.2)
15249 		* "1.2 the {term} property of a particle with
15250 		* {max occurs}=1 which is part of a pair which constitutes
15251 		* the {content type} of a complex type definition."
15252 		*/
15253 		if ((WXS_TYPE_PARTICLE(typeDef))->maxOccurs != 1) {
15254 		    xmlSchemaCustomErr(ACTXT_CAST ctxt,
15255 			/* TODO: error code */
15256 			XML_SCHEMAP_COS_ALL_LIMITED,
15257 			WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)), NULL,
15258 			"The particle's {max occurs} must be 1, since the "
15259 			"reference resolves to an 'all' model group",
15260 			NULL, NULL);
15261 		}
15262 	    }
15263 	}
15264     }
15265 }
15266 
15267 
15268 
15269 /**
15270  * xmlSchemaCheckSTPropsCorrect:
15271  * @ctxt:  the schema parser context
15272  * @type:  the simple type definition
15273  *
15274  * Checks st-props-correct.
15275  *
15276  * Returns 0 if the properties are correct,
15277  * if not, a positive error code and -1 on internal
15278  * errors.
15279  */
15280 static int
xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,xmlSchemaTypePtr type)15281 xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
15282 			     xmlSchemaTypePtr type)
15283 {
15284     xmlSchemaTypePtr baseType = type->baseType;
15285     xmlChar *str = NULL;
15286 
15287     /* STATE: error funcs converted. */
15288     /*
15289     * Schema Component Constraint: Simple Type Definition Properties Correct
15290     *
15291     * NOTE: This is somehow redundant, since we actually built a simple type
15292     * to have all the needed information; this acts as an self test.
15293     */
15294     /* Base type: If the datatype has been `derived` by `restriction`
15295     * then the Simple Type Definition component from which it is `derived`,
15296     * otherwise the Simple Type Definition for anySimpleType ($4.1.6).
15297     */
15298     if (baseType == NULL) {
15299 	/*
15300 	* TODO: Think about: "modulo the impact of Missing
15301 	* Sub-components ($5.3)."
15302 	*/
15303 	xmlSchemaPCustomErr(ctxt,
15304 	    XML_SCHEMAP_ST_PROPS_CORRECT_1,
15305 	    WXS_BASIC_CAST type, NULL,
15306 	    "No base type existent", NULL);
15307 	return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15308 
15309     }
15310     if (! WXS_IS_SIMPLE(baseType)) {
15311 	xmlSchemaPCustomErr(ctxt,
15312 	    XML_SCHEMAP_ST_PROPS_CORRECT_1,
15313 	    WXS_BASIC_CAST type, NULL,
15314 	    "The base type '%s' is not a simple type",
15315 	    xmlSchemaGetComponentQName(&str, baseType));
15316 	FREE_AND_NULL(str)
15317 	return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15318     }
15319     if ((WXS_IS_LIST(type) || WXS_IS_UNION(type)) &&
15320 	(WXS_IS_RESTRICTION(type) == 0) &&
15321 	((! WXS_IS_ANY_SIMPLE_TYPE(baseType)) &&
15322          (baseType->type != XML_SCHEMA_TYPE_SIMPLE))) {
15323 	xmlSchemaPCustomErr(ctxt,
15324 	    XML_SCHEMAP_ST_PROPS_CORRECT_1,
15325 	    WXS_BASIC_CAST type, NULL,
15326 	    "A type, derived by list or union, must have "
15327 	    "the simple ur-type definition as base type, not '%s'",
15328 	    xmlSchemaGetComponentQName(&str, baseType));
15329 	FREE_AND_NULL(str)
15330 	return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15331     }
15332     /*
15333     * Variety: One of {atomic, list, union}.
15334     */
15335     if ((! WXS_IS_ATOMIC(type)) && (! WXS_IS_UNION(type)) &&
15336 	(! WXS_IS_LIST(type))) {
15337 	xmlSchemaPCustomErr(ctxt,
15338 	    XML_SCHEMAP_ST_PROPS_CORRECT_1,
15339 	    WXS_BASIC_CAST type, NULL,
15340 	    "The variety is absent", NULL);
15341 	return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15342     }
15343     /* TODO: Finish this. Hmm, is this finished? */
15344 
15345     /*
15346     * 3 The {final} of the {base type definition} must not contain restriction.
15347     */
15348     if (xmlSchemaTypeFinalContains(baseType,
15349 	XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15350 	xmlSchemaPCustomErr(ctxt,
15351 	    XML_SCHEMAP_ST_PROPS_CORRECT_3,
15352 	    WXS_BASIC_CAST type, NULL,
15353 	    "The 'final' of its base type '%s' must not contain "
15354 	    "'restriction'",
15355 	    xmlSchemaGetComponentQName(&str, baseType));
15356 	FREE_AND_NULL(str)
15357 	return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
15358     }
15359 
15360     /*
15361     * 2 All simple type definitions must be derived ultimately from the `simple
15362     * ur-type definition` (so circular definitions are disallowed). That is, it
15363     * must be possible to reach a built-in primitive datatype or the `simple
15364     * ur-type definition` by repeatedly following the {base type definition}.
15365     *
15366     * NOTE: this is done in xmlSchemaCheckTypeDefCircular().
15367     */
15368     return (0);
15369 }
15370 
15371 /**
15372  * xmlSchemaCheckCOSSTRestricts:
15373  * @ctxt:  the schema parser context
15374  * @type:  the simple type definition
15375  *
15376  * Schema Component Constraint:
15377  * Derivation Valid (Restriction, Simple) (cos-st-restricts)
15378 
15379  * Checks if the given @type (simpleType) is derived validly by restriction.
15380  * STATUS:
15381  *
15382  * Returns -1 on internal errors, 0 if the type is validly derived,
15383  * a positive error code otherwise.
15384  */
15385 static int
xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)15386 xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt,
15387 			     xmlSchemaTypePtr type)
15388 {
15389     xmlChar *str = NULL;
15390 
15391     if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
15392 	PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15393 	    "given type is not a user-derived simpleType");
15394 	return (-1);
15395     }
15396 
15397     if (WXS_IS_ATOMIC(type)) {
15398 	xmlSchemaTypePtr primitive;
15399 	/*
15400 	* 1.1 The {base type definition} must be an atomic simple
15401 	* type definition or a built-in primitive datatype.
15402 	*/
15403 	if (! WXS_IS_ATOMIC(type->baseType)) {
15404 	    xmlSchemaPCustomErr(pctxt,
15405 		XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
15406 		WXS_BASIC_CAST type, NULL,
15407 		"The base type '%s' is not an atomic simple type",
15408 		xmlSchemaGetComponentQName(&str, type->baseType));
15409 	    FREE_AND_NULL(str)
15410 	    return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
15411 	}
15412 	/* 1.2 The {final} of the {base type definition} must not contain
15413 	* restriction.
15414 	*/
15415 	/* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
15416 	if (xmlSchemaTypeFinalContains(type->baseType,
15417 	    XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15418 	    xmlSchemaPCustomErr(pctxt,
15419 		XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
15420 		WXS_BASIC_CAST type, NULL,
15421 		"The final of its base type '%s' must not contain 'restriction'",
15422 		xmlSchemaGetComponentQName(&str, type->baseType));
15423 	    FREE_AND_NULL(str)
15424 	    return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
15425 	}
15426 
15427 	/*
15428 	* 1.3.1 DF must be an allowed constraining facet for the {primitive
15429 	* type definition}, as specified in the appropriate subsection of 3.2
15430 	* Primitive datatypes.
15431 	*/
15432 	if (type->facets != NULL) {
15433 	    xmlSchemaFacetPtr facet;
15434 	    int ok = 1;
15435 
15436 	    primitive = xmlSchemaGetPrimitiveType(type);
15437 	    if (primitive == NULL) {
15438 		PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15439 		    "failed to get primitive type");
15440 		return (-1);
15441 	    }
15442 	    facet = type->facets;
15443 	    do {
15444 		if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
15445 		    ok = 0;
15446 		    xmlSchemaPIllegalFacetAtomicErr(pctxt,
15447 			XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
15448 			type, primitive, facet);
15449 		}
15450 		facet = facet->next;
15451 	    } while (facet != NULL);
15452 	    if (ok == 0)
15453 		return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
15454 	}
15455 	/*
15456 	* SPEC (1.3.2) "If there is a facet of the same kind in the {facets}
15457 	* of the {base type definition} (call this BF),then the DF's {value}
15458 	* must be a valid restriction of BF's {value} as defined in
15459 	* [XML Schemas: Datatypes]."
15460 	*
15461 	* NOTE (1.3.2) Facet derivation constraints are currently handled in
15462 	* xmlSchemaDeriveAndValidateFacets()
15463 	*/
15464     } else if (WXS_IS_LIST(type)) {
15465 	xmlSchemaTypePtr itemType = NULL;
15466 
15467 	itemType = type->subtypes;
15468 	if ((itemType == NULL) || (! WXS_IS_SIMPLE(itemType))) {
15469 	    PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15470 		"failed to evaluate the item type");
15471 	    return (-1);
15472 	}
15473 	if (WXS_IS_TYPE_NOT_FIXED(itemType))
15474 	    xmlSchemaTypeFixup(itemType, ACTXT_CAST pctxt);
15475 	/*
15476 	* 2.1 The {item type definition} must have a {variety} of atomic or
15477 	* union (in which case all the {member type definitions}
15478 	* must be atomic).
15479 	*/
15480 	if ((! WXS_IS_ATOMIC(itemType)) &&
15481 	    (! WXS_IS_UNION(itemType))) {
15482 	    xmlSchemaPCustomErr(pctxt,
15483 		XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
15484 		WXS_BASIC_CAST type, NULL,
15485 		"The item type '%s' does not have a variety of atomic or union",
15486 		xmlSchemaGetComponentQName(&str, itemType));
15487 	    FREE_AND_NULL(str)
15488 	    return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
15489 	} else if (WXS_IS_UNION(itemType)) {
15490 	    xmlSchemaTypeLinkPtr member;
15491 
15492 	    member = itemType->memberTypes;
15493 	    while (member != NULL) {
15494 		if (! WXS_IS_ATOMIC(member->type)) {
15495 		    xmlSchemaPCustomErr(pctxt,
15496 			XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
15497 			WXS_BASIC_CAST type, NULL,
15498 			"The item type is a union type, but the "
15499 			"member type '%s' of this item type is not atomic",
15500 			xmlSchemaGetComponentQName(&str, member->type));
15501 		    FREE_AND_NULL(str)
15502 		    return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
15503 		}
15504 		member = member->next;
15505 	    }
15506 	}
15507 
15508 	if (WXS_IS_ANY_SIMPLE_TYPE(type->baseType)) {
15509 	    xmlSchemaFacetPtr facet;
15510 	    /*
15511 	    * This is the case if we have: <simpleType><list ..
15512 	    */
15513 	    /*
15514 	    * 2.3.1
15515 	    * 2.3.1.1 The {final} of the {item type definition} must not
15516 	    * contain list.
15517 	    */
15518 	    if (xmlSchemaTypeFinalContains(itemType,
15519 		XML_SCHEMAS_TYPE_FINAL_LIST)) {
15520 		xmlSchemaPCustomErr(pctxt,
15521 		    XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
15522 		    WXS_BASIC_CAST type, NULL,
15523 		    "The final of its item type '%s' must not contain 'list'",
15524 		    xmlSchemaGetComponentQName(&str, itemType));
15525 		FREE_AND_NULL(str)
15526 		return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
15527 	    }
15528 	    /*
15529 	    * 2.3.1.2 The {facets} must only contain the whiteSpace
15530 	    * facet component.
15531 	    * OPTIMIZE TODO: the S4S already disallows any facet
15532 	    * to be specified.
15533 	    */
15534 	    if (type->facets != NULL) {
15535 		facet = type->facets;
15536 		do {
15537 		    if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
15538 			xmlSchemaPIllegalFacetListUnionErr(pctxt,
15539 			    XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
15540 			    type, facet);
15541 			return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
15542 		    }
15543 		    facet = facet->next;
15544 		} while (facet != NULL);
15545 	    }
15546 	    /*
15547 	    * MAYBE TODO: (Hmm, not really) Datatypes states:
15548 	    * A `list` datatype can be `derived` from an `atomic` datatype
15549 	    * whose `lexical space` allows space (such as string or anyURI)or
15550 	    * a `union` datatype any of whose {member type definitions}'s
15551 	    * `lexical space` allows space.
15552 	    */
15553 	} else {
15554 	    /*
15555 	    * This is the case if we have: <simpleType><restriction ...
15556 	    * I.e. the variety of "list" is inherited.
15557 	    */
15558 	    /*
15559 	    * 2.3.2
15560 	    * 2.3.2.1 The {base type definition} must have a {variety} of list.
15561 	    */
15562 	    if (! WXS_IS_LIST(type->baseType)) {
15563 		xmlSchemaPCustomErr(pctxt,
15564 		    XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
15565 		    WXS_BASIC_CAST type, NULL,
15566 		    "The base type '%s' must be a list type",
15567 		    xmlSchemaGetComponentQName(&str, type->baseType));
15568 		FREE_AND_NULL(str)
15569 		return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
15570 	    }
15571 	    /*
15572 	    * 2.3.2.2 The {final} of the {base type definition} must not
15573 	    * contain restriction.
15574 	    */
15575 	    if (xmlSchemaTypeFinalContains(type->baseType,
15576 		XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15577 		xmlSchemaPCustomErr(pctxt,
15578 		    XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
15579 		    WXS_BASIC_CAST type, NULL,
15580 		    "The 'final' of the base type '%s' must not contain 'restriction'",
15581 		    xmlSchemaGetComponentQName(&str, type->baseType));
15582 		FREE_AND_NULL(str)
15583 		return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
15584 	    }
15585 	    /*
15586 	    * 2.3.2.3 The {item type definition} must be validly derived
15587 	    * from the {base type definition}'s {item type definition} given
15588 	    * the empty set, as defined in Type Derivation OK (Simple) ($3.14.6).
15589 	    */
15590 	    {
15591 		xmlSchemaTypePtr baseItemType;
15592 
15593 		baseItemType = type->baseType->subtypes;
15594 		if ((baseItemType == NULL) || (! WXS_IS_SIMPLE(baseItemType))) {
15595 		    PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15596 			"failed to eval the item type of a base type");
15597 		    return (-1);
15598 		}
15599 		if ((itemType != baseItemType) &&
15600 		    (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt, itemType,
15601 			baseItemType, 0) != 0)) {
15602 		    xmlChar *strBIT = NULL, *strBT = NULL;
15603 		    xmlSchemaPCustomErrExt(pctxt,
15604 			XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
15605 			WXS_BASIC_CAST type, NULL,
15606 			"The item type '%s' is not validly derived from "
15607 			"the item type '%s' of the base type '%s'",
15608 			xmlSchemaGetComponentQName(&str, itemType),
15609 			xmlSchemaGetComponentQName(&strBIT, baseItemType),
15610 			xmlSchemaGetComponentQName(&strBT, type->baseType));
15611 
15612 		    FREE_AND_NULL(str)
15613 		    FREE_AND_NULL(strBIT)
15614 		    FREE_AND_NULL(strBT)
15615 		    return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
15616 		}
15617 	    }
15618 
15619 	    if (type->facets != NULL) {
15620 		xmlSchemaFacetPtr facet;
15621 		int ok = 1;
15622 		/*
15623 		* 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
15624 		* and enumeration facet components are allowed among the {facets}.
15625 		*/
15626 		facet = type->facets;
15627 		do {
15628 		    switch (facet->type) {
15629 			case XML_SCHEMA_FACET_LENGTH:
15630 			case XML_SCHEMA_FACET_MINLENGTH:
15631 			case XML_SCHEMA_FACET_MAXLENGTH:
15632 			case XML_SCHEMA_FACET_WHITESPACE:
15633 			    /*
15634 			    * TODO: 2.5.1.2 List datatypes
15635 			    * The value of `whiteSpace` is fixed to the value collapse.
15636 			    */
15637 			case XML_SCHEMA_FACET_PATTERN:
15638 			case XML_SCHEMA_FACET_ENUMERATION:
15639 			    break;
15640 			default: {
15641 			    xmlSchemaPIllegalFacetListUnionErr(pctxt,
15642 				XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
15643 				type, facet);
15644 			    /*
15645 			    * We could return, but it's nicer to report all
15646 			    * invalid facets.
15647 			    */
15648 			    ok = 0;
15649 			}
15650 		    }
15651 		    facet = facet->next;
15652 		} while (facet != NULL);
15653 		if (ok == 0)
15654 		    return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
15655 		/*
15656 		* SPEC (2.3.2.5) (same as 1.3.2)
15657 		*
15658 		* NOTE (2.3.2.5) This is currently done in
15659 		* xmlSchemaDeriveAndValidateFacets()
15660 		*/
15661 	    }
15662 	}
15663     } else if (WXS_IS_UNION(type)) {
15664 	/*
15665 	* 3.1 The {member type definitions} must all have {variety} of
15666 	* atomic or list.
15667 	*/
15668 	xmlSchemaTypeLinkPtr member;
15669 
15670 	member = type->memberTypes;
15671 	while (member != NULL) {
15672 	    if (WXS_IS_TYPE_NOT_FIXED(member->type))
15673 		xmlSchemaTypeFixup(member->type, ACTXT_CAST pctxt);
15674 
15675 	    if ((! WXS_IS_ATOMIC(member->type)) &&
15676 		(! WXS_IS_LIST(member->type))) {
15677 		xmlSchemaPCustomErr(pctxt,
15678 		    XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
15679 		    WXS_BASIC_CAST type, NULL,
15680 		    "The member type '%s' is neither an atomic, nor a list type",
15681 		    xmlSchemaGetComponentQName(&str, member->type));
15682 		FREE_AND_NULL(str)
15683 		return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
15684 	    }
15685 	    member = member->next;
15686 	}
15687 	/*
15688 	* 3.3.1 If the {base type definition} is the `simple ur-type
15689 	* definition`
15690 	*/
15691 	if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) {
15692 	    /*
15693 	    * 3.3.1.1 All of the {member type definitions} must have a
15694 	    * {final} which does not contain union.
15695 	    */
15696 	    member = type->memberTypes;
15697 	    while (member != NULL) {
15698 		if (xmlSchemaTypeFinalContains(member->type,
15699 		    XML_SCHEMAS_TYPE_FINAL_UNION)) {
15700 		    xmlSchemaPCustomErr(pctxt,
15701 			XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
15702 			WXS_BASIC_CAST type, NULL,
15703 			"The 'final' of member type '%s' contains 'union'",
15704 			xmlSchemaGetComponentQName(&str, member->type));
15705 		    FREE_AND_NULL(str)
15706 		    return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
15707 		}
15708 		member = member->next;
15709 	    }
15710 	    /*
15711 	    * 3.3.1.2 The {facets} must be empty.
15712 	    */
15713 	    if (type->facetSet != NULL) {
15714 		xmlSchemaPCustomErr(pctxt,
15715 		    XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
15716 		    WXS_BASIC_CAST type, NULL,
15717 		    "No facets allowed", NULL);
15718 		return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
15719 	    }
15720 	} else {
15721 	    /*
15722 	    * 3.3.2.1 The {base type definition} must have a {variety} of union.
15723 	    * I.e. the variety of "list" is inherited.
15724 	    */
15725 	    if (! WXS_IS_UNION(type->baseType)) {
15726 		xmlSchemaPCustomErr(pctxt,
15727 		    XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
15728 		    WXS_BASIC_CAST type, NULL,
15729 		    "The base type '%s' is not a union type",
15730 		    xmlSchemaGetComponentQName(&str, type->baseType));
15731 		FREE_AND_NULL(str)
15732 		return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
15733 	    }
15734 	    /*
15735 	    * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
15736 	    */
15737 	    if (xmlSchemaTypeFinalContains(type->baseType,
15738 		XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15739 		xmlSchemaPCustomErr(pctxt,
15740 		    XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
15741 		    WXS_BASIC_CAST type, NULL,
15742 		    "The 'final' of its base type '%s' must not contain 'restriction'",
15743 		    xmlSchemaGetComponentQName(&str, type->baseType));
15744 		FREE_AND_NULL(str)
15745 		return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
15746 	    }
15747 	    /*
15748 	    * 3.3.2.3 The {member type definitions}, in order, must be validly
15749 	    * derived from the corresponding type definitions in the {base
15750 	    * type definition}'s {member type definitions} given the empty set,
15751 	    * as defined in Type Derivation OK (Simple) ($3.14.6).
15752 	    */
15753 	    {
15754 		xmlSchemaTypeLinkPtr baseMember;
15755 
15756 		/*
15757 		* OPTIMIZE: if the type is restricting, it has no local defined
15758 		* member types and inherits the member types of the base type;
15759 		* thus a check for equality can be skipped.
15760 		*/
15761 		/*
15762 		* Even worse: I cannot see a scenario where a restricting
15763 		* union simple type can have other member types as the member
15764 		* types of it's base type. This check seems not necessary with
15765 		* respect to the derivation process in libxml2.
15766 		* But necessary if constructing types with an API.
15767 		*/
15768 		if (type->memberTypes != NULL) {
15769 		    member = type->memberTypes;
15770 		    baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
15771 		    if ((member == NULL) && (baseMember != NULL)) {
15772 			PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15773 			    "different number of member types in base");
15774 		    }
15775 		    while (member != NULL) {
15776 			if (baseMember == NULL) {
15777 			    PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15778 			    "different number of member types in base");
15779 			} else if ((member->type != baseMember->type) &&
15780 			    (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
15781 				member->type, baseMember->type, 0) != 0)) {
15782 			    xmlChar *strBMT = NULL, *strBT = NULL;
15783 
15784 			    xmlSchemaPCustomErrExt(pctxt,
15785 				XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
15786 				WXS_BASIC_CAST type, NULL,
15787 				"The member type %s is not validly "
15788 				"derived from its corresponding member "
15789 				"type %s of the base type %s",
15790 				xmlSchemaGetComponentQName(&str, member->type),
15791 				xmlSchemaGetComponentQName(&strBMT, baseMember->type),
15792 				xmlSchemaGetComponentQName(&strBT, type->baseType));
15793 			    FREE_AND_NULL(str)
15794 			    FREE_AND_NULL(strBMT)
15795 			    FREE_AND_NULL(strBT)
15796 			    return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
15797 			}
15798 			member = member->next;
15799                         if (baseMember != NULL)
15800                             baseMember = baseMember->next;
15801 		    }
15802 		}
15803 	    }
15804 	    /*
15805 	    * 3.3.2.4 Only pattern and enumeration facet components are
15806 	    * allowed among the {facets}.
15807 	    */
15808 	    if (type->facets != NULL) {
15809 		xmlSchemaFacetPtr facet;
15810 		int ok = 1;
15811 
15812 		facet = type->facets;
15813 		do {
15814 		    if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
15815 			(facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
15816 			xmlSchemaPIllegalFacetListUnionErr(pctxt,
15817 				XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
15818 				type, facet);
15819 			ok = 0;
15820 		    }
15821 		    facet = facet->next;
15822 		} while (facet != NULL);
15823 		if (ok == 0)
15824 		    return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
15825 
15826 	    }
15827 	    /*
15828 	    * SPEC (3.3.2.5) (same as 1.3.2)
15829 	    *
15830 	    * NOTE (3.3.2.5) This is currently done in
15831 	    * xmlSchemaDeriveAndValidateFacets()
15832 	    */
15833 	}
15834     }
15835 
15836     return (0);
15837 }
15838 
15839 /**
15840  * xmlSchemaCheckSRCSimpleType:
15841  * @ctxt:  the schema parser context
15842  * @type:  the simple type definition
15843  *
15844  * Checks crc-simple-type constraints.
15845  *
15846  * Returns 0 if the constraints are satisfied,
15847  * if not a positive error code and -1 on internal
15848  * errors.
15849  */
15850 #if 0
15851 static int
15852 xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
15853 			    xmlSchemaTypePtr type)
15854 {
15855     /*
15856     * src-simple-type.1 The corresponding simple type definition, if any,
15857     * must satisfy the conditions set out in Constraints on Simple Type
15858     * Definition Schema Components ($3.14.6).
15859     */
15860     if (WXS_IS_RESTRICTION(type)) {
15861 	/*
15862 	* src-simple-type.2 "If the <restriction> alternative is chosen,
15863 	* either it must have a base [attribute] or a <simpleType> among its
15864 	* [children], but not both."
15865 	* NOTE: This is checked in the parse function of <restriction>.
15866 	*/
15867 	/*
15868 	*
15869 	*/
15870     } else if (WXS_IS_LIST(type)) {
15871 	/* src-simple-type.3 "If the <list> alternative is chosen, either it must have
15872 	* an itemType [attribute] or a <simpleType> among its [children],
15873 	* but not both."
15874 	*
15875 	* NOTE: This is checked in the parse function of <list>.
15876 	*/
15877     } else if (WXS_IS_UNION(type)) {
15878 	/*
15879 	* src-simple-type.4 is checked in xmlSchemaCheckUnionTypeDefCircular().
15880 	*/
15881     }
15882     return (0);
15883 }
15884 #endif
15885 
15886 static int
xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)15887 xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
15888 {
15889    if (ctxt->vctxt == NULL) {
15890 	ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
15891 	if (ctxt->vctxt == NULL) {
15892 	    xmlSchemaPErr(ctxt, NULL,
15893 		XML_SCHEMAP_INTERNAL,
15894 		"Internal error: xmlSchemaCreateVCtxtOnPCtxt, "
15895 		"failed to create a temp. validation context.\n",
15896 		NULL, NULL);
15897 	    return (-1);
15898 	}
15899 	/* TODO: Pass user data. */
15900 	xmlSchemaSetValidErrors(ctxt->vctxt,
15901 	    ctxt->error, ctxt->warning, ctxt->errCtxt);
15902 	xmlSchemaSetValidStructuredErrors(ctxt->vctxt,
15903 	    ctxt->serror, ctxt->errCtxt);
15904     }
15905     return (0);
15906 }
15907 
15908 static int
15909 xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
15910 			     xmlNodePtr node,
15911 			     xmlSchemaTypePtr type,
15912 			     const xmlChar *value,
15913 			     xmlSchemaValPtr *retVal,
15914 			     int fireErrors,
15915 			     int normalize,
15916 			     int isNormalized);
15917 
15918 /**
15919  * xmlSchemaParseCheckCOSValidDefault:
15920  * @pctxt:  the schema parser context
15921  * @type:  the simple type definition
15922  * @value: the default value
15923  * @node: an optional node (the holder of the value)
15924  *
15925  * Schema Component Constraint: Element Default Valid (Immediate)
15926  * (cos-valid-default)
15927  * This will be used by the parser only. For the validator there's
15928  * an other version.
15929  *
15930  * Returns 0 if the constraints are satisfied,
15931  * if not, a positive error code and -1 on internal
15932  * errors.
15933  */
15934 static int
xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,xmlNodePtr node,xmlSchemaTypePtr type,const xmlChar * value,xmlSchemaValPtr * val)15935 xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
15936 				   xmlNodePtr node,
15937 				   xmlSchemaTypePtr type,
15938 				   const xmlChar *value,
15939 				   xmlSchemaValPtr *val)
15940 {
15941     int ret = 0;
15942 
15943     /*
15944     * cos-valid-default:
15945     * Schema Component Constraint: Element Default Valid (Immediate)
15946     * For a string to be a valid default with respect to a type
15947     * definition the appropriate case among the following must be true:
15948     */
15949     if WXS_IS_COMPLEX(type) {
15950 	/*
15951 	* Complex type.
15952 	*
15953 	* SPEC (2.1) "its {content type} must be a simple type definition
15954 	* or mixed."
15955 	* SPEC (2.2.2) "If the {content type} is mixed, then the {content
15956 	* type}'s particle must be `emptiable` as defined by
15957 	* Particle Emptiable ($3.9.6)."
15958 	*/
15959 	if ((! WXS_HAS_SIMPLE_CONTENT(type)) &&
15960 	    ((! WXS_HAS_MIXED_CONTENT(type)) || (! WXS_EMPTIABLE(type)))) {
15961 	    /* NOTE that this covers (2.2.2) as well. */
15962 	    xmlSchemaPCustomErr(pctxt,
15963 		XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
15964 		WXS_BASIC_CAST type, type->node,
15965 		"For a string to be a valid default, the type definition "
15966 		"must be a simple type or a complex type with mixed content "
15967 		"and a particle emptiable", NULL);
15968 	    return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
15969 	}
15970     }
15971     /*
15972     * 1 If the type definition is a simple type definition, then the string
15973     * must be `valid` with respect to that definition as defined by String
15974     * Valid ($3.14.4).
15975     *
15976     * AND
15977     *
15978     * 2.2.1 If the {content type} is a simple type definition, then the
15979     * string must be `valid` with respect to that simple type definition
15980     * as defined by String Valid ($3.14.4).
15981     */
15982     if (WXS_IS_SIMPLE(type))
15983 	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
15984 	    type, value, val, 1, 1, 0);
15985     else if (WXS_HAS_SIMPLE_CONTENT(type))
15986 	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
15987 	    type->contentTypeDef, value, val, 1, 1, 0);
15988     else
15989 	return (ret);
15990 
15991     if (ret < 0) {
15992 	PERROR_INT("xmlSchemaParseCheckCOSValidDefault",
15993 	    "calling xmlSchemaVCheckCVCSimpleType()");
15994     }
15995 
15996     return (ret);
15997 }
15998 
15999 /**
16000  * xmlSchemaCheckCTPropsCorrect:
16001  * @ctxt:  the schema parser context
16002  * @type:  the complex type definition
16003  *
16004  *.(4.6) Constraints on Complex Type Definition Schema Components
16005  * Schema Component Constraint:
16006  * Complex Type Definition Properties Correct (ct-props-correct)
16007  * STATUS: (seems) complete
16008  *
16009  * Returns 0 if the constraints are satisfied, a positive
16010  * error code if not and -1 if an internal error occurred.
16011  */
16012 static int
xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)16013 xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
16014 			     xmlSchemaTypePtr type)
16015 {
16016     /*
16017     * TODO: Correct the error code; XML_SCHEMAP_SRC_CT_1 is used temporarily.
16018     *
16019     * SPEC (1) "The values of the properties of a complex type definition must
16020     * be as described in the property tableau in The Complex Type Definition
16021     * Schema Component ($3.4.1), modulo the impact of Missing
16022     * Sub-components ($5.3)."
16023     */
16024     if ((type->baseType != NULL) &&
16025 	(WXS_IS_SIMPLE(type->baseType)) &&
16026 	(WXS_IS_EXTENSION(type) == 0)) {
16027 	/*
16028 	* SPEC (2) "If the {base type definition} is a simple type definition,
16029 	* the {derivation method} must be extension."
16030 	*/
16031 	xmlSchemaCustomErr(ACTXT_CAST pctxt,
16032 	    XML_SCHEMAP_SRC_CT_1,
16033 	    NULL, WXS_BASIC_CAST type,
16034 	    "If the base type is a simple type, the derivation method must be "
16035 	    "'extension'", NULL, NULL);
16036 	return (XML_SCHEMAP_SRC_CT_1);
16037     }
16038     /*
16039     * SPEC (3) "Circular definitions are disallowed, except for the `ur-type
16040     * definition`. That is, it must be possible to reach the `ur-type
16041     * definition` by repeatedly following the {base type definition}."
16042     *
16043     * NOTE (3) is done in xmlSchemaCheckTypeDefCircular().
16044     */
16045     /*
16046     * NOTE that (4) and (5) need the following:
16047     *   - attribute uses need to be already inherited (apply attr. prohibitions)
16048     *   - attribute group references need to be expanded already
16049     *   - simple types need to be typefixed already
16050     */
16051     if (type->attrUses &&
16052 	(((xmlSchemaItemListPtr) type->attrUses)->nbItems > 1))
16053     {
16054 	xmlSchemaItemListPtr uses = (xmlSchemaItemListPtr) type->attrUses;
16055 	xmlSchemaAttributeUsePtr use, tmp;
16056 	int i, j, hasId = 0;
16057 
16058 	for (i = uses->nbItems -1; i >= 0; i--) {
16059 	    use = uses->items[i];
16060 
16061 	    /*
16062 	    * SPEC ct-props-correct
16063 	    * (4) "Two distinct attribute declarations in the
16064 	    * {attribute uses} must not have identical {name}s and
16065 	    * {target namespace}s."
16066 	    */
16067 	    if (i > 0) {
16068 		for (j = i -1; j >= 0; j--) {
16069 		    tmp = uses->items[j];
16070 		    if ((WXS_ATTRUSE_DECL_NAME(use) ==
16071 			WXS_ATTRUSE_DECL_NAME(tmp)) &&
16072 			(WXS_ATTRUSE_DECL_TNS(use) ==
16073 			WXS_ATTRUSE_DECL_TNS(tmp)))
16074 		    {
16075 			xmlChar *str = NULL;
16076 
16077 			xmlSchemaCustomErr(ACTXT_CAST pctxt,
16078 			    XML_SCHEMAP_AG_PROPS_CORRECT,
16079 			    NULL, WXS_BASIC_CAST type,
16080 			    "Duplicate %s",
16081 			    xmlSchemaGetComponentDesignation(&str, use),
16082 			    NULL);
16083 			FREE_AND_NULL(str);
16084 			/*
16085 			* Remove the duplicate.
16086 			*/
16087 			if (xmlSchemaItemListRemove(uses, i) == -1)
16088 			    goto exit_failure;
16089 			goto next_use;
16090 		    }
16091 		}
16092 	    }
16093 	    /*
16094 	    * SPEC ct-props-correct
16095 	    * (5) "Two distinct attribute declarations in the
16096 	    * {attribute uses} must not have {type definition}s which
16097 	    * are or are derived from ID."
16098 	    */
16099 	    if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
16100 		if (xmlSchemaIsDerivedFromBuiltInType(
16101 		    WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
16102 		{
16103 		    if (hasId) {
16104 			xmlChar *str = NULL;
16105 
16106 			xmlSchemaCustomErr(ACTXT_CAST pctxt,
16107 			    XML_SCHEMAP_AG_PROPS_CORRECT,
16108 			    NULL, WXS_BASIC_CAST type,
16109 			    "There must not exist more than one attribute "
16110 			    "declaration of type 'xs:ID' "
16111 			    "(or derived from 'xs:ID'). The %s violates this "
16112 			    "constraint",
16113 			    xmlSchemaGetComponentDesignation(&str, use),
16114 			    NULL);
16115 			FREE_AND_NULL(str);
16116 			if (xmlSchemaItemListRemove(uses, i) == -1)
16117 			    goto exit_failure;
16118 		    }
16119 
16120 		    hasId = 1;
16121 		}
16122 	    }
16123 next_use: {}
16124 	}
16125     }
16126     return (0);
16127 exit_failure:
16128     return(-1);
16129 }
16130 
16131 static int
xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,xmlSchemaTypePtr typeB)16132 xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,
16133 		       xmlSchemaTypePtr typeB)
16134 {
16135     /*
16136     * TODO: This should implement component-identity
16137     * in the future.
16138     */
16139     if ((typeA == NULL) || (typeB == NULL))
16140 	return (0);
16141     return (typeA == typeB);
16142 }
16143 
16144 /**
16145  * xmlSchemaCheckCOSCTDerivedOK:
16146  * @ctxt:  the schema parser context
16147  * @type:  the to-be derived complex type definition
16148  * @baseType:  the base complex type definition
16149  * @set: the given set
16150  *
16151  * Schema Component Constraint:
16152  * Type Derivation OK (Complex) (cos-ct-derived-ok)
16153  *
16154  * STATUS: completed
16155  *
16156  * Returns 0 if the constraints are satisfied, or 1
16157  * if not.
16158  */
16159 static int
xmlSchemaCheckCOSCTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,xmlSchemaTypePtr type,xmlSchemaTypePtr baseType,int set)16160 xmlSchemaCheckCOSCTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
16161 			     xmlSchemaTypePtr type,
16162 			     xmlSchemaTypePtr baseType,
16163 			     int set)
16164 {
16165     int equal = xmlSchemaAreEqualTypes(type, baseType);
16166     /* TODO: Error codes. */
16167     /*
16168     * SPEC "For a complex type definition (call it D, for derived)
16169     * to be validly derived from a type definition (call this
16170     * B, for base) given a subset of {extension, restriction}
16171     * all of the following must be true:"
16172     */
16173     if (! equal) {
16174 	/*
16175 	* SPEC (1) "If B and D are not the same type definition, then the
16176 	* {derivation method} of D must not be in the subset."
16177 	*/
16178 	if (((set & SUBSET_EXTENSION) && (WXS_IS_EXTENSION(type))) ||
16179 	    ((set & SUBSET_RESTRICTION) && (WXS_IS_RESTRICTION(type))))
16180 	    return (1);
16181     } else {
16182 	/*
16183 	* SPEC (2.1) "B and D must be the same type definition."
16184 	*/
16185 	return (0);
16186     }
16187     /*
16188     * SPEC (2.2) "B must be D's {base type definition}."
16189     */
16190     if (type->baseType == baseType)
16191 	return (0);
16192     /*
16193     * SPEC (2.3.1) "D's {base type definition} must not be the `ur-type
16194     * definition`."
16195     */
16196     if (WXS_IS_ANYTYPE(type->baseType))
16197 	return (1);
16198 
16199     if (WXS_IS_COMPLEX(type->baseType)) {
16200 	/*
16201 	* SPEC (2.3.2.1) "If D's {base type definition} is complex, then it
16202 	* must be validly derived from B given the subset as defined by this
16203 	* constraint."
16204 	*/
16205 	return (xmlSchemaCheckCOSCTDerivedOK(actxt, type->baseType,
16206 	    baseType, set));
16207     } else {
16208 	/*
16209 	* SPEC (2.3.2.2) "If D's {base type definition} is simple, then it
16210 	* must be validly derived from B given the subset as defined in Type
16211 	* Derivation OK (Simple) ($3.14.6).
16212 	*/
16213 	return (xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
16214 	    baseType, set));
16215     }
16216 }
16217 
16218 /**
16219  * xmlSchemaCheckCOSDerivedOK:
16220  * @type:  the derived simple type definition
16221  * @baseType:  the base type definition
16222  *
16223  * Calls:
16224  * Type Derivation OK (Simple) AND Type Derivation OK (Complex)
16225  *
16226  * Checks whether @type can be validly derived from @baseType.
16227  *
16228  * Returns 0 on success, an positive error code otherwise.
16229  */
16230 static int
xmlSchemaCheckCOSDerivedOK(xmlSchemaAbstractCtxtPtr actxt,xmlSchemaTypePtr type,xmlSchemaTypePtr baseType,int set)16231 xmlSchemaCheckCOSDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
16232 			   xmlSchemaTypePtr type,
16233 			   xmlSchemaTypePtr baseType,
16234 			   int set)
16235 {
16236     if (WXS_IS_SIMPLE(type))
16237 	return (xmlSchemaCheckCOSSTDerivedOK(actxt, type, baseType, set));
16238     else
16239 	return (xmlSchemaCheckCOSCTDerivedOK(actxt, type, baseType, set));
16240 }
16241 
16242 /**
16243  * xmlSchemaCheckCOSCTExtends:
16244  * @ctxt:  the schema parser context
16245  * @type:  the complex type definition
16246  *
16247  * (3.4.6) Constraints on Complex Type Definition Schema Components
16248  * Schema Component Constraint:
16249  * Derivation Valid (Extension) (cos-ct-extends)
16250  *
16251  * STATUS:
16252  *   missing:
16253  *     (1.5)
16254  *     (1.4.3.2.2.2) "Particle Valid (Extension)"
16255  *
16256  * Returns 0 if the constraints are satisfied, a positive
16257  * error code if not and -1 if an internal error occurred.
16258  */
16259 static int
xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,xmlSchemaTypePtr type)16260 xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
16261 			   xmlSchemaTypePtr type)
16262 {
16263     xmlSchemaTypePtr base = type->baseType;
16264     /*
16265     * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
16266     * temporarily only.
16267     */
16268     /*
16269     * SPEC (1) "If the {base type definition} is a complex type definition,
16270     * then all of the following must be true:"
16271     */
16272     if (WXS_IS_COMPLEX(base)) {
16273 	/*
16274 	* SPEC (1.1) "The {final} of the {base type definition} must not
16275 	* contain extension."
16276 	*/
16277 	if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16278 	    xmlSchemaPCustomErr(ctxt,
16279 		XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16280 		WXS_BASIC_CAST type, NULL,
16281 		"The 'final' of the base type definition "
16282 		"contains 'extension'", NULL);
16283 	    return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16284 	}
16285 
16286 	/*
16287 	* ATTENTION: The constrains (1.2) and (1.3) are not applied,
16288 	* since they are automatically satisfied through the
16289 	* inheriting mechanism.
16290 	* Note that even if redefining components, the inheriting mechanism
16291 	* is used.
16292 	*/
16293 #if 0
16294 	/*
16295 	* SPEC (1.2) "Its {attribute uses} must be a subset of the {attribute
16296 	* uses}
16297 	* of the complex type definition itself, that is, for every attribute
16298 	* use in the {attribute uses} of the {base type definition}, there
16299 	* must be an attribute use in the {attribute uses} of the complex
16300 	* type definition itself whose {attribute declaration} has the same
16301 	* {name}, {target namespace} and {type definition} as its attribute
16302 	* declaration"
16303 	*/
16304 	if (base->attrUses != NULL) {
16305 	    int i, j, found;
16306 	    xmlSchemaAttributeUsePtr use, buse;
16307 
16308 	    for (i = 0; i < (WXS_LIST_CAST base->attrUses)->nbItems; i ++) {
16309 		buse = (WXS_LIST_CAST base->attrUses)->items[i];
16310 		found = 0;
16311 		if (type->attrUses != NULL) {
16312 		    use = (WXS_LIST_CAST type->attrUses)->items[j];
16313 		    for (j = 0; j < (WXS_LIST_CAST type->attrUses)->nbItems; j ++)
16314 		    {
16315 			if ((WXS_ATTRUSE_DECL_NAME(use) ==
16316 				WXS_ATTRUSE_DECL_NAME(buse)) &&
16317 			    (WXS_ATTRUSE_DECL_TNS(use) ==
16318 				WXS_ATTRUSE_DECL_TNS(buse)) &&
16319 			    (WXS_ATTRUSE_TYPEDEF(use) ==
16320 				WXS_ATTRUSE_TYPEDEF(buse))
16321 			{
16322 			    found = 1;
16323 			    break;
16324 			}
16325 		    }
16326 		}
16327 		if (! found) {
16328 		    xmlChar *str = NULL;
16329 
16330 		    xmlSchemaCustomErr(ACTXT_CAST ctxt,
16331 			XML_SCHEMAP_COS_CT_EXTENDS_1_2,
16332 			NULL, WXS_BASIC_CAST type,
16333 			/*
16334 			* TODO: The report does not indicate that also the
16335 			* type needs to be the same.
16336 			*/
16337 			"This type is missing a matching correspondent "
16338 			"for its {base type}'s %s in its {attribute uses}",
16339 			xmlSchemaGetComponentDesignation(&str,
16340 			    buse->children),
16341 			NULL);
16342 		    FREE_AND_NULL(str)
16343 		}
16344 	    }
16345 	}
16346 	/*
16347 	* SPEC (1.3) "If it has an {attribute wildcard}, the complex type
16348 	* definition must also have one, and the base type definition's
16349 	* {attribute  wildcard}'s {namespace constraint} must be a subset
16350 	* of the complex  type definition's {attribute wildcard}'s {namespace
16351 	* constraint}, as defined by Wildcard Subset ($3.10.6)."
16352 	*/
16353 
16354 	/*
16355 	* MAYBE TODO: Enable if ever needed. But this will be needed only
16356 	* if created the type via a schema construction API.
16357 	*/
16358 	if (base->attributeWildcard != NULL) {
16359 	    if (type->attributeWildcard == NULL) {
16360 		xmlChar *str = NULL;
16361 
16362 		xmlSchemaCustomErr(ACTXT_CAST pctxt,
16363 		    XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16364 		    NULL, type,
16365 		    "The base %s has an attribute wildcard, "
16366 		    "but this type is missing an attribute wildcard",
16367 		    xmlSchemaGetComponentDesignation(&str, base));
16368 		FREE_AND_NULL(str)
16369 
16370 	    } else if (xmlSchemaCheckCOSNSSubset(
16371 		base->attributeWildcard, type->attributeWildcard))
16372 	    {
16373 		xmlChar *str = NULL;
16374 
16375 		xmlSchemaCustomErr(ACTXT_CAST pctxt,
16376 		    XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16377 		    NULL, type,
16378 		    "The attribute wildcard is not a valid "
16379 		    "superset of the one in the base %s",
16380 		    xmlSchemaGetComponentDesignation(&str, base));
16381 		FREE_AND_NULL(str)
16382 	    }
16383 	}
16384 #endif
16385 	/*
16386 	* SPEC (1.4) "One of the following must be true:"
16387 	*/
16388 	if ((type->contentTypeDef != NULL) &&
16389 	    (type->contentTypeDef == base->contentTypeDef)) {
16390 	    /*
16391 	    * SPEC (1.4.1) "The {content type} of the {base type definition}
16392 	    * and the {content type} of the complex type definition itself
16393 	    * must be the same simple type definition"
16394 	    * PASS
16395 	    */
16396 	} else if ((type->contentType == XML_SCHEMA_CONTENT_EMPTY) &&
16397 	    (base->contentType == XML_SCHEMA_CONTENT_EMPTY) ) {
16398 	    /*
16399 	    * SPEC (1.4.2) "The {content type} of both the {base type
16400 	    * definition} and the complex type definition itself must
16401 	    * be empty."
16402 	    * PASS
16403 	    */
16404 	} else {
16405 	    /*
16406 	    * SPEC (1.4.3) "All of the following must be true:"
16407 	    */
16408 	    if (type->subtypes == NULL) {
16409 		/*
16410 		* SPEC 1.4.3.1 The {content type} of the complex type
16411 		* definition itself must specify a particle.
16412 		*/
16413 		xmlSchemaPCustomErr(ctxt,
16414 		    XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16415 		    WXS_BASIC_CAST type, NULL,
16416 		    "The content type must specify a particle", NULL);
16417 		return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16418 	    }
16419 	    /*
16420 	    * SPEC (1.4.3.2) "One of the following must be true:"
16421 	    */
16422 	    if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16423 		/*
16424 		* SPEC (1.4.3.2.1) "The {content type} of the {base type
16425 		* definition} must be empty.
16426 		* PASS
16427 		*/
16428 	    } else {
16429 		/*
16430 		* SPEC (1.4.3.2.2) "All of the following must be true:"
16431 		*/
16432 		if ((type->contentType != base->contentType) ||
16433 		    ((type->contentType != XML_SCHEMA_CONTENT_MIXED) &&
16434 		    (type->contentType != XML_SCHEMA_CONTENT_ELEMENTS))) {
16435 		    /*
16436 		    * SPEC (1.4.3.2.2.1) "Both {content type}s must be mixed
16437 		    * or both must be element-only."
16438 		    */
16439 		    xmlSchemaPCustomErr(ctxt,
16440 			XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16441 			WXS_BASIC_CAST type, NULL,
16442 			"The content type of both, the type and its base "
16443 			"type, must either 'mixed' or 'element-only'", NULL);
16444 		    return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16445 		}
16446 		/*
16447 		* URGENT TODO SPEC (1.4.3.2.2.2) "The particle of the
16448 		* complex type definition must be a `valid extension`
16449 		* of the {base type definition}'s particle, as defined
16450 		* in Particle Valid (Extension) ($3.9.6)."
16451 		*
16452 		* NOTE that we won't check "Particle Valid (Extension)",
16453 		* since it is ensured by the derivation process in
16454 		* xmlSchemaTypeFixup(). We need to implement this when heading
16455 		* for a construction API
16456 		* TODO: !! This is needed to be checked if redefining a type !!
16457 		*/
16458 	    }
16459 	    /*
16460 	    * URGENT TODO (1.5)
16461 	    */
16462 	}
16463     } else {
16464 	/*
16465 	* SPEC (2) "If the {base type definition} is a simple type definition,
16466 	* then all of the following must be true:"
16467 	*/
16468 	if (type->contentTypeDef != base) {
16469 	    /*
16470 	    * SPEC (2.1) "The {content type} must be the same simple type
16471 	    * definition."
16472 	    */
16473 	    xmlSchemaPCustomErr(ctxt,
16474 		XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16475 		WXS_BASIC_CAST type, NULL,
16476 		"The content type must be the simple base type", NULL);
16477 	    return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16478 	}
16479 	if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16480 	    /*
16481 	    * SPEC (2.2) "The {final} of the {base type definition} must not
16482 	    * contain extension"
16483 	    * NOTE that this is the same as (1.1).
16484 	    */
16485 	    xmlSchemaPCustomErr(ctxt,
16486 		XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16487 		WXS_BASIC_CAST type, NULL,
16488 		"The 'final' of the base type definition "
16489 		"contains 'extension'", NULL);
16490 	    return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16491 	}
16492     }
16493     return (0);
16494 }
16495 
16496 /**
16497  * xmlSchemaCheckDerivationOKRestriction:
16498  * @ctxt:  the schema parser context
16499  * @type:  the complex type definition
16500  *
16501  * (3.4.6) Constraints on Complex Type Definition Schema Components
16502  * Schema Component Constraint:
16503  * Derivation Valid (Restriction, Complex) (derivation-ok-restriction)
16504  *
16505  * STATUS:
16506  *   missing:
16507  *     (5.4.2) ???
16508  *
16509  * ATTENTION:
16510  * In XML Schema 1.1 this will be:
16511  * Validation Rule: Checking complex type subsumption
16512  *
16513  * Returns 0 if the constraints are satisfied, a positive
16514  * error code if not and -1 if an internal error occurred.
16515  */
16516 static int
xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,xmlSchemaTypePtr type)16517 xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,
16518 				      xmlSchemaTypePtr type)
16519 {
16520     xmlSchemaTypePtr base;
16521 
16522     /*
16523     * TODO: Correct the error code; XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1 is used
16524     * temporarily only.
16525     */
16526     base = type->baseType;
16527     if (! WXS_IS_COMPLEX(base)) {
16528 	xmlSchemaCustomErr(ACTXT_CAST ctxt,
16529 	    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16530 	    type->node, WXS_BASIC_CAST type,
16531 	    "The base type must be a complex type", NULL, NULL);
16532 	return(ctxt->err);
16533     }
16534     if (base->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) {
16535 	/*
16536 	* SPEC (1) "The {base type definition} must be a complex type
16537 	* definition whose {final} does not contain restriction."
16538 	*/
16539 	xmlSchemaCustomErr(ACTXT_CAST ctxt,
16540 	    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16541 	    type->node, WXS_BASIC_CAST type,
16542 	    "The 'final' of the base type definition "
16543 	    "contains 'restriction'", NULL, NULL);
16544 	return (ctxt->err);
16545     }
16546     /*
16547     * SPEC (2), (3) and (4)
16548     * Those are handled in a separate function, since the
16549     * same constraints are needed for redefinition of
16550     * attribute groups as well.
16551     */
16552     if (xmlSchemaCheckDerivationOKRestriction2to4(ctxt,
16553 	XML_SCHEMA_ACTION_DERIVE,
16554 	WXS_BASIC_CAST type, WXS_BASIC_CAST base,
16555 	type->attrUses, base->attrUses,
16556 	type->attributeWildcard,
16557 	base->attributeWildcard) == -1)
16558     {
16559 	return(-1);
16560     }
16561     /*
16562     * SPEC (5) "One of the following must be true:"
16563     */
16564     if (base->builtInType == XML_SCHEMAS_ANYTYPE) {
16565 	/*
16566 	* SPEC (5.1) "The {base type definition} must be the
16567 	* `ur-type definition`."
16568 	* PASS
16569 	*/
16570     } else if ((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16571 	    (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16572 	/*
16573 	* SPEC (5.2.1) "The {content type} of the complex type definition
16574 	* must be a simple type definition"
16575 	*
16576 	* SPEC (5.2.2) "One of the following must be true:"
16577 	*/
16578 	if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16579 	    (base->contentType == XML_SCHEMA_CONTENT_BASIC))
16580 	{
16581 	    int err;
16582 	    /*
16583 	    * SPEC (5.2.2.1) "The {content type} of the {base type
16584 	    * definition} must be a simple type definition from which
16585 	    * the {content type} is validly derived given the empty
16586 	    * set as defined in Type Derivation OK (Simple) ($3.14.6)."
16587 	    *
16588 	    * ATTENTION TODO: This seems not needed if the type implicitly
16589 	    * derived from the base type.
16590 	    *
16591 	    */
16592 	    err = xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST ctxt,
16593 		type->contentTypeDef, base->contentTypeDef, 0);
16594 	    if (err != 0) {
16595 		xmlChar *strA = NULL, *strB = NULL;
16596 
16597 		if (err == -1)
16598 		    return(-1);
16599 		xmlSchemaCustomErr(ACTXT_CAST ctxt,
16600 		    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16601 		    NULL, WXS_BASIC_CAST type,
16602 		    "The {content type} %s is not validly derived from the "
16603 		    "base type's {content type} %s",
16604 		    xmlSchemaGetComponentDesignation(&strA,
16605 			type->contentTypeDef),
16606 		    xmlSchemaGetComponentDesignation(&strB,
16607 			base->contentTypeDef));
16608 		FREE_AND_NULL(strA);
16609 		FREE_AND_NULL(strB);
16610 		return(ctxt->err);
16611 	    }
16612 	} else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16613 	    (xmlSchemaIsParticleEmptiable(
16614 		(xmlSchemaParticlePtr) base->subtypes))) {
16615 	    /*
16616 	    * SPEC (5.2.2.2) "The {base type definition} must be mixed
16617 	    * and have a particle which is `emptiable` as defined in
16618 	    * Particle Emptiable ($3.9.6)."
16619 	    * PASS
16620 	    */
16621 	} else {
16622 	    xmlSchemaPCustomErr(ctxt,
16623 		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16624 		WXS_BASIC_CAST type, NULL,
16625 		"The content type of the base type must be either "
16626 		"a simple type or 'mixed' and an emptiable particle", NULL);
16627 	    return (ctxt->err);
16628 	}
16629     } else if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16630 	/*
16631 	* SPEC (5.3.1) "The {content type} of the complex type itself must
16632 	* be empty"
16633 	*/
16634 	if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16635 	    /*
16636 	    * SPEC (5.3.2.1) "The {content type} of the {base type
16637 	    * definition} must also be empty."
16638 	    * PASS
16639 	    */
16640 	} else if (((base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16641 	    (base->contentType == XML_SCHEMA_CONTENT_MIXED)) &&
16642 	    xmlSchemaIsParticleEmptiable(
16643 		(xmlSchemaParticlePtr) base->subtypes)) {
16644 	    /*
16645 	    * SPEC (5.3.2.2) "The {content type} of the {base type
16646 	    * definition} must be elementOnly or mixed and have a particle
16647 	    * which is `emptiable` as defined in Particle Emptiable ($3.9.6)."
16648 	    * PASS
16649 	    */
16650 	} else {
16651 	    xmlSchemaPCustomErr(ctxt,
16652 		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16653 		WXS_BASIC_CAST type, NULL,
16654 		"The content type of the base type must be either "
16655 		"empty or 'mixed' (or 'elements-only') and an emptiable "
16656 		"particle", NULL);
16657 	    return (ctxt->err);
16658 	}
16659     } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16660 	WXS_HAS_MIXED_CONTENT(type)) {
16661 	/*
16662 	* SPEC (5.4.1.1) "The {content type} of the complex type definition
16663 	* itself must be element-only"
16664 	*/
16665 	if (WXS_HAS_MIXED_CONTENT(type) && (! WXS_HAS_MIXED_CONTENT(base))) {
16666 	    /*
16667 	    * SPEC (5.4.1.2) "The {content type} of the complex type
16668 	    * definition itself and of the {base type definition} must be
16669 	    * mixed"
16670 	    */
16671 	    xmlSchemaPCustomErr(ctxt,
16672 		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16673 		WXS_BASIC_CAST type, NULL,
16674 		"If the content type is 'mixed', then the content type of the "
16675 		"base type must also be 'mixed'", NULL);
16676 	    return (ctxt->err);
16677 	}
16678 	/*
16679 	* SPEC (5.4.2) "The particle of the complex type definition itself
16680 	* must be a `valid restriction` of the particle of the {content
16681 	* type} of the {base type definition} as defined in Particle Valid
16682 	* (Restriction) ($3.9.6).
16683 	*
16684 	* URGENT TODO: (5.4.2)
16685 	*/
16686     } else {
16687 	xmlSchemaPCustomErr(ctxt,
16688 	    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16689 	    WXS_BASIC_CAST type, NULL,
16690 	    "The type is not a valid restriction of its base type", NULL);
16691 	return (ctxt->err);
16692     }
16693     return (0);
16694 }
16695 
16696 /**
16697  * xmlSchemaCheckCTComponent:
16698  * @ctxt:  the schema parser context
16699  * @type:  the complex type definition
16700  *
16701  * (3.4.6) Constraints on Complex Type Definition Schema Components
16702  *
16703  * Returns 0 if the constraints are satisfied, a positive
16704  * error code if not and -1 if an internal error occurred.
16705  */
16706 static int
xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,xmlSchemaTypePtr type)16707 xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,
16708 			  xmlSchemaTypePtr type)
16709 {
16710     int ret;
16711     /*
16712     * Complex Type Definition Properties Correct
16713     */
16714     ret = xmlSchemaCheckCTPropsCorrect(ctxt, type);
16715     if (ret != 0)
16716 	return (ret);
16717     if (WXS_IS_EXTENSION(type))
16718 	ret = xmlSchemaCheckCOSCTExtends(ctxt, type);
16719     else
16720 	ret = xmlSchemaCheckDerivationOKRestriction(ctxt, type);
16721     return (ret);
16722 }
16723 
16724 /**
16725  * xmlSchemaCheckSRCCT:
16726  * @ctxt:  the schema parser context
16727  * @type:  the complex type definition
16728  *
16729  * (3.4.3) Constraints on XML Representations of Complex Type Definitions:
16730  * Schema Representation Constraint:
16731  * Complex Type Definition Representation OK (src-ct)
16732  *
16733  * Returns 0 if the constraints are satisfied, a positive
16734  * error code if not and -1 if an internal error occurred.
16735  */
16736 static int
xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,xmlSchemaTypePtr type)16737 xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
16738 		    xmlSchemaTypePtr type)
16739 {
16740     xmlSchemaTypePtr base;
16741     int ret = 0;
16742 
16743     /*
16744     * TODO: Adjust the error codes here, as I used
16745     * XML_SCHEMAP_SRC_CT_1 only yet.
16746     */
16747     base = type->baseType;
16748     if (! WXS_HAS_SIMPLE_CONTENT(type)) {
16749 	/*
16750 	* 1 If the <complexContent> alternative is chosen, the type definition
16751 	* `resolved` to by the `actual value` of the base [attribute]
16752 	* must be a complex type definition;
16753 	*/
16754 	if (! WXS_IS_COMPLEX(base)) {
16755 	    xmlChar *str = NULL;
16756 	    xmlSchemaPCustomErr(ctxt,
16757 		XML_SCHEMAP_SRC_CT_1,
16758 		WXS_BASIC_CAST type, type->node,
16759 		"If using <complexContent>, the base type is expected to be "
16760 		"a complex type. The base type '%s' is a simple type",
16761 		xmlSchemaFormatQName(&str, base->targetNamespace,
16762 		base->name));
16763 	    FREE_AND_NULL(str)
16764 	    return (XML_SCHEMAP_SRC_CT_1);
16765 	}
16766     } else {
16767 	/*
16768 	* SPEC
16769 	* 2 If the <simpleContent> alternative is chosen, all of the
16770 	* following must be true:
16771 	* 2.1 The type definition `resolved` to by the `actual value` of the
16772 	* base [attribute] must be one of the following:
16773 	*/
16774 	if (WXS_IS_SIMPLE(base)) {
16775 	    if (WXS_IS_EXTENSION(type) == 0) {
16776 		xmlChar *str = NULL;
16777 		/*
16778 		* 2.1.3 only if the <extension> alternative is also
16779 		* chosen, a simple type definition.
16780 		*/
16781 		/* TODO: Change error code to ..._SRC_CT_2_1_3. */
16782 		xmlSchemaPCustomErr(ctxt,
16783 		    XML_SCHEMAP_SRC_CT_1,
16784 		    WXS_BASIC_CAST type, NULL,
16785 		    "If using <simpleContent> and <restriction>, the base "
16786 		    "type must be a complex type. The base type '%s' is "
16787 		    "a simple type",
16788 		    xmlSchemaFormatQName(&str, base->targetNamespace,
16789 			base->name));
16790 		FREE_AND_NULL(str)
16791 		return (XML_SCHEMAP_SRC_CT_1);
16792 	    }
16793 	} else {
16794 	    /* Base type is a complex type. */
16795 	    if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16796 		(base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16797 		/*
16798 		* 2.1.1 a complex type definition whose {content type} is a
16799 		* simple type definition;
16800 		* PASS
16801 		*/
16802 		if (base->contentTypeDef == NULL) {
16803 		    xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
16804 			WXS_BASIC_CAST type, NULL,
16805 			"Internal error: xmlSchemaCheckSRCCT, "
16806 			"'%s', base type has no content type",
16807 			type->name);
16808 		    return (-1);
16809 		}
16810 	    } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16811 		(WXS_IS_RESTRICTION(type))) {
16812 
16813 		/*
16814 		* 2.1.2 only if the <restriction> alternative is also
16815 		* chosen, a complex type definition whose {content type}
16816 		* is mixed and a particle emptiable.
16817 		*/
16818 		if (! xmlSchemaIsParticleEmptiable(
16819 		    (xmlSchemaParticlePtr) base->subtypes)) {
16820 		    ret = XML_SCHEMAP_SRC_CT_1;
16821 		} else
16822 		    /*
16823 		    * Attention: at this point the <simpleType> child is in
16824 		    * ->contentTypeDef (put there during parsing).
16825 		    */
16826 		    if (type->contentTypeDef == NULL) {
16827 		    xmlChar *str = NULL;
16828 		    /*
16829 		    * 2.2 If clause 2.1.2 above is satisfied, then there
16830 		    * must be a <simpleType> among the [children] of
16831 		    * <restriction>.
16832 		    */
16833 		    /* TODO: Change error code to ..._SRC_CT_2_2. */
16834 		    xmlSchemaPCustomErr(ctxt,
16835 			XML_SCHEMAP_SRC_CT_1,
16836 			WXS_BASIC_CAST type, NULL,
16837 			"A <simpleType> is expected among the children "
16838 			"of <restriction>, if <simpleContent> is used and "
16839 			"the base type '%s' is a complex type",
16840 			xmlSchemaFormatQName(&str, base->targetNamespace,
16841 			base->name));
16842 		    FREE_AND_NULL(str)
16843 		    return (XML_SCHEMAP_SRC_CT_1);
16844 		}
16845 	    } else {
16846 		ret = XML_SCHEMAP_SRC_CT_1;
16847 	    }
16848 	}
16849 	if (ret > 0) {
16850 	    xmlChar *str = NULL;
16851 	    if (WXS_IS_RESTRICTION(type)) {
16852 		xmlSchemaPCustomErr(ctxt,
16853 		    XML_SCHEMAP_SRC_CT_1,
16854 		    WXS_BASIC_CAST type, NULL,
16855 		    "If <simpleContent> and <restriction> is used, the "
16856 		    "base type must be a simple type or a complex type with "
16857 		    "mixed content and particle emptiable. The base type "
16858 		    "'%s' is none of those",
16859 		    xmlSchemaFormatQName(&str, base->targetNamespace,
16860 		    base->name));
16861 	    } else {
16862 		xmlSchemaPCustomErr(ctxt,
16863 		    XML_SCHEMAP_SRC_CT_1,
16864 		    WXS_BASIC_CAST type, NULL,
16865 		    "If <simpleContent> and <extension> is used, the "
16866 		    "base type must be a simple type. The base type '%s' "
16867 		    "is a complex type",
16868 		    xmlSchemaFormatQName(&str, base->targetNamespace,
16869 		    base->name));
16870 	    }
16871 	    FREE_AND_NULL(str)
16872 	}
16873     }
16874     /*
16875     * SPEC (3) "The corresponding complex type definition component must
16876     * satisfy the conditions set out in Constraints on Complex Type
16877     * Definition Schema Components ($3.4.6);"
16878     * NOTE (3) will be done in xmlSchemaTypeFixup().
16879     */
16880     /*
16881     * SPEC (4) If clause 2.2.1 or clause 2.2.2 in the correspondence specification
16882     * above for {attribute wildcard} is satisfied, the intensional
16883     * intersection must be expressible, as defined in Attribute Wildcard
16884     * Intersection ($3.10.6).
16885     * NOTE (4) is done in xmlSchemaFixupTypeAttributeUses().
16886     */
16887     return (ret);
16888 }
16889 
16890 #ifdef ENABLE_PARTICLE_RESTRICTION
16891 /**
16892  * xmlSchemaCheckParticleRangeOK:
16893  * @ctxt:  the schema parser context
16894  * @type:  the complex type definition
16895  *
16896  * (3.9.6) Constraints on Particle Schema Components
16897  * Schema Component Constraint:
16898  * Occurrence Range OK (range-ok)
16899  *
16900  * STATUS: complete
16901  *
16902  * Returns 0 if the constraints are satisfied, a positive
16903  * error code if not and -1 if an internal error occurred.
16904  */
16905 static int
xmlSchemaCheckParticleRangeOK(int rmin,int rmax,int bmin,int bmax)16906 xmlSchemaCheckParticleRangeOK(int rmin, int rmax,
16907 			      int bmin, int bmax)
16908 {
16909     if (rmin < bmin)
16910 	return (1);
16911     if ((bmax != UNBOUNDED) &&
16912 	(rmax > bmax))
16913 	return (1);
16914     return (0);
16915 }
16916 
16917 /**
16918  * xmlSchemaCheckRCaseNameAndTypeOK:
16919  * @ctxt:  the schema parser context
16920  * @r: the restricting element declaration particle
16921  * @b: the base element declaration particle
16922  *
16923  * (3.9.6) Constraints on Particle Schema Components
16924  * Schema Component Constraint:
16925  * Particle Restriction OK (Elt:Elt -- NameAndTypeOK)
16926  * (rcase-NameAndTypeOK)
16927  *
16928  * STATUS:
16929  *   MISSING (3.2.3)
16930  *   CLARIFY: (3.2.2)
16931  *
16932  * Returns 0 if the constraints are satisfied, a positive
16933  * error code if not and -1 if an internal error occurred.
16934  */
16935 static int
xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr r,xmlSchemaParticlePtr b)16936 xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,
16937 				 xmlSchemaParticlePtr r,
16938 				 xmlSchemaParticlePtr b)
16939 {
16940     xmlSchemaElementPtr elemR, elemB;
16941 
16942     /* TODO: Error codes (rcase-NameAndTypeOK). */
16943     elemR = (xmlSchemaElementPtr) r->children;
16944     elemB = (xmlSchemaElementPtr) b->children;
16945     /*
16946     * SPEC (1) "The declarations' {name}s and {target namespace}s are
16947     * the same."
16948     */
16949     if ((elemR != elemB) &&
16950 	((! xmlStrEqual(elemR->name, elemB->name)) ||
16951 	(! xmlStrEqual(elemR->targetNamespace, elemB->targetNamespace))))
16952 	return (1);
16953     /*
16954     * SPEC (2) "R's occurrence range is a valid restriction of B's
16955     * occurrence range as defined by Occurrence Range OK ($3.9.6)."
16956     */
16957     if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16958 	    b->minOccurs, b->maxOccurs) != 0)
16959 	return (1);
16960     /*
16961     * SPEC (3.1) "Both B's declaration's {scope} and R's declaration's
16962     * {scope} are global."
16963     */
16964     if (elemR == elemB)
16965 	return (0);
16966     /*
16967     * SPEC (3.2.1) "Either B's {nillable} is true or R's {nillable} is false."
16968     */
16969     if (((elemB->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) &&
16970 	(elemR->flags & XML_SCHEMAS_ELEM_NILLABLE))
16971 	 return (1);
16972     /*
16973     * SPEC (3.2.2) "either B's declaration's {value constraint} is absent,
16974     * or is not fixed, or R's declaration's {value constraint} is fixed
16975     * with the same value."
16976     */
16977     if ((elemB->value != NULL) && (elemB->flags & XML_SCHEMAS_ELEM_FIXED) &&
16978 	((elemR->value == NULL) ||
16979 	 ((elemR->flags & XML_SCHEMAS_ELEM_FIXED) == 0) ||
16980 	 /* TODO: Equality of the initial value or normalized or canonical? */
16981 	 (! xmlStrEqual(elemR->value, elemB->value))))
16982 	 return (1);
16983     /*
16984     * TODO: SPEC (3.2.3) "R's declaration's {identity-constraint
16985     * definitions} is a subset of B's declaration's {identity-constraint
16986     * definitions}, if any."
16987     */
16988     if (elemB->idcs != NULL) {
16989 	/* TODO */
16990     }
16991     /*
16992     * SPEC (3.2.4) "R's declaration's {disallowed substitutions} is a
16993     * superset of B's declaration's {disallowed substitutions}."
16994     */
16995     if (((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) &&
16996 	 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) == 0)) ||
16997 	((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) &&
16998 	 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) == 0)) ||
16999 	((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) &&
17000 	 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) == 0)))
17001 	 return (1);
17002     /*
17003     * SPEC (3.2.5) "R's {type definition} is validly derived given
17004     * {extension, list, union} from B's {type definition}"
17005     *
17006     * BADSPEC TODO: What's the point of adding "list" and "union" to the
17007     * set, if the corresponding constraints handle "restriction" and
17008     * "extension" only?
17009     *
17010     */
17011     {
17012 	int set = 0;
17013 
17014 	set |= SUBSET_EXTENSION;
17015 	set |= SUBSET_LIST;
17016 	set |= SUBSET_UNION;
17017 	if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST ctxt, elemR->subtypes,
17018 	    elemB->subtypes, set) != 0)
17019 	    return (1);
17020     }
17021     return (0);
17022 }
17023 
17024 /**
17025  * xmlSchemaCheckRCaseNSCompat:
17026  * @ctxt:  the schema parser context
17027  * @r: the restricting element declaration particle
17028  * @b: the base wildcard particle
17029  *
17030  * (3.9.6) Constraints on Particle Schema Components
17031  * Schema Component Constraint:
17032  * Particle Derivation OK (Elt:Any -- NSCompat)
17033  * (rcase-NSCompat)
17034  *
17035  * STATUS: complete
17036  *
17037  * Returns 0 if the constraints are satisfied, a positive
17038  * error code if not and -1 if an internal error occurred.
17039  */
17040 static int
xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr r,xmlSchemaParticlePtr b)17041 xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,
17042 			    xmlSchemaParticlePtr r,
17043 			    xmlSchemaParticlePtr b)
17044 {
17045     /* TODO:Error codes (rcase-NSCompat). */
17046     /*
17047     * SPEC "For an element declaration particle to be a `valid restriction`
17048     * of a wildcard particle all of the following must be true:"
17049     *
17050     * SPEC (1) "The element declaration's {target namespace} is `valid`
17051     * with respect to the wildcard's {namespace constraint} as defined by
17052     * Wildcard allows Namespace Name ($3.10.4)."
17053     */
17054     if (xmlSchemaCheckCVCWildcardNamespace((xmlSchemaWildcardPtr) b->children,
17055 	((xmlSchemaElementPtr) r->children)->targetNamespace) != 0)
17056 	return (1);
17057     /*
17058     * SPEC (2) "R's occurrence range is a valid restriction of B's
17059     * occurrence range as defined by Occurrence Range OK ($3.9.6)."
17060     */
17061     if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
17062 	    b->minOccurs, b->maxOccurs) != 0)
17063 	return (1);
17064 
17065     return (0);
17066 }
17067 
17068 /**
17069  * xmlSchemaCheckRCaseRecurseAsIfGroup:
17070  * @ctxt:  the schema parser context
17071  * @r: the restricting element declaration particle
17072  * @b: the base model group particle
17073  *
17074  * (3.9.6) Constraints on Particle Schema Components
17075  * Schema Component Constraint:
17076  * Particle Derivation OK (Elt:All/Choice/Sequence -- RecurseAsIfGroup)
17077  * (rcase-RecurseAsIfGroup)
17078  *
17079  * STATUS: TODO
17080  *
17081  * Returns 0 if the constraints are satisfied, a positive
17082  * error code if not and -1 if an internal error occurred.
17083  */
17084 static int
xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr r,xmlSchemaParticlePtr b)17085 xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,
17086 				    xmlSchemaParticlePtr r,
17087 				    xmlSchemaParticlePtr b)
17088 {
17089     /* TODO: Error codes (rcase-RecurseAsIfGroup). */
17090     TODO
17091     return (0);
17092 }
17093 
17094 /**
17095  * xmlSchemaCheckRCaseNSSubset:
17096  * @ctxt:  the schema parser context
17097  * @r: the restricting wildcard particle
17098  * @b: the base wildcard particle
17099  *
17100  * (3.9.6) Constraints on Particle Schema Components
17101  * Schema Component Constraint:
17102  * Particle Derivation OK (Any:Any -- NSSubset)
17103  * (rcase-NSSubset)
17104  *
17105  * STATUS: complete
17106  *
17107  * Returns 0 if the constraints are satisfied, a positive
17108  * error code if not and -1 if an internal error occurred.
17109  */
17110 static int
xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr r,xmlSchemaParticlePtr b,int isAnyTypeBase)17111 xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,
17112 				    xmlSchemaParticlePtr r,
17113 				    xmlSchemaParticlePtr b,
17114 				    int isAnyTypeBase)
17115 {
17116     /* TODO: Error codes (rcase-NSSubset). */
17117     /*
17118     * SPEC (1) "R's occurrence range is a valid restriction of B's
17119     * occurrence range as defined by Occurrence Range OK ($3.9.6)."
17120     */
17121     if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
17122 	    b->minOccurs, b->maxOccurs))
17123 	return (1);
17124     /*
17125     * SPEC (2) "R's {namespace constraint} must be an intensional subset
17126     * of B's {namespace constraint} as defined by Wildcard Subset ($3.10.6)."
17127     */
17128     if (xmlSchemaCheckCOSNSSubset((xmlSchemaWildcardPtr) r->children,
17129 	(xmlSchemaWildcardPtr) b->children))
17130 	return (1);
17131     /*
17132     * SPEC (3) "Unless B is the content model wildcard of the `ur-type
17133     * definition`, R's {process contents} must be identical to or stronger
17134     * than B's {process contents}, where strict is stronger than lax is
17135     * stronger than skip."
17136     */
17137     if (! isAnyTypeBase) {
17138 	if ( ((xmlSchemaWildcardPtr) r->children)->processContents <
17139 	    ((xmlSchemaWildcardPtr) b->children)->processContents)
17140 	    return (1);
17141     }
17142 
17143     return (0);
17144 }
17145 
17146 /**
17147  * xmlSchemaCheckCOSParticleRestrict:
17148  * @ctxt:  the schema parser context
17149  * @type:  the complex type definition
17150  *
17151  * (3.9.6) Constraints on Particle Schema Components
17152  * Schema Component Constraint:
17153  * Particle Valid (Restriction) (cos-particle-restrict)
17154  *
17155  * STATUS: TODO
17156  *
17157  * Returns 0 if the constraints are satisfied, a positive
17158  * error code if not and -1 if an internal error occurred.
17159  */
17160 static int
xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr r,xmlSchemaParticlePtr b)17161 xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,
17162 				  xmlSchemaParticlePtr r,
17163 				  xmlSchemaParticlePtr b)
17164 {
17165     int ret = 0;
17166 
17167     /*part = WXS_TYPE_PARTICLE(type);
17168     basePart = WXS_TYPE_PARTICLE(base);
17169     */
17170 
17171     TODO
17172 
17173     /*
17174     * SPEC (1) "They are the same particle."
17175     */
17176     if (r == b)
17177 	return (0);
17178 
17179 
17180     return (0);
17181 }
17182 
17183 #if 0
17184 /**
17185  * xmlSchemaCheckRCaseNSRecurseCheckCardinality:
17186  * @ctxt:  the schema parser context
17187  * @r: the model group particle
17188  * @b: the base wildcard particle
17189  *
17190  * (3.9.6) Constraints on Particle Schema Components
17191  * Schema Component Constraint:
17192  * Particle Derivation OK (All/Choice/Sequence:Any --
17193  *                         NSRecurseCheckCardinality)
17194  * (rcase-NSRecurseCheckCardinality)
17195  *
17196  * STATUS: TODO: subst-groups
17197  *
17198  * Returns 0 if the constraints are satisfied, a positive
17199  * error code if not and -1 if an internal error occurred.
17200  */
17201 static int
17202 xmlSchemaCheckRCaseNSRecurseCheckCardinality(xmlSchemaParserCtxtPtr ctxt,
17203 					     xmlSchemaParticlePtr r,
17204 					     xmlSchemaParticlePtr b)
17205 {
17206     xmlSchemaParticlePtr part;
17207     /* TODO: Error codes (rcase-NSRecurseCheckCardinality). */
17208     if ((r->children == NULL) || (r->children->children == NULL))
17209 	return (-1);
17210     /*
17211     * SPEC "For a group particle to be a `valid restriction` of a
17212     * wildcard particle..."
17213     *
17214     * SPEC (1) "Every member of the {particles} of the group is a `valid
17215     * restriction` of the wildcard as defined by
17216     * Particle Valid (Restriction) ($3.9.6)."
17217     */
17218     part = (xmlSchemaParticlePtr) r->children->children;
17219     do {
17220 	if (xmlSchemaCheckCOSParticleRestrict(ctxt, part, b))
17221 	    return (1);
17222 	part = (xmlSchemaParticlePtr) part->next;
17223     } while (part != NULL);
17224     /*
17225     * SPEC (2) "The effective total range of the group [...] is a
17226     * valid restriction of B's occurrence range as defined by
17227     * Occurrence Range OK ($3.9.6)."
17228     */
17229     if (xmlSchemaCheckParticleRangeOK(
17230 	    xmlSchemaGetParticleTotalRangeMin(r),
17231 	    xmlSchemaGetParticleTotalRangeMax(r),
17232 	    b->minOccurs, b->maxOccurs) != 0)
17233 	return (1);
17234     return (0);
17235 }
17236 #endif
17237 
17238 /**
17239  * xmlSchemaCheckRCaseRecurse:
17240  * @ctxt:  the schema parser context
17241  * @r: the <all> or <sequence> model group particle
17242  * @b: the base <all> or <sequence> model group particle
17243  *
17244  * (3.9.6) Constraints on Particle Schema Components
17245  * Schema Component Constraint:
17246  * Particle Derivation OK (All:All,Sequence:Sequence --
17247                            Recurse)
17248  * (rcase-Recurse)
17249  *
17250  * STATUS:  ?
17251  * TODO: subst-groups
17252  *
17253  * Returns 0 if the constraints are satisfied, a positive
17254  * error code if not and -1 if an internal error occurred.
17255  */
17256 static int
xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr r,xmlSchemaParticlePtr b)17257 xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,
17258 			   xmlSchemaParticlePtr r,
17259 			   xmlSchemaParticlePtr b)
17260 {
17261     /* xmlSchemaParticlePtr part; */
17262     /* TODO: Error codes (rcase-Recurse). */
17263     if ((r->children == NULL) || (b->children == NULL) ||
17264 	(r->children->type != b->children->type))
17265 	return (-1);
17266     /*
17267     * SPEC "For an all or sequence group particle to be a `valid
17268     * restriction` of another group particle with the same {compositor}..."
17269     *
17270     * SPEC (1) "R's occurrence range is a valid restriction of B's
17271     * occurrence range as defined by Occurrence Range OK ($3.9.6)."
17272     */
17273     if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
17274 	    b->minOccurs, b->maxOccurs))
17275 	return (1);
17276 
17277 
17278     return (0);
17279 }
17280 
17281 #endif
17282 
17283 #define FACET_RESTR_MUTUAL_ERR(fac1, fac2) \
17284     xmlSchemaPCustomErrExt(pctxt,      \
17285 	XML_SCHEMAP_INVALID_FACET_VALUE, \
17286 	WXS_BASIC_CAST fac1, fac1->node, \
17287 	"It is an error for both '%s' and '%s' to be specified on the "\
17288 	"same type definition", \
17289 	BAD_CAST xmlSchemaFacetTypeToString(fac1->type), \
17290 	BAD_CAST xmlSchemaFacetTypeToString(fac2->type), NULL);
17291 
17292 #define FACET_RESTR_ERR(fac1, msg) \
17293     xmlSchemaPCustomErr(pctxt,      \
17294 	XML_SCHEMAP_INVALID_FACET_VALUE, \
17295 	WXS_BASIC_CAST fac1, fac1->node, \
17296 	msg, NULL);
17297 
17298 #define FACET_RESTR_FIXED_ERR(fac) \
17299     xmlSchemaPCustomErr(pctxt, \
17300 	XML_SCHEMAP_INVALID_FACET_VALUE, \
17301 	WXS_BASIC_CAST fac, fac->node, \
17302 	"The base type's facet is 'fixed', thus the value must not " \
17303 	"differ", NULL);
17304 
17305 static void
xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,xmlSchemaFacetPtr facet1,xmlSchemaFacetPtr facet2,int lessGreater,int orEqual,int ofBase)17306 xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,
17307 			xmlSchemaFacetPtr facet1,
17308 			xmlSchemaFacetPtr facet2,
17309 			int lessGreater,
17310 			int orEqual,
17311 			int ofBase)
17312 {
17313     xmlChar *msg = NULL;
17314 
17315     msg = xmlStrdup(BAD_CAST "'");
17316     msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet1->type));
17317     msg = xmlStrcat(msg, BAD_CAST "' has to be");
17318     if (lessGreater == 0)
17319 	msg = xmlStrcat(msg, BAD_CAST " equal to");
17320     if (lessGreater == 1)
17321 	msg = xmlStrcat(msg, BAD_CAST " greater than");
17322     else
17323 	msg = xmlStrcat(msg, BAD_CAST " less than");
17324 
17325     if (orEqual)
17326 	msg = xmlStrcat(msg, BAD_CAST " or equal to");
17327     msg = xmlStrcat(msg, BAD_CAST " '");
17328     msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet2->type));
17329     if (ofBase)
17330 	msg = xmlStrcat(msg, BAD_CAST "' of the base type");
17331     else
17332 	msg = xmlStrcat(msg, BAD_CAST "'");
17333 
17334     xmlSchemaPCustomErr(pctxt,
17335 	XML_SCHEMAP_INVALID_FACET_VALUE,
17336 	WXS_BASIC_CAST facet1, NULL,
17337 	(const char *) msg, NULL);
17338 
17339     if (msg != NULL)
17340 	xmlFree(msg);
17341 }
17342 
17343 /*
17344 * xmlSchemaDeriveAndValidateFacets:
17345 *
17346 * Schema Component Constraint: Simple Type Restriction (Facets)
17347 * (st-restrict-facets)
17348 */
17349 static int
xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)17350 xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,
17351 				 xmlSchemaTypePtr type)
17352 {
17353     xmlSchemaTypePtr base = type->baseType;
17354     xmlSchemaFacetLinkPtr link, cur, last = NULL;
17355     xmlSchemaFacetPtr facet, bfacet,
17356 	flength = NULL, ftotdig = NULL, ffracdig = NULL,
17357 	fmaxlen = NULL, fminlen = NULL, /* facets of the current type */
17358 	fmininc = NULL, fmaxinc = NULL,
17359 	fminexc = NULL, fmaxexc = NULL,
17360 	bflength = NULL, bftotdig = NULL, bffracdig = NULL,
17361 	bfmaxlen = NULL, bfminlen = NULL, /* facets of the base type */
17362 	bfmininc = NULL, bfmaxinc = NULL,
17363 	bfminexc = NULL, bfmaxexc = NULL;
17364     int res; /* err = 0, fixedErr; */
17365 
17366     /*
17367     * SPEC st-restrict-facets 1:
17368     * "The {variety} of R is the same as that of B."
17369     */
17370     /*
17371     * SPEC st-restrict-facets 2:
17372     * "If {variety} is atomic, the {primitive type definition}
17373     * of R is the same as that of B."
17374     *
17375     * NOTE: we leave 1 & 2 out for now, since this will be
17376     * satisfied by the derivation process.
17377     * CONSTRUCTION TODO: Maybe needed if using a construction API.
17378     */
17379     /*
17380     * SPEC st-restrict-facets 3:
17381     * "The {facets} of R are the union of S and the {facets}
17382     * of B, eliminating duplicates. To eliminate duplicates,
17383     * when a facet of the same kind occurs in both S and the
17384     * {facets} of B, the one in the {facets} of B is not
17385     * included, with the exception of enumeration and pattern
17386     * facets, for which multiple occurrences with distinct values
17387     * are allowed."
17388     */
17389 
17390     if ((type->facetSet == NULL) && (base->facetSet == NULL))
17391 	return (0);
17392 
17393     last = type->facetSet;
17394     if (last != NULL)
17395 	while (last->next != NULL)
17396 	    last = last->next;
17397 
17398     for (cur = type->facetSet; cur != NULL; cur = cur->next) {
17399 	facet = cur->facet;
17400 	switch (facet->type) {
17401 	    case XML_SCHEMA_FACET_LENGTH:
17402 		flength = facet; break;
17403 	    case XML_SCHEMA_FACET_MINLENGTH:
17404 		fminlen = facet; break;
17405 	    case XML_SCHEMA_FACET_MININCLUSIVE:
17406 		fmininc = facet; break;
17407 	    case XML_SCHEMA_FACET_MINEXCLUSIVE:
17408 		fminexc = facet; break;
17409 	    case XML_SCHEMA_FACET_MAXLENGTH:
17410 		fmaxlen = facet; break;
17411 	    case XML_SCHEMA_FACET_MAXINCLUSIVE:
17412 		fmaxinc = facet; break;
17413 	    case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17414 		fmaxexc = facet; break;
17415 	    case XML_SCHEMA_FACET_TOTALDIGITS:
17416 		ftotdig = facet; break;
17417 	    case XML_SCHEMA_FACET_FRACTIONDIGITS:
17418 		ffracdig = facet; break;
17419 	    default:
17420 		break;
17421 	}
17422     }
17423     for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17424 	facet = cur->facet;
17425 	switch (facet->type) {
17426 	    case XML_SCHEMA_FACET_LENGTH:
17427 		bflength = facet; break;
17428 	    case XML_SCHEMA_FACET_MINLENGTH:
17429 		bfminlen = facet; break;
17430 	    case XML_SCHEMA_FACET_MININCLUSIVE:
17431 		bfmininc = facet; break;
17432 	    case XML_SCHEMA_FACET_MINEXCLUSIVE:
17433 		bfminexc = facet; break;
17434 	    case XML_SCHEMA_FACET_MAXLENGTH:
17435 		bfmaxlen = facet; break;
17436 	    case XML_SCHEMA_FACET_MAXINCLUSIVE:
17437 		bfmaxinc = facet; break;
17438 	    case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17439 		bfmaxexc = facet; break;
17440 	    case XML_SCHEMA_FACET_TOTALDIGITS:
17441 		bftotdig = facet; break;
17442 	    case XML_SCHEMA_FACET_FRACTIONDIGITS:
17443 		bffracdig = facet; break;
17444 	    default:
17445 		break;
17446 	}
17447     }
17448     /*
17449     * length and minLength or maxLength (2.2) + (3.2)
17450     */
17451     if (flength && (fminlen || fmaxlen)) {
17452 	FACET_RESTR_ERR(flength, "It is an error for both 'length' and "
17453 	    "either of 'minLength' or 'maxLength' to be specified on "
17454 	    "the same type definition")
17455     }
17456     /*
17457     * Mutual exclusions in the same derivation step.
17458     */
17459     if ((fmaxinc) && (fmaxexc)) {
17460 	/*
17461 	* SCC "maxInclusive and maxExclusive"
17462 	*/
17463 	FACET_RESTR_MUTUAL_ERR(fmaxinc, fmaxexc)
17464     }
17465     if ((fmininc) && (fminexc)) {
17466 	/*
17467 	* SCC "minInclusive and minExclusive"
17468 	*/
17469 	FACET_RESTR_MUTUAL_ERR(fmininc, fminexc)
17470     }
17471 
17472     if (flength && bflength) {
17473 	/*
17474 	* SCC "length valid restriction"
17475 	* The values have to be equal.
17476 	*/
17477 	res = xmlSchemaCompareValues(flength->val, bflength->val);
17478 	if (res == -2)
17479 	    goto internal_error;
17480 	if (res != 0)
17481 	    xmlSchemaDeriveFacetErr(pctxt, flength, bflength, 0, 0, 1);
17482 	if ((res != 0) && (bflength->fixed)) {
17483 	    FACET_RESTR_FIXED_ERR(flength)
17484 	}
17485 
17486     }
17487     if (fminlen && bfminlen) {
17488 	/*
17489 	* SCC "minLength valid restriction"
17490 	* minLength >= BASE minLength
17491 	*/
17492 	res = xmlSchemaCompareValues(fminlen->val, bfminlen->val);
17493 	if (res == -2)
17494 	    goto internal_error;
17495 	if (res == -1)
17496 	    xmlSchemaDeriveFacetErr(pctxt, fminlen, bfminlen, 1, 1, 1);
17497 	if ((res != 0) && (bfminlen->fixed)) {
17498 	    FACET_RESTR_FIXED_ERR(fminlen)
17499 	}
17500     }
17501     if (fmaxlen && bfmaxlen) {
17502 	/*
17503 	* SCC "maxLength valid restriction"
17504 	* maxLength <= BASE minLength
17505 	*/
17506 	res = xmlSchemaCompareValues(fmaxlen->val, bfmaxlen->val);
17507 	if (res == -2)
17508 	    goto internal_error;
17509 	if (res == 1)
17510 	    xmlSchemaDeriveFacetErr(pctxt, fmaxlen, bfmaxlen, -1, 1, 1);
17511 	if ((res != 0) && (bfmaxlen->fixed)) {
17512 	    FACET_RESTR_FIXED_ERR(fmaxlen)
17513 	}
17514     }
17515     /*
17516     * SCC "length and minLength or maxLength"
17517     */
17518     if (! flength)
17519 	flength = bflength;
17520     if (flength) {
17521 	if (! fminlen)
17522 	    fminlen = bfminlen;
17523 	if (fminlen) {
17524 	    /* (1.1) length >= minLength */
17525 	    res = xmlSchemaCompareValues(flength->val, fminlen->val);
17526 	    if (res == -2)
17527 		goto internal_error;
17528 	    if (res == -1)
17529 		xmlSchemaDeriveFacetErr(pctxt, flength, fminlen, 1, 1, 0);
17530 	}
17531 	if (! fmaxlen)
17532 	    fmaxlen = bfmaxlen;
17533 	if (fmaxlen) {
17534 	    /* (2.1) length <= maxLength */
17535 	    res = xmlSchemaCompareValues(flength->val, fmaxlen->val);
17536 	    if (res == -2)
17537 		goto internal_error;
17538 	    if (res == 1)
17539 		xmlSchemaDeriveFacetErr(pctxt, flength, fmaxlen, -1, 1, 0);
17540 	}
17541     }
17542     if (fmaxinc) {
17543 	/*
17544 	* "maxInclusive"
17545 	*/
17546 	if (fmininc) {
17547 	    /* SCC "maxInclusive >= minInclusive" */
17548 	    res = xmlSchemaCompareValues(fmaxinc->val, fmininc->val);
17549 	    if (res == -2)
17550 		goto internal_error;
17551 	    if (res == -1) {
17552 		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, fmininc, 1, 1, 0);
17553 	    }
17554 	}
17555 	/*
17556 	* SCC "maxInclusive valid restriction"
17557 	*/
17558 	if (bfmaxinc) {
17559 	    /* maxInclusive <= BASE maxInclusive */
17560 	    res = xmlSchemaCompareValues(fmaxinc->val, bfmaxinc->val);
17561 	    if (res == -2)
17562 		goto internal_error;
17563 	    if (res == 1)
17564 		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxinc, -1, 1, 1);
17565 	    if ((res != 0) && (bfmaxinc->fixed)) {
17566 		FACET_RESTR_FIXED_ERR(fmaxinc)
17567 	    }
17568 	}
17569 	if (bfmaxexc) {
17570 	    /* maxInclusive < BASE maxExclusive */
17571 	    res = xmlSchemaCompareValues(fmaxinc->val, bfmaxexc->val);
17572 	    if (res == -2)
17573 		goto internal_error;
17574 	    if (res != -1) {
17575 		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxexc, -1, 0, 1);
17576 	    }
17577 	}
17578 	if (bfmininc) {
17579 	    /* maxInclusive >= BASE minInclusive */
17580 	    res = xmlSchemaCompareValues(fmaxinc->val, bfmininc->val);
17581 	    if (res == -2)
17582 		goto internal_error;
17583 	    if (res == -1) {
17584 		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmininc, 1, 1, 1);
17585 	    }
17586 	}
17587 	if (bfminexc) {
17588 	    /* maxInclusive > BASE minExclusive */
17589 	    res = xmlSchemaCompareValues(fmaxinc->val, bfminexc->val);
17590 	    if (res == -2)
17591 		goto internal_error;
17592 	    if (res != 1) {
17593 		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfminexc, 1, 0, 1);
17594 	    }
17595 	}
17596     }
17597     if (fmaxexc) {
17598 	/*
17599 	* "maxExclusive >= minExclusive"
17600 	*/
17601 	if (fminexc) {
17602 	    res = xmlSchemaCompareValues(fmaxexc->val, fminexc->val);
17603 	    if (res == -2)
17604 		goto internal_error;
17605 	    if (res == -1) {
17606 		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, fminexc, 1, 1, 0);
17607 	    }
17608 	}
17609 	/*
17610 	* "maxExclusive valid restriction"
17611 	*/
17612 	if (bfmaxexc) {
17613 	    /* maxExclusive <= BASE maxExclusive */
17614 	    res = xmlSchemaCompareValues(fmaxexc->val, bfmaxexc->val);
17615 	    if (res == -2)
17616 		goto internal_error;
17617 	    if (res == 1) {
17618 		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxexc, -1, 1, 1);
17619 	    }
17620 	    if ((res != 0) && (bfmaxexc->fixed)) {
17621 		FACET_RESTR_FIXED_ERR(fmaxexc)
17622 	    }
17623 	}
17624 	if (bfmaxinc) {
17625 	    /* maxExclusive <= BASE maxInclusive */
17626 	    res = xmlSchemaCompareValues(fmaxexc->val, bfmaxinc->val);
17627 	    if (res == -2)
17628 		goto internal_error;
17629 	    if (res == 1) {
17630 		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxinc, -1, 1, 1);
17631 	    }
17632 	}
17633 	if (bfmininc) {
17634 	    /* maxExclusive > BASE minInclusive */
17635 	    res = xmlSchemaCompareValues(fmaxexc->val, bfmininc->val);
17636 	    if (res == -2)
17637 		goto internal_error;
17638 	    if (res != 1) {
17639 		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmininc, 1, 0, 1);
17640 	    }
17641 	}
17642 	if (bfminexc) {
17643 	    /* maxExclusive > BASE minExclusive */
17644 	    res = xmlSchemaCompareValues(fmaxexc->val, bfminexc->val);
17645 	    if (res == -2)
17646 		goto internal_error;
17647 	    if (res != 1) {
17648 		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfminexc, 1, 0, 1);
17649 	    }
17650 	}
17651     }
17652     if (fminexc) {
17653 	/*
17654 	* "minExclusive < maxInclusive"
17655 	*/
17656 	if (fmaxinc) {
17657 	    res = xmlSchemaCompareValues(fminexc->val, fmaxinc->val);
17658 	    if (res == -2)
17659 		goto internal_error;
17660 	    if (res != -1) {
17661 		xmlSchemaDeriveFacetErr(pctxt, fminexc, fmaxinc, -1, 0, 0);
17662 	    }
17663 	}
17664 	/*
17665 	* "minExclusive valid restriction"
17666 	*/
17667 	if (bfminexc) {
17668 	    /* minExclusive >= BASE minExclusive */
17669 	    res = xmlSchemaCompareValues(fminexc->val, bfminexc->val);
17670 	    if (res == -2)
17671 		goto internal_error;
17672 	    if (res == -1) {
17673 		xmlSchemaDeriveFacetErr(pctxt, fminexc, bfminexc, 1, 1, 1);
17674 	    }
17675 	    if ((res != 0) && (bfminexc->fixed)) {
17676 		FACET_RESTR_FIXED_ERR(fminexc)
17677 	    }
17678 	}
17679 	if (bfmaxinc) {
17680 	    /* minExclusive <= BASE maxInclusive */
17681 	    res = xmlSchemaCompareValues(fminexc->val, bfmaxinc->val);
17682 	    if (res == -2)
17683 		goto internal_error;
17684 	    if (res == 1) {
17685 		xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxinc, -1, 1, 1);
17686 	    }
17687 	}
17688 	if (bfmininc) {
17689 	    /* minExclusive >= BASE minInclusive */
17690 	    res = xmlSchemaCompareValues(fminexc->val, bfmininc->val);
17691 	    if (res == -2)
17692 		goto internal_error;
17693 	    if (res == -1) {
17694 		xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmininc, 1, 1, 1);
17695 	    }
17696 	}
17697 	if (bfmaxexc) {
17698 	    /* minExclusive < BASE maxExclusive */
17699 	    res = xmlSchemaCompareValues(fminexc->val, bfmaxexc->val);
17700 	    if (res == -2)
17701 		goto internal_error;
17702 	    if (res != -1) {
17703 		xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxexc, -1, 0, 1);
17704 	    }
17705 	}
17706     }
17707     if (fmininc) {
17708 	/*
17709 	* "minInclusive < maxExclusive"
17710 	*/
17711 	if (fmaxexc) {
17712 	    res = xmlSchemaCompareValues(fmininc->val, fmaxexc->val);
17713 	    if (res == -2)
17714 		goto internal_error;
17715 	    if (res != -1) {
17716 		xmlSchemaDeriveFacetErr(pctxt, fmininc, fmaxexc, -1, 0, 0);
17717 	    }
17718 	}
17719 	/*
17720 	* "minExclusive valid restriction"
17721 	*/
17722 	if (bfmininc) {
17723 	    /* minInclusive >= BASE minInclusive */
17724 	    res = xmlSchemaCompareValues(fmininc->val, bfmininc->val);
17725 	    if (res == -2)
17726 		goto internal_error;
17727 	    if (res == -1) {
17728 		xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmininc, 1, 1, 1);
17729 	    }
17730 	    if ((res != 0) && (bfmininc->fixed)) {
17731 		FACET_RESTR_FIXED_ERR(fmininc)
17732 	    }
17733 	}
17734 	if (bfmaxinc) {
17735 	    /* minInclusive <= BASE maxInclusive */
17736 	    res = xmlSchemaCompareValues(fmininc->val, bfmaxinc->val);
17737 	    if (res == -2)
17738 		goto internal_error;
17739 	    if (res == 1) {
17740 		xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxinc, -1, 1, 1);
17741 	    }
17742 	}
17743 	if (bfminexc) {
17744 	    /* minInclusive > BASE minExclusive */
17745 	    res = xmlSchemaCompareValues(fmininc->val, bfminexc->val);
17746 	    if (res == -2)
17747 		goto internal_error;
17748 	    if (res != 1)
17749 		xmlSchemaDeriveFacetErr(pctxt, fmininc, bfminexc, 1, 0, 1);
17750 	}
17751 	if (bfmaxexc) {
17752 	    /* minInclusive < BASE maxExclusive */
17753 	    res = xmlSchemaCompareValues(fmininc->val, bfmaxexc->val);
17754 	    if (res == -2)
17755 		goto internal_error;
17756 	    if (res != -1)
17757 		xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxexc, -1, 0, 1);
17758 	}
17759     }
17760     if (ftotdig && bftotdig) {
17761 	/*
17762 	* SCC " totalDigits valid restriction"
17763 	* totalDigits <= BASE totalDigits
17764 	*/
17765 	res = xmlSchemaCompareValues(ftotdig->val, bftotdig->val);
17766 	if (res == -2)
17767 	    goto internal_error;
17768 	if (res == 1)
17769 	    xmlSchemaDeriveFacetErr(pctxt, ftotdig, bftotdig,
17770 	    -1, 1, 1);
17771 	if ((res != 0) && (bftotdig->fixed)) {
17772 	    FACET_RESTR_FIXED_ERR(ftotdig)
17773 	}
17774     }
17775     if (ffracdig && bffracdig) {
17776 	/*
17777 	* SCC  "fractionDigits valid restriction"
17778 	* fractionDigits <= BASE fractionDigits
17779 	*/
17780 	res = xmlSchemaCompareValues(ffracdig->val, bffracdig->val);
17781 	if (res == -2)
17782 	    goto internal_error;
17783 	if (res == 1)
17784 	    xmlSchemaDeriveFacetErr(pctxt, ffracdig, bffracdig,
17785 	    -1, 1, 1);
17786 	if ((res != 0) && (bffracdig->fixed)) {
17787 	    FACET_RESTR_FIXED_ERR(ffracdig)
17788 	}
17789     }
17790     /*
17791     * SCC "fractionDigits less than or equal to totalDigits"
17792     */
17793     if (! ftotdig)
17794 	ftotdig = bftotdig;
17795     if (! ffracdig)
17796 	ffracdig = bffracdig;
17797     if (ftotdig && ffracdig) {
17798 	res = xmlSchemaCompareValues(ffracdig->val, ftotdig->val);
17799 	if (res == -2)
17800 	    goto internal_error;
17801 	if (res == 1)
17802 	    xmlSchemaDeriveFacetErr(pctxt, ffracdig, ftotdig,
17803 		-1, 1, 0);
17804     }
17805     /*
17806     * *Enumerations* won' be added here, since only the first set
17807     * of enumerations in the ancestor-or-self axis is used
17808     * for validation, plus we need to use the base type of those
17809     * enumerations for whitespace.
17810     *
17811     * *Patterns*: won't be add here, since they are ORed at
17812     * type level and ANDed at ancestor level. This will
17813     * happen during validation by walking the base axis
17814     * of the type.
17815     */
17816     for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17817 	bfacet = cur->facet;
17818 	/*
17819 	* Special handling of enumerations and patterns.
17820 	* TODO: hmm, they should not appear in the set, so remove this.
17821 	*/
17822 	if ((bfacet->type == XML_SCHEMA_FACET_PATTERN) ||
17823 	    (bfacet->type == XML_SCHEMA_FACET_ENUMERATION))
17824 	    continue;
17825 	/*
17826 	* Search for a duplicate facet in the current type.
17827 	*/
17828 	link = type->facetSet;
17829 	/* err = 0; */
17830 	/* fixedErr = 0; */
17831 	while (link != NULL) {
17832 	    facet = link->facet;
17833 	    if (facet->type == bfacet->type) {
17834 		switch (facet->type) {
17835 		    case XML_SCHEMA_FACET_WHITESPACE:
17836 			/*
17837 			* The whitespace must be stronger.
17838 			*/
17839 			if (facet->whitespace < bfacet->whitespace) {
17840 			    FACET_RESTR_ERR(facet,
17841 				"The 'whitespace' value has to be equal to "
17842 				"or stronger than the 'whitespace' value of "
17843 				"the base type")
17844 			}
17845 			if ((bfacet->fixed) &&
17846 			    (facet->whitespace != bfacet->whitespace)) {
17847 			    FACET_RESTR_FIXED_ERR(facet)
17848 			}
17849 			break;
17850 		    default:
17851 			break;
17852 		}
17853 		/* Duplicate found. */
17854 		break;
17855 	    }
17856 	    link = link->next;
17857 	}
17858 	/*
17859 	* If no duplicate was found: add the base types's facet
17860 	* to the set.
17861 	*/
17862 	if (link == NULL) {
17863 	    link = (xmlSchemaFacetLinkPtr)
17864 		xmlMalloc(sizeof(xmlSchemaFacetLink));
17865 	    if (link == NULL) {
17866 		xmlSchemaPErrMemory(pctxt,
17867 		    "deriving facets, creating a facet link", NULL);
17868 		return (-1);
17869 	    }
17870 	    link->facet = cur->facet;
17871 	    link->next = NULL;
17872 	    if (last == NULL)
17873 		type->facetSet = link;
17874 	    else
17875 		last->next = link;
17876 	    last = link;
17877 	}
17878 
17879     }
17880 
17881     return (0);
17882 internal_error:
17883     PERROR_INT("xmlSchemaDeriveAndValidateFacets",
17884 	"an error occurred");
17885     return (-1);
17886 }
17887 
17888 static int
xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)17889 xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,
17890 					     xmlSchemaTypePtr type)
17891 {
17892     xmlSchemaTypeLinkPtr link, lastLink, prevLink, subLink, newLink;
17893     /*
17894     * The actual value is then formed by replacing any union type
17895     * definition in the `explicit members` with the members of their
17896     * {member type definitions}, in order.
17897     *
17898     * TODO: There's a bug entry at
17899     * "http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0287.html"
17900     * which indicates that we'll keep the union types the future.
17901     */
17902     link = type->memberTypes;
17903     while (link != NULL) {
17904 
17905 	if (WXS_IS_TYPE_NOT_FIXED(link->type))
17906 	    xmlSchemaTypeFixup(link->type, ACTXT_CAST pctxt);
17907 
17908 	if (WXS_IS_UNION(link->type)) {
17909 	    subLink = xmlSchemaGetUnionSimpleTypeMemberTypes(link->type);
17910 	    if (subLink != NULL) {
17911 		link->type = subLink->type;
17912 		if (subLink->next != NULL) {
17913 		    lastLink = link->next;
17914 		    subLink = subLink->next;
17915 		    prevLink = link;
17916 		    while (subLink != NULL) {
17917 			newLink = (xmlSchemaTypeLinkPtr)
17918 			    xmlMalloc(sizeof(xmlSchemaTypeLink));
17919 			if (newLink == NULL) {
17920 			    xmlSchemaPErrMemory(pctxt, "allocating a type link",
17921 				NULL);
17922 			    return (-1);
17923 			}
17924 			newLink->type = subLink->type;
17925 			prevLink->next = newLink;
17926 			prevLink = newLink;
17927 			newLink->next = lastLink;
17928 
17929 			subLink = subLink->next;
17930 		    }
17931 		}
17932 	    }
17933 	}
17934 	link = link->next;
17935     }
17936     return (0);
17937 }
17938 
17939 static void
xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type)17940 xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type)
17941 {
17942     int has = 0, needVal = 0, normVal = 0;
17943 
17944     has	= (type->baseType->flags & XML_SCHEMAS_TYPE_HAS_FACETS) ? 1 : 0;
17945     if (has) {
17946 	needVal = (type->baseType->flags &
17947 	    XML_SCHEMAS_TYPE_FACETSNEEDVALUE) ? 1 : 0;
17948 	normVal = (type->baseType->flags &
17949 	    XML_SCHEMAS_TYPE_NORMVALUENEEDED) ? 1 : 0;
17950     }
17951     if (type->facets != NULL) {
17952 	xmlSchemaFacetPtr fac;
17953 
17954 	for (fac = type->facets; fac != NULL; fac = fac->next) {
17955 	    switch (fac->type) {
17956 		case XML_SCHEMA_FACET_WHITESPACE:
17957 		    break;
17958 		case XML_SCHEMA_FACET_PATTERN:
17959 		    normVal = 1;
17960 		    has = 1;
17961 		    break;
17962 		case XML_SCHEMA_FACET_ENUMERATION:
17963 		    needVal = 1;
17964 		    normVal = 1;
17965 		    has = 1;
17966 		    break;
17967 		default:
17968 		    has = 1;
17969 		    break;
17970 	    }
17971 	}
17972     }
17973     if (normVal)
17974 	type->flags |= XML_SCHEMAS_TYPE_NORMVALUENEEDED;
17975     if (needVal)
17976 	type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17977     if (has)
17978 	type->flags |= XML_SCHEMAS_TYPE_HAS_FACETS;
17979 
17980     if (has && (! needVal) && WXS_IS_ATOMIC(type)) {
17981 	xmlSchemaTypePtr prim = xmlSchemaGetPrimitiveType(type);
17982 	/*
17983 	* OPTIMIZE VAL TODO: Some facets need a computed value.
17984 	*/
17985 	if ((prim->builtInType != XML_SCHEMAS_ANYSIMPLETYPE) &&
17986 	    (prim->builtInType != XML_SCHEMAS_STRING)) {
17987 	    type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17988 	}
17989     }
17990 }
17991 
17992 static int
xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type)17993 xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type)
17994 {
17995 
17996 
17997     /*
17998     * Evaluate the whitespace-facet value.
17999     */
18000     if (WXS_IS_LIST(type)) {
18001 	type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
18002 	return (0);
18003     } else if (WXS_IS_UNION(type))
18004 	return (0);
18005 
18006     if (type->facetSet != NULL) {
18007 	xmlSchemaFacetLinkPtr lin;
18008 
18009 	for (lin = type->facetSet; lin != NULL; lin = lin->next) {
18010 	    if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
18011 		switch (lin->facet->whitespace) {
18012 		case XML_SCHEMAS_FACET_PRESERVE:
18013 		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
18014 		    break;
18015 		case XML_SCHEMAS_FACET_REPLACE:
18016 		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
18017 		    break;
18018 		case XML_SCHEMAS_FACET_COLLAPSE:
18019 		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
18020 		    break;
18021 		default:
18022 		    return (-1);
18023 		}
18024 		return (0);
18025 	    }
18026 	}
18027     }
18028     /*
18029     * For all `atomic` datatypes other than string (and types `derived`
18030     * by `restriction` from it) the value of whiteSpace is fixed to
18031     * collapse
18032     */
18033     {
18034 	xmlSchemaTypePtr anc;
18035 
18036 	for (anc = type->baseType; anc != NULL &&
18037 		anc->builtInType != XML_SCHEMAS_ANYTYPE;
18038 		anc = anc->baseType) {
18039 
18040 	    if (anc->type == XML_SCHEMA_TYPE_BASIC) {
18041 		if (anc->builtInType == XML_SCHEMAS_NORMSTRING) {
18042 		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
18043 
18044 		} else if ((anc->builtInType == XML_SCHEMAS_STRING) ||
18045 		    (anc->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)) {
18046 		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
18047 
18048 		} else
18049 		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
18050 		break;
18051 	    }
18052 	}
18053     }
18054     return (0);
18055 }
18056 
18057 static int
xmlSchemaFixupSimpleTypeStageOne(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)18058 xmlSchemaFixupSimpleTypeStageOne(xmlSchemaParserCtxtPtr pctxt,
18059 			  xmlSchemaTypePtr type)
18060 {
18061     if (type->type != XML_SCHEMA_TYPE_SIMPLE)
18062 	return(0);
18063     if (! WXS_IS_TYPE_NOT_FIXED_1(type))
18064 	return(0);
18065     type->flags |= XML_SCHEMAS_TYPE_FIXUP_1;
18066 
18067     if (WXS_IS_LIST(type)) {
18068 	/*
18069 	* Corresponds to <simpleType><list>...
18070 	*/
18071 	if (type->subtypes == NULL) {
18072 	    /*
18073 	    * This one is really needed, so get out.
18074 	    */
18075 	    PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
18076 		"list type has no item-type assigned");
18077 	    return(-1);
18078 	}
18079     } else if (WXS_IS_UNION(type)) {
18080 	/*
18081 	* Corresponds to <simpleType><union>...
18082 	*/
18083 	if (type->memberTypes == NULL) {
18084 	    /*
18085 	    * This one is really needed, so get out.
18086 	    */
18087 	    PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
18088 		"union type has no member-types assigned");
18089 	    return(-1);
18090 	}
18091     } else {
18092 	/*
18093 	* Corresponds to <simpleType><restriction>...
18094 	*/
18095 	if (type->baseType == NULL) {
18096 	    PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
18097 		"type has no base-type assigned");
18098 	    return(-1);
18099 	}
18100 	if (WXS_IS_TYPE_NOT_FIXED_1(type->baseType))
18101 	    if (xmlSchemaFixupSimpleTypeStageOne(pctxt, type->baseType) == -1)
18102 		return(-1);
18103 	/*
18104 	* Variety
18105 	* If the <restriction> alternative is chosen, then the
18106 	* {variety} of the {base type definition}.
18107 	*/
18108 	if (WXS_IS_ATOMIC(type->baseType))
18109 	    type->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
18110 	else if (WXS_IS_LIST(type->baseType)) {
18111 	    type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
18112 	    /*
18113 	    * Inherit the itemType.
18114 	    */
18115 	    type->subtypes = type->baseType->subtypes;
18116 	} else if (WXS_IS_UNION(type->baseType)) {
18117 	    type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
18118 	    /*
18119 	    * NOTE that we won't assign the memberTypes of the base,
18120 	    * since this will make trouble when freeing them; we will
18121 	    * use a lookup function to access them instead.
18122 	    */
18123 	}
18124     }
18125     return(0);
18126 }
18127 
18128 #ifdef DEBUG_TYPE
18129 static void
xmlSchemaDebugFixedType(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)18130 xmlSchemaDebugFixedType(xmlSchemaParserCtxtPtr pctxt,
18131 		       xmlSchemaTypePtr type)
18132 {
18133     if (type->node != NULL) {
18134         xmlGenericError(xmlGenericErrorContext,
18135                         "Type of %s : %s:%d :", name,
18136                         type->node->doc->URL,
18137                         xmlGetLineNo(type->node));
18138     } else {
18139         xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
18140     }
18141     if ((WXS_IS_SIMPLE(type)) || (WXS_IS_COMPLEX(type))) {
18142 	switch (type->contentType) {
18143 	    case XML_SCHEMA_CONTENT_SIMPLE:
18144 		xmlGenericError(xmlGenericErrorContext, "simple\n");
18145 		break;
18146 	    case XML_SCHEMA_CONTENT_ELEMENTS:
18147 		xmlGenericError(xmlGenericErrorContext, "elements\n");
18148 		break;
18149 	    case XML_SCHEMA_CONTENT_UNKNOWN:
18150 		xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
18151 		break;
18152 	    case XML_SCHEMA_CONTENT_EMPTY:
18153 		xmlGenericError(xmlGenericErrorContext, "empty\n");
18154 		break;
18155 	    case XML_SCHEMA_CONTENT_MIXED:
18156 		if (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr)
18157 		    type->subtypes))
18158 		    xmlGenericError(xmlGenericErrorContext,
18159 			"mixed as emptiable particle\n");
18160 		else
18161 		    xmlGenericError(xmlGenericErrorContext, "mixed\n");
18162 		break;
18163 		/* Removed, since not used. */
18164 		/*
18165 		case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
18166 		xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
18167 		break;
18168 		*/
18169 	    case XML_SCHEMA_CONTENT_BASIC:
18170 		xmlGenericError(xmlGenericErrorContext, "basic\n");
18171 		break;
18172 	    default:
18173 		xmlGenericError(xmlGenericErrorContext,
18174 		    "not registered !!!\n");
18175 		break;
18176 	}
18177     }
18178 }
18179 #endif
18180 
18181 /*
18182 * 3.14.6 Constraints on Simple Type Definition Schema Components
18183 */
18184 static int
xmlSchemaFixupSimpleTypeStageTwo(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)18185 xmlSchemaFixupSimpleTypeStageTwo(xmlSchemaParserCtxtPtr pctxt,
18186 				 xmlSchemaTypePtr type)
18187 {
18188     int res, olderrs = pctxt->nberrors;
18189 
18190     if (type->type != XML_SCHEMA_TYPE_SIMPLE)
18191 	return(-1);
18192 
18193     if (! WXS_IS_TYPE_NOT_FIXED(type))
18194 	return(0);
18195 
18196     type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
18197     type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
18198 
18199     if (type->baseType == NULL) {
18200 	PERROR_INT("xmlSchemaFixupSimpleTypeStageTwo",
18201 	    "missing baseType");
18202 	goto exit_failure;
18203     }
18204     if (WXS_IS_TYPE_NOT_FIXED(type->baseType))
18205 	xmlSchemaTypeFixup(type->baseType, ACTXT_CAST pctxt);
18206     /*
18207     * If a member type of a union is a union itself, we need to substitute
18208     * that member type for its member types.
18209     * NOTE that this might change in WXS 1.1; i.e. we will keep the union
18210     * types in WXS 1.1.
18211     */
18212     if ((type->memberTypes != NULL) &&
18213 	(xmlSchemaFinishMemberTypeDefinitionsProperty(pctxt, type) == -1))
18214 	return(-1);
18215     /*
18216     * SPEC src-simple-type 1
18217     * "The corresponding simple type definition, if any, must satisfy
18218     * the conditions set out in Constraints on Simple Type Definition
18219     * Schema Components ($3.14.6)."
18220     */
18221     /*
18222     * Schema Component Constraint: Simple Type Definition Properties Correct
18223     * (st-props-correct)
18224     */
18225     res = xmlSchemaCheckSTPropsCorrect(pctxt, type);
18226     HFAILURE HERROR
18227     /*
18228     * Schema Component Constraint: Derivation Valid (Restriction, Simple)
18229     * (cos-st-restricts)
18230     */
18231     res = xmlSchemaCheckCOSSTRestricts(pctxt, type);
18232     HFAILURE HERROR
18233     /*
18234     * TODO: Removed the error report, since it got annoying to get an
18235     * extra error report, if anything failed until now.
18236     * Enable this if needed.
18237     *
18238     * xmlSchemaPErr(ctxt, type->node,
18239     *    XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
18240     *    "Simple type '%s' does not satisfy the constraints "
18241     *    "on simple type definitions.\n",
18242     *    type->name, NULL);
18243     */
18244     /*
18245     * Schema Component Constraint: Simple Type Restriction (Facets)
18246     * (st-restrict-facets)
18247     */
18248     res = xmlSchemaCheckFacetValues(type, pctxt);
18249     HFAILURE HERROR
18250     if ((type->facetSet != NULL) ||
18251 	(type->baseType->facetSet != NULL)) {
18252 	res = xmlSchemaDeriveAndValidateFacets(pctxt, type);
18253 	HFAILURE HERROR
18254     }
18255     /*
18256     * Whitespace value.
18257     */
18258     res = xmlSchemaTypeFixupWhitespace(type);
18259     HFAILURE HERROR
18260     xmlSchemaTypeFixupOptimFacets(type);
18261 
18262 exit_error:
18263 #ifdef DEBUG_TYPE
18264     xmlSchemaDebugFixedType(pctxt, type);
18265 #endif
18266     if (olderrs != pctxt->nberrors)
18267 	return(pctxt->err);
18268     return(0);
18269 
18270 exit_failure:
18271 #ifdef DEBUG_TYPE
18272     xmlSchemaDebugFixedType(pctxt, type);
18273 #endif
18274     return(-1);
18275 }
18276 
18277 static int
xmlSchemaFixupComplexType(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)18278 xmlSchemaFixupComplexType(xmlSchemaParserCtxtPtr pctxt,
18279 			  xmlSchemaTypePtr type)
18280 {
18281     int res = 0, olderrs = pctxt->nberrors;
18282     xmlSchemaTypePtr baseType = type->baseType;
18283 
18284     if (! WXS_IS_TYPE_NOT_FIXED(type))
18285 	return(0);
18286     type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
18287     if (baseType == NULL) {
18288 	PERROR_INT("xmlSchemaFixupComplexType",
18289 	    "missing baseType");
18290 	goto exit_failure;
18291     }
18292     /*
18293     * Fixup the base type.
18294     */
18295     if (WXS_IS_TYPE_NOT_FIXED(baseType))
18296 	xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt);
18297     if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) {
18298 	/*
18299 	* Skip fixup if the base type is invalid.
18300 	* TODO: Generate a warning!
18301 	*/
18302 	return(0);
18303     }
18304     /*
18305     * This basically checks if the base type can be derived.
18306     */
18307     res = xmlSchemaCheckSRCCT(pctxt, type);
18308     HFAILURE HERROR
18309     /*
18310     * Fixup the content type.
18311     */
18312     if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) {
18313 	/*
18314 	* Corresponds to <complexType><simpleContent>...
18315 	*/
18316 	if ((WXS_IS_COMPLEX(baseType)) &&
18317 	    (baseType->contentTypeDef != NULL) &&
18318 	    (WXS_IS_RESTRICTION(type))) {
18319 	    xmlSchemaTypePtr contentBase, content;
18320 #ifdef ENABLE_NAMED_LOCALS
18321 	    char buf[30];
18322 	    const xmlChar *tmpname;
18323 #endif
18324 	    /*
18325 	    * SPEC (1) If <restriction> + base type is <complexType>,
18326 	    * "whose own {content type} is a simple type..."
18327 	    */
18328 	    if (type->contentTypeDef != NULL) {
18329 		/*
18330 		* SPEC (1.1) "the simple type definition corresponding to the
18331 		* <simpleType> among the [children] of <restriction> if there
18332 		* is one;"
18333 		* Note that this "<simpleType> among the [children]" was put
18334 		* into ->contentTypeDef during parsing.
18335 		*/
18336 		contentBase = type->contentTypeDef;
18337 		type->contentTypeDef = NULL;
18338 	    } else {
18339 		/*
18340 		* (1.2) "...otherwise (<restriction> has no <simpleType>
18341 		* among its [children]), the simple type definition which
18342 		* is the {content type} of the ... base type."
18343 		*/
18344 		contentBase = baseType->contentTypeDef;
18345 	    }
18346 	    /*
18347 	    * SPEC
18348 	    * "... a simple type definition which restricts the simple
18349 	    * type definition identified in clause 1.1 or clause 1.2
18350 	    * with a set of facet components"
18351 	    *
18352 	    * Create the anonymous simple type, which will be the content
18353 	    * type of the complex type.
18354 	    */
18355 #ifdef ENABLE_NAMED_LOCALS
18356 	    snprintf(buf, 29, "#scST%d", ++(pctxt->counter));
18357 	    tmpname = xmlDictLookup(pctxt->dict, BAD_CAST buf, -1);
18358 	    content = xmlSchemaAddType(pctxt, pctxt->schema,
18359 		XML_SCHEMA_TYPE_SIMPLE, tmpname, type->targetNamespace,
18360 		type->node, 0);
18361 #else
18362 	    content = xmlSchemaAddType(pctxt, pctxt->schema,
18363 		XML_SCHEMA_TYPE_SIMPLE, NULL, type->targetNamespace,
18364 		type->node, 0);
18365 #endif
18366 	    if (content == NULL)
18367 		goto exit_failure;
18368 	    /*
18369 	    * We will use the same node as for the <complexType>
18370 	    * to have it somehow anchored in the schema doc.
18371 	    */
18372 	    content->type = XML_SCHEMA_TYPE_SIMPLE;
18373 	    content->baseType = contentBase;
18374 	    /*
18375 	    * Move the facets, previously anchored on the
18376 	    * complexType during parsing.
18377 	    */
18378 	    content->facets = type->facets;
18379 	    type->facets = NULL;
18380 	    content->facetSet = type->facetSet;
18381 	    type->facetSet = NULL;
18382 
18383 	    type->contentTypeDef = content;
18384 	    if (WXS_IS_TYPE_NOT_FIXED(contentBase))
18385 		xmlSchemaTypeFixup(contentBase, ACTXT_CAST pctxt);
18386 	    /*
18387 	    * Fixup the newly created type. We don't need to check
18388 	    * for circularity here.
18389 	    */
18390 	    res = xmlSchemaFixupSimpleTypeStageOne(pctxt, content);
18391 	    HFAILURE HERROR
18392 	    res = xmlSchemaFixupSimpleTypeStageTwo(pctxt, content);
18393 	    HFAILURE HERROR
18394 
18395 	} else if ((WXS_IS_COMPLEX(baseType)) &&
18396 	    (baseType->contentType == XML_SCHEMA_CONTENT_MIXED) &&
18397 	    (WXS_IS_RESTRICTION(type))) {
18398 	    /*
18399 	    * SPEC (2) If <restriction> + base is a mixed <complexType> with
18400 	    * an emptiable particle, then a simple type definition which
18401 	    * restricts the <restriction>'s <simpleType> child.
18402 	    */
18403 	    if ((type->contentTypeDef == NULL) ||
18404 		(type->contentTypeDef->baseType == NULL)) {
18405 		/*
18406 		* TODO: Check if this ever happens.
18407 		*/
18408 		xmlSchemaPCustomErr(pctxt,
18409 		    XML_SCHEMAP_INTERNAL,
18410 		    WXS_BASIC_CAST type, NULL,
18411 		    "Internal error: xmlSchemaTypeFixup, "
18412 		    "complex type '%s': the <simpleContent><restriction> "
18413 		    "is missing a <simpleType> child, but was not caught "
18414 		    "by xmlSchemaCheckSRCCT()", type->name);
18415 		goto exit_failure;
18416 	    }
18417 	} else if ((WXS_IS_COMPLEX(baseType)) && WXS_IS_EXTENSION(type)) {
18418 	    /*
18419 	    * SPEC (3) If <extension> + base is <complexType> with
18420 	    * <simpleType> content, "...then the {content type} of that
18421 	    * complex type definition"
18422 	    */
18423 	    if (baseType->contentTypeDef == NULL) {
18424 		/*
18425 		* TODO: Check if this ever happens. xmlSchemaCheckSRCCT
18426 		* should have caught this already.
18427 		*/
18428 		xmlSchemaPCustomErr(pctxt,
18429 		    XML_SCHEMAP_INTERNAL,
18430 		    WXS_BASIC_CAST type, NULL,
18431 		    "Internal error: xmlSchemaTypeFixup, "
18432 		    "complex type '%s': the <extension>ed base type is "
18433 		    "a complex type with no simple content type",
18434 		    type->name);
18435 		goto exit_failure;
18436 	    }
18437 	    type->contentTypeDef = baseType->contentTypeDef;
18438 	} else if ((WXS_IS_SIMPLE(baseType)) && WXS_IS_EXTENSION(type)) {
18439 	    /*
18440 	    * SPEC (4) <extension> + base is <simpleType>
18441 	    * "... then that simple type definition"
18442 	    */
18443 	    type->contentTypeDef = baseType;
18444 	} else {
18445 	    /*
18446 	    * TODO: Check if this ever happens.
18447 	    */
18448 	    xmlSchemaPCustomErr(pctxt,
18449 		XML_SCHEMAP_INTERNAL,
18450 		WXS_BASIC_CAST type, NULL,
18451 		"Internal error: xmlSchemaTypeFixup, "
18452 		"complex type '%s' with <simpleContent>: unhandled "
18453 		"derivation case", type->name);
18454 	    goto exit_failure;
18455 	}
18456     } else {
18457 	int dummySequence = 0;
18458 	xmlSchemaParticlePtr particle =
18459 	    (xmlSchemaParticlePtr) type->subtypes;
18460 	/*
18461 	* Corresponds to <complexType><complexContent>...
18462 	*
18463 	* NOTE that the effective mixed was already set during parsing of
18464 	* <complexType> and <complexContent>; its flag value is
18465 	* XML_SCHEMAS_TYPE_MIXED.
18466 	*
18467 	* Compute the "effective content":
18468 	* (2.1.1) + (2.1.2) + (2.1.3)
18469 	*/
18470 	if ((particle == NULL) ||
18471 	    ((particle->type == XML_SCHEMA_TYPE_PARTICLE) &&
18472 	    ((particle->children->type == XML_SCHEMA_TYPE_ALL) ||
18473 	    (particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) ||
18474 	    ((particle->children->type == XML_SCHEMA_TYPE_CHOICE) &&
18475 	    (particle->minOccurs == 0))) &&
18476 	    ( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) {
18477 	    if (type->flags & XML_SCHEMAS_TYPE_MIXED) {
18478 		/*
18479 		* SPEC (2.1.4) "If the `effective mixed` is true, then
18480 		* a particle whose properties are as follows:..."
18481 		*
18482 		* Empty sequence model group with
18483 		* minOccurs/maxOccurs = 1 (i.e. a "particle emptiable").
18484 		* NOTE that we sill assign it the <complexType> node to
18485 		* somehow anchor it in the doc.
18486 		*/
18487 		if ((particle == NULL) ||
18488 		    (particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) {
18489 		    /*
18490 		    * Create the particle.
18491 		    */
18492 		    particle = xmlSchemaAddParticle(pctxt,
18493 			type->node, 1, 1);
18494 		    if (particle == NULL)
18495 			goto exit_failure;
18496 		    /*
18497 		    * Create the model group.
18498 		    */ /* URGENT TODO: avoid adding to pending items. */
18499 		    particle->children = (xmlSchemaTreeItemPtr)
18500 			xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18501 			XML_SCHEMA_TYPE_SEQUENCE, type->node);
18502 		    if (particle->children == NULL)
18503 			goto exit_failure;
18504 
18505 		    type->subtypes = (xmlSchemaTypePtr) particle;
18506 		}
18507 		dummySequence = 1;
18508 		type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18509 	    } else {
18510 		/*
18511 		* SPEC (2.1.5) "otherwise empty"
18512 		*/
18513 		type->contentType = XML_SCHEMA_CONTENT_EMPTY;
18514 	    }
18515 	} else {
18516 	    /*
18517 	    * SPEC (2.2) "otherwise the particle corresponding to the
18518 	    * <all>, <choice>, <group> or <sequence> among the
18519 	    * [children]."
18520 	    */
18521 	    type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18522 	}
18523 	/*
18524 	* Compute the "content type".
18525 	*/
18526 	if (WXS_IS_RESTRICTION(type)) {
18527 	    /*
18528 	    * SPEC (3.1) "If <restriction>..."
18529 	    * (3.1.1) + (3.1.2) */
18530 	    if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) {
18531 		if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18532 		    type->contentType = XML_SCHEMA_CONTENT_MIXED;
18533 	    }
18534 	} else {
18535 	    /*
18536 	    * SPEC (3.2) "If <extension>..."
18537 	    */
18538 	    if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18539 		/*
18540 		* SPEC (3.2.1)
18541 		* "If the `effective content` is empty, then the
18542 		*  {content type} of the [...] base ..."
18543 		*/
18544 		type->contentType = baseType->contentType;
18545 		type->subtypes = baseType->subtypes;
18546 		/*
18547 		* Fixes bug #347316:
18548 		* This is the case when the base type has a simple
18549 		* type definition as content.
18550 		*/
18551 		type->contentTypeDef = baseType->contentTypeDef;
18552 		/*
18553 		* NOTE that the effective mixed is ignored here.
18554 		*/
18555 	    } else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18556 		/*
18557 		* SPEC (3.2.2)
18558 		*/
18559 		if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18560 		    type->contentType = XML_SCHEMA_CONTENT_MIXED;
18561 	    } else {
18562 		/*
18563 		* SPEC (3.2.3)
18564 		*/
18565 		if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18566 		    type->contentType = XML_SCHEMA_CONTENT_MIXED;
18567 		    /*
18568 		    * "A model group whose {compositor} is sequence and whose
18569 		    * {particles} are..."
18570 		    */
18571 		if ((WXS_TYPE_PARTICLE(type) != NULL) &&
18572 		    (WXS_TYPE_PARTICLE_TERM(type) != NULL) &&
18573 		    ((WXS_TYPE_PARTICLE_TERM(type))->type ==
18574 			XML_SCHEMA_TYPE_ALL))
18575 		{
18576 		    /*
18577 		    * SPEC cos-all-limited (1)
18578 		    */
18579 		    xmlSchemaCustomErr(ACTXT_CAST pctxt,
18580 			/* TODO: error code */
18581 			XML_SCHEMAP_COS_ALL_LIMITED,
18582 			WXS_ITEM_NODE(type), NULL,
18583 			"The type has an 'all' model group in its "
18584 			"{content type} and thus cannot be derived from "
18585 			"a non-empty type, since this would produce a "
18586 			"'sequence' model group containing the 'all' "
18587 			"model group; 'all' model groups are not "
18588 			"allowed to appear inside other model groups",
18589 			NULL, NULL);
18590 
18591 		} else if ((WXS_TYPE_PARTICLE(baseType) != NULL) &&
18592 		    (WXS_TYPE_PARTICLE_TERM(baseType) != NULL) &&
18593 		    ((WXS_TYPE_PARTICLE_TERM(baseType))->type ==
18594 			XML_SCHEMA_TYPE_ALL))
18595 		{
18596 		    /*
18597 		    * SPEC cos-all-limited (1)
18598 		    */
18599 		    xmlSchemaCustomErr(ACTXT_CAST pctxt,
18600 			/* TODO: error code */
18601 			XML_SCHEMAP_COS_ALL_LIMITED,
18602 			WXS_ITEM_NODE(type), NULL,
18603 			"A type cannot be derived by extension from a type "
18604 			"which has an 'all' model group in its "
18605 			"{content type}, since this would produce a "
18606 			"'sequence' model group containing the 'all' "
18607 			"model group; 'all' model groups are not "
18608 			"allowed to appear inside other model groups",
18609 			NULL, NULL);
18610 
18611 		} else if (! dummySequence) {
18612 		    xmlSchemaTreeItemPtr effectiveContent =
18613 			(xmlSchemaTreeItemPtr) type->subtypes;
18614 		    /*
18615 		    * Create the particle.
18616 		    */
18617 		    particle = xmlSchemaAddParticle(pctxt,
18618 			type->node, 1, 1);
18619 		    if (particle == NULL)
18620 			goto exit_failure;
18621 		    /*
18622 		    * Create the "sequence" model group.
18623 		    */
18624 		    particle->children = (xmlSchemaTreeItemPtr)
18625 			xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18626 			XML_SCHEMA_TYPE_SEQUENCE, type->node);
18627 		    if (particle->children == NULL)
18628 			goto exit_failure;
18629 		    WXS_TYPE_CONTENTTYPE(type) = (xmlSchemaTypePtr) particle;
18630 		    /*
18631 		    * SPEC "the particle of the {content type} of
18632 		    * the ... base ..."
18633 		    * Create a duplicate of the base type's particle
18634 		    * and assign its "term" to it.
18635 		    */
18636 		    particle->children->children =
18637 			(xmlSchemaTreeItemPtr) xmlSchemaAddParticle(pctxt,
18638 			type->node,
18639 			((xmlSchemaParticlePtr) baseType->subtypes)->minOccurs,
18640 			((xmlSchemaParticlePtr) baseType->subtypes)->maxOccurs);
18641 		    if (particle->children->children == NULL)
18642 			goto exit_failure;
18643 		    particle = (xmlSchemaParticlePtr)
18644 			particle->children->children;
18645 		    particle->children =
18646 			((xmlSchemaParticlePtr) baseType->subtypes)->children;
18647 		    /*
18648 		    * SPEC "followed by the `effective content`."
18649 		    */
18650 		    particle->next = effectiveContent;
18651 		    /*
18652 		    * This all will result in:
18653 		    * new-particle
18654 		    *   --> new-sequence(
18655 		    *         new-particle
18656 		    *           --> base-model,
18657 		    *         this-particle
18658 		    *	        --> this-model
18659 		    *	    )
18660 		    */
18661 		} else {
18662 		    /*
18663 		    * This is the case when there is already an empty
18664 		    * <sequence> with minOccurs==maxOccurs==1.
18665 		    * Just add the base types's content type.
18666 		    * NOTE that, although we miss to add an intermediate
18667 		    * <sequence>, this should produce no difference to
18668 		    * neither the regex compilation of the content model,
18669 		    * nor to the complex type constraints.
18670 		    */
18671 		    particle->children->children =
18672 			(xmlSchemaTreeItemPtr) baseType->subtypes;
18673 		}
18674 	    }
18675 	}
18676     }
18677     /*
18678     * Now fixup attribute uses:
18679     *   - expand attr. group references
18680     *     - intersect attribute wildcards
18681     *   - inherit attribute uses of the base type
18682     *   - inherit or union attr. wildcards if extending
18683     *   - apply attr. use prohibitions if restricting
18684     */
18685     res = xmlSchemaFixupTypeAttributeUses(pctxt, type);
18686     HFAILURE HERROR
18687     /*
18688     * Apply the complex type component constraints; this will not
18689     * check attributes, since this is done in
18690     * xmlSchemaFixupTypeAttributeUses().
18691     */
18692     res = xmlSchemaCheckCTComponent(pctxt, type);
18693     HFAILURE HERROR
18694 
18695 #ifdef DEBUG_TYPE
18696     xmlSchemaDebugFixedType(pctxt, type);
18697 #endif
18698     if (olderrs != pctxt->nberrors)
18699 	return(pctxt->err);
18700     else
18701 	return(0);
18702 
18703 exit_error:
18704     type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18705 #ifdef DEBUG_TYPE
18706     xmlSchemaDebugFixedType(pctxt, type);
18707 #endif
18708     return(pctxt->err);
18709 
18710 exit_failure:
18711     type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18712 #ifdef DEBUG_TYPE
18713     xmlSchemaDebugFixedType(pctxt, type);
18714 #endif
18715     return(-1);
18716 }
18717 
18718 
18719 /**
18720  * xmlSchemaTypeFixup:
18721  * @typeDecl:  the schema type definition
18722  * @ctxt:  the schema parser context
18723  *
18724  * Fixes the content model of the type.
18725  * URGENT TODO: We need an int result!
18726  */
18727 static int
xmlSchemaTypeFixup(xmlSchemaTypePtr type,xmlSchemaAbstractCtxtPtr actxt)18728 xmlSchemaTypeFixup(xmlSchemaTypePtr type,
18729                    xmlSchemaAbstractCtxtPtr actxt)
18730 {
18731     if (type == NULL)
18732         return(0);
18733     if (actxt->type != XML_SCHEMA_CTXT_PARSER) {
18734 	AERROR_INT("xmlSchemaTypeFixup",
18735 	    "this function needs a parser context");
18736 	return(-1);
18737     }
18738     if (! WXS_IS_TYPE_NOT_FIXED(type))
18739 	return(0);
18740     if (type->type == XML_SCHEMA_TYPE_COMPLEX)
18741 	return(xmlSchemaFixupComplexType(PCTXT_CAST actxt, type));
18742     else if (type->type == XML_SCHEMA_TYPE_SIMPLE)
18743 	return(xmlSchemaFixupSimpleTypeStageTwo(PCTXT_CAST actxt, type));
18744     return(0);
18745 }
18746 
18747 /**
18748  * xmlSchemaCheckFacet:
18749  * @facet:  the facet
18750  * @typeDecl:  the schema type definition
18751  * @pctxt:  the schema parser context or NULL
18752  * @name: the optional name of the type
18753  *
18754  * Checks and computes the values of facets.
18755  *
18756  * Returns 0 if valid, a positive error code if not valid and
18757  *         -1 in case of an internal or API error.
18758  */
18759 int
xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,xmlSchemaTypePtr typeDecl,xmlSchemaParserCtxtPtr pctxt,const xmlChar * name ATTRIBUTE_UNUSED)18760 xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
18761                     xmlSchemaTypePtr typeDecl,
18762                     xmlSchemaParserCtxtPtr pctxt,
18763 		    const xmlChar * name ATTRIBUTE_UNUSED)
18764 {
18765     int ret = 0, ctxtGiven;
18766 
18767     if ((facet == NULL) || (typeDecl == NULL))
18768         return(-1);
18769     /*
18770     * TODO: will the parser context be given if used from
18771     * the relaxNG module?
18772     */
18773     if (pctxt == NULL)
18774 	ctxtGiven = 0;
18775     else
18776 	ctxtGiven = 1;
18777 
18778     switch (facet->type) {
18779         case XML_SCHEMA_FACET_MININCLUSIVE:
18780         case XML_SCHEMA_FACET_MINEXCLUSIVE:
18781         case XML_SCHEMA_FACET_MAXINCLUSIVE:
18782         case XML_SCHEMA_FACET_MAXEXCLUSIVE:
18783 	case XML_SCHEMA_FACET_ENUMERATION: {
18784                 /*
18785                  * Okay we need to validate the value
18786                  * at that point.
18787                  */
18788 		xmlSchemaTypePtr base;
18789 
18790 		/* 4.3.5.5 Constraints on enumeration Schema Components
18791 		* Schema Component Constraint: enumeration valid restriction
18792 		* It is an `error` if any member of {value} is not in the
18793 		* `value space` of {base type definition}.
18794 		*
18795 		* minInclusive, maxInclusive, minExclusive, maxExclusive:
18796 		* The value `must` be in the
18797 		* `value space` of the `base type`.
18798 		*/
18799 		/*
18800 		* This function is intended to deliver a compiled value
18801 		* on the facet. In this implementation of XML Schemata the
18802 		* type holding a facet, won't be a built-in type.
18803 		* Thus to ensure that other API
18804 		* calls (relaxng) do work, if the given type is a built-in
18805 		* type, we will assume that the given built-in type *is
18806 		* already* the base type.
18807 		*/
18808 		if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
18809 		    base = typeDecl->baseType;
18810 		    if (base == NULL) {
18811 			PERROR_INT("xmlSchemaCheckFacet",
18812 			    "a type user derived type has no base type");
18813 			return (-1);
18814 		    }
18815 		} else
18816 		    base = typeDecl;
18817 
18818 		if (! ctxtGiven) {
18819 		    /*
18820 		    * A context is needed if called from RelaxNG.
18821 		    */
18822 		    pctxt = xmlSchemaNewParserCtxt("*");
18823 		    if (pctxt == NULL)
18824 			return (-1);
18825 		}
18826 		/*
18827 		* NOTE: This call does not check the content nodes,
18828 		* since they are not available:
18829 		* facet->node is just the node holding the facet
18830 		* definition, *not* the attribute holding the *value*
18831 		* of the facet.
18832 		*/
18833 		ret = xmlSchemaVCheckCVCSimpleType(
18834 		    ACTXT_CAST pctxt, facet->node, base,
18835 		    facet->value, &(facet->val), 1, 1, 0);
18836                 if (ret != 0) {
18837 		    if (ret < 0) {
18838 			/* No error message for RelaxNG. */
18839 			if (ctxtGiven) {
18840 			    xmlSchemaCustomErr(ACTXT_CAST pctxt,
18841 				XML_SCHEMAP_INTERNAL, facet->node, NULL,
18842 				"Internal error: xmlSchemaCheckFacet, "
18843 				"failed to validate the value '%s' of the "
18844 				"facet '%s' against the base type",
18845 				facet->value, xmlSchemaFacetTypeToString(facet->type));
18846 			}
18847 			goto internal_error;
18848 		    }
18849 		    ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18850 		    /* No error message for RelaxNG. */
18851 		    if (ctxtGiven) {
18852 			xmlChar *str = NULL;
18853 
18854 			xmlSchemaCustomErr(ACTXT_CAST pctxt,
18855 			    ret, facet->node, WXS_BASIC_CAST facet,
18856 			    "The value '%s' of the facet does not validate "
18857 			    "against the base type '%s'",
18858 			    facet->value,
18859 			    xmlSchemaFormatQName(&str,
18860 				base->targetNamespace, base->name));
18861 			FREE_AND_NULL(str);
18862 		    }
18863 		    goto exit;
18864                 } else if (facet->val == NULL) {
18865 		    if (ctxtGiven) {
18866 			PERROR_INT("xmlSchemaCheckFacet",
18867 			    "value was not computed");
18868 		    }
18869 		    TODO
18870 		}
18871                 break;
18872             }
18873         case XML_SCHEMA_FACET_PATTERN:
18874             facet->regexp = xmlRegexpCompile(facet->value);
18875             if (facet->regexp == NULL) {
18876 		ret = XML_SCHEMAP_REGEXP_INVALID;
18877 		/* No error message for RelaxNG. */
18878 		if (ctxtGiven) {
18879 		    xmlSchemaCustomErr(ACTXT_CAST pctxt,
18880 			ret, facet->node, WXS_BASIC_CAST typeDecl,
18881 			"The value '%s' of the facet 'pattern' is not a "
18882 			"valid regular expression",
18883 			facet->value, NULL);
18884 		}
18885             }
18886             break;
18887         case XML_SCHEMA_FACET_TOTALDIGITS:
18888         case XML_SCHEMA_FACET_FRACTIONDIGITS:
18889         case XML_SCHEMA_FACET_LENGTH:
18890         case XML_SCHEMA_FACET_MAXLENGTH:
18891         case XML_SCHEMA_FACET_MINLENGTH:
18892 
18893 	    if (facet->type == XML_SCHEMA_FACET_TOTALDIGITS) {
18894 		ret = xmlSchemaValidatePredefinedType(
18895 		    xmlSchemaGetBuiltInType(XML_SCHEMAS_PINTEGER),
18896 		    facet->value, &(facet->val));
18897 	    } else {
18898 		ret = xmlSchemaValidatePredefinedType(
18899 		    xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER),
18900 		    facet->value, &(facet->val));
18901 	    }
18902 	    if (ret != 0) {
18903 		if (ret < 0) {
18904 		    /* No error message for RelaxNG. */
18905 		    if (ctxtGiven) {
18906 			PERROR_INT("xmlSchemaCheckFacet",
18907 			    "validating facet value");
18908 		    }
18909 		    goto internal_error;
18910 		}
18911 		ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18912 		/* No error message for RelaxNG. */
18913 		if (ctxtGiven) {
18914 		    /* error code */
18915 		    xmlSchemaCustomErr4(ACTXT_CAST pctxt,
18916 			ret, facet->node, WXS_BASIC_CAST typeDecl,
18917 			"The value '%s' of the facet '%s' is not a valid '%s'",
18918 			facet->value,
18919 			xmlSchemaFacetTypeToString(facet->type),
18920 			(facet->type != XML_SCHEMA_FACET_TOTALDIGITS) ?
18921 			    BAD_CAST "nonNegativeInteger" :
18922 			    BAD_CAST "positiveInteger",
18923 			NULL);
18924 		}
18925 	    }
18926 	    break;
18927 
18928         case XML_SCHEMA_FACET_WHITESPACE:{
18929                 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
18930                     facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
18931                 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
18932                     facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
18933                 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
18934                     facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
18935                 } else {
18936 		    ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18937                     /* No error message for RelaxNG. */
18938 		    if (ctxtGiven) {
18939 			/* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */
18940 			xmlSchemaCustomErr(ACTXT_CAST pctxt,
18941 			    ret, facet->node, WXS_BASIC_CAST typeDecl,
18942 			    "The value '%s' of the facet 'whitespace' is not "
18943 			    "valid", facet->value, NULL);
18944                     }
18945                 }
18946             }
18947         default:
18948             break;
18949     }
18950 exit:
18951     if ((! ctxtGiven) && (pctxt != NULL))
18952 	xmlSchemaFreeParserCtxt(pctxt);
18953     return (ret);
18954 internal_error:
18955     if ((! ctxtGiven) && (pctxt != NULL))
18956 	xmlSchemaFreeParserCtxt(pctxt);
18957     return (-1);
18958 }
18959 
18960 /**
18961  * xmlSchemaCheckFacetValues:
18962  * @typeDecl:  the schema type definition
18963  * @ctxt:  the schema parser context
18964  *
18965  * Checks the default values types, especially for facets
18966  */
18967 static int
xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,xmlSchemaParserCtxtPtr pctxt)18968 xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
18969 			  xmlSchemaParserCtxtPtr pctxt)
18970 {
18971     int res, olderrs = pctxt->nberrors;
18972     const xmlChar *name = typeDecl->name;
18973     /*
18974     * NOTE: It is intended to use the facets list, instead
18975     * of facetSet.
18976     */
18977     if (typeDecl->facets != NULL) {
18978 	xmlSchemaFacetPtr facet = typeDecl->facets;
18979 
18980 	/*
18981 	* Temporarily assign the "schema" to the validation context
18982 	* of the parser context. This is needed for NOTATION validation.
18983 	*/
18984 	if (pctxt->vctxt == NULL) {
18985 	    if (xmlSchemaCreateVCtxtOnPCtxt(pctxt) == -1)
18986 		return(-1);
18987 	}
18988 	pctxt->vctxt->schema = pctxt->schema;
18989 	while (facet != NULL) {
18990 	    res = xmlSchemaCheckFacet(facet, typeDecl, pctxt, name);
18991 	    HFAILURE
18992 	    facet = facet->next;
18993 	}
18994 	pctxt->vctxt->schema = NULL;
18995     }
18996     if (olderrs != pctxt->nberrors)
18997 	return(pctxt->err);
18998     return(0);
18999 exit_failure:
19000     return(-1);
19001 }
19002 
19003 /**
19004  * xmlSchemaGetCircModelGrDefRef:
19005  * @ctxtMGroup: the searched model group
19006  * @selfMGroup: the second searched model group
19007  * @particle: the first particle
19008  *
19009  * This one is intended to be used by
19010  * xmlSchemaCheckGroupDefCircular only.
19011  *
19012  * Returns the particle with the circular model group definition reference,
19013  * otherwise NULL.
19014  */
19015 static xmlSchemaTreeItemPtr
xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,xmlSchemaTreeItemPtr particle)19016 xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,
19017 			      xmlSchemaTreeItemPtr particle)
19018 {
19019     xmlSchemaTreeItemPtr circ = NULL;
19020     xmlSchemaTreeItemPtr term;
19021     xmlSchemaModelGroupDefPtr gdef;
19022 
19023     for (; particle != NULL; particle = particle->next) {
19024 	term = particle->children;
19025 	if (term == NULL)
19026 	    continue;
19027 	switch (term->type) {
19028 	    case XML_SCHEMA_TYPE_GROUP:
19029 		gdef = (xmlSchemaModelGroupDefPtr) term;
19030 		if (gdef == groupDef)
19031 		    return (particle);
19032 		/*
19033 		* Mark this model group definition to avoid infinite
19034 		* recursion on circular references not yet examined.
19035 		*/
19036 		if (gdef->flags & XML_SCHEMA_MODEL_GROUP_DEF_MARKED)
19037 		    continue;
19038 		if (gdef->children != NULL) {
19039 		    gdef->flags |= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
19040 		    circ = xmlSchemaGetCircModelGrDefRef(groupDef,
19041 			gdef->children->children);
19042 		    gdef->flags ^= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
19043 		    if (circ != NULL)
19044 			return (circ);
19045 		}
19046 		break;
19047 	    case XML_SCHEMA_TYPE_SEQUENCE:
19048 	    case XML_SCHEMA_TYPE_CHOICE:
19049 	    case XML_SCHEMA_TYPE_ALL:
19050 		circ = xmlSchemaGetCircModelGrDefRef(groupDef, term->children);
19051 		if (circ != NULL)
19052 		    return (circ);
19053 		break;
19054 	    default:
19055 		break;
19056 	}
19057     }
19058     return (NULL);
19059 }
19060 
19061 /**
19062  * xmlSchemaCheckGroupDefCircular:
19063  * @item:  the model group definition
19064  * @ctxt:  the parser context
19065  * @name:  the name
19066  *
19067  * Checks for circular references to model group definitions.
19068  */
19069 static void
xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,xmlSchemaParserCtxtPtr ctxt)19070 xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,
19071 			       xmlSchemaParserCtxtPtr ctxt)
19072 {
19073     /*
19074     * Schema Component Constraint: Model Group Correct
19075     * 2 Circular groups are disallowed. That is, within the {particles}
19076     * of a group there must not be at any depth a particle whose {term}
19077     * is the group itself.
19078     */
19079     if ((item == NULL) ||
19080 	(item->type != XML_SCHEMA_TYPE_GROUP) ||
19081 	(item->children == NULL))
19082 	return;
19083     {
19084 	xmlSchemaTreeItemPtr circ;
19085 
19086 	circ = xmlSchemaGetCircModelGrDefRef(item, item->children->children);
19087 	if (circ != NULL) {
19088 	    xmlChar *str = NULL;
19089 	    /*
19090 	    * TODO: The error report is not adequate: this constraint
19091 	    * is defined for model groups but not definitions, but since
19092 	    * there cannot be any circular model groups without a model group
19093 	    * definition (if not using a construction API), we check those
19094 	    * definitions only.
19095 	    */
19096 	    xmlSchemaPCustomErr(ctxt,
19097 		XML_SCHEMAP_MG_PROPS_CORRECT_2,
19098 		NULL, WXS_ITEM_NODE(circ),
19099 		"Circular reference to the model group definition '%s' "
19100 		"defined", xmlSchemaFormatQName(&str,
19101 		    item->targetNamespace, item->name));
19102 	    FREE_AND_NULL(str)
19103 	    /*
19104 	    * NOTE: We will cut the reference to avoid further
19105 	    * confusion of the processor. This is a fatal error.
19106 	    */
19107 	    circ->children = NULL;
19108 	}
19109     }
19110 }
19111 
19112 /**
19113  * xmlSchemaModelGroupToModelGroupDefFixup:
19114  * @ctxt:  the parser context
19115  * @mg:  the model group
19116  *
19117  * Assigns the model group of model group definitions to the "term"
19118  * of the referencing particle.
19119  * In xmlSchemaResolveModelGroupParticleReferences the model group
19120  * definitions were assigned to the "term", since needed for the
19121  * circularity check.
19122  *
19123  * Schema Component Constraint:
19124  *     All Group Limited (cos-all-limited) (1.2)
19125  */
19126 static void
xmlSchemaModelGroupToModelGroupDefFixup(xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,xmlSchemaModelGroupPtr mg)19127 xmlSchemaModelGroupToModelGroupDefFixup(
19128     xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
19129     xmlSchemaModelGroupPtr mg)
19130 {
19131     xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
19132 
19133     while (particle != NULL) {
19134 	if ((WXS_PARTICLE_TERM(particle) == NULL) ||
19135 	    ((WXS_PARTICLE_TERM(particle))->type !=
19136 		XML_SCHEMA_TYPE_GROUP))
19137 	{
19138 	    particle = WXS_PTC_CAST particle->next;
19139 	    continue;
19140 	}
19141 	if (WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle)) == NULL) {
19142 	    /*
19143 	    * TODO: Remove the particle.
19144 	    */
19145 	    WXS_PARTICLE_TERM(particle) = NULL;
19146 	    particle = WXS_PTC_CAST particle->next;
19147 	    continue;
19148 	}
19149 	/*
19150 	* Assign the model group to the {term} of the particle.
19151 	*/
19152 	WXS_PARTICLE_TERM(particle) =
19153 	    WXS_TREE_CAST WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle));
19154 
19155 	particle = WXS_PTC_CAST particle->next;
19156     }
19157 }
19158 
19159 /**
19160  * xmlSchemaCheckAttrGroupCircularRecur:
19161  * @ctxtGr: the searched attribute group
19162  * @attr: the current attribute list to be processed
19163  *
19164  * This one is intended to be used by
19165  * xmlSchemaCheckAttrGroupCircular only.
19166  *
19167  * Returns the circular attribute group reference, otherwise NULL.
19168  */
19169 static xmlSchemaQNameRefPtr
xmlSchemaCheckAttrGroupCircularRecur(xmlSchemaAttributeGroupPtr ctxtGr,xmlSchemaItemListPtr list)19170 xmlSchemaCheckAttrGroupCircularRecur(xmlSchemaAttributeGroupPtr ctxtGr,
19171 				     xmlSchemaItemListPtr list)
19172 {
19173     xmlSchemaAttributeGroupPtr gr;
19174     xmlSchemaQNameRefPtr ref, circ;
19175     int i;
19176     /*
19177     * We will search for an attribute group reference which
19178     * references the context attribute group.
19179     */
19180     for (i = 0; i < list->nbItems; i++) {
19181 	ref = list->items[i];
19182 	if ((ref->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
19183 	    (ref->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
19184 	    (ref->item != NULL))
19185 	{
19186 	    gr = WXS_ATTR_GROUP_CAST ref->item;
19187 	    if (gr == ctxtGr)
19188 		return(ref);
19189 	    if (gr->flags & XML_SCHEMAS_ATTRGROUP_MARKED)
19190 		continue;
19191 	    /*
19192 	    * Mark as visited to avoid infinite recursion on
19193 	    * circular references not yet examined.
19194 	    */
19195 	    if ((gr->attrUses) &&
19196 		(gr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS))
19197 	    {
19198 		gr->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
19199 		circ = xmlSchemaCheckAttrGroupCircularRecur(ctxtGr,
19200 		    (xmlSchemaItemListPtr) gr->attrUses);
19201 		gr->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
19202 		if (circ != NULL)
19203 		    return (circ);
19204 	    }
19205 
19206 	}
19207     }
19208     return (NULL);
19209 }
19210 
19211 /**
19212  * xmlSchemaCheckAttrGroupCircular:
19213  * attrGr:  the attribute group definition
19214  * @ctxt:  the parser context
19215  * @name:  the name
19216  *
19217  * Checks for circular references of attribute groups.
19218  */
19219 static int
xmlSchemaCheckAttrGroupCircular(xmlSchemaAttributeGroupPtr attrGr,xmlSchemaParserCtxtPtr ctxt)19220 xmlSchemaCheckAttrGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
19221 				xmlSchemaParserCtxtPtr ctxt)
19222 {
19223     /*
19224     * Schema Representation Constraint:
19225     * Attribute Group Definition Representation OK
19226     * 3 Circular group reference is disallowed outside <redefine>.
19227     * That is, unless this element information item's parent is
19228     * <redefine>, then among the [children], if any, there must
19229     * not be an <attributeGroup> with ref [attribute] which resolves
19230     * to the component corresponding to this <attributeGroup>. Indirect
19231     * circularity is also ruled out. That is, when QName resolution
19232     * (Schema Document) ($3.15.3) is applied to a `QName` arising from
19233     * any <attributeGroup>s with a ref [attribute] among the [children],
19234     * it must not be the case that a `QName` is encountered at any depth
19235     * which resolves to the component corresponding to this <attributeGroup>.
19236     */
19237     if (attrGr->attrUses == NULL)
19238 	return(0);
19239     else if ((attrGr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS) == 0)
19240 	return(0);
19241     else {
19242 	xmlSchemaQNameRefPtr circ;
19243 
19244 	circ = xmlSchemaCheckAttrGroupCircularRecur(attrGr,
19245 	    (xmlSchemaItemListPtr) attrGr->attrUses);
19246 	if (circ != NULL) {
19247 	    xmlChar *str = NULL;
19248 	    /*
19249 	    * TODO: Report the referenced attr group as QName.
19250 	    */
19251 	    xmlSchemaPCustomErr(ctxt,
19252 		XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
19253 		NULL, WXS_ITEM_NODE(WXS_BASIC_CAST circ),
19254 		"Circular reference to the attribute group '%s' "
19255 		"defined", xmlSchemaGetComponentQName(&str, attrGr));
19256 	    FREE_AND_NULL(str);
19257 	    /*
19258 	    * NOTE: We will cut the reference to avoid further
19259 	    * confusion of the processor.
19260 	    * BADSPEC TODO: The spec should define how to process in this case.
19261 	    */
19262 	    circ->item = NULL;
19263 	    return(ctxt->err);
19264 	}
19265     }
19266     return(0);
19267 }
19268 
19269 static int
19270 xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19271 				  xmlSchemaAttributeGroupPtr attrGr);
19272 
19273 /**
19274  * xmlSchemaExpandAttributeGroupRefs:
19275  * @pctxt: the parser context
19276  * @node: the node of the component holding the attribute uses
19277  * @completeWild: the intersected wildcard to be returned
19278  * @list: the attribute uses
19279  *
19280  * Substitutes contained attribute group references
19281  * for their attribute uses. Wildcards are intersected.
19282  * Attribute use prohibitions are removed from the list
19283  * and returned via the @prohibs list.
19284  * Pointlessness of attr. prohibs, if a matching attr. decl
19285  * is existent a well, are checked.
19286  */
19287 static int
xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,xmlSchemaBasicItemPtr item,xmlSchemaWildcardPtr * completeWild,xmlSchemaItemListPtr list,xmlSchemaItemListPtr prohibs)19288 xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
19289 				  xmlSchemaBasicItemPtr item,
19290 				  xmlSchemaWildcardPtr *completeWild,
19291 				  xmlSchemaItemListPtr list,
19292 				  xmlSchemaItemListPtr prohibs)
19293 {
19294     xmlSchemaAttributeGroupPtr gr;
19295     xmlSchemaAttributeUsePtr use;
19296     xmlSchemaItemListPtr sublist;
19297     int i, j;
19298     int created = (*completeWild == NULL) ? 0 : 1;
19299 
19300     if (prohibs)
19301 	prohibs->nbItems = 0;
19302 
19303     for (i = 0; i < list->nbItems; i++) {
19304 	use = list->items[i];
19305 
19306 	if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
19307 	    if (prohibs == NULL) {
19308 		PERROR_INT("xmlSchemaExpandAttributeGroupRefs",
19309 		    "unexpected attr prohibition found");
19310 		return(-1);
19311 	    }
19312 	    /*
19313 	    * Remove from attribute uses.
19314 	    */
19315 	    if (xmlSchemaItemListRemove(list, i) == -1)
19316 		return(-1);
19317 	    i--;
19318 	    /*
19319 	    * Note that duplicate prohibitions were already
19320 	    * handled at parsing time.
19321 	    */
19322 	    /*
19323 	    * Add to list of prohibitions.
19324 	    */
19325 	    xmlSchemaItemListAddSize(prohibs, 2, use);
19326 	    continue;
19327 	}
19328 	if ((use->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
19329 	    ((WXS_QNAME_CAST use)->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP))
19330 	{
19331 	    if ((WXS_QNAME_CAST use)->item == NULL)
19332 		return(-1);
19333 	    gr = WXS_ATTR_GROUP_CAST (WXS_QNAME_CAST use)->item;
19334 	    /*
19335 	    * Expand the referenced attr. group.
19336 	    * TODO: remove this, this is done in a previous step, so
19337 	    * already done here.
19338 	    */
19339 	    if ((gr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
19340 		if (xmlSchemaAttributeGroupExpandRefs(pctxt, gr) == -1)
19341 		    return(-1);
19342 	    }
19343 	    /*
19344 	    * Build the 'complete' wildcard; i.e. intersect multiple
19345 	    * wildcards.
19346 	    */
19347 	    if (gr->attributeWildcard != NULL) {
19348 		if (*completeWild == NULL) {
19349 		    *completeWild = gr->attributeWildcard;
19350 		} else {
19351 		    if (! created) {
19352 			xmlSchemaWildcardPtr tmpWild;
19353 
19354 			 /*
19355 			* Copy the first encountered wildcard as context,
19356 			* except for the annotation.
19357 			*
19358 			* Although the complete wildcard might not correspond
19359 			* to any node in the schema, we will anchor it on
19360 			* the node of the owner component.
19361 			*/
19362 			tmpWild =  xmlSchemaAddWildcard(pctxt, pctxt->schema,
19363 			    XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
19364 			    WXS_ITEM_NODE(item));
19365 			if (tmpWild == NULL)
19366 			    return(-1);
19367 			if (xmlSchemaCloneWildcardNsConstraints(pctxt,
19368 			    tmpWild, *completeWild) == -1)
19369 			    return (-1);
19370 			tmpWild->processContents = (*completeWild)->processContents;
19371 			*completeWild = tmpWild;
19372 			created = 1;
19373 		    }
19374 
19375 		    if (xmlSchemaIntersectWildcards(pctxt, *completeWild,
19376 			gr->attributeWildcard) == -1)
19377 			return(-1);
19378 		}
19379 	    }
19380 	    /*
19381 	    * Just remove the reference if the referenced group does not
19382 	    * contain any attribute uses.
19383 	    */
19384 	    sublist = ((xmlSchemaItemListPtr) gr->attrUses);
19385 	    if ((sublist == NULL) || sublist->nbItems == 0) {
19386 		if (xmlSchemaItemListRemove(list, i) == -1)
19387 		    return(-1);
19388 		i--;
19389 		continue;
19390 	    }
19391 	    /*
19392 	    * Add the attribute uses.
19393 	    */
19394 	    list->items[i] = sublist->items[0];
19395 	    if (sublist->nbItems != 1) {
19396 		for (j = 1; j < sublist->nbItems; j++) {
19397 		    i++;
19398 		    if (xmlSchemaItemListInsert(list,
19399 			    sublist->items[j], i) == -1)
19400 			return(-1);
19401 		}
19402 	    }
19403 	}
19404 
19405     }
19406     /*
19407     * Handle pointless prohibitions of declared attributes.
19408     */
19409     if (prohibs && (prohibs->nbItems != 0) && (list->nbItems != 0)) {
19410 	xmlSchemaAttributeUseProhibPtr prohib;
19411 
19412 	for (i = prohibs->nbItems -1; i >= 0; i--) {
19413 	    prohib = prohibs->items[i];
19414 	    for (j = 0; j < list->nbItems; j++) {
19415 		use = list->items[j];
19416 
19417 		if ((prohib->name == WXS_ATTRUSE_DECL_NAME(use)) &&
19418 		    (prohib->targetNamespace == WXS_ATTRUSE_DECL_TNS(use)))
19419 		{
19420 		    xmlChar *str = NULL;
19421 
19422 		    xmlSchemaCustomWarning(ACTXT_CAST pctxt,
19423 			XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
19424 			prohib->node, NULL,
19425 			"Skipping pointless attribute use prohibition "
19426 			"'%s', since a corresponding attribute use "
19427 			"exists already in the type definition",
19428 			xmlSchemaFormatQName(&str,
19429 			    prohib->targetNamespace, prohib->name),
19430 			NULL, NULL);
19431 		    FREE_AND_NULL(str);
19432 		    /*
19433 		    * Remove the prohibition.
19434 		    */
19435 		    if (xmlSchemaItemListRemove(prohibs, i) == -1)
19436 			return(-1);
19437 		    break;
19438 		}
19439 	    }
19440 	}
19441     }
19442     return(0);
19443 }
19444 
19445 /**
19446  * xmlSchemaAttributeGroupExpandRefs:
19447  * @pctxt:  the parser context
19448  * @attrGr:  the attribute group definition
19449  *
19450  * Computation of:
19451  * {attribute uses} property
19452  * {attribute wildcard} property
19453  *
19454  * Substitutes contained attribute group references
19455  * for their attribute uses. Wildcards are intersected.
19456  */
19457 static int
xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,xmlSchemaAttributeGroupPtr attrGr)19458 xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19459 				  xmlSchemaAttributeGroupPtr attrGr)
19460 {
19461     if ((attrGr->attrUses == NULL) ||
19462 	(attrGr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED))
19463 	return(0);
19464 
19465     attrGr->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
19466     if (xmlSchemaExpandAttributeGroupRefs(pctxt, WXS_BASIC_CAST attrGr,
19467 	&(attrGr->attributeWildcard), attrGr->attrUses, NULL) == -1)
19468 	return(-1);
19469     return(0);
19470 }
19471 
19472 /**
19473  * xmlSchemaAttributeGroupExpandRefs:
19474  * @pctxt:  the parser context
19475  * @attrGr:  the attribute group definition
19476  *
19477  * Substitutes contained attribute group references
19478  * for their attribute uses. Wildcards are intersected.
19479  *
19480  * Schema Component Constraint:
19481  *    Attribute Group Definition Properties Correct (ag-props-correct)
19482  */
19483 static int
xmlSchemaCheckAGPropsCorrect(xmlSchemaParserCtxtPtr pctxt,xmlSchemaAttributeGroupPtr attrGr)19484 xmlSchemaCheckAGPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19485 				  xmlSchemaAttributeGroupPtr attrGr)
19486 {
19487     /*
19488     * SPEC ag-props-correct
19489     * (1) "The values of the properties of an attribute group definition
19490     * must be as described in the property tableau in The Attribute
19491     * Group Definition Schema Component ($3.6.1), modulo the impact of
19492     * Missing Sub-components ($5.3);"
19493     */
19494 
19495     if ((attrGr->attrUses != NULL) &&
19496 	(WXS_LIST_CAST attrGr->attrUses)->nbItems > 1)
19497     {
19498 	xmlSchemaItemListPtr uses = WXS_LIST_CAST attrGr->attrUses;
19499 	xmlSchemaAttributeUsePtr use, tmp;
19500 	int i, j, hasId = 0;
19501 
19502 	for (i = uses->nbItems -1; i >= 0; i--) {
19503 	    use = uses->items[i];
19504 	    /*
19505 	    * SPEC ag-props-correct
19506 	    * (2) "Two distinct members of the {attribute uses} must not have
19507 	    * {attribute declaration}s both of whose {name}s match and whose
19508 	    * {target namespace}s are identical."
19509 	    */
19510 	    if (i > 0) {
19511 		for (j = i -1; j >= 0; j--) {
19512 		    tmp = uses->items[j];
19513 		    if ((WXS_ATTRUSE_DECL_NAME(use) ==
19514 			WXS_ATTRUSE_DECL_NAME(tmp)) &&
19515 			(WXS_ATTRUSE_DECL_TNS(use) ==
19516 			WXS_ATTRUSE_DECL_TNS(tmp)))
19517 		    {
19518 			xmlChar *str = NULL;
19519 
19520 			xmlSchemaCustomErr(ACTXT_CAST pctxt,
19521 			    XML_SCHEMAP_AG_PROPS_CORRECT,
19522 			    attrGr->node, WXS_BASIC_CAST attrGr,
19523 			    "Duplicate %s",
19524 			    xmlSchemaGetComponentDesignation(&str, use),
19525 			    NULL);
19526 			FREE_AND_NULL(str);
19527 			/*
19528 			* Remove the duplicate.
19529 			*/
19530 			if (xmlSchemaItemListRemove(uses, i) == -1)
19531 			    return(-1);
19532 			goto next_use;
19533 		    }
19534 		}
19535 	    }
19536 	    /*
19537 	    * SPEC ag-props-correct
19538 	    * (3) "Two distinct members of the {attribute uses} must not have
19539 	    * {attribute declaration}s both of whose {type definition}s are or
19540 	    * are derived from ID."
19541 	    * TODO: Does 'derived' include member-types of unions?
19542 	    */
19543 	    if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
19544 		if (xmlSchemaIsDerivedFromBuiltInType(
19545 		    WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
19546 		{
19547 		    if (hasId) {
19548 			xmlChar *str = NULL;
19549 
19550 			xmlSchemaCustomErr(ACTXT_CAST pctxt,
19551 			    XML_SCHEMAP_AG_PROPS_CORRECT,
19552 			    attrGr->node, WXS_BASIC_CAST attrGr,
19553 			    "There must not exist more than one attribute "
19554 			    "declaration of type 'xs:ID' "
19555 			    "(or derived from 'xs:ID'). The %s violates this "
19556 			    "constraint",
19557 			    xmlSchemaGetComponentDesignation(&str, use),
19558 			    NULL);
19559 			FREE_AND_NULL(str);
19560 			if (xmlSchemaItemListRemove(uses, i) == -1)
19561 			    return(-1);
19562 		    }
19563 		    hasId = 1;
19564 		}
19565 	    }
19566 next_use: {}
19567 	}
19568     }
19569     return(0);
19570 }
19571 
19572 /**
19573  * xmlSchemaResolveAttrGroupReferences:
19574  * @attrgrpDecl:  the schema attribute definition
19575  * @ctxt:  the schema parser context
19576  * @name:  the attribute name
19577  *
19578  * Resolves references to attribute group definitions.
19579  */
19580 static int
xmlSchemaResolveAttrGroupReferences(xmlSchemaQNameRefPtr ref,xmlSchemaParserCtxtPtr ctxt)19581 xmlSchemaResolveAttrGroupReferences(xmlSchemaQNameRefPtr ref,
19582 				    xmlSchemaParserCtxtPtr ctxt)
19583 {
19584     xmlSchemaAttributeGroupPtr group;
19585 
19586     if (ref->item != NULL)
19587         return(0);
19588     group = xmlSchemaGetAttributeGroup(ctxt->schema,
19589 	ref->name,
19590 	ref->targetNamespace);
19591     if (group == NULL) {
19592 	xmlSchemaPResCompAttrErr(ctxt,
19593 	    XML_SCHEMAP_SRC_RESOLVE,
19594 	    NULL, ref->node,
19595 	    "ref", ref->name, ref->targetNamespace,
19596 	    ref->itemType, NULL);
19597 	return(ctxt->err);
19598     }
19599     ref->item = WXS_BASIC_CAST group;
19600     return(0);
19601 }
19602 
19603 /**
19604  * xmlSchemaCheckAttrPropsCorrect:
19605  * @item:  an schema attribute declaration/use
19606  * @ctxt:  a schema parser context
19607  * @name:  the name of the attribute
19608  *
19609  *
19610  * Schema Component Constraint:
19611  *    Attribute Declaration Properties Correct (a-props-correct)
19612  *
19613  * Validates the value constraints of an attribute declaration/use.
19614  * NOTE that this needs the simple type definitions to be already
19615  *   built and checked.
19616  */
19617 static int
xmlSchemaCheckAttrPropsCorrect(xmlSchemaParserCtxtPtr pctxt,xmlSchemaAttributePtr attr)19618 xmlSchemaCheckAttrPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19619 			       xmlSchemaAttributePtr attr)
19620 {
19621 
19622     /*
19623     * SPEC a-props-correct (1)
19624     * "The values of the properties of an attribute declaration must
19625     * be as described in the property tableau in The Attribute
19626     * Declaration Schema Component ($3.2.1), modulo the impact of
19627     * Missing Sub-components ($5.3)."
19628     */
19629 
19630     if (WXS_ATTR_TYPEDEF(attr) == NULL)
19631 	return(0);
19632 
19633     if (attr->defValue != NULL) {
19634 	int ret;
19635 
19636 	/*
19637 	* SPEC a-props-correct (3)
19638 	* "If the {type definition} is or is derived from ID then there
19639 	* must not be a {value constraint}."
19640 	*/
19641 	if (xmlSchemaIsDerivedFromBuiltInType(
19642 	    WXS_ATTR_TYPEDEF(attr), XML_SCHEMAS_ID))
19643 	{
19644 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
19645 		XML_SCHEMAP_A_PROPS_CORRECT_3,
19646 		NULL, WXS_BASIC_CAST attr,
19647 		"Value constraints are not allowed if the type definition "
19648 		"is or is derived from xs:ID",
19649 		NULL, NULL);
19650 	    return(pctxt->err);
19651 	}
19652 	/*
19653 	* SPEC a-props-correct (2)
19654 	* "if there is a {value constraint}, the canonical lexical
19655 	* representation of its value must be `valid` with respect
19656 	* to the {type definition} as defined in String Valid ($3.14.4)."
19657 	* TODO: Don't care about the *canonical* stuff here, this requirement
19658 	* will be removed in WXS 1.1 anyway.
19659 	*/
19660 	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt,
19661 	    attr->node, WXS_ATTR_TYPEDEF(attr),
19662 	    attr->defValue, &(attr->defVal),
19663 	    1, 1, 0);
19664 	if (ret != 0) {
19665 	    if (ret < 0) {
19666 		PERROR_INT("xmlSchemaCheckAttrPropsCorrect",
19667 		    "calling xmlSchemaVCheckCVCSimpleType()");
19668 		return(-1);
19669 	    }
19670 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
19671 		XML_SCHEMAP_A_PROPS_CORRECT_2,
19672 		NULL, WXS_BASIC_CAST attr,
19673 		"The value of the value constraint is not valid",
19674 		NULL, NULL);
19675 	    return(pctxt->err);
19676 	}
19677     }
19678 
19679     return(0);
19680 }
19681 
19682 static xmlSchemaElementPtr
xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,xmlSchemaElementPtr ancestor)19683 xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,
19684 				 xmlSchemaElementPtr ancestor)
19685 {
19686     xmlSchemaElementPtr ret;
19687 
19688     if (WXS_SUBST_HEAD(ancestor) == NULL)
19689 	return (NULL);
19690     if (WXS_SUBST_HEAD(ancestor) == elemDecl)
19691 	return (ancestor);
19692 
19693     if (WXS_SUBST_HEAD(ancestor)->flags & XML_SCHEMAS_ELEM_CIRCULAR)
19694 	return (NULL);
19695     WXS_SUBST_HEAD(ancestor)->flags |= XML_SCHEMAS_ELEM_CIRCULAR;
19696     ret = xmlSchemaCheckSubstGroupCircular(elemDecl,
19697 	WXS_SUBST_HEAD(ancestor));
19698     WXS_SUBST_HEAD(ancestor)->flags ^= XML_SCHEMAS_ELEM_CIRCULAR;
19699 
19700     return (ret);
19701 }
19702 
19703 /**
19704  * xmlSchemaCheckElemPropsCorrect:
19705  * @ctxt:  a schema parser context
19706  * @decl: the element declaration
19707  * @name:  the name of the attribute
19708  *
19709  * Schema Component Constraint:
19710  * Element Declaration Properties Correct (e-props-correct)
19711  *
19712  * STATUS:
19713  *   missing: (6)
19714  */
19715 static int
xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,xmlSchemaElementPtr elemDecl)19716 xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19717 			       xmlSchemaElementPtr elemDecl)
19718 {
19719     int ret = 0;
19720     xmlSchemaTypePtr typeDef = WXS_ELEM_TYPEDEF(elemDecl);
19721     /*
19722     * SPEC (1) "The values of the properties of an element declaration
19723     * must be as described in the property tableau in The Element
19724     * Declaration Schema Component ($3.3.1), modulo the impact of Missing
19725     * Sub-components ($5.3)."
19726     */
19727     if (WXS_SUBST_HEAD(elemDecl) != NULL) {
19728 	xmlSchemaElementPtr head = WXS_SUBST_HEAD(elemDecl), circ;
19729 
19730 	xmlSchemaCheckElementDeclComponent(head, pctxt);
19731 	/*
19732 	* SPEC (3) "If there is a non-`absent` {substitution group
19733 	* affiliation}, then {scope} must be global."
19734 	*/
19735 	if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
19736 	    xmlSchemaPCustomErr(pctxt,
19737 		XML_SCHEMAP_E_PROPS_CORRECT_3,
19738 		WXS_BASIC_CAST elemDecl, NULL,
19739 		"Only global element declarations can have a "
19740 		"substitution group affiliation", NULL);
19741 	    ret = XML_SCHEMAP_E_PROPS_CORRECT_3;
19742 	}
19743 	/*
19744 	* TODO: SPEC (6) "Circular substitution groups are disallowed.
19745 	* That is, it must not be possible to return to an element declaration
19746 	* by repeatedly following the {substitution group affiliation}
19747 	* property."
19748 	*/
19749 	if (head == elemDecl)
19750 	    circ = head;
19751 	else if (WXS_SUBST_HEAD(head) != NULL)
19752 	    circ = xmlSchemaCheckSubstGroupCircular(head, head);
19753 	else
19754 	    circ = NULL;
19755 	if (circ != NULL) {
19756 	    xmlChar *strA = NULL, *strB = NULL;
19757 
19758 	    xmlSchemaPCustomErrExt(pctxt,
19759 		XML_SCHEMAP_E_PROPS_CORRECT_6,
19760 		WXS_BASIC_CAST circ, NULL,
19761 		"The element declaration '%s' defines a circular "
19762 		"substitution group to element declaration '%s'",
19763 		xmlSchemaGetComponentQName(&strA, circ),
19764 		xmlSchemaGetComponentQName(&strB, head),
19765 		NULL);
19766 	    FREE_AND_NULL(strA)
19767 	    FREE_AND_NULL(strB)
19768 	    ret = XML_SCHEMAP_E_PROPS_CORRECT_6;
19769 	}
19770 	/*
19771 	* SPEC (4) "If there is a {substitution group affiliation},
19772 	* the {type definition}
19773 	* of the element declaration must be validly derived from the {type
19774 	* definition} of the {substitution group affiliation}, given the value
19775 	* of the {substitution group exclusions} of the {substitution group
19776 	* affiliation}, as defined in Type Derivation OK (Complex) ($3.4.6)
19777 	* (if the {type definition} is complex) or as defined in
19778 	* Type Derivation OK (Simple) ($3.14.6) (if the {type definition} is
19779 	* simple)."
19780 	*
19781 	* NOTE: {substitution group exclusions} means the values of the
19782 	* attribute "final".
19783 	*/
19784 
19785 	if (typeDef != WXS_ELEM_TYPEDEF(WXS_SUBST_HEAD(elemDecl))) {
19786 	    int set = 0;
19787 
19788 	    if (head->flags & XML_SCHEMAS_ELEM_FINAL_EXTENSION)
19789 		set |= SUBSET_EXTENSION;
19790 	    if (head->flags & XML_SCHEMAS_ELEM_FINAL_RESTRICTION)
19791 		set |= SUBSET_RESTRICTION;
19792 
19793 	    if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST pctxt, typeDef,
19794 		WXS_ELEM_TYPEDEF(head), set) != 0) {
19795 		xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
19796 
19797 		ret = XML_SCHEMAP_E_PROPS_CORRECT_4;
19798 		xmlSchemaPCustomErrExt(pctxt,
19799 		    XML_SCHEMAP_E_PROPS_CORRECT_4,
19800 		    WXS_BASIC_CAST elemDecl, NULL,
19801 		    "The type definition '%s' was "
19802 		    "either rejected by the substitution group "
19803 		    "affiliation '%s', or not validly derived from its type "
19804 		    "definition '%s'",
19805 		    xmlSchemaGetComponentQName(&strA, typeDef),
19806 		    xmlSchemaGetComponentQName(&strB, head),
19807 		    xmlSchemaGetComponentQName(&strC, WXS_ELEM_TYPEDEF(head)));
19808 		FREE_AND_NULL(strA)
19809 		FREE_AND_NULL(strB)
19810 		FREE_AND_NULL(strC)
19811 	    }
19812 	}
19813     }
19814     /*
19815     * SPEC (5) "If the {type definition} or {type definition}'s
19816     * {content type}
19817     * is or is derived from ID then there must not be a {value constraint}.
19818     * Note: The use of ID as a type definition for elements goes beyond
19819     * XML 1.0, and should be avoided if backwards compatibility is desired"
19820     */
19821     if ((elemDecl->value != NULL) &&
19822 	((WXS_IS_SIMPLE(typeDef) &&
19823 	  xmlSchemaIsDerivedFromBuiltInType(typeDef, XML_SCHEMAS_ID)) ||
19824 	 (WXS_IS_COMPLEX(typeDef) &&
19825 	  WXS_HAS_SIMPLE_CONTENT(typeDef) &&
19826 	  xmlSchemaIsDerivedFromBuiltInType(typeDef->contentTypeDef,
19827 	    XML_SCHEMAS_ID)))) {
19828 
19829 	ret = XML_SCHEMAP_E_PROPS_CORRECT_5;
19830 	xmlSchemaPCustomErr(pctxt,
19831 	    XML_SCHEMAP_E_PROPS_CORRECT_5,
19832 	    WXS_BASIC_CAST elemDecl, NULL,
19833 	    "The type definition (or type definition's content type) is or "
19834 	    "is derived from ID; value constraints are not allowed in "
19835 	    "conjunction with such a type definition", NULL);
19836     } else if (elemDecl->value != NULL) {
19837 	int vcret;
19838 	xmlNodePtr node = NULL;
19839 
19840 	/*
19841 	* SPEC (2) "If there is a {value constraint}, the canonical lexical
19842 	* representation of its value must be `valid` with respect to the
19843 	* {type definition} as defined in Element Default Valid (Immediate)
19844 	* ($3.3.6)."
19845 	*/
19846 	if (typeDef == NULL) {
19847 	    xmlSchemaPErr(pctxt, elemDecl->node,
19848 		XML_SCHEMAP_INTERNAL,
19849 		"Internal error: xmlSchemaCheckElemPropsCorrect, "
19850 		"type is missing... skipping validation of "
19851 		"the value constraint", NULL, NULL);
19852 	    return (-1);
19853 	}
19854 	if (elemDecl->node != NULL) {
19855 	    if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
19856 		node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19857 		    BAD_CAST "fixed");
19858 	    else
19859 		node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19860 		    BAD_CAST "default");
19861 	}
19862 	vcret = xmlSchemaParseCheckCOSValidDefault(pctxt, node,
19863 	    typeDef, elemDecl->value, &(elemDecl->defVal));
19864 	if (vcret != 0) {
19865 	    if (vcret < 0) {
19866 		PERROR_INT("xmlSchemaElemCheckValConstr",
19867 		    "failed to validate the value constraint of an "
19868 		    "element declaration");
19869 		return (-1);
19870 	    }
19871 	    return (vcret);
19872 	}
19873     }
19874 
19875     return (ret);
19876 }
19877 
19878 /**
19879  * xmlSchemaCheckElemSubstGroup:
19880  * @ctxt:  a schema parser context
19881  * @decl: the element declaration
19882  * @name:  the name of the attribute
19883  *
19884  * Schema Component Constraint:
19885  * Substitution Group (cos-equiv-class)
19886  *
19887  * In Libxml2 the subst. groups will be precomputed, in terms of that
19888  * a list will be built for each subst. group head, holding all direct
19889  * referents to this head.
19890  * NOTE that this function needs:
19891  *   1. circular subst. groups to be checked beforehand
19892  *   2. the declaration's type to be derived from the head's type
19893  *
19894  * STATUS:
19895  *
19896  */
19897 static void
xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,xmlSchemaElementPtr elemDecl)19898 xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,
19899 			     xmlSchemaElementPtr elemDecl)
19900 {
19901     if ((WXS_SUBST_HEAD(elemDecl) == NULL) ||
19902 	/* SPEC (1) "Its {abstract} is false." */
19903 	(elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT))
19904 	return;
19905     {
19906 	xmlSchemaElementPtr head;
19907 	xmlSchemaTypePtr headType, type;
19908 	int set, methSet;
19909 	/*
19910 	* SPEC (2) "It is validly substitutable for HEAD subject to HEAD's
19911 	* {disallowed substitutions} as the blocking constraint, as defined in
19912 	* Substitution Group OK (Transitive) ($3.3.6)."
19913 	*/
19914 	for (head = WXS_SUBST_HEAD(elemDecl); head != NULL;
19915 	    head = WXS_SUBST_HEAD(head)) {
19916 	    set = 0;
19917 	    methSet = 0;
19918 	    /*
19919 	    * The blocking constraints.
19920 	    */
19921 	    if (head->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION)
19922 		continue;
19923 	    headType = head->subtypes;
19924 	    type = elemDecl->subtypes;
19925 	    if (headType == type)
19926 		goto add_member;
19927 	    if (head->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION)
19928 		set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19929 	    if (head->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION)
19930 		set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19931 	    /*
19932 	    * SPEC: Substitution Group OK (Transitive) (2.3)
19933 	    * "The set of all {derivation method}s involved in the
19934 	    * derivation of D's {type definition} from C's {type definition}
19935 	    * does not intersect with the union of the blocking constraint,
19936 	    * C's {prohibited substitutions} (if C is complex, otherwise the
19937 	    * empty set) and the {prohibited substitutions} (respectively the
19938 	    * empty set) of any intermediate {type definition}s in the
19939 	    * derivation of D's {type definition} from C's {type definition}."
19940 	    */
19941 	    /*
19942 	    * OPTIMIZE TODO: Optimize this a bit, since, if traversing the
19943 	    * subst.head axis, the methSet does not need to be computed for
19944 	    * the full depth over and over.
19945 	    */
19946 	    /*
19947 	    * The set of all {derivation method}s involved in the derivation
19948 	    */
19949 	    while ((type != NULL) && (type != headType)) {
19950 		if ((WXS_IS_EXTENSION(type)) &&
19951 		    ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19952 		    methSet |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19953 
19954 		if (WXS_IS_RESTRICTION(type) &&
19955 		    ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19956 		    methSet |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19957 
19958 		type = type->baseType;
19959 	    }
19960 	    /*
19961 	    * The {prohibited substitutions} of all intermediate types +
19962 	    * the head's type.
19963 	    */
19964 	    type = elemDecl->subtypes->baseType;
19965 	    while (type != NULL) {
19966 		if (WXS_IS_COMPLEX(type)) {
19967 		    if ((type->flags &
19968 			    XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19969 			((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) == 0))
19970 		    set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19971 		    if ((type->flags &
19972 			    XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19973 			((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19974 		    set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19975 		} else
19976 		    break;
19977 		if (type == headType)
19978 		    break;
19979 		type = type->baseType;
19980 	    }
19981 	    if ((set != 0) &&
19982 		(((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19983 		(methSet & XML_SCHEMAS_TYPE_BLOCK_EXTENSION)) ||
19984 		((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19985 		(methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION)))) {
19986 		continue;
19987 	    }
19988 add_member:
19989 	    xmlSchemaAddElementSubstitutionMember(ctxt, head, elemDecl);
19990 	    if ((head->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) == 0)
19991 		head->flags |= XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD;
19992 	}
19993     }
19994 }
19995 
19996 #ifdef WXS_ELEM_DECL_CONS_ENABLED /* enable when finished */
19997 /**
19998  * xmlSchemaCheckElementDeclComponent
19999  * @pctxt: the schema parser context
20000  * @ctxtComponent: the context component (an element declaration)
20001  * @ctxtParticle: the first particle of the context component
20002  * @searchParticle: the element declaration particle to be analysed
20003  *
20004  * Schema Component Constraint: Element Declarations Consistent
20005  */
20006 static int
xmlSchemaCheckElementDeclConsistent(xmlSchemaParserCtxtPtr pctxt,xmlSchemaBasicItemPtr ctxtComponent,xmlSchemaParticlePtr ctxtParticle,xmlSchemaParticlePtr searchParticle,xmlSchemaParticlePtr curParticle,int search)20007 xmlSchemaCheckElementDeclConsistent(xmlSchemaParserCtxtPtr pctxt,
20008 				    xmlSchemaBasicItemPtr ctxtComponent,
20009 				    xmlSchemaParticlePtr ctxtParticle,
20010 				    xmlSchemaParticlePtr searchParticle,
20011 				    xmlSchemaParticlePtr curParticle,
20012 				    int search)
20013 {
20014     return(0);
20015 
20016     int ret = 0;
20017     xmlSchemaParticlePtr cur = curParticle;
20018     if (curParticle == NULL) {
20019 	return(0);
20020     }
20021     if (WXS_PARTICLE_TERM(curParticle) == NULL) {
20022 	/*
20023 	* Just return in this case. A missing "term" of the particle
20024 	* might arise due to an invalid "term" component.
20025 	*/
20026 	return(0);
20027     }
20028     while (cur != NULL) {
20029 	switch (WXS_PARTICLE_TERM(cur)->type) {
20030 	    case XML_SCHEMA_TYPE_ANY:
20031 		break;
20032 	    case XML_SCHEMA_TYPE_ELEMENT:
20033 		if (search == 0) {
20034 		    ret = xmlSchemaCheckElementDeclConsistent(pctxt,
20035 			ctxtComponent, ctxtParticle, cur, ctxtParticle, 1);
20036 		    if (ret != 0)
20037 			return(ret);
20038 		} else {
20039 		    xmlSchemaElementPtr elem =
20040 			WXS_ELEM_CAST(WXS_PARTICLE_TERM(cur));
20041 		    /*
20042 		    * SPEC Element Declarations Consistent:
20043 		    * "If the {particles} contains, either directly,
20044 		    * indirectly (that is, within the {particles} of a
20045 		    * contained model group, recursively) or `implicitly`
20046 		    * two or more element declaration particles with
20047 		    * the same {name} and {target namespace}, then
20048 		    * all their type definitions must be the same
20049 		    * top-level definition [...]"
20050 		    */
20051 		    if (xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->name,
20052 			    WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->name) &&
20053 			xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamespace,
20054 			    WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->targetNamespace))
20055 		    {
20056 			xmlChar *strA = NULL, *strB = NULL;
20057 
20058 			xmlSchemaCustomErr(ACTXT_CAST pctxt,
20059 			    /* TODO: error code */
20060 			    XML_SCHEMAP_COS_NONAMBIG,
20061 			    WXS_ITEM_NODE(cur), NULL,
20062 			    "In the content model of %s, there are multiple "
20063 			    "element declarations for '%s' with different "
20064 			    "type definitions",
20065 			    xmlSchemaGetComponentDesignation(&strA,
20066 				ctxtComponent),
20067 			    xmlSchemaFormatQName(&strB,
20068 				WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamespace,
20069 				WXS_PARTICLE_TERM_AS_ELEM(cur)->name));
20070 			FREE_AND_NULL(strA);
20071 			FREE_AND_NULL(strB);
20072 			return(XML_SCHEMAP_COS_NONAMBIG);
20073 		    }
20074 		}
20075 		break;
20076 	    case XML_SCHEMA_TYPE_SEQUENCE: {
20077 		break;
20078 		}
20079 	    case XML_SCHEMA_TYPE_CHOICE:{
20080 		/*
20081 		xmlSchemaTreeItemPtr sub;
20082 
20083 		sub = WXS_PARTICLE_TERM(particle)->children;  (xmlSchemaParticlePtr)
20084 		while (sub != NULL) {
20085 		    ret = xmlSchemaCheckElementDeclConsistent(pctxt, ctxtComponent,
20086 			ctxtParticle, ctxtElem);
20087 		    if (ret != 0)
20088 			return(ret);
20089 		    sub = sub->next;
20090 		}
20091 		*/
20092 		break;
20093 		}
20094 	    case XML_SCHEMA_TYPE_ALL:
20095 		break;
20096 	    case XML_SCHEMA_TYPE_GROUP:
20097 		break;
20098 	    default:
20099 		xmlSchemaInternalErr2(ACTXT_CAST pctxt,
20100 		    "xmlSchemaCheckElementDeclConsistent",
20101 		    "found unexpected term of type '%s' in content model",
20102 		    WXS_ITEM_TYPE_NAME(WXS_PARTICLE_TERM(cur)), NULL);
20103 		return(-1);
20104 	}
20105 	cur = (xmlSchemaParticlePtr) cur->next;
20106     }
20107 
20108 exit:
20109     return(ret);
20110 }
20111 #endif
20112 
20113 /**
20114  * xmlSchemaCheckElementDeclComponent
20115  * @item:  an schema element declaration/particle
20116  * @ctxt:  a schema parser context
20117  * @name:  the name of the attribute
20118  *
20119  * Validates the value constraints of an element declaration.
20120  * Adds substitution group members.
20121  */
20122 static void
xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,xmlSchemaParserCtxtPtr ctxt)20123 xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
20124 				   xmlSchemaParserCtxtPtr ctxt)
20125 {
20126     if (elemDecl == NULL)
20127 	return;
20128     if (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED)
20129 	return;
20130     elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_CHECKED;
20131     if (xmlSchemaCheckElemPropsCorrect(ctxt, elemDecl) == 0) {
20132 	/*
20133 	* Adds substitution group members.
20134 	*/
20135 	xmlSchemaCheckElemSubstGroup(ctxt, elemDecl);
20136     }
20137 }
20138 
20139 /**
20140  * xmlSchemaResolveModelGroupParticleReferences:
20141  * @particle:  a particle component
20142  * @ctxt:  a parser context
20143  *
20144  * Resolves references of a model group's {particles} to
20145  * model group definitions and to element declarations.
20146  */
20147 static void
xmlSchemaResolveModelGroupParticleReferences(xmlSchemaParserCtxtPtr ctxt,xmlSchemaModelGroupPtr mg)20148 xmlSchemaResolveModelGroupParticleReferences(
20149     xmlSchemaParserCtxtPtr ctxt,
20150     xmlSchemaModelGroupPtr mg)
20151 {
20152     xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
20153     xmlSchemaQNameRefPtr ref;
20154     xmlSchemaBasicItemPtr refItem;
20155 
20156     /*
20157     * URGENT TODO: Test this.
20158     */
20159     while (particle != NULL) {
20160 	if ((WXS_PARTICLE_TERM(particle) == NULL) ||
20161 	    ((WXS_PARTICLE_TERM(particle))->type !=
20162 		XML_SCHEMA_EXTRA_QNAMEREF))
20163 	{
20164 	    goto next_particle;
20165 	}
20166 	ref = WXS_QNAME_CAST WXS_PARTICLE_TERM(particle);
20167 	/*
20168 	* Resolve the reference.
20169 	* NULL the {term} by default.
20170 	*/
20171 	particle->children = NULL;
20172 
20173 	refItem = xmlSchemaGetNamedComponent(ctxt->schema,
20174 	    ref->itemType, ref->name, ref->targetNamespace);
20175 	if (refItem == NULL) {
20176 	    xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
20177 		NULL, WXS_ITEM_NODE(particle), "ref", ref->name,
20178 		ref->targetNamespace, ref->itemType, NULL);
20179 	    /* TODO: remove the particle. */
20180 	    goto next_particle;
20181 	}
20182 	if (refItem->type == XML_SCHEMA_TYPE_GROUP) {
20183 	    if (WXS_MODELGROUPDEF_MODEL(refItem) == NULL)
20184 		/* TODO: remove the particle. */
20185 		goto next_particle;
20186 	    /*
20187 	    * NOTE that we will assign the model group definition
20188 	    * itself to the "term" of the particle. This will ease
20189 	    * the check for circular model group definitions. After
20190 	    * that the "term" will be assigned the model group of the
20191 	    * model group definition.
20192 	    */
20193 	    if ((WXS_MODELGROUPDEF_MODEL(refItem))->type ==
20194 		    XML_SCHEMA_TYPE_ALL) {
20195 		/*
20196 		* SPEC cos-all-limited (1)
20197 		* SPEC cos-all-limited (1.2)
20198 		* "It appears only as the value of one or both of the
20199 		* following properties:"
20200 		* (1.1) "the {model group} property of a model group
20201 		*        definition."
20202 		* (1.2) "the {term} property of a particle [... of] the "
20203 		* {content type} of a complex type definition."
20204 		*/
20205 		xmlSchemaCustomErr(ACTXT_CAST ctxt,
20206 		    /* TODO: error code */
20207 		    XML_SCHEMAP_COS_ALL_LIMITED,
20208 		    WXS_ITEM_NODE(particle), NULL,
20209 		    "A model group definition is referenced, but "
20210 		    "it contains an 'all' model group, which "
20211 		    "cannot be contained by model groups",
20212 		    NULL, NULL);
20213 		/* TODO: remove the particle. */
20214 		goto next_particle;
20215 	    }
20216 	    particle->children = (xmlSchemaTreeItemPtr) refItem;
20217 	} else {
20218 	    /*
20219 	    * TODO: Are referenced element declarations the only
20220 	    * other components we expect here?
20221 	    */
20222 	    particle->children = (xmlSchemaTreeItemPtr) refItem;
20223 	}
20224 next_particle:
20225 	particle = WXS_PTC_CAST particle->next;
20226     }
20227 }
20228 
20229 static int
xmlSchemaAreValuesEqual(xmlSchemaValPtr x,xmlSchemaValPtr y)20230 xmlSchemaAreValuesEqual(xmlSchemaValPtr x,
20231 		       xmlSchemaValPtr y)
20232 {
20233     xmlSchemaTypePtr tx, ty, ptx, pty;
20234     int ret;
20235 
20236     while (x != NULL) {
20237 	/* Same types. */
20238 	tx = xmlSchemaGetBuiltInType(xmlSchemaGetValType(x));
20239 	ty = xmlSchemaGetBuiltInType(xmlSchemaGetValType(y));
20240 	ptx = xmlSchemaGetPrimitiveType(tx);
20241 	pty = xmlSchemaGetPrimitiveType(ty);
20242 	/*
20243 	* (1) if a datatype T' is `derived` by `restriction` from an
20244 	* atomic datatype T then the `value space` of T' is a subset of
20245 	* the `value space` of T. */
20246 	/*
20247 	* (2) if datatypes T' and T'' are `derived` by `restriction`
20248 	* from a common atomic ancestor T then the `value space`s of T'
20249 	* and T'' may overlap.
20250 	*/
20251 	if (ptx != pty)
20252 	    return(0);
20253 	/*
20254 	* We assume computed values to be normalized, so do a fast
20255 	* string comparison for string based types.
20256 	*/
20257 	if ((ptx->builtInType == XML_SCHEMAS_STRING) ||
20258 	    WXS_IS_ANY_SIMPLE_TYPE(ptx)) {
20259 	    if (! xmlStrEqual(
20260 		xmlSchemaValueGetAsString(x),
20261 		xmlSchemaValueGetAsString(y)))
20262 		return (0);
20263 	} else {
20264 	    ret = xmlSchemaCompareValuesWhtsp(
20265 		x, XML_SCHEMA_WHITESPACE_PRESERVE,
20266 		y, XML_SCHEMA_WHITESPACE_PRESERVE);
20267 	    if (ret == -2)
20268 		return(-1);
20269 	    if (ret != 0)
20270 		return(0);
20271 	}
20272 	/*
20273 	* Lists.
20274 	*/
20275 	x = xmlSchemaValueGetNext(x);
20276 	if (x != NULL) {
20277 	    y = xmlSchemaValueGetNext(y);
20278 	    if (y == NULL)
20279 		return (0);
20280 	} else if (xmlSchemaValueGetNext(y) != NULL)
20281 	    return (0);
20282 	else
20283 	    return (1);
20284     }
20285     return (0);
20286 }
20287 
20288 /**
20289  * xmlSchemaResolveAttrUseReferences:
20290  * @item:  an attribute use
20291  * @ctxt:  a parser context
20292  *
20293  * Resolves the referenced attribute declaration.
20294  */
20295 static int
xmlSchemaResolveAttrUseReferences(xmlSchemaAttributeUsePtr ause,xmlSchemaParserCtxtPtr ctxt)20296 xmlSchemaResolveAttrUseReferences(xmlSchemaAttributeUsePtr ause,
20297 				  xmlSchemaParserCtxtPtr ctxt)
20298 {
20299     if ((ctxt == NULL) || (ause == NULL))
20300 	return(-1);
20301     if ((ause->attrDecl == NULL) ||
20302 	(ause->attrDecl->type != XML_SCHEMA_EXTRA_QNAMEREF))
20303 	return(0);
20304 
20305     {
20306 	xmlSchemaQNameRefPtr ref = WXS_QNAME_CAST ause->attrDecl;
20307 
20308 	/*
20309 	* TODO: Evaluate, what errors could occur if the declaration is not
20310 	* found.
20311 	*/
20312 	ause->attrDecl = xmlSchemaGetAttributeDecl(ctxt->schema,
20313 	    ref->name, ref->targetNamespace);
20314         if (ause->attrDecl == NULL) {
20315 	    xmlSchemaPResCompAttrErr(ctxt,
20316 		XML_SCHEMAP_SRC_RESOLVE,
20317 		WXS_BASIC_CAST ause, ause->node,
20318 		"ref", ref->name, ref->targetNamespace,
20319 		XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20320             return(ctxt->err);;
20321         }
20322     }
20323     return(0);
20324 }
20325 
20326 /**
20327  * xmlSchemaCheckAttrUsePropsCorrect:
20328  * @ctxt:  a parser context
20329  * @use:  an attribute use
20330  *
20331  * Schema Component Constraint:
20332  * Attribute Use Correct (au-props-correct)
20333  *
20334  */
20335 static int
xmlSchemaCheckAttrUsePropsCorrect(xmlSchemaParserCtxtPtr ctxt,xmlSchemaAttributeUsePtr use)20336 xmlSchemaCheckAttrUsePropsCorrect(xmlSchemaParserCtxtPtr ctxt,
20337 			     xmlSchemaAttributeUsePtr use)
20338 {
20339     if ((ctxt == NULL) || (use == NULL))
20340 	return(-1);
20341     if ((use->defValue == NULL) || (WXS_ATTRUSE_DECL(use) == NULL) ||
20342 	((WXS_ATTRUSE_DECL(use))->type != XML_SCHEMA_TYPE_ATTRIBUTE))
20343 	return(0);
20344 
20345     /*
20346     * SPEC au-props-correct (1)
20347     * "The values of the properties of an attribute use must be as
20348     * described in the property tableau in The Attribute Use Schema
20349     * Component ($3.5.1), modulo the impact of Missing
20350     * Sub-components ($5.3)."
20351     */
20352 
20353     if (((WXS_ATTRUSE_DECL(use))->defValue != NULL) &&
20354 	((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMAS_ATTR_FIXED) &&
20355         ((use->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20356     {
20357 	xmlSchemaPCustomErr(ctxt,
20358 	    XML_SCHEMAP_AU_PROPS_CORRECT_2,
20359 	    WXS_BASIC_CAST use, NULL,
20360 	    "The attribute declaration has a 'fixed' value constraint "
20361 	    ", thus the attribute use must also have a 'fixed' value "
20362 	    "constraint",
20363 	    NULL);
20364 	return(ctxt->err);
20365     }
20366     /*
20367     * Compute and check the value constraint's value.
20368     */
20369     if ((use->defVal != NULL) && (WXS_ATTRUSE_TYPEDEF(use) != NULL)) {
20370 	int ret;
20371 	/*
20372 	* TODO: The spec seems to be missing a check of the
20373 	* value constraint of the attribute use. We will do it here.
20374 	*/
20375 	/*
20376 	* SPEC a-props-correct (3)
20377 	*/
20378 	if (xmlSchemaIsDerivedFromBuiltInType(
20379 	    WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
20380 	{
20381 	    xmlSchemaCustomErr(ACTXT_CAST ctxt,
20382 		XML_SCHEMAP_AU_PROPS_CORRECT,
20383 		NULL, WXS_BASIC_CAST use,
20384 		"Value constraints are not allowed if the type definition "
20385 		"is or is derived from xs:ID",
20386 		NULL, NULL);
20387 	    return(ctxt->err);
20388 	}
20389 
20390 	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST ctxt,
20391 	    use->node, WXS_ATTRUSE_TYPEDEF(use),
20392 	    use->defValue, &(use->defVal),
20393 	    1, 1, 0);
20394 	if (ret != 0) {
20395 	    if (ret < 0) {
20396 		PERROR_INT2("xmlSchemaCheckAttrUsePropsCorrect",
20397 		    "calling xmlSchemaVCheckCVCSimpleType()");
20398 		return(-1);
20399 	    }
20400 	    xmlSchemaCustomErr(ACTXT_CAST ctxt,
20401 		XML_SCHEMAP_AU_PROPS_CORRECT,
20402 		NULL, WXS_BASIC_CAST use,
20403 		"The value of the value constraint is not valid",
20404 		NULL, NULL);
20405 	    return(ctxt->err);
20406 	}
20407     }
20408     /*
20409     * SPEC au-props-correct (2)
20410     * "If the {attribute declaration} has a fixed
20411     * {value constraint}, then if the attribute use itself has a
20412     * {value constraint}, it must also be fixed and its value must match
20413     * that of the {attribute declaration}'s {value constraint}."
20414     */
20415     if (((WXS_ATTRUSE_DECL(use))->defVal != NULL) &&
20416 	(((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20417     {
20418 	if (! xmlSchemaAreValuesEqual(use->defVal,
20419 		(WXS_ATTRUSE_DECL(use))->defVal))
20420 	{
20421 	    xmlSchemaPCustomErr(ctxt,
20422 		XML_SCHEMAP_AU_PROPS_CORRECT_2,
20423 		WXS_BASIC_CAST use, NULL,
20424 		"The 'fixed' value constraint of the attribute use "
20425 		"must match the attribute declaration's value "
20426 		"constraint '%s'",
20427 		(WXS_ATTRUSE_DECL(use))->defValue);
20428 	}
20429 	return(ctxt->err);
20430     }
20431     return(0);
20432 }
20433 
20434 
20435 
20436 
20437 /**
20438  * xmlSchemaResolveAttrTypeReferences:
20439  * @item:  an attribute declaration
20440  * @ctxt:  a parser context
20441  *
20442  * Resolves the referenced type definition component.
20443  */
20444 static int
xmlSchemaResolveAttrTypeReferences(xmlSchemaAttributePtr item,xmlSchemaParserCtxtPtr ctxt)20445 xmlSchemaResolveAttrTypeReferences(xmlSchemaAttributePtr item,
20446 				   xmlSchemaParserCtxtPtr ctxt)
20447 {
20448     /*
20449     * The simple type definition corresponding to the <simpleType> element
20450     * information item in the [children], if present, otherwise the simple
20451     * type definition `resolved` to by the `actual value` of the type
20452     * [attribute], if present, otherwise the `simple ur-type definition`.
20453     */
20454     if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
20455 	return(0);
20456     item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
20457     if (item->subtypes != NULL)
20458         return(0);
20459     if (item->typeName != NULL) {
20460         xmlSchemaTypePtr type;
20461 
20462 	type = xmlSchemaGetType(ctxt->schema, item->typeName,
20463 	    item->typeNs);
20464 	if ((type == NULL) || (! WXS_IS_SIMPLE(type))) {
20465 	    xmlSchemaPResCompAttrErr(ctxt,
20466 		XML_SCHEMAP_SRC_RESOLVE,
20467 		WXS_BASIC_CAST item, item->node,
20468 		"type", item->typeName, item->typeNs,
20469 		XML_SCHEMA_TYPE_SIMPLE, NULL);
20470 	    return(ctxt->err);
20471 	} else
20472 	    item->subtypes = type;
20473 
20474     } else {
20475 	/*
20476 	* The type defaults to the xs:anySimpleType.
20477 	*/
20478 	item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
20479     }
20480     return(0);
20481 }
20482 
20483 /**
20484  * xmlSchemaResolveIDCKeyReferences:
20485  * @idc:  the identity-constraint definition
20486  * @ctxt:  the schema parser context
20487  * @name:  the attribute name
20488  *
20489  * Resolve keyRef references to key/unique IDCs.
20490  * Schema Component Constraint:
20491  *   Identity-constraint Definition Properties Correct (c-props-correct)
20492  */
20493 static int
xmlSchemaResolveIDCKeyReferences(xmlSchemaIDCPtr idc,xmlSchemaParserCtxtPtr pctxt)20494 xmlSchemaResolveIDCKeyReferences(xmlSchemaIDCPtr idc,
20495 			  xmlSchemaParserCtxtPtr pctxt)
20496 {
20497     if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
20498         return(0);
20499     if (idc->ref->name != NULL) {
20500 	idc->ref->item = (xmlSchemaBasicItemPtr)
20501 	    xmlSchemaGetIDC(pctxt->schema, idc->ref->name,
20502 		idc->ref->targetNamespace);
20503         if (idc->ref->item == NULL) {
20504 	    /*
20505 	    * TODO: It is actually not an error to fail to resolve
20506 	    * at this stage. BUT we need to be that strict!
20507 	    */
20508 	    xmlSchemaPResCompAttrErr(pctxt,
20509 		XML_SCHEMAP_SRC_RESOLVE,
20510 		WXS_BASIC_CAST idc, idc->node,
20511 		"refer", idc->ref->name,
20512 		idc->ref->targetNamespace,
20513 		XML_SCHEMA_TYPE_IDC_KEY, NULL);
20514             return(pctxt->err);
20515 	} else if (idc->ref->item->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
20516 	    /*
20517 	    * SPEC c-props-correct (1)
20518 	    */
20519 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
20520 		XML_SCHEMAP_C_PROPS_CORRECT,
20521 		NULL, WXS_BASIC_CAST idc,
20522 		"The keyref references a keyref",
20523 		NULL, NULL);
20524 	    idc->ref->item = NULL;
20525 	    return(pctxt->err);
20526 	} else {
20527 	    if (idc->nbFields !=
20528 		((xmlSchemaIDCPtr) idc->ref->item)->nbFields) {
20529 		xmlChar *str = NULL;
20530 		xmlSchemaIDCPtr refer;
20531 
20532 		refer = (xmlSchemaIDCPtr) idc->ref->item;
20533 		/*
20534 		* SPEC c-props-correct(2)
20535 		* "If the {identity-constraint category} is keyref,
20536 		* the cardinality of the {fields} must equal that of
20537 		* the {fields} of the {referenced key}.
20538 		*/
20539 		xmlSchemaCustomErr(ACTXT_CAST pctxt,
20540 		    XML_SCHEMAP_C_PROPS_CORRECT,
20541 		    NULL, WXS_BASIC_CAST idc,
20542 		    "The cardinality of the keyref differs from the "
20543 		    "cardinality of the referenced key/unique '%s'",
20544 		    xmlSchemaFormatQName(&str, refer->targetNamespace,
20545 			refer->name),
20546 		    NULL);
20547 		FREE_AND_NULL(str)
20548 		return(pctxt->err);
20549 	    }
20550 	}
20551     }
20552     return(0);
20553 }
20554 
20555 static int
xmlSchemaResolveAttrUseProhibReferences(xmlSchemaAttributeUseProhibPtr prohib,xmlSchemaParserCtxtPtr pctxt)20556 xmlSchemaResolveAttrUseProhibReferences(xmlSchemaAttributeUseProhibPtr prohib,
20557 				       xmlSchemaParserCtxtPtr pctxt)
20558 {
20559     if (xmlSchemaGetAttributeDecl(pctxt->schema, prohib->name,
20560 	prohib->targetNamespace) == NULL) {
20561 
20562 	xmlSchemaPResCompAttrErr(pctxt,
20563 	    XML_SCHEMAP_SRC_RESOLVE,
20564 	    NULL, prohib->node,
20565 	    "ref", prohib->name, prohib->targetNamespace,
20566 	    XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20567 	return(XML_SCHEMAP_SRC_RESOLVE);
20568     }
20569     return(0);
20570 }
20571 
20572 #define WXS_REDEFINED_TYPE(c) \
20573 (((xmlSchemaTypePtr) item)->flags & XML_SCHEMAS_TYPE_REDEFINED)
20574 
20575 #define WXS_REDEFINED_MODEL_GROUP_DEF(c) \
20576 (((xmlSchemaModelGroupDefPtr) item)->flags & XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20577 
20578 #define WXS_REDEFINED_ATTR_GROUP(c) \
20579 (((xmlSchemaAttributeGroupPtr) item)->flags & XML_SCHEMAS_ATTRGROUP_REDEFINED)
20580 
20581 static int
xmlSchemaCheckSRCRedefineFirst(xmlSchemaParserCtxtPtr pctxt)20582 xmlSchemaCheckSRCRedefineFirst(xmlSchemaParserCtxtPtr pctxt)
20583 {
20584     int err = 0;
20585     xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20586     xmlSchemaBasicItemPtr prev, item;
20587     int wasRedefined;
20588 
20589     if (redef == NULL)
20590 	return(0);
20591 
20592     do {
20593 	item = redef->item;
20594 	/*
20595 	* First try to locate the redefined component in the
20596 	* schema graph starting with the redefined schema.
20597 	* NOTE: According to this schema bug entry:
20598 	*   http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005OctDec/0019.html
20599 	*   it's not clear if the referenced component needs to originate
20600 	*   from the <redefine>d schema _document_ or the schema; the latter
20601 	*   would include all imported and included sub-schemas of the
20602 	*   <redefine>d schema. Currently the latter approach is used.
20603 	*   SUPPLEMENT: It seems that the WG moves towards the latter
20604 	*   approach, so we are doing it right.
20605 	*
20606 	*/
20607 	prev = xmlSchemaFindRedefCompInGraph(
20608 	    redef->targetBucket, item->type,
20609 	    redef->refName, redef->refTargetNs);
20610 	if (prev == NULL) {
20611 	    xmlChar *str = NULL;
20612 	    xmlNodePtr node;
20613 
20614 	    /*
20615 	    * SPEC src-redefine:
20616 	    * (6.2.1) "The `actual value` of its own name attribute plus
20617 	    * target namespace must successfully `resolve` to a model
20618 	    * group definition in I."
20619 	    * (7.2.1) "The `actual value` of its own name attribute plus
20620 	    * target namespace must successfully `resolve` to an attribute
20621 	    * group definition in I."
20622 
20623 	    *
20624 	    * Note that, if we are redefining with the use of references
20625 	    * to components, the spec assumes the src-resolve to be used;
20626 	    * but this won't assure that we search only *inside* the
20627 	    * redefined schema.
20628 	    */
20629 	    if (redef->reference)
20630 		node = WXS_ITEM_NODE(redef->reference);
20631 	    else
20632 		node = WXS_ITEM_NODE(item);
20633 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
20634 		/*
20635 		* TODO: error code.
20636 		* Probably XML_SCHEMAP_SRC_RESOLVE, if this is using the
20637 		* reference kind.
20638 		*/
20639 		XML_SCHEMAP_SRC_REDEFINE, node, NULL,
20640 		"The %s '%s' to be redefined could not be found in "
20641 		"the redefined schema",
20642 		WXS_ITEM_TYPE_NAME(item),
20643 		xmlSchemaFormatQName(&str, redef->refTargetNs,
20644 		    redef->refName));
20645 	    FREE_AND_NULL(str);
20646 	    err = pctxt->err;
20647 	    redef = redef->next;
20648 	    continue;
20649 	}
20650 	/*
20651 	* TODO: Obtaining and setting the redefinition state is really
20652 	* clumsy.
20653 	*/
20654 	wasRedefined = 0;
20655 	switch (item->type) {
20656 	    case XML_SCHEMA_TYPE_COMPLEX:
20657 	    case XML_SCHEMA_TYPE_SIMPLE:
20658 		if ((WXS_TYPE_CAST prev)->flags &
20659 		    XML_SCHEMAS_TYPE_REDEFINED)
20660 		{
20661 		    wasRedefined = 1;
20662 		    break;
20663 		}
20664 		/* Mark it as redefined. */
20665 		(WXS_TYPE_CAST prev)->flags |= XML_SCHEMAS_TYPE_REDEFINED;
20666 		/*
20667 		* Assign the redefined type to the
20668 		* base type of the redefining type.
20669 		* TODO: How
20670 		*/
20671 		((xmlSchemaTypePtr) item)->baseType =
20672 		    (xmlSchemaTypePtr) prev;
20673 		break;
20674 	    case XML_SCHEMA_TYPE_GROUP:
20675 		if ((WXS_MODEL_GROUPDEF_CAST prev)->flags &
20676 		    XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20677 		{
20678 		    wasRedefined = 1;
20679 		    break;
20680 		}
20681 		/* Mark it as redefined. */
20682 		(WXS_MODEL_GROUPDEF_CAST prev)->flags |=
20683 		    XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED;
20684 		if (redef->reference != NULL) {
20685 		    /*
20686 		    * Overwrite the QName-reference with the
20687 		    * referenced model group def.
20688 		    */
20689 		    (WXS_PTC_CAST redef->reference)->children =
20690 			WXS_TREE_CAST prev;
20691 		}
20692 		redef->target = prev;
20693 		break;
20694 	    case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20695 		if ((WXS_ATTR_GROUP_CAST prev)->flags &
20696 		    XML_SCHEMAS_ATTRGROUP_REDEFINED)
20697 		{
20698 		    wasRedefined = 1;
20699 		    break;
20700 		}
20701 		(WXS_ATTR_GROUP_CAST prev)->flags |=
20702 		    XML_SCHEMAS_ATTRGROUP_REDEFINED;
20703 		if (redef->reference != NULL) {
20704 		    /*
20705 		    * Assign the redefined attribute group to the
20706 		    * QName-reference component.
20707 		    * This is the easy case, since we will just
20708 		    * expand the redefined group.
20709 		    */
20710 		    (WXS_QNAME_CAST redef->reference)->item = prev;
20711 		    redef->target = NULL;
20712 		} else {
20713 		    /*
20714 		    * This is the complicated case: we need
20715 		    * to apply src-redefine (7.2.2) at a later
20716 		    * stage, i.e. when attribute group references
20717 		    * have been expanded and simple types have
20718 		    * been fixed.
20719 		    */
20720 		    redef->target = prev;
20721 		}
20722 		break;
20723 	    default:
20724 		PERROR_INT("xmlSchemaResolveRedefReferences",
20725 		    "Unexpected redefined component type");
20726 		return(-1);
20727 	}
20728 	if (wasRedefined) {
20729 	    xmlChar *str = NULL;
20730 	    xmlNodePtr node;
20731 
20732 	    if (redef->reference)
20733 		node = WXS_ITEM_NODE(redef->reference);
20734 	    else
20735 		node = WXS_ITEM_NODE(redef->item);
20736 
20737 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
20738 		/* TODO: error code. */
20739 		XML_SCHEMAP_SRC_REDEFINE,
20740 		node, NULL,
20741 		"The referenced %s was already redefined. Multiple "
20742 		"redefinition of the same component is not supported",
20743 		xmlSchemaGetComponentDesignation(&str, prev),
20744 		NULL);
20745 	    FREE_AND_NULL(str)
20746 	    err = pctxt->err;
20747 	    redef = redef->next;
20748 	    continue;
20749 	}
20750 	redef = redef->next;
20751     } while (redef != NULL);
20752 
20753     return(err);
20754 }
20755 
20756 static int
xmlSchemaCheckSRCRedefineSecond(xmlSchemaParserCtxtPtr pctxt)20757 xmlSchemaCheckSRCRedefineSecond(xmlSchemaParserCtxtPtr pctxt)
20758 {
20759     int err = 0;
20760     xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20761     xmlSchemaBasicItemPtr item;
20762 
20763     if (redef == NULL)
20764 	return(0);
20765 
20766     do {
20767 	if (redef->target == NULL) {
20768 	    redef = redef->next;
20769 	    continue;
20770 	}
20771 	item = redef->item;
20772 
20773 	switch (item->type) {
20774 	    case XML_SCHEMA_TYPE_SIMPLE:
20775 	    case XML_SCHEMA_TYPE_COMPLEX:
20776 		/*
20777 		* Since the spec wants the {name} of the redefined
20778 		* type to be 'absent', we'll NULL it.
20779 		*/
20780 		(WXS_TYPE_CAST redef->target)->name = NULL;
20781 
20782 		/*
20783 		* TODO: Seems like there's nothing more to do. The normal
20784 		* inheritance mechanism is used. But not 100% sure.
20785 		*/
20786 		break;
20787 	    case XML_SCHEMA_TYPE_GROUP:
20788 		/*
20789 		* URGENT TODO:
20790 		* SPEC src-redefine:
20791 		* (6.2.2) "The {model group} of the model group definition
20792 		* which corresponds to it per XML Representation of Model
20793 		* Group Definition Schema Components ($3.7.2) must be a
20794 		* `valid restriction` of the {model group} of that model
20795 		* group definition in I, as defined in Particle Valid
20796 		* (Restriction) ($3.9.6)."
20797 		*/
20798 		break;
20799 	    case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20800 		/*
20801 		* SPEC src-redefine:
20802 		* (7.2.2) "The {attribute uses} and {attribute wildcard} of
20803 		* the attribute group definition which corresponds to it
20804 		* per XML Representation of Attribute Group Definition Schema
20805 		* Components ($3.6.2) must be `valid restrictions` of the
20806 		* {attribute uses} and {attribute wildcard} of that attribute
20807 		* group definition in I, as defined in clause 2, clause 3 and
20808 		* clause 4 of Derivation Valid (Restriction, Complex)
20809 		* ($3.4.6) (where references to the base type definition are
20810 		* understood as references to the attribute group definition
20811 		* in I)."
20812 		*/
20813 		err = xmlSchemaCheckDerivationOKRestriction2to4(pctxt,
20814 		    XML_SCHEMA_ACTION_REDEFINE,
20815 		    item, redef->target,
20816 		    (WXS_ATTR_GROUP_CAST item)->attrUses,
20817 		    (WXS_ATTR_GROUP_CAST redef->target)->attrUses,
20818 		    (WXS_ATTR_GROUP_CAST item)->attributeWildcard,
20819 		    (WXS_ATTR_GROUP_CAST redef->target)->attributeWildcard);
20820 		if (err == -1)
20821 		    return(-1);
20822 		break;
20823 	    default:
20824 		break;
20825 	}
20826 	redef = redef->next;
20827     } while (redef != NULL);
20828     return(0);
20829 }
20830 
20831 
20832 static int
xmlSchemaAddComponents(xmlSchemaParserCtxtPtr pctxt,xmlSchemaBucketPtr bucket)20833 xmlSchemaAddComponents(xmlSchemaParserCtxtPtr pctxt,
20834 		       xmlSchemaBucketPtr bucket)
20835 {
20836     xmlSchemaBasicItemPtr item;
20837     int err;
20838     xmlHashTablePtr *table;
20839     const xmlChar *name;
20840     int i;
20841 
20842 #define WXS_GET_GLOBAL_HASH(c, slot) { \
20843     if (WXS_IS_BUCKET_IMPMAIN((c)->type)) \
20844 	table = &(WXS_IMPBUCKET((c))->schema->slot); \
20845     else \
20846 	table = &(WXS_INCBUCKET((c))->ownerImport->schema->slot); }
20847 
20848     /*
20849     * Add global components to the schema's hash tables.
20850     * This is the place where duplicate components will be
20851     * detected.
20852     * TODO: I think normally we should support imports of the
20853     *   same namespace from multiple locations. We don't do currently,
20854     *   but if we do then according to:
20855     *   http://www.w3.org/Bugs/Public/show_bug.cgi?id=2224
20856     *   we would need, if imported directly, to import redefined
20857     *   components as well to be able to catch clashing components.
20858     *   (I hope I'll still know what this means after some months :-()
20859     */
20860     if (bucket == NULL)
20861 	return(-1);
20862     if (bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED)
20863 	return(0);
20864     bucket->flags |= XML_SCHEMA_BUCKET_COMPS_ADDED;
20865 
20866     for (i = 0; i < bucket->globals->nbItems; i++) {
20867 	item = bucket->globals->items[i];
20868 	table = NULL;
20869 	switch (item->type) {
20870 	    case XML_SCHEMA_TYPE_COMPLEX:
20871 	    case XML_SCHEMA_TYPE_SIMPLE:
20872 		if (WXS_REDEFINED_TYPE(item))
20873 		    continue;
20874 		name = (WXS_TYPE_CAST item)->name;
20875 		WXS_GET_GLOBAL_HASH(bucket, typeDecl)
20876 		break;
20877 	    case XML_SCHEMA_TYPE_ELEMENT:
20878 		name = (WXS_ELEM_CAST item)->name;
20879 		WXS_GET_GLOBAL_HASH(bucket, elemDecl)
20880 		break;
20881 	    case XML_SCHEMA_TYPE_ATTRIBUTE:
20882 		name = (WXS_ATTR_CAST item)->name;
20883 		WXS_GET_GLOBAL_HASH(bucket, attrDecl)
20884 		break;
20885 	    case XML_SCHEMA_TYPE_GROUP:
20886 		if (WXS_REDEFINED_MODEL_GROUP_DEF(item))
20887 		    continue;
20888 		name = (WXS_MODEL_GROUPDEF_CAST item)->name;
20889 		WXS_GET_GLOBAL_HASH(bucket, groupDecl)
20890 		break;
20891 	    case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20892 		if (WXS_REDEFINED_ATTR_GROUP(item))
20893 		    continue;
20894 		name = (WXS_ATTR_GROUP_CAST item)->name;
20895 		WXS_GET_GLOBAL_HASH(bucket, attrgrpDecl)
20896 		break;
20897 	    case XML_SCHEMA_TYPE_IDC_KEY:
20898 	    case XML_SCHEMA_TYPE_IDC_UNIQUE:
20899 	    case XML_SCHEMA_TYPE_IDC_KEYREF:
20900 		name = (WXS_IDC_CAST item)->name;
20901 		WXS_GET_GLOBAL_HASH(bucket, idcDef)
20902 		break;
20903 	    case XML_SCHEMA_TYPE_NOTATION:
20904 		name = ((xmlSchemaNotationPtr) item)->name;
20905 		WXS_GET_GLOBAL_HASH(bucket, notaDecl)
20906 		break;
20907 	    default:
20908 		PERROR_INT("xmlSchemaAddComponents",
20909 		    "Unexpected global component type");
20910 		continue;
20911 	}
20912 	if (*table == NULL) {
20913 	    *table = xmlHashCreateDict(10, pctxt->dict);
20914 	    if (*table == NULL) {
20915 		PERROR_INT("xmlSchemaAddComponents",
20916 		    "failed to create a component hash table");
20917 		return(-1);
20918 	    }
20919 	}
20920 	err = xmlHashAddEntry(*table, name, item);
20921 	if (err != 0) {
20922 	    xmlChar *str = NULL;
20923 
20924 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
20925 		XML_SCHEMAP_REDEFINED_TYPE,
20926 		WXS_ITEM_NODE(item),
20927 		WXS_BASIC_CAST item,
20928 		"A global %s '%s' does already exist",
20929 		WXS_ITEM_TYPE_NAME(item),
20930 		xmlSchemaGetComponentQName(&str, item));
20931 	    FREE_AND_NULL(str);
20932 	}
20933     }
20934     /*
20935     * Process imported/included schemas.
20936     */
20937     if (bucket->relations != NULL) {
20938 	xmlSchemaSchemaRelationPtr rel = bucket->relations;
20939 	do {
20940 	    if ((rel->bucket != NULL) &&
20941 		((rel->bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED) == 0)) {
20942 		if (xmlSchemaAddComponents(pctxt, rel->bucket) == -1)
20943 		    return(-1);
20944 	    }
20945 	    rel = rel->next;
20946 	} while (rel != NULL);
20947     }
20948     return(0);
20949 }
20950 
20951 static int
xmlSchemaFixupComponents(xmlSchemaParserCtxtPtr pctxt,xmlSchemaBucketPtr rootBucket)20952 xmlSchemaFixupComponents(xmlSchemaParserCtxtPtr pctxt,
20953 			 xmlSchemaBucketPtr rootBucket)
20954 {
20955     xmlSchemaConstructionCtxtPtr con = pctxt->constructor;
20956     xmlSchemaTreeItemPtr item, *items;
20957     int nbItems, i, ret = 0;
20958     xmlSchemaBucketPtr oldbucket = con->bucket;
20959     xmlSchemaElementPtr elemDecl;
20960 
20961 #define FIXHFAILURE if (pctxt->err == XML_SCHEMAP_INTERNAL) goto exit_failure;
20962 
20963     if ((con->pending == NULL) ||
20964 	(con->pending->nbItems == 0))
20965 	return(0);
20966 
20967     /*
20968     * Since xmlSchemaFixupComplexType() will create new particles
20969     * (local components), and those particle components need a bucket
20970     * on the constructor, we'll assure here that the constructor has
20971     * a bucket.
20972     * TODO: Think about storing locals _only_ on the main bucket.
20973     */
20974     if (con->bucket == NULL)
20975 	con->bucket = rootBucket;
20976 
20977     /* TODO:
20978     * SPEC (src-redefine):
20979     * (6.2) "If it has no such self-reference, then all of the
20980     * following must be true:"
20981 
20982     * (6.2.2) The {model group} of the model group definition which
20983     * corresponds to it per XML Representation of Model Group
20984     * Definition Schema Components ($3.7.2) must be a `valid
20985     * restriction` of the {model group} of that model group definition
20986     * in I, as defined in Particle Valid (Restriction) ($3.9.6)."
20987     */
20988     xmlSchemaCheckSRCRedefineFirst(pctxt);
20989 
20990     /*
20991     * Add global components to the schemata's hash tables.
20992     */
20993     xmlSchemaAddComponents(pctxt, rootBucket);
20994 
20995     pctxt->ctxtType = NULL;
20996     items = (xmlSchemaTreeItemPtr *) con->pending->items;
20997     nbItems = con->pending->nbItems;
20998     /*
20999     * Now that we have parsed *all* the schema document(s) and converted
21000     * them to schema components, we can resolve references, apply component
21001     * constraints, create the FSA from the content model, etc.
21002     */
21003     /*
21004     * Resolve references of..
21005     *
21006     * 1. element declarations:
21007     *   - the type definition
21008     *   - the substitution group affiliation
21009     * 2. simple/complex types:
21010     *   - the base type definition
21011     *   - the memberTypes of union types
21012     *   - the itemType of list types
21013     * 3. attributes declarations and attribute uses:
21014     *   - the type definition
21015     *   - if an attribute use, then the attribute declaration
21016     * 4. attribute group references:
21017     *   - the attribute group definition
21018     * 5. particles:
21019     *   - the term of the particle (e.g. a model group)
21020     * 6. IDC key-references:
21021     *   - the referenced IDC 'key' or 'unique' definition
21022     * 7. Attribute prohibitions which had a "ref" attribute.
21023     */
21024     for (i = 0; i < nbItems; i++) {
21025 	item = items[i];
21026 	switch (item->type) {
21027 	    case XML_SCHEMA_TYPE_ELEMENT:
21028 		xmlSchemaResolveElementReferences(
21029 		    (xmlSchemaElementPtr) item, pctxt);
21030 		FIXHFAILURE;
21031 		break;
21032 	    case XML_SCHEMA_TYPE_COMPLEX:
21033 	    case XML_SCHEMA_TYPE_SIMPLE:
21034 		xmlSchemaResolveTypeReferences(
21035 		    (xmlSchemaTypePtr) item, pctxt);
21036 		FIXHFAILURE;
21037 		break;
21038 	    case XML_SCHEMA_TYPE_ATTRIBUTE:
21039 		xmlSchemaResolveAttrTypeReferences(
21040 		    (xmlSchemaAttributePtr) item, pctxt);
21041 		FIXHFAILURE;
21042 		break;
21043 	    case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
21044 		xmlSchemaResolveAttrUseReferences(
21045 		    (xmlSchemaAttributeUsePtr) item, pctxt);
21046 		FIXHFAILURE;
21047 		break;
21048 	    case XML_SCHEMA_EXTRA_QNAMEREF:
21049 		if ((WXS_QNAME_CAST item)->itemType ==
21050 		    XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
21051 		{
21052 		    xmlSchemaResolveAttrGroupReferences(
21053 			WXS_QNAME_CAST item, pctxt);
21054 		}
21055 		FIXHFAILURE;
21056 		break;
21057 	    case XML_SCHEMA_TYPE_SEQUENCE:
21058 	    case XML_SCHEMA_TYPE_CHOICE:
21059 	    case XML_SCHEMA_TYPE_ALL:
21060 		xmlSchemaResolveModelGroupParticleReferences(pctxt,
21061 		    WXS_MODEL_GROUP_CAST item);
21062 		FIXHFAILURE;
21063 		break;
21064 	    case XML_SCHEMA_TYPE_IDC_KEY:
21065 	    case XML_SCHEMA_TYPE_IDC_UNIQUE:
21066 	    case XML_SCHEMA_TYPE_IDC_KEYREF:
21067 		xmlSchemaResolveIDCKeyReferences(
21068 		    (xmlSchemaIDCPtr) item, pctxt);
21069 		FIXHFAILURE;
21070 		break;
21071 	    case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
21072 		/*
21073 		* Handle attribute prohibition which had a
21074 		* "ref" attribute.
21075 		*/
21076 		xmlSchemaResolveAttrUseProhibReferences(
21077 		    WXS_ATTR_PROHIB_CAST item, pctxt);
21078 		FIXHFAILURE;
21079 		break;
21080 	    default:
21081 		break;
21082 	}
21083     }
21084     if (pctxt->nberrors != 0)
21085 	goto exit_error;
21086 
21087     /*
21088     * Now that all references are resolved we
21089     * can check for circularity of...
21090     * 1. the base axis of type definitions
21091     * 2. nested model group definitions
21092     * 3. nested attribute group definitions
21093     * TODO: check for circular substitution groups.
21094     */
21095     for (i = 0; i < nbItems; i++) {
21096 	item = items[i];
21097 	/*
21098 	* Let's better stop on the first error here.
21099 	*/
21100 	switch (item->type) {
21101 	    case XML_SCHEMA_TYPE_COMPLEX:
21102 	    case XML_SCHEMA_TYPE_SIMPLE:
21103 		xmlSchemaCheckTypeDefCircular(
21104 		    (xmlSchemaTypePtr) item, pctxt);
21105 		FIXHFAILURE;
21106 		if (pctxt->nberrors != 0)
21107 		    goto exit_error;
21108 		break;
21109 	    case XML_SCHEMA_TYPE_GROUP:
21110 		xmlSchemaCheckGroupDefCircular(
21111 		    (xmlSchemaModelGroupDefPtr) item, pctxt);
21112 		FIXHFAILURE;
21113 		if (pctxt->nberrors != 0)
21114 		    goto exit_error;
21115 		break;
21116 	    case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
21117 		xmlSchemaCheckAttrGroupCircular(
21118 		    (xmlSchemaAttributeGroupPtr) item, pctxt);
21119 		FIXHFAILURE;
21120 		if (pctxt->nberrors != 0)
21121 		    goto exit_error;
21122 		break;
21123 	    default:
21124 		break;
21125 	}
21126     }
21127     if (pctxt->nberrors != 0)
21128 	goto exit_error;
21129     /*
21130     * Model group definition references:
21131     * Such a reference is reflected by a particle at the component
21132     * level. Until now the 'term' of such particles pointed
21133     * to the model group definition; this was done, in order to
21134     * ease circularity checks. Now we need to set the 'term' of
21135     * such particles to the model group of the model group definition.
21136     */
21137     for (i = 0; i < nbItems; i++) {
21138 	item = items[i];
21139 	switch (item->type) {
21140 	    case XML_SCHEMA_TYPE_SEQUENCE:
21141 	    case XML_SCHEMA_TYPE_CHOICE:
21142 		xmlSchemaModelGroupToModelGroupDefFixup(pctxt,
21143 		    WXS_MODEL_GROUP_CAST item);
21144 		break;
21145 	    default:
21146 		break;
21147 	}
21148     }
21149     if (pctxt->nberrors != 0)
21150 	goto exit_error;
21151     /*
21152     * Expand attribute group references of attribute group definitions.
21153     */
21154     for (i = 0; i < nbItems; i++) {
21155 	item = items[i];
21156 	switch (item->type) {
21157             case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
21158 		if ((! WXS_ATTR_GROUP_EXPANDED(item)) &&
21159 		    WXS_ATTR_GROUP_HAS_REFS(item))
21160 		{
21161 		    xmlSchemaAttributeGroupExpandRefs(pctxt,
21162 			WXS_ATTR_GROUP_CAST item);
21163 		    FIXHFAILURE;
21164 		}
21165 		break;
21166 	    default:
21167 		break;
21168 	}
21169     }
21170     if (pctxt->nberrors != 0)
21171 	goto exit_error;
21172     /*
21173     * First compute the variety of simple types. This is needed as
21174     * a separate step, since otherwise we won't be able to detect
21175     * circular union types in all cases.
21176     */
21177     for (i = 0; i < nbItems; i++) {
21178 	item = items[i];
21179 	switch (item->type) {
21180             case XML_SCHEMA_TYPE_SIMPLE:
21181 		if (WXS_IS_TYPE_NOT_FIXED_1((xmlSchemaTypePtr) item)) {
21182 		    xmlSchemaFixupSimpleTypeStageOne(pctxt,
21183 			(xmlSchemaTypePtr) item);
21184 		    FIXHFAILURE;
21185 		}
21186 		break;
21187 	    default:
21188 		break;
21189 	}
21190     }
21191     if (pctxt->nberrors != 0)
21192 	goto exit_error;
21193     /*
21194     * Detect circular union types. Note that this needs the variety to
21195     * be already computed.
21196     */
21197     for (i = 0; i < nbItems; i++) {
21198 	item = items[i];
21199 	switch (item->type) {
21200             case XML_SCHEMA_TYPE_SIMPLE:
21201 		if (((xmlSchemaTypePtr) item)->memberTypes != NULL) {
21202 		    xmlSchemaCheckUnionTypeDefCircular(pctxt,
21203 			(xmlSchemaTypePtr) item);
21204 		    FIXHFAILURE;
21205 		}
21206 		break;
21207 	    default:
21208 		break;
21209 	}
21210     }
21211     if (pctxt->nberrors != 0)
21212 	goto exit_error;
21213 
21214     /*
21215     * Do the complete type fixup for simple types.
21216     */
21217     for (i = 0; i < nbItems; i++) {
21218 	item = items[i];
21219 	switch (item->type) {
21220             case XML_SCHEMA_TYPE_SIMPLE:
21221 		if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
21222 		    xmlSchemaFixupSimpleTypeStageTwo(pctxt, WXS_TYPE_CAST item);
21223 		    FIXHFAILURE;
21224 		}
21225 		break;
21226 	    default:
21227 		break;
21228 	}
21229     }
21230     if (pctxt->nberrors != 0)
21231 	goto exit_error;
21232     /*
21233     * At this point we need build and check all simple types.
21234     */
21235     /*
21236     * Apply constraints for attribute declarations.
21237     */
21238     for (i = 0; i < nbItems; i++) {
21239 	item = items[i];
21240 	switch (item->type) {
21241 	    case XML_SCHEMA_TYPE_ATTRIBUTE:
21242 		xmlSchemaCheckAttrPropsCorrect(pctxt, WXS_ATTR_CAST item);
21243 		FIXHFAILURE;
21244 		break;
21245 	    default:
21246 		break;
21247 	}
21248     }
21249     if (pctxt->nberrors != 0)
21250 	goto exit_error;
21251     /*
21252     * Apply constraints for attribute uses.
21253     */
21254     for (i = 0; i < nbItems; i++) {
21255 	item = items[i];
21256 	switch (item->type) {
21257 	    case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
21258 		if (((xmlSchemaAttributeUsePtr)item)->defValue != NULL) {
21259 		    xmlSchemaCheckAttrUsePropsCorrect(pctxt,
21260 			WXS_ATTR_USE_CAST item);
21261 		    FIXHFAILURE;
21262 		}
21263 		break;
21264 	    default:
21265 		break;
21266 	}
21267     }
21268     if (pctxt->nberrors != 0)
21269 	goto exit_error;
21270 
21271     /*
21272     * Apply constraints for attribute group definitions.
21273     */
21274     for (i = 0; i < nbItems; i++) {
21275 	item = items[i];
21276 	switch (item->type) {
21277 	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
21278 	    if (( (WXS_ATTR_GROUP_CAST item)->attrUses != NULL) &&
21279 		( (WXS_LIST_CAST (WXS_ATTR_GROUP_CAST item)->attrUses)->nbItems > 1))
21280 	    {
21281 		xmlSchemaCheckAGPropsCorrect(pctxt, WXS_ATTR_GROUP_CAST item);
21282 		FIXHFAILURE;
21283 	    }
21284 	    break;
21285 	default:
21286 	    break;
21287 	}
21288     }
21289     if (pctxt->nberrors != 0)
21290 	goto exit_error;
21291 
21292     /*
21293     * Apply constraints for redefinitions.
21294     */
21295     if (WXS_CONSTRUCTOR(pctxt)->redefs != NULL)
21296 	xmlSchemaCheckSRCRedefineSecond(pctxt);
21297     if (pctxt->nberrors != 0)
21298 	goto exit_error;
21299 
21300     /*
21301     * Complex types are built and checked.
21302     */
21303     for (i = 0; i < nbItems; i++) {
21304 	item = con->pending->items[i];
21305 	switch (item->type) {
21306 	    case XML_SCHEMA_TYPE_COMPLEX:
21307 		if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
21308 		    xmlSchemaFixupComplexType(pctxt, WXS_TYPE_CAST item);
21309 		    FIXHFAILURE;
21310 		}
21311 		break;
21312 	    default:
21313 		break;
21314 	}
21315     }
21316     if (pctxt->nberrors != 0)
21317 	goto exit_error;
21318 
21319     /*
21320     * The list could have changed, since xmlSchemaFixupComplexType()
21321     * will create particles and model groups in some cases.
21322     */
21323     items = (xmlSchemaTreeItemPtr *) con->pending->items;
21324     nbItems = con->pending->nbItems;
21325 
21326     /*
21327     * Apply some constraints for element declarations.
21328     */
21329     for (i = 0; i < nbItems; i++) {
21330 	item = items[i];
21331 	switch (item->type) {
21332 	    case XML_SCHEMA_TYPE_ELEMENT:
21333 		elemDecl = (xmlSchemaElementPtr) item;
21334 
21335 		if ((elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED) == 0)
21336 		{
21337 		    xmlSchemaCheckElementDeclComponent(
21338 			(xmlSchemaElementPtr) elemDecl, pctxt);
21339 		    FIXHFAILURE;
21340 		}
21341 
21342 #ifdef WXS_ELEM_DECL_CONS_ENABLED
21343 		/*
21344 		* Schema Component Constraint: Element Declarations Consistent
21345 		* Apply this constraint to local types of element declarations.
21346 		*/
21347 		if ((WXS_ELEM_TYPEDEF(elemDecl) != NULL) &&
21348 		    (WXS_IS_COMPLEX(WXS_ELEM_TYPEDEF(elemDecl))) &&
21349 		    (WXS_TYPE_IS_LOCAL(WXS_ELEM_TYPEDEF(elemDecl))))
21350 		{
21351 		    xmlSchemaCheckElementDeclConsistent(pctxt,
21352 			WXS_BASIC_CAST elemDecl,
21353 			WXS_TYPE_PARTICLE(WXS_ELEM_TYPEDEF(elemDecl)),
21354 			NULL, NULL, 0);
21355 		}
21356 #endif
21357 		break;
21358 	    default:
21359 		break;
21360 	}
21361     }
21362     if (pctxt->nberrors != 0)
21363 	goto exit_error;
21364 
21365     /*
21366     * Finally we can build the automaton from the content model of
21367     * complex types.
21368     */
21369 
21370     for (i = 0; i < nbItems; i++) {
21371 	item = items[i];
21372 	switch (item->type) {
21373 	    case XML_SCHEMA_TYPE_COMPLEX:
21374 		xmlSchemaBuildContentModel((xmlSchemaTypePtr) item, pctxt);
21375 		/* FIXHFAILURE; */
21376 		break;
21377 	    default:
21378 		break;
21379 	}
21380     }
21381     if (pctxt->nberrors != 0)
21382 	goto exit_error;
21383     /*
21384     * URGENT TODO: cos-element-consistent
21385     */
21386     goto exit;
21387 
21388 exit_error:
21389     ret = pctxt->err;
21390     goto exit;
21391 
21392 exit_failure:
21393     ret = -1;
21394 
21395 exit:
21396     /*
21397     * Reset the constructor. This is needed for XSI acquisition, since
21398     * those items will be processed over and over again for every XSI
21399     * if not cleared here.
21400     */
21401     con->bucket = oldbucket;
21402     con->pending->nbItems = 0;
21403     if (con->substGroups != NULL) {
21404 	xmlHashFree(con->substGroups, xmlSchemaSubstGroupFreeEntry);
21405 	con->substGroups = NULL;
21406     }
21407     if (con->redefs != NULL) {
21408 	xmlSchemaRedefListFree(con->redefs);
21409 	con->redefs = NULL;
21410     }
21411     return(ret);
21412 }
21413 /**
21414  * xmlSchemaParse:
21415  * @ctxt:  a schema validation context
21416  *
21417  * parse a schema definition resource and build an internal
21418  * XML Schema structure which can be used to validate instances.
21419  *
21420  * Returns the internal XML Schema structure built from the resource or
21421  *         NULL in case of error
21422  */
21423 xmlSchemaPtr
xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)21424 xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
21425 {
21426     xmlSchemaPtr mainSchema = NULL;
21427     xmlSchemaBucketPtr bucket = NULL;
21428     int res;
21429 
21430     /*
21431     * This one is used if the schema to be parsed was specified via
21432     * the API; i.e. not automatically by the validated instance document.
21433     */
21434 
21435     xmlSchemaInitTypes();
21436 
21437     if (ctxt == NULL)
21438         return (NULL);
21439 
21440     /* TODO: Init the context. Is this all we need?*/
21441     ctxt->nberrors = 0;
21442     ctxt->err = 0;
21443     ctxt->counter = 0;
21444 
21445     /* Create the *main* schema. */
21446     mainSchema = xmlSchemaNewSchema(ctxt);
21447     if (mainSchema == NULL)
21448 	goto exit_failure;
21449     /*
21450     * Create the schema constructor.
21451     */
21452     if (ctxt->constructor == NULL) {
21453 	ctxt->constructor = xmlSchemaConstructionCtxtCreate(ctxt->dict);
21454 	if (ctxt->constructor == NULL)
21455 	    return(NULL);
21456 	/* Take ownership of the constructor to be able to free it. */
21457 	ctxt->ownsConstructor = 1;
21458     }
21459     ctxt->constructor->mainSchema = mainSchema;
21460     /*
21461     * Locate and add the schema document.
21462     */
21463     res = xmlSchemaAddSchemaDoc(ctxt, XML_SCHEMA_SCHEMA_MAIN,
21464 	ctxt->URL, ctxt->doc, ctxt->buffer, ctxt->size, NULL,
21465 	NULL, NULL, &bucket);
21466     if (res == -1)
21467 	goto exit_failure;
21468     if (res != 0)
21469 	goto exit;
21470 
21471     if (bucket == NULL) {
21472 	/* TODO: Error code, actually we failed to *locate* the schema. */
21473 	if (ctxt->URL)
21474 	    xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21475 		NULL, NULL,
21476 		"Failed to locate the main schema resource at '%s'",
21477 		ctxt->URL, NULL);
21478 	else
21479 	    xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21480 		NULL, NULL,
21481 		"Failed to locate the main schema resource",
21482 		    NULL, NULL);
21483 	goto exit;
21484     }
21485     /* Then do the parsing for good. */
21486     if (xmlSchemaParseNewDocWithContext(ctxt, mainSchema, bucket) == -1)
21487 	goto exit_failure;
21488     if (ctxt->nberrors != 0)
21489 	goto exit;
21490 
21491     mainSchema->doc = bucket->doc;
21492     mainSchema->preserve = ctxt->preserve;
21493 
21494     ctxt->schema = mainSchema;
21495 
21496     if (xmlSchemaFixupComponents(ctxt, WXS_CONSTRUCTOR(ctxt)->mainBucket) == -1)
21497 	goto exit_failure;
21498 
21499     /*
21500     * TODO: This is not nice, since we cannot distinguish from the
21501     * result if there was an internal error or not.
21502     */
21503 exit:
21504     if (ctxt->nberrors != 0) {
21505 	if (mainSchema) {
21506 	    xmlSchemaFree(mainSchema);
21507 	    mainSchema = NULL;
21508 	}
21509 	if (ctxt->constructor) {
21510 	    xmlSchemaConstructionCtxtFree(ctxt->constructor);
21511 	    ctxt->constructor = NULL;
21512 	    ctxt->ownsConstructor = 0;
21513 	}
21514     }
21515     ctxt->schema = NULL;
21516     return(mainSchema);
21517 exit_failure:
21518     /*
21519     * Quite verbose, but should catch internal errors, which were
21520     * not communicated.
21521     */
21522     if (mainSchema) {
21523         xmlSchemaFree(mainSchema);
21524 	mainSchema = NULL;
21525     }
21526     if (ctxt->constructor) {
21527 	xmlSchemaConstructionCtxtFree(ctxt->constructor);
21528 	ctxt->constructor = NULL;
21529 	ctxt->ownsConstructor = 0;
21530     }
21531     PERROR_INT2("xmlSchemaParse",
21532 	"An internal error occurred");
21533     ctxt->schema = NULL;
21534     return(NULL);
21535 }
21536 
21537 /**
21538  * xmlSchemaSetParserErrors:
21539  * @ctxt:  a schema validation context
21540  * @err:  the error callback
21541  * @warn:  the warning callback
21542  * @ctx:  contextual data for the callbacks
21543  *
21544  * Set the callback functions used to handle errors for a validation context
21545  */
21546 void
xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,xmlSchemaValidityErrorFunc err,xmlSchemaValidityWarningFunc warn,void * ctx)21547 xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
21548                          xmlSchemaValidityErrorFunc err,
21549                          xmlSchemaValidityWarningFunc warn, void *ctx)
21550 {
21551     if (ctxt == NULL)
21552         return;
21553     ctxt->error = err;
21554     ctxt->warning = warn;
21555     ctxt->errCtxt = ctx;
21556     if (ctxt->vctxt != NULL)
21557 	xmlSchemaSetValidErrors(ctxt->vctxt, err, warn, ctx);
21558 }
21559 
21560 /**
21561  * xmlSchemaSetParserStructuredErrors:
21562  * @ctxt:  a schema parser context
21563  * @serror:  the structured error function
21564  * @ctx: the functions context
21565  *
21566  * Set the structured error callback
21567  */
21568 void
xmlSchemaSetParserStructuredErrors(xmlSchemaParserCtxtPtr ctxt,xmlStructuredErrorFunc serror,void * ctx)21569 xmlSchemaSetParserStructuredErrors(xmlSchemaParserCtxtPtr ctxt,
21570 				   xmlStructuredErrorFunc serror,
21571 				   void *ctx)
21572 {
21573     if (ctxt == NULL)
21574 	return;
21575     ctxt->serror = serror;
21576     ctxt->errCtxt = ctx;
21577     if (ctxt->vctxt != NULL)
21578 	xmlSchemaSetValidStructuredErrors(ctxt->vctxt, serror, ctx);
21579 }
21580 
21581 /**
21582  * xmlSchemaGetParserErrors:
21583  * @ctxt:  a XMl-Schema parser context
21584  * @err: the error callback result
21585  * @warn: the warning callback result
21586  * @ctx: contextual data for the callbacks result
21587  *
21588  * Get the callback information used to handle errors for a parser context
21589  *
21590  * Returns -1 in case of failure, 0 otherwise
21591  */
21592 int
xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,xmlSchemaValidityErrorFunc * err,xmlSchemaValidityWarningFunc * warn,void ** ctx)21593 xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
21594 			 xmlSchemaValidityErrorFunc * err,
21595 			 xmlSchemaValidityWarningFunc * warn, void **ctx)
21596 {
21597 	if (ctxt == NULL)
21598 		return(-1);
21599 	if (err != NULL)
21600 		*err = ctxt->error;
21601 	if (warn != NULL)
21602 		*warn = ctxt->warning;
21603 	if (ctx != NULL)
21604 		*ctx = ctxt->errCtxt;
21605 	return(0);
21606 }
21607 
21608 /**
21609  * xmlSchemaFacetTypeToString:
21610  * @type:  the facet type
21611  *
21612  * Convert the xmlSchemaTypeType to a char string.
21613  *
21614  * Returns the char string representation of the facet type if the
21615  *     type is a facet and an "Internal Error" string otherwise.
21616  */
21617 static const xmlChar *
xmlSchemaFacetTypeToString(xmlSchemaTypeType type)21618 xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
21619 {
21620     switch (type) {
21621         case XML_SCHEMA_FACET_PATTERN:
21622             return (BAD_CAST "pattern");
21623         case XML_SCHEMA_FACET_MAXEXCLUSIVE:
21624             return (BAD_CAST "maxExclusive");
21625         case XML_SCHEMA_FACET_MAXINCLUSIVE:
21626             return (BAD_CAST "maxInclusive");
21627         case XML_SCHEMA_FACET_MINEXCLUSIVE:
21628             return (BAD_CAST "minExclusive");
21629         case XML_SCHEMA_FACET_MININCLUSIVE:
21630             return (BAD_CAST "minInclusive");
21631         case XML_SCHEMA_FACET_WHITESPACE:
21632             return (BAD_CAST "whiteSpace");
21633         case XML_SCHEMA_FACET_ENUMERATION:
21634             return (BAD_CAST "enumeration");
21635         case XML_SCHEMA_FACET_LENGTH:
21636             return (BAD_CAST "length");
21637         case XML_SCHEMA_FACET_MAXLENGTH:
21638             return (BAD_CAST "maxLength");
21639         case XML_SCHEMA_FACET_MINLENGTH:
21640             return (BAD_CAST "minLength");
21641         case XML_SCHEMA_FACET_TOTALDIGITS:
21642             return (BAD_CAST "totalDigits");
21643         case XML_SCHEMA_FACET_FRACTIONDIGITS:
21644             return (BAD_CAST "fractionDigits");
21645         default:
21646             break;
21647     }
21648     return (BAD_CAST "Internal Error");
21649 }
21650 
21651 static xmlSchemaWhitespaceValueType
xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)21652 xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
21653 {
21654     /*
21655     * The normalization type can be changed only for types which are derived
21656     * from xsd:string.
21657     */
21658     if (type->type == XML_SCHEMA_TYPE_BASIC) {
21659 	/*
21660 	* Note that we assume a whitespace of preserve for anySimpleType.
21661 	*/
21662 	if ((type->builtInType == XML_SCHEMAS_STRING) ||
21663 	    (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
21664 	    return(XML_SCHEMA_WHITESPACE_PRESERVE);
21665 	else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
21666 	    return(XML_SCHEMA_WHITESPACE_REPLACE);
21667 	else {
21668 	    /*
21669 	    * For all `atomic` datatypes other than string (and types `derived`
21670 	    * by `restriction` from it) the value of whiteSpace is fixed to
21671 	    * collapse
21672 	    * Note that this includes built-in list datatypes.
21673 	    */
21674 	    return(XML_SCHEMA_WHITESPACE_COLLAPSE);
21675 	}
21676     } else if (WXS_IS_LIST(type)) {
21677 	/*
21678 	* For list types the facet "whiteSpace" is fixed to "collapse".
21679 	*/
21680 	return (XML_SCHEMA_WHITESPACE_COLLAPSE);
21681     } else if (WXS_IS_UNION(type)) {
21682 	return (XML_SCHEMA_WHITESPACE_UNKNOWN);
21683     } else if (WXS_IS_ATOMIC(type)) {
21684 	if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE)
21685 	    return (XML_SCHEMA_WHITESPACE_PRESERVE);
21686 	else if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_REPLACE)
21687 	    return (XML_SCHEMA_WHITESPACE_REPLACE);
21688 	else
21689 	    return (XML_SCHEMA_WHITESPACE_COLLAPSE);
21690     }
21691     return (-1);
21692 }
21693 
21694 /************************************************************************
21695  *									*
21696  *			Simple type validation				*
21697  *									*
21698  ************************************************************************/
21699 
21700 
21701 /************************************************************************
21702  *									*
21703  *			DOM Validation code				*
21704  *									*
21705  ************************************************************************/
21706 
21707 /**
21708  * xmlSchemaAssembleByLocation:
21709  * @pctxt:  a schema parser context
21710  * @vctxt:  a schema validation context
21711  * @schema: the existing schema
21712  * @node: the node that fired the assembling
21713  * @nsName: the namespace name of the new schema
21714  * @location: the location of the schema
21715  *
21716  * Expands an existing schema by an additional schema.
21717  *
21718  * Returns 0 if the new schema is correct, a positive error code
21719  * number otherwise and -1 in case of an internal or API error.
21720  */
21721 static int
xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,xmlSchemaPtr schema,xmlNodePtr node,const xmlChar * nsName,const xmlChar * location)21722 xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
21723 			    xmlSchemaPtr schema,
21724 			    xmlNodePtr node,
21725 			    const xmlChar *nsName,
21726 			    const xmlChar *location)
21727 {
21728     int ret = 0;
21729     xmlSchemaParserCtxtPtr pctxt;
21730     xmlSchemaBucketPtr bucket = NULL;
21731 
21732     if ((vctxt == NULL) || (schema == NULL))
21733 	return (-1);
21734 
21735     if (vctxt->pctxt == NULL) {
21736 	VERROR_INT("xmlSchemaAssembleByLocation",
21737 	    "no parser context available");
21738 	return(-1);
21739     }
21740     pctxt = vctxt->pctxt;
21741     if (pctxt->constructor == NULL) {
21742 	PERROR_INT("xmlSchemaAssembleByLocation",
21743 	    "no constructor");
21744 	return(-1);
21745     }
21746     /*
21747     * Acquire the schema document.
21748     */
21749     location = xmlSchemaBuildAbsoluteURI(pctxt->dict,
21750 	location, node);
21751     /*
21752     * Note that we pass XML_SCHEMA_SCHEMA_IMPORT here;
21753     * the process will automatically change this to
21754     * XML_SCHEMA_SCHEMA_MAIN if it is the first schema document.
21755     */
21756     ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
21757 	location, NULL, NULL, 0, node, NULL, nsName,
21758 	&bucket);
21759     if (ret != 0)
21760 	return(ret);
21761     if (bucket == NULL) {
21762 	/*
21763 	* Generate a warning that the document could not be located.
21764 	*/
21765 	xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC,
21766 	    node, NULL,
21767 	    "The document at location '%s' could not be acquired",
21768 	    location, NULL, NULL);
21769 	return(ret);
21770     }
21771     /*
21772     * The first located schema will be handled as if all other
21773     * schemas imported by XSI were imported by this first schema.
21774     */
21775     if ((bucket != NULL) &&
21776 	(WXS_CONSTRUCTOR(pctxt)->bucket == NULL))
21777 	WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
21778     /*
21779     * TODO: Is this handled like an import? I.e. is it not an error
21780     * if the schema cannot be located?
21781     */
21782     if ((bucket == NULL) || (! CAN_PARSE_SCHEMA(bucket)))
21783 	return(0);
21784     /*
21785     * We will reuse the parser context for every schema imported
21786     * directly via XSI. So reset the context.
21787     */
21788     pctxt->nberrors = 0;
21789     pctxt->err = 0;
21790     pctxt->doc = bucket->doc;
21791 
21792     ret = xmlSchemaParseNewDocWithContext(pctxt, schema, bucket);
21793     if (ret == -1) {
21794 	pctxt->doc = NULL;
21795 	goto exit_failure;
21796     }
21797     /* Paranoid error channelling. */
21798     if ((ret == 0) && (pctxt->nberrors != 0))
21799 	ret = pctxt->err;
21800     if (pctxt->nberrors == 0) {
21801 	/*
21802 	* Only bother to fixup pending components, if there was
21803 	* no error yet.
21804 	* For every XSI acquired schema (and its sub-schemata) we will
21805 	* fixup the components.
21806 	*/
21807 	xmlSchemaFixupComponents(pctxt, bucket);
21808 	ret = pctxt->err;
21809 	/*
21810 	* Not nice, but we need somehow to channel the schema parser
21811 	* error to the validation context.
21812 	*/
21813 	if ((ret != 0) && (vctxt->err == 0))
21814 	    vctxt->err = ret;
21815 	vctxt->nberrors += pctxt->nberrors;
21816     } else {
21817 	/* Add to validation error sum. */
21818 	vctxt->nberrors += pctxt->nberrors;
21819     }
21820     pctxt->doc = NULL;
21821     return(ret);
21822 exit_failure:
21823     pctxt->doc = NULL;
21824     return (-1);
21825 }
21826 
21827 static xmlSchemaAttrInfoPtr
xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,int metaType)21828 xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,
21829 			 int metaType)
21830 {
21831     if (vctxt->nbAttrInfos == 0)
21832 	return (NULL);
21833     {
21834 	int i;
21835 	xmlSchemaAttrInfoPtr iattr;
21836 
21837 	for (i = 0; i < vctxt->nbAttrInfos; i++) {
21838 	    iattr = vctxt->attrInfos[i];
21839 	    if (iattr->metaType == metaType)
21840 		return (iattr);
21841 	}
21842 
21843     }
21844     return (NULL);
21845 }
21846 
21847 /**
21848  * xmlSchemaAssembleByXSI:
21849  * @vctxt:  a schema validation context
21850  *
21851  * Expands an existing schema by an additional schema using
21852  * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
21853  * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
21854  * must be set to 1.
21855  *
21856  * Returns 0 if the new schema is correct, a positive error code
21857  * number otherwise and -1 in case of an internal or API error.
21858  */
21859 static int
xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)21860 xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)
21861 {
21862     const xmlChar *cur, *end;
21863     const xmlChar *nsname = NULL, *location;
21864     int count = 0;
21865     int ret = 0;
21866     xmlSchemaAttrInfoPtr iattr;
21867 
21868     /*
21869     * Parse the value; we will assume an even number of values
21870     * to be given (this is how Xerces and XSV work).
21871     *
21872     * URGENT TODO: !! This needs to work for both
21873     * @noNamespaceSchemaLocation AND @schemaLocation on the same
21874     * element !!
21875     */
21876     iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21877 	XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC);
21878     if (iattr == NULL)
21879 	iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21880 	XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC);
21881     if (iattr == NULL)
21882 	return (0);
21883     cur = iattr->value;
21884     do {
21885 	/*
21886 	* TODO: Move the string parsing mechanism away from here.
21887 	*/
21888 	if (iattr->metaType == XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC) {
21889 	    /*
21890 	    * Get the namespace name.
21891 	    */
21892 	    while (IS_BLANK_CH(*cur))
21893 		cur++;
21894 	    end = cur;
21895 	    while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21896 		end++;
21897 	    if (end == cur)
21898 		break;
21899 	    count++; /* TODO: Don't use the schema's dict. */
21900 	    nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
21901 	    cur = end;
21902 	}
21903 	/*
21904 	* Get the URI.
21905 	*/
21906 	while (IS_BLANK_CH(*cur))
21907 	    cur++;
21908 	end = cur;
21909 	while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21910 	    end++;
21911 	if (end == cur) {
21912 	    if (iattr->metaType ==
21913 		XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC)
21914 	    {
21915 		/*
21916 		* If using @schemaLocation then tuples are expected.
21917 		* I.e. the namespace name *and* the document's URI.
21918 		*/
21919 		xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC,
21920 		    iattr->node, NULL,
21921 		    "The value must consist of tuples: the target namespace "
21922 		    "name and the document's URI", NULL, NULL, NULL);
21923 	    }
21924 	    break;
21925 	}
21926 	count++; /* TODO: Don't use the schema's dict. */
21927 	location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
21928 	cur = end;
21929 	ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
21930 	    iattr->node, nsname, location);
21931 	if (ret == -1) {
21932 	    VERROR_INT("xmlSchemaAssembleByXSI",
21933 		"assembling schemata");
21934 	    return (-1);
21935 	}
21936     } while (*cur != 0);
21937     return (ret);
21938 }
21939 
21940 static const xmlChar *
xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,const xmlChar * prefix)21941 xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,
21942 			 const xmlChar *prefix)
21943 {
21944     if (vctxt->sax != NULL) {
21945 	int i, j;
21946 	xmlSchemaNodeInfoPtr inode;
21947 
21948 	for (i = vctxt->depth; i >= 0; i--) {
21949 	    if (vctxt->elemInfos[i]->nbNsBindings != 0) {
21950 		inode = vctxt->elemInfos[i];
21951 		for (j = 0; j < inode->nbNsBindings * 2; j += 2) {
21952 		    if (((prefix == NULL) &&
21953 			    (inode->nsBindings[j] == NULL)) ||
21954 			((prefix != NULL) && xmlStrEqual(prefix,
21955 			    inode->nsBindings[j]))) {
21956 
21957 			/*
21958 			* Note that the namespace bindings are already
21959 			* in a string dict.
21960 			*/
21961 			return (inode->nsBindings[j+1]);
21962 		    }
21963 		}
21964 	    }
21965 	}
21966 	return (NULL);
21967 #ifdef LIBXML_READER_ENABLED
21968     } else if (vctxt->reader != NULL) {
21969 	xmlChar *nsName;
21970 
21971 	nsName = xmlTextReaderLookupNamespace(vctxt->reader, prefix);
21972 	if (nsName != NULL) {
21973 	    const xmlChar *ret;
21974 
21975 	    ret = xmlDictLookup(vctxt->dict, nsName, -1);
21976 	    xmlFree(nsName);
21977 	    return (ret);
21978 	} else
21979 	    return (NULL);
21980 #endif
21981     } else {
21982 	xmlNsPtr ns;
21983 
21984 	if ((vctxt->inode->node == NULL) ||
21985 	    (vctxt->inode->node->doc == NULL)) {
21986 	    VERROR_INT("xmlSchemaLookupNamespace",
21987 		"no node or node's doc available");
21988 	    return (NULL);
21989 	}
21990 	ns = xmlSearchNs(vctxt->inode->node->doc,
21991 	    vctxt->inode->node, prefix);
21992 	if (ns != NULL)
21993 	    return (ns->href);
21994 	return (NULL);
21995     }
21996 }
21997 
21998 /*
21999 * This one works on the schema of the validation context.
22000 */
22001 static int
xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,xmlSchemaPtr schema,xmlNodePtr node,const xmlChar * value,xmlSchemaValPtr * val,int valNeeded)22002 xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
22003 			  xmlSchemaPtr schema,
22004 			  xmlNodePtr node,
22005 			  const xmlChar *value,
22006 			  xmlSchemaValPtr *val,
22007 			  int valNeeded)
22008 {
22009     int ret;
22010 
22011     if (vctxt && (vctxt->schema == NULL)) {
22012 	VERROR_INT("xmlSchemaValidateNotation",
22013 	    "a schema is needed on the validation context");
22014 	return (-1);
22015     }
22016     ret = xmlValidateQName(value, 1);
22017     if (ret != 0)
22018 	return (ret);
22019     {
22020 	xmlChar *localName = NULL;
22021 	xmlChar *prefix = NULL;
22022 
22023 	localName = xmlSplitQName2(value, &prefix);
22024 	if (prefix != NULL) {
22025 	    const xmlChar *nsName = NULL;
22026 
22027 	    if (vctxt != NULL)
22028 		nsName = xmlSchemaLookupNamespace(vctxt, BAD_CAST prefix);
22029 	    else if (node != NULL) {
22030 		xmlNsPtr ns = xmlSearchNs(node->doc, node, prefix);
22031 		if (ns != NULL)
22032 		    nsName = ns->href;
22033 	    } else {
22034 		xmlFree(prefix);
22035 		xmlFree(localName);
22036 		return (1);
22037 	    }
22038 	    if (nsName == NULL) {
22039 		xmlFree(prefix);
22040 		xmlFree(localName);
22041 		return (1);
22042 	    }
22043 	    if (xmlSchemaGetNotation(schema, localName, nsName) != NULL) {
22044 		if ((valNeeded) && (val != NULL)) {
22045 		    (*val) = xmlSchemaNewNOTATIONValue(xmlStrdup(localName),
22046 						       xmlStrdup(nsName));
22047 		    if (*val == NULL)
22048 			ret = -1;
22049 		}
22050 	    } else
22051 		ret = 1;
22052 	    xmlFree(prefix);
22053 	    xmlFree(localName);
22054 	} else {
22055 	    if (xmlSchemaGetNotation(schema, value, NULL) != NULL) {
22056 		if (valNeeded && (val != NULL)) {
22057 		    (*val) = xmlSchemaNewNOTATIONValue(
22058 			BAD_CAST xmlStrdup(value), NULL);
22059 		    if (*val == NULL)
22060 			ret = -1;
22061 		}
22062 	    } else
22063 		return (1);
22064 	}
22065     }
22066     return (ret);
22067 }
22068 
22069 static int
xmlSchemaVAddNodeQName(xmlSchemaValidCtxtPtr vctxt,const xmlChar * lname,const xmlChar * nsname)22070 xmlSchemaVAddNodeQName(xmlSchemaValidCtxtPtr vctxt,
22071 		       const xmlChar* lname,
22072 		       const xmlChar* nsname)
22073 {
22074     int i;
22075 
22076     lname = xmlDictLookup(vctxt->dict, lname, -1);
22077     if (lname == NULL)
22078 	return(-1);
22079     if (nsname != NULL) {
22080 	nsname = xmlDictLookup(vctxt->dict, nsname, -1);
22081 	if (nsname == NULL)
22082 	    return(-1);
22083     }
22084     for (i = 0; i < vctxt->nodeQNames->nbItems; i += 2) {
22085 	if ((vctxt->nodeQNames->items [i] == lname) &&
22086 	    (vctxt->nodeQNames->items[i +1] == nsname))
22087 	    /* Already there */
22088 	    return(i);
22089     }
22090     /* Add new entry. */
22091     i = vctxt->nodeQNames->nbItems;
22092     xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) lname);
22093     xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) nsname);
22094     return(i);
22095 }
22096 
22097 /************************************************************************
22098  *									*
22099  *  Validation of identity-constraints (IDC)                            *
22100  *									*
22101  ************************************************************************/
22102 
22103 /**
22104  * xmlSchemaAugmentIDC:
22105  * @idcDef: the IDC definition
22106  *
22107  * Creates an augmented IDC definition item.
22108  *
22109  * Returns the item, or NULL on internal errors.
22110  */
22111 static void
xmlSchemaAugmentIDC(void * payload,void * data,const xmlChar * name ATTRIBUTE_UNUSED)22112 xmlSchemaAugmentIDC(void *payload, void *data,
22113                     const xmlChar *name ATTRIBUTE_UNUSED)
22114 {
22115     xmlSchemaIDCPtr idcDef = (xmlSchemaIDCPtr) payload;
22116     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) data;
22117     xmlSchemaIDCAugPtr aidc;
22118 
22119     aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
22120     if (aidc == NULL) {
22121 	xmlSchemaVErrMemory(vctxt,
22122 	    "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
22123 	    NULL);
22124 	return;
22125     }
22126     aidc->keyrefDepth = -1;
22127     aidc->def = idcDef;
22128     aidc->next = NULL;
22129     if (vctxt->aidcs == NULL)
22130 	vctxt->aidcs = aidc;
22131     else {
22132 	aidc->next = vctxt->aidcs;
22133 	vctxt->aidcs = aidc;
22134     }
22135     /*
22136     * Save if we have keyrefs at all.
22137     */
22138     if ((vctxt->hasKeyrefs == 0) &&
22139 	(idcDef->type == XML_SCHEMA_TYPE_IDC_KEYREF))
22140 	vctxt->hasKeyrefs = 1;
22141 }
22142 
22143 /**
22144  * xmlSchemaAugmentImportedIDC:
22145  * @imported: the imported schema
22146  *
22147  * Creates an augmented IDC definition for the imported schema.
22148  */
22149 static void
xmlSchemaAugmentImportedIDC(void * payload,void * data,const xmlChar * name ATTRIBUTE_UNUSED)22150 xmlSchemaAugmentImportedIDC(void *payload, void *data,
22151                             const xmlChar *name ATTRIBUTE_UNUSED) {
22152     xmlSchemaImportPtr imported = (xmlSchemaImportPtr) payload;
22153     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) data;
22154     if (imported->schema->idcDef != NULL) {
22155 	    xmlHashScan(imported->schema->idcDef, xmlSchemaAugmentIDC, vctxt);
22156     }
22157 }
22158 
22159 /**
22160  * xmlSchemaIDCNewBinding:
22161  * @idcDef: the IDC definition of this binding
22162  *
22163  * Creates a new IDC binding.
22164  *
22165  * Returns the new IDC binding, NULL on internal errors.
22166  */
22167 static xmlSchemaPSVIIDCBindingPtr
xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)22168 xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
22169 {
22170     xmlSchemaPSVIIDCBindingPtr ret;
22171 
22172     ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
22173 	    sizeof(xmlSchemaPSVIIDCBinding));
22174     if (ret == NULL) {
22175 	xmlSchemaVErrMemory(NULL,
22176 	    "allocating a PSVI IDC binding item", NULL);
22177 	return (NULL);
22178     }
22179     memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
22180     ret->definition = idcDef;
22181     return (ret);
22182 }
22183 
22184 /**
22185  * xmlSchemaIDCStoreNodeTableItem:
22186  * @vctxt: the WXS validation context
22187  * @item: the IDC node table item
22188  *
22189  * The validation context is used to store IDC node table items.
22190  * They are stored to avoid copying them if IDC node-tables are merged
22191  * with corresponding parent IDC node-tables (bubbling).
22192  *
22193  * Returns 0 if succeeded, -1 on internal errors.
22194  */
22195 static int
xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,xmlSchemaPSVIIDCNodePtr item)22196 xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
22197 			       xmlSchemaPSVIIDCNodePtr item)
22198 {
22199     /*
22200     * Add to global list.
22201     */
22202     if (vctxt->idcNodes == NULL) {
22203 	vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
22204 	    xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
22205 	if (vctxt->idcNodes == NULL) {
22206 	    xmlSchemaVErrMemory(vctxt,
22207 		"allocating the IDC node table item list", NULL);
22208 	    return (-1);
22209 	}
22210 	vctxt->sizeIdcNodes = 20;
22211     } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
22212 	vctxt->sizeIdcNodes *= 2;
22213 	vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
22214 	    xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
22215 	    sizeof(xmlSchemaPSVIIDCNodePtr));
22216 	if (vctxt->idcNodes == NULL) {
22217 	    xmlSchemaVErrMemory(vctxt,
22218 		"re-allocating the IDC node table item list", NULL);
22219 	    return (-1);
22220 	}
22221     }
22222     vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
22223 
22224     return (0);
22225 }
22226 
22227 /**
22228  * xmlSchemaIDCStoreKey:
22229  * @vctxt: the WXS validation context
22230  * @item: the IDC key
22231  *
22232  * The validation context is used to store an IDC key.
22233  *
22234  * Returns 0 if succeeded, -1 on internal errors.
22235  */
22236 static int
xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,xmlSchemaPSVIIDCKeyPtr key)22237 xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
22238 		     xmlSchemaPSVIIDCKeyPtr key)
22239 {
22240     /*
22241     * Add to global list.
22242     */
22243     if (vctxt->idcKeys == NULL) {
22244 	vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
22245 	    xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
22246 	if (vctxt->idcKeys == NULL) {
22247 	    xmlSchemaVErrMemory(vctxt,
22248 		"allocating the IDC key storage list", NULL);
22249 	    return (-1);
22250 	}
22251 	vctxt->sizeIdcKeys = 40;
22252     } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
22253 	vctxt->sizeIdcKeys *= 2;
22254 	vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
22255 	    xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
22256 	    sizeof(xmlSchemaPSVIIDCKeyPtr));
22257 	if (vctxt->idcKeys == NULL) {
22258 	    xmlSchemaVErrMemory(vctxt,
22259 		"re-allocating the IDC key storage list", NULL);
22260 	    return (-1);
22261 	}
22262     }
22263     vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
22264 
22265     return (0);
22266 }
22267 
22268 /**
22269  * xmlSchemaIDCAppendNodeTableItem:
22270  * @bind: the IDC binding
22271  * @ntItem: the node-table item
22272  *
22273  * Appends the IDC node-table item to the binding.
22274  *
22275  * Returns 0 on success and -1 on internal errors.
22276  */
22277 static int
xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,xmlSchemaPSVIIDCNodePtr ntItem)22278 xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
22279 				xmlSchemaPSVIIDCNodePtr ntItem)
22280 {
22281     if (bind->nodeTable == NULL) {
22282 	bind->sizeNodes = 10;
22283 	bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
22284 	    xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
22285 	if (bind->nodeTable == NULL) {
22286 	    xmlSchemaVErrMemory(NULL,
22287 		"allocating an array of IDC node-table items", NULL);
22288 	    return(-1);
22289 	}
22290     } else if (bind->sizeNodes <= bind->nbNodes) {
22291 	bind->sizeNodes *= 2;
22292 	bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
22293 	    xmlRealloc(bind->nodeTable, bind->sizeNodes *
22294 		sizeof(xmlSchemaPSVIIDCNodePtr));
22295 	if (bind->nodeTable == NULL) {
22296 	    xmlSchemaVErrMemory(NULL,
22297 		"re-allocating an array of IDC node-table items", NULL);
22298 	    return(-1);
22299 	}
22300     }
22301     bind->nodeTable[bind->nbNodes++] = ntItem;
22302     return(0);
22303 }
22304 
22305 /**
22306  * xmlSchemaIDCAcquireBinding:
22307  * @vctxt: the WXS validation context
22308  * @matcher: the IDC matcher
22309  *
22310  * Looks up an PSVI IDC binding, for the IDC definition and
22311  * of the given matcher. If none found, a new one is created
22312  * and added to the IDC table.
22313  *
22314  * Returns an IDC binding or NULL on internal errors.
22315  */
22316 static xmlSchemaPSVIIDCBindingPtr
xmlSchemaIDCAcquireBinding(xmlSchemaValidCtxtPtr vctxt,xmlSchemaIDCMatcherPtr matcher)22317 xmlSchemaIDCAcquireBinding(xmlSchemaValidCtxtPtr vctxt,
22318 			  xmlSchemaIDCMatcherPtr matcher)
22319 {
22320     xmlSchemaNodeInfoPtr ielem;
22321 
22322     ielem = vctxt->elemInfos[matcher->depth];
22323 
22324     if (ielem->idcTable == NULL) {
22325 	ielem->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
22326 	if (ielem->idcTable == NULL)
22327 	    return (NULL);
22328 	return(ielem->idcTable);
22329     } else {
22330 	xmlSchemaPSVIIDCBindingPtr bind = NULL;
22331 
22332 	bind = ielem->idcTable;
22333 	do {
22334 	    if (bind->definition == matcher->aidc->def)
22335 		return(bind);
22336 	    if (bind->next == NULL) {
22337 		bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
22338 		if (bind->next == NULL)
22339 		    return (NULL);
22340 		return(bind->next);
22341 	    }
22342 	    bind = bind->next;
22343 	} while (bind != NULL);
22344     }
22345     return (NULL);
22346 }
22347 
22348 static xmlSchemaItemListPtr
xmlSchemaIDCAcquireTargetList(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,xmlSchemaIDCMatcherPtr matcher)22349 xmlSchemaIDCAcquireTargetList(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
22350 			     xmlSchemaIDCMatcherPtr matcher)
22351 {
22352     if (matcher->targets == NULL)
22353 	matcher->targets = xmlSchemaItemListCreate();
22354     return(matcher->targets);
22355 }
22356 
22357 /**
22358  * xmlSchemaIDCFreeKey:
22359  * @key: the IDC key
22360  *
22361  * Frees an IDC key together with its compiled value.
22362  */
22363 static void
xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)22364 xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
22365 {
22366     if (key->val != NULL)
22367 	xmlSchemaFreeValue(key->val);
22368     xmlFree(key);
22369 }
22370 
22371 /**
22372  * xmlSchemaIDCFreeBinding:
22373  *
22374  * Frees an IDC binding. Note that the node table-items
22375  * are not freed.
22376  */
22377 static void
xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)22378 xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
22379 {
22380     if (bind->nodeTable != NULL)
22381 	xmlFree(bind->nodeTable);
22382     if (bind->dupls != NULL)
22383 	xmlSchemaItemListFree(bind->dupls);
22384     xmlFree(bind);
22385 }
22386 
22387 /**
22388  * xmlSchemaIDCFreeIDCTable:
22389  * @bind: the first IDC binding in the list
22390  *
22391  * Frees an IDC table, i.e. all the IDC bindings in the list.
22392  */
22393 static void
xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)22394 xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
22395 {
22396     xmlSchemaPSVIIDCBindingPtr prev;
22397 
22398     while (bind != NULL) {
22399 	prev = bind;
22400 	bind = bind->next;
22401 	xmlSchemaIDCFreeBinding(prev);
22402     }
22403 }
22404 
22405 static void
xmlFreeIDCHashEntry(void * payload,const xmlChar * name ATTRIBUTE_UNUSED)22406 xmlFreeIDCHashEntry (void *payload, const xmlChar *name ATTRIBUTE_UNUSED)
22407 {
22408     xmlIDCHashEntryPtr e = payload, n;
22409     while (e) {
22410 	n = e->next;
22411 	xmlFree(e);
22412 	e = n;
22413     }
22414 }
22415 
22416 /**
22417  * xmlSchemaIDCFreeMatcherList:
22418  * @matcher: the first IDC matcher in the list
22419  *
22420  * Frees a list of IDC matchers.
22421  */
22422 static void
xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)22423 xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
22424 {
22425     xmlSchemaIDCMatcherPtr next;
22426 
22427     while (matcher != NULL) {
22428 	next = matcher->next;
22429 	if (matcher->keySeqs != NULL) {
22430 	    int i;
22431 	    for (i = 0; i < matcher->sizeKeySeqs; i++)
22432 		if (matcher->keySeqs[i] != NULL)
22433 		    xmlFree(matcher->keySeqs[i]);
22434 	    xmlFree(matcher->keySeqs);
22435 	}
22436 	if (matcher->targets != NULL) {
22437 	    if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
22438 		int i;
22439 		xmlSchemaPSVIIDCNodePtr idcNode;
22440 		/*
22441 		* Node-table items for keyrefs are not stored globally
22442 		* to the validation context, since they are not bubbled.
22443 		* We need to free them here.
22444 		*/
22445 		for (i = 0; i < matcher->targets->nbItems; i++) {
22446 		    idcNode =
22447 			(xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
22448 		    xmlFree(idcNode->keys);
22449 		    xmlFree(idcNode);
22450 		}
22451 	    }
22452 	    xmlSchemaItemListFree(matcher->targets);
22453 	}
22454 	if (matcher->htab != NULL)
22455 	  xmlHashFree(matcher->htab, xmlFreeIDCHashEntry);
22456 	xmlFree(matcher);
22457 	matcher = next;
22458     }
22459 }
22460 
22461 /**
22462  * xmlSchemaIDCReleaseMatcherList:
22463  * @vctxt: the WXS validation context
22464  * @matcher: the first IDC matcher in the list
22465  *
22466  * Caches a list of IDC matchers for reuse.
22467  */
22468 static void
xmlSchemaIDCReleaseMatcherList(xmlSchemaValidCtxtPtr vctxt,xmlSchemaIDCMatcherPtr matcher)22469 xmlSchemaIDCReleaseMatcherList(xmlSchemaValidCtxtPtr vctxt,
22470 			       xmlSchemaIDCMatcherPtr matcher)
22471 {
22472     xmlSchemaIDCMatcherPtr next;
22473 
22474     while (matcher != NULL) {
22475 	next = matcher->next;
22476 	if (matcher->keySeqs != NULL) {
22477 	    int i;
22478 	    /*
22479 	    * Don't free the array, but only the content.
22480 	    */
22481 	    for (i = 0; i < matcher->sizeKeySeqs; i++)
22482 		if (matcher->keySeqs[i] != NULL) {
22483 		    xmlFree(matcher->keySeqs[i]);
22484 		    matcher->keySeqs[i] = NULL;
22485 		}
22486 	}
22487 	if (matcher->targets) {
22488 	    if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
22489 		int i;
22490 		xmlSchemaPSVIIDCNodePtr idcNode;
22491 		/*
22492 		* Node-table items for keyrefs are not stored globally
22493 		* to the validation context, since they are not bubbled.
22494 		* We need to free them here.
22495 		*/
22496 		for (i = 0; i < matcher->targets->nbItems; i++) {
22497 		    idcNode =
22498 			(xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
22499 		    xmlFree(idcNode->keys);
22500 		    xmlFree(idcNode);
22501 		}
22502 	    }
22503 	    xmlSchemaItemListFree(matcher->targets);
22504 	    matcher->targets = NULL;
22505 	}
22506 	if (matcher->htab != NULL) {
22507 	    xmlHashFree(matcher->htab, xmlFreeIDCHashEntry);
22508 	    matcher->htab = NULL;
22509 	}
22510 	matcher->next = NULL;
22511 	/*
22512 	* Cache the matcher.
22513 	*/
22514 	if (vctxt->idcMatcherCache != NULL)
22515 	    matcher->nextCached = vctxt->idcMatcherCache;
22516 	vctxt->idcMatcherCache = matcher;
22517 
22518 	matcher = next;
22519     }
22520 }
22521 
22522 /**
22523  * xmlSchemaIDCAddStateObject:
22524  * @vctxt: the WXS validation context
22525  * @matcher: the IDC matcher
22526  * @sel: the XPath information
22527  * @parent: the parent "selector" state object if any
22528  * @type: "selector" or "field"
22529  *
22530  * Creates/reuses and activates state objects for the given
22531  * XPath information; if the XPath expression consists of unions,
22532  * multiple state objects are created for every unioned expression.
22533  *
22534  * Returns 0 on success and -1 on internal errors.
22535  */
22536 static int
xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,xmlSchemaIDCMatcherPtr matcher,xmlSchemaIDCSelectPtr sel,int type)22537 xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
22538 			xmlSchemaIDCMatcherPtr matcher,
22539 			xmlSchemaIDCSelectPtr sel,
22540 			int type)
22541 {
22542     xmlSchemaIDCStateObjPtr sto;
22543 
22544     /*
22545     * Reuse the state objects from the pool.
22546     */
22547     if (vctxt->xpathStatePool != NULL) {
22548 	sto = vctxt->xpathStatePool;
22549 	vctxt->xpathStatePool = sto->next;
22550 	sto->next = NULL;
22551     } else {
22552 	/*
22553 	* Create a new state object.
22554 	*/
22555 	sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
22556 	if (sto == NULL) {
22557 	    xmlSchemaVErrMemory(NULL,
22558 		"allocating an IDC state object", NULL);
22559 	    return (-1);
22560 	}
22561 	memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
22562     }
22563     /*
22564     * Add to global list.
22565     */
22566     if (vctxt->xpathStates != NULL)
22567 	sto->next = vctxt->xpathStates;
22568     vctxt->xpathStates = sto;
22569 
22570     /*
22571     * Free the old xpath validation context.
22572     */
22573     if (sto->xpathCtxt != NULL)
22574 	xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
22575 
22576     /*
22577     * Create a new XPath (pattern) validation context.
22578     */
22579     sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
22580 	(xmlPatternPtr) sel->xpathComp);
22581     if (sto->xpathCtxt == NULL) {
22582 	VERROR_INT("xmlSchemaIDCAddStateObject",
22583 	    "failed to create an XPath validation context");
22584 	return (-1);
22585     }
22586     sto->type = type;
22587     sto->depth = vctxt->depth;
22588     sto->matcher = matcher;
22589     sto->sel = sel;
22590     sto->nbHistory = 0;
22591 
22592 #ifdef DEBUG_IDC
22593     xmlGenericError(xmlGenericErrorContext, "IDC:   STO push '%s'\n",
22594 	sto->sel->xpath);
22595 #endif
22596     return (0);
22597 }
22598 
22599 /**
22600  * xmlSchemaXPathEvaluate:
22601  * @vctxt: the WXS validation context
22602  * @nodeType: the nodeType of the current node
22603  *
22604  * Evaluates all active XPath state objects.
22605  *
22606  * Returns the number of IC "field" state objects which resolved to
22607  * this node, 0 if none resolved and -1 on internal errors.
22608  */
22609 static int
xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,xmlElementType nodeType)22610 xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
22611 		       xmlElementType nodeType)
22612 {
22613     xmlSchemaIDCStateObjPtr sto, head = NULL, first;
22614     int res, resolved = 0, depth = vctxt->depth;
22615 
22616     if (vctxt->xpathStates == NULL)
22617 	return (0);
22618 
22619     if (nodeType == XML_ATTRIBUTE_NODE)
22620 	depth++;
22621 #ifdef DEBUG_IDC
22622     {
22623 	xmlChar *str = NULL;
22624 	xmlGenericError(xmlGenericErrorContext,
22625 	    "IDC: EVAL on %s, depth %d, type %d\n",
22626 	    xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22627 		vctxt->inode->localName), depth, nodeType);
22628 	FREE_AND_NULL(str)
22629     }
22630 #endif
22631     /*
22632     * Process all active XPath state objects.
22633     */
22634     first = vctxt->xpathStates;
22635     sto = first;
22636     while (sto != head) {
22637 #ifdef DEBUG_IDC
22638 	if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
22639 	    xmlGenericError(xmlGenericErrorContext, "IDC:   ['%s'] selector '%s'\n",
22640 		sto->matcher->aidc->def->name, sto->sel->xpath);
22641 	else
22642 	    xmlGenericError(xmlGenericErrorContext, "IDC:   ['%s'] field '%s'\n",
22643 		sto->matcher->aidc->def->name, sto->sel->xpath);
22644 #endif
22645 	if (nodeType == XML_ELEMENT_NODE)
22646 	    res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
22647 		vctxt->inode->localName, vctxt->inode->nsName);
22648 	else
22649 	    res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
22650 		vctxt->inode->localName, vctxt->inode->nsName);
22651 
22652 	if (res == -1) {
22653 	    VERROR_INT("xmlSchemaXPathEvaluate",
22654 		"calling xmlStreamPush()");
22655 	    return (-1);
22656 	}
22657 	if (res == 0)
22658 	    goto next_sto;
22659 	/*
22660 	* Full match.
22661 	*/
22662 #ifdef DEBUG_IDC
22663 	xmlGenericError(xmlGenericErrorContext, "IDC:     "
22664 	    "MATCH\n");
22665 #endif
22666 	/*
22667 	* Register a match in the state object history.
22668 	*/
22669 	if (sto->history == NULL) {
22670 	    sto->history = (int *) xmlMalloc(5 * sizeof(int));
22671 	    if (sto->history == NULL) {
22672 		xmlSchemaVErrMemory(NULL,
22673 		    "allocating the state object history", NULL);
22674 		return(-1);
22675 	    }
22676 	    sto->sizeHistory = 5;
22677 	} else if (sto->sizeHistory <= sto->nbHistory) {
22678 	    sto->sizeHistory *= 2;
22679 	    sto->history = (int *) xmlRealloc(sto->history,
22680 		sto->sizeHistory * sizeof(int));
22681 	    if (sto->history == NULL) {
22682 		xmlSchemaVErrMemory(NULL,
22683 		    "re-allocating the state object history", NULL);
22684 		return(-1);
22685 	    }
22686 	}
22687 	sto->history[sto->nbHistory++] = depth;
22688 
22689 #ifdef DEBUG_IDC
22690 	xmlGenericError(xmlGenericErrorContext, "IDC:       push match '%d'\n",
22691 	    vctxt->depth);
22692 #endif
22693 
22694 	if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
22695 	    xmlSchemaIDCSelectPtr sel;
22696 	    /*
22697 	    * Activate state objects for the IDC fields of
22698 	    * the IDC selector.
22699 	    */
22700 #ifdef DEBUG_IDC
22701 	    xmlGenericError(xmlGenericErrorContext, "IDC:     "
22702 		"activating field states\n");
22703 #endif
22704 	    sel = sto->matcher->aidc->def->fields;
22705 	    while (sel != NULL) {
22706 		if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
22707 		    sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
22708 		    return (-1);
22709 		sel = sel->next;
22710 	    }
22711 	} else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22712 	    /*
22713 	    * An IDC key node was found by the IDC field.
22714 	    */
22715 #ifdef DEBUG_IDC
22716 	    xmlGenericError(xmlGenericErrorContext,
22717 		"IDC:     key found\n");
22718 #endif
22719 	    /*
22720 	    * Notify that the character value of this node is
22721 	    * needed.
22722 	    */
22723 	    if (resolved == 0) {
22724 		if ((vctxt->inode->flags &
22725 		    XML_SCHEMA_NODE_INFO_VALUE_NEEDED) == 0)
22726 		vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
22727 	    }
22728 	    resolved++;
22729 	}
22730 next_sto:
22731 	if (sto->next == NULL) {
22732 	    /*
22733 	    * Evaluate field state objects created on this node as well.
22734 	    */
22735 	    head = first;
22736 	    sto = vctxt->xpathStates;
22737 	} else
22738 	    sto = sto->next;
22739     }
22740     return (resolved);
22741 }
22742 
22743 static const xmlChar *
xmlSchemaFormatIDCKeySequence_1(xmlSchemaValidCtxtPtr vctxt,xmlChar ** buf,xmlSchemaPSVIIDCKeyPtr * seq,int count,int for_hash)22744 xmlSchemaFormatIDCKeySequence_1(xmlSchemaValidCtxtPtr vctxt,
22745 				xmlChar **buf,
22746 				xmlSchemaPSVIIDCKeyPtr *seq,
22747 				int count, int for_hash)
22748 {
22749     int i, res;
22750     xmlChar *value = NULL;
22751 
22752     *buf = xmlStrdup(BAD_CAST "[");
22753     for (i = 0; i < count; i++) {
22754 	*buf = xmlStrcat(*buf, BAD_CAST "'");
22755 	if (!for_hash)
22756 	    res = xmlSchemaGetCanonValueWhtspExt(seq[i]->val,
22757 		    xmlSchemaGetWhiteSpaceFacetValue(seq[i]->type),
22758 		    &value);
22759 	else {
22760 	    res = xmlSchemaGetCanonValueHash(seq[i]->val, &value);
22761 	}
22762 	if (res == 0)
22763 	    *buf = xmlStrcat(*buf, BAD_CAST value);
22764 	else {
22765 	    VERROR_INT("xmlSchemaFormatIDCKeySequence",
22766 		"failed to compute a canonical value");
22767 	    *buf = xmlStrcat(*buf, BAD_CAST "???");
22768 	}
22769 	if (i < count -1)
22770 	    *buf = xmlStrcat(*buf, BAD_CAST "', ");
22771 	else
22772 	    *buf = xmlStrcat(*buf, BAD_CAST "'");
22773 	if (value != NULL) {
22774 	    xmlFree(value);
22775 	    value = NULL;
22776 	}
22777     }
22778     *buf = xmlStrcat(*buf, BAD_CAST "]");
22779 
22780     return (BAD_CAST *buf);
22781 }
22782 
22783 static const xmlChar *
xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,xmlChar ** buf,xmlSchemaPSVIIDCKeyPtr * seq,int count)22784 xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,
22785 			      xmlChar **buf,
22786 			      xmlSchemaPSVIIDCKeyPtr *seq,
22787 			      int count)
22788 {
22789     return xmlSchemaFormatIDCKeySequence_1(vctxt, buf, seq, count, 0);
22790 }
22791 
22792 static const xmlChar *
xmlSchemaHashKeySequence(xmlSchemaValidCtxtPtr vctxt,xmlChar ** buf,xmlSchemaPSVIIDCKeyPtr * seq,int count)22793 xmlSchemaHashKeySequence(xmlSchemaValidCtxtPtr vctxt,
22794 			 xmlChar **buf,
22795 			 xmlSchemaPSVIIDCKeyPtr *seq,
22796 			 int count)
22797 {
22798     return xmlSchemaFormatIDCKeySequence_1(vctxt, buf, seq, count, 1);
22799 }
22800 
22801 /**
22802  * xmlSchemaXPathPop:
22803  * @vctxt: the WXS validation context
22804  *
22805  * Pops all XPath states.
22806  *
22807  * Returns 0 on success and -1 on internal errors.
22808  */
22809 static int
xmlSchemaXPathPop(xmlSchemaValidCtxtPtr vctxt)22810 xmlSchemaXPathPop(xmlSchemaValidCtxtPtr vctxt)
22811 {
22812     xmlSchemaIDCStateObjPtr sto;
22813     int res;
22814 
22815     if (vctxt->xpathStates == NULL)
22816 	return(0);
22817     sto = vctxt->xpathStates;
22818     do {
22819 	res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22820 	if (res == -1)
22821 	    return (-1);
22822 	sto = sto->next;
22823     } while (sto != NULL);
22824     return(0);
22825 }
22826 
22827 /**
22828  * xmlSchemaXPathProcessHistory:
22829  * @vctxt: the WXS validation context
22830  * @type: the simple/complex type of the current node if any at all
22831  * @val: the precompiled value
22832  *
22833  * Processes and pops the history items of the IDC state objects.
22834  * IDC key-sequences are validated/created on IDC bindings.
22835  *
22836  * Returns 0 on success and -1 on internal errors.
22837  */
22838 static int
xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,int depth)22839 xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
22840 			     int depth)
22841 {
22842     xmlSchemaIDCStateObjPtr sto, nextsto;
22843     int res, matchDepth;
22844     xmlSchemaPSVIIDCKeyPtr key = NULL;
22845     xmlSchemaTypePtr type = vctxt->inode->typeDef, simpleType = NULL;
22846 
22847     if (vctxt->xpathStates == NULL)
22848 	return (0);
22849     sto = vctxt->xpathStates;
22850 
22851 #ifdef DEBUG_IDC
22852     {
22853 	xmlChar *str = NULL;
22854 	xmlGenericError(xmlGenericErrorContext,
22855 	    "IDC: BACK on %s, depth %d\n",
22856 	    xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22857 		vctxt->inode->localName), vctxt->depth);
22858 	FREE_AND_NULL(str)
22859     }
22860 #endif
22861     /*
22862     * Evaluate the state objects.
22863     */
22864     while (sto != NULL) {
22865 	res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22866 	if (res == -1) {
22867 	    VERROR_INT("xmlSchemaXPathProcessHistory",
22868 		"calling xmlStreamPop()");
22869 	    return (-1);
22870 	}
22871 #ifdef DEBUG_IDC
22872 	xmlGenericError(xmlGenericErrorContext, "IDC:   stream pop '%s'\n",
22873 	    sto->sel->xpath);
22874 #endif
22875 	if (sto->nbHistory == 0)
22876 	    goto deregister_check;
22877 
22878 	matchDepth = sto->history[sto->nbHistory -1];
22879 
22880 	/*
22881 	* Only matches at the current depth are of interest.
22882 	*/
22883 	if (matchDepth != depth) {
22884 	    sto = sto->next;
22885 	    continue;
22886 	}
22887 	if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22888 	    /*
22889 	    * NOTE: According to
22890 	    *   http://www.w3.org/Bugs/Public/show_bug.cgi?id=2198
22891 	    *   ... the simple-content of complex types is also allowed.
22892 	    */
22893 
22894 	    if (WXS_IS_COMPLEX(type)) {
22895 		if (WXS_HAS_SIMPLE_CONTENT(type)) {
22896 		    /*
22897 		    * Sanity check for complex types with simple content.
22898 		    */
22899 		    simpleType = type->contentTypeDef;
22900 		    if (simpleType == NULL) {
22901 			VERROR_INT("xmlSchemaXPathProcessHistory",
22902 			    "field resolves to a CT with simple content "
22903 			    "but the CT is missing the ST definition");
22904 			return (-1);
22905 		    }
22906 		} else
22907 		    simpleType = NULL;
22908 	    } else
22909 		simpleType = type;
22910 	    if (simpleType == NULL) {
22911 		xmlChar *str = NULL;
22912 
22913 		/*
22914 		* Not qualified if the field resolves to a node of non
22915 		* simple type.
22916 		*/
22917 		xmlSchemaCustomErr(ACTXT_CAST vctxt,
22918 		    XML_SCHEMAV_CVC_IDC, NULL,
22919 		    WXS_BASIC_CAST sto->matcher->aidc->def,
22920 		    "The XPath '%s' of a field of %s does evaluate to a node of "
22921 		    "non-simple type",
22922 		    sto->sel->xpath,
22923 		    xmlSchemaGetIDCDesignation(&str, sto->matcher->aidc->def));
22924 		FREE_AND_NULL(str);
22925 		sto->nbHistory--;
22926 		goto deregister_check;
22927 	    }
22928 
22929 	    if ((key == NULL) && (vctxt->inode->val == NULL)) {
22930 		/*
22931 		* Failed to provide the normalized value; maybe
22932 		* the value was invalid.
22933 		*/
22934 		VERROR(XML_SCHEMAV_CVC_IDC,
22935 		    WXS_BASIC_CAST sto->matcher->aidc->def,
22936 		    "Warning: No precomputed value available, the value "
22937 		    "was either invalid or something strange happened");
22938 		sto->nbHistory--;
22939 		goto deregister_check;
22940 	    } else {
22941 		xmlSchemaIDCMatcherPtr matcher = sto->matcher;
22942 		xmlSchemaPSVIIDCKeyPtr *keySeq;
22943 		int pos, idx;
22944 
22945 		/*
22946 		* The key will be anchored on the matcher's list of
22947 		* key-sequences. The position in this list is determined
22948 		* by the target node's depth relative to the matcher's
22949 		* depth of creation (i.e. the depth of the scope element).
22950 		*
22951 		* Element        Depth    Pos   List-entries
22952 		* <scope>          0              NULL
22953 		*   <bar>          1              NULL
22954 		*     <target/>    2       2      target
22955 		*   <bar>
22956                 * </scope>
22957 		*
22958 		* The size of the list is only dependent on the depth of
22959 		* the tree.
22960 		* An entry will be NULLed in selector_leave, i.e. when
22961 		* we hit the target's
22962 		*/
22963 		pos = sto->depth - matcher->depth;
22964 		idx = sto->sel->index;
22965 
22966 		/*
22967 		* Create/grow the array of key-sequences.
22968 		*/
22969 		if (matcher->keySeqs == NULL) {
22970 		    if (pos > 9)
22971 			matcher->sizeKeySeqs = pos * 2;
22972 		    else
22973 			matcher->sizeKeySeqs = 10;
22974 		    matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22975 			xmlMalloc(matcher->sizeKeySeqs *
22976 			sizeof(xmlSchemaPSVIIDCKeyPtr *));
22977 		    if (matcher->keySeqs == NULL) {
22978 			xmlSchemaVErrMemory(NULL,
22979 			    "allocating an array of key-sequences",
22980 			    NULL);
22981 			return(-1);
22982 		    }
22983 		    memset(matcher->keySeqs, 0,
22984 			matcher->sizeKeySeqs *
22985 			sizeof(xmlSchemaPSVIIDCKeyPtr *));
22986 		} else if (pos >= matcher->sizeKeySeqs) {
22987 		    int i = matcher->sizeKeySeqs;
22988 
22989 		    matcher->sizeKeySeqs *= 2;
22990 		    matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22991 			xmlRealloc(matcher->keySeqs,
22992 			matcher->sizeKeySeqs *
22993 			sizeof(xmlSchemaPSVIIDCKeyPtr *));
22994 		    if (matcher->keySeqs == NULL) {
22995 			xmlSchemaVErrMemory(NULL,
22996 			    "reallocating an array of key-sequences",
22997 			    NULL);
22998 			return (-1);
22999 		    }
23000 		    /*
23001 		    * The array needs to be NULLed.
23002 		    * TODO: Use memset?
23003 		    */
23004 		    for (; i < matcher->sizeKeySeqs; i++)
23005 			matcher->keySeqs[i] = NULL;
23006 		}
23007 
23008 		/*
23009 		* Get/create the key-sequence.
23010 		*/
23011 		keySeq = matcher->keySeqs[pos];
23012 		if (keySeq == NULL) {
23013 		    goto create_sequence;
23014 		} else if (keySeq[idx] != NULL) {
23015 		    xmlChar *str = NULL;
23016 		    /*
23017 		    * cvc-identity-constraint:
23018 		    * 3 For each node in the `target node set` all
23019 		    * of the {fields}, with that node as the context
23020 		    * node, evaluate to either an empty node-set or
23021 		    * a node-set with exactly one member, which must
23022 		    * have a simple type.
23023 		    *
23024 		    * The key was already set; report an error.
23025 		    */
23026 		    xmlSchemaCustomErr(ACTXT_CAST vctxt,
23027 			XML_SCHEMAV_CVC_IDC, NULL,
23028 			WXS_BASIC_CAST matcher->aidc->def,
23029 			"The XPath '%s' of a field of %s evaluates to a "
23030 			"node-set with more than one member",
23031 			sto->sel->xpath,
23032 			xmlSchemaGetIDCDesignation(&str, matcher->aidc->def));
23033 		    FREE_AND_NULL(str);
23034 		    sto->nbHistory--;
23035 		    goto deregister_check;
23036 		} else
23037 		    goto create_key;
23038 
23039 create_sequence:
23040 		/*
23041 		* Create a key-sequence.
23042 		*/
23043 		keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
23044 		    matcher->aidc->def->nbFields *
23045 		    sizeof(xmlSchemaPSVIIDCKeyPtr));
23046 		if (keySeq == NULL) {
23047 		    xmlSchemaVErrMemory(NULL,
23048 			"allocating an IDC key-sequence", NULL);
23049 		    return(-1);
23050 		}
23051 		memset(keySeq, 0, matcher->aidc->def->nbFields *
23052 		    sizeof(xmlSchemaPSVIIDCKeyPtr));
23053 		matcher->keySeqs[pos] = keySeq;
23054 create_key:
23055 		/*
23056 		* Create a key once per node only.
23057 		*/
23058 		if (key == NULL) {
23059 		    key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
23060 			sizeof(xmlSchemaPSVIIDCKey));
23061 		    if (key == NULL) {
23062 			xmlSchemaVErrMemory(NULL,
23063 			    "allocating a IDC key", NULL);
23064 			xmlFree(keySeq);
23065 			matcher->keySeqs[pos] = NULL;
23066 			return(-1);
23067 		    }
23068 		    /*
23069 		    * Consume the compiled value.
23070 		    */
23071 		    key->type = simpleType;
23072 		    key->val = vctxt->inode->val;
23073 		    vctxt->inode->val = NULL;
23074 		    /*
23075 		    * Store the key in a global list.
23076 		    */
23077 		    if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
23078 			xmlSchemaIDCFreeKey(key);
23079 			return (-1);
23080 		    }
23081 		}
23082 		keySeq[idx] = key;
23083 	    }
23084 	} else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
23085 
23086 	    xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
23087 	    /* xmlSchemaPSVIIDCBindingPtr bind; */
23088 	    xmlSchemaPSVIIDCNodePtr ntItem;
23089 	    xmlSchemaIDCMatcherPtr matcher;
23090 	    xmlSchemaIDCPtr idc;
23091 	    xmlSchemaItemListPtr targets;
23092 	    int pos, i, j, nbKeys;
23093 	    /*
23094 	    * Here we have the following scenario:
23095 	    * An IDC 'selector' state object resolved to a target node,
23096 	    * during the time this target node was in the
23097 	    * ancestor-or-self axis, the 'field' state object(s) looked
23098 	    * out for matching nodes to create a key-sequence for this
23099 	    * target node. Now we are back to this target node and need
23100 	    * to put the key-sequence, together with the target node
23101 	    * itself, into the node-table of the corresponding IDC
23102 	    * binding.
23103 	    */
23104 	    matcher = sto->matcher;
23105 	    idc = matcher->aidc->def;
23106 	    nbKeys = idc->nbFields;
23107 	    pos = depth - matcher->depth;
23108 	    /*
23109 	    * Check if the matcher has any key-sequences at all, plus
23110 	    * if it has a key-sequence for the current target node.
23111 	    */
23112 	    if ((matcher->keySeqs == NULL) ||
23113 		(matcher->sizeKeySeqs <= pos)) {
23114 		if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
23115 		    goto selector_key_error;
23116 		else
23117 		    goto selector_leave;
23118 	    }
23119 
23120 	    keySeq = &(matcher->keySeqs[pos]);
23121 	    if (*keySeq == NULL) {
23122 		if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
23123 		    goto selector_key_error;
23124 		else
23125 		    goto selector_leave;
23126 	    }
23127 
23128 	    for (i = 0; i < nbKeys; i++) {
23129 		if ((*keySeq)[i] == NULL) {
23130 		    /*
23131 		    * Not qualified, if not all fields did resolve.
23132 		    */
23133 		    if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
23134 			/*
23135 			* All fields of a "key" IDC must resolve.
23136 			*/
23137 			goto selector_key_error;
23138 		    }
23139 		    goto selector_leave;
23140 		}
23141 	    }
23142 	    /*
23143 	    * All fields did resolve.
23144 	    */
23145 
23146 	    /*
23147 	    * 4.1 If the {identity-constraint category} is unique(/key),
23148 	    * then no two members of the `qualified node set` have
23149 	    * `key-sequences` whose members are pairwise equal, as
23150 	    * defined by Equal in [XML Schemas: Datatypes].
23151 	    *
23152 	    * Get the IDC binding from the matcher and check for
23153 	    * duplicate key-sequences.
23154 	    */
23155 #if 0
23156 	    bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
23157 #endif
23158 	    targets = xmlSchemaIDCAcquireTargetList(vctxt, matcher);
23159 	    if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
23160 		(targets->nbItems != 0)) {
23161 		xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
23162 		xmlIDCHashEntryPtr e;
23163 
23164 		res = 0;
23165 
23166 		if (!matcher->htab)
23167 		    e = NULL;
23168 		else {
23169 		    xmlChar *value = NULL;
23170 		    xmlSchemaHashKeySequence(vctxt, &value, *keySeq, nbKeys);
23171 		    e = xmlHashLookup(matcher->htab, value);
23172 		    FREE_AND_NULL(value);
23173 		}
23174 
23175 		/*
23176 		* Compare the key-sequences, key by key.
23177 		*/
23178 		for (;e; e = e->next) {
23179 		    bkeySeq =
23180 			((xmlSchemaPSVIIDCNodePtr) targets->items[e->index])->keys;
23181 		    for (j = 0; j < nbKeys; j++) {
23182 			ckey = (*keySeq)[j];
23183 			bkey = bkeySeq[j];
23184 			res = xmlSchemaAreValuesEqual(ckey->val, bkey->val);
23185 			if (res == -1) {
23186 			    return (-1);
23187 			} else if (res == 0) {
23188 			    /*
23189 			    * One of the keys differs, so the key-sequence
23190 			    * won't be equal; get out.
23191 			    */
23192 			    break;
23193 			}
23194 		    }
23195 		    if (res == 1) {
23196 			/*
23197 			* Duplicate key-sequence found.
23198 			*/
23199 			break;
23200 		    }
23201 		}
23202 		if (e) {
23203 		    xmlChar *str = NULL, *strB = NULL;
23204 		    /*
23205 		    * TODO: Try to report the key-sequence.
23206 		    */
23207 		    xmlSchemaCustomErr(ACTXT_CAST vctxt,
23208 			XML_SCHEMAV_CVC_IDC, NULL,
23209 			WXS_BASIC_CAST idc,
23210 			"Duplicate key-sequence %s in %s",
23211 			xmlSchemaFormatIDCKeySequence(vctxt, &str,
23212 			    (*keySeq), nbKeys),
23213 			xmlSchemaGetIDCDesignation(&strB, idc));
23214 		    FREE_AND_NULL(str);
23215 		    FREE_AND_NULL(strB);
23216 		    goto selector_leave;
23217 		}
23218 	    }
23219 	    /*
23220 	    * Add a node-table item to the IDC binding.
23221 	    */
23222 	    ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
23223 		sizeof(xmlSchemaPSVIIDCNode));
23224 	    if (ntItem == NULL) {
23225 		xmlSchemaVErrMemory(NULL,
23226 		    "allocating an IDC node-table item", NULL);
23227 		xmlFree(*keySeq);
23228 		*keySeq = NULL;
23229 		return(-1);
23230 	    }
23231 	    memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
23232 
23233 	    /*
23234 	    * Store the node-table item in a global list.
23235 	    */
23236 	    if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
23237 		if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
23238 		    xmlFree(ntItem);
23239 		    xmlFree(*keySeq);
23240 		    *keySeq = NULL;
23241 		    return (-1);
23242 		}
23243 		ntItem->nodeQNameID = -1;
23244 	    } else {
23245 		/*
23246 		* Save a cached QName for this node on the IDC node, to be
23247 		* able to report it, even if the node is not saved.
23248 		*/
23249 		ntItem->nodeQNameID = xmlSchemaVAddNodeQName(vctxt,
23250 		    vctxt->inode->localName, vctxt->inode->nsName);
23251 		if (ntItem->nodeQNameID == -1) {
23252 		    xmlFree(ntItem);
23253 		    xmlFree(*keySeq);
23254 		    *keySeq = NULL;
23255 		    return (-1);
23256 		}
23257 	    }
23258 	    /*
23259 	    * Init the node-table item: Save the node, position and
23260 	    * consume the key-sequence.
23261 	    */
23262 	    ntItem->node = vctxt->node;
23263 	    ntItem->nodeLine = vctxt->inode->nodeLine;
23264 	    ntItem->keys = *keySeq;
23265 	    *keySeq = NULL;
23266 #if 0
23267 	    if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1)
23268 #endif
23269 	    if (xmlSchemaItemListAdd(targets, ntItem) == -1) {
23270 		if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
23271 		    /*
23272 		    * Free the item, since keyref items won't be
23273 		    * put on a global list.
23274 		    */
23275 		    xmlFree(ntItem->keys);
23276 		    xmlFree(ntItem);
23277 		}
23278 		return (-1);
23279 	    }
23280 	    if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
23281 		xmlChar *value = NULL;
23282 		xmlIDCHashEntryPtr r, e;
23283 		if (!matcher->htab)
23284 		  matcher->htab = xmlHashCreate(4);
23285 		xmlSchemaHashKeySequence(vctxt, &value, ntItem->keys, nbKeys);
23286 		e = xmlMalloc(sizeof *e);
23287 		e->index = targets->nbItems - 1;
23288 		r = xmlHashLookup(matcher->htab, value);
23289 		if (r) {
23290 		    e->next = r->next;
23291 		    r->next = e;
23292 		} else {
23293 		    e->next = NULL;
23294 		    xmlHashAddEntry(matcher->htab, value, e);
23295 		}
23296 		FREE_AND_NULL(value);
23297 	    }
23298 
23299 	    goto selector_leave;
23300 selector_key_error:
23301 	    {
23302 		xmlChar *str = NULL;
23303 		/*
23304 		* 4.2.1 (KEY) The `target node set` and the
23305 		* `qualified node set` are equal, that is, every
23306 		* member of the `target node set` is also a member
23307 		* of the `qualified node set` and vice versa.
23308 		*/
23309 		xmlSchemaCustomErr(ACTXT_CAST vctxt,
23310 		    XML_SCHEMAV_CVC_IDC, NULL,
23311 		    WXS_BASIC_CAST idc,
23312 		    "Not all fields of %s evaluate to a node",
23313 		    xmlSchemaGetIDCDesignation(&str, idc), NULL);
23314 		FREE_AND_NULL(str);
23315 	    }
23316 selector_leave:
23317 	    /*
23318 	    * Free the key-sequence if not added to the IDC table.
23319 	    */
23320 	    if ((keySeq != NULL) && (*keySeq != NULL)) {
23321 		xmlFree(*keySeq);
23322 		*keySeq = NULL;
23323 	    }
23324 	} /* if selector */
23325 
23326 	sto->nbHistory--;
23327 
23328 deregister_check:
23329 	/*
23330 	* Deregister state objects if they reach the depth of creation.
23331 	*/
23332 	if ((sto->nbHistory == 0) && (sto->depth == depth)) {
23333 #ifdef DEBUG_IDC
23334 	    xmlGenericError(xmlGenericErrorContext, "IDC:   STO pop '%s'\n",
23335 		sto->sel->xpath);
23336 #endif
23337 	    if (vctxt->xpathStates != sto) {
23338 		VERROR_INT("xmlSchemaXPathProcessHistory",
23339 		    "The state object to be removed is not the first "
23340 		    "in the list");
23341 	    }
23342 	    nextsto = sto->next;
23343 	    /*
23344 	    * Unlink from the list of active XPath state objects.
23345 	    */
23346 	    vctxt->xpathStates = sto->next;
23347 	    sto->next = vctxt->xpathStatePool;
23348 	    /*
23349 	    * Link it to the pool of reusable state objects.
23350 	    */
23351 	    vctxt->xpathStatePool = sto;
23352 	    sto = nextsto;
23353 	} else
23354 	    sto = sto->next;
23355     } /* while (sto != NULL) */
23356     return (0);
23357 }
23358 
23359 /**
23360  * xmlSchemaIDCRegisterMatchers:
23361  * @vctxt: the WXS validation context
23362  * @elemDecl: the element declaration
23363  *
23364  * Creates helper objects to evaluate IDC selectors/fields
23365  * successively.
23366  *
23367  * Returns 0 if OK and -1 on internal errors.
23368  */
23369 static int
xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,xmlSchemaElementPtr elemDecl)23370 xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
23371 			     xmlSchemaElementPtr elemDecl)
23372 {
23373     xmlSchemaIDCMatcherPtr matcher, last = NULL;
23374     xmlSchemaIDCPtr idc, refIdc;
23375     xmlSchemaIDCAugPtr aidc;
23376 
23377     idc = (xmlSchemaIDCPtr) elemDecl->idcs;
23378     if (idc == NULL)
23379 	return (0);
23380 
23381 #ifdef DEBUG_IDC
23382     {
23383 	xmlChar *str = NULL;
23384 	xmlGenericError(xmlGenericErrorContext,
23385 	    "IDC: REGISTER on %s, depth %d\n",
23386 	    (char *) xmlSchemaFormatQName(&str, vctxt->inode->nsName,
23387 		vctxt->inode->localName), vctxt->depth);
23388 	FREE_AND_NULL(str)
23389     }
23390 #endif
23391     if (vctxt->inode->idcMatchers != NULL) {
23392 	VERROR_INT("xmlSchemaIDCRegisterMatchers",
23393 	    "The chain of IDC matchers is expected to be empty");
23394 	return (-1);
23395     }
23396     do {
23397 	if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
23398 	    /*
23399 	    * Since IDCs bubbles are expensive we need to know the
23400 	    * depth at which the bubbles should stop; this will be
23401 	    * the depth of the top-most keyref IDC. If no keyref
23402 	    * references a key/unique IDC, the keyrefDepth will
23403 	    * be -1, indicating that no bubbles are needed.
23404 	    */
23405 	    refIdc = (xmlSchemaIDCPtr) idc->ref->item;
23406 	    if (refIdc != NULL) {
23407 		/*
23408 		* Remember that we have keyrefs on this node.
23409 		*/
23410 		vctxt->inode->hasKeyrefs = 1;
23411 		/*
23412 		* Lookup the referenced augmented IDC info.
23413 		*/
23414 		aidc = vctxt->aidcs;
23415 		while (aidc != NULL) {
23416 		    if (aidc->def == refIdc)
23417 			break;
23418 		    aidc = aidc->next;
23419 		}
23420 		if (aidc == NULL) {
23421 		    VERROR_INT("xmlSchemaIDCRegisterMatchers",
23422 			"Could not find an augmented IDC item for an IDC "
23423 			"definition");
23424 		    return (-1);
23425 		}
23426 		if ((aidc->keyrefDepth == -1) ||
23427 		    (vctxt->depth < aidc->keyrefDepth))
23428 		    aidc->keyrefDepth = vctxt->depth;
23429 	    }
23430 	}
23431 	/*
23432 	* Lookup the augmented IDC item for the IDC definition.
23433 	*/
23434 	aidc = vctxt->aidcs;
23435 	while (aidc != NULL) {
23436 	    if (aidc->def == idc)
23437 		break;
23438 	    aidc = aidc->next;
23439 	}
23440 	if (aidc == NULL) {
23441 	    VERROR_INT("xmlSchemaIDCRegisterMatchers",
23442 		"Could not find an augmented IDC item for an IDC definition");
23443 	    return (-1);
23444 	}
23445 	/*
23446 	* Create an IDC matcher for every IDC definition.
23447 	*/
23448 	if (vctxt->idcMatcherCache != NULL) {
23449 	    /*
23450 	    * Reuse a cached matcher.
23451 	    */
23452 	    matcher = vctxt->idcMatcherCache;
23453 	    vctxt->idcMatcherCache = matcher->nextCached;
23454 	    matcher->nextCached = NULL;
23455 	} else {
23456 	    matcher = (xmlSchemaIDCMatcherPtr)
23457 		xmlMalloc(sizeof(xmlSchemaIDCMatcher));
23458 	    if (matcher == NULL) {
23459 		xmlSchemaVErrMemory(vctxt,
23460 		    "allocating an IDC matcher", NULL);
23461 		return (-1);
23462 	    }
23463 	    memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
23464 	}
23465 	if (last == NULL)
23466 	    vctxt->inode->idcMatchers = matcher;
23467 	else
23468 	    last->next = matcher;
23469 	last = matcher;
23470 
23471 	matcher->type = IDC_MATCHER;
23472 	matcher->depth = vctxt->depth;
23473 	matcher->aidc = aidc;
23474 	matcher->idcType = aidc->def->type;
23475 #ifdef DEBUG_IDC
23476 	xmlGenericError(xmlGenericErrorContext, "IDC:   register matcher\n");
23477 #endif
23478 	/*
23479 	* Init the automaton state object.
23480 	*/
23481 	if (xmlSchemaIDCAddStateObject(vctxt, matcher,
23482 	    idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
23483 	    return (-1);
23484 
23485 	idc = idc->next;
23486     } while (idc != NULL);
23487     return (0);
23488 }
23489 
23490 static int
xmlSchemaIDCFillNodeTables(xmlSchemaValidCtxtPtr vctxt,xmlSchemaNodeInfoPtr ielem)23491 xmlSchemaIDCFillNodeTables(xmlSchemaValidCtxtPtr vctxt,
23492 			   xmlSchemaNodeInfoPtr ielem)
23493 {
23494     xmlSchemaPSVIIDCBindingPtr bind;
23495     int res, i, j, k, nbTargets, nbFields, nbDupls, nbNodeTable;
23496     xmlSchemaPSVIIDCKeyPtr *keys, *ntkeys;
23497     xmlSchemaPSVIIDCNodePtr *targets, *dupls;
23498 
23499     xmlSchemaIDCMatcherPtr matcher = ielem->idcMatchers;
23500     /* vctxt->createIDCNodeTables */
23501     while (matcher != NULL) {
23502 	/*
23503 	* Skip keyref IDCs and empty IDC target-lists.
23504 	*/
23505 	if ((matcher->aidc->def->type == XML_SCHEMA_TYPE_IDC_KEYREF) ||
23506 	    WXS_ILIST_IS_EMPTY(matcher->targets))
23507 	{
23508 	    matcher = matcher->next;
23509 	    continue;
23510 	}
23511 	/*
23512 	* If we _want_ the IDC node-table to be created in any case
23513 	* then do so. Otherwise create them only if keyrefs need them.
23514 	*/
23515 	if ((! vctxt->createIDCNodeTables) &&
23516 	    ((matcher->aidc->keyrefDepth == -1) ||
23517 	     (matcher->aidc->keyrefDepth > vctxt->depth)))
23518 	{
23519 	    matcher = matcher->next;
23520 	    continue;
23521 	}
23522 	/*
23523 	* Get/create the IDC binding on this element for the IDC definition.
23524 	*/
23525 	bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
23526 	if (bind == NULL)
23527 	   goto internal_error;
23528 
23529 	if (! WXS_ILIST_IS_EMPTY(bind->dupls)) {
23530 	    dupls = (xmlSchemaPSVIIDCNodePtr *) bind->dupls->items;
23531 	    nbDupls = bind->dupls->nbItems;
23532 	} else {
23533 	    dupls = NULL;
23534 	    nbDupls = 0;
23535 	}
23536 	if (bind->nodeTable != NULL) {
23537 	    nbNodeTable = bind->nbNodes;
23538 	} else {
23539 	    nbNodeTable = 0;
23540 	}
23541 
23542 	if ((nbNodeTable == 0) && (nbDupls == 0)) {
23543 	    /*
23544 	    * Transfer all IDC target-nodes to the IDC node-table.
23545 	    */
23546 	    bind->nodeTable =
23547 		(xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
23548 	    bind->sizeNodes = matcher->targets->sizeItems;
23549 	    bind->nbNodes = matcher->targets->nbItems;
23550 
23551 	    matcher->targets->items = NULL;
23552 	    matcher->targets->sizeItems = 0;
23553 	    matcher->targets->nbItems = 0;
23554 	    if (matcher->htab) {
23555 		xmlHashFree(matcher->htab, xmlFreeIDCHashEntry);
23556 		matcher->htab = NULL;
23557 	    }
23558 	} else {
23559 	    /*
23560 	    * Compare the key-sequences and add to the IDC node-table.
23561 	    */
23562 	    nbTargets = matcher->targets->nbItems;
23563 	    targets = (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
23564 	    nbFields = matcher->aidc->def->nbFields;
23565 	    i = 0;
23566 	    do {
23567 		keys = targets[i]->keys;
23568 		if (nbDupls) {
23569 		    /*
23570 		    * Search in already found duplicates first.
23571 		    */
23572 		    j = 0;
23573 		    do {
23574 			if (nbFields == 1) {
23575 			    res = xmlSchemaAreValuesEqual(keys[0]->val,
23576 				dupls[j]->keys[0]->val);
23577 			    if (res == -1)
23578 				goto internal_error;
23579 			    if (res == 1) {
23580 				/*
23581 				* Equal key-sequence.
23582 				*/
23583 				goto next_target;
23584 			    }
23585 			} else {
23586 			    res = 0;
23587 			    ntkeys = dupls[j]->keys;
23588 			    for (k = 0; k < nbFields; k++) {
23589 				res = xmlSchemaAreValuesEqual(keys[k]->val,
23590 				    ntkeys[k]->val);
23591 				if (res == -1)
23592 				    goto internal_error;
23593 				if (res == 0) {
23594 				    /*
23595 				    * One of the keys differs.
23596 				    */
23597 				    break;
23598 				}
23599 			    }
23600 			    if (res == 1) {
23601 				/*
23602 				* Equal key-sequence found.
23603 				*/
23604 				goto next_target;
23605 			    }
23606 			}
23607 			j++;
23608 		    } while (j < nbDupls);
23609 		}
23610 		if (nbNodeTable) {
23611 		    j = 0;
23612 		    do {
23613 			if (nbFields == 1) {
23614 			    res = xmlSchemaAreValuesEqual(keys[0]->val,
23615 				bind->nodeTable[j]->keys[0]->val);
23616 			    if (res == -1)
23617 				goto internal_error;
23618 			    if (res == 0) {
23619 				/*
23620 				* The key-sequence differs.
23621 				*/
23622 				goto next_node_table_entry;
23623 			    }
23624 			} else {
23625 			    res = 0;
23626 			    ntkeys = bind->nodeTable[j]->keys;
23627 			    for (k = 0; k < nbFields; k++) {
23628 				res = xmlSchemaAreValuesEqual(keys[k]->val,
23629 				    ntkeys[k]->val);
23630 				if (res == -1)
23631 				    goto internal_error;
23632 				if (res == 0) {
23633 				    /*
23634 				    * One of the keys differs.
23635 				    */
23636 				    goto next_node_table_entry;
23637 				}
23638 			    }
23639 			}
23640 			/*
23641 			* Add the duplicate to the list of duplicates.
23642 			*/
23643 			if (bind->dupls == NULL) {
23644 			    bind->dupls = xmlSchemaItemListCreate();
23645 			    if (bind->dupls == NULL)
23646 				goto internal_error;
23647 			}
23648 			if (xmlSchemaItemListAdd(bind->dupls, bind->nodeTable[j]) == -1)
23649 			    goto internal_error;
23650 			/*
23651 			* Remove the duplicate entry from the IDC node-table.
23652 			*/
23653 			bind->nodeTable[j] = bind->nodeTable[bind->nbNodes -1];
23654 			bind->nbNodes--;
23655 
23656 			goto next_target;
23657 
23658 next_node_table_entry:
23659 			j++;
23660 		    } while (j < nbNodeTable);
23661 		}
23662 		/*
23663 		* If everything is fine, then add the IDC target-node to
23664 		* the IDC node-table.
23665 		*/
23666 		if (xmlSchemaIDCAppendNodeTableItem(bind, targets[i]) == -1)
23667 		    goto internal_error;
23668 
23669 next_target:
23670 		i++;
23671 	    } while (i < nbTargets);
23672 	}
23673 	matcher = matcher->next;
23674     }
23675     return(0);
23676 
23677 internal_error:
23678     return(-1);
23679 }
23680 
23681 /**
23682  * xmlSchemaBubbleIDCNodeTables:
23683  * @depth: the current tree depth
23684  *
23685  * Merges IDC bindings of an element at @depth into the corresponding IDC
23686  * bindings of its parent element. If a duplicate note-table entry is found,
23687  * both, the parent node-table entry and child entry are discarded from the
23688  * node-table of the parent.
23689  *
23690  * Returns 0 if OK and -1 on internal errors.
23691  */
23692 static int
xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)23693 xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
23694 {
23695     xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
23696     xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL; /* parent IDC bindings. */
23697     xmlSchemaPSVIIDCNodePtr node, parNode = NULL, *dupls, *parNodes; /* node-table entries. */
23698     xmlSchemaIDCAugPtr aidc;
23699     int i, j, k, ret = 0, nbFields, oldNum, oldDupls;
23700 
23701     bind = vctxt->inode->idcTable;
23702     if (bind == NULL) {
23703 	/* Fine, no table, no bubbles. */
23704 	return (0);
23705     }
23706 
23707     parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
23708     /*
23709     * Walk all bindings; create new or add to existing bindings.
23710     * Remove duplicate key-sequences.
23711     */
23712     while (bind != NULL) {
23713 
23714 	if ((bind->nbNodes == 0) && WXS_ILIST_IS_EMPTY(bind->dupls))
23715 	    goto next_binding;
23716 	/*
23717 	* Check if the key/unique IDC table needs to be bubbled.
23718 	*/
23719 	if (! vctxt->createIDCNodeTables) {
23720 	    aidc = vctxt->aidcs;
23721 	    do {
23722 		if (aidc->def == bind->definition) {
23723 		    if ((aidc->keyrefDepth == -1) ||
23724 			(aidc->keyrefDepth >= vctxt->depth)) {
23725 			goto next_binding;
23726 		    }
23727 		    break;
23728 		}
23729 		aidc = aidc->next;
23730 	    } while (aidc != NULL);
23731 	}
23732 
23733 	if (parTable != NULL)
23734 	    parBind = *parTable;
23735 	/*
23736 	* Search a matching parent binding for the
23737 	* IDC definition.
23738 	*/
23739 	while (parBind != NULL) {
23740 	    if (parBind->definition == bind->definition)
23741 		break;
23742 	    parBind = parBind->next;
23743 	}
23744 
23745 	if (parBind != NULL) {
23746 	    /*
23747 	    * Compare every node-table entry of the child node,
23748 	    * i.e. the key-sequence within, ...
23749 	    */
23750 	    oldNum = parBind->nbNodes; /* Skip newly added items. */
23751 
23752 	    if (! WXS_ILIST_IS_EMPTY(parBind->dupls)) {
23753 		oldDupls = parBind->dupls->nbItems;
23754 		dupls = (xmlSchemaPSVIIDCNodePtr *) parBind->dupls->items;
23755 	    } else {
23756 		dupls = NULL;
23757 		oldDupls = 0;
23758 	    }
23759 
23760 	    parNodes = parBind->nodeTable;
23761 	    nbFields = bind->definition->nbFields;
23762 
23763 	    for (i = 0; i < bind->nbNodes; i++) {
23764 		node = bind->nodeTable[i];
23765 		if (node == NULL)
23766 		    continue;
23767 		/*
23768 		* ...with every key-sequence of the parent node, already
23769 		* evaluated to be a duplicate key-sequence.
23770 		*/
23771 		if (oldDupls) {
23772 		    j = 0;
23773 		    while (j < oldDupls) {
23774 			if (nbFields == 1) {
23775 			    ret = xmlSchemaAreValuesEqual(
23776 				node->keys[0]->val,
23777 				dupls[j]->keys[0]->val);
23778 			    if (ret == -1)
23779 				goto internal_error;
23780 			    if (ret == 0) {
23781 				j++;
23782 				continue;
23783 			    }
23784 			} else {
23785 			    parNode = dupls[j];
23786 			    for (k = 0; k < nbFields; k++) {
23787 				ret = xmlSchemaAreValuesEqual(
23788 				    node->keys[k]->val,
23789 				    parNode->keys[k]->val);
23790 				if (ret == -1)
23791 				    goto internal_error;
23792 				if (ret == 0)
23793 				    break;
23794 			    }
23795 			}
23796 			if (ret == 1)
23797 			    /* Duplicate found. */
23798 			    break;
23799 			j++;
23800 		    }
23801 		    if (j != oldDupls) {
23802 			/* Duplicate found. Skip this entry. */
23803 			continue;
23804 		    }
23805 		}
23806 		/*
23807 		* ... and with every key-sequence of the parent node.
23808 		*/
23809 		if (oldNum) {
23810 		    j = 0;
23811 		    while (j < oldNum) {
23812 			parNode = parNodes[j];
23813 			if (nbFields == 1) {
23814 			    ret = xmlSchemaAreValuesEqual(
23815 				node->keys[0]->val,
23816 				parNode->keys[0]->val);
23817 			    if (ret == -1)
23818 				goto internal_error;
23819 			    if (ret == 0) {
23820 				j++;
23821 				continue;
23822 			    }
23823 			} else {
23824 			    for (k = 0; k < nbFields; k++) {
23825 				ret = xmlSchemaAreValuesEqual(
23826 				    node->keys[k]->val,
23827 				    parNode->keys[k]->val);
23828 				if (ret == -1)
23829 				    goto internal_error;
23830 				if (ret == 0)
23831 				    break;
23832 			    }
23833 			}
23834 			if (ret == 1)
23835 			    /* Duplicate found. */
23836 			    break;
23837 			j++;
23838 		    }
23839 		    if (j != oldNum) {
23840 			/*
23841 			* Handle duplicates. Move the duplicate in
23842 			* the parent's node-table to the list of
23843 			* duplicates.
23844 			*/
23845 			oldNum--;
23846 			parBind->nbNodes--;
23847 			/*
23848 			* Move last old item to pos of duplicate.
23849 			*/
23850 			parNodes[j] = parNodes[oldNum];
23851 
23852 			if (parBind->nbNodes != oldNum) {
23853 			    /*
23854 			    * If new items exist, move last new item to
23855 			    * last of old items.
23856 			    */
23857 			    parNodes[oldNum] =
23858 				parNodes[parBind->nbNodes];
23859 			}
23860 			if (parBind->dupls == NULL) {
23861 			    parBind->dupls = xmlSchemaItemListCreate();
23862 			    if (parBind->dupls == NULL)
23863 				goto internal_error;
23864 			}
23865 			xmlSchemaItemListAdd(parBind->dupls, parNode);
23866 		    } else {
23867 			/*
23868 			* Add the node-table entry (node and key-sequence) of
23869 			* the child node to the node table of the parent node.
23870 			*/
23871 			if (parBind->nodeTable == NULL) {
23872 			    parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23873 				xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
23874 			    if (parBind->nodeTable == NULL) {
23875 				xmlSchemaVErrMemory(NULL,
23876 				    "allocating IDC list of node-table items", NULL);
23877 				goto internal_error;
23878 			    }
23879 			    parBind->sizeNodes = 1;
23880 			} else if (parBind->nbNodes >= parBind->sizeNodes) {
23881 			    parBind->sizeNodes *= 2;
23882 			    parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23883 				xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
23884 				sizeof(xmlSchemaPSVIIDCNodePtr));
23885 			    if (parBind->nodeTable == NULL) {
23886 				xmlSchemaVErrMemory(NULL,
23887 				    "re-allocating IDC list of node-table items", NULL);
23888 				goto internal_error;
23889 			    }
23890 			}
23891 			parNodes = parBind->nodeTable;
23892 			/*
23893 			* Append the new node-table entry to the 'new node-table
23894 			* entries' section.
23895 			*/
23896 			parNodes[parBind->nbNodes++] = node;
23897 		    }
23898 
23899 		}
23900 
23901 	    }
23902 	} else {
23903 	    /*
23904 	    * No binding for the IDC was found: create a new one and
23905 	    * copy all node-tables.
23906 	    */
23907 	    parBind = xmlSchemaIDCNewBinding(bind->definition);
23908 	    if (parBind == NULL)
23909 		goto internal_error;
23910 
23911 	    /*
23912 	    * TODO: Hmm, how to optimize the initial number of
23913 	    * allocated entries?
23914 	    */
23915 	    if (bind->nbNodes != 0) {
23916 		/*
23917 		* Add all IDC node-table entries.
23918 		*/
23919 		if (! vctxt->psviExposeIDCNodeTables) {
23920 		    /*
23921 		    * Just move the entries.
23922 		    * NOTE: this is quite save here, since
23923 		    * all the keyref lookups have already been
23924 		    * performed.
23925 		    */
23926 		    parBind->nodeTable = bind->nodeTable;
23927 		    bind->nodeTable = NULL;
23928 		    parBind->sizeNodes = bind->sizeNodes;
23929 		    bind->sizeNodes = 0;
23930 		    parBind->nbNodes = bind->nbNodes;
23931 		    bind->nbNodes = 0;
23932 		} else {
23933 		    /*
23934 		    * Copy the entries.
23935 		    */
23936 		    parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23937 			xmlMalloc(bind->nbNodes *
23938 			sizeof(xmlSchemaPSVIIDCNodePtr));
23939 		    if (parBind->nodeTable == NULL) {
23940 			xmlSchemaVErrMemory(NULL,
23941 			    "allocating an array of IDC node-table "
23942 			    "items", NULL);
23943 			xmlSchemaIDCFreeBinding(parBind);
23944 			goto internal_error;
23945 		    }
23946 		    parBind->sizeNodes = bind->nbNodes;
23947 		    parBind->nbNodes = bind->nbNodes;
23948 		    memcpy(parBind->nodeTable, bind->nodeTable,
23949 			bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
23950 		}
23951 	    }
23952 	    if (bind->dupls) {
23953 		/*
23954 		* Move the duplicates.
23955 		*/
23956 		if (parBind->dupls != NULL)
23957 		    xmlSchemaItemListFree(parBind->dupls);
23958 		parBind->dupls = bind->dupls;
23959 		bind->dupls = NULL;
23960 	    }
23961             if (parTable != NULL) {
23962                 if (*parTable == NULL)
23963                     *parTable = parBind;
23964                 else {
23965                     parBind->next = *parTable;
23966                     *parTable = parBind;
23967                 }
23968             }
23969 	}
23970 
23971 next_binding:
23972 	bind = bind->next;
23973     }
23974     return (0);
23975 
23976 internal_error:
23977     return(-1);
23978 }
23979 
23980 /**
23981  * xmlSchemaCheckCVCIDCKeyRef:
23982  * @vctxt: the WXS validation context
23983  * @elemDecl: the element declaration
23984  *
23985  * Check the cvc-idc-keyref constraints.
23986  */
23987 static int
xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)23988 xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
23989 {
23990     xmlSchemaIDCMatcherPtr matcher;
23991     xmlSchemaPSVIIDCBindingPtr bind;
23992 
23993     matcher = vctxt->inode->idcMatchers;
23994     /*
23995     * Find a keyref.
23996     */
23997     while (matcher != NULL) {
23998 	if ((matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) &&
23999 	    matcher->targets &&
24000 	    matcher->targets->nbItems)
24001 	{
24002 	    int i, j, k, res, nbFields, hasDupls;
24003 	    xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
24004 	    xmlSchemaPSVIIDCNodePtr refNode = NULL;
24005 	    xmlHashTablePtr table = NULL;
24006 
24007 	    nbFields = matcher->aidc->def->nbFields;
24008 
24009 	    /*
24010 	    * Find the IDC node-table for the referenced IDC key/unique.
24011 	    */
24012 	    bind = vctxt->inode->idcTable;
24013 	    while (bind != NULL) {
24014 		if ((xmlSchemaIDCPtr) matcher->aidc->def->ref->item ==
24015 		    bind->definition)
24016 		    break;
24017 		bind = bind->next;
24018 	    }
24019 	    hasDupls = (bind && bind->dupls && bind->dupls->nbItems) ? 1 : 0;
24020 	    /*
24021 	    * Search for a matching key-sequences.
24022 	    */
24023 	    if (bind) {
24024 		table = xmlHashCreate(bind->nbNodes * 2);
24025 		for (j = 0; j < bind->nbNodes; j++) {
24026 		    xmlChar *value;
24027 		    xmlIDCHashEntryPtr r, e;
24028 		    keys = bind->nodeTable[j]->keys;
24029 		    xmlSchemaHashKeySequence(vctxt, &value, keys, nbFields);
24030 		    e = xmlMalloc(sizeof *e);
24031 		    e->index = j;
24032 		    r = xmlHashLookup(table, value);
24033 		    if (r) {
24034 			e->next = r->next;
24035 			r->next = e;
24036 		    } else {
24037 			e->next = NULL;
24038 			xmlHashAddEntry(table, value, e);
24039 		    }
24040 		    FREE_AND_NULL(value);
24041 		}
24042 	    }
24043 	    for (i = 0; i < matcher->targets->nbItems; i++) {
24044 		res = 0;
24045 		refNode = matcher->targets->items[i];
24046 		if (bind != NULL) {
24047 		    xmlChar *value;
24048 		    xmlIDCHashEntryPtr e;
24049 		    refKeys = refNode->keys;
24050 		    xmlSchemaHashKeySequence(vctxt, &value, refKeys, nbFields);
24051 		    e = xmlHashLookup(table, value);
24052 		    FREE_AND_NULL(value);
24053 		    res = 0;
24054 		    for (;e; e = e->next) {
24055 			keys = bind->nodeTable[e->index]->keys;
24056 			for (k = 0; k < nbFields; k++) {
24057 			    res = xmlSchemaAreValuesEqual(keys[k]->val,
24058 							  refKeys[k]->val);
24059 			    if (res == 0)
24060 			        break;
24061 			    else if (res == -1) {
24062 				return (-1);
24063 			    }
24064 			}
24065 			if (res == 1) {
24066 			    /*
24067 			     * Match found.
24068 			     */
24069 			    break;
24070 			}
24071 		    }
24072 		    if ((res == 0) && hasDupls) {
24073 			/*
24074 			* Search in duplicates
24075 			*/
24076 			for (j = 0; j < bind->dupls->nbItems; j++) {
24077 			    keys = ((xmlSchemaPSVIIDCNodePtr)
24078 				bind->dupls->items[j])->keys;
24079 			    for (k = 0; k < nbFields; k++) {
24080 				res = xmlSchemaAreValuesEqual(keys[k]->val,
24081 				    refKeys[k]->val);
24082 				if (res == 0)
24083 				    break;
24084 				else if (res == -1) {
24085 				    return (-1);
24086 				}
24087 			    }
24088 			    if (res == 1) {
24089 				/*
24090 				* Match in duplicates found.
24091 				*/
24092 				xmlChar *str = NULL, *strB = NULL;
24093 				xmlSchemaKeyrefErr(vctxt,
24094 				    XML_SCHEMAV_CVC_IDC, refNode,
24095 				    (xmlSchemaTypePtr) matcher->aidc->def,
24096 				    "More than one match found for "
24097 				    "key-sequence %s of keyref '%s'",
24098 				    xmlSchemaFormatIDCKeySequence(vctxt, &str,
24099 					refNode->keys, nbFields),
24100 				    xmlSchemaGetComponentQName(&strB,
24101 					matcher->aidc->def));
24102 				FREE_AND_NULL(str);
24103 				FREE_AND_NULL(strB);
24104 				break;
24105 			    }
24106 			}
24107 		    }
24108 		}
24109 
24110 		if (res == 0) {
24111 		    xmlChar *str = NULL, *strB = NULL;
24112 		    xmlSchemaKeyrefErr(vctxt,
24113 			XML_SCHEMAV_CVC_IDC, refNode,
24114 			(xmlSchemaTypePtr) matcher->aidc->def,
24115 			"No match found for key-sequence %s of keyref '%s'",
24116 			xmlSchemaFormatIDCKeySequence(vctxt, &str,
24117 			    refNode->keys, nbFields),
24118 			xmlSchemaGetComponentQName(&strB, matcher->aidc->def));
24119 		    FREE_AND_NULL(str);
24120 		    FREE_AND_NULL(strB);
24121 		}
24122 	    }
24123 	    if (table) {
24124 		xmlHashFree(table, xmlFreeIDCHashEntry);
24125 	    }
24126 	}
24127 	matcher = matcher->next;
24128     }
24129     /* TODO: Return an error if any error encountered. */
24130     return (0);
24131 }
24132 
24133 /************************************************************************
24134  *									*
24135  *			XML Reader validation code                      *
24136  *									*
24137  ************************************************************************/
24138 
24139 static xmlSchemaAttrInfoPtr
xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)24140 xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)
24141 {
24142     xmlSchemaAttrInfoPtr iattr;
24143     /*
24144     * Grow/create list of attribute infos.
24145     */
24146     if (vctxt->attrInfos == NULL) {
24147 	vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
24148 	    xmlMalloc(sizeof(xmlSchemaAttrInfoPtr));
24149 	vctxt->sizeAttrInfos = 1;
24150 	if (vctxt->attrInfos == NULL) {
24151 	    xmlSchemaVErrMemory(vctxt,
24152 		"allocating attribute info list", NULL);
24153 	    return (NULL);
24154 	}
24155     } else if (vctxt->sizeAttrInfos <= vctxt->nbAttrInfos) {
24156 	vctxt->sizeAttrInfos++;
24157 	vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
24158 	    xmlRealloc(vctxt->attrInfos,
24159 		vctxt->sizeAttrInfos * sizeof(xmlSchemaAttrInfoPtr));
24160 	if (vctxt->attrInfos == NULL) {
24161 	    xmlSchemaVErrMemory(vctxt,
24162 		"re-allocating attribute info list", NULL);
24163 	    return (NULL);
24164 	}
24165     } else {
24166 	iattr = vctxt->attrInfos[vctxt->nbAttrInfos++];
24167 	if (iattr->localName != NULL) {
24168 	    VERROR_INT("xmlSchemaGetFreshAttrInfo",
24169 		"attr info not cleared");
24170 	    return (NULL);
24171 	}
24172 	iattr->nodeType = XML_ATTRIBUTE_NODE;
24173 	return (iattr);
24174     }
24175     /*
24176     * Create an attribute info.
24177     */
24178     iattr = (xmlSchemaAttrInfoPtr)
24179 	xmlMalloc(sizeof(xmlSchemaAttrInfo));
24180     if (iattr == NULL) {
24181 	xmlSchemaVErrMemory(vctxt, "creating new attribute info", NULL);
24182 	return (NULL);
24183     }
24184     memset(iattr, 0, sizeof(xmlSchemaAttrInfo));
24185     iattr->nodeType = XML_ATTRIBUTE_NODE;
24186     vctxt->attrInfos[vctxt->nbAttrInfos++] = iattr;
24187 
24188     return (iattr);
24189 }
24190 
24191 static int
xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,xmlNodePtr attrNode,int nodeLine,const xmlChar * localName,const xmlChar * nsName,int ownedNames,xmlChar * value,int ownedValue)24192 xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,
24193 			xmlNodePtr attrNode,
24194 			int nodeLine,
24195 			const xmlChar *localName,
24196 			const xmlChar *nsName,
24197 			int ownedNames,
24198 			xmlChar *value,
24199 			int ownedValue)
24200 {
24201     xmlSchemaAttrInfoPtr attr;
24202 
24203     attr = xmlSchemaGetFreshAttrInfo(vctxt);
24204     if (attr == NULL) {
24205 	VERROR_INT("xmlSchemaPushAttribute",
24206 	    "calling xmlSchemaGetFreshAttrInfo()");
24207 	return (-1);
24208     }
24209     attr->node = attrNode;
24210     attr->nodeLine = nodeLine;
24211     attr->state = XML_SCHEMAS_ATTR_UNKNOWN;
24212     attr->localName = localName;
24213     attr->nsName = nsName;
24214     if (ownedNames)
24215 	attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
24216     /*
24217     * Evaluate if it's an XSI attribute.
24218     */
24219     if (nsName != NULL) {
24220 	if (xmlStrEqual(localName, BAD_CAST "nil")) {
24221 	    if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
24222 		attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NIL;
24223 	    }
24224 	} else if (xmlStrEqual(localName, BAD_CAST "type")) {
24225 	    if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
24226 		attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_TYPE;
24227 	    }
24228 	} else if (xmlStrEqual(localName, BAD_CAST "schemaLocation")) {
24229 	    if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
24230 		attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC;
24231 	    }
24232 	} else if (xmlStrEqual(localName, BAD_CAST "noNamespaceSchemaLocation")) {
24233 	    if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
24234 		attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC;
24235 	    }
24236 	} else if (xmlStrEqual(attr->nsName, xmlNamespaceNs)) {
24237 	    attr->metaType = XML_SCHEMA_ATTR_INFO_META_XMLNS;
24238 	}
24239     }
24240     attr->value = value;
24241     if (ownedValue)
24242 	attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
24243     if (attr->metaType != 0)
24244 	attr->state = XML_SCHEMAS_ATTR_META;
24245     return (0);
24246 }
24247 
24248 /**
24249  * xmlSchemaClearElemInfo:
24250  * @vctxt: the WXS validation context
24251  * @ielem: the element information item
24252  */
24253 static void
xmlSchemaClearElemInfo(xmlSchemaValidCtxtPtr vctxt,xmlSchemaNodeInfoPtr ielem)24254 xmlSchemaClearElemInfo(xmlSchemaValidCtxtPtr vctxt,
24255 		       xmlSchemaNodeInfoPtr ielem)
24256 {
24257     ielem->hasKeyrefs = 0;
24258     ielem->appliedXPath = 0;
24259     if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
24260 	FREE_AND_NULL(ielem->localName);
24261 	FREE_AND_NULL(ielem->nsName);
24262     } else {
24263 	ielem->localName = NULL;
24264 	ielem->nsName = NULL;
24265     }
24266     if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
24267 	FREE_AND_NULL(ielem->value);
24268     } else {
24269 	ielem->value = NULL;
24270     }
24271     if (ielem->val != NULL) {
24272 	/*
24273 	* PSVI TODO: Be careful not to free it when the value is
24274 	* exposed via PSVI.
24275 	*/
24276 	xmlSchemaFreeValue(ielem->val);
24277 	ielem->val = NULL;
24278     }
24279     if (ielem->idcMatchers != NULL) {
24280 	/*
24281 	* REVISIT OPTIMIZE TODO: Use a pool of IDC matchers.
24282 	*   Does it work?
24283 	*/
24284 	xmlSchemaIDCReleaseMatcherList(vctxt, ielem->idcMatchers);
24285 #if 0
24286 	xmlSchemaIDCFreeMatcherList(ielem->idcMatchers);
24287 #endif
24288 	ielem->idcMatchers = NULL;
24289     }
24290     if (ielem->idcTable != NULL) {
24291 	/*
24292 	* OPTIMIZE TODO: Use a pool of IDC tables??.
24293 	*/
24294 	xmlSchemaIDCFreeIDCTable(ielem->idcTable);
24295 	ielem->idcTable = NULL;
24296     }
24297     if (ielem->regexCtxt != NULL) {
24298 	xmlRegFreeExecCtxt(ielem->regexCtxt);
24299 	ielem->regexCtxt = NULL;
24300     }
24301     if (ielem->nsBindings != NULL) {
24302 	xmlFree((xmlChar **)ielem->nsBindings);
24303 	ielem->nsBindings = NULL;
24304 	ielem->nbNsBindings = 0;
24305 	ielem->sizeNsBindings = 0;
24306     }
24307 }
24308 
24309 /**
24310  * xmlSchemaGetFreshElemInfo:
24311  * @vctxt: the schema validation context
24312  *
24313  * Creates/reuses and initializes the element info item for
24314  * the current tree depth.
24315  *
24316  * Returns the element info item or NULL on API or internal errors.
24317  */
24318 static xmlSchemaNodeInfoPtr
xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)24319 xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)
24320 {
24321     xmlSchemaNodeInfoPtr info = NULL;
24322 
24323     if (vctxt->depth > vctxt->sizeElemInfos) {
24324 	VERROR_INT("xmlSchemaGetFreshElemInfo",
24325 	    "inconsistent depth encountered");
24326 	return (NULL);
24327     }
24328     if (vctxt->elemInfos == NULL) {
24329 	vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
24330 	    xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
24331 	if (vctxt->elemInfos == NULL) {
24332 	    xmlSchemaVErrMemory(vctxt,
24333 		"allocating the element info array", NULL);
24334 	    return (NULL);
24335 	}
24336 	memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
24337 	vctxt->sizeElemInfos = 10;
24338     } else if (vctxt->sizeElemInfos <= vctxt->depth) {
24339 	int i = vctxt->sizeElemInfos;
24340 
24341 	vctxt->sizeElemInfos *= 2;
24342 	vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
24343 	    xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
24344 	    sizeof(xmlSchemaNodeInfoPtr));
24345 	if (vctxt->elemInfos == NULL) {
24346 	    xmlSchemaVErrMemory(vctxt,
24347 		"re-allocating the element info array", NULL);
24348 	    return (NULL);
24349 	}
24350 	/*
24351 	* We need the new memory to be NULLed.
24352 	* TODO: Use memset instead?
24353 	*/
24354 	for (; i < vctxt->sizeElemInfos; i++)
24355 	    vctxt->elemInfos[i] = NULL;
24356     } else
24357 	info = vctxt->elemInfos[vctxt->depth];
24358 
24359     if (info == NULL) {
24360 	info = (xmlSchemaNodeInfoPtr)
24361 	    xmlMalloc(sizeof(xmlSchemaNodeInfo));
24362 	if (info == NULL) {
24363 	    xmlSchemaVErrMemory(vctxt,
24364 		"allocating an element info", NULL);
24365 	    return (NULL);
24366 	}
24367 	vctxt->elemInfos[vctxt->depth] = info;
24368     } else {
24369 	if (info->localName != NULL) {
24370 	    VERROR_INT("xmlSchemaGetFreshElemInfo",
24371 		"elem info has not been cleared");
24372 	    return (NULL);
24373 	}
24374     }
24375     memset(info, 0, sizeof(xmlSchemaNodeInfo));
24376     info->nodeType = XML_ELEMENT_NODE;
24377     info->depth = vctxt->depth;
24378 
24379     return (info);
24380 }
24381 
24382 #define ACTIVATE_ATTRIBUTE(item) vctxt->inode = (xmlSchemaNodeInfoPtr) item;
24383 #define ACTIVATE_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth];
24384 #define ACTIVATE_PARENT_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth -1];
24385 
24386 static int
xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,xmlNodePtr node,xmlSchemaTypePtr type,xmlSchemaValType valType,const xmlChar * value,xmlSchemaValPtr val,unsigned long length,int fireErrors)24387 xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,
24388 			xmlNodePtr node,
24389 			xmlSchemaTypePtr type,
24390 			xmlSchemaValType valType,
24391 			const xmlChar * value,
24392 			xmlSchemaValPtr val,
24393 			unsigned long length,
24394 			int fireErrors)
24395 {
24396     int ret, error = 0, found;
24397 
24398     xmlSchemaTypePtr tmpType;
24399     xmlSchemaFacetLinkPtr facetLink;
24400     xmlSchemaFacetPtr facet;
24401     unsigned long len = 0;
24402     xmlSchemaWhitespaceValueType ws;
24403 
24404     /*
24405     * In Libxml2, derived built-in types have currently no explicit facets.
24406     */
24407     if (type->type == XML_SCHEMA_TYPE_BASIC)
24408 	return (0);
24409 
24410     /*
24411     * NOTE: Do not jump away, if the facetSet of the given type is
24412     * empty: until now, "pattern" and "enumeration" facets of the
24413     * *base types* need to be checked as well.
24414     */
24415     if (type->facetSet == NULL)
24416 	goto pattern_and_enum;
24417 
24418     if (! WXS_IS_ATOMIC(type)) {
24419 	if (WXS_IS_LIST(type))
24420 	    goto WXS_IS_LIST;
24421 	else
24422 	    goto pattern_and_enum;
24423     }
24424 
24425     /*
24426     * Whitespace handling is only of importance for string-based
24427     * types.
24428     */
24429     tmpType = xmlSchemaGetPrimitiveType(type);
24430     if ((tmpType->builtInType == XML_SCHEMAS_STRING) ||
24431 	WXS_IS_ANY_SIMPLE_TYPE(tmpType)) {
24432 	ws = xmlSchemaGetWhiteSpaceFacetValue(type);
24433     } else
24434 	ws = XML_SCHEMA_WHITESPACE_COLLAPSE;
24435 
24436     /*
24437     * If the value was not computed (for string or
24438     * anySimpleType based types), then use the provided
24439     * type.
24440     */
24441     if (val != NULL)
24442 	valType = xmlSchemaGetValType(val);
24443 
24444     ret = 0;
24445     for (facetLink = type->facetSet; facetLink != NULL;
24446 	facetLink = facetLink->next) {
24447 	/*
24448 	* Skip the pattern "whiteSpace": it is used to
24449 	* format the character content beforehand.
24450 	*/
24451 	switch (facetLink->facet->type) {
24452 	    case XML_SCHEMA_FACET_WHITESPACE:
24453 	    case XML_SCHEMA_FACET_PATTERN:
24454 	    case XML_SCHEMA_FACET_ENUMERATION:
24455 		continue;
24456 	    case XML_SCHEMA_FACET_LENGTH:
24457 	    case XML_SCHEMA_FACET_MINLENGTH:
24458 	    case XML_SCHEMA_FACET_MAXLENGTH:
24459 		ret = xmlSchemaValidateLengthFacetWhtsp(facetLink->facet,
24460 		    valType, value, val, &len, ws);
24461 		break;
24462 	    default:
24463 		ret = xmlSchemaValidateFacetWhtsp(facetLink->facet, ws,
24464 		    valType, value, val, ws);
24465 		break;
24466 	}
24467 	if (ret < 0) {
24468 	    AERROR_INT("xmlSchemaValidateFacets",
24469 		"validating against a atomic type facet");
24470 	    return (-1);
24471 	} else if (ret > 0) {
24472 	    if (fireErrors)
24473 		xmlSchemaFacetErr(actxt, ret, node,
24474 		value, len, type, facetLink->facet, NULL, NULL, NULL);
24475 	    else
24476 		return (ret);
24477 	    if (error == 0)
24478 		error = ret;
24479 	}
24480 	ret = 0;
24481     }
24482 
24483 WXS_IS_LIST:
24484     if (! WXS_IS_LIST(type))
24485 	goto pattern_and_enum;
24486     /*
24487     * "length", "minLength" and "maxLength" of list types.
24488     */
24489     ret = 0;
24490     for (facetLink = type->facetSet; facetLink != NULL;
24491 	facetLink = facetLink->next) {
24492 
24493 	switch (facetLink->facet->type) {
24494 	    case XML_SCHEMA_FACET_LENGTH:
24495 	    case XML_SCHEMA_FACET_MINLENGTH:
24496 	    case XML_SCHEMA_FACET_MAXLENGTH:
24497 		ret = xmlSchemaValidateListSimpleTypeFacet(facetLink->facet,
24498 		    value, length, NULL);
24499 		break;
24500 	    default:
24501 		continue;
24502 	}
24503 	if (ret < 0) {
24504 	    AERROR_INT("xmlSchemaValidateFacets",
24505 		"validating against a list type facet");
24506 	    return (-1);
24507 	} else if (ret > 0) {
24508 	    if (fireErrors)
24509 		xmlSchemaFacetErr(actxt, ret, node,
24510 		value, length, type, facetLink->facet, NULL, NULL, NULL);
24511 	    else
24512 		return (ret);
24513 	    if (error == 0)
24514 		error = ret;
24515 	}
24516 	ret = 0;
24517     }
24518 
24519 pattern_and_enum:
24520     found = 0;
24521     /*
24522     * Process enumerations. Facet values are in the value space
24523     * of the defining type's base type. This seems to be a bug in the
24524     * XML Schema 1.0 spec. Use the whitespace type of the base type.
24525     * Only the first set of enumerations in the ancestor-or-self axis
24526     * is used for validation.
24527     */
24528     ret = 0;
24529     tmpType = type;
24530     do {
24531         for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
24532             if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
24533                 continue;
24534             found = 1;
24535             ret = xmlSchemaAreValuesEqual(facet->val, val);
24536             if (ret == 1)
24537                 break;
24538             else if (ret < 0) {
24539                 AERROR_INT("xmlSchemaValidateFacets",
24540                     "validating against an enumeration facet");
24541                 return (-1);
24542             }
24543         }
24544         if (ret != 0)
24545             break;
24546         /*
24547         * Break on the first set of enumerations. Any additional
24548         *  enumerations which might be existent on the ancestors
24549         *  of the current type are restricted by this set; thus
24550         *  *must* *not* be taken into account.
24551         */
24552         if (found)
24553             break;
24554         tmpType = tmpType->baseType;
24555     } while ((tmpType != NULL) &&
24556         (tmpType->type != XML_SCHEMA_TYPE_BASIC));
24557     if (found && (ret == 0)) {
24558         ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
24559         if (fireErrors) {
24560             xmlSchemaFacetErr(actxt, ret, node,
24561                 value, 0, type, NULL, NULL, NULL, NULL);
24562         } else
24563             return (ret);
24564         if (error == 0)
24565             error = ret;
24566     }
24567 
24568     /*
24569     * Process patters. Pattern facets are ORed at type level
24570     * and ANDed if derived. Walk the base type axis.
24571     */
24572     tmpType = type;
24573     facet = NULL;
24574     do {
24575         found = 0;
24576         for (facetLink = tmpType->facetSet; facetLink != NULL;
24577             facetLink = facetLink->next) {
24578             if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
24579                 continue;
24580             found = 1;
24581             /*
24582             * NOTE that for patterns, @value needs to be the
24583             * normalized value.
24584             */
24585             ret = xmlRegexpExec(facetLink->facet->regexp, value);
24586             if (ret == 1)
24587                 break;
24588             else if (ret < 0) {
24589                 AERROR_INT("xmlSchemaValidateFacets",
24590                     "validating against a pattern facet");
24591                 return (-1);
24592             } else {
24593                 /*
24594                 * Save the last non-validating facet.
24595                 */
24596                 facet = facetLink->facet;
24597             }
24598         }
24599         if (found && (ret != 1)) {
24600             ret = XML_SCHEMAV_CVC_PATTERN_VALID;
24601             if (fireErrors) {
24602                 xmlSchemaFacetErr(actxt, ret, node,
24603                     value, 0, type, facet, NULL, NULL, NULL);
24604             } else
24605                 return (ret);
24606             if (error == 0)
24607                 error = ret;
24608             break;
24609         }
24610         tmpType = tmpType->baseType;
24611     } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
24612 
24613     return (error);
24614 }
24615 
24616 static xmlChar *
xmlSchemaNormalizeValue(xmlSchemaTypePtr type,const xmlChar * value)24617 xmlSchemaNormalizeValue(xmlSchemaTypePtr type,
24618 			const xmlChar *value)
24619 {
24620     switch (xmlSchemaGetWhiteSpaceFacetValue(type)) {
24621 	case XML_SCHEMA_WHITESPACE_COLLAPSE:
24622 	    return (xmlSchemaCollapseString(value));
24623 	case XML_SCHEMA_WHITESPACE_REPLACE:
24624 	    return (xmlSchemaWhiteSpaceReplace(value));
24625 	default:
24626 	    return (NULL);
24627     }
24628 }
24629 
24630 static int
xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt,const xmlChar * value,xmlSchemaValPtr * val,int valNeeded)24631 xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt,
24632 		       const xmlChar *value,
24633 		       xmlSchemaValPtr *val,
24634 		       int valNeeded)
24635 {
24636     int ret;
24637     const xmlChar *nsName;
24638     xmlChar *local, *prefix = NULL;
24639 
24640     ret = xmlValidateQName(value, 1);
24641     if (ret != 0) {
24642 	if (ret == -1) {
24643 	    VERROR_INT("xmlSchemaValidateQName",
24644 		"calling xmlValidateQName()");
24645 	    return (-1);
24646 	}
24647 	return( XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
24648     }
24649     /*
24650     * NOTE: xmlSplitQName2 will always return a duplicated
24651     * strings.
24652     */
24653     local = xmlSplitQName2(value, &prefix);
24654     if (local == NULL)
24655 	local = xmlStrdup(value);
24656     /*
24657     * OPTIMIZE TODO: Use flags for:
24658     *  - is there any namespace binding?
24659     *  - is there a default namespace?
24660     */
24661     nsName = xmlSchemaLookupNamespace(vctxt, prefix);
24662 
24663     if (prefix != NULL) {
24664 	xmlFree(prefix);
24665 	/*
24666 	* A namespace must be found if the prefix is
24667 	* NOT NULL.
24668 	*/
24669 	if (nsName == NULL) {
24670 	    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24671 	    xmlSchemaCustomErr(ACTXT_CAST vctxt, ret, NULL,
24672 		WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24673 		"The QName value '%s' has no "
24674 		"corresponding namespace declaration in "
24675 		"scope", value, NULL);
24676 	    if (local != NULL)
24677 		xmlFree(local);
24678 	    return (ret);
24679 	}
24680     }
24681     if (valNeeded && val) {
24682 	if (nsName != NULL)
24683 	    *val = xmlSchemaNewQNameValue(
24684 		BAD_CAST xmlStrdup(nsName), BAD_CAST local);
24685 	else
24686 	    *val = xmlSchemaNewQNameValue(NULL,
24687 		BAD_CAST local);
24688     } else
24689 	xmlFree(local);
24690     return (0);
24691 }
24692 
24693 /*
24694 * cvc-simple-type
24695 */
24696 static int
xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,xmlNodePtr node,xmlSchemaTypePtr type,const xmlChar * value,xmlSchemaValPtr * retVal,int fireErrors,int normalize,int isNormalized)24697 xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
24698 			     xmlNodePtr node,
24699 			     xmlSchemaTypePtr type,
24700 			     const xmlChar *value,
24701 			     xmlSchemaValPtr *retVal,
24702 			     int fireErrors,
24703 			     int normalize,
24704 			     int isNormalized)
24705 {
24706     int ret = 0, valNeeded = (retVal) ? 1 : 0;
24707     xmlSchemaValPtr val = NULL;
24708     /* xmlSchemaWhitespaceValueType ws; */
24709     xmlChar *normValue = NULL;
24710 
24711 #define NORMALIZE(atype) \
24712     if ((! isNormalized) && \
24713     (normalize || (type->flags & XML_SCHEMAS_TYPE_NORMVALUENEEDED))) { \
24714 	normValue = xmlSchemaNormalizeValue(atype, value); \
24715 	if (normValue != NULL) \
24716 	    value = normValue; \
24717 	isNormalized = 1; \
24718     }
24719 
24720     if ((retVal != NULL) && (*retVal != NULL)) {
24721 	xmlSchemaFreeValue(*retVal);
24722 	*retVal = NULL;
24723     }
24724     /*
24725     * 3.14.4 Simple Type Definition Validation Rules
24726     * Validation Rule: String Valid
24727     */
24728     /*
24729     * 1 It is schema-valid with respect to that definition as defined
24730     * by Datatype Valid in [XML Schemas: Datatypes].
24731     */
24732     /*
24733     * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
24734     * the empty set, as defined in Type Derivation OK (Simple) ($3.14.6), then
24735     * the string must be a `declared entity name`.
24736     */
24737     /*
24738     * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
24739     * given the empty set, as defined in Type Derivation OK (Simple) ($3.14.6),
24740     * then every whitespace-delimited substring of the string must be a `declared
24741     * entity name`.
24742     */
24743     /*
24744     * 2.3 otherwise no further condition applies.
24745     */
24746     if ((! valNeeded) && (type->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
24747 	valNeeded = 1;
24748     if (value == NULL)
24749 	value = BAD_CAST "";
24750     if (WXS_IS_ANY_SIMPLE_TYPE(type) || WXS_IS_ATOMIC(type)) {
24751 	xmlSchemaTypePtr biType; /* The built-in type. */
24752 	/*
24753 	* SPEC (1.2.1) "if {variety} is `atomic` then the string must `match`
24754 	* a literal in the `lexical space` of {base type definition}"
24755 	*/
24756 	/*
24757 	* Whitespace-normalize.
24758 	*/
24759 	NORMALIZE(type);
24760 	if (type->type != XML_SCHEMA_TYPE_BASIC) {
24761 	    /*
24762 	    * Get the built-in type.
24763 	    */
24764 	    biType = type->baseType;
24765 	    while ((biType != NULL) &&
24766 		(biType->type != XML_SCHEMA_TYPE_BASIC))
24767 		biType = biType->baseType;
24768 
24769 	    if (biType == NULL) {
24770 		AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24771 		    "could not get the built-in type");
24772 		goto internal_error;
24773 	    }
24774 	} else
24775 	    biType = type;
24776 	/*
24777 	* NOTATIONs need to be processed here, since they need
24778 	* to lookup in the hashtable of NOTATION declarations of the schema.
24779 	*/
24780 	if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
24781 	    switch (biType->builtInType) {
24782 		case XML_SCHEMAS_NOTATION:
24783 		    ret = xmlSchemaValidateNotation(
24784 			(xmlSchemaValidCtxtPtr) actxt,
24785 			((xmlSchemaValidCtxtPtr) actxt)->schema,
24786 			NULL, value, &val, valNeeded);
24787 		    break;
24788 		case XML_SCHEMAS_QNAME:
24789 		    ret = xmlSchemaValidateQName((xmlSchemaValidCtxtPtr) actxt,
24790 			value, &val, valNeeded);
24791 		    break;
24792 		default:
24793 		    /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
24794 		    if (valNeeded)
24795 			ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24796 			    value, &val, node);
24797 		    else
24798 			ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24799 			    value, NULL, node);
24800 		    break;
24801 	    }
24802 	} else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
24803 	    switch (biType->builtInType) {
24804 		case XML_SCHEMAS_NOTATION:
24805 		    ret = xmlSchemaValidateNotation(NULL,
24806 			((xmlSchemaParserCtxtPtr) actxt)->schema, node,
24807 			value, &val, valNeeded);
24808 		    break;
24809 		default:
24810 		    /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
24811 		    if (valNeeded)
24812 			ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24813 			    value, &val, node);
24814 		    else
24815 			ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24816 			    value, NULL, node);
24817 		    break;
24818 	    }
24819 	} else {
24820 	    /*
24821 	    * Validation via a public API is not implemented yet.
24822 	    */
24823 	    TODO
24824 	    goto internal_error;
24825 	}
24826 	if (ret != 0) {
24827 	    if (ret < 0) {
24828 		AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24829 		    "validating against a built-in type");
24830 		goto internal_error;
24831 	    }
24832 	    if (WXS_IS_LIST(type))
24833 		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24834 	    else
24835 		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24836 	}
24837 	if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24838 	    /*
24839 	    * Check facets.
24840 	    */
24841 	    ret = xmlSchemaValidateFacets(actxt, node, type,
24842 		(xmlSchemaValType) biType->builtInType, value, val,
24843 		0, fireErrors);
24844 	    if (ret != 0) {
24845 		if (ret < 0) {
24846 		    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24847 			"validating facets of atomic simple type");
24848 		    goto internal_error;
24849 		}
24850 		if (WXS_IS_LIST(type))
24851 		    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24852 		else
24853 		    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24854 	    }
24855 	}
24856 	else if (fireErrors && (ret > 0))
24857 	    xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24858     } else if (WXS_IS_LIST(type)) {
24859 
24860 	xmlSchemaTypePtr itemType;
24861 	const xmlChar *cur, *end;
24862 	xmlChar *tmpValue = NULL;
24863 	unsigned long len = 0;
24864 	xmlSchemaValPtr prevVal = NULL, curVal = NULL;
24865 	/* 1.2.2 if {variety} is `list` then the string must be a sequence
24866 	* of white space separated tokens, each of which `match`es a literal
24867 	* in the `lexical space` of {item type definition}
24868 	*/
24869 	/*
24870 	* Note that XML_SCHEMAS_TYPE_NORMVALUENEEDED will be set if
24871 	* the list type has an enum or pattern facet.
24872 	*/
24873 	NORMALIZE(type);
24874 	/*
24875 	* VAL TODO: Optimize validation of empty values.
24876 	* VAL TODO: We do not have computed values for lists.
24877 	*/
24878 	itemType = WXS_LIST_ITEMTYPE(type);
24879 	cur = value;
24880 	do {
24881 	    while (IS_BLANK_CH(*cur))
24882 		cur++;
24883 	    end = cur;
24884 	    while ((*end != 0) && (!(IS_BLANK_CH(*end))))
24885 		end++;
24886 	    if (end == cur)
24887 		break;
24888 	    tmpValue = xmlStrndup(cur, end - cur);
24889 	    len++;
24890 
24891 	    if (valNeeded)
24892 		ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24893 		    tmpValue, &curVal, fireErrors, 0, 1);
24894 	    else
24895 		ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24896 		    tmpValue, NULL, fireErrors, 0, 1);
24897 	    FREE_AND_NULL(tmpValue);
24898 	    if (curVal != NULL) {
24899 		/*
24900 		* Add to list of computed values.
24901 		*/
24902 		if (val == NULL)
24903 		    val = curVal;
24904 		else
24905 		    xmlSchemaValueAppend(prevVal, curVal);
24906 		prevVal = curVal;
24907 		curVal = NULL;
24908 	    }
24909 	    if (ret != 0) {
24910 		if (ret < 0) {
24911 		    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24912 			"validating an item of list simple type");
24913 		    goto internal_error;
24914 		}
24915 		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24916 		break;
24917 	    }
24918 	    cur = end;
24919 	} while (*cur != 0);
24920 	FREE_AND_NULL(tmpValue);
24921 	if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24922 	    /*
24923 	    * Apply facets (pattern, enumeration).
24924 	    */
24925 	    ret = xmlSchemaValidateFacets(actxt, node, type,
24926 		XML_SCHEMAS_UNKNOWN, value, val,
24927 		len, fireErrors);
24928 	    if (ret != 0) {
24929 		if (ret < 0) {
24930 		    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24931 			"validating facets of list simple type");
24932 		    goto internal_error;
24933 		}
24934 		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24935 	    }
24936 	}
24937 	if (fireErrors && (ret > 0)) {
24938 	    /*
24939 	    * Report the normalized value.
24940 	    */
24941 	    normalize = 1;
24942 	    NORMALIZE(type);
24943 	    xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24944 	}
24945     } else if (WXS_IS_UNION(type)) {
24946 	xmlSchemaTypeLinkPtr memberLink;
24947 	/*
24948 	* TODO: For all datatypes `derived` by `union`  whiteSpace does
24949 	* not apply directly; however, the normalization behavior of `union`
24950 	* types is controlled by the value of whiteSpace on that one of the
24951 	* `memberTypes` against which the `union` is successfully validated.
24952 	*
24953 	* This means that the value is normalized by the first validating
24954 	* member type, then the facets of the union type are applied. This
24955 	* needs changing of the value!
24956 	*/
24957 
24958 	/*
24959 	* 1.2.3 if {variety} is `union` then the string must `match` a
24960 	* literal in the `lexical space` of at least one member of
24961 	* {member type definitions}
24962 	*/
24963 	memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
24964 	if (memberLink == NULL) {
24965 	    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24966 		"union simple type has no member types");
24967 	    goto internal_error;
24968 	}
24969 	/*
24970 	* Always normalize union type values, since we currently
24971 	* cannot store the whitespace information with the value
24972 	* itself; otherwise a later value-comparison would be
24973 	* not possible.
24974 	*/
24975 	while (memberLink != NULL) {
24976 	    if (valNeeded)
24977 		ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24978 		    memberLink->type, value, &val, 0, 1, 0);
24979 	    else
24980 		ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24981 		    memberLink->type, value, NULL, 0, 1, 0);
24982 	    if (ret <= 0)
24983 		break;
24984 	    memberLink = memberLink->next;
24985 	}
24986 	if (ret != 0) {
24987 	    if (ret < 0) {
24988 		AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24989 		    "validating members of union simple type");
24990 		goto internal_error;
24991 	    }
24992 	    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
24993 	}
24994 	/*
24995 	* Apply facets (pattern, enumeration).
24996 	*/
24997 	if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24998 	    /*
24999 	    * The normalization behavior of `union` types is controlled by
25000 	    * the value of whiteSpace on that one of the `memberTypes`
25001 	    * against which the `union` is successfully validated.
25002 	    */
25003 	    NORMALIZE(memberLink->type);
25004 	    ret = xmlSchemaValidateFacets(actxt, node, type,
25005 		XML_SCHEMAS_UNKNOWN, value, val,
25006 		0, fireErrors);
25007 	    if (ret != 0) {
25008 		if (ret < 0) {
25009 		    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
25010 			"validating facets of union simple type");
25011 		    goto internal_error;
25012 		}
25013 		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
25014 	    }
25015 	}
25016 	if (fireErrors && (ret > 0))
25017 	    xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
25018     }
25019 
25020     if (normValue != NULL)
25021 	xmlFree(normValue);
25022     if (ret == 0) {
25023 	if (retVal != NULL)
25024 	    *retVal = val;
25025 	else if (val != NULL)
25026 	    xmlSchemaFreeValue(val);
25027     } else if (val != NULL)
25028 	xmlSchemaFreeValue(val);
25029     return (ret);
25030 internal_error:
25031     if (normValue != NULL)
25032 	xmlFree(normValue);
25033     if (val != NULL)
25034 	xmlSchemaFreeValue(val);
25035     return (-1);
25036 }
25037 
25038 static int
xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt,const xmlChar * value,const xmlChar ** nsName,const xmlChar ** localName)25039 xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt,
25040 			   const xmlChar *value,
25041 			   const xmlChar **nsName,
25042 			   const xmlChar **localName)
25043 {
25044     int ret = 0;
25045 
25046     if ((nsName == NULL) || (localName == NULL))
25047 	return (-1);
25048     *nsName = NULL;
25049     *localName = NULL;
25050 
25051     ret = xmlValidateQName(value, 1);
25052     if (ret == -1)
25053 	return (-1);
25054     if (ret > 0) {
25055 	xmlSchemaSimpleTypeErr(ACTXT_CAST vctxt,
25056 	    XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
25057 	    value, xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), 1);
25058 	return (1);
25059     }
25060     {
25061 	xmlChar *local = NULL;
25062 	xmlChar *prefix;
25063 
25064 	/*
25065 	* NOTE: xmlSplitQName2 will return a duplicated
25066 	* string.
25067 	*/
25068 	local = xmlSplitQName2(value, &prefix);
25069 	if (local == NULL)
25070 	    *localName = xmlDictLookup(vctxt->dict, value, -1);
25071 	else {
25072 	    *localName = xmlDictLookup(vctxt->dict, local, -1);
25073 	    xmlFree(local);
25074 	}
25075 
25076 	*nsName = xmlSchemaLookupNamespace(vctxt, prefix);
25077 
25078 	if (prefix != NULL) {
25079 	    xmlFree(prefix);
25080 	    /*
25081 	    * A namespace must be found if the prefix is NOT NULL.
25082 	    */
25083 	    if (*nsName == NULL) {
25084 		xmlSchemaCustomErr(ACTXT_CAST vctxt,
25085 		    XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
25086 		    WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
25087 		    "The QName value '%s' has no "
25088 		    "corresponding namespace declaration in scope",
25089 		    value, NULL);
25090 		return (2);
25091 	    }
25092 	}
25093     }
25094     return (0);
25095 }
25096 
25097 static int
xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,xmlSchemaAttrInfoPtr iattr,xmlSchemaTypePtr * localType,xmlSchemaElementPtr elemDecl)25098 xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,
25099 			xmlSchemaAttrInfoPtr iattr,
25100 			xmlSchemaTypePtr *localType,
25101 			xmlSchemaElementPtr elemDecl)
25102 {
25103     int ret = 0;
25104     /*
25105     * cvc-elt (3.3.4) : (4)
25106     * AND
25107     * Schema-Validity Assessment (Element) (cvc-assess-elt)
25108     *   (1.2.1.2.1) - (1.2.1.2.4)
25109     * Handle 'xsi:type'.
25110     */
25111     if (localType == NULL)
25112 	return (-1);
25113     *localType = NULL;
25114     if (iattr == NULL)
25115 	return (0);
25116     else {
25117 	const xmlChar *nsName = NULL, *local = NULL;
25118 	/*
25119 	* TODO: We should report a *warning* that the type was overridden
25120 	* by the instance.
25121 	*/
25122 	ACTIVATE_ATTRIBUTE(iattr);
25123 	/*
25124 	* (cvc-elt) (3.3.4) : (4.1)
25125 	* (cvc-assess-elt) (1.2.1.2.2)
25126 	*/
25127 	ret = xmlSchemaVExpandQName(vctxt, iattr->value,
25128 	    &nsName, &local);
25129 	if (ret != 0) {
25130 	    if (ret < 0) {
25131 		VERROR_INT("xmlSchemaValidateElementByDeclaration",
25132 		    "calling xmlSchemaQNameExpand() to validate the "
25133 		    "attribute 'xsi:type'");
25134 		goto internal_error;
25135 	    }
25136 	    goto exit;
25137 	}
25138 	/*
25139 	* (cvc-elt) (3.3.4) : (4.2)
25140 	* (cvc-assess-elt) (1.2.1.2.3)
25141 	*/
25142 	*localType = xmlSchemaGetType(vctxt->schema, local, nsName);
25143 	if (*localType == NULL) {
25144 	    xmlChar *str = NULL;
25145 
25146 	    xmlSchemaCustomErr(ACTXT_CAST vctxt,
25147 		XML_SCHEMAV_CVC_ELT_4_2, NULL,
25148 		WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
25149 		"The QName value '%s' of the xsi:type attribute does not "
25150 		"resolve to a type definition",
25151 		xmlSchemaFormatQName(&str, nsName, local), NULL);
25152 	    FREE_AND_NULL(str);
25153 	    ret = vctxt->err;
25154 	    goto exit;
25155 	}
25156 	if (elemDecl != NULL) {
25157 	    int set = 0;
25158 
25159 	    /*
25160 	    * SPEC cvc-elt (3.3.4) : (4.3) (Type Derivation OK)
25161 	    * "The `local type definition` must be validly
25162 	    * derived from the {type definition} given the union of
25163 	    * the {disallowed substitutions} and the {type definition}'s
25164 	    * {prohibited substitutions}, as defined in
25165 	    * Type Derivation OK (Complex) ($3.4.6)
25166 	    * (if it is a complex type definition),
25167 	    * or given {disallowed substitutions} as defined in Type
25168 	    * Derivation OK (Simple) ($3.14.6) (if it is a simple type
25169 	    * definition)."
25170 	    *
25171 	    * {disallowed substitutions}: the "block" on the element decl.
25172 	    * {prohibited substitutions}: the "block" on the type def.
25173 	    */
25174 	    /*
25175 	    * OPTIMIZE TODO: We could map types already evaluated
25176 	    * to be validly derived from other types to avoid checking
25177 	    * this over and over for the same types.
25178 	    */
25179 	    if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) ||
25180 		(elemDecl->subtypes->flags &
25181 		    XML_SCHEMAS_TYPE_BLOCK_EXTENSION))
25182 		set |= SUBSET_EXTENSION;
25183 
25184 	    if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) ||
25185 		(elemDecl->subtypes->flags &
25186 		    XML_SCHEMAS_TYPE_BLOCK_RESTRICTION))
25187 		set |= SUBSET_RESTRICTION;
25188 
25189 	    /*
25190 	    * REMOVED and CHANGED since this produced a parser context
25191 	    * which adds to the string dict of the schema. So this would
25192 	    * change the schema and we don't want this. We don't need
25193 	    * the parser context anymore.
25194 	    *
25195 	    * if ((vctxt->pctxt == NULL) &&
25196 	    *	(xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
25197 	    *	    return (-1);
25198 	    */
25199 
25200 	    if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST vctxt, *localType,
25201 		elemDecl->subtypes, set) != 0) {
25202 		xmlChar *str = NULL;
25203 
25204 		xmlSchemaCustomErr(ACTXT_CAST vctxt,
25205 		    XML_SCHEMAV_CVC_ELT_4_3, NULL, NULL,
25206 		    "The type definition '%s', specified by xsi:type, is "
25207 		    "blocked or not validly derived from the type definition "
25208 		    "of the element declaration",
25209 		    xmlSchemaFormatQName(&str,
25210 			(*localType)->targetNamespace,
25211 			(*localType)->name),
25212 		    NULL);
25213 		FREE_AND_NULL(str);
25214 		ret = vctxt->err;
25215 		*localType = NULL;
25216 	    }
25217 	}
25218     }
25219 exit:
25220     ACTIVATE_ELEM;
25221     return (ret);
25222 internal_error:
25223     ACTIVATE_ELEM;
25224     return (-1);
25225 }
25226 
25227 static int
xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt)25228 xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt)
25229 {
25230     xmlSchemaElementPtr elemDecl = vctxt->inode->decl;
25231     xmlSchemaTypePtr actualType;
25232 
25233     /*
25234     * cvc-elt (3.3.4) : 1
25235     */
25236     if (elemDecl == NULL) {
25237 	VERROR(XML_SCHEMAV_CVC_ELT_1, NULL,
25238 	    "No matching declaration available");
25239         return (vctxt->err);
25240     }
25241     actualType = WXS_ELEM_TYPEDEF(elemDecl);
25242     /*
25243     * cvc-elt (3.3.4) : 2
25244     */
25245     if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
25246 	VERROR(XML_SCHEMAV_CVC_ELT_2, NULL,
25247 	    "The element declaration is abstract");
25248         return (vctxt->err);
25249     }
25250     if (actualType == NULL) {
25251 	VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
25252 	    "The type definition is absent");
25253 	return (XML_SCHEMAV_CVC_TYPE_1);
25254     }
25255     if (vctxt->nbAttrInfos != 0) {
25256 	int ret;
25257 	xmlSchemaAttrInfoPtr iattr;
25258 	/*
25259 	* cvc-elt (3.3.4) : 3
25260 	* Handle 'xsi:nil'.
25261 	*/
25262 	iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25263 	    XML_SCHEMA_ATTR_INFO_META_XSI_NIL);
25264 	if (iattr) {
25265 	    ACTIVATE_ATTRIBUTE(iattr);
25266 	    /*
25267 	    * Validate the value.
25268 	    */
25269 	    ret = xmlSchemaVCheckCVCSimpleType(
25270 		ACTXT_CAST vctxt, NULL,
25271 		xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
25272 		iattr->value, &(iattr->val), 1, 0, 0);
25273 	    ACTIVATE_ELEM;
25274 	    if (ret < 0) {
25275 		VERROR_INT("xmlSchemaValidateElemDecl",
25276 		    "calling xmlSchemaVCheckCVCSimpleType() to "
25277 		    "validate the attribute 'xsi:nil'");
25278 		return (-1);
25279 	    }
25280 	    if (ret == 0) {
25281 		if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
25282 		    /*
25283 		    * cvc-elt (3.3.4) : 3.1
25284 		    */
25285 		    VERROR(XML_SCHEMAV_CVC_ELT_3_1, NULL,
25286 			"The element is not 'nillable'");
25287 		    /* Does not return an error on purpose. */
25288 		} else {
25289 		    if (xmlSchemaValueGetAsBoolean(iattr->val)) {
25290 			/*
25291 			* cvc-elt (3.3.4) : 3.2.2
25292 			*/
25293 			if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
25294 			    (elemDecl->value != NULL)) {
25295 			    VERROR(XML_SCHEMAV_CVC_ELT_3_2_2, NULL,
25296 				"The element cannot be 'nilled' because "
25297 				"there is a fixed value constraint defined "
25298 				"for it");
25299 			     /* Does not return an error on purpose. */
25300 			} else
25301 			    vctxt->inode->flags |=
25302 				XML_SCHEMA_ELEM_INFO_NILLED;
25303 		    }
25304 		}
25305 	    }
25306 	}
25307 	/*
25308 	* cvc-elt (3.3.4) : 4
25309 	* Handle 'xsi:type'.
25310 	*/
25311 	iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25312 	    XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
25313 	if (iattr) {
25314 	    xmlSchemaTypePtr localType = NULL;
25315 
25316 	    ret = xmlSchemaProcessXSIType(vctxt, iattr, &localType,
25317 		elemDecl);
25318 	    if (ret != 0) {
25319 		if (ret == -1) {
25320 		    VERROR_INT("xmlSchemaValidateElemDecl",
25321 			"calling xmlSchemaProcessXSIType() to "
25322 			"process the attribute 'xsi:type'");
25323 		    return (-1);
25324 		}
25325 		/* Does not return an error on purpose. */
25326 	    }
25327 	    if (localType != NULL) {
25328 		vctxt->inode->flags |= XML_SCHEMA_ELEM_INFO_LOCAL_TYPE;
25329 		actualType = localType;
25330 	    }
25331 	}
25332     }
25333     /*
25334     * IDC: Register identity-constraint XPath matchers.
25335     */
25336     if ((elemDecl->idcs != NULL) &&
25337 	(xmlSchemaIDCRegisterMatchers(vctxt, elemDecl) == -1))
25338 	    return (-1);
25339     /*
25340     * No actual type definition.
25341     */
25342     if (actualType == NULL) {
25343 	VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
25344 	    "The type definition is absent");
25345 	return (XML_SCHEMAV_CVC_TYPE_1);
25346     }
25347     /*
25348     * Remember the actual type definition.
25349     */
25350     vctxt->inode->typeDef = actualType;
25351 
25352     return (0);
25353 }
25354 
25355 static int
xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt)25356 xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt)
25357 {
25358     xmlSchemaAttrInfoPtr iattr;
25359     int ret = 0, i;
25360 
25361     /*
25362     * SPEC cvc-type (3.1.1)
25363     * "The attributes of must be empty, excepting those whose namespace
25364     * name is identical to http://www.w3.org/2001/XMLSchema-instance and
25365     * whose local name is one of type, nil, schemaLocation or
25366     * noNamespaceSchemaLocation."
25367     */
25368     if (vctxt->nbAttrInfos == 0)
25369 	return (0);
25370     for (i = 0; i < vctxt->nbAttrInfos; i++) {
25371 	iattr = vctxt->attrInfos[i];
25372 	if (! iattr->metaType) {
25373 	    ACTIVATE_ATTRIBUTE(iattr)
25374 	    xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25375 		XML_SCHEMAV_CVC_TYPE_3_1_1, iattr, NULL);
25376 	    ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
25377         }
25378     }
25379     ACTIVATE_ELEM
25380     return (ret);
25381 }
25382 
25383 /*
25384 * Cleanup currently used attribute infos.
25385 */
25386 static void
xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)25387 xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)
25388 {
25389     int i;
25390     xmlSchemaAttrInfoPtr attr;
25391 
25392     if (vctxt->nbAttrInfos == 0)
25393 	return;
25394     for (i = 0; i < vctxt->nbAttrInfos; i++) {
25395 	attr = vctxt->attrInfos[i];
25396 	if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
25397 	    if (attr->localName != NULL)
25398 		xmlFree((xmlChar *) attr->localName);
25399 	    if (attr->nsName != NULL)
25400 		xmlFree((xmlChar *) attr->nsName);
25401 	}
25402 	if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
25403 	    if (attr->value != NULL)
25404 		xmlFree((xmlChar *) attr->value);
25405 	}
25406 	if (attr->val != NULL) {
25407 	    xmlSchemaFreeValue(attr->val);
25408 	    attr->val = NULL;
25409 	}
25410 	memset(attr, 0, sizeof(xmlSchemaAttrInfo));
25411     }
25412     vctxt->nbAttrInfos = 0;
25413 }
25414 
25415 /*
25416 * 3.4.4 Complex Type Definition Validation Rules
25417 *   Element Locally Valid (Complex Type) (cvc-complex-type)
25418 * 3.2.4 Attribute Declaration Validation Rules
25419 *   Validation Rule: Attribute Locally Valid (cvc-attribute)
25420 *   Attribute Locally Valid (Use) (cvc-au)
25421 *
25422 * Only "assessed" attribute information items will be visible to
25423 * IDCs. I.e. not "lax" (without declaration) and "skip" wild attributes.
25424 */
25425 static int
xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)25426 xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)
25427 {
25428     xmlSchemaTypePtr type = vctxt->inode->typeDef;
25429     xmlSchemaItemListPtr attrUseList;
25430     xmlSchemaAttributeUsePtr attrUse = NULL;
25431     xmlSchemaAttributePtr attrDecl = NULL;
25432     xmlSchemaAttrInfoPtr iattr, tmpiattr;
25433     int i, j, found, nbAttrs, nbUses;
25434     int xpathRes = 0, res, wildIDs = 0, fixed;
25435     xmlNodePtr defAttrOwnerElem = NULL;
25436 
25437     /*
25438     * SPEC (cvc-attribute)
25439     * (1) "The declaration must not be `absent` (see Missing
25440     * Sub-components ($5.3) for how this can fail to be
25441     * the case)."
25442     * (2) "Its {type definition} must not be absent."
25443     *
25444     * NOTE (1) + (2): This is not handled here, since we currently do not
25445     * allow validation against schemas which have missing sub-components.
25446     *
25447     * SPEC (cvc-complex-type)
25448     * (3) "For each attribute information item in the element information
25449     * item's [attributes] excepting those whose [namespace name] is
25450     * identical to http://www.w3.org/2001/XMLSchema-instance and whose
25451     * [local name] is one of type, nil, schemaLocation or
25452     * noNamespaceSchemaLocation, the appropriate case among the following
25453     * must be true:
25454     *
25455     */
25456     attrUseList = (xmlSchemaItemListPtr) type->attrUses;
25457     /*
25458     * @nbAttrs is the number of attributes present in the instance.
25459     */
25460     nbAttrs = vctxt->nbAttrInfos;
25461     if (attrUseList != NULL)
25462 	nbUses = attrUseList->nbItems;
25463     else
25464 	nbUses = 0;
25465     for (i = 0; i < nbUses; i++) {
25466         found = 0;
25467 	attrUse = attrUseList->items[i];
25468 	attrDecl = WXS_ATTRUSE_DECL(attrUse);
25469         for (j = 0; j < nbAttrs; j++) {
25470 	    iattr = vctxt->attrInfos[j];
25471 	    /*
25472 	    * SPEC (cvc-complex-type) (3)
25473 	    * Skip meta attributes.
25474 	    */
25475 	    if (iattr->metaType)
25476 		continue;
25477 	    if (iattr->localName[0] != attrDecl->name[0])
25478 		continue;
25479 	    if (!xmlStrEqual(iattr->localName, attrDecl->name))
25480 		continue;
25481 	    if (!xmlStrEqual(iattr->nsName, attrDecl->targetNamespace))
25482 		continue;
25483 	    found = 1;
25484 	    /*
25485 	    * SPEC (cvc-complex-type)
25486 	    * (3.1) "If there is among the {attribute uses} an attribute
25487 	    * use with an {attribute declaration} whose {name} matches
25488 	    * the attribute information item's [local name] and whose
25489 	    * {target namespace} is identical to the attribute information
25490 	    * item's [namespace name] (where an `absent` {target namespace}
25491 	    * is taken to be identical to a [namespace name] with no value),
25492 	    * then the attribute information must be `valid` with respect
25493 	    * to that attribute use as per Attribute Locally Valid (Use)
25494 	    * ($3.5.4). In this case the {attribute declaration} of that
25495 	    * attribute use is the `context-determined declaration` for the
25496 	    * attribute information item with respect to Schema-Validity
25497 	    * Assessment (Attribute) ($3.2.4) and
25498 	    * Assessment Outcome (Attribute) ($3.2.5).
25499 	    */
25500 	    iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
25501 	    iattr->use = attrUse;
25502 	    /*
25503 	    * Context-determined declaration.
25504 	    */
25505 	    iattr->decl = attrDecl;
25506 	    iattr->typeDef = attrDecl->subtypes;
25507 	    break;
25508 	}
25509 
25510 	if (found)
25511 	    continue;
25512 
25513 	if (attrUse->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
25514 	    /*
25515 	    * Handle non-existent, required attributes.
25516 	    *
25517 	    * SPEC (cvc-complex-type)
25518 	    * (4) "The {attribute declaration} of each attribute use in
25519 	    * the {attribute uses} whose {required} is true matches one
25520 	    * of the attribute information items in the element information
25521 	    * item's [attributes] as per clause 3.1 above."
25522 	    */
25523 	    tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
25524 	    if (tmpiattr == NULL) {
25525 		VERROR_INT(
25526 		    "xmlSchemaVAttributesComplex",
25527 		    "calling xmlSchemaGetFreshAttrInfo()");
25528 		return (-1);
25529 	    }
25530 	    tmpiattr->state = XML_SCHEMAS_ATTR_ERR_MISSING;
25531 	    tmpiattr->use = attrUse;
25532 	    tmpiattr->decl = attrDecl;
25533 	} else if ((attrUse->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
25534 	    ((attrUse->defValue != NULL) ||
25535 	     (attrDecl->defValue != NULL))) {
25536 	    /*
25537 	    * Handle non-existent, optional, default/fixed attributes.
25538 	    */
25539 	    tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
25540 	    if (tmpiattr == NULL) {
25541 		VERROR_INT(
25542 		    "xmlSchemaVAttributesComplex",
25543 		    "calling xmlSchemaGetFreshAttrInfo()");
25544 		return (-1);
25545 	    }
25546 	    tmpiattr->state = XML_SCHEMAS_ATTR_DEFAULT;
25547 	    tmpiattr->use = attrUse;
25548 	    tmpiattr->decl = attrDecl;
25549 	    tmpiattr->typeDef = attrDecl->subtypes;
25550 	    tmpiattr->localName = attrDecl->name;
25551 	    tmpiattr->nsName = attrDecl->targetNamespace;
25552 	}
25553     }
25554 
25555     if (vctxt->nbAttrInfos == 0)
25556 	return (0);
25557     /*
25558     * Validate against the wildcard.
25559     */
25560     if (type->attributeWildcard != NULL) {
25561 	/*
25562 	* SPEC (cvc-complex-type)
25563 	* (3.2.1) "There must be an {attribute wildcard}."
25564 	*/
25565 	for (i = 0; i < nbAttrs; i++) {
25566 	    iattr = vctxt->attrInfos[i];
25567 	    /*
25568 	    * SPEC (cvc-complex-type) (3)
25569 	    * Skip meta attributes.
25570 	    */
25571 	    if (iattr->state != XML_SCHEMAS_ATTR_UNKNOWN)
25572 		continue;
25573 	    /*
25574 	    * SPEC (cvc-complex-type)
25575 	    * (3.2.2) "The attribute information item must be `valid` with
25576 	    * respect to it as defined in Item Valid (Wildcard) ($3.10.4)."
25577 	    *
25578 	    * SPEC Item Valid (Wildcard) (cvc-wildcard)
25579 	    * "... its [namespace name] must be `valid` with respect to
25580 	    * the wildcard constraint, as defined in Wildcard allows
25581 	    * Namespace Name ($3.10.4)."
25582 	    */
25583 	    if (xmlSchemaCheckCVCWildcardNamespace(type->attributeWildcard,
25584 		    iattr->nsName) == 0) {
25585 		/*
25586 		* Handle processContents.
25587 		*
25588 		* SPEC (cvc-wildcard):
25589 		* processContents | context-determined declaration:
25590 		* "strict"          "mustFind"
25591 		* "lax"             "none"
25592 		* "skip"            "skip"
25593 		*/
25594 		if (type->attributeWildcard->processContents ==
25595 		    XML_SCHEMAS_ANY_SKIP) {
25596 		     /*
25597 		    * context-determined declaration = "skip"
25598 		    *
25599 		    * SPEC PSVI Assessment Outcome (Attribute)
25600 		    * [validity] = "notKnown"
25601 		    * [validation attempted] = "none"
25602 		    */
25603 		    iattr->state = XML_SCHEMAS_ATTR_WILD_SKIP;
25604 		    continue;
25605 		}
25606 		/*
25607 		* Find an attribute declaration.
25608 		*/
25609 		iattr->decl = xmlSchemaGetAttributeDecl(vctxt->schema,
25610 		    iattr->localName, iattr->nsName);
25611 		if (iattr->decl != NULL) {
25612 		    iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
25613 		    /*
25614 		    * SPEC (cvc-complex-type)
25615 		    * (5) "Let [Definition:]  the wild IDs be the set of
25616 		    * all attribute information item to which clause 3.2
25617 		    * applied and whose `validation` resulted in a
25618 		    * `context-determined declaration` of mustFind or no
25619 		    * `context-determined declaration` at all, and whose
25620 		    * [local name] and [namespace name] resolve (as
25621 		    * defined by QName resolution (Instance) ($3.15.4)) to
25622 		    * an attribute declaration whose {type definition} is
25623 		    * or is derived from ID. Then all of the following
25624 		    * must be true:"
25625 		    */
25626 		    iattr->typeDef = WXS_ATTR_TYPEDEF(iattr->decl);
25627 		    if (xmlSchemaIsDerivedFromBuiltInType(
25628 			iattr->typeDef, XML_SCHEMAS_ID)) {
25629 			/*
25630 			* SPEC (5.1) "There must be no more than one
25631 			* item in `wild IDs`."
25632 			*/
25633 			if (wildIDs != 0) {
25634 			    /* VAL TODO */
25635 			    iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID;
25636 			    TODO
25637 			    continue;
25638 			}
25639 			wildIDs++;
25640 			/*
25641 			* SPEC (cvc-complex-type)
25642 			* (5.2) "If `wild IDs` is non-empty, there must not
25643 			* be any attribute uses among the {attribute uses}
25644 			* whose {attribute declaration}'s {type definition}
25645 			* is or is derived from ID."
25646 			*/
25647                         if (attrUseList != NULL) {
25648                             for (j = 0; j < attrUseList->nbItems; j++) {
25649                                 if (xmlSchemaIsDerivedFromBuiltInType(
25650                                     WXS_ATTRUSE_TYPEDEF(attrUseList->items[j]),
25651                                     XML_SCHEMAS_ID)) {
25652                                     /* URGENT VAL TODO: implement */
25653                             iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID;
25654                                     TODO
25655                                     break;
25656                                 }
25657                             }
25658                         }
25659 		    }
25660 		} else if (type->attributeWildcard->processContents ==
25661 		    XML_SCHEMAS_ANY_LAX) {
25662 		    iattr->state = XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL;
25663 		    /*
25664 		    * SPEC PSVI Assessment Outcome (Attribute)
25665 		    * [validity] = "notKnown"
25666 		    * [validation attempted] = "none"
25667 		    */
25668 		} else {
25669 		    iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL;
25670 		}
25671 	    }
25672 	}
25673     }
25674 
25675     if (vctxt->nbAttrInfos == 0)
25676 	return (0);
25677 
25678     /*
25679     * Get the owner element; needed for creation of default attributes.
25680     * This fixes bug #341337, reported by David Grohmann.
25681     */
25682     if (vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
25683 	xmlSchemaNodeInfoPtr ielem = vctxt->elemInfos[vctxt->depth];
25684 	if (ielem && ielem->node && ielem->node->doc)
25685 	    defAttrOwnerElem = ielem->node;
25686     }
25687     /*
25688     * Validate values, create default attributes, evaluate IDCs.
25689     */
25690     for (i = 0; i < vctxt->nbAttrInfos; i++) {
25691 	iattr = vctxt->attrInfos[i];
25692 	/*
25693 	* VAL TODO: Note that we won't try to resolve IDCs to
25694 	* "lax" and "skip" validated attributes. Check what to
25695 	* do in this case.
25696 	*/
25697 	if ((iattr->state != XML_SCHEMAS_ATTR_ASSESSED) &&
25698 	    (iattr->state != XML_SCHEMAS_ATTR_DEFAULT))
25699 	    continue;
25700 	/*
25701 	* VAL TODO: What to do if the type definition is missing?
25702 	*/
25703 	if (iattr->typeDef == NULL) {
25704 	    iattr->state = XML_SCHEMAS_ATTR_ERR_NO_TYPE;
25705 	    continue;
25706 	}
25707 
25708 	ACTIVATE_ATTRIBUTE(iattr);
25709 	fixed = 0;
25710 	xpathRes = 0;
25711 
25712 	if (vctxt->xpathStates != NULL) {
25713 	    /*
25714 	    * Evaluate IDCs.
25715 	    */
25716 	    xpathRes = xmlSchemaXPathEvaluate(vctxt,
25717 		XML_ATTRIBUTE_NODE);
25718 	    if (xpathRes == -1) {
25719 		VERROR_INT("xmlSchemaVAttributesComplex",
25720 		    "calling xmlSchemaXPathEvaluate()");
25721 		goto internal_error;
25722 	    }
25723 	}
25724 
25725 	if (iattr->state == XML_SCHEMAS_ATTR_DEFAULT) {
25726 	    /*
25727 	    * Default/fixed attributes.
25728 	    * We need the value only if we need to resolve IDCs or
25729 	    * will create default attributes.
25730 	    */
25731 	    if ((xpathRes) || (defAttrOwnerElem)) {
25732 		if (iattr->use->defValue != NULL) {
25733 		    iattr->value = (xmlChar *) iattr->use->defValue;
25734 		    iattr->val = iattr->use->defVal;
25735 		} else {
25736 		    iattr->value = (xmlChar *) iattr->decl->defValue;
25737 		    iattr->val = iattr->decl->defVal;
25738 		}
25739 		/*
25740 		* IDCs will consume the precomputed default value,
25741 		* so we need to clone it.
25742 		*/
25743 		if (iattr->val == NULL) {
25744 		    VERROR_INT("xmlSchemaVAttributesComplex",
25745 			"default/fixed value on an attribute use was "
25746 			"not precomputed");
25747 		    goto internal_error;
25748 		}
25749 		iattr->val = xmlSchemaCopyValue(iattr->val);
25750 		if (iattr->val == NULL) {
25751 		    VERROR_INT("xmlSchemaVAttributesComplex",
25752 			"calling xmlSchemaCopyValue()");
25753 		    goto internal_error;
25754 		}
25755 	    }
25756 	    /*
25757 	    * PSVI: Add the default attribute to the current element.
25758 	    * VAL TODO: Should we use the *normalized* value? This currently
25759 	    *   uses the *initial* value.
25760 	    */
25761 
25762 	    if (defAttrOwnerElem) {
25763 		xmlChar *normValue;
25764 		const xmlChar *value;
25765 
25766 		value = iattr->value;
25767 		/*
25768 		* Normalize the value.
25769 		*/
25770 		normValue = xmlSchemaNormalizeValue(iattr->typeDef,
25771 		    iattr->value);
25772 		if (normValue != NULL)
25773 		    value = BAD_CAST normValue;
25774 
25775 		if (iattr->nsName == NULL) {
25776 		    if (xmlNewProp(defAttrOwnerElem,
25777 			iattr->localName, value) == NULL) {
25778 			VERROR_INT("xmlSchemaVAttributesComplex",
25779 			    "calling xmlNewProp()");
25780 			if (normValue != NULL)
25781 			    xmlFree(normValue);
25782 			goto internal_error;
25783 		    }
25784 		} else {
25785 		    xmlNsPtr ns;
25786 
25787 		    ns = xmlSearchNsByHref(defAttrOwnerElem->doc,
25788 			defAttrOwnerElem, iattr->nsName);
25789 		    if (ns == NULL) {
25790 			xmlChar prefix[12];
25791 			int counter = 0;
25792 
25793 			/*
25794 			* Create a namespace declaration on the validation
25795 			* root node if no namespace declaration is in scope.
25796 			*/
25797 			do {
25798 			    snprintf((char *) prefix, 12, "p%d", counter++);
25799 			    ns = xmlSearchNs(defAttrOwnerElem->doc,
25800 				defAttrOwnerElem, BAD_CAST prefix);
25801 			    if (counter > 1000) {
25802 				VERROR_INT(
25803 				    "xmlSchemaVAttributesComplex",
25804 				    "could not compute a ns prefix for a "
25805 				    "default/fixed attribute");
25806 				if (normValue != NULL)
25807 				    xmlFree(normValue);
25808 				goto internal_error;
25809 			    }
25810 			} while (ns != NULL);
25811 			ns = xmlNewNs(vctxt->validationRoot,
25812 			    iattr->nsName, BAD_CAST prefix);
25813 		    }
25814 		    /*
25815 		    * TODO:
25816 		    * http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0406.html
25817 		    * If we have QNames: do we need to ensure there's a
25818 		    * prefix defined for the QName?
25819 		    */
25820 		    xmlNewNsProp(defAttrOwnerElem, ns, iattr->localName, value);
25821 		}
25822 		if (normValue != NULL)
25823 		    xmlFree(normValue);
25824 	    }
25825 	    /*
25826 	    * Go directly to IDC evaluation.
25827 	    */
25828 	    goto eval_idcs;
25829 	}
25830 	/*
25831 	* Validate the value.
25832 	*/
25833 	if (vctxt->value != NULL) {
25834 	    /*
25835 	    * Free last computed value; just for safety reasons.
25836 	    */
25837 	    xmlSchemaFreeValue(vctxt->value);
25838 	    vctxt->value = NULL;
25839 	}
25840 	/*
25841 	* Note that the attribute *use* can be unavailable, if
25842 	* the attribute was a wild attribute.
25843 	*/
25844 	if ((iattr->decl->flags & XML_SCHEMAS_ATTR_FIXED) ||
25845 	    ((iattr->use != NULL) &&
25846 	     (iattr->use->flags & XML_SCHEMAS_ATTR_FIXED)))
25847 	    fixed = 1;
25848 	else
25849 	    fixed = 0;
25850 	/*
25851 	* SPEC (cvc-attribute)
25852 	* (3) "The item's `normalized value` must be locally `valid`
25853 	* with respect to that {type definition} as per
25854 	* String Valid ($3.14.4)."
25855 	*
25856 	* VAL TODO: Do we already have the
25857 	* "normalized attribute value" here?
25858 	*/
25859 	if (xpathRes || fixed) {
25860 	    iattr->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
25861 	    /*
25862 	    * Request a computed value.
25863 	    */
25864 	    res = xmlSchemaVCheckCVCSimpleType(
25865 		ACTXT_CAST vctxt,
25866 		iattr->node, iattr->typeDef, iattr->value, &(iattr->val),
25867 		1, 1, 0);
25868 	} else {
25869 	    res = xmlSchemaVCheckCVCSimpleType(
25870 		ACTXT_CAST vctxt,
25871 		iattr->node, iattr->typeDef, iattr->value, NULL,
25872 		1, 0, 0);
25873 	}
25874 
25875 	if (res != 0) {
25876 	    if (res == -1) {
25877 		VERROR_INT("xmlSchemaVAttributesComplex",
25878 		    "calling xmlSchemaStreamValidateSimpleTypeValue()");
25879 		goto internal_error;
25880 	    }
25881 	    iattr->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
25882 	    /*
25883 	    * SPEC PSVI Assessment Outcome (Attribute)
25884 	    * [validity] = "invalid"
25885 	    */
25886 	    goto eval_idcs;
25887 	}
25888 
25889 	if (fixed) {
25890 	    /*
25891 	    * SPEC Attribute Locally Valid (Use) (cvc-au)
25892 	    * "For an attribute information item to be `valid`
25893 	    * with respect to an attribute use its *normalized*
25894 	    * value must match the *canonical* lexical
25895 	    * representation of the attribute use's {value
25896 	    * constraint}value, if it is present and fixed."
25897 	    *
25898 	    * VAL TODO: The requirement for the *canonical* value
25899 	    * will be removed in XML Schema 1.1.
25900 	    */
25901 	    /*
25902 	    * SPEC Attribute Locally Valid (cvc-attribute)
25903 	    * (4) "The item's *actual* value must match the *value* of
25904 	    * the {value constraint}, if it is present and fixed."
25905 	    */
25906 	    if (iattr->val == NULL) {
25907 		/* VAL TODO: A value was not precomputed. */
25908 		TODO
25909 		goto eval_idcs;
25910 	    }
25911 	    if ((iattr->use != NULL) &&
25912 		(iattr->use->defValue != NULL)) {
25913 		if (iattr->use->defVal == NULL) {
25914 		    /* VAL TODO: A default value was not precomputed. */
25915 		    TODO
25916 		    goto eval_idcs;
25917 		}
25918 		iattr->vcValue = iattr->use->defValue;
25919 		/*
25920 		if (xmlSchemaCompareValuesWhtsp(attr->val,
25921 		    (xmlSchemaWhitespaceValueType) ws,
25922 		    attr->use->defVal,
25923 		    (xmlSchemaWhitespaceValueType) ws) != 0) {
25924 		*/
25925 		if (! xmlSchemaAreValuesEqual(iattr->val, iattr->use->defVal))
25926 		    iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
25927 	    } else {
25928 		if (iattr->decl->defVal == NULL) {
25929 		    /* VAL TODO: A default value was not precomputed. */
25930 		    TODO
25931 		    goto eval_idcs;
25932 		}
25933 		iattr->vcValue = iattr->decl->defValue;
25934 		/*
25935 		if (xmlSchemaCompareValuesWhtsp(attr->val,
25936 		    (xmlSchemaWhitespaceValueType) ws,
25937 		    attrDecl->defVal,
25938 		    (xmlSchemaWhitespaceValueType) ws) != 0) {
25939 		*/
25940 		if (! xmlSchemaAreValuesEqual(iattr->val, iattr->decl->defVal))
25941 		    iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
25942 	    }
25943 	    /*
25944 	    * [validity] = "valid"
25945 	    */
25946 	}
25947 eval_idcs:
25948 	/*
25949 	* Evaluate IDCs.
25950 	*/
25951 	if (xpathRes) {
25952 	    if (xmlSchemaXPathProcessHistory(vctxt,
25953 		vctxt->depth +1) == -1) {
25954 		VERROR_INT("xmlSchemaVAttributesComplex",
25955 		    "calling xmlSchemaXPathEvaluate()");
25956 		goto internal_error;
25957 	    }
25958 	} else if (vctxt->xpathStates != NULL)
25959 	    xmlSchemaXPathPop(vctxt);
25960     }
25961 
25962     /*
25963     * Report errors.
25964     */
25965     for (i = 0; i < vctxt->nbAttrInfos; i++) {
25966 	iattr = vctxt->attrInfos[i];
25967 	if ((iattr->state == XML_SCHEMAS_ATTR_META) ||
25968 	    (iattr->state == XML_SCHEMAS_ATTR_ASSESSED) ||
25969 	    (iattr->state == XML_SCHEMAS_ATTR_WILD_SKIP) ||
25970 	    (iattr->state == XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL))
25971 	    continue;
25972 	ACTIVATE_ATTRIBUTE(iattr);
25973 	switch (iattr->state) {
25974 	    case XML_SCHEMAS_ATTR_ERR_MISSING: {
25975 		    xmlChar *str = NULL;
25976 		    ACTIVATE_ELEM;
25977 		    xmlSchemaCustomErr(ACTXT_CAST vctxt,
25978 			XML_SCHEMAV_CVC_COMPLEX_TYPE_4, NULL, NULL,
25979 			"The attribute '%s' is required but missing",
25980 			xmlSchemaFormatQName(&str,
25981 			    iattr->decl->targetNamespace,
25982 			    iattr->decl->name),
25983 			NULL);
25984 		    FREE_AND_NULL(str)
25985 		    break;
25986 		}
25987 	    case XML_SCHEMAS_ATTR_ERR_NO_TYPE:
25988 		VERROR(XML_SCHEMAV_CVC_ATTRIBUTE_2, NULL,
25989 		    "The type definition is absent");
25990 		break;
25991 	    case XML_SCHEMAS_ATTR_ERR_FIXED_VALUE:
25992 		xmlSchemaCustomErr(ACTXT_CAST vctxt,
25993 		    XML_SCHEMAV_CVC_AU, NULL, NULL,
25994 		    "The value '%s' does not match the fixed "
25995 		    "value constraint '%s'",
25996 		    iattr->value, iattr->vcValue);
25997 		break;
25998 	    case XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL:
25999 		VERROR(XML_SCHEMAV_CVC_WILDCARD, NULL,
26000 		    "No matching global attribute declaration available, but "
26001 		    "demanded by the strict wildcard");
26002 		break;
26003 	    case XML_SCHEMAS_ATTR_UNKNOWN:
26004 		if (iattr->metaType)
26005 		    break;
26006 		/*
26007 		* MAYBE VAL TODO: One might report different error messages
26008 		* for the following errors.
26009 		*/
26010 		if (type->attributeWildcard == NULL) {
26011 		    xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
26012 			XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, iattr, NULL);
26013 		} else {
26014 		    xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
26015 			XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, iattr, NULL);
26016 		}
26017 		break;
26018 	    default:
26019 		break;
26020 	}
26021     }
26022 
26023     ACTIVATE_ELEM;
26024     return (0);
26025 internal_error:
26026     ACTIVATE_ELEM;
26027     return (-1);
26028 }
26029 
26030 static int
xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt,int * skip)26031 xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt,
26032 			      int *skip)
26033 {
26034     xmlSchemaWildcardPtr wild = (xmlSchemaWildcardPtr) vctxt->inode->decl;
26035     /*
26036     * The namespace of the element was already identified to be
26037     * matching the wildcard.
26038     */
26039     if ((skip == NULL) || (wild == NULL) ||
26040 	(wild->type != XML_SCHEMA_TYPE_ANY)) {
26041 	VERROR_INT("xmlSchemaValidateElemWildcard",
26042 	    "bad arguments");
26043 	return (-1);
26044     }
26045     *skip = 0;
26046     if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
26047 	/*
26048 	* URGENT VAL TODO: Either we need to position the stream to the
26049 	* next sibling, or walk the whole subtree.
26050 	*/
26051 	*skip = 1;
26052 	return (0);
26053     }
26054     {
26055 	xmlSchemaElementPtr decl = NULL;
26056 
26057 	decl = xmlSchemaGetElem(vctxt->schema,
26058 	    vctxt->inode->localName, vctxt->inode->nsName);
26059 	if (decl != NULL) {
26060 	    vctxt->inode->decl = decl;
26061 	    return (0);
26062 	}
26063     }
26064     if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
26065 	/* VAL TODO: Change to proper error code. */
26066 	VERROR(XML_SCHEMAV_CVC_ELT_1, NULL, /* WXS_BASIC_CAST wild */
26067 	    "No matching global element declaration available, but "
26068 	    "demanded by the strict wildcard");
26069 	return (vctxt->err);
26070     }
26071     if (vctxt->nbAttrInfos != 0) {
26072 	xmlSchemaAttrInfoPtr iattr;
26073 	/*
26074 	* SPEC Validation Rule: Schema-Validity Assessment (Element)
26075 	* (1.2.1.2.1) - (1.2.1.2.3 )
26076 	*
26077 	* Use the xsi:type attribute for the type definition.
26078 	*/
26079 	iattr = xmlSchemaGetMetaAttrInfo(vctxt,
26080 	    XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
26081 	if (iattr != NULL) {
26082 	    if (xmlSchemaProcessXSIType(vctxt, iattr,
26083 		&(vctxt->inode->typeDef), NULL) == -1) {
26084 		VERROR_INT("xmlSchemaValidateElemWildcard",
26085 		    "calling xmlSchemaProcessXSIType() to "
26086 		    "process the attribute 'xsi:nil'");
26087 		return (-1);
26088 	    }
26089 	    /*
26090 	    * Don't return an error on purpose.
26091 	    */
26092 	    return (0);
26093 	}
26094     }
26095     /*
26096     * SPEC Validation Rule: Schema-Validity Assessment (Element)
26097     *
26098     * Fallback to "anyType".
26099     */
26100     vctxt->inode->typeDef =
26101 	xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
26102     return (0);
26103 }
26104 
26105 /*
26106 * xmlSchemaCheckCOSValidDefault:
26107 *
26108 * This will be called if: not nilled, no content and a default/fixed
26109 * value is provided.
26110 */
26111 
26112 static int
xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt,const xmlChar * value,xmlSchemaValPtr * val)26113 xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt,
26114 			      const xmlChar *value,
26115 			      xmlSchemaValPtr *val)
26116 {
26117     int ret = 0;
26118     xmlSchemaNodeInfoPtr inode = vctxt->inode;
26119 
26120     /*
26121     * cos-valid-default:
26122     * Schema Component Constraint: Element Default Valid (Immediate)
26123     * For a string to be a valid default with respect to a type
26124     * definition the appropriate case among the following must be true:
26125     */
26126     if WXS_IS_COMPLEX(inode->typeDef) {
26127 	/*
26128 	* Complex type.
26129 	*
26130 	* SPEC (2.1) "its {content type} must be a simple type definition
26131 	* or mixed."
26132 	* SPEC (2.2.2) "If the {content type} is mixed, then the {content
26133 	* type}'s particle must be `emptiable` as defined by
26134 	* Particle Emptiable ($3.9.6)."
26135 	*/
26136 	if ((! WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) &&
26137 	    ((! WXS_HAS_MIXED_CONTENT(inode->typeDef)) ||
26138 	     (! WXS_EMPTIABLE(inode->typeDef)))) {
26139 	    ret = XML_SCHEMAP_COS_VALID_DEFAULT_2_1;
26140 	    /* NOTE that this covers (2.2.2) as well. */
26141 	    VERROR(ret, NULL,
26142 		"For a string to be a valid default, the type definition "
26143 		"must be a simple type or a complex type with simple content "
26144 		"or mixed content and a particle emptiable");
26145 	    return(ret);
26146 	}
26147     }
26148     /*
26149     * 1 If the type definition is a simple type definition, then the string
26150     * must be `valid` with respect to that definition as defined by String
26151     * Valid ($3.14.4).
26152     *
26153     * AND
26154     *
26155     * 2.2.1 If the {content type} is a simple type definition, then the
26156     * string must be `valid` with respect to that simple type definition
26157     * as defined by String Valid ($3.14.4).
26158     */
26159     if (WXS_IS_SIMPLE(inode->typeDef)) {
26160 
26161 	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
26162 	    NULL, inode->typeDef, value, val, 1, 1, 0);
26163 
26164     } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26165 
26166 	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
26167 	    NULL, inode->typeDef->contentTypeDef, value, val, 1, 1, 0);
26168     }
26169     if (ret < 0) {
26170 	VERROR_INT("xmlSchemaCheckCOSValidDefault",
26171 	    "calling xmlSchemaVCheckCVCSimpleType()");
26172     }
26173     return (ret);
26174 }
26175 
26176 static void
xmlSchemaVContentModelCallback(xmlRegExecCtxtPtr exec ATTRIBUTE_UNUSED,const xmlChar * name ATTRIBUTE_UNUSED,void * transdata,void * inputdata)26177 xmlSchemaVContentModelCallback(xmlRegExecCtxtPtr exec ATTRIBUTE_UNUSED,
26178 			       const xmlChar * name ATTRIBUTE_UNUSED,
26179 			       void *transdata, void *inputdata)
26180 {
26181     xmlSchemaElementPtr item = (xmlSchemaElementPtr) transdata;
26182     xmlSchemaNodeInfoPtr inode = (xmlSchemaNodeInfoPtr) inputdata;
26183     inode->decl = item;
26184 #ifdef DEBUG_CONTENT
26185     {
26186 	xmlChar *str = NULL;
26187 
26188 	if (item->type == XML_SCHEMA_TYPE_ELEMENT) {
26189 	    xmlGenericError(xmlGenericErrorContext,
26190 		"AUTOMATON callback for '%s' [declaration]\n",
26191 		xmlSchemaFormatQName(&str,
26192 		inode->localName, inode->nsName));
26193 	} else {
26194 	    xmlGenericError(xmlGenericErrorContext,
26195 		    "AUTOMATON callback for '%s' [wildcard]\n",
26196 		    xmlSchemaFormatQName(&str,
26197 		    inode->localName, inode->nsName));
26198 
26199 	}
26200 	FREE_AND_NULL(str)
26201     }
26202 #endif
26203 }
26204 
26205 static int
xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt)26206 xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt)
26207 {
26208     vctxt->inode = xmlSchemaGetFreshElemInfo(vctxt);
26209     if (vctxt->inode == NULL) {
26210 	VERROR_INT("xmlSchemaValidatorPushElem",
26211 	    "calling xmlSchemaGetFreshElemInfo()");
26212 	return (-1);
26213     }
26214     vctxt->nbAttrInfos = 0;
26215     return (0);
26216 }
26217 
26218 static int
xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt,xmlSchemaNodeInfoPtr inode,xmlSchemaTypePtr type,const xmlChar * value)26219 xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt,
26220 			     xmlSchemaNodeInfoPtr inode,
26221 			     xmlSchemaTypePtr type,
26222 			     const xmlChar *value)
26223 {
26224     if (inode->flags & XML_SCHEMA_NODE_INFO_VALUE_NEEDED)
26225 	return (xmlSchemaVCheckCVCSimpleType(
26226 	    ACTXT_CAST vctxt, NULL,
26227 	    type, value, &(inode->val), 1, 1, 0));
26228     else
26229 	return (xmlSchemaVCheckCVCSimpleType(
26230 	    ACTXT_CAST vctxt, NULL,
26231 	    type, value, NULL, 1, 0, 0));
26232 }
26233 
26234 
26235 
26236 /*
26237 * Process END of element.
26238 */
26239 static int
xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)26240 xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)
26241 {
26242     int ret = 0;
26243     xmlSchemaNodeInfoPtr inode = vctxt->inode;
26244 
26245     if (vctxt->nbAttrInfos != 0)
26246 	xmlSchemaClearAttrInfos(vctxt);
26247     if (inode->flags & XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED) {
26248 	/*
26249 	* This element was not expected;
26250 	* we will not validate child elements of broken parents.
26251 	* Skip validation of all content of the parent.
26252 	*/
26253 	vctxt->skipDepth = vctxt->depth -1;
26254 	goto end_elem;
26255     }
26256     if ((inode->typeDef == NULL) ||
26257 	(inode->flags & XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE)) {
26258 	/*
26259 	* 1. the type definition might be missing if the element was
26260 	*    error prone
26261 	* 2. it might be abstract.
26262 	*/
26263 	goto end_elem;
26264     }
26265     /*
26266     * Check the content model.
26267     */
26268     if ((inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) ||
26269 	(inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)) {
26270 
26271 	/*
26272 	* Workaround for "anyType".
26273 	*/
26274 	if (inode->typeDef->builtInType == XML_SCHEMAS_ANYTYPE)
26275 	    goto character_content;
26276 
26277 	if ((inode->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0) {
26278 	    xmlChar *values[10];
26279 	    int terminal, nbval = 10, nbneg;
26280 
26281 	    if (inode->regexCtxt == NULL) {
26282 		/*
26283 		* Create the regex context.
26284 		*/
26285 		inode->regexCtxt =
26286 		    xmlRegNewExecCtxt(inode->typeDef->contModel,
26287 		    xmlSchemaVContentModelCallback, vctxt);
26288 		if (inode->regexCtxt == NULL) {
26289 		    VERROR_INT("xmlSchemaValidatorPopElem",
26290 			"failed to create a regex context");
26291 		    goto internal_error;
26292 		}
26293 #ifdef DEBUG_AUTOMATA
26294 		xmlGenericError(xmlGenericErrorContext,
26295 		    "AUTOMATON create on '%s'\n", inode->localName);
26296 #endif
26297 	    }
26298 
26299 	    /*
26300 	     * Do not check further content if the node has been nilled
26301 	     */
26302 	    if (INODE_NILLED(inode)) {
26303 		ret = 0;
26304 #ifdef DEBUG_AUTOMATA
26305 		xmlGenericError(xmlGenericErrorContext,
26306 		    "AUTOMATON succeeded on nilled '%s'\n",
26307 		    inode->localName);
26308 #endif
26309                 goto skip_nilled;
26310 	    }
26311 
26312 	    /*
26313 	    * Get hold of the still expected content, since a further
26314 	    * call to xmlRegExecPushString() will lose this information.
26315 	    */
26316 	    xmlRegExecNextValues(inode->regexCtxt,
26317 		&nbval, &nbneg, &values[0], &terminal);
26318 	    ret = xmlRegExecPushString(inode->regexCtxt, NULL, NULL);
26319 	    if ((ret<0) || ((ret==0) && (!INODE_NILLED(inode)))) {
26320 		/*
26321 		* Still missing something.
26322 		*/
26323 		ret = 1;
26324 		inode->flags |=
26325 		    XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
26326 		xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
26327 		    XML_SCHEMAV_ELEMENT_CONTENT, NULL, NULL,
26328 		    "Missing child element(s)",
26329 		    nbval, nbneg, values);
26330 #ifdef DEBUG_AUTOMATA
26331 		xmlGenericError(xmlGenericErrorContext,
26332 		    "AUTOMATON missing ERROR on '%s'\n",
26333 		    inode->localName);
26334 #endif
26335 	    } else {
26336 		/*
26337 		* Content model is satisfied.
26338 		*/
26339 		ret = 0;
26340 #ifdef DEBUG_AUTOMATA
26341 		xmlGenericError(xmlGenericErrorContext,
26342 		    "AUTOMATON succeeded on '%s'\n",
26343 		    inode->localName);
26344 #endif
26345 	    }
26346 
26347 	}
26348     }
26349 
26350 skip_nilled:
26351 
26352     if (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)
26353 	goto end_elem;
26354 
26355 character_content:
26356 
26357     if (vctxt->value != NULL) {
26358 	xmlSchemaFreeValue(vctxt->value);
26359 	vctxt->value = NULL;
26360     }
26361     /*
26362     * Check character content.
26363     */
26364     if (inode->decl == NULL) {
26365 	/*
26366 	* Speedup if no declaration exists.
26367 	*/
26368 	if (WXS_IS_SIMPLE(inode->typeDef)) {
26369 	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26370 		inode, inode->typeDef, inode->value);
26371 	} else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26372 	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26373 		inode, inode->typeDef->contentTypeDef,
26374 		inode->value);
26375 	}
26376 	if (ret < 0) {
26377 	    VERROR_INT("xmlSchemaValidatorPopElem",
26378 		"calling xmlSchemaVCheckCVCSimpleType()");
26379 	    goto internal_error;
26380 	}
26381 	goto end_elem;
26382     }
26383     /*
26384     * cvc-elt (3.3.4) : 5
26385     * The appropriate case among the following must be true:
26386     */
26387     /*
26388     * cvc-elt (3.3.4) : 5.1
26389     * If the declaration has a {value constraint},
26390     * the item has neither element nor character [children] and
26391     * clause 3.2 has not applied, then all of the following must be true:
26392     */
26393     if ((inode->decl->value != NULL) &&
26394 	(inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) &&
26395 	(! INODE_NILLED(inode))) {
26396 	/*
26397 	* cvc-elt (3.3.4) : 5.1.1
26398 	* If the `actual type definition` is a `local type definition`
26399 	* then the canonical lexical representation of the {value constraint}
26400 	* value must be a valid default for the `actual type definition` as
26401 	* defined in Element Default Valid (Immediate) ($3.3.6).
26402 	*/
26403 	/*
26404 	* NOTE: 'local' above means types acquired by xsi:type.
26405 	* NOTE: Although the *canonical* value is stated, it is not
26406 	* relevant if canonical or not. Additionally XML Schema 1.1
26407 	* will removed this requirement as well.
26408 	*/
26409 	if (inode->flags & XML_SCHEMA_ELEM_INFO_LOCAL_TYPE) {
26410 
26411 	    ret = xmlSchemaCheckCOSValidDefault(vctxt,
26412 		inode->decl->value, &(inode->val));
26413 	    if (ret != 0) {
26414 		if (ret < 0) {
26415 		    VERROR_INT("xmlSchemaValidatorPopElem",
26416 			"calling xmlSchemaCheckCOSValidDefault()");
26417 		    goto internal_error;
26418 		}
26419 		goto end_elem;
26420 	    }
26421 	    /*
26422 	    * Stop here, to avoid redundant validation of the value
26423 	    * (see following).
26424 	    */
26425 	    goto default_psvi;
26426 	}
26427 	/*
26428 	* cvc-elt (3.3.4) : 5.1.2
26429 	* The element information item with the canonical lexical
26430 	* representation of the {value constraint} value used as its
26431 	* `normalized value` must be `valid` with respect to the
26432 	* `actual type definition` as defined by Element Locally Valid (Type)
26433 	* ($3.3.4).
26434 	*/
26435 	if (WXS_IS_SIMPLE(inode->typeDef)) {
26436 	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26437 		inode, inode->typeDef, inode->decl->value);
26438 	} else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26439 	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26440 		inode, inode->typeDef->contentTypeDef,
26441 		inode->decl->value);
26442 	}
26443 	if (ret != 0) {
26444 	    if (ret < 0) {
26445 		VERROR_INT("xmlSchemaValidatorPopElem",
26446 		    "calling xmlSchemaVCheckCVCSimpleType()");
26447 		goto internal_error;
26448 	    }
26449 	    goto end_elem;
26450 	}
26451 
26452 default_psvi:
26453 	/*
26454 	* PSVI: Create a text node on the instance element.
26455 	*/
26456 	if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
26457 	    (inode->node != NULL)) {
26458 	    xmlNodePtr textChild;
26459 	    xmlChar *normValue;
26460 	    /*
26461 	    * VAL TODO: Normalize the value.
26462 	    */
26463 	    normValue = xmlSchemaNormalizeValue(inode->typeDef,
26464 		inode->decl->value);
26465 	    if (normValue != NULL) {
26466 		textChild = xmlNewText(BAD_CAST normValue);
26467 		xmlFree(normValue);
26468 	    } else
26469 		textChild = xmlNewText(inode->decl->value);
26470 	    if (textChild == NULL) {
26471 		VERROR_INT("xmlSchemaValidatorPopElem",
26472 		    "calling xmlNewText()");
26473 		goto internal_error;
26474 	    } else
26475 		xmlAddChild(inode->node, textChild);
26476 	}
26477 
26478     } else if (! INODE_NILLED(inode)) {
26479 	/*
26480 	* 5.2.1 The element information item must be `valid` with respect
26481 	* to the `actual type definition` as defined by Element Locally
26482 	* Valid (Type) ($3.3.4).
26483 	*/
26484 	if (WXS_IS_SIMPLE(inode->typeDef)) {
26485 	     /*
26486 	    * SPEC (cvc-type) (3.1)
26487 	    * "If the type definition is a simple type definition, ..."
26488 	    * (3.1.3) "If clause 3.2 of Element Locally Valid
26489 	    * (Element) ($3.3.4) did not apply, then the `normalized value`
26490 	    * must be `valid` with respect to the type definition as defined
26491 	    * by String Valid ($3.14.4).
26492 	    */
26493 	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26494 		    inode, inode->typeDef, inode->value);
26495 	} else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26496 	    /*
26497 	    * SPEC (cvc-type) (3.2) "If the type definition is a complex type
26498 	    * definition, then the element information item must be
26499 	    * `valid` with respect to the type definition as per
26500 	    * Element Locally Valid (Complex Type) ($3.4.4);"
26501 	    *
26502 	    * SPEC (cvc-complex-type) (2.2)
26503 	    * "If the {content type} is a simple type definition, ...
26504 	    * the `normalized value` of the element information item is
26505 	    * `valid` with respect to that simple type definition as
26506 	    * defined by String Valid ($3.14.4)."
26507 	    */
26508 	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26509 		inode, inode->typeDef->contentTypeDef, inode->value);
26510 	}
26511 	if (ret != 0) {
26512 	    if (ret < 0) {
26513 		VERROR_INT("xmlSchemaValidatorPopElem",
26514 		    "calling xmlSchemaVCheckCVCSimpleType()");
26515 		goto internal_error;
26516 	    }
26517 	    goto end_elem;
26518 	}
26519 	/*
26520 	* 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
26521 	* not applied, all of the following must be true:
26522 	*/
26523 	if ((inode->decl->value != NULL) &&
26524 	    (inode->decl->flags & XML_SCHEMAS_ELEM_FIXED)) {
26525 
26526 	    /*
26527 	    * TODO: We will need a computed value, when comparison is
26528 	    * done on computed values.
26529 	    */
26530 	    /*
26531 	    * 5.2.2.1 The element information item must have no element
26532 	    * information item [children].
26533 	    */
26534 	    if (inode->flags &
26535 		    XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT) {
26536 		ret = XML_SCHEMAV_CVC_ELT_5_2_2_1;
26537 		VERROR(ret, NULL,
26538 		    "The content must not contain element nodes since "
26539 		    "there is a fixed value constraint");
26540 		goto end_elem;
26541 	    } else {
26542 		/*
26543 		* 5.2.2.2 The appropriate case among the following must
26544 		* be true:
26545 		*/
26546 		if (WXS_HAS_MIXED_CONTENT(inode->typeDef)) {
26547 		    /*
26548 		    * 5.2.2.2.1 If the {content type} of the `actual type
26549 		    * definition` is mixed, then the *initial value* of the
26550 		    * item must match the canonical lexical representation
26551 		    * of the {value constraint} value.
26552 		    *
26553 		    * ... the *initial value* of an element information
26554 		    * item is the string composed of, in order, the
26555 		    * [character code] of each character information item in
26556 		    * the [children] of that element information item.
26557 		    */
26558 		    if (! xmlStrEqual(inode->value, inode->decl->value)){
26559 			/*
26560 			* VAL TODO: Report invalid & expected values as well.
26561 			* VAL TODO: Implement the canonical stuff.
26562 			*/
26563 			ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_1;
26564 			xmlSchemaCustomErr(ACTXT_CAST vctxt,
26565 			    ret, NULL, NULL,
26566 			    "The initial value '%s' does not match the fixed "
26567 			    "value constraint '%s'",
26568 			    inode->value, inode->decl->value);
26569 			goto end_elem;
26570 		    }
26571 		} else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26572 		    /*
26573 		    * 5.2.2.2.2 If the {content type} of the `actual type
26574 		    * definition` is a simple type definition, then the
26575 		    * *actual value* of the item must match the canonical
26576 		    * lexical representation of the {value constraint} value.
26577 		    */
26578 		    /*
26579 		    * VAL TODO: *actual value* is the normalized value, impl.
26580 		    *           this.
26581 		    * VAL TODO: Report invalid & expected values as well.
26582 		    * VAL TODO: Implement a comparison with the computed values.
26583 		    */
26584 		    if (! xmlStrEqual(inode->value,
26585 			    inode->decl->value)) {
26586 			ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_2;
26587 			xmlSchemaCustomErr(ACTXT_CAST vctxt,
26588 			    ret, NULL, NULL,
26589 			    "The actual value '%s' does not match the fixed "
26590 			    "value constraint '%s'",
26591 			    inode->value,
26592 			    inode->decl->value);
26593 			goto end_elem;
26594 		    }
26595 		}
26596 	    }
26597 	}
26598     }
26599 
26600 end_elem:
26601     if (vctxt->depth < 0) {
26602 	/* TODO: raise error? */
26603 	return (0);
26604     }
26605     if (vctxt->depth == vctxt->skipDepth)
26606 	vctxt->skipDepth = -1;
26607     /*
26608     * Evaluate the history of XPath state objects.
26609     */
26610     if (inode->appliedXPath &&
26611 	(xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1))
26612 	goto internal_error;
26613     /*
26614     * MAYBE TODO:
26615     * SPEC (6) "The element information item must be `valid` with
26616     * respect to each of the {identity-constraint definitions} as per
26617     * Identity-constraint Satisfied ($3.11.4)."
26618     */
26619     /*
26620     * PSVI TODO: If we expose IDC node-tables via PSVI then the tables
26621     *   need to be built in any case.
26622     *   We will currently build IDC node-tables and bubble them only if
26623     *   keyrefs do exist.
26624     */
26625 
26626     /*
26627     * Add the current IDC target-nodes to the IDC node-tables.
26628     */
26629     if ((inode->idcMatchers != NULL) &&
26630 	(vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
26631     {
26632 	if (xmlSchemaIDCFillNodeTables(vctxt, inode) == -1)
26633 	    goto internal_error;
26634     }
26635     /*
26636     * Validate IDC keyrefs.
26637     */
26638     if (vctxt->inode->hasKeyrefs)
26639 	if (xmlSchemaCheckCVCIDCKeyRef(vctxt) == -1)
26640 	    goto internal_error;
26641     /*
26642     * Merge/free the IDC table.
26643     */
26644     if (inode->idcTable != NULL) {
26645 #ifdef DEBUG_IDC_NODE_TABLE
26646 	xmlSchemaDebugDumpIDCTable(stdout,
26647 	    inode->nsName,
26648 	    inode->localName,
26649 	    inode->idcTable);
26650 #endif
26651 	if ((vctxt->depth > 0) &&
26652 	    (vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
26653 	{
26654 	    /*
26655 	    * Merge the IDC node table with the table of the parent node.
26656 	    */
26657 	    if (xmlSchemaBubbleIDCNodeTables(vctxt) == -1)
26658 		goto internal_error;
26659 	}
26660     }
26661     /*
26662     * Clear the current ielem.
26663     * VAL TODO: Don't free the PSVI IDC tables if they are
26664     * requested for the PSVI.
26665     */
26666     xmlSchemaClearElemInfo(vctxt, inode);
26667     /*
26668     * Skip further processing if we are on the validation root.
26669     */
26670     if (vctxt->depth == 0) {
26671 	vctxt->depth--;
26672 	vctxt->inode = NULL;
26673 	return (0);
26674     }
26675     /*
26676     * Reset the keyrefDepth if needed.
26677     */
26678     if (vctxt->aidcs != NULL) {
26679 	xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
26680 	do {
26681 	    if (aidc->keyrefDepth == vctxt->depth) {
26682 		/*
26683 		* A 'keyrefDepth' of a key/unique IDC matches the current
26684 		* depth, this means that we are leaving the scope of the
26685 		* top-most keyref IDC which refers to this IDC.
26686 		*/
26687 		aidc->keyrefDepth = -1;
26688 	    }
26689 	    aidc = aidc->next;
26690 	} while (aidc != NULL);
26691     }
26692     vctxt->depth--;
26693     vctxt->inode = vctxt->elemInfos[vctxt->depth];
26694     /*
26695     * VAL TODO: 7 If the element information item is the `validation root`, it must be
26696     * `valid` per Validation Root Valid (ID/IDREF) ($3.3.4).
26697     */
26698     return (ret);
26699 
26700 internal_error:
26701     vctxt->err = -1;
26702     return (-1);
26703 }
26704 
26705 /*
26706 * 3.4.4 Complex Type Definition Validation Rules
26707 * Validation Rule: Element Locally Valid (Complex Type) (cvc-complex-type)
26708 */
26709 static int
xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)26710 xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)
26711 {
26712     xmlSchemaNodeInfoPtr pielem;
26713     xmlSchemaTypePtr ptype;
26714     int ret = 0;
26715 
26716     if (vctxt->depth <= 0) {
26717 	VERROR_INT("xmlSchemaValidateChildElem",
26718 	    "not intended for the validation root");
26719 	return (-1);
26720     }
26721     pielem = vctxt->elemInfos[vctxt->depth -1];
26722     if (pielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26723 	pielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
26724     /*
26725     * Handle 'nilled' elements.
26726     */
26727     if (INODE_NILLED(pielem)) {
26728 	/*
26729 	* SPEC (cvc-elt) (3.3.4) : (3.2.1)
26730 	*/
26731 	ACTIVATE_PARENT_ELEM;
26732 	ret = XML_SCHEMAV_CVC_ELT_3_2_1;
26733 	VERROR(ret, NULL,
26734 	    "Neither character nor element content is allowed, "
26735 	    "because the element was 'nilled'");
26736 	ACTIVATE_ELEM;
26737 	goto unexpected_elem;
26738     }
26739 
26740     ptype = pielem->typeDef;
26741 
26742     if (ptype->builtInType == XML_SCHEMAS_ANYTYPE) {
26743 	/*
26744 	* Workaround for "anyType": we have currently no content model
26745 	* assigned for "anyType", so handle it explicitly.
26746 	* "anyType" has an unbounded, lax "any" wildcard.
26747 	*/
26748 	vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26749 	    vctxt->inode->localName,
26750 	    vctxt->inode->nsName);
26751 
26752 	if (vctxt->inode->decl == NULL) {
26753 	    xmlSchemaAttrInfoPtr iattr;
26754 	    /*
26755 	    * Process "xsi:type".
26756 	    * SPEC (cvc-assess-elt) (1.2.1.2.1) - (1.2.1.2.3)
26757 	    */
26758 	    iattr = xmlSchemaGetMetaAttrInfo(vctxt,
26759 		XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
26760 	    if (iattr != NULL) {
26761 		ret = xmlSchemaProcessXSIType(vctxt, iattr,
26762 		    &(vctxt->inode->typeDef), NULL);
26763 		if (ret != 0) {
26764 		    if (ret == -1) {
26765 			VERROR_INT("xmlSchemaValidateChildElem",
26766 			    "calling xmlSchemaProcessXSIType() to "
26767 			    "process the attribute 'xsi:nil'");
26768 			return (-1);
26769 		    }
26770 		    return (ret);
26771 		}
26772 	    } else {
26773 		 /*
26774 		 * Fallback to "anyType".
26775 		 *
26776 		 * SPEC (cvc-assess-elt)
26777 		 * "If the item cannot be `strictly assessed`, [...]
26778 		 * an element information item's schema validity may be laxly
26779 		 * assessed if its `context-determined declaration` is not
26780 		 * skip by `validating` with respect to the `ur-type
26781 		 * definition` as per Element Locally Valid (Type) ($3.3.4)."
26782 		*/
26783 		vctxt->inode->typeDef =
26784 		    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
26785 	    }
26786 	}
26787 	return (0);
26788     }
26789 
26790     switch (ptype->contentType) {
26791 	case XML_SCHEMA_CONTENT_EMPTY:
26792 	    /*
26793 	    * SPEC (2.1) "If the {content type} is empty, then the
26794 	    * element information item has no character or element
26795 	    * information item [children]."
26796 	    */
26797 	    ACTIVATE_PARENT_ELEM
26798 	    ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1;
26799 	    VERROR(ret, NULL,
26800 		"Element content is not allowed, "
26801 		"because the content type is empty");
26802 	    ACTIVATE_ELEM
26803 	    goto unexpected_elem;
26804 	    break;
26805 
26806 	case XML_SCHEMA_CONTENT_MIXED:
26807         case XML_SCHEMA_CONTENT_ELEMENTS: {
26808 	    xmlRegExecCtxtPtr regexCtxt;
26809 	    xmlChar *values[10];
26810 	    int terminal, nbval = 10, nbneg;
26811 
26812 	    /* VAL TODO: Optimized "anyType" validation.*/
26813 
26814 	    if (ptype->contModel == NULL) {
26815 		VERROR_INT("xmlSchemaValidateChildElem",
26816 		    "type has elem content but no content model");
26817 		return (-1);
26818 	    }
26819 	    /*
26820 	    * Safety belt for evaluation if the cont. model was already
26821 	    * examined to be invalid.
26822 	    */
26823 	    if (pielem->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) {
26824 		VERROR_INT("xmlSchemaValidateChildElem",
26825 		    "validating elem, but elem content is already invalid");
26826 		return (-1);
26827 	    }
26828 
26829 	    regexCtxt = pielem->regexCtxt;
26830 	    if (regexCtxt == NULL) {
26831 		/*
26832 		* Create the regex context.
26833 		*/
26834 		regexCtxt = xmlRegNewExecCtxt(ptype->contModel,
26835 		    xmlSchemaVContentModelCallback, vctxt);
26836 		if (regexCtxt == NULL) {
26837 		    VERROR_INT("xmlSchemaValidateChildElem",
26838 			"failed to create a regex context");
26839 		    return (-1);
26840 		}
26841 		pielem->regexCtxt = regexCtxt;
26842 #ifdef DEBUG_AUTOMATA
26843 		xmlGenericError(xmlGenericErrorContext, "AUTOMATA create on '%s'\n",
26844 		    pielem->localName);
26845 #endif
26846 	    }
26847 
26848 	    /*
26849 	    * SPEC (2.4) "If the {content type} is element-only or mixed,
26850 	    * then the sequence of the element information item's
26851 	    * element information item [children], if any, taken in
26852 	    * order, is `valid` with respect to the {content type}'s
26853 	    * particle, as defined in Element Sequence Locally Valid
26854 	    * (Particle) ($3.9.4)."
26855 	    */
26856 	    ret = xmlRegExecPushString2(regexCtxt,
26857 		vctxt->inode->localName,
26858 		vctxt->inode->nsName,
26859 		vctxt->inode);
26860 #ifdef DEBUG_AUTOMATA
26861 	    if (ret < 0)
26862 		xmlGenericError(xmlGenericErrorContext,
26863 		"AUTOMATON push ERROR for '%s' on '%s'\n",
26864 		vctxt->inode->localName, pielem->localName);
26865 	    else
26866 		xmlGenericError(xmlGenericErrorContext,
26867 		"AUTOMATON push OK for '%s' on '%s'\n",
26868 		vctxt->inode->localName, pielem->localName);
26869 #endif
26870 	    if (vctxt->err == XML_SCHEMAV_INTERNAL) {
26871 		VERROR_INT("xmlSchemaValidateChildElem",
26872 		    "calling xmlRegExecPushString2()");
26873 		return (-1);
26874 	    }
26875 	    if (ret < 0) {
26876 		xmlRegExecErrInfo(regexCtxt, NULL, &nbval, &nbneg,
26877 		    &values[0], &terminal);
26878 		xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
26879 		    XML_SCHEMAV_ELEMENT_CONTENT, NULL,NULL,
26880 		    "This element is not expected",
26881 		    nbval, nbneg, values);
26882 		ret = vctxt->err;
26883 		goto unexpected_elem;
26884 	    } else
26885 		ret = 0;
26886 	}
26887 	    break;
26888 	case XML_SCHEMA_CONTENT_SIMPLE:
26889 	case XML_SCHEMA_CONTENT_BASIC:
26890 	    ACTIVATE_PARENT_ELEM
26891 	    if (WXS_IS_COMPLEX(ptype)) {
26892 		/*
26893 		* SPEC (cvc-complex-type) (2.2)
26894 		* "If the {content type} is a simple type definition, then
26895 		* the element information item has no element information
26896 		* item [children], ..."
26897 		*/
26898 		ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
26899 		VERROR(ret, NULL, "Element content is not allowed, "
26900 		    "because the content type is a simple type definition");
26901 	    } else {
26902 		/*
26903 		* SPEC (cvc-type) (3.1.2) "The element information item must
26904 		* have no element information item [children]."
26905 		*/
26906 		ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
26907 		VERROR(ret, NULL, "Element content is not allowed, "
26908 		    "because the type definition is simple");
26909 	    }
26910 	    ACTIVATE_ELEM
26911 	    ret = vctxt->err;
26912 	    goto unexpected_elem;
26913 	    break;
26914 
26915 	default:
26916 	    break;
26917     }
26918     return (ret);
26919 unexpected_elem:
26920     /*
26921     * Pop this element and set the skipDepth to skip
26922     * all further content of the parent element.
26923     */
26924     vctxt->skipDepth = vctxt->depth;
26925     vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
26926     pielem->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
26927     return (ret);
26928 }
26929 
26930 #define XML_SCHEMA_PUSH_TEXT_PERSIST 1
26931 #define XML_SCHEMA_PUSH_TEXT_CREATED 2
26932 #define XML_SCHEMA_PUSH_TEXT_VOLATILE 3
26933 
26934 static int
xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,int nodeType,const xmlChar * value,int len,int mode,int * consumed)26935 xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,
26936 		  int nodeType, const xmlChar *value, int len,
26937 		  int mode, int *consumed)
26938 {
26939     /*
26940     * Unfortunately we have to duplicate the text sometimes.
26941     * OPTIMIZE: Maybe we could skip it, if:
26942     *   1. content type is simple
26943     *   2. whitespace is "collapse"
26944     *   3. it consists of whitespace only
26945     *
26946     * Process character content.
26947     */
26948     if (consumed != NULL)
26949 	*consumed = 0;
26950     if (INODE_NILLED(vctxt->inode)) {
26951 	/*
26952 	* SPEC cvc-elt (3.3.4 - 3.2.1)
26953 	* "The element information item must have no character or
26954 	* element information item [children]."
26955 	*/
26956 	VERROR(XML_SCHEMAV_CVC_ELT_3_2_1, NULL,
26957 	    "Neither character nor element content is allowed "
26958 	    "because the element is 'nilled'");
26959 	return (vctxt->err);
26960     }
26961     /*
26962     * SPEC (2.1) "If the {content type} is empty, then the
26963     * element information item has no character or element
26964     * information item [children]."
26965     */
26966     if (vctxt->inode->typeDef->contentType ==
26967 	    XML_SCHEMA_CONTENT_EMPTY) {
26968 	VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1, NULL,
26969 	    "Character content is not allowed, "
26970 	    "because the content type is empty");
26971 	return (vctxt->err);
26972     }
26973 
26974     if (vctxt->inode->typeDef->contentType ==
26975 	    XML_SCHEMA_CONTENT_ELEMENTS) {
26976 	if ((nodeType != XML_TEXT_NODE) ||
26977 	    (! xmlSchemaIsBlank((xmlChar *) value, len))) {
26978 	    /*
26979 	    * SPEC cvc-complex-type (2.3)
26980 	    * "If the {content type} is element-only, then the
26981 	    * element information item has no character information
26982 	    * item [children] other than those whose [character
26983 	    * code] is defined as a white space in [XML 1.0 (Second
26984 	    * Edition)]."
26985 	    */
26986 	    VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3, NULL,
26987 		"Character content other than whitespace is not allowed "
26988 		"because the content type is 'element-only'");
26989 	    return (vctxt->err);
26990 	}
26991 	return (0);
26992     }
26993 
26994     if ((value == NULL) || (value[0] == 0))
26995 	return (0);
26996     /*
26997     * Save the value.
26998     * NOTE that even if the content type is *mixed*, we need the
26999     * *initial value* for default/fixed value constraints.
27000     */
27001     if ((vctxt->inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) &&
27002 	((vctxt->inode->decl == NULL) ||
27003 	(vctxt->inode->decl->value == NULL)))
27004 	return (0);
27005 
27006     if (vctxt->inode->value == NULL) {
27007 	/*
27008 	* Set the value.
27009 	*/
27010 	switch (mode) {
27011 	    case XML_SCHEMA_PUSH_TEXT_PERSIST:
27012 		/*
27013 		* When working on a tree.
27014 		*/
27015 		vctxt->inode->value = value;
27016 		break;
27017 	    case XML_SCHEMA_PUSH_TEXT_CREATED:
27018 		/*
27019 		* When working with the reader.
27020 		* The value will be freed by the element info.
27021 		*/
27022 		vctxt->inode->value = value;
27023 		if (consumed != NULL)
27024 		    *consumed = 1;
27025 		vctxt->inode->flags |=
27026 		    XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
27027 		break;
27028 	    case XML_SCHEMA_PUSH_TEXT_VOLATILE:
27029 		/*
27030 		* When working with SAX.
27031 		* The value will be freed by the element info.
27032 		*/
27033 		if (len != -1)
27034 		    vctxt->inode->value = BAD_CAST xmlStrndup(value, len);
27035 		else
27036 		    vctxt->inode->value = BAD_CAST xmlStrdup(value);
27037 		vctxt->inode->flags |=
27038 		    XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
27039 		break;
27040 	    default:
27041 		break;
27042 	}
27043     } else {
27044 	if (len < 0)
27045 	    len = xmlStrlen(value);
27046 	/*
27047 	* Concat the value.
27048 	*/
27049 	if (vctxt->inode->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
27050 	    vctxt->inode->value = BAD_CAST xmlStrncat(
27051 		(xmlChar *) vctxt->inode->value, value, len);
27052 	} else {
27053 	    vctxt->inode->value =
27054 		BAD_CAST xmlStrncatNew(vctxt->inode->value, value, len);
27055 	    vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
27056 	}
27057     }
27058 
27059     return (0);
27060 }
27061 
27062 static int
xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt)27063 xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt)
27064 {
27065     int ret = 0;
27066 
27067     if ((vctxt->skipDepth != -1) &&
27068 	(vctxt->depth >= vctxt->skipDepth)) {
27069 	VERROR_INT("xmlSchemaValidateElem",
27070 	    "in skip-state");
27071 	goto internal_error;
27072     }
27073     if (vctxt->xsiAssemble) {
27074 	/*
27075 	* We will stop validation if there was an error during
27076 	* dynamic schema construction.
27077 	* Note that we simply set @skipDepth to 0, this could
27078 	* mean that a streaming document via SAX would be
27079 	* still read to the end but it won't be validated any more.
27080 	* TODO: If we are sure how to stop the validation at once
27081 	*   for all input scenarios, then this should be changed to
27082 	*   instantly stop the validation.
27083 	*/
27084 	ret = xmlSchemaAssembleByXSI(vctxt);
27085 	if (ret != 0) {
27086 	    if (ret == -1)
27087 		goto internal_error;
27088 	    vctxt->skipDepth = 0;
27089 	    return(ret);
27090 	}
27091         /*
27092          * Augment the IDC definitions for the main schema and all imported ones
27093          * NOTE: main schema is the first in the imported list
27094          */
27095         xmlHashScan(vctxt->schema->schemasImports, xmlSchemaAugmentImportedIDC,
27096                     vctxt);
27097     }
27098     if (vctxt->depth > 0) {
27099 	/*
27100 	* Validate this element against the content model
27101 	* of the parent.
27102 	*/
27103 	ret = xmlSchemaValidateChildElem(vctxt);
27104 	if (ret != 0) {
27105 	    if (ret < 0) {
27106 		VERROR_INT("xmlSchemaValidateElem",
27107 		    "calling xmlSchemaStreamValidateChildElement()");
27108 		goto internal_error;
27109 	    }
27110 	    goto exit;
27111 	}
27112 	if (vctxt->depth == vctxt->skipDepth)
27113 	    goto exit;
27114 	if ((vctxt->inode->decl == NULL) &&
27115 	    (vctxt->inode->typeDef == NULL)) {
27116 	    VERROR_INT("xmlSchemaValidateElem",
27117 		"the child element was valid but neither the "
27118 		"declaration nor the type was set");
27119 	    goto internal_error;
27120 	}
27121     } else {
27122 	/*
27123 	* Get the declaration of the validation root.
27124 	*/
27125 	vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
27126 	    vctxt->inode->localName,
27127 	    vctxt->inode->nsName);
27128 	if (vctxt->inode->decl == NULL) {
27129 	    ret = XML_SCHEMAV_CVC_ELT_1;
27130 	    VERROR(ret, NULL,
27131 		"No matching global declaration available "
27132 		"for the validation root");
27133 	    goto exit;
27134 	}
27135     }
27136 
27137     if (vctxt->inode->decl == NULL)
27138 	goto type_validation;
27139 
27140     if (vctxt->inode->decl->type == XML_SCHEMA_TYPE_ANY) {
27141 	int skip;
27142 	/*
27143 	* Wildcards.
27144 	*/
27145 	ret = xmlSchemaValidateElemWildcard(vctxt, &skip);
27146 	if (ret != 0) {
27147 	    if (ret < 0) {
27148 		VERROR_INT("xmlSchemaValidateElem",
27149 		    "calling xmlSchemaValidateElemWildcard()");
27150 		goto internal_error;
27151 	    }
27152 	    goto exit;
27153 	}
27154 	if (skip) {
27155 	    vctxt->skipDepth = vctxt->depth;
27156 	    goto exit;
27157 	}
27158 	/*
27159 	* The declaration might be set by the wildcard validation,
27160 	* when the processContents is "lax" or "strict".
27161 	*/
27162 	if (vctxt->inode->decl->type != XML_SCHEMA_TYPE_ELEMENT) {
27163 	    /*
27164 	    * Clear the "decl" field to not confuse further processing.
27165 	    */
27166 	    vctxt->inode->decl = NULL;
27167 	    goto type_validation;
27168 	}
27169     }
27170     /*
27171     * Validate against the declaration.
27172     */
27173     ret = xmlSchemaValidateElemDecl(vctxt);
27174     if (ret != 0) {
27175 	if (ret < 0) {
27176 	    VERROR_INT("xmlSchemaValidateElem",
27177 		"calling xmlSchemaValidateElemDecl()");
27178 	    goto internal_error;
27179 	}
27180 	goto exit;
27181     }
27182     /*
27183     * Validate against the type definition.
27184     */
27185 type_validation:
27186 
27187     if (vctxt->inode->typeDef == NULL) {
27188 	vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
27189 	ret = XML_SCHEMAV_CVC_TYPE_1;
27190 	VERROR(ret, NULL,
27191 	    "The type definition is absent");
27192 	goto exit;
27193     }
27194     if (vctxt->inode->typeDef->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
27195 	vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
27196 	ret = XML_SCHEMAV_CVC_TYPE_2;
27197 	    VERROR(ret, NULL,
27198 	    "The type definition is abstract");
27199 	goto exit;
27200     }
27201     /*
27202     * Evaluate IDCs. Do it here, since new IDC matchers are registered
27203     * during validation against the declaration. This must be done
27204     * _before_ attribute validation.
27205     */
27206     if (vctxt->xpathStates != NULL) {
27207 	ret = xmlSchemaXPathEvaluate(vctxt, XML_ELEMENT_NODE);
27208 	vctxt->inode->appliedXPath = 1;
27209 	if (ret == -1) {
27210 	    VERROR_INT("xmlSchemaValidateElem",
27211 		"calling xmlSchemaXPathEvaluate()");
27212 	    goto internal_error;
27213 	}
27214     }
27215     /*
27216     * Validate attributes.
27217     */
27218     if (WXS_IS_COMPLEX(vctxt->inode->typeDef)) {
27219 	if ((vctxt->nbAttrInfos != 0) ||
27220 	    (vctxt->inode->typeDef->attrUses != NULL)) {
27221 
27222 	    ret = xmlSchemaVAttributesComplex(vctxt);
27223 	}
27224     } else if (vctxt->nbAttrInfos != 0) {
27225 
27226 	ret = xmlSchemaVAttributesSimple(vctxt);
27227     }
27228     /*
27229     * Clear registered attributes.
27230     */
27231     if (vctxt->nbAttrInfos != 0)
27232 	xmlSchemaClearAttrInfos(vctxt);
27233     if (ret == -1) {
27234 	VERROR_INT("xmlSchemaValidateElem",
27235 	    "calling attributes validation");
27236 	goto internal_error;
27237     }
27238     /*
27239     * Don't return an error if attributes are invalid on purpose.
27240     */
27241     ret = 0;
27242 
27243 exit:
27244     if (ret != 0)
27245 	vctxt->skipDepth = vctxt->depth;
27246     return (ret);
27247 internal_error:
27248     return (-1);
27249 }
27250 
27251 #ifdef XML_SCHEMA_READER_ENABLED
27252 static int
xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt)27253 xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt)
27254 {
27255     const int WHTSP = 13, SIGN_WHTSP = 14, END_ELEM = 15;
27256     int depth, nodeType, ret = 0, consumed;
27257     xmlSchemaNodeInfoPtr ielem;
27258 
27259     vctxt->depth = -1;
27260     ret = xmlTextReaderRead(vctxt->reader);
27261     /*
27262     * Move to the document element.
27263     */
27264     while (ret == 1) {
27265 	nodeType = xmlTextReaderNodeType(vctxt->reader);
27266 	if (nodeType == XML_ELEMENT_NODE)
27267 	    goto root_found;
27268 	ret = xmlTextReaderRead(vctxt->reader);
27269     }
27270     goto exit;
27271 
27272 root_found:
27273 
27274     do {
27275 	depth = xmlTextReaderDepth(vctxt->reader);
27276 	nodeType = xmlTextReaderNodeType(vctxt->reader);
27277 
27278 	if (nodeType == XML_ELEMENT_NODE) {
27279 
27280 	    vctxt->depth++;
27281 	    if (xmlSchemaValidatorPushElem(vctxt) == -1) {
27282 		VERROR_INT("xmlSchemaVReaderWalk",
27283 		    "calling xmlSchemaValidatorPushElem()");
27284 		goto internal_error;
27285 	    }
27286 	    ielem = vctxt->inode;
27287 	    ielem->localName = xmlTextReaderLocalName(vctxt->reader);
27288 	    ielem->nsName = xmlTextReaderNamespaceUri(vctxt->reader);
27289 	    ielem->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
27290 	    /*
27291 	    * Is the element empty?
27292 	    */
27293 	    ret = xmlTextReaderIsEmptyElement(vctxt->reader);
27294 	    if (ret == -1) {
27295 		VERROR_INT("xmlSchemaVReaderWalk",
27296 		    "calling xmlTextReaderIsEmptyElement()");
27297 		goto internal_error;
27298 	    }
27299 	    if (ret) {
27300 		ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27301 	    }
27302 	    /*
27303 	    * Register attributes.
27304 	    */
27305 	    vctxt->nbAttrInfos = 0;
27306 	    ret = xmlTextReaderMoveToFirstAttribute(vctxt->reader);
27307 	    if (ret == -1) {
27308 		VERROR_INT("xmlSchemaVReaderWalk",
27309 		    "calling xmlTextReaderMoveToFirstAttribute()");
27310 		goto internal_error;
27311 	    }
27312 	    if (ret == 1) {
27313 		do {
27314 		    /*
27315 		    * VAL TODO: How do we know that the reader works on a
27316 		    * node tree, to be able to pass a node here?
27317 		    */
27318 		    if (xmlSchemaValidatorPushAttribute(vctxt, NULL,
27319 			(const xmlChar *) xmlTextReaderLocalName(vctxt->reader),
27320 			xmlTextReaderNamespaceUri(vctxt->reader), 1,
27321 			xmlTextReaderValue(vctxt->reader), 1) == -1) {
27322 
27323 			VERROR_INT("xmlSchemaVReaderWalk",
27324 			    "calling xmlSchemaValidatorPushAttribute()");
27325 			goto internal_error;
27326 		    }
27327 		    ret = xmlTextReaderMoveToNextAttribute(vctxt->reader);
27328 		    if (ret == -1) {
27329 			VERROR_INT("xmlSchemaVReaderWalk",
27330 			    "calling xmlTextReaderMoveToFirstAttribute()");
27331 			goto internal_error;
27332 		    }
27333 		} while (ret == 1);
27334 		/*
27335 		* Back to element position.
27336 		*/
27337 		ret = xmlTextReaderMoveToElement(vctxt->reader);
27338 		if (ret == -1) {
27339 		    VERROR_INT("xmlSchemaVReaderWalk",
27340 			"calling xmlTextReaderMoveToElement()");
27341 		    goto internal_error;
27342 		}
27343 	    }
27344 	    /*
27345 	    * Validate the element.
27346 	    */
27347 	    ret= xmlSchemaValidateElem(vctxt);
27348 	    if (ret != 0) {
27349 		if (ret == -1) {
27350 		    VERROR_INT("xmlSchemaVReaderWalk",
27351 			"calling xmlSchemaValidateElem()");
27352 		    goto internal_error;
27353 		}
27354 		goto exit;
27355 	    }
27356 	    if (vctxt->depth == vctxt->skipDepth) {
27357 		int curDepth;
27358 		/*
27359 		* Skip all content.
27360 		*/
27361 		if ((ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) == 0) {
27362 		    ret = xmlTextReaderRead(vctxt->reader);
27363 		    curDepth = xmlTextReaderDepth(vctxt->reader);
27364 		    while ((ret == 1) && (curDepth != depth)) {
27365 			ret = xmlTextReaderRead(vctxt->reader);
27366 			curDepth = xmlTextReaderDepth(vctxt->reader);
27367 		    }
27368 		    if (ret < 0) {
27369 			/*
27370 			* VAL TODO: A reader error occurred; what to do here?
27371 			*/
27372 			ret = 1;
27373 			goto exit;
27374 		    }
27375 		}
27376 		goto leave_elem;
27377 	    }
27378 	    /*
27379 	    * READER VAL TODO: Is an END_ELEM really never called
27380 	    * if the elem is empty?
27381 	    */
27382 	    if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27383 		goto leave_elem;
27384 	} else if (nodeType == END_ELEM) {
27385 	    /*
27386 	    * Process END of element.
27387 	    */
27388 leave_elem:
27389 	    ret = xmlSchemaValidatorPopElem(vctxt);
27390 	    if (ret != 0) {
27391 		if (ret < 0) {
27392 		    VERROR_INT("xmlSchemaVReaderWalk",
27393 			"calling xmlSchemaValidatorPopElem()");
27394 		    goto internal_error;
27395 		}
27396 		goto exit;
27397 	    }
27398 	    if (vctxt->depth >= 0)
27399 		ielem = vctxt->inode;
27400 	    else
27401 		ielem = NULL;
27402 	} else if ((nodeType == XML_TEXT_NODE) ||
27403 	    (nodeType == XML_CDATA_SECTION_NODE) ||
27404 	    (nodeType == WHTSP) ||
27405 	    (nodeType == SIGN_WHTSP)) {
27406 	    /*
27407 	    * Process character content.
27408 	    */
27409 	    xmlChar *value;
27410 
27411 	    if ((nodeType == WHTSP) || (nodeType == SIGN_WHTSP))
27412 		nodeType = XML_TEXT_NODE;
27413 
27414 	    value = xmlTextReaderValue(vctxt->reader);
27415 	    ret = xmlSchemaVPushText(vctxt, nodeType, BAD_CAST value,
27416 		-1, XML_SCHEMA_PUSH_TEXT_CREATED, &consumed);
27417 	    if (! consumed)
27418 		xmlFree(value);
27419 	    if (ret == -1) {
27420 		VERROR_INT("xmlSchemaVReaderWalk",
27421 		    "calling xmlSchemaVPushText()");
27422 		goto internal_error;
27423 	    }
27424 	} else if ((nodeType == XML_ENTITY_NODE) ||
27425 	    (nodeType == XML_ENTITY_REF_NODE)) {
27426 	    /*
27427 	    * VAL TODO: What to do with entities?
27428 	    */
27429 	    TODO
27430 	}
27431 	/*
27432 	* Read next node.
27433 	*/
27434 	ret = xmlTextReaderRead(vctxt->reader);
27435     } while (ret == 1);
27436 
27437 exit:
27438     return (ret);
27439 internal_error:
27440     return (-1);
27441 }
27442 #endif
27443 
27444 /************************************************************************
27445  *									*
27446  *			SAX validation handlers				*
27447  *									*
27448  ************************************************************************/
27449 
27450 /*
27451 * Process text content.
27452 */
27453 static void
xmlSchemaSAXHandleText(void * ctx,const xmlChar * ch,int len)27454 xmlSchemaSAXHandleText(void *ctx,
27455 		       const xmlChar * ch,
27456 		       int len)
27457 {
27458     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27459 
27460     if (vctxt->depth < 0)
27461 	return;
27462     if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27463 	return;
27464     if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27465 	vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27466     if (xmlSchemaVPushText(vctxt, XML_TEXT_NODE, ch, len,
27467 	XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
27468 	VERROR_INT("xmlSchemaSAXHandleCDataSection",
27469 	    "calling xmlSchemaVPushText()");
27470 	vctxt->err = -1;
27471 	xmlStopParser(vctxt->parserCtxt);
27472     }
27473 }
27474 
27475 /*
27476 * Process CDATA content.
27477 */
27478 static void
xmlSchemaSAXHandleCDataSection(void * ctx,const xmlChar * ch,int len)27479 xmlSchemaSAXHandleCDataSection(void *ctx,
27480 			     const xmlChar * ch,
27481 			     int len)
27482 {
27483     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27484 
27485     if (vctxt->depth < 0)
27486 	return;
27487     if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27488 	return;
27489     if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27490 	vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27491     if (xmlSchemaVPushText(vctxt, XML_CDATA_SECTION_NODE, ch, len,
27492 	XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
27493 	VERROR_INT("xmlSchemaSAXHandleCDataSection",
27494 	    "calling xmlSchemaVPushText()");
27495 	vctxt->err = -1;
27496 	xmlStopParser(vctxt->parserCtxt);
27497     }
27498 }
27499 
27500 static void
xmlSchemaSAXHandleReference(void * ctx ATTRIBUTE_UNUSED,const xmlChar * name ATTRIBUTE_UNUSED)27501 xmlSchemaSAXHandleReference(void *ctx ATTRIBUTE_UNUSED,
27502 			    const xmlChar * name ATTRIBUTE_UNUSED)
27503 {
27504     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27505 
27506     if (vctxt->depth < 0)
27507 	return;
27508     if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27509 	return;
27510     /* SAX VAL TODO: What to do here? */
27511     TODO
27512 }
27513 
27514 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)27515 xmlSchemaSAXHandleStartElementNs(void *ctx,
27516 				 const xmlChar * localname,
27517 				 const xmlChar * prefix ATTRIBUTE_UNUSED,
27518 				 const xmlChar * URI,
27519 				 int nb_namespaces,
27520 				 const xmlChar ** namespaces,
27521 				 int nb_attributes,
27522 				 int nb_defaulted ATTRIBUTE_UNUSED,
27523 				 const xmlChar ** attributes)
27524 {
27525     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27526     int ret;
27527     xmlSchemaNodeInfoPtr ielem;
27528     int i, j;
27529 
27530     /*
27531     * SAX VAL TODO: What to do with nb_defaulted?
27532     */
27533     /*
27534     * Skip elements if inside a "skip" wildcard or invalid.
27535     */
27536     vctxt->depth++;
27537     if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27538 	return;
27539     /*
27540     * Push the element.
27541     */
27542     if (xmlSchemaValidatorPushElem(vctxt) == -1) {
27543 	VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27544 	    "calling xmlSchemaValidatorPushElem()");
27545 	goto internal_error;
27546     }
27547     ielem = vctxt->inode;
27548     /*
27549     * TODO: Is this OK?
27550     */
27551     ielem->nodeLine = xmlSAX2GetLineNumber(vctxt->parserCtxt);
27552     ielem->localName = localname;
27553     ielem->nsName = URI;
27554     ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27555     /*
27556     * Register namespaces on the elem info.
27557     */
27558     if (nb_namespaces != 0) {
27559 	/*
27560 	* Although the parser builds its own namespace list,
27561 	* we have no access to it, so we'll use an own one.
27562 	*/
27563         for (i = 0, j = 0; i < nb_namespaces; i++, j += 2) {
27564 	    /*
27565 	    * Store prefix and namespace name.
27566 	    */
27567 	    if (ielem->nsBindings == NULL) {
27568 		ielem->nsBindings =
27569 		    (const xmlChar **) xmlMalloc(10 *
27570 			sizeof(const xmlChar *));
27571 		if (ielem->nsBindings == NULL) {
27572 		    xmlSchemaVErrMemory(vctxt,
27573 			"allocating namespace bindings for SAX validation",
27574 			NULL);
27575 		    goto internal_error;
27576 		}
27577 		ielem->nbNsBindings = 0;
27578 		ielem->sizeNsBindings = 5;
27579 	    } else if (ielem->sizeNsBindings <= ielem->nbNsBindings) {
27580 		ielem->sizeNsBindings *= 2;
27581 		ielem->nsBindings =
27582 		    (const xmlChar **) xmlRealloc(
27583 			(void *) ielem->nsBindings,
27584 			ielem->sizeNsBindings * 2 * sizeof(const xmlChar *));
27585 		if (ielem->nsBindings == NULL) {
27586 		    xmlSchemaVErrMemory(vctxt,
27587 			"re-allocating namespace bindings for SAX validation",
27588 			NULL);
27589 		    goto internal_error;
27590 		}
27591 	    }
27592 
27593 	    ielem->nsBindings[ielem->nbNsBindings * 2] = namespaces[j];
27594 	    if (namespaces[j+1][0] == 0) {
27595 		/*
27596 		* Handle xmlns="".
27597 		*/
27598 		ielem->nsBindings[ielem->nbNsBindings * 2 + 1] = NULL;
27599 	    } else
27600 		ielem->nsBindings[ielem->nbNsBindings * 2 + 1] =
27601 		    namespaces[j+1];
27602 	    ielem->nbNsBindings++;
27603 	}
27604     }
27605     /*
27606     * Register attributes.
27607     * SAX VAL TODO: We are not adding namespace declaration
27608     * attributes yet.
27609     */
27610     if (nb_attributes != 0) {
27611 	int valueLen, k, l;
27612 	xmlChar *value;
27613 
27614         for (j = 0, i = 0; i < nb_attributes; i++, j += 5) {
27615 	    /*
27616 	    * Duplicate the value, changing any &#38; to a literal ampersand.
27617 	    *
27618 	    * libxml2 differs from normal SAX here in that it escapes all ampersands
27619 	    * as &#38; instead of delivering the raw converted string. Changing the
27620 	    * behavior at this point would break applications that use this API, so
27621 	    * we are forced to work around it.
27622 	    */
27623 	    valueLen = attributes[j+4] - attributes[j+3];
27624 	    value = xmlMallocAtomic(valueLen + 1);
27625 	    if (value == NULL) {
27626 		xmlSchemaVErrMemory(vctxt,
27627 		    "allocating string for decoded attribute",
27628 		    NULL);
27629 		goto internal_error;
27630 	    }
27631 	    for (k = 0, l = 0; k < valueLen; l++) {
27632 		if (k < valueLen - 4 &&
27633 		    attributes[j+3][k+0] == '&' &&
27634 		    attributes[j+3][k+1] == '#' &&
27635 		    attributes[j+3][k+2] == '3' &&
27636 		    attributes[j+3][k+3] == '8' &&
27637 		    attributes[j+3][k+4] == ';') {
27638 		    value[l] = '&';
27639 		    k += 5;
27640 		} else {
27641 		    value[l] = attributes[j+3][k];
27642 		    k++;
27643 		}
27644 	    }
27645 	    value[l] = '\0';
27646 	    /*
27647 	    * TODO: Set the node line.
27648 	    */
27649 	    ret = xmlSchemaValidatorPushAttribute(vctxt,
27650 		NULL, ielem->nodeLine, attributes[j], attributes[j+2], 0,
27651 		value, 1);
27652 	    if (ret == -1) {
27653 		VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27654 		    "calling xmlSchemaValidatorPushAttribute()");
27655 		goto internal_error;
27656 	    }
27657 	}
27658     }
27659     /*
27660     * Validate the element.
27661     */
27662     ret = xmlSchemaValidateElem(vctxt);
27663     if (ret != 0) {
27664 	if (ret == -1) {
27665 	    VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27666 		"calling xmlSchemaValidateElem()");
27667 	    goto internal_error;
27668 	}
27669 	goto exit;
27670     }
27671 
27672 exit:
27673     return;
27674 internal_error:
27675     vctxt->err = -1;
27676     xmlStopParser(vctxt->parserCtxt);
27677     return;
27678 }
27679 
27680 static void
xmlSchemaSAXHandleEndElementNs(void * ctx,const xmlChar * localname ATTRIBUTE_UNUSED,const xmlChar * prefix ATTRIBUTE_UNUSED,const xmlChar * URI ATTRIBUTE_UNUSED)27681 xmlSchemaSAXHandleEndElementNs(void *ctx,
27682 			       const xmlChar * localname ATTRIBUTE_UNUSED,
27683 			       const xmlChar * prefix ATTRIBUTE_UNUSED,
27684 			       const xmlChar * URI ATTRIBUTE_UNUSED)
27685 {
27686     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27687     int res;
27688 
27689     /*
27690     * Skip elements if inside a "skip" wildcard or if invalid.
27691     */
27692     if (vctxt->skipDepth != -1) {
27693 	if (vctxt->depth > vctxt->skipDepth) {
27694 	    vctxt->depth--;
27695 	    return;
27696 	} else
27697 	    vctxt->skipDepth = -1;
27698     }
27699     /*
27700     * SAX VAL TODO: Just a temporary check.
27701     */
27702     if ((!xmlStrEqual(vctxt->inode->localName, localname)) ||
27703 	(!xmlStrEqual(vctxt->inode->nsName, URI))) {
27704 	VERROR_INT("xmlSchemaSAXHandleEndElementNs",
27705 	    "elem pop mismatch");
27706     }
27707     res = xmlSchemaValidatorPopElem(vctxt);
27708     if (res != 0) {
27709 	if (res < 0) {
27710 	    VERROR_INT("xmlSchemaSAXHandleEndElementNs",
27711 		"calling xmlSchemaValidatorPopElem()");
27712 	    goto internal_error;
27713 	}
27714 	goto exit;
27715     }
27716 exit:
27717     return;
27718 internal_error:
27719     vctxt->err = -1;
27720     xmlStopParser(vctxt->parserCtxt);
27721     return;
27722 }
27723 
27724 /************************************************************************
27725  *									*
27726  *			Validation interfaces				*
27727  *									*
27728  ************************************************************************/
27729 
27730 /**
27731  * xmlSchemaNewValidCtxt:
27732  * @schema:  a precompiled XML Schemas
27733  *
27734  * Create an XML Schemas validation context based on the given schema.
27735  *
27736  * Returns the validation context or NULL in case of error
27737  */
27738 xmlSchemaValidCtxtPtr
xmlSchemaNewValidCtxt(xmlSchemaPtr schema)27739 xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
27740 {
27741     xmlSchemaValidCtxtPtr ret;
27742 
27743     ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
27744     if (ret == NULL) {
27745         xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
27746         return (NULL);
27747     }
27748     memset(ret, 0, sizeof(xmlSchemaValidCtxt));
27749     ret->type = XML_SCHEMA_CTXT_VALIDATOR;
27750     ret->dict = xmlDictCreate();
27751     ret->nodeQNames = xmlSchemaItemListCreate();
27752     ret->schema = schema;
27753     return (ret);
27754 }
27755 
27756 /**
27757  * xmlSchemaValidateSetFilename:
27758  * @vctxt: the schema validation context
27759  * @filename: the file name
27760  *
27761  * Workaround to provide file error reporting information when this is
27762  * not provided by current APIs
27763  */
27764 void
xmlSchemaValidateSetFilename(xmlSchemaValidCtxtPtr vctxt,const char * filename)27765 xmlSchemaValidateSetFilename(xmlSchemaValidCtxtPtr vctxt, const char *filename) {
27766     if (vctxt == NULL)
27767         return;
27768     if (vctxt->filename != NULL)
27769         xmlFree(vctxt->filename);
27770     if (filename != NULL)
27771         vctxt->filename = (char *) xmlStrdup((const xmlChar *) filename);
27772     else
27773         vctxt->filename = NULL;
27774 }
27775 
27776 /**
27777  * xmlSchemaClearValidCtxt:
27778  * @vctxt: the schema validation context
27779  *
27780  * Free the resources associated to the schema validation context;
27781  * leaves some fields alive intended for reuse of the context.
27782  */
27783 static void
xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)27784 xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
27785 {
27786     if (vctxt == NULL)
27787         return;
27788 
27789     /*
27790     * TODO: Should we clear the flags?
27791     *   Might be problematic if one reuses the context
27792     *   and assumes that the options remain the same.
27793     */
27794     vctxt->flags = 0;
27795     vctxt->validationRoot = NULL;
27796     vctxt->doc = NULL;
27797 #ifdef LIBXML_READER_ENABLED
27798     vctxt->reader = NULL;
27799 #endif
27800     vctxt->hasKeyrefs = 0;
27801 
27802     if (vctxt->value != NULL) {
27803         xmlSchemaFreeValue(vctxt->value);
27804 	vctxt->value = NULL;
27805     }
27806     /*
27807     * Augmented IDC information.
27808     */
27809     if (vctxt->aidcs != NULL) {
27810 	xmlSchemaIDCAugPtr cur = vctxt->aidcs, next;
27811 	do {
27812 	    next = cur->next;
27813 	    xmlFree(cur);
27814 	    cur = next;
27815 	} while (cur != NULL);
27816 	vctxt->aidcs = NULL;
27817     }
27818     if (vctxt->idcMatcherCache != NULL) {
27819 	xmlSchemaIDCMatcherPtr matcher = vctxt->idcMatcherCache, tmp;
27820 
27821 	while (matcher) {
27822 	    tmp = matcher;
27823 	    matcher = matcher->nextCached;
27824 	    xmlSchemaIDCFreeMatcherList(tmp);
27825 	}
27826 	vctxt->idcMatcherCache = NULL;
27827     }
27828 
27829 
27830     if (vctxt->idcNodes != NULL) {
27831 	int i;
27832 	xmlSchemaPSVIIDCNodePtr item;
27833 
27834 	for (i = 0; i < vctxt->nbIdcNodes; i++) {
27835 	    item = vctxt->idcNodes[i];
27836 	    xmlFree(item->keys);
27837 	    xmlFree(item);
27838 	}
27839 	xmlFree(vctxt->idcNodes);
27840 	vctxt->idcNodes = NULL;
27841 	vctxt->nbIdcNodes = 0;
27842 	vctxt->sizeIdcNodes = 0;
27843     }
27844 
27845     if (vctxt->idcKeys != NULL) {
27846 	int i;
27847 	for (i = 0; i < vctxt->nbIdcKeys; i++)
27848 	    xmlSchemaIDCFreeKey(vctxt->idcKeys[i]);
27849 	xmlFree(vctxt->idcKeys);
27850 	vctxt->idcKeys = NULL;
27851 	vctxt->nbIdcKeys = 0;
27852 	vctxt->sizeIdcKeys = 0;
27853     }
27854 
27855     /*
27856     * Note that we won't delete the XPath state pool here.
27857     */
27858     if (vctxt->xpathStates != NULL) {
27859 	xmlSchemaFreeIDCStateObjList(vctxt->xpathStates);
27860 	vctxt->xpathStates = NULL;
27861     }
27862     /*
27863     * Attribute info.
27864     */
27865     if (vctxt->nbAttrInfos != 0) {
27866 	xmlSchemaClearAttrInfos(vctxt);
27867     }
27868     /*
27869     * Element info.
27870     */
27871     if (vctxt->elemInfos != NULL) {
27872 	int i;
27873 	xmlSchemaNodeInfoPtr ei;
27874 
27875 	for (i = 0; i < vctxt->sizeElemInfos; i++) {
27876 	    ei = vctxt->elemInfos[i];
27877 	    if (ei == NULL)
27878 		break;
27879 	    xmlSchemaClearElemInfo(vctxt, ei);
27880 	}
27881     }
27882     xmlSchemaItemListClear(vctxt->nodeQNames);
27883     /* Recreate the dict. */
27884     xmlDictFree(vctxt->dict);
27885     /*
27886     * TODO: Is is save to recreate it? Do we have a scenario
27887     * where the user provides the dict?
27888     */
27889     vctxt->dict = xmlDictCreate();
27890 
27891     if (vctxt->filename != NULL) {
27892         xmlFree(vctxt->filename);
27893 	vctxt->filename = NULL;
27894     }
27895 }
27896 
27897 /**
27898  * xmlSchemaFreeValidCtxt:
27899  * @ctxt:  the schema validation context
27900  *
27901  * Free the resources associated to the schema validation context
27902  */
27903 void
xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)27904 xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
27905 {
27906     if (ctxt == NULL)
27907         return;
27908     if (ctxt->value != NULL)
27909         xmlSchemaFreeValue(ctxt->value);
27910     if (ctxt->pctxt != NULL)
27911 	xmlSchemaFreeParserCtxt(ctxt->pctxt);
27912     if (ctxt->idcNodes != NULL) {
27913 	int i;
27914 	xmlSchemaPSVIIDCNodePtr item;
27915 
27916 	for (i = 0; i < ctxt->nbIdcNodes; i++) {
27917 	    item = ctxt->idcNodes[i];
27918 	    xmlFree(item->keys);
27919 	    xmlFree(item);
27920 	}
27921 	xmlFree(ctxt->idcNodes);
27922     }
27923     if (ctxt->idcKeys != NULL) {
27924 	int i;
27925 	for (i = 0; i < ctxt->nbIdcKeys; i++)
27926 	    xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
27927 	xmlFree(ctxt->idcKeys);
27928     }
27929 
27930     if (ctxt->xpathStates != NULL) {
27931 	xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
27932 	ctxt->xpathStates = NULL;
27933     }
27934     if (ctxt->xpathStatePool != NULL) {
27935 	xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
27936 	ctxt->xpathStatePool = NULL;
27937     }
27938 
27939     /*
27940     * Augmented IDC information.
27941     */
27942     if (ctxt->aidcs != NULL) {
27943 	xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
27944 	do {
27945 	    next = cur->next;
27946 	    xmlFree(cur);
27947 	    cur = next;
27948 	} while (cur != NULL);
27949     }
27950     if (ctxt->attrInfos != NULL) {
27951 	int i;
27952 	xmlSchemaAttrInfoPtr attr;
27953 
27954 	/* Just a paranoid call to the cleanup. */
27955 	if (ctxt->nbAttrInfos != 0)
27956 	    xmlSchemaClearAttrInfos(ctxt);
27957 	for (i = 0; i < ctxt->sizeAttrInfos; i++) {
27958 	    attr = ctxt->attrInfos[i];
27959 	    xmlFree(attr);
27960 	}
27961 	xmlFree(ctxt->attrInfos);
27962     }
27963     if (ctxt->elemInfos != NULL) {
27964 	int i;
27965 	xmlSchemaNodeInfoPtr ei;
27966 
27967 	for (i = 0; i < ctxt->sizeElemInfos; i++) {
27968 	    ei = ctxt->elemInfos[i];
27969 	    if (ei == NULL)
27970 		break;
27971 	    xmlSchemaClearElemInfo(ctxt, ei);
27972 	    xmlFree(ei);
27973 	}
27974 	xmlFree(ctxt->elemInfos);
27975     }
27976     if (ctxt->nodeQNames != NULL)
27977 	xmlSchemaItemListFree(ctxt->nodeQNames);
27978     if (ctxt->dict != NULL)
27979 	xmlDictFree(ctxt->dict);
27980     if (ctxt->filename != NULL)
27981 	xmlFree(ctxt->filename);
27982     xmlFree(ctxt);
27983 }
27984 
27985 /**
27986  * xmlSchemaIsValid:
27987  * @ctxt: the schema validation context
27988  *
27989  * Check if any error was detected during validation.
27990  *
27991  * Returns 1 if valid so far, 0 if errors were detected, and -1 in case
27992  *         of internal error.
27993  */
27994 int
xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt)27995 xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt)
27996 {
27997     if (ctxt == NULL)
27998         return(-1);
27999     return(ctxt->err == 0);
28000 }
28001 
28002 /**
28003  * xmlSchemaSetValidErrors:
28004  * @ctxt:  a schema validation context
28005  * @err:  the error function
28006  * @warn: the warning function
28007  * @ctx: the functions context
28008  *
28009  * Set the error and warning callback information
28010  */
28011 void
xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,xmlSchemaValidityErrorFunc err,xmlSchemaValidityWarningFunc warn,void * ctx)28012 xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
28013                         xmlSchemaValidityErrorFunc err,
28014                         xmlSchemaValidityWarningFunc warn, void *ctx)
28015 {
28016     if (ctxt == NULL)
28017         return;
28018     ctxt->error = err;
28019     ctxt->warning = warn;
28020     ctxt->errCtxt = ctx;
28021     if (ctxt->pctxt != NULL)
28022 	xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
28023 }
28024 
28025 /**
28026  * xmlSchemaSetValidStructuredErrors:
28027  * @ctxt:  a schema validation context
28028  * @serror:  the structured error function
28029  * @ctx: the functions context
28030  *
28031  * Set the structured error callback
28032  */
28033 void
xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt,xmlStructuredErrorFunc serror,void * ctx)28034 xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt,
28035 				  xmlStructuredErrorFunc serror, void *ctx)
28036 {
28037     if (ctxt == NULL)
28038         return;
28039     ctxt->serror = serror;
28040     ctxt->error = NULL;
28041     ctxt->warning = NULL;
28042     ctxt->errCtxt = ctx;
28043     if (ctxt->pctxt != NULL)
28044 	xmlSchemaSetParserStructuredErrors(ctxt->pctxt, serror, ctx);
28045 }
28046 
28047 /**
28048  * xmlSchemaGetValidErrors:
28049  * @ctxt: a XML-Schema validation context
28050  * @err: the error function result
28051  * @warn: the warning function result
28052  * @ctx: the functions context result
28053  *
28054  * Get the error and warning callback information
28055  *
28056  * Returns -1 in case of error and 0 otherwise
28057  */
28058 int
xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,xmlSchemaValidityErrorFunc * err,xmlSchemaValidityWarningFunc * warn,void ** ctx)28059 xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
28060 			xmlSchemaValidityErrorFunc * err,
28061 			xmlSchemaValidityWarningFunc * warn, void **ctx)
28062 {
28063 	if (ctxt == NULL)
28064 		return (-1);
28065 	if (err != NULL)
28066 		*err = ctxt->error;
28067 	if (warn != NULL)
28068 		*warn = ctxt->warning;
28069 	if (ctx != NULL)
28070 		*ctx = ctxt->errCtxt;
28071 	return (0);
28072 }
28073 
28074 
28075 /**
28076  * xmlSchemaSetValidOptions:
28077  * @ctxt:	a schema validation context
28078  * @options: a combination of xmlSchemaValidOption
28079  *
28080  * Sets the options to be used during the validation.
28081  *
28082  * Returns 0 in case of success, -1 in case of an
28083  * API error.
28084  */
28085 int
xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,int options)28086 xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
28087 			 int options)
28088 
28089 {
28090     int i;
28091 
28092     if (ctxt == NULL)
28093 	return (-1);
28094     /*
28095     * WARNING: Change the start value if adding to the
28096     * xmlSchemaValidOption.
28097     * TODO: Is there an other, more easy to maintain,
28098     * way?
28099     */
28100     for (i = 1; i < (int) sizeof(int) * 8; i++) {
28101         if (options & 1<<i)
28102 	    return (-1);
28103     }
28104     ctxt->options = options;
28105     return (0);
28106 }
28107 
28108 /**
28109  * xmlSchemaValidCtxtGetOptions:
28110  * @ctxt: a schema validation context
28111  *
28112  * Get the validation context options.
28113  *
28114  * Returns the option combination or -1 on error.
28115  */
28116 int
xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)28117 xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
28118 
28119 {
28120     if (ctxt == NULL)
28121 	return (-1);
28122     else
28123 	return (ctxt->options);
28124 }
28125 
28126 static int
xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)28127 xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)
28128 {
28129     xmlAttrPtr attr;
28130     int ret = 0;
28131     xmlSchemaNodeInfoPtr ielem = NULL;
28132     xmlNodePtr node, valRoot;
28133     const xmlChar *nsName;
28134 
28135     /* DOC VAL TODO: Move this to the start function. */
28136     if (vctxt->validationRoot != NULL)
28137         valRoot = vctxt->validationRoot;
28138     else
28139 	valRoot = xmlDocGetRootElement(vctxt->doc);
28140     if (valRoot == NULL) {
28141 	/* VAL TODO: Error code? */
28142 	VERROR(1, NULL, "The document has no document element");
28143 	return (1);
28144     }
28145     vctxt->depth = -1;
28146     vctxt->validationRoot = valRoot;
28147     node = valRoot;
28148     while (node != NULL) {
28149 	if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
28150 	    goto next_sibling;
28151 	if (node->type == XML_ELEMENT_NODE) {
28152 
28153 	    /*
28154 	    * Init the node-info.
28155 	    */
28156 	    vctxt->depth++;
28157 	    if (xmlSchemaValidatorPushElem(vctxt) == -1)
28158 		goto internal_error;
28159 	    ielem = vctxt->inode;
28160 	    ielem->node = node;
28161 	    ielem->nodeLine = node->line;
28162 	    ielem->localName = node->name;
28163 	    if (node->ns != NULL)
28164 		ielem->nsName = node->ns->href;
28165 	    ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
28166 	    /*
28167 	    * Register attributes.
28168 	    * DOC VAL TODO: We do not register namespace declaration
28169 	    * attributes yet.
28170 	    */
28171 	    vctxt->nbAttrInfos = 0;
28172 	    if (node->properties != NULL) {
28173 		attr = node->properties;
28174 		do {
28175 		    if (attr->ns != NULL)
28176 			nsName = attr->ns->href;
28177 		    else
28178 			nsName = NULL;
28179 		    ret = xmlSchemaValidatorPushAttribute(vctxt,
28180 			(xmlNodePtr) attr,
28181 			/*
28182 			* Note that we give it the line number of the
28183 			* parent element.
28184 			*/
28185 			ielem->nodeLine,
28186 			attr->name, nsName, 0,
28187 			xmlNodeListGetString(attr->doc, attr->children, 1), 1);
28188 		    if (ret == -1) {
28189 			VERROR_INT("xmlSchemaDocWalk",
28190 			    "calling xmlSchemaValidatorPushAttribute()");
28191 			goto internal_error;
28192 		    }
28193 		    attr = attr->next;
28194 		} while (attr);
28195 	    }
28196 	    /*
28197 	    * Validate the element.
28198 	    */
28199 	    ret = xmlSchemaValidateElem(vctxt);
28200 	    if (ret != 0) {
28201 		if (ret == -1) {
28202 		    VERROR_INT("xmlSchemaDocWalk",
28203 			"calling xmlSchemaValidateElem()");
28204 		    goto internal_error;
28205 		}
28206 		/*
28207 		* Don't stop validation; just skip the content
28208 		* of this element.
28209 		*/
28210 		goto leave_node;
28211 	    }
28212 	    if ((vctxt->skipDepth != -1) &&
28213 		(vctxt->depth >= vctxt->skipDepth))
28214 		goto leave_node;
28215 	} else if ((node->type == XML_TEXT_NODE) ||
28216 	    (node->type == XML_CDATA_SECTION_NODE)) {
28217 	    /*
28218 	    * Process character content.
28219 	    */
28220 	    if ((ielem != NULL) && (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY))
28221 		ielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
28222 	    ret = xmlSchemaVPushText(vctxt, node->type, node->content,
28223 		-1, XML_SCHEMA_PUSH_TEXT_PERSIST, NULL);
28224 	    if (ret < 0) {
28225 		VERROR_INT("xmlSchemaVDocWalk",
28226 		    "calling xmlSchemaVPushText()");
28227 		goto internal_error;
28228 	    }
28229 	    /*
28230 	    * DOC VAL TODO: Should we skip further validation of the
28231 	    * element content here?
28232 	    */
28233 	} else if ((node->type == XML_ENTITY_NODE) ||
28234 	    (node->type == XML_ENTITY_REF_NODE)) {
28235 	    /*
28236 	    * DOC VAL TODO: What to do with entities?
28237 	    */
28238 	    VERROR_INT("xmlSchemaVDocWalk",
28239 		"there is at least one entity reference in the node-tree "
28240 		"currently being validated. Processing of entities with "
28241 		"this XML Schema processor is not supported (yet). Please "
28242 		"substitute entities before validation.");
28243 	    goto internal_error;
28244 	} else {
28245 	    goto leave_node;
28246 	    /*
28247 	    * DOC VAL TODO: XInclude nodes, etc.
28248 	    */
28249 	}
28250 	/*
28251 	* Walk the doc.
28252 	*/
28253 	if (node->children != NULL) {
28254 	    node = node->children;
28255 	    continue;
28256 	}
28257 leave_node:
28258 	if (node->type == XML_ELEMENT_NODE) {
28259 	    /*
28260 	    * Leaving the scope of an element.
28261 	    */
28262 	    if (node != vctxt->inode->node) {
28263 		VERROR_INT("xmlSchemaVDocWalk",
28264 		    "element position mismatch");
28265 		goto internal_error;
28266 	    }
28267 	    ret = xmlSchemaValidatorPopElem(vctxt);
28268 	    if (ret != 0) {
28269 		if (ret < 0) {
28270 		    VERROR_INT("xmlSchemaVDocWalk",
28271 			"calling xmlSchemaValidatorPopElem()");
28272 		    goto internal_error;
28273 		}
28274 	    }
28275 	    if (node == valRoot)
28276 		goto exit;
28277 	}
28278 next_sibling:
28279 	if (node->next != NULL)
28280 	    node = node->next;
28281 	else {
28282 	    node = node->parent;
28283 	    goto leave_node;
28284 	}
28285     }
28286 
28287 exit:
28288     return (ret);
28289 internal_error:
28290     return (-1);
28291 }
28292 
28293 static int
xmlSchemaPreRun(xmlSchemaValidCtxtPtr vctxt)28294 xmlSchemaPreRun(xmlSchemaValidCtxtPtr vctxt) {
28295     /*
28296     * Some initialization.
28297     */
28298     vctxt->err = 0;
28299     vctxt->nberrors = 0;
28300     vctxt->depth = -1;
28301     vctxt->skipDepth = -1;
28302     vctxt->hasKeyrefs = 0;
28303 #ifdef ENABLE_IDC_NODE_TABLES_TEST
28304     vctxt->createIDCNodeTables = 1;
28305 #else
28306     vctxt->createIDCNodeTables = 0;
28307 #endif
28308     /*
28309     * Create a schema + parser if necessary.
28310     */
28311     if (vctxt->schema == NULL) {
28312 	xmlSchemaParserCtxtPtr pctxt;
28313 
28314 	vctxt->xsiAssemble = 1;
28315 	/*
28316 	* If not schema was given then we will create a schema
28317 	* dynamically using XSI schema locations.
28318 	*
28319 	* Create the schema parser context.
28320 	*/
28321 	if ((vctxt->pctxt == NULL) &&
28322 	   (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
28323 	   return (-1);
28324 	pctxt = vctxt->pctxt;
28325 	pctxt->xsiAssemble = 1;
28326 	/*
28327 	* Create the schema.
28328 	*/
28329 	vctxt->schema = xmlSchemaNewSchema(pctxt);
28330 	if (vctxt->schema == NULL)
28331 	    return (-1);
28332 	/*
28333 	* Create the schema construction context.
28334 	*/
28335 	pctxt->constructor = xmlSchemaConstructionCtxtCreate(pctxt->dict);
28336 	if (pctxt->constructor == NULL)
28337 	    return(-1);
28338 	pctxt->constructor->mainSchema = vctxt->schema;
28339 	/*
28340 	* Take ownership of the constructor to be able to free it.
28341 	*/
28342 	pctxt->ownsConstructor = 1;
28343     }
28344     /*
28345     * Augment the IDC definitions for the main schema and all imported ones
28346     * NOTE: main schema if the first in the imported list
28347     */
28348     xmlHashScan(vctxt->schema->schemasImports, xmlSchemaAugmentImportedIDC,
28349                 vctxt);
28350 
28351     return(0);
28352 }
28353 
28354 static void
xmlSchemaPostRun(xmlSchemaValidCtxtPtr vctxt)28355 xmlSchemaPostRun(xmlSchemaValidCtxtPtr vctxt) {
28356     if (vctxt->xsiAssemble) {
28357 	if (vctxt->schema != NULL) {
28358 	    xmlSchemaFree(vctxt->schema);
28359 	    vctxt->schema = NULL;
28360 	}
28361     }
28362     xmlSchemaClearValidCtxt(vctxt);
28363 }
28364 
28365 static int
xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt)28366 xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt)
28367 {
28368     int ret = 0;
28369 
28370     if (xmlSchemaPreRun(vctxt) < 0)
28371         return(-1);
28372 
28373     if (vctxt->doc != NULL) {
28374 	/*
28375 	 * Tree validation.
28376 	 */
28377 	ret = xmlSchemaVDocWalk(vctxt);
28378 #ifdef LIBXML_READER_ENABLED
28379     } else if (vctxt->reader != NULL) {
28380 	/*
28381 	 * XML Reader validation.
28382 	 */
28383 #ifdef XML_SCHEMA_READER_ENABLED
28384 	ret = xmlSchemaVReaderWalk(vctxt);
28385 #endif
28386 #endif
28387     } else if ((vctxt->sax != NULL) && (vctxt->parserCtxt != NULL)) {
28388 	/*
28389 	 * SAX validation.
28390 	 */
28391 	ret = xmlParseDocument(vctxt->parserCtxt);
28392     } else {
28393 	VERROR_INT("xmlSchemaVStart",
28394 	    "no instance to validate");
28395 	ret = -1;
28396     }
28397 
28398     xmlSchemaPostRun(vctxt);
28399     if (ret == 0)
28400 	ret = vctxt->err;
28401     return (ret);
28402 }
28403 
28404 /**
28405  * xmlSchemaValidateOneElement:
28406  * @ctxt:  a schema validation context
28407  * @elem:  an element node
28408  *
28409  * Validate a branch of a tree, starting with the given @elem.
28410  *
28411  * Returns 0 if the element and its subtree is valid, a positive error
28412  * code number otherwise and -1 in case of an internal or API error.
28413  */
28414 int
xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt,xmlNodePtr elem)28415 xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
28416 {
28417     if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
28418 	return (-1);
28419 
28420     if (ctxt->schema == NULL)
28421 	return (-1);
28422 
28423     ctxt->doc = elem->doc;
28424     ctxt->node = elem;
28425     ctxt->validationRoot = elem;
28426     return(xmlSchemaVStart(ctxt));
28427 }
28428 
28429 /**
28430  * xmlSchemaValidateDoc:
28431  * @ctxt:  a schema validation context
28432  * @doc:  a parsed document tree
28433  *
28434  * Validate a document tree in memory.
28435  *
28436  * Returns 0 if the document is schemas valid, a positive error code
28437  *     number otherwise and -1 in case of internal or API error.
28438  */
28439 int
xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt,xmlDocPtr doc)28440 xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
28441 {
28442     if ((ctxt == NULL) || (doc == NULL))
28443         return (-1);
28444 
28445     ctxt->doc = doc;
28446     ctxt->node = xmlDocGetRootElement(doc);
28447     if (ctxt->node == NULL) {
28448         xmlSchemaCustomErr(ACTXT_CAST ctxt,
28449 	    XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
28450 	    (xmlNodePtr) doc, NULL,
28451 	    "The document has no document element", NULL, NULL);
28452         return (ctxt->err);
28453     }
28454     ctxt->validationRoot = ctxt->node;
28455     return (xmlSchemaVStart(ctxt));
28456 }
28457 
28458 
28459 /************************************************************************
28460  *									*
28461  *		Function and data for SAX streaming API			*
28462  *									*
28463  ************************************************************************/
28464 typedef struct _xmlSchemaSplitSAXData xmlSchemaSplitSAXData;
28465 typedef xmlSchemaSplitSAXData *xmlSchemaSplitSAXDataPtr;
28466 
28467 struct _xmlSchemaSplitSAXData {
28468     xmlSAXHandlerPtr      user_sax;
28469     void                 *user_data;
28470     xmlSchemaValidCtxtPtr ctxt;
28471     xmlSAXHandlerPtr      schemas_sax;
28472 };
28473 
28474 #define XML_SAX_PLUG_MAGIC 0xdc43ba21
28475 
28476 struct _xmlSchemaSAXPlug {
28477     unsigned int magic;
28478 
28479     /* the original callbacks information */
28480     xmlSAXHandlerPtr     *user_sax_ptr;
28481     xmlSAXHandlerPtr      user_sax;
28482     void                **user_data_ptr;
28483     void                 *user_data;
28484 
28485     /* the block plugged back and validation information */
28486     xmlSAXHandler         schemas_sax;
28487     xmlSchemaValidCtxtPtr ctxt;
28488 };
28489 
28490 /* All those functions just bounces to the user provided SAX handlers */
28491 static void
internalSubsetSplit(void * ctx,const xmlChar * name,const xmlChar * ExternalID,const xmlChar * SystemID)28492 internalSubsetSplit(void *ctx, const xmlChar *name,
28493 	       const xmlChar *ExternalID, const xmlChar *SystemID)
28494 {
28495     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28496     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28497         (ctxt->user_sax->internalSubset != NULL))
28498 	ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
28499 	                               SystemID);
28500 }
28501 
28502 static int
isStandaloneSplit(void * ctx)28503 isStandaloneSplit(void *ctx)
28504 {
28505     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28506     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28507         (ctxt->user_sax->isStandalone != NULL))
28508 	return(ctxt->user_sax->isStandalone(ctxt->user_data));
28509     return(0);
28510 }
28511 
28512 static int
hasInternalSubsetSplit(void * ctx)28513 hasInternalSubsetSplit(void *ctx)
28514 {
28515     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28516     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28517         (ctxt->user_sax->hasInternalSubset != NULL))
28518 	return(ctxt->user_sax->hasInternalSubset(ctxt->user_data));
28519     return(0);
28520 }
28521 
28522 static int
hasExternalSubsetSplit(void * ctx)28523 hasExternalSubsetSplit(void *ctx)
28524 {
28525     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28526     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28527         (ctxt->user_sax->hasExternalSubset != NULL))
28528 	return(ctxt->user_sax->hasExternalSubset(ctxt->user_data));
28529     return(0);
28530 }
28531 
28532 static void
externalSubsetSplit(void * ctx,const xmlChar * name,const xmlChar * ExternalID,const xmlChar * SystemID)28533 externalSubsetSplit(void *ctx, const xmlChar *name,
28534 	       const xmlChar *ExternalID, const xmlChar *SystemID)
28535 {
28536     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28537     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28538         (ctxt->user_sax->externalSubset != NULL))
28539 	ctxt->user_sax->externalSubset(ctxt->user_data, name, ExternalID,
28540 	                               SystemID);
28541 }
28542 
28543 static xmlParserInputPtr
resolveEntitySplit(void * ctx,const xmlChar * publicId,const xmlChar * systemId)28544 resolveEntitySplit(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
28545 {
28546     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28547     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28548         (ctxt->user_sax->resolveEntity != NULL))
28549 	return(ctxt->user_sax->resolveEntity(ctxt->user_data, publicId,
28550 	                                     systemId));
28551     return(NULL);
28552 }
28553 
28554 static xmlEntityPtr
getEntitySplit(void * ctx,const xmlChar * name)28555 getEntitySplit(void *ctx, const xmlChar *name)
28556 {
28557     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28558     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28559         (ctxt->user_sax->getEntity != NULL))
28560 	return(ctxt->user_sax->getEntity(ctxt->user_data, name));
28561     return(NULL);
28562 }
28563 
28564 static xmlEntityPtr
getParameterEntitySplit(void * ctx,const xmlChar * name)28565 getParameterEntitySplit(void *ctx, const xmlChar *name)
28566 {
28567     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28568     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28569         (ctxt->user_sax->getParameterEntity != NULL))
28570 	return(ctxt->user_sax->getParameterEntity(ctxt->user_data, name));
28571     return(NULL);
28572 }
28573 
28574 
28575 static void
entityDeclSplit(void * ctx,const xmlChar * name,int type,const xmlChar * publicId,const xmlChar * systemId,xmlChar * content)28576 entityDeclSplit(void *ctx, const xmlChar *name, int type,
28577           const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
28578 {
28579     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28580     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28581         (ctxt->user_sax->entityDecl != NULL))
28582 	ctxt->user_sax->entityDecl(ctxt->user_data, name, type, publicId,
28583 	                           systemId, content);
28584 }
28585 
28586 static void
attributeDeclSplit(void * ctx,const xmlChar * elem,const xmlChar * name,int type,int def,const xmlChar * defaultValue,xmlEnumerationPtr tree)28587 attributeDeclSplit(void *ctx, const xmlChar * elem,
28588                    const xmlChar * name, int type, int def,
28589                    const xmlChar * defaultValue, xmlEnumerationPtr tree)
28590 {
28591     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28592     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28593         (ctxt->user_sax->attributeDecl != NULL)) {
28594 	ctxt->user_sax->attributeDecl(ctxt->user_data, elem, name, type,
28595 	                              def, defaultValue, tree);
28596     } else {
28597 	xmlFreeEnumeration(tree);
28598     }
28599 }
28600 
28601 static void
elementDeclSplit(void * ctx,const xmlChar * name,int type,xmlElementContentPtr content)28602 elementDeclSplit(void *ctx, const xmlChar *name, int type,
28603 	    xmlElementContentPtr content)
28604 {
28605     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28606     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28607         (ctxt->user_sax->elementDecl != NULL))
28608 	ctxt->user_sax->elementDecl(ctxt->user_data, name, type, content);
28609 }
28610 
28611 static void
notationDeclSplit(void * ctx,const xmlChar * name,const xmlChar * publicId,const xmlChar * systemId)28612 notationDeclSplit(void *ctx, const xmlChar *name,
28613 	     const xmlChar *publicId, const xmlChar *systemId)
28614 {
28615     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28616     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28617         (ctxt->user_sax->notationDecl != NULL))
28618 	ctxt->user_sax->notationDecl(ctxt->user_data, name, publicId,
28619 	                             systemId);
28620 }
28621 
28622 static void
unparsedEntityDeclSplit(void * ctx,const xmlChar * name,const xmlChar * publicId,const xmlChar * systemId,const xmlChar * notationName)28623 unparsedEntityDeclSplit(void *ctx, const xmlChar *name,
28624 		   const xmlChar *publicId, const xmlChar *systemId,
28625 		   const xmlChar *notationName)
28626 {
28627     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28628     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28629         (ctxt->user_sax->unparsedEntityDecl != NULL))
28630 	ctxt->user_sax->unparsedEntityDecl(ctxt->user_data, name, publicId,
28631 	                                   systemId, notationName);
28632 }
28633 
28634 static void
setDocumentLocatorSplit(void * ctx,xmlSAXLocatorPtr loc)28635 setDocumentLocatorSplit(void *ctx, xmlSAXLocatorPtr loc)
28636 {
28637     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28638     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28639         (ctxt->user_sax->setDocumentLocator != NULL))
28640 	ctxt->user_sax->setDocumentLocator(ctxt->user_data, loc);
28641 }
28642 
28643 static void
startDocumentSplit(void * ctx)28644 startDocumentSplit(void *ctx)
28645 {
28646     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28647     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28648         (ctxt->user_sax->startDocument != NULL))
28649 	ctxt->user_sax->startDocument(ctxt->user_data);
28650 }
28651 
28652 static void
endDocumentSplit(void * ctx)28653 endDocumentSplit(void *ctx)
28654 {
28655     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28656     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28657         (ctxt->user_sax->endDocument != NULL))
28658 	ctxt->user_sax->endDocument(ctxt->user_data);
28659 }
28660 
28661 static void
processingInstructionSplit(void * ctx,const xmlChar * target,const xmlChar * data)28662 processingInstructionSplit(void *ctx, const xmlChar *target,
28663                       const xmlChar *data)
28664 {
28665     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28666     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28667         (ctxt->user_sax->processingInstruction != NULL))
28668 	ctxt->user_sax->processingInstruction(ctxt->user_data, target, data);
28669 }
28670 
28671 static void
commentSplit(void * ctx,const xmlChar * value)28672 commentSplit(void *ctx, const xmlChar *value)
28673 {
28674     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28675     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28676         (ctxt->user_sax->comment != NULL))
28677 	ctxt->user_sax->comment(ctxt->user_data, value);
28678 }
28679 
28680 /*
28681  * Varargs error callbacks to the user application, harder ...
28682  */
28683 
28684 static void XMLCDECL
warningSplit(void * ctx,const char * msg ATTRIBUTE_UNUSED,...)28685 warningSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28686     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28687     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28688         (ctxt->user_sax->warning != NULL)) {
28689 	TODO
28690     }
28691 }
28692 static void XMLCDECL
errorSplit(void * ctx,const char * msg ATTRIBUTE_UNUSED,...)28693 errorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28694     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28695     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28696         (ctxt->user_sax->error != NULL)) {
28697 	TODO
28698     }
28699 }
28700 static void XMLCDECL
fatalErrorSplit(void * ctx,const char * msg ATTRIBUTE_UNUSED,...)28701 fatalErrorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28702     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28703     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28704         (ctxt->user_sax->fatalError != NULL)) {
28705 	TODO
28706     }
28707 }
28708 
28709 /*
28710  * Those are function where both the user handler and the schemas handler
28711  * need to be called.
28712  */
28713 static void
charactersSplit(void * ctx,const xmlChar * ch,int len)28714 charactersSplit(void *ctx, const xmlChar *ch, int len)
28715 {
28716     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28717     if (ctxt == NULL)
28718         return;
28719     if ((ctxt->user_sax != NULL) && (ctxt->user_sax->characters != NULL))
28720 	ctxt->user_sax->characters(ctxt->user_data, ch, len);
28721     if (ctxt->ctxt != NULL)
28722 	xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
28723 }
28724 
28725 static void
ignorableWhitespaceSplit(void * ctx,const xmlChar * ch,int len)28726 ignorableWhitespaceSplit(void *ctx, const xmlChar *ch, int len)
28727 {
28728     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28729     if (ctxt == NULL)
28730         return;
28731     if ((ctxt->user_sax != NULL) &&
28732         (ctxt->user_sax->ignorableWhitespace != NULL))
28733 	ctxt->user_sax->ignorableWhitespace(ctxt->user_data, ch, len);
28734     if (ctxt->ctxt != NULL)
28735 	xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
28736 }
28737 
28738 static void
cdataBlockSplit(void * ctx,const xmlChar * value,int len)28739 cdataBlockSplit(void *ctx, const xmlChar *value, int len)
28740 {
28741     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28742     if (ctxt == NULL)
28743         return;
28744     if ((ctxt->user_sax != NULL) &&
28745         (ctxt->user_sax->cdataBlock != NULL))
28746 	ctxt->user_sax->cdataBlock(ctxt->user_data, value, len);
28747     if (ctxt->ctxt != NULL)
28748 	xmlSchemaSAXHandleCDataSection(ctxt->ctxt, value, len);
28749 }
28750 
28751 static void
referenceSplit(void * ctx,const xmlChar * name)28752 referenceSplit(void *ctx, const xmlChar *name)
28753 {
28754     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28755     if (ctxt == NULL)
28756         return;
28757     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28758         (ctxt->user_sax->reference != NULL))
28759 	ctxt->user_sax->reference(ctxt->user_data, name);
28760     if (ctxt->ctxt != NULL)
28761         xmlSchemaSAXHandleReference(ctxt->user_data, name);
28762 }
28763 
28764 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)28765 startElementNsSplit(void *ctx, const xmlChar * localname,
28766 		    const xmlChar * prefix, const xmlChar * URI,
28767 		    int nb_namespaces, const xmlChar ** namespaces,
28768 		    int nb_attributes, int nb_defaulted,
28769 		    const xmlChar ** attributes) {
28770     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28771     if (ctxt == NULL)
28772         return;
28773     if ((ctxt->user_sax != NULL) &&
28774         (ctxt->user_sax->startElementNs != NULL))
28775 	ctxt->user_sax->startElementNs(ctxt->user_data, localname, prefix,
28776 	                               URI, nb_namespaces, namespaces,
28777 				       nb_attributes, nb_defaulted,
28778 				       attributes);
28779     if (ctxt->ctxt != NULL)
28780 	xmlSchemaSAXHandleStartElementNs(ctxt->ctxt, localname, prefix,
28781 	                                 URI, nb_namespaces, namespaces,
28782 					 nb_attributes, nb_defaulted,
28783 					 attributes);
28784 }
28785 
28786 static void
endElementNsSplit(void * ctx,const xmlChar * localname,const xmlChar * prefix,const xmlChar * URI)28787 endElementNsSplit(void *ctx, const xmlChar * localname,
28788 		    const xmlChar * prefix, const xmlChar * URI) {
28789     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28790     if (ctxt == NULL)
28791         return;
28792     if ((ctxt->user_sax != NULL) &&
28793         (ctxt->user_sax->endElementNs != NULL))
28794 	ctxt->user_sax->endElementNs(ctxt->user_data, localname, prefix, URI);
28795     if (ctxt->ctxt != NULL)
28796 	xmlSchemaSAXHandleEndElementNs(ctxt->ctxt, localname, prefix, URI);
28797 }
28798 
28799 /**
28800  * xmlSchemaSAXPlug:
28801  * @ctxt:  a schema validation context
28802  * @sax:  a pointer to the original xmlSAXHandlerPtr
28803  * @user_data:  a pointer to the original SAX user data pointer
28804  *
28805  * Plug a SAX based validation layer in a SAX parsing event flow.
28806  * The original @saxptr and @dataptr data are replaced by new pointers
28807  * but the calls to the original will be maintained.
28808  *
28809  * Returns a pointer to a data structure needed to unplug the validation layer
28810  *         or NULL in case of errors.
28811  */
28812 xmlSchemaSAXPlugPtr
xmlSchemaSAXPlug(xmlSchemaValidCtxtPtr ctxt,xmlSAXHandlerPtr * sax,void ** user_data)28813 xmlSchemaSAXPlug(xmlSchemaValidCtxtPtr ctxt,
28814 		 xmlSAXHandlerPtr *sax, void **user_data)
28815 {
28816     xmlSchemaSAXPlugPtr ret;
28817     xmlSAXHandlerPtr old_sax;
28818 
28819     if ((ctxt == NULL) || (sax == NULL) || (user_data == NULL))
28820         return(NULL);
28821 
28822     /*
28823      * We only allow to plug into SAX2 event streams
28824      */
28825     old_sax = *sax;
28826     if ((old_sax != NULL) && (old_sax->initialized != XML_SAX2_MAGIC))
28827         return(NULL);
28828     if ((old_sax != NULL) &&
28829         (old_sax->startElementNs == NULL) && (old_sax->endElementNs == NULL) &&
28830         ((old_sax->startElement != NULL) || (old_sax->endElement != NULL)))
28831         return(NULL);
28832 
28833     /*
28834      * everything seems right allocate the local data needed for that layer
28835      */
28836     ret = (xmlSchemaSAXPlugPtr) xmlMalloc(sizeof(xmlSchemaSAXPlugStruct));
28837     if (ret == NULL) {
28838         return(NULL);
28839     }
28840     memset(ret, 0, sizeof(xmlSchemaSAXPlugStruct));
28841     ret->magic = XML_SAX_PLUG_MAGIC;
28842     ret->schemas_sax.initialized = XML_SAX2_MAGIC;
28843     ret->ctxt = ctxt;
28844     ret->user_sax_ptr = sax;
28845     ret->user_sax = old_sax;
28846     if (old_sax == NULL) {
28847         /*
28848 	 * go direct, no need for the split block and functions.
28849 	 */
28850 	ret->schemas_sax.startElementNs = xmlSchemaSAXHandleStartElementNs;
28851 	ret->schemas_sax.endElementNs = xmlSchemaSAXHandleEndElementNs;
28852 	/*
28853 	 * Note that we use the same text-function for both, to prevent
28854 	 * the parser from testing for ignorable whitespace.
28855 	 */
28856 	ret->schemas_sax.ignorableWhitespace = xmlSchemaSAXHandleText;
28857 	ret->schemas_sax.characters = xmlSchemaSAXHandleText;
28858 
28859 	ret->schemas_sax.cdataBlock = xmlSchemaSAXHandleCDataSection;
28860 	ret->schemas_sax.reference = xmlSchemaSAXHandleReference;
28861 
28862 	ret->user_data = ctxt;
28863 	*user_data = ctxt;
28864     } else {
28865        /*
28866         * for each callback unused by Schemas initialize it to the Split
28867 	* routine only if non NULL in the user block, this can speed up
28868 	* things at the SAX level.
28869 	*/
28870         if (old_sax->internalSubset != NULL)
28871             ret->schemas_sax.internalSubset = internalSubsetSplit;
28872         if (old_sax->isStandalone != NULL)
28873             ret->schemas_sax.isStandalone = isStandaloneSplit;
28874         if (old_sax->hasInternalSubset != NULL)
28875             ret->schemas_sax.hasInternalSubset = hasInternalSubsetSplit;
28876         if (old_sax->hasExternalSubset != NULL)
28877             ret->schemas_sax.hasExternalSubset = hasExternalSubsetSplit;
28878         if (old_sax->resolveEntity != NULL)
28879             ret->schemas_sax.resolveEntity = resolveEntitySplit;
28880         if (old_sax->getEntity != NULL)
28881             ret->schemas_sax.getEntity = getEntitySplit;
28882         if (old_sax->entityDecl != NULL)
28883             ret->schemas_sax.entityDecl = entityDeclSplit;
28884         if (old_sax->notationDecl != NULL)
28885             ret->schemas_sax.notationDecl = notationDeclSplit;
28886         if (old_sax->attributeDecl != NULL)
28887             ret->schemas_sax.attributeDecl = attributeDeclSplit;
28888         if (old_sax->elementDecl != NULL)
28889             ret->schemas_sax.elementDecl = elementDeclSplit;
28890         if (old_sax->unparsedEntityDecl != NULL)
28891             ret->schemas_sax.unparsedEntityDecl = unparsedEntityDeclSplit;
28892         if (old_sax->setDocumentLocator != NULL)
28893             ret->schemas_sax.setDocumentLocator = setDocumentLocatorSplit;
28894         if (old_sax->startDocument != NULL)
28895             ret->schemas_sax.startDocument = startDocumentSplit;
28896         if (old_sax->endDocument != NULL)
28897             ret->schemas_sax.endDocument = endDocumentSplit;
28898         if (old_sax->processingInstruction != NULL)
28899             ret->schemas_sax.processingInstruction = processingInstructionSplit;
28900         if (old_sax->comment != NULL)
28901             ret->schemas_sax.comment = commentSplit;
28902         if (old_sax->warning != NULL)
28903             ret->schemas_sax.warning = warningSplit;
28904         if (old_sax->error != NULL)
28905             ret->schemas_sax.error = errorSplit;
28906         if (old_sax->fatalError != NULL)
28907             ret->schemas_sax.fatalError = fatalErrorSplit;
28908         if (old_sax->getParameterEntity != NULL)
28909             ret->schemas_sax.getParameterEntity = getParameterEntitySplit;
28910         if (old_sax->externalSubset != NULL)
28911             ret->schemas_sax.externalSubset = externalSubsetSplit;
28912 
28913 	/*
28914 	 * the 6 schemas callback have to go to the splitter functions
28915 	 * Note that we use the same text-function for ignorableWhitespace
28916 	 * if possible, to prevent the parser from testing for ignorable
28917 	 * whitespace.
28918 	 */
28919         ret->schemas_sax.characters = charactersSplit;
28920 	if ((old_sax->ignorableWhitespace != NULL) &&
28921 	    (old_sax->ignorableWhitespace != old_sax->characters))
28922 	    ret->schemas_sax.ignorableWhitespace = ignorableWhitespaceSplit;
28923 	else
28924 	    ret->schemas_sax.ignorableWhitespace = charactersSplit;
28925         ret->schemas_sax.cdataBlock = cdataBlockSplit;
28926         ret->schemas_sax.reference = referenceSplit;
28927         ret->schemas_sax.startElementNs = startElementNsSplit;
28928         ret->schemas_sax.endElementNs = endElementNsSplit;
28929 
28930 	ret->user_data_ptr = user_data;
28931 	ret->user_data = *user_data;
28932 	*user_data = ret;
28933     }
28934 
28935     /*
28936      * plug the pointers back.
28937      */
28938     *sax = &(ret->schemas_sax);
28939     ctxt->sax = *sax;
28940     ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28941     xmlSchemaPreRun(ctxt);
28942     return(ret);
28943 }
28944 
28945 /**
28946  * xmlSchemaSAXUnplug:
28947  * @plug:  a data structure returned by xmlSchemaSAXPlug
28948  *
28949  * Unplug a SAX based validation layer in a SAX parsing event flow.
28950  * The original pointers used in the call are restored.
28951  *
28952  * Returns 0 in case of success and -1 in case of failure.
28953  */
28954 int
xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug)28955 xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug)
28956 {
28957     xmlSAXHandlerPtr *sax;
28958     void **user_data;
28959 
28960     if ((plug == NULL) || (plug->magic != XML_SAX_PLUG_MAGIC))
28961         return(-1);
28962     plug->magic = 0;
28963 
28964     xmlSchemaPostRun(plug->ctxt);
28965     /* restore the data */
28966     sax = plug->user_sax_ptr;
28967     *sax = plug->user_sax;
28968     if (plug->user_sax != NULL) {
28969 	user_data = plug->user_data_ptr;
28970 	*user_data = plug->user_data;
28971     }
28972 
28973     /* free and return */
28974     xmlFree(plug);
28975     return(0);
28976 }
28977 
28978 /**
28979  * xmlSchemaValidateSetLocator:
28980  * @vctxt: a schema validation context
28981  * @f: the locator function pointer
28982  * @ctxt: the locator context
28983  *
28984  * Allows to set a locator function to the validation context,
28985  * which will be used to provide file and line information since
28986  * those are not provided as part of the SAX validation flow
28987  * Setting @f to NULL disable the locator.
28988  */
28989 
28990 void
xmlSchemaValidateSetLocator(xmlSchemaValidCtxtPtr vctxt,xmlSchemaValidityLocatorFunc f,void * ctxt)28991 xmlSchemaValidateSetLocator(xmlSchemaValidCtxtPtr vctxt,
28992                             xmlSchemaValidityLocatorFunc f,
28993 			    void *ctxt)
28994 {
28995     if (vctxt == NULL) return;
28996     vctxt->locFunc = f;
28997     vctxt->locCtxt = ctxt;
28998 }
28999 
29000 /**
29001  * xmlSchemaValidateStreamLocator:
29002  * @ctx: the xmlTextReaderPtr used
29003  * @file: returned file information
29004  * @line: returned line information
29005  *
29006  * Internal locator function for the readers
29007  *
29008  * Returns 0 in case the Schema validation could be (de)activated and
29009  *         -1 in case of error.
29010  */
29011 static int
xmlSchemaValidateStreamLocator(void * ctx,const char ** file,unsigned long * line)29012 xmlSchemaValidateStreamLocator(void *ctx, const char **file,
29013                                unsigned long *line) {
29014     xmlParserCtxtPtr ctxt;
29015 
29016     if ((ctx == NULL) || ((file == NULL) && (line == NULL)))
29017         return(-1);
29018 
29019     if (file != NULL)
29020         *file = NULL;
29021     if (line != NULL)
29022         *line = 0;
29023 
29024     ctxt = (xmlParserCtxtPtr) ctx;
29025     if (ctxt->input != NULL) {
29026        if (file != NULL)
29027            *file = ctxt->input->filename;
29028        if (line != NULL)
29029            *line = ctxt->input->line;
29030        return(0);
29031     }
29032     return(-1);
29033 }
29034 
29035 /**
29036  * xmlSchemaValidateStream:
29037  * @ctxt:  a schema validation context
29038  * @input:  the input to use for reading the data
29039  * @enc:  an optional encoding information
29040  * @sax:  a SAX handler for the resulting events
29041  * @user_data:  the context to provide to the SAX handler.
29042  *
29043  * Validate an input based on a flow of SAX event from the parser
29044  * and forward the events to the @sax handler with the provided @user_data
29045  * the user provided @sax handler must be a SAX2 one.
29046  *
29047  * Returns 0 if the document is schemas valid, a positive error code
29048  *     number otherwise and -1 in case of internal or API error.
29049  */
29050 int
xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,xmlParserInputBufferPtr input,xmlCharEncoding enc,xmlSAXHandlerPtr sax,void * user_data)29051 xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
29052                         xmlParserInputBufferPtr input, xmlCharEncoding enc,
29053                         xmlSAXHandlerPtr sax, void *user_data)
29054 {
29055     xmlSchemaSAXPlugPtr plug = NULL;
29056     xmlSAXHandlerPtr old_sax = NULL;
29057     xmlParserCtxtPtr pctxt = NULL;
29058     xmlParserInputPtr inputStream = NULL;
29059     int ret;
29060 
29061     if ((ctxt == NULL) || (input == NULL))
29062         return (-1);
29063 
29064     /*
29065      * prepare the parser
29066      */
29067     pctxt = xmlNewParserCtxt();
29068     if (pctxt == NULL)
29069         return (-1);
29070     old_sax = pctxt->sax;
29071     pctxt->sax = sax;
29072     pctxt->userData = user_data;
29073 #if 0
29074     if (options)
29075         xmlCtxtUseOptions(pctxt, options);
29076 #endif
29077     pctxt->linenumbers = 1;
29078     xmlSchemaValidateSetLocator(ctxt, xmlSchemaValidateStreamLocator, pctxt);
29079 
29080     inputStream = xmlNewIOInputStream(pctxt, input, enc);;
29081     if (inputStream == NULL) {
29082         ret = -1;
29083 	goto done;
29084     }
29085     inputPush(pctxt, inputStream);
29086     ctxt->parserCtxt = pctxt;
29087     ctxt->input = input;
29088 
29089     /*
29090      * Plug the validation and launch the parsing
29091      */
29092     plug = xmlSchemaSAXPlug(ctxt, &(pctxt->sax), &(pctxt->userData));
29093     if (plug == NULL) {
29094         ret = -1;
29095 	goto done;
29096     }
29097     ctxt->input = input;
29098     ctxt->enc = enc;
29099     ctxt->sax = pctxt->sax;
29100     ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
29101     ret = xmlSchemaVStart(ctxt);
29102 
29103     if ((ret == 0) && (! ctxt->parserCtxt->wellFormed)) {
29104 	ret = ctxt->parserCtxt->errNo;
29105 	if (ret == 0)
29106 	    ret = 1;
29107     }
29108 
29109 done:
29110     ctxt->parserCtxt = NULL;
29111     ctxt->sax = NULL;
29112     ctxt->input = NULL;
29113     if (plug != NULL) {
29114         xmlSchemaSAXUnplug(plug);
29115     }
29116     /* cleanup */
29117     if (pctxt != NULL) {
29118 	pctxt->sax = old_sax;
29119 	xmlFreeParserCtxt(pctxt);
29120     }
29121     return (ret);
29122 }
29123 
29124 /**
29125  * xmlSchemaValidateFile:
29126  * @ctxt: a schema validation context
29127  * @filename: the URI of the instance
29128  * @options: a future set of options, currently unused
29129  *
29130  * Do a schemas validation of the given resource, it will use the
29131  * SAX streamable validation internally.
29132  *
29133  * Returns 0 if the document is valid, a positive error code
29134  *     number otherwise and -1 in case of an internal or API error.
29135  */
29136 int
xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt,const char * filename,int options ATTRIBUTE_UNUSED)29137 xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt,
29138                       const char * filename,
29139 		      int options ATTRIBUTE_UNUSED)
29140 {
29141     int ret;
29142     xmlParserInputBufferPtr input;
29143 
29144     if ((ctxt == NULL) || (filename == NULL))
29145         return (-1);
29146 
29147     input = xmlParserInputBufferCreateFilename(filename,
29148 	XML_CHAR_ENCODING_NONE);
29149     if (input == NULL)
29150 	return (-1);
29151     ret = xmlSchemaValidateStream(ctxt, input, XML_CHAR_ENCODING_NONE,
29152 	NULL, NULL);
29153     return (ret);
29154 }
29155 
29156 /**
29157  * xmlSchemaValidCtxtGetParserCtxt:
29158  * @ctxt: a schema validation context
29159  *
29160  * allow access to the parser context of the schema validation context
29161  *
29162  * Returns the parser context of the schema validation context or NULL
29163  *         in case of error.
29164  */
29165 xmlParserCtxtPtr
xmlSchemaValidCtxtGetParserCtxt(xmlSchemaValidCtxtPtr ctxt)29166 xmlSchemaValidCtxtGetParserCtxt(xmlSchemaValidCtxtPtr ctxt)
29167 {
29168     if (ctxt == NULL)
29169         return(NULL);
29170     return (ctxt->parserCtxt);
29171 }
29172 
29173 #endif /* LIBXML_SCHEMAS_ENABLED */
29174