• 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  *   - Elimated item creation for: <restriction>, <extension>,
26  *     <simpleContent>, <complexContent>, <list>, <union>
27  *
28  * PROBLEMS:
29  *   - http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0337.html
30  *     IDC XPath expression and chameleon includes: the targetNamespace is changed, so
31  *     XPath will have trouble to resolve to this namespace, since not known.
32  *
33  *
34  * CONSTRAINTS:
35  *
36  * Schema Component Constraint:
37  *   All Group Limited (cos-all-limited)
38  *   Status: complete
39  *   (1.2)
40  *     In xmlSchemaGroupDefReferenceTermFixup() and
41  *   (2)
42  *     In xmlSchemaParseModelGroup()
43  *     TODO: Actually this should go to component-level checks,
44  *     but is done here due to performance. Move it to an other layer
45  *     is schema construction via an API is implemented.
46  */
47 
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 };
864 
865 /*
866 * Element info flags.
867 */
868 #define XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES  1<<0
869 #define XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES 1<<1
870 #define XML_SCHEMA_ELEM_INFO_NILLED	       1<<2
871 #define XML_SCHEMA_ELEM_INFO_LOCAL_TYPE	       1<<3
872 
873 #define XML_SCHEMA_NODE_INFO_VALUE_NEEDED      1<<4
874 #define XML_SCHEMA_ELEM_INFO_EMPTY             1<<5
875 #define XML_SCHEMA_ELEM_INFO_HAS_CONTENT       1<<6
876 
877 #define XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT  1<<7
878 #define XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT  1<<8
879 #define XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED  1<<9
880 #define XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE  1<<10
881 
882 /**
883  * xmlSchemaNodeInfo:
884  *
885  * Holds information of an element node.
886  */
887 struct _xmlSchemaNodeInfo {
888     int nodeType;
889     xmlNodePtr node;
890     int nodeLine;
891     const xmlChar *localName;
892     const xmlChar *nsName;
893     const xmlChar *value;
894     xmlSchemaValPtr val; /* the pre-computed value if any */
895     xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
896 
897     int flags; /* combination of node info flags */
898 
899     int valNeeded;
900     int normVal;
901 
902     xmlSchemaElementPtr decl; /* the element/attribute declaration */
903     int depth;
904     xmlSchemaPSVIIDCBindingPtr idcTable; /* the table of PSVI IDC bindings
905                                             for the scope element*/
906     xmlSchemaIDCMatcherPtr idcMatchers; /* the IDC matchers for the scope
907                                            element */
908     xmlRegExecCtxtPtr regexCtxt;
909 
910     const xmlChar **nsBindings; /* Namespace bindings on this element */
911     int nbNsBindings;
912     int sizeNsBindings;
913 
914     int hasKeyrefs;
915     int appliedXPath; /* Indicates that an XPath has been applied. */
916 };
917 
918 #define XML_SCHEMAS_ATTR_UNKNOWN 1
919 #define XML_SCHEMAS_ATTR_ASSESSED 2
920 #define XML_SCHEMAS_ATTR_PROHIBITED 3
921 #define XML_SCHEMAS_ATTR_ERR_MISSING 4
922 #define XML_SCHEMAS_ATTR_INVALID_VALUE 5
923 #define XML_SCHEMAS_ATTR_ERR_NO_TYPE 6
924 #define XML_SCHEMAS_ATTR_ERR_FIXED_VALUE 7
925 #define XML_SCHEMAS_ATTR_DEFAULT 8
926 #define XML_SCHEMAS_ATTR_VALIDATE_VALUE 9
927 #define XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL 10
928 #define XML_SCHEMAS_ATTR_HAS_ATTR_USE 11
929 #define XML_SCHEMAS_ATTR_HAS_ATTR_DECL 12
930 #define XML_SCHEMAS_ATTR_WILD_SKIP 13
931 #define XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL 14
932 #define XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID 15
933 #define XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID 16
934 #define XML_SCHEMAS_ATTR_META 17
935 /*
936 * @metaType values of xmlSchemaAttrInfo.
937 */
938 #define XML_SCHEMA_ATTR_INFO_META_XSI_TYPE 1
939 #define XML_SCHEMA_ATTR_INFO_META_XSI_NIL 2
940 #define XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC 3
941 #define XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC 4
942 #define XML_SCHEMA_ATTR_INFO_META_XMLNS 5
943 
944 typedef struct _xmlSchemaAttrInfo xmlSchemaAttrInfo;
945 typedef xmlSchemaAttrInfo *xmlSchemaAttrInfoPtr;
946 struct _xmlSchemaAttrInfo {
947     int nodeType;
948     xmlNodePtr node;
949     int nodeLine;
950     const xmlChar *localName;
951     const xmlChar *nsName;
952     const xmlChar *value;
953     xmlSchemaValPtr val; /* the pre-computed value if any */
954     xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
955     int flags; /* combination of node info flags */
956 
957     xmlSchemaAttributePtr decl; /* the attribute declaration */
958     xmlSchemaAttributeUsePtr use;  /* the attribute use */
959     int state;
960     int metaType;
961     const xmlChar *vcValue; /* the value constraint value */
962     xmlSchemaNodeInfoPtr parent;
963 };
964 
965 
966 #define XML_SCHEMA_VALID_CTXT_FLAG_STREAM 1
967 /**
968  * xmlSchemaValidCtxt:
969  *
970  * A Schemas validation context
971  */
972 struct _xmlSchemaValidCtxt {
973     int type;
974     void *errCtxt;             /* user specific data block */
975     xmlSchemaValidityErrorFunc error;   /* the callback in case of errors */
976     xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
977     xmlStructuredErrorFunc serror;
978 
979     xmlSchemaPtr schema;        /* The schema in use */
980     xmlDocPtr doc;
981     xmlParserInputBufferPtr input;
982     xmlCharEncoding enc;
983     xmlSAXHandlerPtr sax;
984     xmlParserCtxtPtr parserCtxt;
985     void *user_data; /* TODO: What is this for? */
986     char *filename;
987 
988     int err;
989     int nberrors;
990 
991     xmlNodePtr node;
992     xmlNodePtr cur;
993     /* xmlSchemaTypePtr type; */
994 
995     xmlRegExecCtxtPtr regexp;
996     xmlSchemaValPtr value;
997 
998     int valueWS;
999     int options;
1000     xmlNodePtr validationRoot;
1001     xmlSchemaParserCtxtPtr pctxt;
1002     int xsiAssemble;
1003 
1004     int depth;
1005     xmlSchemaNodeInfoPtr *elemInfos; /* array of element informations */
1006     int sizeElemInfos;
1007     xmlSchemaNodeInfoPtr inode; /* the current element information */
1008 
1009     xmlSchemaIDCAugPtr aidcs; /* a list of augmented IDC informations */
1010 
1011     xmlSchemaIDCStateObjPtr xpathStates; /* first active state object. */
1012     xmlSchemaIDCStateObjPtr xpathStatePool; /* first stored state object. */
1013     xmlSchemaIDCMatcherPtr idcMatcherCache; /* Cache for IDC matcher objects. */
1014 
1015     xmlSchemaPSVIIDCNodePtr *idcNodes; /* list of all IDC node-table entries*/
1016     int nbIdcNodes;
1017     int sizeIdcNodes;
1018 
1019     xmlSchemaPSVIIDCKeyPtr *idcKeys; /* list of all IDC node-table entries */
1020     int nbIdcKeys;
1021     int sizeIdcKeys;
1022 
1023     int flags;
1024 
1025     xmlDictPtr dict;
1026 
1027 #ifdef LIBXML_READER_ENABLED
1028     xmlTextReaderPtr reader;
1029 #endif
1030 
1031     xmlSchemaAttrInfoPtr *attrInfos;
1032     int nbAttrInfos;
1033     int sizeAttrInfos;
1034 
1035     int skipDepth;
1036     xmlSchemaItemListPtr nodeQNames;
1037     int hasKeyrefs;
1038     int createIDCNodeTables;
1039     int psviExposeIDCNodeTables;
1040 
1041     /* Locator for error reporting in streaming mode */
1042     xmlSchemaValidityLocatorFunc locFunc;
1043     void *locCtxt;
1044 };
1045 
1046 /**
1047  * xmlSchemaSubstGroup:
1048  *
1049  *
1050  */
1051 typedef struct _xmlSchemaSubstGroup xmlSchemaSubstGroup;
1052 typedef xmlSchemaSubstGroup *xmlSchemaSubstGroupPtr;
1053 struct _xmlSchemaSubstGroup {
1054     xmlSchemaElementPtr head;
1055     xmlSchemaItemListPtr members;
1056 };
1057 
1058 /************************************************************************
1059  *									*
1060  *			Some predeclarations				*
1061  *									*
1062  ************************************************************************/
1063 
1064 static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
1065                                  xmlSchemaPtr schema,
1066                                  xmlNodePtr node);
1067 static int xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr ctxt,
1068                                  xmlSchemaPtr schema,
1069                                  xmlNodePtr node);
1070 static int
1071 xmlSchemaTypeFixup(xmlSchemaTypePtr type,
1072                    xmlSchemaAbstractCtxtPtr ctxt);
1073 static const xmlChar *
1074 xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
1075 static int
1076 xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1077                      xmlNodePtr node);
1078 static int
1079 xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
1080                        xmlSchemaParserCtxtPtr ctxt);
1081 static void
1082 xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt);
1083 static xmlSchemaWhitespaceValueType
1084 xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type);
1085 static xmlSchemaTreeItemPtr
1086 xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1087 			 xmlNodePtr node, xmlSchemaTypeType type,
1088 			 int withParticle);
1089 static const xmlChar *
1090 xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item);
1091 static xmlSchemaTypeLinkPtr
1092 xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type);
1093 static void
1094 xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
1095 		     const char *funcName,
1096 		     const char *message) LIBXML_ATTR_FORMAT(3,0);
1097 static int
1098 xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr ctxt,
1099 			     xmlSchemaTypePtr type,
1100 			     xmlSchemaTypePtr baseType,
1101 			     int subset);
1102 static void
1103 xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
1104 				   xmlSchemaParserCtxtPtr ctxt);
1105 static void
1106 xmlSchemaComponentListFree(xmlSchemaItemListPtr list);
1107 static xmlSchemaQNameRefPtr
1108 xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,
1109 				xmlSchemaPtr schema,
1110 				xmlNodePtr node);
1111 
1112 /************************************************************************
1113  *									*
1114  *			Helper functions			        *
1115  *									*
1116  ************************************************************************/
1117 
1118 /**
1119  * xmlSchemaItemTypeToStr:
1120  * @type: the type of the schema item
1121  *
1122  * Returns the component name of a schema item.
1123  */
1124 static const xmlChar *
xmlSchemaItemTypeToStr(xmlSchemaTypeType type)1125 xmlSchemaItemTypeToStr(xmlSchemaTypeType type)
1126 {
1127     switch (type) {
1128 	case XML_SCHEMA_TYPE_BASIC:
1129 	    return(BAD_CAST "simple type definition");
1130 	case XML_SCHEMA_TYPE_SIMPLE:
1131 	    return(BAD_CAST "simple type definition");
1132 	case XML_SCHEMA_TYPE_COMPLEX:
1133 	    return(BAD_CAST "complex type definition");
1134 	case XML_SCHEMA_TYPE_ELEMENT:
1135 	    return(BAD_CAST "element declaration");
1136 	case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1137 	    return(BAD_CAST "attribute use");
1138 	case XML_SCHEMA_TYPE_ATTRIBUTE:
1139 	    return(BAD_CAST "attribute declaration");
1140 	case XML_SCHEMA_TYPE_GROUP:
1141 	    return(BAD_CAST "model group definition");
1142 	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1143 	    return(BAD_CAST "attribute group definition");
1144 	case XML_SCHEMA_TYPE_NOTATION:
1145 	    return(BAD_CAST "notation declaration");
1146 	case XML_SCHEMA_TYPE_SEQUENCE:
1147 	    return(BAD_CAST "model group (sequence)");
1148 	case XML_SCHEMA_TYPE_CHOICE:
1149 	    return(BAD_CAST "model group (choice)");
1150 	case XML_SCHEMA_TYPE_ALL:
1151 	    return(BAD_CAST "model group (all)");
1152 	case XML_SCHEMA_TYPE_PARTICLE:
1153 	    return(BAD_CAST "particle");
1154 	case XML_SCHEMA_TYPE_IDC_UNIQUE:
1155 	    return(BAD_CAST "unique identity-constraint");
1156 	    /* return(BAD_CAST "IDC (unique)"); */
1157 	case XML_SCHEMA_TYPE_IDC_KEY:
1158 	    return(BAD_CAST "key identity-constraint");
1159 	    /* return(BAD_CAST "IDC (key)"); */
1160 	case XML_SCHEMA_TYPE_IDC_KEYREF:
1161 	    return(BAD_CAST "keyref identity-constraint");
1162 	    /* return(BAD_CAST "IDC (keyref)"); */
1163 	case XML_SCHEMA_TYPE_ANY:
1164 	    return(BAD_CAST "wildcard (any)");
1165 	case XML_SCHEMA_EXTRA_QNAMEREF:
1166 	    return(BAD_CAST "[helper component] QName reference");
1167 	case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
1168 	    return(BAD_CAST "[helper component] attribute use prohibition");
1169 	default:
1170 	    return(BAD_CAST "Not a schema component");
1171     }
1172 }
1173 
1174 /**
1175  * xmlSchemaGetComponentTypeStr:
1176  * @type: the type of the schema item
1177  *
1178  * Returns the component name of a schema item.
1179  */
1180 static const xmlChar *
xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item)1181 xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item)
1182 {
1183     switch (item->type) {
1184 	case XML_SCHEMA_TYPE_BASIC:
1185 	    if (WXS_IS_COMPLEX(WXS_TYPE_CAST item))
1186 		return(BAD_CAST "complex type definition");
1187 	    else
1188 		return(BAD_CAST "simple type definition");
1189 	default:
1190 	    return(xmlSchemaItemTypeToStr(item->type));
1191     }
1192 }
1193 
1194 /**
1195  * xmlSchemaGetComponentNode:
1196  * @item: a schema component
1197  *
1198  * Returns node associated with the schema component.
1199  * NOTE that such a node need not be available; plus, a component's
1200  * node need not to reflect the component directly, since there is no
1201  * one-to-one relationship between the XML Schema representation and
1202  * the component representation.
1203  */
1204 static xmlNodePtr
xmlSchemaGetComponentNode(xmlSchemaBasicItemPtr item)1205 xmlSchemaGetComponentNode(xmlSchemaBasicItemPtr item)
1206 {
1207     switch (item->type) {
1208 	case XML_SCHEMA_TYPE_ELEMENT:
1209 	    return (((xmlSchemaElementPtr) item)->node);
1210 	case XML_SCHEMA_TYPE_ATTRIBUTE:
1211 	    return (((xmlSchemaAttributePtr) item)->node);
1212 	case XML_SCHEMA_TYPE_COMPLEX:
1213 	case XML_SCHEMA_TYPE_SIMPLE:
1214 	    return (((xmlSchemaTypePtr) item)->node);
1215 	case XML_SCHEMA_TYPE_ANY:
1216 	case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1217 	    return (((xmlSchemaWildcardPtr) item)->node);
1218 	case XML_SCHEMA_TYPE_PARTICLE:
1219 	    return (((xmlSchemaParticlePtr) item)->node);
1220 	case XML_SCHEMA_TYPE_SEQUENCE:
1221 	case XML_SCHEMA_TYPE_CHOICE:
1222 	case XML_SCHEMA_TYPE_ALL:
1223 	    return (((xmlSchemaModelGroupPtr) item)->node);
1224 	case XML_SCHEMA_TYPE_GROUP:
1225 	    return (((xmlSchemaModelGroupDefPtr) item)->node);
1226 	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1227 	    return (((xmlSchemaAttributeGroupPtr) item)->node);
1228 	case XML_SCHEMA_TYPE_IDC_UNIQUE:
1229 	case XML_SCHEMA_TYPE_IDC_KEY:
1230 	case XML_SCHEMA_TYPE_IDC_KEYREF:
1231 	    return (((xmlSchemaIDCPtr) item)->node);
1232 	case XML_SCHEMA_EXTRA_QNAMEREF:
1233 	    return(((xmlSchemaQNameRefPtr) item)->node);
1234 	/* TODO: What to do with NOTATIONs?
1235 	case XML_SCHEMA_TYPE_NOTATION:
1236 	    return (((xmlSchemaNotationPtr) item)->node);
1237 	*/
1238 	case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1239 	    return (((xmlSchemaAttributeUsePtr) item)->node);
1240 	default:
1241 	    return (NULL);
1242     }
1243 }
1244 
1245 #if 0
1246 /**
1247  * xmlSchemaGetNextComponent:
1248  * @item: a schema component
1249  *
1250  * Returns the next sibling of the schema component.
1251  */
1252 static xmlSchemaBasicItemPtr
1253 xmlSchemaGetNextComponent(xmlSchemaBasicItemPtr item)
1254 {
1255     switch (item->type) {
1256 	case XML_SCHEMA_TYPE_ELEMENT:
1257 	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaElementPtr) item)->next);
1258 	case XML_SCHEMA_TYPE_ATTRIBUTE:
1259 	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributePtr) item)->next);
1260 	case XML_SCHEMA_TYPE_COMPLEX:
1261 	case XML_SCHEMA_TYPE_SIMPLE:
1262 	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaTypePtr) item)->next);
1263 	case XML_SCHEMA_TYPE_ANY:
1264 	case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1265 	    return (NULL);
1266 	case XML_SCHEMA_TYPE_PARTICLE:
1267 	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaParticlePtr) item)->next);
1268 	case XML_SCHEMA_TYPE_SEQUENCE:
1269 	case XML_SCHEMA_TYPE_CHOICE:
1270 	case XML_SCHEMA_TYPE_ALL:
1271 	    return (NULL);
1272 	case XML_SCHEMA_TYPE_GROUP:
1273 	    return (NULL);
1274 	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1275 	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributeGroupPtr) item)->next);
1276 	case XML_SCHEMA_TYPE_IDC_UNIQUE:
1277 	case XML_SCHEMA_TYPE_IDC_KEY:
1278 	case XML_SCHEMA_TYPE_IDC_KEYREF:
1279 	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaIDCPtr) item)->next);
1280 	default:
1281 	    return (NULL);
1282     }
1283 }
1284 #endif
1285 
1286 
1287 /**
1288  * xmlSchemaFormatQName:
1289  * @buf: the string buffer
1290  * @namespaceName:  the namespace name
1291  * @localName: the local name
1292  *
1293  * Returns the given QName in the format "{namespaceName}localName" or
1294  * just "localName" if @namespaceName is NULL.
1295  *
1296  * Returns the localName if @namespaceName is NULL, a formatted
1297  * string otherwise.
1298  */
1299 static const xmlChar*
xmlSchemaFormatQName(xmlChar ** buf,const xmlChar * namespaceName,const xmlChar * localName)1300 xmlSchemaFormatQName(xmlChar **buf,
1301 		     const xmlChar *namespaceName,
1302 		     const xmlChar *localName)
1303 {
1304     FREE_AND_NULL(*buf)
1305     if (namespaceName != NULL) {
1306 	*buf = xmlStrdup(BAD_CAST "{");
1307 	*buf = xmlStrcat(*buf, namespaceName);
1308 	*buf = xmlStrcat(*buf, BAD_CAST "}");
1309     }
1310     if (localName != NULL) {
1311 	if (namespaceName == NULL)
1312 	    return(localName);
1313 	*buf = xmlStrcat(*buf, localName);
1314     } else {
1315 	*buf = xmlStrcat(*buf, BAD_CAST "(NULL)");
1316     }
1317     return ((const xmlChar *) *buf);
1318 }
1319 
1320 static const xmlChar*
xmlSchemaFormatQNameNs(xmlChar ** buf,xmlNsPtr ns,const xmlChar * localName)1321 xmlSchemaFormatQNameNs(xmlChar **buf, xmlNsPtr ns, const xmlChar *localName)
1322 {
1323     if (ns != NULL)
1324 	return (xmlSchemaFormatQName(buf, ns->href, localName));
1325     else
1326 	return (xmlSchemaFormatQName(buf, NULL, localName));
1327 }
1328 
1329 static const xmlChar *
xmlSchemaGetComponentName(xmlSchemaBasicItemPtr item)1330 xmlSchemaGetComponentName(xmlSchemaBasicItemPtr item)
1331 {
1332     switch (item->type) {
1333 	case XML_SCHEMA_TYPE_ELEMENT:
1334 	    return (((xmlSchemaElementPtr) item)->name);
1335 	case XML_SCHEMA_TYPE_ATTRIBUTE:
1336 	    return (((xmlSchemaAttributePtr) item)->name);
1337 	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1338 	    return (((xmlSchemaAttributeGroupPtr) item)->name);
1339 	case XML_SCHEMA_TYPE_BASIC:
1340 	case XML_SCHEMA_TYPE_SIMPLE:
1341 	case XML_SCHEMA_TYPE_COMPLEX:
1342 	    return (((xmlSchemaTypePtr) item)->name);
1343 	case XML_SCHEMA_TYPE_GROUP:
1344 	    return (((xmlSchemaModelGroupDefPtr) item)->name);
1345 	case XML_SCHEMA_TYPE_IDC_KEY:
1346 	case XML_SCHEMA_TYPE_IDC_UNIQUE:
1347 	case XML_SCHEMA_TYPE_IDC_KEYREF:
1348 	    return (((xmlSchemaIDCPtr) item)->name);
1349 	case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1350 	    if (WXS_ATTRUSE_DECL(item) != NULL) {
1351 		return(xmlSchemaGetComponentName(
1352 		    WXS_BASIC_CAST WXS_ATTRUSE_DECL(item)));
1353 	    } else
1354 		return(NULL);
1355 	case XML_SCHEMA_EXTRA_QNAMEREF:
1356 	    return (((xmlSchemaQNameRefPtr) item)->name);
1357 	case XML_SCHEMA_TYPE_NOTATION:
1358 	    return (((xmlSchemaNotationPtr) item)->name);
1359 	default:
1360 	    /*
1361 	    * Other components cannot have names.
1362 	    */
1363 	    break;
1364     }
1365     return (NULL);
1366 }
1367 
1368 #define xmlSchemaGetQNameRefName(r) (WXS_QNAME_CAST (r))->name
1369 #define xmlSchemaGetQNameRefTargetNs(r) (WXS_QNAME_CAST (r))->targetNamespace
1370 /*
1371 static const xmlChar *
1372 xmlSchemaGetQNameRefName(void *ref)
1373 {
1374     return(((xmlSchemaQNameRefPtr) ref)->name);
1375 }
1376 
1377 static const xmlChar *
1378 xmlSchemaGetQNameRefTargetNs(void *ref)
1379 {
1380     return(((xmlSchemaQNameRefPtr) ref)->targetNamespace);
1381 }
1382 */
1383 
1384 static const xmlChar *
xmlSchemaGetComponentTargetNs(xmlSchemaBasicItemPtr item)1385 xmlSchemaGetComponentTargetNs(xmlSchemaBasicItemPtr item)
1386 {
1387     switch (item->type) {
1388 	case XML_SCHEMA_TYPE_ELEMENT:
1389 	    return (((xmlSchemaElementPtr) item)->targetNamespace);
1390 	case XML_SCHEMA_TYPE_ATTRIBUTE:
1391 	    return (((xmlSchemaAttributePtr) item)->targetNamespace);
1392 	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1393 	    return (((xmlSchemaAttributeGroupPtr) item)->targetNamespace);
1394 	case XML_SCHEMA_TYPE_BASIC:
1395 	    return (BAD_CAST "http://www.w3.org/2001/XMLSchema");
1396 	case XML_SCHEMA_TYPE_SIMPLE:
1397 	case XML_SCHEMA_TYPE_COMPLEX:
1398 	    return (((xmlSchemaTypePtr) item)->targetNamespace);
1399 	case XML_SCHEMA_TYPE_GROUP:
1400 	    return (((xmlSchemaModelGroupDefPtr) item)->targetNamespace);
1401 	case XML_SCHEMA_TYPE_IDC_KEY:
1402 	case XML_SCHEMA_TYPE_IDC_UNIQUE:
1403 	case XML_SCHEMA_TYPE_IDC_KEYREF:
1404 	    return (((xmlSchemaIDCPtr) item)->targetNamespace);
1405 	case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1406 	    if (WXS_ATTRUSE_DECL(item) != NULL) {
1407 		return(xmlSchemaGetComponentTargetNs(
1408 		    WXS_BASIC_CAST WXS_ATTRUSE_DECL(item)));
1409 	    }
1410 	    /* TODO: Will returning NULL break something? */
1411 	    break;
1412 	case XML_SCHEMA_EXTRA_QNAMEREF:
1413 	    return (((xmlSchemaQNameRefPtr) item)->targetNamespace);
1414 	case XML_SCHEMA_TYPE_NOTATION:
1415 	    return (((xmlSchemaNotationPtr) item)->targetNamespace);
1416 	default:
1417 	    /*
1418 	    * Other components cannot have names.
1419 	    */
1420 	    break;
1421     }
1422     return (NULL);
1423 }
1424 
1425 static const xmlChar*
xmlSchemaGetComponentQName(xmlChar ** buf,void * item)1426 xmlSchemaGetComponentQName(xmlChar **buf,
1427 			   void *item)
1428 {
1429     return (xmlSchemaFormatQName(buf,
1430 	xmlSchemaGetComponentTargetNs((xmlSchemaBasicItemPtr) item),
1431 	xmlSchemaGetComponentName((xmlSchemaBasicItemPtr) item)));
1432 }
1433 
1434 static const xmlChar*
xmlSchemaGetComponentDesignation(xmlChar ** buf,void * item)1435 xmlSchemaGetComponentDesignation(xmlChar **buf, void *item)
1436 {
1437     xmlChar *str = NULL;
1438 
1439     *buf = xmlStrcat(*buf, WXS_ITEM_TYPE_NAME(item));
1440     *buf = xmlStrcat(*buf, BAD_CAST " '");
1441     *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str,
1442 	(xmlSchemaBasicItemPtr) item));
1443     *buf = xmlStrcat(*buf, BAD_CAST "'");
1444     FREE_AND_NULL(str);
1445     return(*buf);
1446 }
1447 
1448 static const xmlChar*
xmlSchemaGetIDCDesignation(xmlChar ** buf,xmlSchemaIDCPtr idc)1449 xmlSchemaGetIDCDesignation(xmlChar **buf, xmlSchemaIDCPtr idc)
1450 {
1451     return(xmlSchemaGetComponentDesignation(buf, idc));
1452 }
1453 
1454 /**
1455  * xmlSchemaWildcardPCToString:
1456  * @pc: the type of processContents
1457  *
1458  * Returns a string representation of the type of
1459  * processContents.
1460  */
1461 static const xmlChar *
xmlSchemaWildcardPCToString(int pc)1462 xmlSchemaWildcardPCToString(int pc)
1463 {
1464     switch (pc) {
1465 	case XML_SCHEMAS_ANY_SKIP:
1466 	    return (BAD_CAST "skip");
1467 	case XML_SCHEMAS_ANY_LAX:
1468 	    return (BAD_CAST "lax");
1469 	case XML_SCHEMAS_ANY_STRICT:
1470 	    return (BAD_CAST "strict");
1471 	default:
1472 	    return (BAD_CAST "invalid process contents");
1473     }
1474 }
1475 
1476 /**
1477  * xmlSchemaGetCanonValueWhtspExt:
1478  * @val: the precomputed value
1479  * @retValue: the returned value
1480  * @ws: the whitespace type of the value
1481  *
1482  * Get a the canonical representation of the value.
1483  * The caller has to free the returned retValue.
1484  *
1485  * Returns 0 if the value could be built and -1 in case of
1486  *         API errors or if the value type is not supported yet.
1487  */
1488 static int
xmlSchemaGetCanonValueWhtspExt(xmlSchemaValPtr val,xmlSchemaWhitespaceValueType ws,xmlChar ** retValue)1489 xmlSchemaGetCanonValueWhtspExt(xmlSchemaValPtr val,
1490 			       xmlSchemaWhitespaceValueType ws,
1491 			       xmlChar **retValue)
1492 {
1493     int list;
1494     xmlSchemaValType valType;
1495     const xmlChar *value, *value2 = NULL;
1496 
1497 
1498     if ((retValue == NULL) || (val == NULL))
1499 	return (-1);
1500     list = xmlSchemaValueGetNext(val) ? 1 : 0;
1501     *retValue = NULL;
1502     do {
1503 	value = NULL;
1504 	valType = xmlSchemaGetValType(val);
1505 	switch (valType) {
1506 	    case XML_SCHEMAS_STRING:
1507 	    case XML_SCHEMAS_NORMSTRING:
1508 	    case XML_SCHEMAS_ANYSIMPLETYPE:
1509 		value = xmlSchemaValueGetAsString(val);
1510 		if (value != NULL) {
1511 		    if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
1512 			value2 = xmlSchemaCollapseString(value);
1513 		    else if (ws == XML_SCHEMA_WHITESPACE_REPLACE)
1514 			value2 = xmlSchemaWhiteSpaceReplace(value);
1515 		    if (value2 != NULL)
1516 			value = value2;
1517 		}
1518 		break;
1519 	    default:
1520 		if (xmlSchemaGetCanonValue(val, &value2) == -1) {
1521 		    if (value2 != NULL)
1522 			xmlFree((xmlChar *) value2);
1523 		    goto internal_error;
1524 		}
1525 		value = value2;
1526 	}
1527 	if (*retValue == NULL)
1528 	    if (value == NULL) {
1529 		if (! list)
1530 		    *retValue = xmlStrdup(BAD_CAST "");
1531 	    } else
1532 		*retValue = xmlStrdup(value);
1533 	else if (value != NULL) {
1534 	    /* List. */
1535 	    *retValue = xmlStrcat((xmlChar *) *retValue, BAD_CAST " ");
1536 	    *retValue = xmlStrcat((xmlChar *) *retValue, value);
1537 	}
1538 	FREE_AND_NULL(value2)
1539 	val = xmlSchemaValueGetNext(val);
1540     } while (val != NULL);
1541 
1542     return (0);
1543 internal_error:
1544     if (*retValue != NULL)
1545 	xmlFree((xmlChar *) (*retValue));
1546     if (value2 != NULL)
1547 	xmlFree((xmlChar *) value2);
1548     return (-1);
1549 }
1550 
1551 /**
1552  * xmlSchemaFormatItemForReport:
1553  * @buf: the string buffer
1554  * @itemDes: the designation of the item
1555  * @itemName: the name of the item
1556  * @item: the item as an object
1557  * @itemNode: the node of the item
1558  * @local: the local name
1559  * @parsing: if the function is used during the parse
1560  *
1561  * Returns a representation of the given item used
1562  * for error reports.
1563  *
1564  * The following order is used to build the resulting
1565  * designation if the arguments are not NULL:
1566  * 1a. If itemDes not NULL -> itemDes
1567  * 1b. If (itemDes not NULL) and (itemName not NULL)
1568  *     -> itemDes + itemName
1569  * 2. If the preceding was NULL and (item not NULL) -> item
1570  * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
1571  *
1572  * If the itemNode is an attribute node, the name of the attribute
1573  * will be appended to the result.
1574  *
1575  * Returns the formatted string and sets @buf to the resulting value.
1576  */
1577 static xmlChar*
xmlSchemaFormatItemForReport(xmlChar ** buf,const xmlChar * itemDes,xmlSchemaBasicItemPtr item,xmlNodePtr itemNode)1578 xmlSchemaFormatItemForReport(xmlChar **buf,
1579 		     const xmlChar *itemDes,
1580 		     xmlSchemaBasicItemPtr item,
1581 		     xmlNodePtr itemNode)
1582 {
1583     xmlChar *str = NULL;
1584     int named = 1;
1585 
1586     if (*buf != NULL) {
1587 	xmlFree(*buf);
1588 	*buf = NULL;
1589     }
1590 
1591     if (itemDes != NULL) {
1592 	*buf = xmlStrdup(itemDes);
1593     } else if (item != NULL) {
1594 	switch (item->type) {
1595 	case XML_SCHEMA_TYPE_BASIC: {
1596 	    xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1597 
1598 	    if (WXS_IS_ATOMIC(type))
1599 		*buf = xmlStrdup(BAD_CAST "atomic type 'xs:");
1600 	    else if (WXS_IS_LIST(type))
1601 		*buf = xmlStrdup(BAD_CAST "list type 'xs:");
1602 	    else if (WXS_IS_UNION(type))
1603 		*buf = xmlStrdup(BAD_CAST "union type 'xs:");
1604 	    else
1605 		*buf = xmlStrdup(BAD_CAST "simple type 'xs:");
1606 	    *buf = xmlStrcat(*buf, type->name);
1607 	    *buf = xmlStrcat(*buf, BAD_CAST "'");
1608 	    }
1609 	    break;
1610 	case XML_SCHEMA_TYPE_SIMPLE: {
1611 	    xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1612 
1613 	    if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1614 		*buf = xmlStrdup(BAD_CAST"");
1615 	    } else {
1616 		*buf = xmlStrdup(BAD_CAST "local ");
1617 	    }
1618 	    if (WXS_IS_ATOMIC(type))
1619 		*buf = xmlStrcat(*buf, BAD_CAST "atomic type");
1620 	    else if (WXS_IS_LIST(type))
1621 		*buf = xmlStrcat(*buf, BAD_CAST "list type");
1622 	    else if (WXS_IS_UNION(type))
1623 		*buf = xmlStrcat(*buf, BAD_CAST "union type");
1624 	    else
1625 		*buf = xmlStrcat(*buf, BAD_CAST "simple type");
1626 	    if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1627 		*buf = xmlStrcat(*buf, BAD_CAST " '");
1628 		*buf = xmlStrcat(*buf, type->name);
1629 		*buf = xmlStrcat(*buf, BAD_CAST "'");
1630 	    }
1631 	    }
1632 	    break;
1633 	case XML_SCHEMA_TYPE_COMPLEX: {
1634 	    xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1635 
1636 	    if (type->flags & XML_SCHEMAS_TYPE_GLOBAL)
1637 		*buf = xmlStrdup(BAD_CAST "");
1638 	    else
1639 		*buf = xmlStrdup(BAD_CAST "local ");
1640 	    *buf = xmlStrcat(*buf, BAD_CAST "complex type");
1641 	    if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1642 		*buf = xmlStrcat(*buf, BAD_CAST " '");
1643 		*buf = xmlStrcat(*buf, type->name);
1644 		*buf = xmlStrcat(*buf, BAD_CAST "'");
1645 	    }
1646 	    }
1647 	    break;
1648 	case XML_SCHEMA_TYPE_ATTRIBUTE_USE: {
1649 		xmlSchemaAttributeUsePtr ause;
1650 
1651 		ause = WXS_ATTR_USE_CAST item;
1652 		*buf = xmlStrdup(BAD_CAST "attribute use ");
1653 		if (WXS_ATTRUSE_DECL(ause) != NULL) {
1654 		    *buf = xmlStrcat(*buf, BAD_CAST "'");
1655 		    *buf = xmlStrcat(*buf,
1656 			xmlSchemaGetComponentQName(&str, WXS_ATTRUSE_DECL(ause)));
1657 		    FREE_AND_NULL(str)
1658 			*buf = xmlStrcat(*buf, BAD_CAST "'");
1659 		} else {
1660 		    *buf = xmlStrcat(*buf, BAD_CAST "(unknown)");
1661 		}
1662 	    }
1663 	    break;
1664 	case XML_SCHEMA_TYPE_ATTRIBUTE: {
1665 		xmlSchemaAttributePtr attr;
1666 
1667 		attr = (xmlSchemaAttributePtr) item;
1668 		*buf = xmlStrdup(BAD_CAST "attribute decl.");
1669 		*buf = xmlStrcat(*buf, BAD_CAST " '");
1670 		*buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1671 		    attr->targetNamespace, attr->name));
1672 		FREE_AND_NULL(str)
1673 		    *buf = xmlStrcat(*buf, BAD_CAST "'");
1674 	    }
1675 	    break;
1676 	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1677 	    xmlSchemaGetComponentDesignation(buf, item);
1678 	    break;
1679 	case XML_SCHEMA_TYPE_ELEMENT: {
1680 		xmlSchemaElementPtr elem;
1681 
1682 		elem = (xmlSchemaElementPtr) item;
1683 		*buf = xmlStrdup(BAD_CAST "element decl.");
1684 		*buf = xmlStrcat(*buf, BAD_CAST " '");
1685 		*buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1686 		    elem->targetNamespace, elem->name));
1687 		*buf = xmlStrcat(*buf, BAD_CAST "'");
1688 	    }
1689 	    break;
1690 	case XML_SCHEMA_TYPE_IDC_UNIQUE:
1691 	case XML_SCHEMA_TYPE_IDC_KEY:
1692 	case XML_SCHEMA_TYPE_IDC_KEYREF:
1693 	    if (item->type == XML_SCHEMA_TYPE_IDC_UNIQUE)
1694 		*buf = xmlStrdup(BAD_CAST "unique '");
1695 	    else if (item->type == XML_SCHEMA_TYPE_IDC_KEY)
1696 		*buf = xmlStrdup(BAD_CAST "key '");
1697 	    else
1698 		*buf = xmlStrdup(BAD_CAST "keyRef '");
1699 	    *buf = xmlStrcat(*buf, ((xmlSchemaIDCPtr) item)->name);
1700 	    *buf = xmlStrcat(*buf, BAD_CAST "'");
1701 	    break;
1702 	case XML_SCHEMA_TYPE_ANY:
1703 	case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1704 	    *buf = xmlStrdup(xmlSchemaWildcardPCToString(
1705 		    ((xmlSchemaWildcardPtr) item)->processContents));
1706 	    *buf = xmlStrcat(*buf, BAD_CAST " wildcard");
1707 	    break;
1708 	case XML_SCHEMA_FACET_MININCLUSIVE:
1709 	case XML_SCHEMA_FACET_MINEXCLUSIVE:
1710 	case XML_SCHEMA_FACET_MAXINCLUSIVE:
1711 	case XML_SCHEMA_FACET_MAXEXCLUSIVE:
1712 	case XML_SCHEMA_FACET_TOTALDIGITS:
1713 	case XML_SCHEMA_FACET_FRACTIONDIGITS:
1714 	case XML_SCHEMA_FACET_PATTERN:
1715 	case XML_SCHEMA_FACET_ENUMERATION:
1716 	case XML_SCHEMA_FACET_WHITESPACE:
1717 	case XML_SCHEMA_FACET_LENGTH:
1718 	case XML_SCHEMA_FACET_MAXLENGTH:
1719 	case XML_SCHEMA_FACET_MINLENGTH:
1720 	    *buf = xmlStrdup(BAD_CAST "facet '");
1721 	    *buf = xmlStrcat(*buf, xmlSchemaFacetTypeToString(item->type));
1722 	    *buf = xmlStrcat(*buf, BAD_CAST "'");
1723 	    break;
1724 	case XML_SCHEMA_TYPE_GROUP: {
1725 		*buf = xmlStrdup(BAD_CAST "model group def.");
1726 		*buf = xmlStrcat(*buf, BAD_CAST " '");
1727 		*buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, item));
1728 		*buf = xmlStrcat(*buf, BAD_CAST "'");
1729 		FREE_AND_NULL(str)
1730 	    }
1731 	    break;
1732 	case XML_SCHEMA_TYPE_SEQUENCE:
1733 	case XML_SCHEMA_TYPE_CHOICE:
1734 	case XML_SCHEMA_TYPE_ALL:
1735 	case XML_SCHEMA_TYPE_PARTICLE:
1736 	    *buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item));
1737 	    break;
1738 	case XML_SCHEMA_TYPE_NOTATION: {
1739 		*buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item));
1740 		*buf = xmlStrcat(*buf, BAD_CAST " '");
1741 		*buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, item));
1742 		*buf = xmlStrcat(*buf, BAD_CAST "'");
1743 		FREE_AND_NULL(str);
1744 	    }
1745             /* Falls through. */
1746 	default:
1747 	    named = 0;
1748 	}
1749     } else
1750 	named = 0;
1751 
1752     if ((named == 0) && (itemNode != NULL)) {
1753 	xmlNodePtr elem;
1754 
1755 	if (itemNode->type == XML_ATTRIBUTE_NODE)
1756 	    elem = itemNode->parent;
1757 	else
1758 	    elem = itemNode;
1759 	*buf = xmlStrdup(BAD_CAST "Element '");
1760 	if (elem->ns != NULL) {
1761 	    *buf = xmlStrcat(*buf,
1762 		xmlSchemaFormatQName(&str, elem->ns->href, elem->name));
1763 	    FREE_AND_NULL(str)
1764 	} else
1765 	    *buf = xmlStrcat(*buf, elem->name);
1766 	*buf = xmlStrcat(*buf, BAD_CAST "'");
1767 
1768     }
1769     if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
1770 	*buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
1771 	if (itemNode->ns != NULL) {
1772 	    *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1773 		itemNode->ns->href, itemNode->name));
1774 	    FREE_AND_NULL(str)
1775 	} else
1776 	    *buf = xmlStrcat(*buf, itemNode->name);
1777 	*buf = xmlStrcat(*buf, BAD_CAST "'");
1778     }
1779     FREE_AND_NULL(str)
1780 
1781     return (xmlEscapeFormatString(buf));
1782 }
1783 
1784 /**
1785  * xmlSchemaFormatFacetEnumSet:
1786  * @buf: the string buffer
1787  * @type: the type holding the enumeration facets
1788  *
1789  * Builds a string consisting of all enumeration elements.
1790  *
1791  * Returns a string of all enumeration elements.
1792  */
1793 static const xmlChar *
xmlSchemaFormatFacetEnumSet(xmlSchemaAbstractCtxtPtr actxt,xmlChar ** buf,xmlSchemaTypePtr type)1794 xmlSchemaFormatFacetEnumSet(xmlSchemaAbstractCtxtPtr actxt,
1795 			    xmlChar **buf, xmlSchemaTypePtr type)
1796 {
1797     xmlSchemaFacetPtr facet;
1798     xmlSchemaWhitespaceValueType ws;
1799     xmlChar *value = NULL;
1800     int res, found = 0;
1801 
1802     if (*buf != NULL)
1803 	xmlFree(*buf);
1804     *buf = NULL;
1805 
1806     do {
1807 	/*
1808 	* Use the whitespace type of the base type.
1809 	*/
1810 	ws = xmlSchemaGetWhiteSpaceFacetValue(type->baseType);
1811 	for (facet = type->facets; facet != NULL; facet = facet->next) {
1812 	    if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
1813 		continue;
1814 	    found = 1;
1815 	    res = xmlSchemaGetCanonValueWhtspExt(facet->val,
1816 		ws, &value);
1817 	    if (res == -1) {
1818 		xmlSchemaInternalErr(actxt,
1819 		    "xmlSchemaFormatFacetEnumSet",
1820 		    "compute the canonical lexical representation");
1821 		if (*buf != NULL)
1822 		    xmlFree(*buf);
1823 		*buf = NULL;
1824 		return (NULL);
1825 	    }
1826 	    if (*buf == NULL)
1827 		*buf = xmlStrdup(BAD_CAST "'");
1828 	    else
1829 		*buf = xmlStrcat(*buf, BAD_CAST ", '");
1830 	    *buf = xmlStrcat(*buf, BAD_CAST value);
1831 	    *buf = xmlStrcat(*buf, BAD_CAST "'");
1832 	    if (value != NULL) {
1833 		xmlFree((xmlChar *)value);
1834 		value = NULL;
1835 	    }
1836 	}
1837 	/*
1838 	* The enumeration facet of a type restricts the enumeration
1839 	* facet of the ancestor type; i.e., such restricted enumerations
1840 	* do not belong to the set of the given type. Thus we break
1841 	* on the first found enumeration.
1842 	*/
1843 	if (found)
1844 	    break;
1845 	type = type->baseType;
1846     } while ((type != NULL) && (type->type != XML_SCHEMA_TYPE_BASIC));
1847 
1848     return ((const xmlChar *) *buf);
1849 }
1850 
1851 /************************************************************************
1852  *									*
1853  *			Error functions				        *
1854  *									*
1855  ************************************************************************/
1856 
1857 #if 0
1858 static void
1859 xmlSchemaErrMemory(const char *msg)
1860 {
1861     __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
1862                      msg);
1863 }
1864 #endif
1865 
1866 static void
xmlSchemaPSimpleErr(const char * msg)1867 xmlSchemaPSimpleErr(const char *msg)
1868 {
1869     __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
1870                      msg);
1871 }
1872 
1873 /**
1874  * xmlSchemaPErrMemory:
1875  * @node: a context node
1876  * @extra:  extra informations
1877  *
1878  * Handle an out of memory condition
1879  */
1880 static void
xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,const char * extra,xmlNodePtr node)1881 xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
1882                     const char *extra, xmlNodePtr node)
1883 {
1884     if (ctxt != NULL)
1885         ctxt->nberrors++;
1886     __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
1887                      extra);
1888 }
1889 
1890 /**
1891  * xmlSchemaPErr:
1892  * @ctxt: the parsing context
1893  * @node: the context node
1894  * @error: the error code
1895  * @msg: the error message
1896  * @str1: extra data
1897  * @str2: extra data
1898  *
1899  * Handle a parser error
1900  */
1901 static void LIBXML_ATTR_FORMAT(4,0)
xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,int error,const char * msg,const xmlChar * str1,const xmlChar * str2)1902 xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1903               const char *msg, const xmlChar * str1, const xmlChar * str2)
1904 {
1905     xmlGenericErrorFunc channel = NULL;
1906     xmlStructuredErrorFunc schannel = NULL;
1907     void *data = NULL;
1908 
1909     if (ctxt != NULL) {
1910         ctxt->nberrors++;
1911 	ctxt->err = error;
1912         channel = ctxt->error;
1913         data = ctxt->errCtxt;
1914 	schannel = ctxt->serror;
1915     }
1916     __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
1917                     error, XML_ERR_ERROR, NULL, 0,
1918                     (const char *) str1, (const char *) str2, NULL, 0, 0,
1919                     msg, str1, str2);
1920 }
1921 
1922 /**
1923  * xmlSchemaPErr2:
1924  * @ctxt: the parsing context
1925  * @node: the context node
1926  * @node: the current child
1927  * @error: the error code
1928  * @msg: the error message
1929  * @str1: extra data
1930  * @str2: extra data
1931  *
1932  * Handle a parser error
1933  */
1934 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)1935 xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
1936                xmlNodePtr child, int error,
1937                const char *msg, const xmlChar * str1, const xmlChar * str2)
1938 {
1939     if (child != NULL)
1940         xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
1941     else
1942         xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
1943 }
1944 
1945 
1946 /**
1947  * xmlSchemaPErrExt:
1948  * @ctxt: the parsing context
1949  * @node: the context node
1950  * @error: the error code
1951  * @strData1: extra data
1952  * @strData2: extra data
1953  * @strData3: extra data
1954  * @msg: the message
1955  * @str1:  extra parameter for the message display
1956  * @str2:  extra parameter for the message display
1957  * @str3:  extra parameter for the message display
1958  * @str4:  extra parameter for the message display
1959  * @str5:  extra parameter for the message display
1960  *
1961  * Handle a parser error
1962  */
1963 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)1964 xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1965 		const xmlChar * strData1, const xmlChar * strData2,
1966 		const xmlChar * strData3, const char *msg, const xmlChar * str1,
1967 		const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
1968 		const xmlChar * str5)
1969 {
1970 
1971     xmlGenericErrorFunc channel = NULL;
1972     xmlStructuredErrorFunc schannel = NULL;
1973     void *data = NULL;
1974 
1975     if (ctxt != NULL) {
1976         ctxt->nberrors++;
1977 	ctxt->err = error;
1978         channel = ctxt->error;
1979         data = ctxt->errCtxt;
1980 	schannel = ctxt->serror;
1981     }
1982     __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
1983                     error, XML_ERR_ERROR, NULL, 0,
1984                     (const char *) strData1, (const char *) strData2,
1985 		    (const char *) strData3, 0, 0, msg, str1, str2,
1986 		    str3, str4, str5);
1987 }
1988 
1989 /************************************************************************
1990  *									*
1991  *			Allround error functions			*
1992  *									*
1993  ************************************************************************/
1994 
1995 /**
1996  * xmlSchemaVTypeErrMemory:
1997  * @node: a context node
1998  * @extra:  extra informations
1999  *
2000  * Handle an out of memory condition
2001  */
2002 static void
xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,const char * extra,xmlNodePtr node)2003 xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
2004                     const char *extra, xmlNodePtr node)
2005 {
2006     if (ctxt != NULL) {
2007         ctxt->nberrors++;
2008         ctxt->err = XML_SCHEMAV_INTERNAL;
2009     }
2010     __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
2011                      extra);
2012 }
2013 
2014 static void LIBXML_ATTR_FORMAT(2,0)
xmlSchemaPSimpleInternalErr(xmlNodePtr node,const char * msg,const xmlChar * str)2015 xmlSchemaPSimpleInternalErr(xmlNodePtr node,
2016 			    const char *msg, const xmlChar *str)
2017 {
2018      __xmlSimpleError(XML_FROM_SCHEMASP, XML_SCHEMAP_INTERNAL, node,
2019 	 msg, (const char *) str);
2020 }
2021 
2022 #define WXS_ERROR_TYPE_ERROR 1
2023 #define WXS_ERROR_TYPE_WARNING 2
2024 /**
2025  * xmlSchemaErr4Line:
2026  * @ctxt: the validation context
2027  * @errorLevel: the error level
2028  * @error: the error code
2029  * @node: the context node
2030  * @line: the line number
2031  * @msg: the error message
2032  * @str1: extra data
2033  * @str2: extra data
2034  * @str3: extra data
2035  * @str4: extra data
2036  *
2037  * Handle a validation error
2038  */
2039 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)2040 xmlSchemaErr4Line(xmlSchemaAbstractCtxtPtr ctxt,
2041 		  xmlErrorLevel errorLevel,
2042 		  int error, xmlNodePtr node, int line, const char *msg,
2043 		  const xmlChar *str1, const xmlChar *str2,
2044 		  const xmlChar *str3, const xmlChar *str4)
2045 {
2046     xmlStructuredErrorFunc schannel = NULL;
2047     xmlGenericErrorFunc channel = NULL;
2048     void *data = NULL;
2049 
2050     if (ctxt != NULL) {
2051 	if (ctxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
2052 	    xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctxt;
2053 	    const char *file = NULL;
2054 	    int col = 0;
2055 	    if (errorLevel != XML_ERR_WARNING) {
2056 		vctxt->nberrors++;
2057 		vctxt->err = error;
2058 		channel = vctxt->error;
2059 	    } else {
2060 		channel = vctxt->warning;
2061 	    }
2062 	    schannel = vctxt->serror;
2063 	    data = vctxt->errCtxt;
2064 
2065 	    /*
2066 	    * Error node. If we specify a line number, then
2067 	    * do not channel any node to the error function.
2068 	    */
2069 	    if (line == 0) {
2070 		if ((node == NULL) &&
2071 		    (vctxt->depth >= 0) &&
2072 		    (vctxt->inode != NULL)) {
2073 		    node = vctxt->inode->node;
2074 		}
2075 		/*
2076 		* Get filename and line if no node-tree.
2077 		*/
2078 		if ((node == NULL) &&
2079 		    (vctxt->parserCtxt != NULL) &&
2080 		    (vctxt->parserCtxt->input != NULL)) {
2081 		    file = vctxt->parserCtxt->input->filename;
2082 		    line = vctxt->parserCtxt->input->line;
2083 		    col = vctxt->parserCtxt->input->col;
2084 		}
2085 	    } else {
2086 		/*
2087 		* Override the given node's (if any) position
2088 		* and channel only the given line number.
2089 		*/
2090 		node = NULL;
2091 		/*
2092 		* Get filename.
2093 		*/
2094 		if (vctxt->doc != NULL)
2095 		    file = (const char *) vctxt->doc->URL;
2096 		else if ((vctxt->parserCtxt != NULL) &&
2097 		    (vctxt->parserCtxt->input != NULL))
2098 		    file = vctxt->parserCtxt->input->filename;
2099 	    }
2100 	    if (vctxt->locFunc != NULL) {
2101 	        if ((file == NULL) || (line == 0)) {
2102 		    unsigned long l;
2103 		    const char *f;
2104 		    vctxt->locFunc(vctxt->locCtxt, &f, &l);
2105 		    if (file == NULL)
2106 		        file = f;
2107 		    if (line == 0)
2108 		        line = (int) l;
2109 		}
2110 	    }
2111 	    if ((file == NULL) && (vctxt->filename != NULL))
2112 	        file = vctxt->filename;
2113 
2114 	    __xmlRaiseError(schannel, channel, data, ctxt,
2115 		node, XML_FROM_SCHEMASV,
2116 		error, errorLevel, file, line,
2117 		(const char *) str1, (const char *) str2,
2118 		(const char *) str3, 0, col, msg, str1, str2, str3, str4);
2119 
2120 	} else if (ctxt->type == XML_SCHEMA_CTXT_PARSER) {
2121 	    xmlSchemaParserCtxtPtr pctxt = (xmlSchemaParserCtxtPtr) ctxt;
2122 	    if (errorLevel != XML_ERR_WARNING) {
2123 		pctxt->nberrors++;
2124 		pctxt->err = error;
2125 		channel = pctxt->error;
2126 	    } else {
2127 		channel = pctxt->warning;
2128 	    }
2129 	    schannel = pctxt->serror;
2130 	    data = pctxt->errCtxt;
2131 	    __xmlRaiseError(schannel, channel, data, ctxt,
2132 		node, XML_FROM_SCHEMASP, error,
2133 		errorLevel, NULL, 0,
2134 		(const char *) str1, (const char *) str2,
2135 		(const char *) str3, 0, 0, msg, str1, str2, str3, str4);
2136 	} else {
2137 	    TODO
2138 	}
2139     }
2140 }
2141 
2142 /**
2143  * xmlSchemaErr3:
2144  * @ctxt: the validation context
2145  * @node: the context node
2146  * @error: the error code
2147  * @msg: the error message
2148  * @str1: extra data
2149  * @str2: extra data
2150  * @str3: extra data
2151  *
2152  * Handle a validation error
2153  */
2154 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)2155 xmlSchemaErr3(xmlSchemaAbstractCtxtPtr actxt,
2156 	      int error, xmlNodePtr node, const char *msg,
2157 	      const xmlChar *str1, const xmlChar *str2, const xmlChar *str3)
2158 {
2159     xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0,
2160 	msg, str1, str2, str3, NULL);
2161 }
2162 
2163 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)2164 xmlSchemaErr4(xmlSchemaAbstractCtxtPtr actxt,
2165 	      int error, xmlNodePtr node, const char *msg,
2166 	      const xmlChar *str1, const xmlChar *str2,
2167 	      const xmlChar *str3, const xmlChar *str4)
2168 {
2169     xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0,
2170 	msg, str1, str2, str3, str4);
2171 }
2172 
2173 static void LIBXML_ATTR_FORMAT(4,0)
xmlSchemaErr(xmlSchemaAbstractCtxtPtr actxt,int error,xmlNodePtr node,const char * msg,const xmlChar * str1,const xmlChar * str2)2174 xmlSchemaErr(xmlSchemaAbstractCtxtPtr actxt,
2175 	     int error, xmlNodePtr node, const char *msg,
2176 	     const xmlChar *str1, const xmlChar *str2)
2177 {
2178     xmlSchemaErr4(actxt, error, node, msg, str1, str2, NULL, NULL);
2179 }
2180 
2181 static xmlChar *
xmlSchemaFormatNodeForError(xmlChar ** msg,xmlSchemaAbstractCtxtPtr actxt,xmlNodePtr node)2182 xmlSchemaFormatNodeForError(xmlChar ** msg,
2183 			    xmlSchemaAbstractCtxtPtr actxt,
2184 			    xmlNodePtr node)
2185 {
2186     xmlChar *str = NULL;
2187 
2188     *msg = NULL;
2189     if ((node != NULL) &&
2190 	(node->type != XML_ELEMENT_NODE) &&
2191 	(node->type != XML_ATTRIBUTE_NODE))
2192     {
2193 	/*
2194 	* Don't try to format other nodes than element and
2195 	* attribute nodes.
2196 	* Play safe and return an empty string.
2197 	*/
2198 	*msg = xmlStrdup(BAD_CAST "");
2199 	return(*msg);
2200     }
2201     if (node != NULL) {
2202 	/*
2203 	* Work on tree nodes.
2204 	*/
2205 	if (node->type == XML_ATTRIBUTE_NODE) {
2206 	    xmlNodePtr elem = node->parent;
2207 
2208 	    *msg = xmlStrdup(BAD_CAST "Element '");
2209 	    if (elem->ns != NULL)
2210 		*msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2211 		    elem->ns->href, elem->name));
2212 	    else
2213 		*msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2214 		    NULL, elem->name));
2215 	    FREE_AND_NULL(str);
2216 	    *msg = xmlStrcat(*msg, BAD_CAST "', ");
2217 	    *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
2218 	} else {
2219 	    *msg = xmlStrdup(BAD_CAST "Element '");
2220 	}
2221 	if (node->ns != NULL)
2222 	    *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2223 	    node->ns->href, node->name));
2224 	else
2225 	    *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2226 	    NULL, node->name));
2227 	FREE_AND_NULL(str);
2228 	*msg = xmlStrcat(*msg, BAD_CAST "': ");
2229     } else if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
2230 	xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) actxt;
2231 	/*
2232 	* Work on node infos.
2233 	*/
2234 	if (vctxt->inode->nodeType == XML_ATTRIBUTE_NODE) {
2235 	    xmlSchemaNodeInfoPtr ielem =
2236 		vctxt->elemInfos[vctxt->depth];
2237 
2238 	    *msg = xmlStrdup(BAD_CAST "Element '");
2239 	    *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2240 		ielem->nsName, ielem->localName));
2241 	    FREE_AND_NULL(str);
2242 	    *msg = xmlStrcat(*msg, BAD_CAST "', ");
2243 	    *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
2244 	} else {
2245 	    *msg = xmlStrdup(BAD_CAST "Element '");
2246 	}
2247 	*msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2248 	    vctxt->inode->nsName, vctxt->inode->localName));
2249 	FREE_AND_NULL(str);
2250 	*msg = xmlStrcat(*msg, BAD_CAST "': ");
2251     } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
2252 	/*
2253 	* Hmm, no node while parsing?
2254 	* Return an empty string, in case NULL will break something.
2255 	*/
2256 	*msg = xmlStrdup(BAD_CAST "");
2257     } else {
2258 	TODO
2259 	return (NULL);
2260     }
2261 
2262     /*
2263      * xmlSchemaFormatItemForReport() also returns an escaped format
2264      * string, so do this before calling it below (in the future).
2265      */
2266     xmlEscapeFormatString(msg);
2267 
2268     /*
2269     * VAL TODO: The output of the given schema component is currently
2270     * disabled.
2271     */
2272 #if 0
2273     if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
2274 	*msg = xmlStrcat(*msg, BAD_CAST " [");
2275 	*msg = xmlStrcat(*msg, xmlSchemaFormatItemForReport(&str,
2276 	    NULL, type, NULL, 0));
2277 	FREE_AND_NULL(str)
2278 	*msg = xmlStrcat(*msg, BAD_CAST "]");
2279     }
2280 #endif
2281     return (*msg);
2282 }
2283 
2284 static void LIBXML_ATTR_FORMAT(3,0)
xmlSchemaInternalErr2(xmlSchemaAbstractCtxtPtr actxt,const char * funcName,const char * message,const xmlChar * str1,const xmlChar * str2)2285 xmlSchemaInternalErr2(xmlSchemaAbstractCtxtPtr actxt,
2286 		     const char *funcName,
2287 		     const char *message,
2288 		     const xmlChar *str1,
2289 		     const xmlChar *str2)
2290 {
2291     xmlChar *msg = NULL;
2292 
2293     if (actxt == NULL)
2294         return;
2295     msg = xmlStrdup(BAD_CAST "Internal error: %s, ");
2296     msg = xmlStrcat(msg, BAD_CAST message);
2297     msg = xmlStrcat(msg, BAD_CAST ".\n");
2298 
2299     if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR)
2300 	xmlSchemaErr3(actxt, XML_SCHEMAV_INTERNAL, NULL,
2301 	    (const char *) msg, (const xmlChar *) funcName, str1, str2);
2302     else if (actxt->type == XML_SCHEMA_CTXT_PARSER)
2303 	xmlSchemaErr3(actxt, XML_SCHEMAP_INTERNAL, NULL,
2304 	    (const char *) msg, (const xmlChar *) funcName, str1, str2);
2305 
2306     FREE_AND_NULL(msg)
2307 }
2308 
2309 static void LIBXML_ATTR_FORMAT(3,0)
xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,const char * funcName,const char * message)2310 xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
2311 		     const char *funcName,
2312 		     const char *message)
2313 {
2314     xmlSchemaInternalErr2(actxt, funcName, message, NULL, NULL);
2315 }
2316 
2317 #if 0
2318 static void LIBXML_ATTR_FORMAT(3,0)
2319 xmlSchemaPInternalErr(xmlSchemaParserCtxtPtr pctxt,
2320 		     const char *funcName,
2321 		     const char *message,
2322 		     const xmlChar *str1,
2323 		     const xmlChar *str2)
2324 {
2325     xmlSchemaInternalErr2(ACTXT_CAST pctxt, funcName, message,
2326 	str1, str2);
2327 }
2328 #endif
2329 
2330 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)2331 xmlSchemaCustomErr4(xmlSchemaAbstractCtxtPtr actxt,
2332 		   xmlParserErrors error,
2333 		   xmlNodePtr node,
2334 		   xmlSchemaBasicItemPtr item,
2335 		   const char *message,
2336 		   const xmlChar *str1, const xmlChar *str2,
2337 		   const xmlChar *str3, const xmlChar *str4)
2338 {
2339     xmlChar *msg = NULL;
2340 
2341     if ((node == NULL) && (item != NULL) &&
2342 	(actxt->type == XML_SCHEMA_CTXT_PARSER)) {
2343 	node = WXS_ITEM_NODE(item);
2344 	xmlSchemaFormatItemForReport(&msg, NULL, item, NULL);
2345 	msg = xmlStrcat(msg, BAD_CAST ": ");
2346     } else
2347 	xmlSchemaFormatNodeForError(&msg, actxt, node);
2348     msg = xmlStrcat(msg, (const xmlChar *) message);
2349     msg = xmlStrcat(msg, BAD_CAST ".\n");
2350     xmlSchemaErr4(actxt, error, node,
2351 	(const char *) msg, str1, str2, str3, str4);
2352     FREE_AND_NULL(msg)
2353 }
2354 
2355 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)2356 xmlSchemaCustomErr(xmlSchemaAbstractCtxtPtr actxt,
2357 		   xmlParserErrors error,
2358 		   xmlNodePtr node,
2359 		   xmlSchemaBasicItemPtr item,
2360 		   const char *message,
2361 		   const xmlChar *str1,
2362 		   const xmlChar *str2)
2363 {
2364     xmlSchemaCustomErr4(actxt, error, node, item,
2365 	message, str1, str2, NULL, NULL);
2366 }
2367 
2368 
2369 
2370 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)2371 xmlSchemaCustomWarning(xmlSchemaAbstractCtxtPtr actxt,
2372 		   xmlParserErrors error,
2373 		   xmlNodePtr node,
2374 		   xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2375 		   const char *message,
2376 		   const xmlChar *str1,
2377 		   const xmlChar *str2,
2378 		   const xmlChar *str3)
2379 {
2380     xmlChar *msg = NULL;
2381 
2382     xmlSchemaFormatNodeForError(&msg, actxt, node);
2383     msg = xmlStrcat(msg, (const xmlChar *) message);
2384     msg = xmlStrcat(msg, BAD_CAST ".\n");
2385 
2386     /* URGENT TODO: Set the error code to something sane. */
2387     xmlSchemaErr4Line(actxt, XML_ERR_WARNING, error, node, 0,
2388 	(const char *) msg, str1, str2, str3, NULL);
2389 
2390     FREE_AND_NULL(msg)
2391 }
2392 
2393 
2394 
2395 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)2396 xmlSchemaKeyrefErr(xmlSchemaValidCtxtPtr vctxt,
2397 		   xmlParserErrors error,
2398 		   xmlSchemaPSVIIDCNodePtr idcNode,
2399 		   xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2400 		   const char *message,
2401 		   const xmlChar *str1,
2402 		   const xmlChar *str2)
2403 {
2404     xmlChar *msg = NULL, *qname = NULL;
2405 
2406     msg = xmlStrdup(BAD_CAST "Element '%s': ");
2407     msg = xmlStrcat(msg, (const xmlChar *) message);
2408     msg = xmlStrcat(msg, BAD_CAST ".\n");
2409     xmlSchemaErr4Line(ACTXT_CAST vctxt, XML_ERR_ERROR,
2410 	error, NULL, idcNode->nodeLine, (const char *) msg,
2411 	xmlSchemaFormatQName(&qname,
2412 	    vctxt->nodeQNames->items[idcNode->nodeQNameID +1],
2413 	    vctxt->nodeQNames->items[idcNode->nodeQNameID]),
2414 	str1, str2, NULL);
2415     FREE_AND_NULL(qname);
2416     FREE_AND_NULL(msg);
2417 }
2418 
2419 static int
xmlSchemaEvalErrorNodeType(xmlSchemaAbstractCtxtPtr actxt,xmlNodePtr node)2420 xmlSchemaEvalErrorNodeType(xmlSchemaAbstractCtxtPtr actxt,
2421 			   xmlNodePtr node)
2422 {
2423     if (node != NULL)
2424 	return (node->type);
2425     if ((actxt->type == XML_SCHEMA_CTXT_VALIDATOR) &&
2426 	(((xmlSchemaValidCtxtPtr) actxt)->inode != NULL))
2427 	return ( ((xmlSchemaValidCtxtPtr) actxt)->inode->nodeType);
2428     return (-1);
2429 }
2430 
2431 static int
xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)2432 xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
2433 {
2434     switch (item->type) {
2435 	case XML_SCHEMA_TYPE_COMPLEX:
2436 	case XML_SCHEMA_TYPE_SIMPLE:
2437 	    if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
2438 		return(1);
2439 	    break;
2440 	case XML_SCHEMA_TYPE_GROUP:
2441 	    return (1);
2442 	case XML_SCHEMA_TYPE_ELEMENT:
2443 	    if ( ((xmlSchemaElementPtr) item)->flags &
2444 		XML_SCHEMAS_ELEM_GLOBAL)
2445 		return(1);
2446 	    break;
2447 	case XML_SCHEMA_TYPE_ATTRIBUTE:
2448 	    if ( ((xmlSchemaAttributePtr) item)->flags &
2449 		XML_SCHEMAS_ATTR_GLOBAL)
2450 		return(1);
2451 	    break;
2452 	/* Note that attribute groups are always global. */
2453 	default:
2454 	    return(1);
2455     }
2456     return (0);
2457 }
2458 
2459 static void
xmlSchemaSimpleTypeErr(xmlSchemaAbstractCtxtPtr actxt,xmlParserErrors error,xmlNodePtr node,const xmlChar * value,xmlSchemaTypePtr type,int displayValue)2460 xmlSchemaSimpleTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2461 		       xmlParserErrors error,
2462 		       xmlNodePtr node,
2463 		       const xmlChar *value,
2464 		       xmlSchemaTypePtr type,
2465 		       int displayValue)
2466 {
2467     xmlChar *msg = NULL;
2468 
2469     xmlSchemaFormatNodeForError(&msg, actxt, node);
2470 
2471     if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2472 	    XML_ATTRIBUTE_NODE))
2473 	msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
2474     else
2475 	msg = xmlStrcat(msg, BAD_CAST "The character content is not a valid "
2476 	    "value of ");
2477 
2478     if (! xmlSchemaIsGlobalItem(type))
2479 	msg = xmlStrcat(msg, BAD_CAST "the local ");
2480     else
2481 	msg = xmlStrcat(msg, BAD_CAST "the ");
2482 
2483     if (WXS_IS_ATOMIC(type))
2484 	msg = xmlStrcat(msg, BAD_CAST "atomic type");
2485     else if (WXS_IS_LIST(type))
2486 	msg = xmlStrcat(msg, BAD_CAST "list type");
2487     else if (WXS_IS_UNION(type))
2488 	msg = xmlStrcat(msg, BAD_CAST "union type");
2489 
2490     if (xmlSchemaIsGlobalItem(type)) {
2491 	xmlChar *str = NULL;
2492 	msg = xmlStrcat(msg, BAD_CAST " '");
2493 	if (type->builtInType != 0) {
2494 	    msg = xmlStrcat(msg, BAD_CAST "xs:");
2495 	    str = xmlStrdup(type->name);
2496 	} else {
2497 	    const xmlChar *qName = xmlSchemaFormatQName(&str, type->targetNamespace, type->name);
2498 	    if (!str)
2499 		str = xmlStrdup(qName);
2500 	}
2501 	msg = xmlStrcat(msg, xmlEscapeFormatString(&str));
2502 	msg = xmlStrcat(msg, BAD_CAST "'");
2503 	FREE_AND_NULL(str);
2504     }
2505     msg = xmlStrcat(msg, BAD_CAST ".\n");
2506     if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2507 	    XML_ATTRIBUTE_NODE))
2508 	xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2509     else
2510 	xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2511     FREE_AND_NULL(msg)
2512 }
2513 
2514 static const xmlChar *
xmlSchemaFormatErrorNodeQName(xmlChar ** str,xmlSchemaNodeInfoPtr ni,xmlNodePtr node)2515 xmlSchemaFormatErrorNodeQName(xmlChar ** str,
2516 			      xmlSchemaNodeInfoPtr ni,
2517 			      xmlNodePtr node)
2518 {
2519     if (node != NULL) {
2520 	if (node->ns != NULL)
2521 	    return (xmlSchemaFormatQName(str, node->ns->href, node->name));
2522 	else
2523 	    return (xmlSchemaFormatQName(str, NULL, node->name));
2524     } else if (ni != NULL)
2525 	return (xmlSchemaFormatQName(str, ni->nsName, ni->localName));
2526     return (NULL);
2527 }
2528 
2529 static void
xmlSchemaIllegalAttrErr(xmlSchemaAbstractCtxtPtr actxt,xmlParserErrors error,xmlSchemaAttrInfoPtr ni,xmlNodePtr node)2530 xmlSchemaIllegalAttrErr(xmlSchemaAbstractCtxtPtr actxt,
2531 			xmlParserErrors error,
2532 			xmlSchemaAttrInfoPtr ni,
2533 			xmlNodePtr node)
2534 {
2535     xmlChar *msg = NULL, *str = NULL;
2536 
2537     xmlSchemaFormatNodeForError(&msg, actxt, node);
2538     msg = xmlStrcat(msg, BAD_CAST "The attribute '%s' is not allowed.\n");
2539     xmlSchemaErr(actxt, error, node, (const char *) msg,
2540 	xmlSchemaFormatErrorNodeQName(&str, (xmlSchemaNodeInfoPtr) ni, node),
2541 	NULL);
2542     FREE_AND_NULL(str)
2543     FREE_AND_NULL(msg)
2544 }
2545 
2546 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)2547 xmlSchemaComplexTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2548 		        xmlParserErrors error,
2549 		        xmlNodePtr node,
2550 			xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2551 			const char *message,
2552 			int nbval,
2553 			int nbneg,
2554 			xmlChar **values)
2555 {
2556     xmlChar *str = NULL, *msg = NULL;
2557     xmlChar *localName, *nsName;
2558     const xmlChar *cur, *end;
2559     int i;
2560 
2561     xmlSchemaFormatNodeForError(&msg, actxt, node);
2562     msg = xmlStrcat(msg, (const xmlChar *) message);
2563     msg = xmlStrcat(msg, BAD_CAST ".");
2564     /*
2565     * Note that is does not make sense to report that we have a
2566     * wildcard here, since the wildcard might be unfolded into
2567     * multiple transitions.
2568     */
2569     if (nbval + nbneg > 0) {
2570 	if (nbval + nbneg > 1) {
2571 	    str = xmlStrdup(BAD_CAST " Expected is one of ( ");
2572 	} else
2573 	    str = xmlStrdup(BAD_CAST " Expected is ( ");
2574 	nsName = NULL;
2575 
2576 	for (i = 0; i < nbval + nbneg; i++) {
2577 	    cur = values[i];
2578 	    if (cur == NULL)
2579 	        continue;
2580 	    if ((cur[0] == 'n') && (cur[1] == 'o') && (cur[2] == 't') &&
2581 	        (cur[3] == ' ')) {
2582 		cur += 4;
2583 		str = xmlStrcat(str, BAD_CAST "##other");
2584 	    }
2585 	    /*
2586 	    * Get the local name.
2587 	    */
2588 	    localName = NULL;
2589 
2590 	    end = cur;
2591 	    if (*end == '*') {
2592 		localName = xmlStrdup(BAD_CAST "*");
2593 		end++;
2594 	    } else {
2595 		while ((*end != 0) && (*end != '|'))
2596 		    end++;
2597 		localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
2598 	    }
2599 	    if (*end != 0) {
2600 		end++;
2601 		/*
2602 		* Skip "*|*" if they come with negated expressions, since
2603 		* they represent the same negated wildcard.
2604 		*/
2605 		if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
2606 		    /*
2607 		    * Get the namespace name.
2608 		    */
2609 		    cur = end;
2610 		    if (*end == '*') {
2611 			nsName = xmlStrdup(BAD_CAST "{*}");
2612 		    } else {
2613 			while (*end != 0)
2614 			    end++;
2615 
2616 			if (i >= nbval)
2617 			    nsName = xmlStrdup(BAD_CAST "{##other:");
2618 			else
2619 			    nsName = xmlStrdup(BAD_CAST "{");
2620 
2621 			nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
2622 			nsName = xmlStrcat(nsName, BAD_CAST "}");
2623 		    }
2624 		    str = xmlStrcat(str, BAD_CAST nsName);
2625 		    FREE_AND_NULL(nsName)
2626 		} else {
2627 		    FREE_AND_NULL(localName);
2628 		    continue;
2629 		}
2630 	    }
2631 	    str = xmlStrcat(str, BAD_CAST localName);
2632 	    FREE_AND_NULL(localName);
2633 
2634 	    if (i < nbval + nbneg -1)
2635 		str = xmlStrcat(str, BAD_CAST ", ");
2636 	}
2637 	str = xmlStrcat(str, BAD_CAST " ).\n");
2638 	msg = xmlStrcat(msg, xmlEscapeFormatString(&str));
2639 	FREE_AND_NULL(str)
2640     } else
2641       msg = xmlStrcat(msg, BAD_CAST "\n");
2642     xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2643     xmlFree(msg);
2644 }
2645 
2646 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)2647 xmlSchemaFacetErr(xmlSchemaAbstractCtxtPtr actxt,
2648 		  xmlParserErrors error,
2649 		  xmlNodePtr node,
2650 		  const xmlChar *value,
2651 		  unsigned long length,
2652 		  xmlSchemaTypePtr type,
2653 		  xmlSchemaFacetPtr facet,
2654 		  const char *message,
2655 		  const xmlChar *str1,
2656 		  const xmlChar *str2)
2657 {
2658     xmlChar *str = NULL, *msg = NULL;
2659     xmlSchemaTypeType facetType;
2660     int nodeType = xmlSchemaEvalErrorNodeType(actxt, node);
2661 
2662     xmlSchemaFormatNodeForError(&msg, actxt, node);
2663     if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
2664 	facetType = XML_SCHEMA_FACET_ENUMERATION;
2665 	/*
2666 	* If enumerations are validated, one must not expect the
2667 	* facet to be given.
2668 	*/
2669     } else
2670 	facetType = facet->type;
2671     msg = xmlStrcat(msg, BAD_CAST "[");
2672     msg = xmlStrcat(msg, BAD_CAST "facet '");
2673     msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facetType));
2674     msg = xmlStrcat(msg, BAD_CAST "'] ");
2675     if (message == NULL) {
2676 	/*
2677 	* Use a default message.
2678 	*/
2679 	if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
2680 	    (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
2681 	    (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
2682 
2683 	    char len[25], actLen[25];
2684 
2685 	    /* FIXME, TODO: What is the max expected string length of the
2686 	    * this value?
2687 	    */
2688 	    if (nodeType == XML_ATTRIBUTE_NODE)
2689 		msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
2690 	    else
2691 		msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
2692 
2693 	    snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
2694 	    snprintf(actLen, 24, "%lu", length);
2695 
2696 	    if (facetType == XML_SCHEMA_FACET_LENGTH)
2697 		msg = xmlStrcat(msg,
2698 		BAD_CAST "this differs from the allowed length of '%s'.\n");
2699 	    else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
2700 		msg = xmlStrcat(msg,
2701 		BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
2702 	    else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
2703 		msg = xmlStrcat(msg,
2704 		BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
2705 
2706 	    if (nodeType == XML_ATTRIBUTE_NODE)
2707 		xmlSchemaErr3(actxt, error, node, (const char *) msg,
2708 		    value, (const xmlChar *) actLen, (const xmlChar *) len);
2709 	    else
2710 		xmlSchemaErr(actxt, error, node, (const char *) msg,
2711 		    (const xmlChar *) actLen, (const xmlChar *) len);
2712 
2713 	} else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
2714 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
2715 		"of the set {%s}.\n");
2716 	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2717 		xmlSchemaFormatFacetEnumSet(actxt, &str, type));
2718 	} else if (facetType == XML_SCHEMA_FACET_PATTERN) {
2719 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
2720 		"by the pattern '%s'.\n");
2721 	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2722 		facet->value);
2723 	} else if (facetType == XML_SCHEMA_FACET_MININCLUSIVE) {
2724 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' is less than the "
2725 		"minimum value allowed ('%s').\n");
2726 	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2727 		facet->value);
2728 	} else if (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) {
2729 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' is greater than the "
2730 		"maximum value allowed ('%s').\n");
2731 	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2732 		facet->value);
2733 	} else if (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE) {
2734 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be greater than "
2735 		"'%s'.\n");
2736 	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2737 		facet->value);
2738 	} else if (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) {
2739 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be less than "
2740 		"'%s'.\n");
2741 	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2742 		facet->value);
2743 	} else if (facetType == XML_SCHEMA_FACET_TOTALDIGITS) {
2744 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more "
2745 		"digits than are allowed ('%s').\n");
2746 	    xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2747 		facet->value);
2748 	} else if (facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) {
2749 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more fractional "
2750 		"digits than are allowed ('%s').\n");
2751 	    xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2752 		facet->value);
2753 	} else if (nodeType == XML_ATTRIBUTE_NODE) {
2754 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
2755 	    xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2756 	} else {
2757 	    msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
2758 	    xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2759 	}
2760     } else {
2761 	msg = xmlStrcat(msg, (const xmlChar *) message);
2762 	msg = xmlStrcat(msg, BAD_CAST ".\n");
2763 	xmlSchemaErr(actxt, error, node, (const char *) msg, str1, str2);
2764     }
2765     FREE_AND_NULL(str)
2766     xmlFree(msg);
2767 }
2768 
2769 #define VERROR(err, type, msg) \
2770     xmlSchemaCustomErr(ACTXT_CAST vctxt, err, NULL, type, msg, NULL, NULL);
2771 
2772 #define VERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST vctxt, func, msg);
2773 
2774 #define PERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST pctxt, func, msg);
2775 #define PERROR_INT2(func, msg) xmlSchemaInternalErr(ACTXT_CAST ctxt, func, msg);
2776 
2777 #define AERROR_INT(func, msg) xmlSchemaInternalErr(actxt, func, msg);
2778 
2779 
2780 /**
2781  * xmlSchemaPMissingAttrErr:
2782  * @ctxt: the schema validation context
2783  * @ownerDes: the designation of  the owner
2784  * @ownerName: the name of the owner
2785  * @ownerItem: the owner as a schema object
2786  * @ownerElem: the owner as an element node
2787  * @node: the parent element node of the missing attribute node
2788  * @type: the corresponding type of the attribute node
2789  *
2790  * Reports an illegal attribute.
2791  */
2792 static void
xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaBasicItemPtr ownerItem,xmlNodePtr ownerElem,const char * name,const char * message)2793 xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
2794 			 xmlParserErrors error,
2795 			 xmlSchemaBasicItemPtr ownerItem,
2796 			 xmlNodePtr ownerElem,
2797 			 const char *name,
2798 			 const char *message)
2799 {
2800     xmlChar *des = NULL;
2801 
2802     xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2803 
2804     if (message != NULL)
2805 	xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
2806     else
2807 	xmlSchemaPErr(ctxt, ownerElem, error,
2808 	    "%s: The attribute '%s' is required but missing.\n",
2809 	    BAD_CAST des, BAD_CAST name);
2810     FREE_AND_NULL(des);
2811 }
2812 
2813 
2814 /**
2815  * xmlSchemaPResCompAttrErr:
2816  * @ctxt: the schema validation context
2817  * @error: the error code
2818  * @ownerDes: the designation of  the owner
2819  * @ownerItem: the owner as a schema object
2820  * @ownerElem: the owner as an element node
2821  * @name: the name of the attribute holding the QName
2822  * @refName: the referenced local name
2823  * @refURI: the referenced namespace URI
2824  * @message: optional message
2825  *
2826  * Used to report QName attribute values that failed to resolve
2827  * to schema components.
2828  */
2829 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)2830 xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
2831 			 xmlParserErrors error,
2832 			 xmlSchemaBasicItemPtr ownerItem,
2833 			 xmlNodePtr ownerElem,
2834 			 const char *name,
2835 			 const xmlChar *refName,
2836 			 const xmlChar *refURI,
2837 			 xmlSchemaTypeType refType,
2838 			 const char *refTypeStr)
2839 {
2840     xmlChar *des = NULL, *strA = NULL;
2841 
2842     xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2843     if (refTypeStr == NULL)
2844 	refTypeStr = (const char *) xmlSchemaItemTypeToStr(refType);
2845     xmlSchemaPErrExt(ctxt, ownerElem, error,
2846 	    NULL, NULL, NULL,
2847 	    "%s, attribute '%s': The QName value '%s' does not resolve to a(n) "
2848 	    "%s.\n", BAD_CAST des, BAD_CAST name,
2849 	    xmlSchemaFormatQName(&strA, refURI, refName),
2850 	    BAD_CAST refTypeStr, NULL);
2851     FREE_AND_NULL(des)
2852     FREE_AND_NULL(strA)
2853 }
2854 
2855 /**
2856  * xmlSchemaPCustomAttrErr:
2857  * @ctxt: the schema parser context
2858  * @error: the error code
2859  * @ownerDes: the designation of the owner
2860  * @ownerItem: the owner as a schema object
2861  * @attr: the illegal attribute node
2862  *
2863  * Reports an illegal attribute during the parse.
2864  */
2865 static void
xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlChar ** ownerDes,xmlSchemaBasicItemPtr ownerItem,xmlAttrPtr attr,const char * msg)2866 xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
2867 			xmlParserErrors error,
2868 			xmlChar **ownerDes,
2869 			xmlSchemaBasicItemPtr ownerItem,
2870 			xmlAttrPtr attr,
2871 			const char *msg)
2872 {
2873     xmlChar *des = NULL;
2874 
2875     if (ownerDes == NULL)
2876 	xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
2877     else if (*ownerDes == NULL) {
2878 	xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
2879 	des = *ownerDes;
2880     } else
2881 	des = *ownerDes;
2882     if (attr == NULL) {
2883 	xmlSchemaPErrExt(ctxt, NULL, error, NULL, NULL, NULL,
2884 	    "%s, attribute '%s': %s.\n",
2885 	    BAD_CAST des, (const xmlChar *) "Unknown",
2886 	    (const xmlChar *) msg, NULL, NULL);
2887     } else {
2888 	xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
2889 	    "%s, attribute '%s': %s.\n",
2890 	    BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
2891     }
2892     if (ownerDes == NULL)
2893 	FREE_AND_NULL(des);
2894 }
2895 
2896 /**
2897  * xmlSchemaPIllegalAttrErr:
2898  * @ctxt: the schema parser context
2899  * @error: the error code
2900  * @ownerDes: the designation of the attribute's owner
2901  * @ownerItem: the attribute's owner item
2902  * @attr: the illegal attribute node
2903  *
2904  * Reports an illegal attribute during the parse.
2905  */
2906 static void
xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaBasicItemPtr ownerComp ATTRIBUTE_UNUSED,xmlAttrPtr attr)2907 xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
2908 			 xmlParserErrors error,
2909 			 xmlSchemaBasicItemPtr ownerComp ATTRIBUTE_UNUSED,
2910 			 xmlAttrPtr attr)
2911 {
2912     xmlChar *strA = NULL, *strB = NULL;
2913 
2914     xmlSchemaFormatNodeForError(&strA, ACTXT_CAST ctxt, attr->parent);
2915     xmlSchemaErr4(ACTXT_CAST ctxt, error, (xmlNodePtr) attr,
2916 	"%sThe attribute '%s' is not allowed.\n", BAD_CAST strA,
2917 	xmlSchemaFormatQNameNs(&strB, attr->ns, attr->name),
2918 	NULL, NULL);
2919     FREE_AND_NULL(strA);
2920     FREE_AND_NULL(strB);
2921 }
2922 
2923 /**
2924  * xmlSchemaPCustomErr:
2925  * @ctxt: the schema parser context
2926  * @error: the error code
2927  * @itemDes: the designation of the schema item
2928  * @item: the schema item
2929  * @itemElem: the node of the schema item
2930  * @message: the error message
2931  * @str1: an optional param for the error message
2932  * @str2: an optional param for the error message
2933  * @str3: an optional param for the error message
2934  *
2935  * Reports an error during parsing.
2936  */
2937 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)2938 xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
2939 		    xmlParserErrors error,
2940 		    xmlSchemaBasicItemPtr item,
2941 		    xmlNodePtr itemElem,
2942 		    const char *message,
2943 		    const xmlChar *str1,
2944 		    const xmlChar *str2,
2945 		    const xmlChar *str3)
2946 {
2947     xmlChar *des = NULL, *msg = NULL;
2948 
2949     xmlSchemaFormatItemForReport(&des, NULL, item, itemElem);
2950     msg = xmlStrdup(BAD_CAST "%s: ");
2951     msg = xmlStrcat(msg, (const xmlChar *) message);
2952     msg = xmlStrcat(msg, BAD_CAST ".\n");
2953     if ((itemElem == NULL) && (item != NULL))
2954 	itemElem = WXS_ITEM_NODE(item);
2955     xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
2956 	(const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
2957     FREE_AND_NULL(des);
2958     FREE_AND_NULL(msg);
2959 }
2960 
2961 /**
2962  * xmlSchemaPCustomErr:
2963  * @ctxt: the schema parser context
2964  * @error: the error code
2965  * @itemDes: the designation of the schema item
2966  * @item: the schema item
2967  * @itemElem: the node of the schema item
2968  * @message: the error message
2969  * @str1: the optional param for the error message
2970  *
2971  * Reports an error during parsing.
2972  */
2973 static void LIBXML_ATTR_FORMAT(5,0)
xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaBasicItemPtr item,xmlNodePtr itemElem,const char * message,const xmlChar * str1)2974 xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
2975 		    xmlParserErrors error,
2976 		    xmlSchemaBasicItemPtr item,
2977 		    xmlNodePtr itemElem,
2978 		    const char *message,
2979 		    const xmlChar *str1)
2980 {
2981     xmlSchemaPCustomErrExt(ctxt, error, item, itemElem, message,
2982 	str1, NULL, NULL);
2983 }
2984 
2985 /**
2986  * xmlSchemaPAttrUseErr:
2987  * @ctxt: the schema parser context
2988  * @error: the error code
2989  * @itemDes: the designation of the schema type
2990  * @item: the schema type
2991  * @itemElem: the node of the schema type
2992  * @attr: the invalid schema attribute
2993  * @message: the error message
2994  * @str1: the optional param for the error message
2995  *
2996  * Reports an attribute use error during parsing.
2997  */
2998 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)2999 xmlSchemaPAttrUseErr4(xmlSchemaParserCtxtPtr ctxt,
3000 		    xmlParserErrors error,
3001 		    xmlNodePtr node,
3002 		    xmlSchemaBasicItemPtr ownerItem,
3003 		    const xmlSchemaAttributeUsePtr attruse,
3004 		    const char *message,
3005 		    const xmlChar *str1, const xmlChar *str2,
3006 		    const xmlChar *str3,const xmlChar *str4)
3007 {
3008     xmlChar *str = NULL, *msg = NULL;
3009 
3010     xmlSchemaFormatItemForReport(&msg, NULL, ownerItem, NULL);
3011     msg = xmlStrcat(msg, BAD_CAST ", ");
3012     msg = xmlStrcat(msg,
3013 	BAD_CAST xmlSchemaFormatItemForReport(&str, NULL,
3014 	WXS_BASIC_CAST attruse, NULL));
3015     FREE_AND_NULL(str);
3016     msg = xmlStrcat(msg, BAD_CAST ": ");
3017     msg = xmlStrcat(msg, (const xmlChar *) message);
3018     msg = xmlStrcat(msg, BAD_CAST ".\n");
3019     xmlSchemaErr4(ACTXT_CAST ctxt, error, node,
3020 	(const char *) msg, str1, str2, str3, str4);
3021     xmlFree(msg);
3022 }
3023 
3024 /**
3025  * xmlSchemaPIllegalFacetAtomicErr:
3026  * @ctxt: the schema parser context
3027  * @error: the error code
3028  * @type: the schema type
3029  * @baseType: the base type of type
3030  * @facet: the illegal facet
3031  *
3032  * Reports an illegal facet for atomic simple types.
3033  */
3034 static void
xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaTypePtr type,xmlSchemaTypePtr baseType,xmlSchemaFacetPtr facet)3035 xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
3036 			  xmlParserErrors error,
3037 			  xmlSchemaTypePtr type,
3038 			  xmlSchemaTypePtr baseType,
3039 			  xmlSchemaFacetPtr facet)
3040 {
3041     xmlChar *des = NULL, *strT = NULL;
3042 
3043     xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type, type->node);
3044     xmlSchemaPErrExt(ctxt, type->node, error, NULL, NULL, NULL,
3045 	"%s: The facet '%s' is not allowed on types derived from the "
3046 	"type %s.\n",
3047 	BAD_CAST des, xmlSchemaFacetTypeToString(facet->type),
3048 	xmlSchemaFormatItemForReport(&strT, NULL, WXS_BASIC_CAST baseType, NULL),
3049 	NULL, NULL);
3050     FREE_AND_NULL(des);
3051     FREE_AND_NULL(strT);
3052 }
3053 
3054 /**
3055  * xmlSchemaPIllegalFacetListUnionErr:
3056  * @ctxt: the schema parser context
3057  * @error: the error code
3058  * @itemDes: the designation of the schema item involved
3059  * @item: the schema item involved
3060  * @facet: the illegal facet
3061  *
3062  * Reports an illegal facet for <list> and <union>.
3063  */
3064 static void
xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaTypePtr type,xmlSchemaFacetPtr facet)3065 xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
3066 			  xmlParserErrors error,
3067 			  xmlSchemaTypePtr type,
3068 			  xmlSchemaFacetPtr facet)
3069 {
3070     xmlChar *des = NULL;
3071 
3072     xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type,
3073 	type->node);
3074     xmlSchemaPErr(ctxt, type->node, error,
3075 	"%s: The facet '%s' is not allowed.\n",
3076 	BAD_CAST des, xmlSchemaFacetTypeToString(facet->type));
3077     FREE_AND_NULL(des);
3078 }
3079 
3080 /**
3081  * xmlSchemaPMutualExclAttrErr:
3082  * @ctxt: the schema validation context
3083  * @error: the error code
3084  * @elemDes: the designation of the parent element node
3085  * @attr: the bad attribute node
3086  * @type: the corresponding type of the attribute node
3087  *
3088  * Reports an illegal attribute.
3089  */
3090 static void
xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaBasicItemPtr ownerItem,xmlAttrPtr attr,const char * name1,const char * name2)3091 xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
3092 			 xmlParserErrors error,
3093 			 xmlSchemaBasicItemPtr ownerItem,
3094 			 xmlAttrPtr attr,
3095 			 const char *name1,
3096 			 const char *name2)
3097 {
3098     xmlChar *des = NULL;
3099 
3100     xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST ownerItem, attr->parent);
3101     xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
3102 	"%s: The attributes '%s' and '%s' are mutually exclusive.\n",
3103 	BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
3104     FREE_AND_NULL(des);
3105 }
3106 
3107 /**
3108  * xmlSchemaPSimpleTypeErr:
3109  * @ctxt:  the schema validation context
3110  * @error: the error code
3111  * @type: the type specifier
3112  * @ownerDes: the designation of the owner
3113  * @ownerItem: the schema object if existent
3114  * @node: the validated node
3115  * @value: the validated value
3116  *
3117  * Reports a simple type validation error.
3118  * TODO: Should this report the value of an element as well?
3119  */
3120 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)3121 xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
3122 			xmlParserErrors error,
3123 			xmlSchemaBasicItemPtr ownerItem ATTRIBUTE_UNUSED,
3124 			xmlNodePtr node,
3125 			xmlSchemaTypePtr type,
3126 			const char *expected,
3127 			const xmlChar *value,
3128 			const char *message,
3129 			const xmlChar *str1,
3130 			const xmlChar *str2)
3131 {
3132     xmlChar *msg = NULL;
3133 
3134     xmlSchemaFormatNodeForError(&msg, ACTXT_CAST ctxt, node);
3135     if (message == NULL) {
3136 	/*
3137 	* Use default messages.
3138 	*/
3139 	if (type != NULL) {
3140 	    if (node->type == XML_ATTRIBUTE_NODE)
3141 		msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
3142 	    else
3143 		msg = xmlStrcat(msg, BAD_CAST "The character content is not a "
3144 		"valid value of ");
3145 	    if (! xmlSchemaIsGlobalItem(type))
3146 		msg = xmlStrcat(msg, BAD_CAST "the local ");
3147 	    else
3148 		msg = xmlStrcat(msg, BAD_CAST "the ");
3149 
3150 	    if (WXS_IS_ATOMIC(type))
3151 		msg = xmlStrcat(msg, BAD_CAST "atomic type");
3152 	    else if (WXS_IS_LIST(type))
3153 		msg = xmlStrcat(msg, BAD_CAST "list type");
3154 	    else if (WXS_IS_UNION(type))
3155 		msg = xmlStrcat(msg, BAD_CAST "union type");
3156 
3157 	    if (xmlSchemaIsGlobalItem(type)) {
3158 		xmlChar *str = NULL;
3159 		msg = xmlStrcat(msg, BAD_CAST " '");
3160 		if (type->builtInType != 0) {
3161 		    msg = xmlStrcat(msg, BAD_CAST "xs:");
3162 		    str = xmlStrdup(type->name);
3163 		} else {
3164 		    const xmlChar *qName = xmlSchemaFormatQName(&str, type->targetNamespace, type->name);
3165 		    if (!str)
3166 			str = xmlStrdup(qName);
3167 		}
3168 		msg = xmlStrcat(msg, xmlEscapeFormatString(&str));
3169 		msg = xmlStrcat(msg, BAD_CAST "'.");
3170 		FREE_AND_NULL(str);
3171 	    }
3172 	} else {
3173 	    if (node->type == XML_ATTRIBUTE_NODE)
3174 		msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not valid.");
3175 	    else
3176 		msg = xmlStrcat(msg, BAD_CAST "The character content is not "
3177 		"valid.");
3178 	}
3179 	if (expected) {
3180 	    xmlChar *expectedEscaped = xmlCharStrdup(expected);
3181 	    msg = xmlStrcat(msg, BAD_CAST " Expected is '");
3182 	    msg = xmlStrcat(msg, xmlEscapeFormatString(&expectedEscaped));
3183 	    FREE_AND_NULL(expectedEscaped);
3184 	    msg = xmlStrcat(msg, BAD_CAST "'.\n");
3185 	} else
3186 	    msg = xmlStrcat(msg, BAD_CAST "\n");
3187 	if (node->type == XML_ATTRIBUTE_NODE)
3188 	    xmlSchemaPErr(ctxt, node, error, (const char *) msg, value, NULL);
3189 	else
3190 	    xmlSchemaPErr(ctxt, node, error, (const char *) msg, NULL, NULL);
3191     } else {
3192 	msg = xmlStrcat(msg, BAD_CAST message);
3193 	msg = xmlStrcat(msg, BAD_CAST ".\n");
3194 	xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
3195 	     (const char*) msg, str1, str2, NULL, NULL, NULL);
3196     }
3197     /* Cleanup. */
3198     FREE_AND_NULL(msg)
3199 }
3200 
3201 /**
3202  * xmlSchemaPContentErr:
3203  * @ctxt: the schema parser context
3204  * @error: the error code
3205  * @onwerDes: the designation of the holder of the content
3206  * @ownerItem: the owner item of the holder of the content
3207  * @ownerElem: the node of the holder of the content
3208  * @child: the invalid child node
3209  * @message: the optional error message
3210  * @content: the optional string describing the correct content
3211  *
3212  * Reports an error concerning the content of a schema element.
3213  */
3214 static void
xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaBasicItemPtr ownerItem,xmlNodePtr ownerElem,xmlNodePtr child,const char * message,const char * content)3215 xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
3216 		     xmlParserErrors error,
3217 		     xmlSchemaBasicItemPtr ownerItem,
3218 		     xmlNodePtr ownerElem,
3219 		     xmlNodePtr child,
3220 		     const char *message,
3221 		     const char *content)
3222 {
3223     xmlChar *des = NULL;
3224 
3225     xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
3226     if (message != NULL)
3227 	xmlSchemaPErr2(ctxt, ownerElem, child, error,
3228 	    "%s: %s.\n",
3229 	    BAD_CAST des, BAD_CAST message);
3230     else {
3231 	if (content != NULL) {
3232 	    xmlSchemaPErr2(ctxt, ownerElem, child, error,
3233 		"%s: The content is not valid. Expected is %s.\n",
3234 		BAD_CAST des, BAD_CAST content);
3235 	} else {
3236 	    xmlSchemaPErr2(ctxt, ownerElem, child, error,
3237 		"%s: The content is not valid.\n",
3238 		BAD_CAST des, NULL);
3239 	}
3240     }
3241     FREE_AND_NULL(des)
3242 }
3243 
3244 /************************************************************************
3245  *									*
3246  *			Streamable error functions                      *
3247  *									*
3248  ************************************************************************/
3249 
3250 
3251 
3252 
3253 /************************************************************************
3254  *									*
3255  *			Validation helper functions			*
3256  *									*
3257  ************************************************************************/
3258 
3259 
3260 /************************************************************************
3261  *									*
3262  *			Allocation functions				*
3263  *									*
3264  ************************************************************************/
3265 
3266 /**
3267  * xmlSchemaNewSchemaForParserCtxt:
3268  * @ctxt:  a schema validation context
3269  *
3270  * Allocate a new Schema structure.
3271  *
3272  * Returns the newly allocated structure or NULL in case or error
3273  */
3274 static xmlSchemaPtr
xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)3275 xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
3276 {
3277     xmlSchemaPtr ret;
3278 
3279     ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
3280     if (ret == NULL) {
3281         xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
3282         return (NULL);
3283     }
3284     memset(ret, 0, sizeof(xmlSchema));
3285     ret->dict = ctxt->dict;
3286     xmlDictReference(ret->dict);
3287 
3288     return (ret);
3289 }
3290 
3291 /**
3292  * xmlSchemaNewFacet:
3293  *
3294  * Allocate a new Facet structure.
3295  *
3296  * Returns the newly allocated structure or NULL in case or error
3297  */
3298 xmlSchemaFacetPtr
xmlSchemaNewFacet(void)3299 xmlSchemaNewFacet(void)
3300 {
3301     xmlSchemaFacetPtr ret;
3302 
3303     ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
3304     if (ret == NULL) {
3305         return (NULL);
3306     }
3307     memset(ret, 0, sizeof(xmlSchemaFacet));
3308 
3309     return (ret);
3310 }
3311 
3312 /**
3313  * xmlSchemaNewAnnot:
3314  * @ctxt:  a schema validation context
3315  * @node:  a node
3316  *
3317  * Allocate a new annotation structure.
3318  *
3319  * Returns the newly allocated structure or NULL in case or error
3320  */
3321 static xmlSchemaAnnotPtr
xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node)3322 xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3323 {
3324     xmlSchemaAnnotPtr ret;
3325 
3326     ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
3327     if (ret == NULL) {
3328         xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
3329         return (NULL);
3330     }
3331     memset(ret, 0, sizeof(xmlSchemaAnnot));
3332     ret->content = node;
3333     return (ret);
3334 }
3335 
3336 static xmlSchemaItemListPtr
xmlSchemaItemListCreate(void)3337 xmlSchemaItemListCreate(void)
3338 {
3339     xmlSchemaItemListPtr ret;
3340 
3341     ret = xmlMalloc(sizeof(xmlSchemaItemList));
3342     if (ret == NULL) {
3343 	xmlSchemaPErrMemory(NULL,
3344 	    "allocating an item list structure", NULL);
3345 	return (NULL);
3346     }
3347     memset(ret, 0, sizeof(xmlSchemaItemList));
3348     return (ret);
3349 }
3350 
3351 static void
xmlSchemaItemListClear(xmlSchemaItemListPtr list)3352 xmlSchemaItemListClear(xmlSchemaItemListPtr list)
3353 {
3354     if (list->items != NULL) {
3355 	xmlFree(list->items);
3356 	list->items = NULL;
3357     }
3358     list->nbItems = 0;
3359     list->sizeItems = 0;
3360 }
3361 
3362 static int
xmlSchemaItemListAdd(xmlSchemaItemListPtr list,void * item)3363 xmlSchemaItemListAdd(xmlSchemaItemListPtr list, void *item)
3364 {
3365     if (list->items == NULL) {
3366 	list->items = (void **) xmlMalloc(
3367 	    20 * sizeof(void *));
3368 	if (list->items == NULL) {
3369 	    xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3370 	    return(-1);
3371 	}
3372 	list->sizeItems = 20;
3373     } else if (list->sizeItems <= list->nbItems) {
3374 	list->sizeItems *= 2;
3375 	list->items = (void **) xmlRealloc(list->items,
3376 	    list->sizeItems * sizeof(void *));
3377 	if (list->items == NULL) {
3378 	    xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3379 	    list->sizeItems = 0;
3380 	    return(-1);
3381 	}
3382     }
3383     list->items[list->nbItems++] = item;
3384     return(0);
3385 }
3386 
3387 static int
xmlSchemaItemListAddSize(xmlSchemaItemListPtr list,int initialSize,void * item)3388 xmlSchemaItemListAddSize(xmlSchemaItemListPtr list,
3389 			 int initialSize,
3390 			 void *item)
3391 {
3392     if (list->items == NULL) {
3393 	if (initialSize <= 0)
3394 	    initialSize = 1;
3395 	list->items = (void **) xmlMalloc(
3396 	    initialSize * sizeof(void *));
3397 	if (list->items == NULL) {
3398 	    xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3399 	    return(-1);
3400 	}
3401 	list->sizeItems = initialSize;
3402     } else if (list->sizeItems <= list->nbItems) {
3403 	list->sizeItems *= 2;
3404 	list->items = (void **) xmlRealloc(list->items,
3405 	    list->sizeItems * sizeof(void *));
3406 	if (list->items == NULL) {
3407 	    xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3408 	    list->sizeItems = 0;
3409 	    return(-1);
3410 	}
3411     }
3412     list->items[list->nbItems++] = item;
3413     return(0);
3414 }
3415 
3416 static int
xmlSchemaItemListInsert(xmlSchemaItemListPtr list,void * item,int idx)3417 xmlSchemaItemListInsert(xmlSchemaItemListPtr list, void *item, int idx)
3418 {
3419     if (list->items == NULL) {
3420 	list->items = (void **) xmlMalloc(
3421 	    20 * sizeof(void *));
3422 	if (list->items == NULL) {
3423 	    xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3424 	    return(-1);
3425 	}
3426 	list->sizeItems = 20;
3427     } else if (list->sizeItems <= list->nbItems) {
3428 	list->sizeItems *= 2;
3429 	list->items = (void **) xmlRealloc(list->items,
3430 	    list->sizeItems * sizeof(void *));
3431 	if (list->items == NULL) {
3432 	    xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3433 	    list->sizeItems = 0;
3434 	    return(-1);
3435 	}
3436     }
3437     /*
3438     * Just append if the index is greater/equal than the item count.
3439     */
3440     if (idx >= list->nbItems) {
3441 	list->items[list->nbItems++] = item;
3442     } else {
3443 	int i;
3444 	for (i = list->nbItems; i > idx; i--)
3445 	    list->items[i] = list->items[i-1];
3446 	list->items[idx] = item;
3447 	list->nbItems++;
3448     }
3449     return(0);
3450 }
3451 
3452 #if 0 /* enable if ever needed */
3453 static int
3454 xmlSchemaItemListInsertSize(xmlSchemaItemListPtr list,
3455 			    int initialSize,
3456 			    void *item,
3457 			    int idx)
3458 {
3459     if (list->items == NULL) {
3460 	if (initialSize <= 0)
3461 	    initialSize = 1;
3462 	list->items = (void **) xmlMalloc(
3463 	    initialSize * sizeof(void *));
3464 	if (list->items == NULL) {
3465 	    xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3466 	    return(-1);
3467 	}
3468 	list->sizeItems = initialSize;
3469     } else if (list->sizeItems <= list->nbItems) {
3470 	list->sizeItems *= 2;
3471 	list->items = (void **) xmlRealloc(list->items,
3472 	    list->sizeItems * sizeof(void *));
3473 	if (list->items == NULL) {
3474 	    xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3475 	    list->sizeItems = 0;
3476 	    return(-1);
3477 	}
3478     }
3479     /*
3480     * Just append if the index is greater/equal than the item count.
3481     */
3482     if (idx >= list->nbItems) {
3483 	list->items[list->nbItems++] = item;
3484     } else {
3485 	int i;
3486 	for (i = list->nbItems; i > idx; i--)
3487 	    list->items[i] = list->items[i-1];
3488 	list->items[idx] = item;
3489 	list->nbItems++;
3490     }
3491     return(0);
3492 }
3493 #endif
3494 
3495 static int
xmlSchemaItemListRemove(xmlSchemaItemListPtr list,int idx)3496 xmlSchemaItemListRemove(xmlSchemaItemListPtr list, int idx)
3497 {
3498     int i;
3499     if ((list->items == NULL) || (idx >= list->nbItems)) {
3500 	xmlSchemaPSimpleErr("Internal error: xmlSchemaItemListRemove, "
3501 	    "index error.\n");
3502 	return(-1);
3503     }
3504 
3505     if (list->nbItems == 1) {
3506 	/* TODO: Really free the list? */
3507 	xmlFree(list->items);
3508 	list->items = NULL;
3509 	list->nbItems = 0;
3510 	list->sizeItems = 0;
3511     } else if (list->nbItems -1 == idx) {
3512 	list->nbItems--;
3513     } else {
3514 	for (i = idx; i < list->nbItems -1; i++)
3515 	    list->items[i] = list->items[i+1];
3516 	list->nbItems--;
3517     }
3518     return(0);
3519 }
3520 
3521 /**
3522  * xmlSchemaItemListFree:
3523  * @annot:  a schema type structure
3524  *
3525  * Deallocate a annotation structure
3526  */
3527 static void
xmlSchemaItemListFree(xmlSchemaItemListPtr list)3528 xmlSchemaItemListFree(xmlSchemaItemListPtr list)
3529 {
3530     if (list == NULL)
3531 	return;
3532     if (list->items != NULL)
3533 	xmlFree(list->items);
3534     xmlFree(list);
3535 }
3536 
3537 static void
xmlSchemaBucketFree(xmlSchemaBucketPtr bucket)3538 xmlSchemaBucketFree(xmlSchemaBucketPtr bucket)
3539 {
3540     if (bucket == NULL)
3541 	return;
3542     if (bucket->globals != NULL) {
3543 	xmlSchemaComponentListFree(bucket->globals);
3544 	xmlSchemaItemListFree(bucket->globals);
3545     }
3546     if (bucket->locals != NULL) {
3547 	xmlSchemaComponentListFree(bucket->locals);
3548 	xmlSchemaItemListFree(bucket->locals);
3549     }
3550     if (bucket->relations != NULL) {
3551 	xmlSchemaSchemaRelationPtr prev, cur = bucket->relations;
3552 	do {
3553 	    prev = cur;
3554 	    cur = cur->next;
3555 	    xmlFree(prev);
3556 	} while (cur != NULL);
3557     }
3558     if ((! bucket->preserveDoc) && (bucket->doc != NULL)) {
3559 	xmlFreeDoc(bucket->doc);
3560     }
3561     if (bucket->type == XML_SCHEMA_SCHEMA_IMPORT) {
3562 	if (WXS_IMPBUCKET(bucket)->schema != NULL)
3563 	    xmlSchemaFree(WXS_IMPBUCKET(bucket)->schema);
3564     }
3565     xmlFree(bucket);
3566 }
3567 
3568 static void
xmlSchemaBucketFreeEntry(void * bucket,const xmlChar * name ATTRIBUTE_UNUSED)3569 xmlSchemaBucketFreeEntry(void *bucket, const xmlChar *name ATTRIBUTE_UNUSED)
3570 {
3571     xmlSchemaBucketFree((xmlSchemaBucketPtr) bucket);
3572 }
3573 
3574 static xmlSchemaBucketPtr
xmlSchemaBucketCreate(xmlSchemaParserCtxtPtr pctxt,int type,const xmlChar * targetNamespace)3575 xmlSchemaBucketCreate(xmlSchemaParserCtxtPtr pctxt,
3576 			 int type, const xmlChar *targetNamespace)
3577 {
3578     xmlSchemaBucketPtr ret;
3579     int size;
3580     xmlSchemaPtr mainSchema;
3581 
3582     if (WXS_CONSTRUCTOR(pctxt)->mainSchema == NULL) {
3583 	PERROR_INT("xmlSchemaBucketCreate",
3584 	    "no main schema on constructor");
3585 	return(NULL);
3586     }
3587     mainSchema = WXS_CONSTRUCTOR(pctxt)->mainSchema;
3588     /* Create the schema bucket. */
3589     if (WXS_IS_BUCKET_INCREDEF(type))
3590 	size = sizeof(xmlSchemaInclude);
3591     else
3592 	size = sizeof(xmlSchemaImport);
3593     ret = (xmlSchemaBucketPtr) xmlMalloc(size);
3594     if (ret == NULL) {
3595 	xmlSchemaPErrMemory(NULL, "allocating schema bucket", NULL);
3596 	return(NULL);
3597     }
3598     memset(ret, 0, size);
3599     ret->targetNamespace = targetNamespace;
3600     ret->type = type;
3601     ret->globals = xmlSchemaItemListCreate();
3602     if (ret->globals == NULL) {
3603 	xmlFree(ret);
3604 	return(NULL);
3605     }
3606     ret->locals = xmlSchemaItemListCreate();
3607     if (ret->locals == NULL) {
3608 	xmlFree(ret);
3609 	return(NULL);
3610     }
3611     /*
3612     * The following will assure that only the first bucket is marked as
3613     * XML_SCHEMA_SCHEMA_MAIN and it points to the *main* schema.
3614     * For each following import buckets an xmlSchema will be created.
3615     * An xmlSchema will be created for every distinct targetNamespace.
3616     * We assign the targetNamespace to the schemata here.
3617     */
3618     if (! WXS_HAS_BUCKETS(pctxt)) {
3619 	if (WXS_IS_BUCKET_INCREDEF(type)) {
3620 	    PERROR_INT("xmlSchemaBucketCreate",
3621 		"first bucket but it's an include or redefine");
3622 	    xmlSchemaBucketFree(ret);
3623 	    return(NULL);
3624 	}
3625 	/* Force the type to be XML_SCHEMA_SCHEMA_MAIN. */
3626 	ret->type = XML_SCHEMA_SCHEMA_MAIN;
3627 	/* Point to the *main* schema. */
3628 	WXS_CONSTRUCTOR(pctxt)->mainBucket = ret;
3629 	WXS_IMPBUCKET(ret)->schema = mainSchema;
3630 	/*
3631 	* Ensure that the main schema gets a targetNamespace.
3632 	*/
3633 	mainSchema->targetNamespace = targetNamespace;
3634     } else {
3635 	if (type == XML_SCHEMA_SCHEMA_MAIN) {
3636 	    PERROR_INT("xmlSchemaBucketCreate",
3637 		"main bucket but it's not the first one");
3638 	    xmlSchemaBucketFree(ret);
3639 	    return(NULL);
3640 	} else if (type == XML_SCHEMA_SCHEMA_IMPORT) {
3641 	    /*
3642 	    * Create a schema for imports and assign the
3643 	    * targetNamespace.
3644 	    */
3645 	    WXS_IMPBUCKET(ret)->schema = xmlSchemaNewSchema(pctxt);
3646 	    if (WXS_IMPBUCKET(ret)->schema == NULL) {
3647 		xmlSchemaBucketFree(ret);
3648 		return(NULL);
3649 	    }
3650 	    WXS_IMPBUCKET(ret)->schema->targetNamespace = targetNamespace;
3651 	}
3652     }
3653     if (WXS_IS_BUCKET_IMPMAIN(type)) {
3654 	int res;
3655 	/*
3656 	* Imports go into the "schemasImports" slot of the main *schema*.
3657 	* Note that we create an import entry for the main schema as well; i.e.,
3658 	* even if there's only one schema, we'll get an import.
3659 	*/
3660 	if (mainSchema->schemasImports == NULL) {
3661 	    mainSchema->schemasImports = xmlHashCreateDict(5,
3662 		WXS_CONSTRUCTOR(pctxt)->dict);
3663 	    if (mainSchema->schemasImports == NULL) {
3664 		xmlSchemaBucketFree(ret);
3665 		return(NULL);
3666 	    }
3667 	}
3668 	if (targetNamespace == NULL)
3669 	    res = xmlHashAddEntry(mainSchema->schemasImports,
3670 		XML_SCHEMAS_NO_NAMESPACE, ret);
3671 	else
3672 	    res = xmlHashAddEntry(mainSchema->schemasImports,
3673 		targetNamespace, ret);
3674 	if (res != 0) {
3675 	    PERROR_INT("xmlSchemaBucketCreate",
3676 		"failed to add the schema bucket to the hash");
3677 	    xmlSchemaBucketFree(ret);
3678 	    return(NULL);
3679 	}
3680     } else {
3681 	/* Set the @ownerImport of an include bucket. */
3682 	if (WXS_IS_BUCKET_IMPMAIN(WXS_CONSTRUCTOR(pctxt)->bucket->type))
3683 	    WXS_INCBUCKET(ret)->ownerImport =
3684 		WXS_IMPBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket);
3685 	else
3686 	    WXS_INCBUCKET(ret)->ownerImport =
3687 		WXS_INCBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket)->ownerImport;
3688 
3689 	/* Includes got into the "includes" slot of the *main* schema. */
3690 	if (mainSchema->includes == NULL) {
3691 	    mainSchema->includes = xmlSchemaItemListCreate();
3692 	    if (mainSchema->includes == NULL) {
3693 		xmlSchemaBucketFree(ret);
3694 		return(NULL);
3695 	    }
3696 	}
3697 	xmlSchemaItemListAdd(mainSchema->includes, ret);
3698     }
3699     /*
3700     * Add to list of all buckets; this is used for lookup
3701     * during schema construction time only.
3702     */
3703     if (xmlSchemaItemListAdd(WXS_CONSTRUCTOR(pctxt)->buckets, ret) == -1)
3704 	return(NULL);
3705     return(ret);
3706 }
3707 
3708 static int
xmlSchemaAddItemSize(xmlSchemaItemListPtr * list,int initialSize,void * item)3709 xmlSchemaAddItemSize(xmlSchemaItemListPtr *list, int initialSize, void *item)
3710 {
3711     if (*list == NULL) {
3712 	*list = xmlSchemaItemListCreate();
3713 	if (*list == NULL)
3714 	    return(-1);
3715     }
3716     xmlSchemaItemListAddSize(*list, initialSize, item);
3717     return(0);
3718 }
3719 
3720 /**
3721  * xmlSchemaFreeAnnot:
3722  * @annot:  a schema type structure
3723  *
3724  * Deallocate a annotation structure
3725  */
3726 static void
xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)3727 xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
3728 {
3729     if (annot == NULL)
3730         return;
3731     if (annot->next == NULL) {
3732 	xmlFree(annot);
3733     } else {
3734 	xmlSchemaAnnotPtr prev;
3735 
3736 	do {
3737 	    prev = annot;
3738 	    annot = annot->next;
3739 	    xmlFree(prev);
3740 	} while (annot != NULL);
3741     }
3742 }
3743 
3744 /**
3745  * xmlSchemaFreeNotation:
3746  * @schema:  a schema notation structure
3747  *
3748  * Deallocate a Schema Notation structure.
3749  */
3750 static void
xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)3751 xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
3752 {
3753     if (nota == NULL)
3754         return;
3755     xmlFree(nota);
3756 }
3757 
3758 /**
3759  * xmlSchemaFreeAttribute:
3760  * @attr:  an attribute declaration
3761  *
3762  * Deallocates an attribute declaration structure.
3763  */
3764 static void
xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)3765 xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
3766 {
3767     if (attr == NULL)
3768         return;
3769     if (attr->annot != NULL)
3770 	xmlSchemaFreeAnnot(attr->annot);
3771     if (attr->defVal != NULL)
3772 	xmlSchemaFreeValue(attr->defVal);
3773     xmlFree(attr);
3774 }
3775 
3776 /**
3777  * xmlSchemaFreeAttributeUse:
3778  * @use:  an attribute use
3779  *
3780  * Deallocates an attribute use structure.
3781  */
3782 static void
xmlSchemaFreeAttributeUse(xmlSchemaAttributeUsePtr use)3783 xmlSchemaFreeAttributeUse(xmlSchemaAttributeUsePtr use)
3784 {
3785     if (use == NULL)
3786         return;
3787     if (use->annot != NULL)
3788 	xmlSchemaFreeAnnot(use->annot);
3789     if (use->defVal != NULL)
3790 	xmlSchemaFreeValue(use->defVal);
3791     xmlFree(use);
3792 }
3793 
3794 /**
3795  * xmlSchemaFreeAttributeUseProhib:
3796  * @prohib:  an attribute use prohibition
3797  *
3798  * Deallocates an attribute use structure.
3799  */
3800 static void
xmlSchemaFreeAttributeUseProhib(xmlSchemaAttributeUseProhibPtr prohib)3801 xmlSchemaFreeAttributeUseProhib(xmlSchemaAttributeUseProhibPtr prohib)
3802 {
3803     if (prohib == NULL)
3804         return;
3805     xmlFree(prohib);
3806 }
3807 
3808 /**
3809  * xmlSchemaFreeWildcardNsSet:
3810  * set:  a schema wildcard namespace
3811  *
3812  * Deallocates a list of wildcard constraint structures.
3813  */
3814 static void
xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)3815 xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
3816 {
3817     xmlSchemaWildcardNsPtr next;
3818 
3819     while (set != NULL) {
3820 	next = set->next;
3821 	xmlFree(set);
3822 	set = next;
3823     }
3824 }
3825 
3826 /**
3827  * xmlSchemaFreeWildcard:
3828  * @wildcard:  a wildcard structure
3829  *
3830  * Deallocates a wildcard structure.
3831  */
3832 void
xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)3833 xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
3834 {
3835     if (wildcard == NULL)
3836         return;
3837     if (wildcard->annot != NULL)
3838         xmlSchemaFreeAnnot(wildcard->annot);
3839     if (wildcard->nsSet != NULL)
3840 	xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
3841     if (wildcard->negNsSet != NULL)
3842 	xmlFree(wildcard->negNsSet);
3843     xmlFree(wildcard);
3844 }
3845 
3846 /**
3847  * xmlSchemaFreeAttributeGroup:
3848  * @schema:  a schema attribute group structure
3849  *
3850  * Deallocate a Schema Attribute Group structure.
3851  */
3852 static void
xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attrGr)3853 xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attrGr)
3854 {
3855     if (attrGr == NULL)
3856         return;
3857     if (attrGr->annot != NULL)
3858         xmlSchemaFreeAnnot(attrGr->annot);
3859     if (attrGr->attrUses != NULL)
3860 	xmlSchemaItemListFree(WXS_LIST_CAST attrGr->attrUses);
3861     xmlFree(attrGr);
3862 }
3863 
3864 /**
3865  * xmlSchemaFreeQNameRef:
3866  * @item: a QName reference structure
3867  *
3868  * Deallocatea a QName reference structure.
3869  */
3870 static void
xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item)3871 xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item)
3872 {
3873     xmlFree(item);
3874 }
3875 
3876 /**
3877  * xmlSchemaFreeTypeLinkList:
3878  * @alink: a type link
3879  *
3880  * Deallocate a list of types.
3881  */
3882 static void
xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)3883 xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
3884 {
3885     xmlSchemaTypeLinkPtr next;
3886 
3887     while (link != NULL) {
3888 	next = link->next;
3889 	xmlFree(link);
3890 	link = next;
3891     }
3892 }
3893 
3894 static void
xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)3895 xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
3896 {
3897     xmlSchemaIDCStateObjPtr next;
3898     while (sto != NULL) {
3899 	next = sto->next;
3900 	if (sto->history != NULL)
3901 	    xmlFree(sto->history);
3902 	if (sto->xpathCtxt != NULL)
3903 	    xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
3904 	xmlFree(sto);
3905 	sto = next;
3906     }
3907 }
3908 
3909 /**
3910  * xmlSchemaFreeIDC:
3911  * @idc: a identity-constraint definition
3912  *
3913  * Deallocates an identity-constraint definition.
3914  */
3915 static void
xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)3916 xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)
3917 {
3918     xmlSchemaIDCSelectPtr cur, prev;
3919 
3920     if (idcDef == NULL)
3921 	return;
3922     if (idcDef->annot != NULL)
3923         xmlSchemaFreeAnnot(idcDef->annot);
3924     /* Selector */
3925     if (idcDef->selector != NULL) {
3926 	if (idcDef->selector->xpathComp != NULL)
3927 	    xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp);
3928 	xmlFree(idcDef->selector);
3929     }
3930     /* Fields */
3931     if (idcDef->fields != NULL) {
3932 	cur = idcDef->fields;
3933 	do {
3934 	    prev = cur;
3935 	    cur = cur->next;
3936 	    if (prev->xpathComp != NULL)
3937 		xmlFreePattern((xmlPatternPtr) prev->xpathComp);
3938 	    xmlFree(prev);
3939 	} while (cur != NULL);
3940     }
3941     xmlFree(idcDef);
3942 }
3943 
3944 /**
3945  * xmlSchemaFreeElement:
3946  * @schema:  a schema element structure
3947  *
3948  * Deallocate a Schema Element structure.
3949  */
3950 static void
xmlSchemaFreeElement(xmlSchemaElementPtr elem)3951 xmlSchemaFreeElement(xmlSchemaElementPtr elem)
3952 {
3953     if (elem == NULL)
3954         return;
3955     if (elem->annot != NULL)
3956         xmlSchemaFreeAnnot(elem->annot);
3957     if (elem->contModel != NULL)
3958         xmlRegFreeRegexp(elem->contModel);
3959     if (elem->defVal != NULL)
3960 	xmlSchemaFreeValue(elem->defVal);
3961     xmlFree(elem);
3962 }
3963 
3964 /**
3965  * xmlSchemaFreeFacet:
3966  * @facet:  a schema facet structure
3967  *
3968  * Deallocate a Schema Facet structure.
3969  */
3970 void
xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)3971 xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
3972 {
3973     if (facet == NULL)
3974         return;
3975     if (facet->val != NULL)
3976         xmlSchemaFreeValue(facet->val);
3977     if (facet->regexp != NULL)
3978         xmlRegFreeRegexp(facet->regexp);
3979     if (facet->annot != NULL)
3980         xmlSchemaFreeAnnot(facet->annot);
3981     xmlFree(facet);
3982 }
3983 
3984 /**
3985  * xmlSchemaFreeType:
3986  * @type:  a schema type structure
3987  *
3988  * Deallocate a Schema Type structure.
3989  */
3990 void
xmlSchemaFreeType(xmlSchemaTypePtr type)3991 xmlSchemaFreeType(xmlSchemaTypePtr type)
3992 {
3993     if (type == NULL)
3994         return;
3995     if (type->annot != NULL)
3996         xmlSchemaFreeAnnot(type->annot);
3997     if (type->facets != NULL) {
3998         xmlSchemaFacetPtr facet, next;
3999 
4000         facet = type->facets;
4001         while (facet != NULL) {
4002             next = facet->next;
4003             xmlSchemaFreeFacet(facet);
4004             facet = next;
4005         }
4006     }
4007     if (type->attrUses != NULL)
4008 	xmlSchemaItemListFree((xmlSchemaItemListPtr) type->attrUses);
4009     if (type->memberTypes != NULL)
4010 	xmlSchemaFreeTypeLinkList(type->memberTypes);
4011     if (type->facetSet != NULL) {
4012 	xmlSchemaFacetLinkPtr next, link;
4013 
4014 	link = type->facetSet;
4015 	do {
4016 	    next = link->next;
4017 	    xmlFree(link);
4018 	    link = next;
4019 	} while (link != NULL);
4020     }
4021     if (type->contModel != NULL)
4022         xmlRegFreeRegexp(type->contModel);
4023     xmlFree(type);
4024 }
4025 
4026 /**
4027  * xmlSchemaFreeModelGroupDef:
4028  * @item:  a schema model group definition
4029  *
4030  * Deallocates a schema model group definition.
4031  */
4032 static void
xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item)4033 xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item)
4034 {
4035     if (item->annot != NULL)
4036 	xmlSchemaFreeAnnot(item->annot);
4037     xmlFree(item);
4038 }
4039 
4040 /**
4041  * xmlSchemaFreeModelGroup:
4042  * @item:  a schema model group
4043  *
4044  * Deallocates a schema model group structure.
4045  */
4046 static void
xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item)4047 xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item)
4048 {
4049     if (item->annot != NULL)
4050 	xmlSchemaFreeAnnot(item->annot);
4051     xmlFree(item);
4052 }
4053 
4054 static void
xmlSchemaComponentListFree(xmlSchemaItemListPtr list)4055 xmlSchemaComponentListFree(xmlSchemaItemListPtr list)
4056 {
4057     if ((list == NULL) || (list->nbItems == 0))
4058 	return;
4059     {
4060 	xmlSchemaTreeItemPtr item;
4061 	xmlSchemaTreeItemPtr *items = (xmlSchemaTreeItemPtr *) list->items;
4062 	int i;
4063 
4064 	for (i = 0; i < list->nbItems; i++) {
4065 	    item = items[i];
4066 	    if (item == NULL)
4067 		continue;
4068 	    switch (item->type) {
4069 		case XML_SCHEMA_TYPE_SIMPLE:
4070 		case XML_SCHEMA_TYPE_COMPLEX:
4071 		    xmlSchemaFreeType((xmlSchemaTypePtr) item);
4072 		    break;
4073 		case XML_SCHEMA_TYPE_ATTRIBUTE:
4074 		    xmlSchemaFreeAttribute((xmlSchemaAttributePtr) item);
4075 		    break;
4076 		case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
4077 		    xmlSchemaFreeAttributeUse((xmlSchemaAttributeUsePtr) item);
4078 		    break;
4079 		case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
4080 		    xmlSchemaFreeAttributeUseProhib(
4081 			(xmlSchemaAttributeUseProhibPtr) item);
4082 		    break;
4083 		case XML_SCHEMA_TYPE_ELEMENT:
4084 		    xmlSchemaFreeElement((xmlSchemaElementPtr) item);
4085 		    break;
4086 		case XML_SCHEMA_TYPE_PARTICLE:
4087 		    if (item->annot != NULL)
4088 			xmlSchemaFreeAnnot(item->annot);
4089 		    xmlFree(item);
4090 		    break;
4091 		case XML_SCHEMA_TYPE_SEQUENCE:
4092 		case XML_SCHEMA_TYPE_CHOICE:
4093 		case XML_SCHEMA_TYPE_ALL:
4094 		    xmlSchemaFreeModelGroup((xmlSchemaModelGroupPtr) item);
4095 		    break;
4096 		case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
4097 		    xmlSchemaFreeAttributeGroup(
4098 			(xmlSchemaAttributeGroupPtr) item);
4099 		    break;
4100 		case XML_SCHEMA_TYPE_GROUP:
4101 		    xmlSchemaFreeModelGroupDef(
4102 			(xmlSchemaModelGroupDefPtr) item);
4103 		    break;
4104 		case XML_SCHEMA_TYPE_ANY:
4105 		case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
4106 		    xmlSchemaFreeWildcard((xmlSchemaWildcardPtr) item);
4107 		    break;
4108 		case XML_SCHEMA_TYPE_IDC_KEY:
4109 		case XML_SCHEMA_TYPE_IDC_UNIQUE:
4110 		case XML_SCHEMA_TYPE_IDC_KEYREF:
4111 		    xmlSchemaFreeIDC((xmlSchemaIDCPtr) item);
4112 		    break;
4113 		case XML_SCHEMA_TYPE_NOTATION:
4114 		    xmlSchemaFreeNotation((xmlSchemaNotationPtr) item);
4115 		    break;
4116 		case XML_SCHEMA_EXTRA_QNAMEREF:
4117 		    xmlSchemaFreeQNameRef((xmlSchemaQNameRefPtr) item);
4118 		    break;
4119 		default: {
4120 		    /* TODO: This should never be hit. */
4121 		    xmlSchemaPSimpleInternalErr(NULL,
4122 			"Internal error: xmlSchemaComponentListFree, "
4123 			"unexpected component type '%s'\n",
4124 			(const xmlChar *) WXS_ITEM_TYPE_NAME(item));
4125 			 }
4126 		    break;
4127 	    }
4128 	}
4129 	list->nbItems = 0;
4130     }
4131 }
4132 
4133 /**
4134  * xmlSchemaFree:
4135  * @schema:  a schema structure
4136  *
4137  * Deallocate a Schema structure.
4138  */
4139 void
xmlSchemaFree(xmlSchemaPtr schema)4140 xmlSchemaFree(xmlSchemaPtr schema)
4141 {
4142     if (schema == NULL)
4143         return;
4144     /* @volatiles is not used anymore :-/ */
4145     if (schema->volatiles != NULL)
4146 	TODO
4147     /*
4148     * Note that those slots are not responsible for freeing
4149     * schema components anymore; this will now be done by
4150     * the schema buckets.
4151     */
4152     if (schema->notaDecl != NULL)
4153         xmlHashFree(schema->notaDecl, NULL);
4154     if (schema->attrDecl != NULL)
4155         xmlHashFree(schema->attrDecl, NULL);
4156     if (schema->attrgrpDecl != NULL)
4157         xmlHashFree(schema->attrgrpDecl, NULL);
4158     if (schema->elemDecl != NULL)
4159         xmlHashFree(schema->elemDecl, NULL);
4160     if (schema->typeDecl != NULL)
4161         xmlHashFree(schema->typeDecl, NULL);
4162     if (schema->groupDecl != NULL)
4163         xmlHashFree(schema->groupDecl, NULL);
4164     if (schema->idcDef != NULL)
4165         xmlHashFree(schema->idcDef, NULL);
4166 
4167     if (schema->schemasImports != NULL)
4168 	xmlHashFree(schema->schemasImports, xmlSchemaBucketFreeEntry);
4169     if (schema->includes != NULL) {
4170 	xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) schema->includes;
4171 	int i;
4172 	for (i = 0; i < list->nbItems; i++) {
4173 	    xmlSchemaBucketFree((xmlSchemaBucketPtr) list->items[i]);
4174 	}
4175 	xmlSchemaItemListFree(list);
4176     }
4177     if (schema->annot != NULL)
4178         xmlSchemaFreeAnnot(schema->annot);
4179     /* Never free the doc here, since this will be done by the buckets. */
4180 
4181     xmlDictFree(schema->dict);
4182     xmlFree(schema);
4183 }
4184 
4185 /************************************************************************
4186  *									*
4187  *			Debug functions					*
4188  *									*
4189  ************************************************************************/
4190 
4191 #ifdef LIBXML_OUTPUT_ENABLED
4192 
4193 static void
4194 xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output); /* forward */
4195 
4196 /**
4197  * xmlSchemaElementDump:
4198  * @elem:  an element
4199  * @output:  the file output
4200  *
4201  * Dump the element
4202  */
4203 static void
xmlSchemaElementDump(void * payload,void * data,const xmlChar * name ATTRIBUTE_UNUSED,const xmlChar * namespace ATTRIBUTE_UNUSED,const xmlChar * context ATTRIBUTE_UNUSED)4204 xmlSchemaElementDump(void *payload, void *data,
4205                      const xmlChar * name ATTRIBUTE_UNUSED,
4206 		     const xmlChar * namespace ATTRIBUTE_UNUSED,
4207                      const xmlChar * context ATTRIBUTE_UNUSED)
4208 {
4209     xmlSchemaElementPtr elem = (xmlSchemaElementPtr) payload;
4210     FILE *output = (FILE *) data;
4211     if (elem == NULL)
4212         return;
4213 
4214 
4215     fprintf(output, "Element");
4216     if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
4217 	fprintf(output, " (global)");
4218     fprintf(output, ": '%s' ", elem->name);
4219     if (namespace != NULL)
4220 	fprintf(output, "ns '%s'", namespace);
4221     fprintf(output, "\n");
4222 #if 0
4223     if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
4224 	fprintf(output, "  min %d ", elem->minOccurs);
4225         if (elem->maxOccurs >= UNBOUNDED)
4226             fprintf(output, "max: unbounded\n");
4227         else if (elem->maxOccurs != 1)
4228             fprintf(output, "max: %d\n", elem->maxOccurs);
4229         else
4230             fprintf(output, "\n");
4231     }
4232 #endif
4233     /*
4234     * Misc other properties.
4235     */
4236     if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
4237 	(elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
4238 	(elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
4239 	(elem->flags & XML_SCHEMAS_ELEM_DEFAULT)) {
4240 	fprintf(output, "  props: ");
4241 	if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
4242 	    fprintf(output, "[fixed] ");
4243 	if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
4244 	    fprintf(output, "[default] ");
4245 	if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
4246 	    fprintf(output, "[abstract] ");
4247 	if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
4248 	    fprintf(output, "[nillable] ");
4249 	fprintf(output, "\n");
4250     }
4251     /*
4252     * Default/fixed value.
4253     */
4254     if (elem->value != NULL)
4255 	fprintf(output, "  value: '%s'\n", elem->value);
4256     /*
4257     * Type.
4258     */
4259     if (elem->namedType != NULL) {
4260 	fprintf(output, "  type: '%s' ", elem->namedType);
4261 	if (elem->namedTypeNs != NULL)
4262 	    fprintf(output, "ns '%s'\n", elem->namedTypeNs);
4263 	else
4264 	    fprintf(output, "\n");
4265     } else if (elem->subtypes != NULL) {
4266 	/*
4267 	* Dump local types.
4268 	*/
4269 	xmlSchemaTypeDump(elem->subtypes, output);
4270     }
4271     /*
4272     * Substitution group.
4273     */
4274     if (elem->substGroup != NULL) {
4275 	fprintf(output, "  substitutionGroup: '%s' ", elem->substGroup);
4276 	if (elem->substGroupNs != NULL)
4277 	    fprintf(output, "ns '%s'\n", elem->substGroupNs);
4278 	else
4279 	    fprintf(output, "\n");
4280     }
4281 }
4282 
4283 /**
4284  * xmlSchemaAnnotDump:
4285  * @output:  the file output
4286  * @annot:  a annotation
4287  *
4288  * Dump the annotation
4289  */
4290 static void
xmlSchemaAnnotDump(FILE * output,xmlSchemaAnnotPtr annot)4291 xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
4292 {
4293     xmlChar *content;
4294 
4295     if (annot == NULL)
4296         return;
4297 
4298     content = xmlNodeGetContent(annot->content);
4299     if (content != NULL) {
4300         fprintf(output, "  Annot: %s\n", content);
4301         xmlFree(content);
4302     } else
4303         fprintf(output, "  Annot: empty\n");
4304 }
4305 
4306 /**
4307  * xmlSchemaContentModelDump:
4308  * @particle: the schema particle
4309  * @output: the file output
4310  * @depth: the depth used for intentation
4311  *
4312  * Dump a SchemaType structure
4313  */
4314 static void
xmlSchemaContentModelDump(xmlSchemaParticlePtr particle,FILE * output,int depth)4315 xmlSchemaContentModelDump(xmlSchemaParticlePtr particle, FILE * output, int depth)
4316 {
4317     xmlChar *str = NULL;
4318     xmlSchemaTreeItemPtr term;
4319     char shift[100];
4320     int i;
4321 
4322     if (particle == NULL)
4323 	return;
4324     for (i = 0;((i < depth) && (i < 25));i++)
4325         shift[2 * i] = shift[2 * i + 1] = ' ';
4326     shift[2 * i] = shift[2 * i + 1] = 0;
4327     fprintf(output, "%s", shift);
4328     if (particle->children == NULL) {
4329 	fprintf(output, "MISSING particle term\n");
4330 	return;
4331     }
4332     term = particle->children;
4333     if (term == NULL) {
4334 	fprintf(output, "(NULL)");
4335     } else {
4336 	switch (term->type) {
4337 	    case XML_SCHEMA_TYPE_ELEMENT:
4338 		fprintf(output, "ELEM '%s'", xmlSchemaFormatQName(&str,
4339 		    ((xmlSchemaElementPtr)term)->targetNamespace,
4340 		    ((xmlSchemaElementPtr)term)->name));
4341 		FREE_AND_NULL(str);
4342 		break;
4343 	    case XML_SCHEMA_TYPE_SEQUENCE:
4344 		fprintf(output, "SEQUENCE");
4345 		break;
4346 	    case XML_SCHEMA_TYPE_CHOICE:
4347 		fprintf(output, "CHOICE");
4348 		break;
4349 	    case XML_SCHEMA_TYPE_ALL:
4350 		fprintf(output, "ALL");
4351 		break;
4352 	    case XML_SCHEMA_TYPE_ANY:
4353 		fprintf(output, "ANY");
4354 		break;
4355 	    default:
4356 		fprintf(output, "UNKNOWN\n");
4357 		return;
4358 	}
4359     }
4360     if (particle->minOccurs != 1)
4361 	fprintf(output, " min: %d", particle->minOccurs);
4362     if (particle->maxOccurs >= UNBOUNDED)
4363 	fprintf(output, " max: unbounded");
4364     else if (particle->maxOccurs != 1)
4365 	fprintf(output, " max: %d", particle->maxOccurs);
4366     fprintf(output, "\n");
4367     if (term &&
4368 	((term->type == XML_SCHEMA_TYPE_SEQUENCE) ||
4369 	 (term->type == XML_SCHEMA_TYPE_CHOICE) ||
4370 	 (term->type == XML_SCHEMA_TYPE_ALL)) &&
4371 	 (term->children != NULL)) {
4372 	xmlSchemaContentModelDump((xmlSchemaParticlePtr) term->children,
4373 	    output, depth +1);
4374     }
4375     if (particle->next != NULL)
4376 	xmlSchemaContentModelDump((xmlSchemaParticlePtr) particle->next,
4377 		output, depth);
4378 }
4379 
4380 /**
4381  * xmlSchemaAttrUsesDump:
4382  * @uses:  attribute uses list
4383  * @output:  the file output
4384  *
4385  * Dumps a list of attribute use components.
4386  */
4387 static void
xmlSchemaAttrUsesDump(xmlSchemaItemListPtr uses,FILE * output)4388 xmlSchemaAttrUsesDump(xmlSchemaItemListPtr uses, FILE * output)
4389 {
4390     xmlSchemaAttributeUsePtr use;
4391     xmlSchemaAttributeUseProhibPtr prohib;
4392     xmlSchemaQNameRefPtr ref;
4393     const xmlChar *name, *tns;
4394     xmlChar *str = NULL;
4395     int i;
4396 
4397     if ((uses == NULL) || (uses->nbItems == 0))
4398         return;
4399 
4400     fprintf(output, "  attributes:\n");
4401     for (i = 0; i < uses->nbItems; i++) {
4402 	use = uses->items[i];
4403 	if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
4404 	    fprintf(output, "  [prohibition] ");
4405 	    prohib = (xmlSchemaAttributeUseProhibPtr) use;
4406 	    name = prohib->name;
4407 	    tns = prohib->targetNamespace;
4408 	} else if (use->type == XML_SCHEMA_EXTRA_QNAMEREF) {
4409 	    fprintf(output, "  [reference] ");
4410 	    ref = (xmlSchemaQNameRefPtr) use;
4411 	    name = ref->name;
4412 	    tns = ref->targetNamespace;
4413 	} else {
4414 	    fprintf(output, "  [use] ");
4415 	    name = WXS_ATTRUSE_DECL_NAME(use);
4416 	    tns = WXS_ATTRUSE_DECL_TNS(use);
4417 	}
4418 	fprintf(output, "'%s'\n",
4419 	    (const char *) xmlSchemaFormatQName(&str, tns, name));
4420 	FREE_AND_NULL(str);
4421     }
4422 }
4423 
4424 /**
4425  * xmlSchemaTypeDump:
4426  * @output:  the file output
4427  * @type:  a type structure
4428  *
4429  * Dump a SchemaType structure
4430  */
4431 static void
xmlSchemaTypeDump(xmlSchemaTypePtr type,FILE * output)4432 xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
4433 {
4434     if (type == NULL) {
4435         fprintf(output, "Type: NULL\n");
4436         return;
4437     }
4438     fprintf(output, "Type: ");
4439     if (type->name != NULL)
4440         fprintf(output, "'%s' ", type->name);
4441     else
4442         fprintf(output, "(no name) ");
4443     if (type->targetNamespace != NULL)
4444 	fprintf(output, "ns '%s' ", type->targetNamespace);
4445     switch (type->type) {
4446         case XML_SCHEMA_TYPE_BASIC:
4447             fprintf(output, "[basic] ");
4448             break;
4449         case XML_SCHEMA_TYPE_SIMPLE:
4450             fprintf(output, "[simple] ");
4451             break;
4452         case XML_SCHEMA_TYPE_COMPLEX:
4453             fprintf(output, "[complex] ");
4454             break;
4455         case XML_SCHEMA_TYPE_SEQUENCE:
4456             fprintf(output, "[sequence] ");
4457             break;
4458         case XML_SCHEMA_TYPE_CHOICE:
4459             fprintf(output, "[choice] ");
4460             break;
4461         case XML_SCHEMA_TYPE_ALL:
4462             fprintf(output, "[all] ");
4463             break;
4464         case XML_SCHEMA_TYPE_UR:
4465             fprintf(output, "[ur] ");
4466             break;
4467         case XML_SCHEMA_TYPE_RESTRICTION:
4468             fprintf(output, "[restriction] ");
4469             break;
4470         case XML_SCHEMA_TYPE_EXTENSION:
4471             fprintf(output, "[extension] ");
4472             break;
4473         default:
4474             fprintf(output, "[unknown type %d] ", type->type);
4475             break;
4476     }
4477     fprintf(output, "content: ");
4478     switch (type->contentType) {
4479         case XML_SCHEMA_CONTENT_UNKNOWN:
4480             fprintf(output, "[unknown] ");
4481             break;
4482         case XML_SCHEMA_CONTENT_EMPTY:
4483             fprintf(output, "[empty] ");
4484             break;
4485         case XML_SCHEMA_CONTENT_ELEMENTS:
4486             fprintf(output, "[element] ");
4487             break;
4488         case XML_SCHEMA_CONTENT_MIXED:
4489             fprintf(output, "[mixed] ");
4490             break;
4491         case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
4492 	/* not used. */
4493             break;
4494         case XML_SCHEMA_CONTENT_BASIC:
4495             fprintf(output, "[basic] ");
4496             break;
4497         case XML_SCHEMA_CONTENT_SIMPLE:
4498             fprintf(output, "[simple] ");
4499             break;
4500         case XML_SCHEMA_CONTENT_ANY:
4501             fprintf(output, "[any] ");
4502             break;
4503     }
4504     fprintf(output, "\n");
4505     if (type->base != NULL) {
4506         fprintf(output, "  base type: '%s'", type->base);
4507 	if (type->baseNs != NULL)
4508 	    fprintf(output, " ns '%s'\n", type->baseNs);
4509 	else
4510 	    fprintf(output, "\n");
4511     }
4512     if (type->attrUses != NULL)
4513 	xmlSchemaAttrUsesDump(type->attrUses, output);
4514     if (type->annot != NULL)
4515         xmlSchemaAnnotDump(output, type->annot);
4516 #ifdef DUMP_CONTENT_MODEL
4517     if ((type->type == XML_SCHEMA_TYPE_COMPLEX) &&
4518 	(type->subtypes != NULL)) {
4519 	xmlSchemaContentModelDump((xmlSchemaParticlePtr) type->subtypes,
4520 	    output, 1);
4521     }
4522 #endif
4523 }
4524 
4525 static void
xmlSchemaTypeDumpEntry(void * type,void * output,const xmlChar * name ATTRIBUTE_UNUSED)4526 xmlSchemaTypeDumpEntry(void *type, void *output,
4527                        const xmlChar *name ATTRIBUTE_UNUSED)
4528 {
4529     xmlSchemaTypeDump((xmlSchemaTypePtr) type, (FILE *) output);
4530 }
4531 
4532 /**
4533  * xmlSchemaDump:
4534  * @output:  the file output
4535  * @schema:  a schema structure
4536  *
4537  * Dump a Schema structure.
4538  */
4539 void
xmlSchemaDump(FILE * output,xmlSchemaPtr schema)4540 xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
4541 {
4542     if (output == NULL)
4543         return;
4544     if (schema == NULL) {
4545         fprintf(output, "Schemas: NULL\n");
4546         return;
4547     }
4548     fprintf(output, "Schemas: ");
4549     if (schema->name != NULL)
4550         fprintf(output, "%s, ", schema->name);
4551     else
4552         fprintf(output, "no name, ");
4553     if (schema->targetNamespace != NULL)
4554         fprintf(output, "%s", (const char *) schema->targetNamespace);
4555     else
4556         fprintf(output, "no target namespace");
4557     fprintf(output, "\n");
4558     if (schema->annot != NULL)
4559         xmlSchemaAnnotDump(output, schema->annot);
4560     xmlHashScan(schema->typeDecl, xmlSchemaTypeDumpEntry, output);
4561     xmlHashScanFull(schema->elemDecl, xmlSchemaElementDump, output);
4562 }
4563 
4564 #ifdef DEBUG_IDC_NODE_TABLE
4565 /**
4566  * xmlSchemaDebugDumpIDCTable:
4567  * @vctxt: the WXS validation context
4568  *
4569  * Displays the current IDC table for debug purposes.
4570  */
4571 static void
xmlSchemaDebugDumpIDCTable(FILE * output,const xmlChar * namespaceName,const xmlChar * localName,xmlSchemaPSVIIDCBindingPtr bind)4572 xmlSchemaDebugDumpIDCTable(FILE * output,
4573 			   const xmlChar *namespaceName,
4574 			   const xmlChar *localName,
4575 			   xmlSchemaPSVIIDCBindingPtr bind)
4576 {
4577     xmlChar *str = NULL;
4578     const xmlChar *value;
4579     xmlSchemaPSVIIDCNodePtr tab;
4580     xmlSchemaPSVIIDCKeyPtr key;
4581     int i, j, res;
4582 
4583     fprintf(output, "IDC: TABLES on '%s'\n",
4584 	xmlSchemaFormatQName(&str, namespaceName, localName));
4585     FREE_AND_NULL(str)
4586 
4587     if (bind == NULL)
4588 	return;
4589     do {
4590 	fprintf(output, "IDC:   BINDING '%s' (%d)\n",
4591 	    xmlSchemaGetComponentQName(&str,
4592 		bind->definition), bind->nbNodes);
4593 	FREE_AND_NULL(str)
4594 	for (i = 0; i < bind->nbNodes; i++) {
4595 	    tab = bind->nodeTable[i];
4596 	    fprintf(output, "         ( ");
4597 	    for (j = 0; j < bind->definition->nbFields; j++) {
4598 		key = tab->keys[j];
4599 		if ((key != NULL) && (key->val != NULL)) {
4600 		    res = xmlSchemaGetCanonValue(key->val, &value);
4601 		    if (res >= 0)
4602 			fprintf(output, "'%s' ", value);
4603 		    else
4604 			fprintf(output, "CANON-VALUE-FAILED ");
4605 		    if (res == 0)
4606 			FREE_AND_NULL(value)
4607 		} else if (key != NULL)
4608 		    fprintf(output, "(no val), ");
4609 		else
4610 		    fprintf(output, "(key missing), ");
4611 	    }
4612 	    fprintf(output, ")\n");
4613 	}
4614 	if (bind->dupls && bind->dupls->nbItems) {
4615 	    fprintf(output, "IDC:     dupls (%d):\n", bind->dupls->nbItems);
4616 	    for (i = 0; i < bind->dupls->nbItems; i++) {
4617 		tab = bind->dupls->items[i];
4618 		fprintf(output, "         ( ");
4619 		for (j = 0; j < bind->definition->nbFields; j++) {
4620 		    key = tab->keys[j];
4621 		    if ((key != NULL) && (key->val != NULL)) {
4622 			res = xmlSchemaGetCanonValue(key->val, &value);
4623 			if (res >= 0)
4624 			    fprintf(output, "'%s' ", value);
4625 			else
4626 			    fprintf(output, "CANON-VALUE-FAILED ");
4627 			if (res == 0)
4628 			    FREE_AND_NULL(value)
4629 		    } else if (key != NULL)
4630 		    fprintf(output, "(no val), ");
4631 			else
4632 			    fprintf(output, "(key missing), ");
4633 		}
4634 		fprintf(output, ")\n");
4635 	    }
4636 	}
4637 	bind = bind->next;
4638     } while (bind != NULL);
4639 }
4640 #endif /* DEBUG_IDC */
4641 #endif /* LIBXML_OUTPUT_ENABLED */
4642 
4643 /************************************************************************
4644  *									*
4645  *			Utilities					*
4646  *									*
4647  ************************************************************************/
4648 
4649 /**
4650  * xmlSchemaGetPropNode:
4651  * @node: the element node
4652  * @name: the name of the attribute
4653  *
4654  * Seeks an attribute with a name of @name in
4655  * no namespace.
4656  *
4657  * Returns the attribute or NULL if not present.
4658  */
4659 static xmlAttrPtr
xmlSchemaGetPropNode(xmlNodePtr node,const char * name)4660 xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
4661 {
4662     xmlAttrPtr prop;
4663 
4664     if ((node == NULL) || (name == NULL))
4665 	return(NULL);
4666     prop = node->properties;
4667     while (prop != NULL) {
4668         if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
4669 	    return(prop);
4670 	prop = prop->next;
4671     }
4672     return (NULL);
4673 }
4674 
4675 /**
4676  * xmlSchemaGetPropNodeNs:
4677  * @node: the element node
4678  * @uri: the uri
4679  * @name: the name of the attribute
4680  *
4681  * Seeks an attribute with a local name of @name and
4682  * a namespace URI of @uri.
4683  *
4684  * Returns the attribute or NULL if not present.
4685  */
4686 static xmlAttrPtr
xmlSchemaGetPropNodeNs(xmlNodePtr node,const char * uri,const char * name)4687 xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
4688 {
4689     xmlAttrPtr prop;
4690 
4691     if ((node == NULL) || (name == NULL))
4692 	return(NULL);
4693     prop = node->properties;
4694     while (prop != NULL) {
4695 	if ((prop->ns != NULL) &&
4696 	    xmlStrEqual(prop->name, BAD_CAST name) &&
4697 	    xmlStrEqual(prop->ns->href, BAD_CAST uri))
4698 	    return(prop);
4699 	prop = prop->next;
4700     }
4701     return (NULL);
4702 }
4703 
4704 static const xmlChar *
xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node)4705 xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
4706 {
4707     xmlChar *val;
4708     const xmlChar *ret;
4709 
4710     val = xmlNodeGetContent(node);
4711     if (val == NULL)
4712 	val = xmlStrdup((xmlChar *)"");
4713     ret = xmlDictLookup(ctxt->dict, val, -1);
4714     xmlFree(val);
4715     return(ret);
4716 }
4717 
4718 static const xmlChar *
xmlSchemaGetNodeContentNoDict(xmlNodePtr node)4719 xmlSchemaGetNodeContentNoDict(xmlNodePtr node)
4720 {
4721     return((const xmlChar*) xmlNodeGetContent(node));
4722 }
4723 
4724 /**
4725  * xmlSchemaGetProp:
4726  * @ctxt: the parser context
4727  * @node: the node
4728  * @name: the property name
4729  *
4730  * Read a attribute value and internalize the string
4731  *
4732  * Returns the string or NULL if not present.
4733  */
4734 static const xmlChar *
xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,const char * name)4735 xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
4736                  const char *name)
4737 {
4738     xmlChar *val;
4739     const xmlChar *ret;
4740 
4741     val = xmlGetNoNsProp(node, BAD_CAST name);
4742     if (val == NULL)
4743         return(NULL);
4744     ret = xmlDictLookup(ctxt->dict, val, -1);
4745     xmlFree(val);
4746     return(ret);
4747 }
4748 
4749 /************************************************************************
4750  *									*
4751  *			Parsing functions				*
4752  *									*
4753  ************************************************************************/
4754 
4755 #define WXS_FIND_GLOBAL_ITEM(slot)			\
4756     if (xmlStrEqual(nsName, schema->targetNamespace)) { \
4757 	ret = xmlHashLookup(schema->slot, name); \
4758 	if (ret != NULL) goto exit; \
4759     } \
4760     if (xmlHashSize(schema->schemasImports) > 1) { \
4761 	xmlSchemaImportPtr import; \
4762 	if (nsName == NULL) \
4763 	    import = xmlHashLookup(schema->schemasImports, \
4764 		XML_SCHEMAS_NO_NAMESPACE); \
4765 	else \
4766 	    import = xmlHashLookup(schema->schemasImports, nsName); \
4767 	if (import == NULL) \
4768 	    goto exit; \
4769 	ret = xmlHashLookup(import->schema->slot, name); \
4770     }
4771 
4772 /**
4773  * xmlSchemaGetElem:
4774  * @schema:  the schema context
4775  * @name:  the element name
4776  * @ns:  the element namespace
4777  *
4778  * Lookup a global element declaration in the schema.
4779  *
4780  * Returns the element declaration or NULL if not found.
4781  */
4782 static xmlSchemaElementPtr
xmlSchemaGetElem(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName)4783 xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
4784                  const xmlChar * nsName)
4785 {
4786     xmlSchemaElementPtr ret = NULL;
4787 
4788     if ((name == NULL) || (schema == NULL))
4789         return(NULL);
4790     if (schema != NULL) {
4791 	WXS_FIND_GLOBAL_ITEM(elemDecl)
4792     }
4793 exit:
4794 #ifdef DEBUG
4795     if (ret == NULL) {
4796         if (nsName == NULL)
4797             fprintf(stderr, "Unable to lookup element decl. %s", name);
4798         else
4799             fprintf(stderr, "Unable to lookup element decl. %s:%s", name,
4800                     nsName);
4801     }
4802 #endif
4803     return (ret);
4804 }
4805 
4806 /**
4807  * xmlSchemaGetType:
4808  * @schema:  the main schema
4809  * @name:  the type's name
4810  * nsName:  the type's namespace
4811  *
4812  * Lookup a type in the schemas or the predefined types
4813  *
4814  * Returns the group definition or NULL if not found.
4815  */
4816 static xmlSchemaTypePtr
xmlSchemaGetType(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName)4817 xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
4818                  const xmlChar * nsName)
4819 {
4820     xmlSchemaTypePtr ret = NULL;
4821 
4822     if (name == NULL)
4823         return (NULL);
4824     /* First try the built-in types. */
4825     if ((nsName != NULL) && xmlStrEqual(nsName, xmlSchemaNs)) {
4826 	ret = xmlSchemaGetPredefinedType(name, nsName);
4827 	if (ret != NULL)
4828 	    goto exit;
4829 	/*
4830 	* Note that we try the parsed schemas as well here
4831 	* since one might have parsed the S4S, which contain more
4832 	* than the built-in types.
4833 	* TODO: Can we optimize this?
4834 	*/
4835     }
4836     if (schema != NULL) {
4837 	WXS_FIND_GLOBAL_ITEM(typeDecl)
4838     }
4839 exit:
4840 
4841 #ifdef DEBUG
4842     if (ret == NULL) {
4843         if (nsName == NULL)
4844             fprintf(stderr, "Unable to lookup type %s", name);
4845         else
4846             fprintf(stderr, "Unable to lookup type %s:%s", name,
4847                     nsName);
4848     }
4849 #endif
4850     return (ret);
4851 }
4852 
4853 /**
4854  * xmlSchemaGetAttributeDecl:
4855  * @schema:  the context of the schema
4856  * @name:  the name of the attribute
4857  * @ns:  the target namespace of the attribute
4858  *
4859  * Lookup a an attribute in the schema or imported schemas
4860  *
4861  * Returns the attribute declaration or NULL if not found.
4862  */
4863 static xmlSchemaAttributePtr
xmlSchemaGetAttributeDecl(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName)4864 xmlSchemaGetAttributeDecl(xmlSchemaPtr schema, const xmlChar * name,
4865                  const xmlChar * nsName)
4866 {
4867     xmlSchemaAttributePtr ret = NULL;
4868 
4869     if ((name == NULL) || (schema == NULL))
4870         return (NULL);
4871     if (schema != NULL) {
4872 	WXS_FIND_GLOBAL_ITEM(attrDecl)
4873     }
4874 exit:
4875 #ifdef DEBUG
4876     if (ret == NULL) {
4877         if (nsName == NULL)
4878             fprintf(stderr, "Unable to lookup attribute %s", name);
4879         else
4880             fprintf(stderr, "Unable to lookup attribute %s:%s", name,
4881                     nsName);
4882     }
4883 #endif
4884     return (ret);
4885 }
4886 
4887 /**
4888  * xmlSchemaGetAttributeGroup:
4889  * @schema:  the context of the schema
4890  * @name:  the name of the attribute group
4891  * @ns:  the target namespace of the attribute group
4892  *
4893  * Lookup a an attribute group in the schema or imported schemas
4894  *
4895  * Returns the attribute group definition or NULL if not found.
4896  */
4897 static xmlSchemaAttributeGroupPtr
xmlSchemaGetAttributeGroup(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName)4898 xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
4899                  const xmlChar * nsName)
4900 {
4901     xmlSchemaAttributeGroupPtr ret = NULL;
4902 
4903     if ((name == NULL) || (schema == NULL))
4904         return (NULL);
4905     if (schema != NULL) {
4906 	WXS_FIND_GLOBAL_ITEM(attrgrpDecl)
4907     }
4908 exit:
4909     /* TODO:
4910     if ((ret != NULL) && (ret->redef != NULL)) {
4911 	* Return the last redefinition. *
4912 	ret = ret->redef;
4913     }
4914     */
4915 #ifdef DEBUG
4916     if (ret == NULL) {
4917         if (nsName == NULL)
4918             fprintf(stderr, "Unable to lookup attribute group %s", name);
4919         else
4920             fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
4921                     nsName);
4922     }
4923 #endif
4924     return (ret);
4925 }
4926 
4927 /**
4928  * xmlSchemaGetGroup:
4929  * @schema:  the context of the schema
4930  * @name:  the name of the group
4931  * @ns:  the target namespace of the group
4932  *
4933  * Lookup a group in the schema or imported schemas
4934  *
4935  * Returns the group definition or NULL if not found.
4936  */
4937 static xmlSchemaModelGroupDefPtr
xmlSchemaGetGroup(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName)4938 xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
4939                  const xmlChar * nsName)
4940 {
4941     xmlSchemaModelGroupDefPtr ret = NULL;
4942 
4943     if ((name == NULL) || (schema == NULL))
4944         return (NULL);
4945     if (schema != NULL) {
4946 	WXS_FIND_GLOBAL_ITEM(groupDecl)
4947     }
4948 exit:
4949 
4950 #ifdef DEBUG
4951     if (ret == NULL) {
4952         if (nsName == NULL)
4953             fprintf(stderr, "Unable to lookup group %s", name);
4954         else
4955             fprintf(stderr, "Unable to lookup group %s:%s", name,
4956                     nsName);
4957     }
4958 #endif
4959     return (ret);
4960 }
4961 
4962 static xmlSchemaNotationPtr
xmlSchemaGetNotation(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName)4963 xmlSchemaGetNotation(xmlSchemaPtr schema,
4964 		     const xmlChar *name,
4965 		     const xmlChar *nsName)
4966 {
4967     xmlSchemaNotationPtr ret = NULL;
4968 
4969     if ((name == NULL) || (schema == NULL))
4970         return (NULL);
4971     if (schema != NULL) {
4972 	WXS_FIND_GLOBAL_ITEM(notaDecl)
4973     }
4974 exit:
4975     return (ret);
4976 }
4977 
4978 static xmlSchemaIDCPtr
xmlSchemaGetIDC(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName)4979 xmlSchemaGetIDC(xmlSchemaPtr schema,
4980 		const xmlChar *name,
4981 		const xmlChar *nsName)
4982 {
4983     xmlSchemaIDCPtr ret = NULL;
4984 
4985     if ((name == NULL) || (schema == NULL))
4986         return (NULL);
4987     if (schema != NULL) {
4988 	WXS_FIND_GLOBAL_ITEM(idcDef)
4989     }
4990 exit:
4991     return (ret);
4992 }
4993 
4994 /**
4995  * xmlSchemaGetNamedComponent:
4996  * @schema:  the schema
4997  * @name:  the name of the group
4998  * @ns:  the target namespace of the group
4999  *
5000  * Lookup a group in the schema or imported schemas
5001  *
5002  * Returns the group definition or NULL if not found.
5003  */
5004 static xmlSchemaBasicItemPtr
xmlSchemaGetNamedComponent(xmlSchemaPtr schema,xmlSchemaTypeType itemType,const xmlChar * name,const xmlChar * targetNs)5005 xmlSchemaGetNamedComponent(xmlSchemaPtr schema,
5006 			   xmlSchemaTypeType itemType,
5007 			   const xmlChar *name,
5008 			   const xmlChar *targetNs)
5009 {
5010     switch (itemType) {
5011 	case XML_SCHEMA_TYPE_GROUP:
5012 	    return ((xmlSchemaBasicItemPtr) xmlSchemaGetGroup(schema,
5013 		name, targetNs));
5014 	case XML_SCHEMA_TYPE_ELEMENT:
5015 	    return ((xmlSchemaBasicItemPtr) xmlSchemaGetElem(schema,
5016 		name, targetNs));
5017 	default:
5018 	    TODO
5019 	    return (NULL);
5020     }
5021 }
5022 
5023 /************************************************************************
5024  *									*
5025  *			Parsing functions				*
5026  *									*
5027  ************************************************************************/
5028 
5029 #define IS_BLANK_NODE(n)						\
5030     (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content, -1)))
5031 
5032 /**
5033  * xmlSchemaIsBlank:
5034  * @str:  a string
5035  * @len: the length of the string or -1
5036  *
5037  * Check if a string is ignorable
5038  *
5039  * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
5040  */
5041 static int
xmlSchemaIsBlank(xmlChar * str,int len)5042 xmlSchemaIsBlank(xmlChar * str, int len)
5043 {
5044     if (str == NULL)
5045         return (1);
5046     if (len < 0) {
5047 	while (*str != 0) {
5048 	    if (!(IS_BLANK_CH(*str)))
5049 		return (0);
5050 	    str++;
5051 	}
5052     } else while ((*str != 0) && (len != 0)) {
5053 	if (!(IS_BLANK_CH(*str)))
5054 	    return (0);
5055 	str++;
5056 	len--;
5057     }
5058 
5059     return (1);
5060 }
5061 
5062 #define WXS_COMP_NAME(c, t) ((t) (c))->name
5063 #define WXS_COMP_TNS(c, t) ((t) (c))->targetNamespace
5064 /*
5065 * xmlSchemaFindRedefCompInGraph:
5066 * ATTENTION TODO: This uses pointer comp. for strings.
5067 */
5068 static xmlSchemaBasicItemPtr
xmlSchemaFindRedefCompInGraph(xmlSchemaBucketPtr bucket,xmlSchemaTypeType type,const xmlChar * name,const xmlChar * nsName)5069 xmlSchemaFindRedefCompInGraph(xmlSchemaBucketPtr bucket,
5070 			      xmlSchemaTypeType type,
5071 			      const xmlChar *name,
5072 			      const xmlChar *nsName)
5073 {
5074     xmlSchemaBasicItemPtr ret;
5075     int i;
5076 
5077     if ((bucket == NULL) || (name == NULL))
5078 	return(NULL);
5079     if ((bucket->globals == NULL) ||
5080 	(bucket->globals->nbItems == 0))
5081 	goto subschemas;
5082     /*
5083     * Search in global components.
5084     */
5085     for (i = 0; i < bucket->globals->nbItems; i++) {
5086 	ret = bucket->globals->items[i];
5087 	if (ret->type == type) {
5088 	    switch (type) {
5089 		case XML_SCHEMA_TYPE_COMPLEX:
5090 		case XML_SCHEMA_TYPE_SIMPLE:
5091 		    if ((WXS_COMP_NAME(ret, xmlSchemaTypePtr) == name) &&
5092 			(WXS_COMP_TNS(ret, xmlSchemaTypePtr) ==
5093 			nsName))
5094 		    {
5095 			return(ret);
5096 		    }
5097 		    break;
5098 		case XML_SCHEMA_TYPE_GROUP:
5099 		    if ((WXS_COMP_NAME(ret,
5100 			    xmlSchemaModelGroupDefPtr) == name) &&
5101 			(WXS_COMP_TNS(ret,
5102 			    xmlSchemaModelGroupDefPtr) == nsName))
5103 		    {
5104 			return(ret);
5105 		    }
5106 		    break;
5107 		case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
5108 		    if ((WXS_COMP_NAME(ret,
5109 			    xmlSchemaAttributeGroupPtr) == name) &&
5110 			(WXS_COMP_TNS(ret,
5111 			    xmlSchemaAttributeGroupPtr) == nsName))
5112 		    {
5113 			return(ret);
5114 		    }
5115 		    break;
5116 		default:
5117 		    /* Should not be hit. */
5118 		    return(NULL);
5119 	    }
5120 	}
5121     }
5122 subschemas:
5123     /*
5124     * Process imported/included schemas.
5125     */
5126     if (bucket->relations != NULL) {
5127 	xmlSchemaSchemaRelationPtr rel = bucket->relations;
5128 
5129 	/*
5130 	* TODO: Marking the bucket will not avoid multiple searches
5131 	* in the same schema, but avoids at least circularity.
5132 	*/
5133 	bucket->flags |= XML_SCHEMA_BUCKET_MARKED;
5134 	do {
5135 	    if ((rel->bucket != NULL) &&
5136 		((rel->bucket->flags & XML_SCHEMA_BUCKET_MARKED) == 0)) {
5137 		ret = xmlSchemaFindRedefCompInGraph(rel->bucket,
5138 		    type, name, nsName);
5139 		if (ret != NULL)
5140 		    return(ret);
5141 	    }
5142 	    rel = rel->next;
5143 	} while (rel != NULL);
5144 	 bucket->flags ^= XML_SCHEMA_BUCKET_MARKED;
5145     }
5146     return(NULL);
5147 }
5148 
5149 /**
5150  * xmlSchemaAddNotation:
5151  * @ctxt:  a schema parser context
5152  * @schema:  the schema being built
5153  * @name:  the item name
5154  *
5155  * Add an XML schema annotation declaration
5156  * *WARNING* this interface is highly subject to change
5157  *
5158  * Returns the new struture or NULL in case of error
5159  */
5160 static xmlSchemaNotationPtr
xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName,xmlNodePtr node ATTRIBUTE_UNUSED)5161 xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5162                      const xmlChar *name, const xmlChar *nsName,
5163 		     xmlNodePtr node ATTRIBUTE_UNUSED)
5164 {
5165     xmlSchemaNotationPtr ret = NULL;
5166 
5167     if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5168         return (NULL);
5169 
5170     ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
5171     if (ret == NULL) {
5172         xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
5173         return (NULL);
5174     }
5175     memset(ret, 0, sizeof(xmlSchemaNotation));
5176     ret->type = XML_SCHEMA_TYPE_NOTATION;
5177     ret->name = name;
5178     ret->targetNamespace = nsName;
5179     /* TODO: do we need the node to be set?
5180     * ret->node = node;*/
5181     WXS_ADD_GLOBAL(ctxt, ret);
5182     return (ret);
5183 }
5184 
5185 /**
5186  * xmlSchemaAddAttribute:
5187  * @ctxt:  a schema parser context
5188  * @schema:  the schema being built
5189  * @name:  the item name
5190  * @namespace:  the namespace
5191  *
5192  * Add an XML schema Attrribute declaration
5193  * *WARNING* this interface is highly subject to change
5194  *
5195  * Returns the new struture or NULL in case of error
5196  */
5197 static xmlSchemaAttributePtr
xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName,xmlNodePtr node,int topLevel)5198 xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5199                       const xmlChar * name, const xmlChar * nsName,
5200 		      xmlNodePtr node, int topLevel)
5201 {
5202     xmlSchemaAttributePtr ret = NULL;
5203 
5204     if ((ctxt == NULL) || (schema == NULL))
5205         return (NULL);
5206 
5207     ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
5208     if (ret == NULL) {
5209         xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
5210         return (NULL);
5211     }
5212     memset(ret, 0, sizeof(xmlSchemaAttribute));
5213     ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
5214     ret->node = node;
5215     ret->name = name;
5216     ret->targetNamespace = nsName;
5217 
5218     if (topLevel)
5219 	WXS_ADD_GLOBAL(ctxt, ret);
5220     else
5221 	WXS_ADD_LOCAL(ctxt, ret);
5222     WXS_ADD_PENDING(ctxt, ret);
5223     return (ret);
5224 }
5225 
5226 /**
5227  * xmlSchemaAddAttributeUse:
5228  * @ctxt:  a schema parser context
5229  * @schema:  the schema being built
5230  * @name:  the item name
5231  * @namespace:  the namespace
5232  *
5233  * Add an XML schema Attrribute declaration
5234  * *WARNING* this interface is highly subject to change
5235  *
5236  * Returns the new struture or NULL in case of error
5237  */
5238 static xmlSchemaAttributeUsePtr
xmlSchemaAddAttributeUse(xmlSchemaParserCtxtPtr pctxt,xmlNodePtr node)5239 xmlSchemaAddAttributeUse(xmlSchemaParserCtxtPtr pctxt,
5240 			 xmlNodePtr node)
5241 {
5242     xmlSchemaAttributeUsePtr ret = NULL;
5243 
5244     if (pctxt == NULL)
5245         return (NULL);
5246 
5247     ret = (xmlSchemaAttributeUsePtr) xmlMalloc(sizeof(xmlSchemaAttributeUse));
5248     if (ret == NULL) {
5249         xmlSchemaPErrMemory(pctxt, "allocating attribute", NULL);
5250         return (NULL);
5251     }
5252     memset(ret, 0, sizeof(xmlSchemaAttributeUse));
5253     ret->type = XML_SCHEMA_TYPE_ATTRIBUTE_USE;
5254     ret->node = node;
5255 
5256     WXS_ADD_LOCAL(pctxt, ret);
5257     return (ret);
5258 }
5259 
5260 /*
5261 * xmlSchemaAddRedef:
5262 *
5263 * Adds a redefinition information. This is used at a later stage to:
5264 * resolve references to the redefined components and to check constraints.
5265 */
5266 static xmlSchemaRedefPtr
xmlSchemaAddRedef(xmlSchemaParserCtxtPtr pctxt,xmlSchemaBucketPtr targetBucket,void * item,const xmlChar * refName,const xmlChar * refTargetNs)5267 xmlSchemaAddRedef(xmlSchemaParserCtxtPtr pctxt,
5268 		  xmlSchemaBucketPtr targetBucket,
5269 		  void *item,
5270 		  const xmlChar *refName,
5271 		  const xmlChar *refTargetNs)
5272 {
5273     xmlSchemaRedefPtr ret;
5274 
5275     ret = (xmlSchemaRedefPtr)
5276 	xmlMalloc(sizeof(xmlSchemaRedef));
5277     if (ret == NULL) {
5278 	xmlSchemaPErrMemory(pctxt,
5279 	    "allocating redefinition info", NULL);
5280 	return (NULL);
5281     }
5282     memset(ret, 0, sizeof(xmlSchemaRedef));
5283     ret->item = item;
5284     ret->targetBucket = targetBucket;
5285     ret->refName = refName;
5286     ret->refTargetNs = refTargetNs;
5287     if (WXS_CONSTRUCTOR(pctxt)->redefs == NULL)
5288 	WXS_CONSTRUCTOR(pctxt)->redefs = ret;
5289     else
5290 	WXS_CONSTRUCTOR(pctxt)->lastRedef->next = ret;
5291     WXS_CONSTRUCTOR(pctxt)->lastRedef = ret;
5292 
5293     return (ret);
5294 }
5295 
5296 /**
5297  * xmlSchemaAddAttributeGroupDefinition:
5298  * @ctxt:  a schema parser context
5299  * @schema:  the schema being built
5300  * @name:  the item name
5301  * @nsName:  the target namespace
5302  * @node: the corresponding node
5303  *
5304  * Add an XML schema Attrribute Group definition.
5305  *
5306  * Returns the new struture or NULL in case of error
5307  */
5308 static xmlSchemaAttributeGroupPtr
xmlSchemaAddAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema ATTRIBUTE_UNUSED,const xmlChar * name,const xmlChar * nsName,xmlNodePtr node)5309 xmlSchemaAddAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
5310                            xmlSchemaPtr schema ATTRIBUTE_UNUSED,
5311 			   const xmlChar *name,
5312 			   const xmlChar *nsName,
5313 			   xmlNodePtr node)
5314 {
5315     xmlSchemaAttributeGroupPtr ret = NULL;
5316 
5317     if ((pctxt == NULL) || (name == NULL))
5318         return (NULL);
5319 
5320     ret = (xmlSchemaAttributeGroupPtr)
5321         xmlMalloc(sizeof(xmlSchemaAttributeGroup));
5322     if (ret == NULL) {
5323 	xmlSchemaPErrMemory(pctxt, "allocating attribute group", NULL);
5324 	return (NULL);
5325     }
5326     memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
5327     ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5328     ret->name = name;
5329     ret->targetNamespace = nsName;
5330     ret->node = node;
5331 
5332     /* TODO: Remove the flag. */
5333     ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
5334     if (pctxt->isRedefine) {
5335 	pctxt->redef = xmlSchemaAddRedef(pctxt, pctxt->redefined,
5336 	    ret, name, nsName);
5337 	if (pctxt->redef == NULL) {
5338 	    xmlFree(ret);
5339 	    return(NULL);
5340 	}
5341 	pctxt->redefCounter = 0;
5342     }
5343     WXS_ADD_GLOBAL(pctxt, ret);
5344     WXS_ADD_PENDING(pctxt, ret);
5345     return (ret);
5346 }
5347 
5348 /**
5349  * xmlSchemaAddElement:
5350  * @ctxt:  a schema parser context
5351  * @schema:  the schema being built
5352  * @name:  the type name
5353  * @namespace:  the type namespace
5354  *
5355  * Add an XML schema Element declaration
5356  * *WARNING* this interface is highly subject to change
5357  *
5358  * Returns the new struture or NULL in case of error
5359  */
5360 static xmlSchemaElementPtr
xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt,const xmlChar * name,const xmlChar * nsName,xmlNodePtr node,int topLevel)5361 xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt,
5362                     const xmlChar * name, const xmlChar * nsName,
5363 		    xmlNodePtr node, int topLevel)
5364 {
5365     xmlSchemaElementPtr ret = NULL;
5366 
5367     if ((ctxt == NULL) || (name == NULL))
5368         return (NULL);
5369 
5370     ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
5371     if (ret == NULL) {
5372         xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
5373         return (NULL);
5374     }
5375     memset(ret, 0, sizeof(xmlSchemaElement));
5376     ret->type = XML_SCHEMA_TYPE_ELEMENT;
5377     ret->name = name;
5378     ret->targetNamespace = nsName;
5379     ret->node = node;
5380 
5381     if (topLevel)
5382 	WXS_ADD_GLOBAL(ctxt, ret);
5383     else
5384 	WXS_ADD_LOCAL(ctxt, ret);
5385     WXS_ADD_PENDING(ctxt, ret);
5386     return (ret);
5387 }
5388 
5389 /**
5390  * xmlSchemaAddType:
5391  * @ctxt:  a schema parser context
5392  * @schema:  the schema being built
5393  * @name:  the item name
5394  * @namespace:  the namespace
5395  *
5396  * Add an XML schema item
5397  * *WARNING* this interface is highly subject to change
5398  *
5399  * Returns the new struture or NULL in case of error
5400  */
5401 static xmlSchemaTypePtr
xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlSchemaTypeType type,const xmlChar * name,const xmlChar * nsName,xmlNodePtr node,int topLevel)5402 xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5403 		 xmlSchemaTypeType type,
5404                  const xmlChar * name, const xmlChar * nsName,
5405 		 xmlNodePtr node, int topLevel)
5406 {
5407     xmlSchemaTypePtr ret = NULL;
5408 
5409     if ((ctxt == NULL) || (schema == NULL))
5410         return (NULL);
5411 
5412     ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
5413     if (ret == NULL) {
5414         xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
5415         return (NULL);
5416     }
5417     memset(ret, 0, sizeof(xmlSchemaType));
5418     ret->type = type;
5419     ret->name = name;
5420     ret->targetNamespace = nsName;
5421     ret->node = node;
5422     if (topLevel) {
5423 	if (ctxt->isRedefine) {
5424 	    ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5425 		ret, name, nsName);
5426 	    if (ctxt->redef == NULL) {
5427 		xmlFree(ret);
5428 		return(NULL);
5429 	    }
5430 	    ctxt->redefCounter = 0;
5431 	}
5432 	WXS_ADD_GLOBAL(ctxt, ret);
5433     } else
5434 	WXS_ADD_LOCAL(ctxt, ret);
5435     WXS_ADD_PENDING(ctxt, ret);
5436     return (ret);
5437 }
5438 
5439 static xmlSchemaQNameRefPtr
xmlSchemaNewQNameRef(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypeType refType,const xmlChar * refName,const xmlChar * refNs)5440 xmlSchemaNewQNameRef(xmlSchemaParserCtxtPtr pctxt,
5441 		     xmlSchemaTypeType refType,
5442 		     const xmlChar *refName,
5443 		     const xmlChar *refNs)
5444 {
5445     xmlSchemaQNameRefPtr ret;
5446 
5447     ret = (xmlSchemaQNameRefPtr)
5448 	xmlMalloc(sizeof(xmlSchemaQNameRef));
5449     if (ret == NULL) {
5450 	xmlSchemaPErrMemory(pctxt,
5451 	    "allocating QName reference item", NULL);
5452 	return (NULL);
5453     }
5454     ret->node = NULL;
5455     ret->type = XML_SCHEMA_EXTRA_QNAMEREF;
5456     ret->name = refName;
5457     ret->targetNamespace = refNs;
5458     ret->item = NULL;
5459     ret->itemType = refType;
5460     /*
5461     * Store the reference item in the schema.
5462     */
5463     WXS_ADD_LOCAL(pctxt, ret);
5464     return (ret);
5465 }
5466 
5467 static xmlSchemaAttributeUseProhibPtr
xmlSchemaAddAttributeUseProhib(xmlSchemaParserCtxtPtr pctxt)5468 xmlSchemaAddAttributeUseProhib(xmlSchemaParserCtxtPtr pctxt)
5469 {
5470     xmlSchemaAttributeUseProhibPtr ret;
5471 
5472     ret = (xmlSchemaAttributeUseProhibPtr)
5473 	xmlMalloc(sizeof(xmlSchemaAttributeUseProhib));
5474     if (ret == NULL) {
5475 	xmlSchemaPErrMemory(pctxt,
5476 	    "allocating attribute use prohibition", NULL);
5477 	return (NULL);
5478     }
5479     memset(ret, 0, sizeof(xmlSchemaAttributeUseProhib));
5480     ret->type = XML_SCHEMA_EXTRA_ATTR_USE_PROHIB;
5481     WXS_ADD_LOCAL(pctxt, ret);
5482     return (ret);
5483 }
5484 
5485 
5486 /**
5487  * xmlSchemaAddModelGroup:
5488  * @ctxt:  a schema parser context
5489  * @schema:  the schema being built
5490  * @type: the "compositor" type of the model group
5491  * @node: the node in the schema doc
5492  *
5493  * Adds a schema model group
5494  * *WARNING* this interface is highly subject to change
5495  *
5496  * Returns the new struture or NULL in case of error
5497  */
5498 static xmlSchemaModelGroupPtr
xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlSchemaTypeType type,xmlNodePtr node)5499 xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt,
5500 		       xmlSchemaPtr schema,
5501 		       xmlSchemaTypeType type,
5502 		       xmlNodePtr node)
5503 {
5504     xmlSchemaModelGroupPtr ret = NULL;
5505 
5506     if ((ctxt == NULL) || (schema == NULL))
5507         return (NULL);
5508 
5509     ret = (xmlSchemaModelGroupPtr)
5510 	xmlMalloc(sizeof(xmlSchemaModelGroup));
5511     if (ret == NULL) {
5512 	xmlSchemaPErrMemory(ctxt, "allocating model group component",
5513 	    NULL);
5514 	return (NULL);
5515     }
5516     memset(ret, 0, sizeof(xmlSchemaModelGroup));
5517     ret->type = type;
5518     ret->node = node;
5519     WXS_ADD_LOCAL(ctxt, ret);
5520     if ((type == XML_SCHEMA_TYPE_SEQUENCE) ||
5521 	(type == XML_SCHEMA_TYPE_CHOICE))
5522 	WXS_ADD_PENDING(ctxt, ret);
5523     return (ret);
5524 }
5525 
5526 
5527 /**
5528  * xmlSchemaAddParticle:
5529  * @ctxt:  a schema parser context
5530  * @schema:  the schema being built
5531  * @node: the corresponding node in the schema doc
5532  * @min: the minOccurs
5533  * @max: the maxOccurs
5534  *
5535  * Adds an XML schema particle component.
5536  * *WARNING* this interface is highly subject to change
5537  *
5538  * Returns the new struture or NULL in case of error
5539  */
5540 static xmlSchemaParticlePtr
xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,int min,int max)5541 xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt,
5542 		     xmlNodePtr node, int min, int max)
5543 {
5544     xmlSchemaParticlePtr ret = NULL;
5545     if (ctxt == NULL)
5546         return (NULL);
5547 
5548 #ifdef DEBUG
5549     fprintf(stderr, "Adding particle component\n");
5550 #endif
5551     ret = (xmlSchemaParticlePtr)
5552 	xmlMalloc(sizeof(xmlSchemaParticle));
5553     if (ret == NULL) {
5554 	xmlSchemaPErrMemory(ctxt, "allocating particle component",
5555 	    NULL);
5556 	return (NULL);
5557     }
5558     ret->type = XML_SCHEMA_TYPE_PARTICLE;
5559     ret->annot = NULL;
5560     ret->node = node;
5561     ret->minOccurs = min;
5562     ret->maxOccurs = max;
5563     ret->next = NULL;
5564     ret->children = NULL;
5565 
5566     WXS_ADD_LOCAL(ctxt, ret);
5567     /*
5568     * Note that addition to pending components will be done locally
5569     * to the specific parsing function, since the most particles
5570     * need not to be fixed up (i.e. the reference to be resolved).
5571     * REMOVED: WXS_ADD_PENDING(ctxt, ret);
5572     */
5573     return (ret);
5574 }
5575 
5576 /**
5577  * xmlSchemaAddModelGroupDefinition:
5578  * @ctxt:  a schema validation context
5579  * @schema:  the schema being built
5580  * @name:  the group name
5581  *
5582  * Add an XML schema Group definition
5583  *
5584  * Returns the new struture or NULL in case of error
5585  */
5586 static xmlSchemaModelGroupDefPtr
xmlSchemaAddModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName,xmlNodePtr node)5587 xmlSchemaAddModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
5588 				 xmlSchemaPtr schema,
5589 				 const xmlChar *name,
5590 				 const xmlChar *nsName,
5591 				 xmlNodePtr node)
5592 {
5593     xmlSchemaModelGroupDefPtr ret = NULL;
5594 
5595     if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5596         return (NULL);
5597 
5598     ret = (xmlSchemaModelGroupDefPtr)
5599 	xmlMalloc(sizeof(xmlSchemaModelGroupDef));
5600     if (ret == NULL) {
5601         xmlSchemaPErrMemory(ctxt, "adding group", NULL);
5602         return (NULL);
5603     }
5604     memset(ret, 0, sizeof(xmlSchemaModelGroupDef));
5605     ret->name = name;
5606     ret->type = XML_SCHEMA_TYPE_GROUP;
5607     ret->node = node;
5608     ret->targetNamespace = nsName;
5609 
5610     if (ctxt->isRedefine) {
5611 	ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5612 	    ret, name, nsName);
5613 	if (ctxt->redef == NULL) {
5614 	    xmlFree(ret);
5615 	    return(NULL);
5616 	}
5617 	ctxt->redefCounter = 0;
5618     }
5619     WXS_ADD_GLOBAL(ctxt, ret);
5620     WXS_ADD_PENDING(ctxt, ret);
5621     return (ret);
5622 }
5623 
5624 /**
5625  * xmlSchemaNewWildcardNs:
5626  * @ctxt:  a schema validation context
5627  *
5628  * Creates a new wildcard namespace constraint.
5629  *
5630  * Returns the new struture or NULL in case of error
5631  */
5632 static xmlSchemaWildcardNsPtr
xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)5633 xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
5634 {
5635     xmlSchemaWildcardNsPtr ret;
5636 
5637     ret = (xmlSchemaWildcardNsPtr)
5638 	xmlMalloc(sizeof(xmlSchemaWildcardNs));
5639     if (ret == NULL) {
5640 	xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
5641 	return (NULL);
5642     }
5643     ret->value = NULL;
5644     ret->next = NULL;
5645     return (ret);
5646 }
5647 
5648 static xmlSchemaIDCPtr
xmlSchemaAddIDC(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName,int category,xmlNodePtr node)5649 xmlSchemaAddIDC(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5650                   const xmlChar *name, const xmlChar *nsName,
5651 		  int category, xmlNodePtr node)
5652 {
5653     xmlSchemaIDCPtr ret = NULL;
5654 
5655     if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5656         return (NULL);
5657 
5658     ret = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
5659     if (ret == NULL) {
5660         xmlSchemaPErrMemory(ctxt,
5661 	    "allocating an identity-constraint definition", NULL);
5662         return (NULL);
5663     }
5664     memset(ret, 0, sizeof(xmlSchemaIDC));
5665     /* The target namespace of the parent element declaration. */
5666     ret->targetNamespace = nsName;
5667     ret->name = name;
5668     ret->type = category;
5669     ret->node = node;
5670 
5671     WXS_ADD_GLOBAL(ctxt, ret);
5672     /*
5673     * Only keyrefs need to be fixup up.
5674     */
5675     if (category == XML_SCHEMA_TYPE_IDC_KEYREF)
5676 	WXS_ADD_PENDING(ctxt, ret);
5677     return (ret);
5678 }
5679 
5680 /**
5681  * xmlSchemaAddWildcard:
5682  * @ctxt:  a schema validation context
5683  * @schema: a schema
5684  *
5685  * Adds a wildcard.
5686  * It corresponds to a xsd:anyAttribute and xsd:any.
5687  *
5688  * Returns the new struture or NULL in case of error
5689  */
5690 static xmlSchemaWildcardPtr
xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlSchemaTypeType type,xmlNodePtr node)5691 xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5692 		     xmlSchemaTypeType type, xmlNodePtr node)
5693 {
5694     xmlSchemaWildcardPtr ret = NULL;
5695 
5696     if ((ctxt == NULL) || (schema == NULL))
5697         return (NULL);
5698 
5699     ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
5700     if (ret == NULL) {
5701         xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
5702         return (NULL);
5703     }
5704     memset(ret, 0, sizeof(xmlSchemaWildcard));
5705     ret->type = type;
5706     ret->node = node;
5707     WXS_ADD_LOCAL(ctxt, ret);
5708     return (ret);
5709 }
5710 
5711 static void
xmlSchemaSubstGroupFree(xmlSchemaSubstGroupPtr group)5712 xmlSchemaSubstGroupFree(xmlSchemaSubstGroupPtr group)
5713 {
5714     if (group == NULL)
5715 	return;
5716     if (group->members != NULL)
5717 	xmlSchemaItemListFree(group->members);
5718     xmlFree(group);
5719 }
5720 
5721 static void
xmlSchemaSubstGroupFreeEntry(void * group,const xmlChar * name ATTRIBUTE_UNUSED)5722 xmlSchemaSubstGroupFreeEntry(void *group, const xmlChar *name ATTRIBUTE_UNUSED)
5723 {
5724     xmlSchemaSubstGroupFree((xmlSchemaSubstGroupPtr) group);
5725 }
5726 
5727 static xmlSchemaSubstGroupPtr
xmlSchemaSubstGroupAdd(xmlSchemaParserCtxtPtr pctxt,xmlSchemaElementPtr head)5728 xmlSchemaSubstGroupAdd(xmlSchemaParserCtxtPtr pctxt,
5729 		       xmlSchemaElementPtr head)
5730 {
5731     xmlSchemaSubstGroupPtr ret;
5732 
5733     /* Init subst group hash. */
5734     if (WXS_SUBST_GROUPS(pctxt) == NULL) {
5735 	WXS_SUBST_GROUPS(pctxt) = xmlHashCreateDict(10, pctxt->dict);
5736 	if (WXS_SUBST_GROUPS(pctxt) == NULL)
5737 	    return(NULL);
5738     }
5739     /* Create a new substitution group. */
5740     ret = (xmlSchemaSubstGroupPtr) xmlMalloc(sizeof(xmlSchemaSubstGroup));
5741     if (ret == NULL) {
5742 	xmlSchemaPErrMemory(NULL,
5743 	    "allocating a substitution group container", NULL);
5744 	return(NULL);
5745     }
5746     memset(ret, 0, sizeof(xmlSchemaSubstGroup));
5747     ret->head = head;
5748     /* Create list of members. */
5749     ret->members = xmlSchemaItemListCreate();
5750     if (ret->members == NULL) {
5751 	xmlSchemaSubstGroupFree(ret);
5752 	return(NULL);
5753     }
5754     /* Add subst group to hash. */
5755     if (xmlHashAddEntry2(WXS_SUBST_GROUPS(pctxt),
5756 	head->name, head->targetNamespace, ret) != 0) {
5757 	PERROR_INT("xmlSchemaSubstGroupAdd",
5758 	    "failed to add a new substitution container");
5759 	xmlSchemaSubstGroupFree(ret);
5760 	return(NULL);
5761     }
5762     return(ret);
5763 }
5764 
5765 static xmlSchemaSubstGroupPtr
xmlSchemaSubstGroupGet(xmlSchemaParserCtxtPtr pctxt,xmlSchemaElementPtr head)5766 xmlSchemaSubstGroupGet(xmlSchemaParserCtxtPtr pctxt,
5767 		       xmlSchemaElementPtr head)
5768 {
5769     if (WXS_SUBST_GROUPS(pctxt) == NULL)
5770 	return(NULL);
5771     return(xmlHashLookup2(WXS_SUBST_GROUPS(pctxt),
5772 	head->name, head->targetNamespace));
5773 
5774 }
5775 
5776 /**
5777  * xmlSchemaAddElementSubstitutionMember:
5778  * @pctxt:  a schema parser context
5779  * @head:  the head of the substitution group
5780  * @member: the new member of the substitution group
5781  *
5782  * Allocate a new annotation structure.
5783  *
5784  * Returns the newly allocated structure or NULL in case or error
5785  */
5786 static int
xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt,xmlSchemaElementPtr head,xmlSchemaElementPtr member)5787 xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt,
5788 				      xmlSchemaElementPtr head,
5789 				      xmlSchemaElementPtr member)
5790 {
5791     xmlSchemaSubstGroupPtr substGroup = NULL;
5792 
5793     if ((pctxt == NULL) || (head == NULL) || (member == NULL))
5794 	return (-1);
5795 
5796     substGroup = xmlSchemaSubstGroupGet(pctxt, head);
5797     if (substGroup == NULL)
5798 	substGroup = xmlSchemaSubstGroupAdd(pctxt, head);
5799     if (substGroup == NULL)
5800 	return(-1);
5801     if (xmlSchemaItemListAdd(substGroup->members, member) == -1)
5802 	return(-1);
5803     return(0);
5804 }
5805 
5806 /************************************************************************
5807  *									*
5808  *		Utilities for parsing					*
5809  *									*
5810  ************************************************************************/
5811 
5812 /**
5813  * xmlSchemaPValAttrNodeQNameValue:
5814  * @ctxt:  a schema parser context
5815  * @schema: the schema context
5816  * @ownerDes: the designation of the parent element
5817  * @ownerItem: the parent as a schema object
5818  * @value:  the QName value
5819  * @local: the resulting local part if found, the attribute value otherwise
5820  * @uri:  the resulting namespace URI if found
5821  *
5822  * Extracts the local name and the URI of a QName value and validates it.
5823  * This one is intended to be used on attribute values that
5824  * should resolve to schema components.
5825  *
5826  * Returns 0, in case the QName is valid, a positive error code
5827  * if not valid and -1 if an internal error occurs.
5828  */
5829 static int
xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlSchemaBasicItemPtr ownerItem,xmlAttrPtr attr,const xmlChar * value,const xmlChar ** uri,const xmlChar ** local)5830 xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
5831 				       xmlSchemaPtr schema,
5832 				       xmlSchemaBasicItemPtr ownerItem,
5833 				       xmlAttrPtr attr,
5834 				       const xmlChar *value,
5835 				       const xmlChar **uri,
5836 				       const xmlChar **local)
5837 {
5838     const xmlChar *pref;
5839     xmlNsPtr ns;
5840     int len, ret;
5841 
5842     *uri = NULL;
5843     *local = NULL;
5844     ret = xmlValidateQName(value, 1);
5845     if (ret > 0) {
5846 	xmlSchemaPSimpleTypeErr(ctxt,
5847 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5848 	    ownerItem, (xmlNodePtr) attr,
5849 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
5850 	    NULL, value, NULL, NULL, NULL);
5851 	*local = value;
5852 	return (ctxt->err);
5853     } else if (ret < 0)
5854 	return (-1);
5855 
5856     if (!strchr((char *) value, ':')) {
5857 	ns = xmlSearchNs(attr->doc, attr->parent, NULL);
5858 	if (ns)
5859 	    *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5860 	else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
5861 	    /* TODO: move XML_SCHEMAS_INCLUDING_CONVERT_NS to the
5862 	    * parser context. */
5863 	    /*
5864 	    * This one takes care of included schemas with no
5865 	    * target namespace.
5866 	    */
5867 	    *uri = ctxt->targetNamespace;
5868 	}
5869 	*local = xmlDictLookup(ctxt->dict, value, -1);
5870 	return (0);
5871     }
5872     /*
5873     * At this point xmlSplitQName3 has to return a local name.
5874     */
5875     *local = xmlSplitQName3(value, &len);
5876     *local = xmlDictLookup(ctxt->dict, *local, -1);
5877     pref = xmlDictLookup(ctxt->dict, value, len);
5878     ns = xmlSearchNs(attr->doc, attr->parent, pref);
5879     if (ns == NULL) {
5880 	xmlSchemaPSimpleTypeErr(ctxt,
5881 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5882 	    ownerItem, (xmlNodePtr) attr,
5883 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, value,
5884 	    "The value '%s' of simple type 'xs:QName' has no "
5885 	    "corresponding namespace declaration in scope", value, NULL);
5886 	return (ctxt->err);
5887     } else {
5888         *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5889     }
5890     return (0);
5891 }
5892 
5893 /**
5894  * xmlSchemaPValAttrNodeQName:
5895  * @ctxt:  a schema parser context
5896  * @schema: the schema context
5897  * @ownerDes: the designation of the owner element
5898  * @ownerItem: the owner as a schema object
5899  * @attr:  the attribute node
5900  * @local: the resulting local part if found, the attribute value otherwise
5901  * @uri:  the resulting namespace URI if found
5902  *
5903  * Extracts and validates the QName of an attribute value.
5904  * This one is intended to be used on attribute values that
5905  * should resolve to schema components.
5906  *
5907  * Returns 0, in case the QName is valid, a positive error code
5908  * if not valid and -1 if an internal error occurs.
5909  */
5910 static int
xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlSchemaBasicItemPtr ownerItem,xmlAttrPtr attr,const xmlChar ** uri,const xmlChar ** local)5911 xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
5912 				       xmlSchemaPtr schema,
5913 				       xmlSchemaBasicItemPtr ownerItem,
5914 				       xmlAttrPtr attr,
5915 				       const xmlChar **uri,
5916 				       const xmlChar **local)
5917 {
5918     const xmlChar *value;
5919 
5920     value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5921     return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
5922 	ownerItem, attr, value, uri, local));
5923 }
5924 
5925 /**
5926  * xmlSchemaPValAttrQName:
5927  * @ctxt:  a schema parser context
5928  * @schema: the schema context
5929  * @ownerDes: the designation of the parent element
5930  * @ownerItem: the owner as a schema object
5931  * @ownerElem:  the parent node of the attribute
5932  * @name:  the name of the attribute
5933  * @local: the resulting local part if found, the attribute value otherwise
5934  * @uri:  the resulting namespace URI if found
5935  *
5936  * Extracts and validates the QName of an attribute value.
5937  *
5938  * Returns 0, in case the QName is valid, a positive error code
5939  * if not valid and -1 if an internal error occurs.
5940  */
5941 static int
xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlSchemaBasicItemPtr ownerItem,xmlNodePtr ownerElem,const char * name,const xmlChar ** uri,const xmlChar ** local)5942 xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
5943 				   xmlSchemaPtr schema,
5944 				   xmlSchemaBasicItemPtr ownerItem,
5945 				   xmlNodePtr ownerElem,
5946 				   const char *name,
5947 				   const xmlChar **uri,
5948 				   const xmlChar **local)
5949 {
5950     xmlAttrPtr attr;
5951 
5952     attr = xmlSchemaGetPropNode(ownerElem, name);
5953     if (attr == NULL) {
5954 	*local = NULL;
5955 	*uri = NULL;
5956 	return (0);
5957     }
5958     return (xmlSchemaPValAttrNodeQName(ctxt, schema,
5959 	ownerItem, attr, uri, local));
5960 }
5961 
5962 /**
5963  * xmlSchemaPValAttrID:
5964  * @ctxt:  a schema parser context
5965  * @schema: the schema context
5966  * @ownerDes: the designation of the parent element
5967  * @ownerItem: the owner as a schema object
5968  * @ownerElem:  the parent node of the attribute
5969  * @name:  the name of the attribute
5970  *
5971  * Extracts and validates the ID of an attribute value.
5972  *
5973  * Returns 0, in case the ID is valid, a positive error code
5974  * if not valid and -1 if an internal error occurs.
5975  */
5976 static int
xmlSchemaPValAttrNodeID(xmlSchemaParserCtxtPtr ctxt,xmlAttrPtr attr)5977 xmlSchemaPValAttrNodeID(xmlSchemaParserCtxtPtr ctxt, xmlAttrPtr attr)
5978 {
5979     int ret;
5980     const xmlChar *value;
5981 
5982     if (attr == NULL)
5983 	return(0);
5984     value = xmlSchemaGetNodeContentNoDict((xmlNodePtr) attr);
5985     ret = xmlValidateNCName(value, 1);
5986     if (ret == 0) {
5987 	/*
5988 	* NOTE: the IDness might have already be declared in the DTD
5989 	*/
5990 	if (attr->atype != XML_ATTRIBUTE_ID) {
5991 	    xmlIDPtr res;
5992 	    xmlChar *strip;
5993 
5994 	    /*
5995 	    * TODO: Use xmlSchemaStrip here; it's not exported at this
5996 	    * moment.
5997 	    */
5998 	    strip = xmlSchemaCollapseString(value);
5999 	    if (strip != NULL) {
6000 		xmlFree((xmlChar *) value);
6001 		value = strip;
6002 	    }
6003 	    res = xmlAddID(NULL, attr->doc, value, attr);
6004 	    if (res == NULL) {
6005 		ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
6006 		xmlSchemaPSimpleTypeErr(ctxt,
6007 		    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6008 		    NULL, (xmlNodePtr) attr,
6009 		    xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
6010 		    NULL, NULL, "Duplicate value '%s' of simple "
6011 		    "type 'xs:ID'", value, NULL);
6012 	    } else
6013 		attr->atype = XML_ATTRIBUTE_ID;
6014 	}
6015     } else if (ret > 0) {
6016 	ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
6017 	xmlSchemaPSimpleTypeErr(ctxt,
6018 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6019 	    NULL, (xmlNodePtr) attr,
6020 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
6021 	    NULL, NULL, "The value '%s' of simple type 'xs:ID' is "
6022 	    "not a valid 'xs:NCName'",
6023 	    value, NULL);
6024     }
6025     if (value != NULL)
6026 	xmlFree((xmlChar *)value);
6027 
6028     return (ret);
6029 }
6030 
6031 static int
xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr ownerElem,const xmlChar * name)6032 xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,
6033 		    xmlNodePtr ownerElem,
6034 		    const xmlChar *name)
6035 {
6036     xmlAttrPtr attr;
6037 
6038     attr = xmlSchemaGetPropNode(ownerElem, (const char *) name);
6039     if (attr == NULL)
6040 	return(0);
6041     return(xmlSchemaPValAttrNodeID(ctxt, attr));
6042 
6043 }
6044 
6045 /**
6046  * xmlGetMaxOccurs:
6047  * @ctxt:  a schema validation context
6048  * @node:  a subtree containing XML Schema informations
6049  *
6050  * Get the maxOccurs property
6051  *
6052  * Returns the default if not found, or the value
6053  */
6054 static int
xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,int min,int max,int def,const char * expected)6055 xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
6056 		int min, int max, int def, const char *expected)
6057 {
6058     const xmlChar *val, *cur;
6059     int ret = 0;
6060     xmlAttrPtr attr;
6061 
6062     attr = xmlSchemaGetPropNode(node, "maxOccurs");
6063     if (attr == NULL)
6064 	return (def);
6065     val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6066 
6067     if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
6068 	if (max != UNBOUNDED) {
6069 	    xmlSchemaPSimpleTypeErr(ctxt,
6070 		XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6071 		/* XML_SCHEMAP_INVALID_MINOCCURS, */
6072 		NULL, (xmlNodePtr) attr, NULL, expected,
6073 		val, NULL, NULL, NULL);
6074 	    return (def);
6075 	} else
6076 	    return (UNBOUNDED);  /* encoding it with -1 might be another option */
6077     }
6078 
6079     cur = val;
6080     while (IS_BLANK_CH(*cur))
6081         cur++;
6082     if (*cur == 0) {
6083         xmlSchemaPSimpleTypeErr(ctxt,
6084 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6085 	    /* XML_SCHEMAP_INVALID_MINOCCURS, */
6086 	    NULL, (xmlNodePtr) attr, NULL, expected,
6087 	    val, NULL, NULL, NULL);
6088 	return (def);
6089     }
6090     while ((*cur >= '0') && (*cur <= '9')) {
6091         ret = ret * 10 + (*cur - '0');
6092         cur++;
6093     }
6094     while (IS_BLANK_CH(*cur))
6095         cur++;
6096     /*
6097     * TODO: Restrict the maximal value to Integer.
6098     */
6099     if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
6100 	xmlSchemaPSimpleTypeErr(ctxt,
6101 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6102 	    /* XML_SCHEMAP_INVALID_MINOCCURS, */
6103 	    NULL, (xmlNodePtr) attr, NULL, expected,
6104 	    val, NULL, NULL, NULL);
6105         return (def);
6106     }
6107     return (ret);
6108 }
6109 
6110 /**
6111  * xmlGetMinOccurs:
6112  * @ctxt:  a schema validation context
6113  * @node:  a subtree containing XML Schema informations
6114  *
6115  * Get the minOccurs property
6116  *
6117  * Returns the default if not found, or the value
6118  */
6119 static int
xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,int min,int max,int def,const char * expected)6120 xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
6121 		int min, int max, int def, const char *expected)
6122 {
6123     const xmlChar *val, *cur;
6124     int ret = 0;
6125     xmlAttrPtr attr;
6126 
6127     attr = xmlSchemaGetPropNode(node, "minOccurs");
6128     if (attr == NULL)
6129 	return (def);
6130     val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6131     cur = val;
6132     while (IS_BLANK_CH(*cur))
6133         cur++;
6134     if (*cur == 0) {
6135         xmlSchemaPSimpleTypeErr(ctxt,
6136 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6137 	    /* XML_SCHEMAP_INVALID_MINOCCURS, */
6138 	    NULL, (xmlNodePtr) attr, NULL, expected,
6139 	    val, NULL, NULL, NULL);
6140         return (def);
6141     }
6142     while ((*cur >= '0') && (*cur <= '9')) {
6143         ret = ret * 10 + (*cur - '0');
6144         cur++;
6145     }
6146     while (IS_BLANK_CH(*cur))
6147         cur++;
6148     /*
6149     * TODO: Restrict the maximal value to Integer.
6150     */
6151     if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
6152 	xmlSchemaPSimpleTypeErr(ctxt,
6153 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6154 	    /* XML_SCHEMAP_INVALID_MINOCCURS, */
6155 	    NULL, (xmlNodePtr) attr, NULL, expected,
6156 	    val, NULL, NULL, NULL);
6157         return (def);
6158     }
6159     return (ret);
6160 }
6161 
6162 /**
6163  * xmlSchemaPGetBoolNodeValue:
6164  * @ctxt:  a schema validation context
6165  * @ownerDes:  owner designation
6166  * @ownerItem:  the owner as a schema item
6167  * @node: the node holding the value
6168  *
6169  * Converts a boolean string value into 1 or 0.
6170  *
6171  * Returns 0 or 1.
6172  */
6173 static int
xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,xmlSchemaBasicItemPtr ownerItem,xmlNodePtr node)6174 xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
6175 			   xmlSchemaBasicItemPtr ownerItem,
6176 			   xmlNodePtr node)
6177 {
6178     xmlChar *value = NULL;
6179     int res = 0;
6180 
6181     value = xmlNodeGetContent(node);
6182     /*
6183     * 3.2.2.1 Lexical representation
6184     * An instance of a datatype that is defined as `boolean`
6185     * can have the following legal literals {true, false, 1, 0}.
6186     */
6187     if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
6188         res = 1;
6189     else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
6190         res = 0;
6191     else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
6192 	res = 1;
6193     else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
6194         res = 0;
6195     else {
6196         xmlSchemaPSimpleTypeErr(ctxt,
6197 	    XML_SCHEMAP_INVALID_BOOLEAN,
6198 	    ownerItem, node,
6199 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6200 	    NULL, BAD_CAST value,
6201 	    NULL, NULL, NULL);
6202     }
6203     if (value != NULL)
6204 	xmlFree(value);
6205     return (res);
6206 }
6207 
6208 /**
6209  * xmlGetBooleanProp:
6210  * @ctxt:  a schema validation context
6211  * @node:  a subtree containing XML Schema informations
6212  * @name:  the attribute name
6213  * @def:  the default value
6214  *
6215  * Evaluate if a boolean property is set
6216  *
6217  * Returns the default if not found, 0 if found to be false,
6218  * 1 if found to be true
6219  */
6220 static int
xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,const char * name,int def)6221 xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
6222 		  xmlNodePtr node,
6223                   const char *name, int def)
6224 {
6225     const xmlChar *val;
6226 
6227     val = xmlSchemaGetProp(ctxt, node, name);
6228     if (val == NULL)
6229         return (def);
6230     /*
6231     * 3.2.2.1 Lexical representation
6232     * An instance of a datatype that is defined as `boolean`
6233     * can have the following legal literals {true, false, 1, 0}.
6234     */
6235     if (xmlStrEqual(val, BAD_CAST "true"))
6236         def = 1;
6237     else if (xmlStrEqual(val, BAD_CAST "false"))
6238         def = 0;
6239     else if (xmlStrEqual(val, BAD_CAST "1"))
6240 	def = 1;
6241     else if (xmlStrEqual(val, BAD_CAST "0"))
6242         def = 0;
6243     else {
6244         xmlSchemaPSimpleTypeErr(ctxt,
6245 	    XML_SCHEMAP_INVALID_BOOLEAN,
6246 	    NULL,
6247 	    (xmlNodePtr) xmlSchemaGetPropNode(node, name),
6248 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6249 	    NULL, val, NULL, NULL, NULL);
6250     }
6251     return (def);
6252 }
6253 
6254 /************************************************************************
6255  *									*
6256  *		Shema extraction from an Infoset			*
6257  *									*
6258  ************************************************************************/
6259 static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
6260                                                  ctxt, xmlSchemaPtr schema,
6261                                                  xmlNodePtr node,
6262 						 int topLevel);
6263 static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
6264                                                   ctxt,
6265                                                   xmlSchemaPtr schema,
6266                                                   xmlNodePtr node,
6267 						  int topLevel);
6268 static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
6269                                                   ctxt,
6270                                                   xmlSchemaPtr schema,
6271                                                   xmlNodePtr node,
6272 						  xmlSchemaTypeType parentType);
6273 static xmlSchemaBasicItemPtr
6274 xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
6275 			     xmlSchemaPtr schema,
6276 			     xmlNodePtr node,
6277 			     xmlSchemaItemListPtr uses,
6278 			     int parentType);
6279 static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
6280                                            xmlSchemaPtr schema,
6281                                            xmlNodePtr node);
6282 static xmlSchemaWildcardPtr
6283 xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
6284                            xmlSchemaPtr schema, xmlNodePtr node);
6285 
6286 /**
6287  * xmlSchemaPValAttrNodeValue:
6288  *
6289  * @ctxt:  a schema parser context
6290  * @ownerDes: the designation of the parent element
6291  * @ownerItem: the schema object owner if existent
6292  * @attr:  the schema attribute node being validated
6293  * @value: the value
6294  * @type: the built-in type to be validated against
6295  *
6296  * Validates a value against the given built-in type.
6297  * This one is intended to be used internally for validation
6298  * of schema attribute values during parsing of the schema.
6299  *
6300  * Returns 0 if the value is valid, a positive error code
6301  * number otherwise and -1 in case of an internal or API error.
6302  */
6303 static int
xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr pctxt,xmlSchemaBasicItemPtr ownerItem,xmlAttrPtr attr,const xmlChar * value,xmlSchemaTypePtr type)6304 xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr pctxt,
6305 			   xmlSchemaBasicItemPtr ownerItem,
6306 			   xmlAttrPtr attr,
6307 			   const xmlChar *value,
6308 			   xmlSchemaTypePtr type)
6309 {
6310 
6311     int ret = 0;
6312 
6313     /*
6314     * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
6315     * one is really meant to be used internally, so better not.
6316     */
6317     if ((pctxt == NULL) || (type == NULL) || (attr == NULL))
6318 	return (-1);
6319     if (type->type != XML_SCHEMA_TYPE_BASIC) {
6320 	PERROR_INT("xmlSchemaPValAttrNodeValue",
6321 	    "the given type is not a built-in type");
6322 	return (-1);
6323     }
6324     switch (type->builtInType) {
6325 	case XML_SCHEMAS_NCNAME:
6326 	case XML_SCHEMAS_QNAME:
6327 	case XML_SCHEMAS_ANYURI:
6328 	case XML_SCHEMAS_TOKEN:
6329 	case XML_SCHEMAS_LANGUAGE:
6330 	    ret = xmlSchemaValPredefTypeNode(type, value, NULL,
6331 		(xmlNodePtr) attr);
6332 	    break;
6333 	default: {
6334 	    PERROR_INT("xmlSchemaPValAttrNodeValue",
6335 		"validation using the given type is not supported while "
6336 		"parsing a schema");
6337 	    return (-1);
6338 	}
6339     }
6340     /*
6341     * TODO: Should we use the S4S error codes instead?
6342     */
6343     if (ret < 0) {
6344 	PERROR_INT("xmlSchemaPValAttrNodeValue",
6345 	    "failed to validate a schema attribute value");
6346 	return (-1);
6347     } else if (ret > 0) {
6348 	if (WXS_IS_LIST(type))
6349 	    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
6350 	else
6351 	    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
6352 	xmlSchemaPSimpleTypeErr(pctxt,
6353 	    ret, ownerItem, (xmlNodePtr) attr,
6354 	    type, NULL, value, NULL, NULL, NULL);
6355     }
6356     return (ret);
6357 }
6358 
6359 /**
6360  * xmlSchemaPValAttrNode:
6361  *
6362  * @ctxt:  a schema parser context
6363  * @ownerDes: the designation of the parent element
6364  * @ownerItem: the schema object owner if existent
6365  * @attr:  the schema attribute node being validated
6366  * @type: the built-in type to be validated against
6367  * @value: the resulting value if any
6368  *
6369  * Extracts and validates a value against the given built-in type.
6370  * This one is intended to be used internally for validation
6371  * of schema attribute values during parsing of the schema.
6372  *
6373  * Returns 0 if the value is valid, a positive error code
6374  * number otherwise and -1 in case of an internal or API error.
6375  */
6376 static int
xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,xmlSchemaBasicItemPtr ownerItem,xmlAttrPtr attr,xmlSchemaTypePtr type,const xmlChar ** value)6377 xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
6378 			   xmlSchemaBasicItemPtr ownerItem,
6379 			   xmlAttrPtr attr,
6380 			   xmlSchemaTypePtr type,
6381 			   const xmlChar **value)
6382 {
6383     const xmlChar *val;
6384 
6385     if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
6386 	return (-1);
6387 
6388     val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6389     if (value != NULL)
6390 	*value = val;
6391 
6392     return (xmlSchemaPValAttrNodeValue(ctxt, ownerItem, attr,
6393 	val, type));
6394 }
6395 
6396 /**
6397  * xmlSchemaPValAttr:
6398  *
6399  * @ctxt:  a schema parser context
6400  * @node: the element node of the attribute
6401  * @ownerDes: the designation of the parent element
6402  * @ownerItem: the schema object owner if existent
6403  * @ownerElem: the owner element node
6404  * @name:  the name of the schema attribute node
6405  * @type: the built-in type to be validated against
6406  * @value: the resulting value if any
6407  *
6408  * Extracts and validates a value against the given built-in type.
6409  * This one is intended to be used internally for validation
6410  * of schema attribute values during parsing of the schema.
6411  *
6412  * Returns 0 if the value is valid, a positive error code
6413  * number otherwise and -1 in case of an internal or API error.
6414  */
6415 static int
xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,xmlSchemaBasicItemPtr ownerItem,xmlNodePtr ownerElem,const char * name,xmlSchemaTypePtr type,const xmlChar ** value)6416 xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
6417 		       xmlSchemaBasicItemPtr ownerItem,
6418 		       xmlNodePtr ownerElem,
6419 		       const char *name,
6420 		       xmlSchemaTypePtr type,
6421 		       const xmlChar **value)
6422 {
6423     xmlAttrPtr attr;
6424 
6425     if ((ctxt == NULL) || (type == NULL)) {
6426 	if (value != NULL)
6427 	    *value = NULL;
6428 	return (-1);
6429     }
6430     if (type->type != XML_SCHEMA_TYPE_BASIC) {
6431 	if (value != NULL)
6432 	    *value = NULL;
6433 	xmlSchemaPErr(ctxt, ownerElem,
6434 	    XML_SCHEMAP_INTERNAL,
6435 	    "Internal error: xmlSchemaPValAttr, the given "
6436 	    "type '%s' is not a built-in type.\n",
6437 	    type->name, NULL);
6438 	return (-1);
6439     }
6440     attr = xmlSchemaGetPropNode(ownerElem, name);
6441     if (attr == NULL) {
6442 	if (value != NULL)
6443 	    *value = NULL;
6444 	return (0);
6445     }
6446     return (xmlSchemaPValAttrNode(ctxt, ownerItem, attr,
6447 	type, value));
6448 }
6449 
6450 static int
xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema ATTRIBUTE_UNUSED,xmlNodePtr node,xmlAttrPtr attr,const xmlChar * namespaceName)6451 xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,
6452 		  xmlSchemaPtr schema ATTRIBUTE_UNUSED,
6453 		  xmlNodePtr node,
6454 		  xmlAttrPtr attr,
6455 		  const xmlChar *namespaceName)
6456 {
6457     /* TODO: Pointer comparison instead? */
6458     if (xmlStrEqual(pctxt->targetNamespace, namespaceName))
6459 	return (0);
6460     if (xmlStrEqual(xmlSchemaNs, namespaceName))
6461 	return (0);
6462     /*
6463     * Check if the referenced namespace was <import>ed.
6464     */
6465     if (WXS_BUCKET(pctxt)->relations != NULL) {
6466 	xmlSchemaSchemaRelationPtr rel;
6467 
6468 	rel = WXS_BUCKET(pctxt)->relations;
6469 	do {
6470 	    if (WXS_IS_BUCKET_IMPMAIN(rel->type) &&
6471 		xmlStrEqual(namespaceName, rel->importNamespace))
6472 		return (0);
6473 	    rel = rel->next;
6474 	} while (rel != NULL);
6475     }
6476     /*
6477     * No matching <import>ed namespace found.
6478     */
6479     {
6480 	xmlNodePtr n = (attr != NULL) ? (xmlNodePtr) attr : node;
6481 
6482 	if (namespaceName == NULL)
6483 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
6484 		XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6485 		"References from this schema to components in no "
6486 		"namespace are not allowed, since not indicated by an "
6487 		"import statement", NULL, NULL);
6488 	else
6489 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
6490 		XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6491 		"References from this schema to components in the "
6492 		"namespace '%s' are not allowed, since not indicated by an "
6493 		"import statement", namespaceName, NULL);
6494     }
6495     return (XML_SCHEMAP_SRC_RESOLVE);
6496 }
6497 
6498 /**
6499  * xmlSchemaParseLocalAttributes:
6500  * @ctxt:  a schema validation context
6501  * @schema:  the schema being built
6502  * @node:  a subtree containing XML Schema informations
6503  * @type:  the hosting type where the attributes will be anchored
6504  *
6505  * Parses attribute uses and attribute declarations and
6506  * attribute group references.
6507  */
6508 static int
xmlSchemaParseLocalAttributes(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr * child,xmlSchemaItemListPtr * list,int parentType,int * hasRefs)6509 xmlSchemaParseLocalAttributes(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6510                         xmlNodePtr *child, xmlSchemaItemListPtr *list,
6511 			int parentType, int *hasRefs)
6512 {
6513     void *item;
6514 
6515     while ((IS_SCHEMA((*child), "attribute")) ||
6516            (IS_SCHEMA((*child), "attributeGroup"))) {
6517         if (IS_SCHEMA((*child), "attribute")) {
6518 	    item = xmlSchemaParseLocalAttribute(ctxt, schema, *child,
6519 		*list, parentType);
6520         } else {
6521             item = xmlSchemaParseAttributeGroupRef(ctxt, schema, *child);
6522 	    if ((item != NULL) && (hasRefs != NULL))
6523 		*hasRefs = 1;
6524         }
6525 	if (item != NULL) {
6526 	    if (*list == NULL) {
6527 		/* TODO: Customize grow factor. */
6528 		*list = xmlSchemaItemListCreate();
6529 		if (*list == NULL)
6530 		    return(-1);
6531 	    }
6532 	    if (xmlSchemaItemListAddSize(*list, 2, item) == -1)
6533 		return(-1);
6534 	}
6535         *child = (*child)->next;
6536     }
6537     return (0);
6538 }
6539 
6540 /**
6541  * xmlSchemaParseAnnotation:
6542  * @ctxt:  a schema validation context
6543  * @schema:  the schema being built
6544  * @node:  a subtree containing XML Schema informations
6545  *
6546  * parse a XML schema Attrribute declaration
6547  * *WARNING* this interface is highly subject to change
6548  *
6549  * Returns -1 in case of error, 0 if the declaration is improper and
6550  *         1 in case of success.
6551  */
6552 static xmlSchemaAnnotPtr
xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,int needed)6553 xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int needed)
6554 {
6555     xmlSchemaAnnotPtr ret;
6556     xmlNodePtr child = NULL;
6557     xmlAttrPtr attr;
6558     int barked = 0;
6559 
6560     /*
6561     * INFO: S4S completed.
6562     */
6563     /*
6564     * id = ID
6565     * {any attributes with non-schema namespace . . .}>
6566     * Content: (appinfo | documentation)*
6567     */
6568     if ((ctxt == NULL) || (node == NULL))
6569         return (NULL);
6570     if (needed)
6571 	ret = xmlSchemaNewAnnot(ctxt, node);
6572     else
6573 	ret = NULL;
6574     attr = node->properties;
6575     while (attr != NULL) {
6576 	if (((attr->ns == NULL) &&
6577 	    (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
6578 	    ((attr->ns != NULL) &&
6579 	    xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
6580 
6581 	    xmlSchemaPIllegalAttrErr(ctxt,
6582 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6583 	}
6584 	attr = attr->next;
6585     }
6586     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6587     /*
6588     * And now for the children...
6589     */
6590     child = node->children;
6591     while (child != NULL) {
6592 	if (IS_SCHEMA(child, "appinfo")) {
6593 	    /* TODO: make available the content of "appinfo". */
6594 	    /*
6595 	    * source = anyURI
6596 	    * {any attributes with non-schema namespace . . .}>
6597 	    * Content: ({any})*
6598 	    */
6599 	    attr = child->properties;
6600 	    while (attr != NULL) {
6601 		if (((attr->ns == NULL) &&
6602 		     (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
6603 		     ((attr->ns != NULL) &&
6604 		      xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
6605 
6606 		    xmlSchemaPIllegalAttrErr(ctxt,
6607 			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6608 		}
6609 		attr = attr->next;
6610 	    }
6611 	    xmlSchemaPValAttr(ctxt, NULL, child, "source",
6612 		xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
6613 	    child = child->next;
6614 	} else if (IS_SCHEMA(child, "documentation")) {
6615 	    /* TODO: make available the content of "documentation". */
6616 	    /*
6617 	    * source = anyURI
6618 	    * {any attributes with non-schema namespace . . .}>
6619 	    * Content: ({any})*
6620 	    */
6621 	    attr = child->properties;
6622 	    while (attr != NULL) {
6623 		if (attr->ns == NULL) {
6624 		    if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
6625 			xmlSchemaPIllegalAttrErr(ctxt,
6626 			    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6627 		    }
6628 		} else {
6629 		    if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
6630 			(xmlStrEqual(attr->name, BAD_CAST "lang") &&
6631 			(!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
6632 
6633 			xmlSchemaPIllegalAttrErr(ctxt,
6634 			    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6635 		    }
6636 		}
6637 		attr = attr->next;
6638 	    }
6639 	    /*
6640 	    * Attribute "xml:lang".
6641 	    */
6642 	    attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
6643 	    if (attr != NULL)
6644 		xmlSchemaPValAttrNode(ctxt, NULL, attr,
6645 		xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
6646 	    child = child->next;
6647 	} else {
6648 	    if (!barked)
6649 		xmlSchemaPContentErr(ctxt,
6650 		    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6651 		    NULL, node, child, NULL, "(appinfo | documentation)*");
6652 	    barked = 1;
6653 	    child = child->next;
6654 	}
6655     }
6656 
6657     return (ret);
6658 }
6659 
6660 /**
6661  * xmlSchemaParseFacet:
6662  * @ctxt:  a schema validation context
6663  * @schema:  the schema being built
6664  * @node:  a subtree containing XML Schema informations
6665  *
6666  * parse a XML schema Facet declaration
6667  * *WARNING* this interface is highly subject to change
6668  *
6669  * Returns the new type structure or NULL in case of error
6670  */
6671 static xmlSchemaFacetPtr
xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)6672 xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6673                     xmlNodePtr node)
6674 {
6675     xmlSchemaFacetPtr facet;
6676     xmlNodePtr child = NULL;
6677     const xmlChar *value;
6678 
6679     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6680         return (NULL);
6681 
6682     facet = xmlSchemaNewFacet();
6683     if (facet == NULL) {
6684         xmlSchemaPErrMemory(ctxt, "allocating facet", node);
6685         return (NULL);
6686     }
6687     facet->node = node;
6688     value = xmlSchemaGetProp(ctxt, node, "value");
6689     if (value == NULL) {
6690         xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
6691                        "Facet %s has no value\n", node->name, NULL);
6692         xmlSchemaFreeFacet(facet);
6693         return (NULL);
6694     }
6695     if (IS_SCHEMA(node, "minInclusive")) {
6696         facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
6697     } else if (IS_SCHEMA(node, "minExclusive")) {
6698         facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
6699     } else if (IS_SCHEMA(node, "maxInclusive")) {
6700         facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
6701     } else if (IS_SCHEMA(node, "maxExclusive")) {
6702         facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
6703     } else if (IS_SCHEMA(node, "totalDigits")) {
6704         facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
6705     } else if (IS_SCHEMA(node, "fractionDigits")) {
6706         facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
6707     } else if (IS_SCHEMA(node, "pattern")) {
6708         facet->type = XML_SCHEMA_FACET_PATTERN;
6709     } else if (IS_SCHEMA(node, "enumeration")) {
6710         facet->type = XML_SCHEMA_FACET_ENUMERATION;
6711     } else if (IS_SCHEMA(node, "whiteSpace")) {
6712         facet->type = XML_SCHEMA_FACET_WHITESPACE;
6713     } else if (IS_SCHEMA(node, "length")) {
6714         facet->type = XML_SCHEMA_FACET_LENGTH;
6715     } else if (IS_SCHEMA(node, "maxLength")) {
6716         facet->type = XML_SCHEMA_FACET_MAXLENGTH;
6717     } else if (IS_SCHEMA(node, "minLength")) {
6718         facet->type = XML_SCHEMA_FACET_MINLENGTH;
6719     } else {
6720         xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
6721                        "Unknown facet type %s\n", node->name, NULL);
6722         xmlSchemaFreeFacet(facet);
6723         return (NULL);
6724     }
6725     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6726     facet->value = value;
6727     if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
6728 	(facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
6729 	const xmlChar *fixed;
6730 
6731 	fixed = xmlSchemaGetProp(ctxt, node, "fixed");
6732 	if (fixed != NULL) {
6733 	    if (xmlStrEqual(fixed, BAD_CAST "true"))
6734 		facet->fixed = 1;
6735 	}
6736     }
6737     child = node->children;
6738 
6739     if (IS_SCHEMA(child, "annotation")) {
6740         facet->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
6741         child = child->next;
6742     }
6743     if (child != NULL) {
6744         xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
6745                        "Facet %s has unexpected child content\n",
6746                        node->name, NULL);
6747     }
6748     return (facet);
6749 }
6750 
6751 /**
6752  * xmlSchemaParseWildcardNs:
6753  * @ctxt:  a schema parser context
6754  * @wildc:  the wildcard, already created
6755  * @node:  a subtree containing XML Schema informations
6756  *
6757  * Parses the attribute "processContents" and "namespace"
6758  * of a xsd:anyAttribute and xsd:any.
6759  * *WARNING* this interface is highly subject to change
6760  *
6761  * Returns 0 if everything goes fine, a positive error code
6762  * if something is not valid and -1 if an internal error occurs.
6763  */
6764 static int
xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema ATTRIBUTE_UNUSED,xmlSchemaWildcardPtr wildc,xmlNodePtr node)6765 xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
6766 			 xmlSchemaPtr schema ATTRIBUTE_UNUSED,
6767 			 xmlSchemaWildcardPtr wildc,
6768 			 xmlNodePtr node)
6769 {
6770     const xmlChar *pc, *ns, *dictnsItem;
6771     int ret = 0;
6772     xmlChar *nsItem;
6773     xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
6774     xmlAttrPtr attr;
6775 
6776     pc = xmlSchemaGetProp(ctxt, node, "processContents");
6777     if ((pc == NULL)
6778         || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
6779         wildc->processContents = XML_SCHEMAS_ANY_STRICT;
6780     } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
6781         wildc->processContents = XML_SCHEMAS_ANY_SKIP;
6782     } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
6783         wildc->processContents = XML_SCHEMAS_ANY_LAX;
6784     } else {
6785         xmlSchemaPSimpleTypeErr(ctxt,
6786 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6787 	    NULL, node,
6788 	    NULL, "(strict | skip | lax)", pc,
6789 	    NULL, NULL, NULL);
6790         wildc->processContents = XML_SCHEMAS_ANY_STRICT;
6791 	ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
6792     }
6793     /*
6794      * Build the namespace constraints.
6795      */
6796     attr = xmlSchemaGetPropNode(node, "namespace");
6797     ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6798     if ((attr == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
6799 	wildc->any = 1;
6800     else if (xmlStrEqual(ns, BAD_CAST "##other")) {
6801 	wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
6802 	if (wildc->negNsSet == NULL) {
6803 	    return (-1);
6804 	}
6805 	wildc->negNsSet->value = ctxt->targetNamespace;
6806     } else {
6807 	const xmlChar *end, *cur;
6808 
6809 	cur = ns;
6810 	do {
6811 	    while (IS_BLANK_CH(*cur))
6812 		cur++;
6813 	    end = cur;
6814 	    while ((*end != 0) && (!(IS_BLANK_CH(*end))))
6815 		end++;
6816 	    if (end == cur)
6817 		break;
6818 	    nsItem = xmlStrndup(cur, end - cur);
6819 	    if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
6820 		    (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
6821 		xmlSchemaPSimpleTypeErr(ctxt,
6822 		    XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
6823 		    NULL, (xmlNodePtr) attr,
6824 		    NULL,
6825 		    "((##any | ##other) | List of (xs:anyURI | "
6826 		    "(##targetNamespace | ##local)))",
6827 		    nsItem, NULL, NULL, NULL);
6828 		ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
6829 	    } else {
6830 		if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
6831 		    dictnsItem = ctxt->targetNamespace;
6832 		} else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
6833 		    dictnsItem = NULL;
6834 		} else {
6835 		    /*
6836 		    * Validate the item (anyURI).
6837 		    */
6838 		    xmlSchemaPValAttrNodeValue(ctxt, NULL, attr,
6839 			nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
6840 		    dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
6841 		}
6842 		/*
6843 		* Avoid dublicate namespaces.
6844 		*/
6845 		tmp = wildc->nsSet;
6846 		while (tmp != NULL) {
6847 		    if (dictnsItem == tmp->value)
6848 			break;
6849 		    tmp = tmp->next;
6850 		}
6851 		if (tmp == NULL) {
6852 		    tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
6853 		    if (tmp == NULL) {
6854 			xmlFree(nsItem);
6855 			return (-1);
6856 		    }
6857 		    tmp->value = dictnsItem;
6858 		    tmp->next = NULL;
6859 		    if (wildc->nsSet == NULL)
6860 			wildc->nsSet = tmp;
6861 		    else if (lastNs != NULL)
6862 			lastNs->next = tmp;
6863 		    lastNs = tmp;
6864 		}
6865 
6866 	    }
6867 	    xmlFree(nsItem);
6868 	    cur = end;
6869 	} while (*cur != 0);
6870     }
6871     return (ret);
6872 }
6873 
6874 static int
xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr item ATTRIBUTE_UNUSED,xmlNodePtr node,int minOccurs,int maxOccurs)6875 xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
6876 				 xmlSchemaParticlePtr item ATTRIBUTE_UNUSED,
6877 				 xmlNodePtr node,
6878 				 int minOccurs,
6879 				 int maxOccurs) {
6880 
6881     if ((maxOccurs == 0) && ( minOccurs == 0))
6882 	return (0);
6883     if (maxOccurs != UNBOUNDED) {
6884 	/*
6885 	* TODO: Maybe we should better not create the particle,
6886 	* if min/max is invalid, since it could confuse the build of the
6887 	* content model.
6888 	*/
6889 	/*
6890 	* 3.9.6 Schema Component Constraint: Particle Correct
6891 	*
6892 	*/
6893 	if (maxOccurs < 1) {
6894 	    /*
6895 	    * 2.2 {max occurs} must be greater than or equal to 1.
6896 	    */
6897 	    xmlSchemaPCustomAttrErr(ctxt,
6898 		XML_SCHEMAP_P_PROPS_CORRECT_2_2,
6899 		NULL, NULL,
6900 		xmlSchemaGetPropNode(node, "maxOccurs"),
6901 		"The value must be greater than or equal to 1");
6902 	    return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
6903 	} else if (minOccurs > maxOccurs) {
6904 	    /*
6905 	    * 2.1 {min occurs} must not be greater than {max occurs}.
6906 	    */
6907 	    xmlSchemaPCustomAttrErr(ctxt,
6908 		XML_SCHEMAP_P_PROPS_CORRECT_2_1,
6909 		NULL, NULL,
6910 		xmlSchemaGetPropNode(node, "minOccurs"),
6911 		"The value must not be greater than the value of 'maxOccurs'");
6912 	    return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
6913 	}
6914     }
6915     return (0);
6916 }
6917 
6918 /**
6919  * xmlSchemaParseAny:
6920  * @ctxt:  a schema validation context
6921  * @schema:  the schema being built
6922  * @node:  a subtree containing XML Schema informations
6923  *
6924  * Parsea a XML schema <any> element. A particle and wildcard
6925  * will be created (except if minOccurs==maxOccurs==0, in this case
6926  * nothing will be created).
6927  * *WARNING* this interface is highly subject to change
6928  *
6929  * Returns the particle or NULL in case of error or if minOccurs==maxOccurs==0
6930  */
6931 static xmlSchemaParticlePtr
xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)6932 xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6933                   xmlNodePtr node)
6934 {
6935     xmlSchemaParticlePtr particle;
6936     xmlNodePtr child = NULL;
6937     xmlSchemaWildcardPtr wild;
6938     int min, max;
6939     xmlAttrPtr attr;
6940     xmlSchemaAnnotPtr annot = NULL;
6941 
6942     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6943         return (NULL);
6944     /*
6945     * Check for illegal attributes.
6946     */
6947     attr = node->properties;
6948     while (attr != NULL) {
6949 	if (attr->ns == NULL) {
6950 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6951 		(!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
6952 		(!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
6953 	        (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6954 		(!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
6955 		xmlSchemaPIllegalAttrErr(ctxt,
6956 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6957 	    }
6958 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6959 	    xmlSchemaPIllegalAttrErr(ctxt,
6960 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6961 	}
6962 	attr = attr->next;
6963     }
6964     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6965     /*
6966     * minOccurs/maxOccurs.
6967     */
6968     max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
6969 	"(xs:nonNegativeInteger | unbounded)");
6970     min = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
6971 	"xs:nonNegativeInteger");
6972     xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
6973     /*
6974     * Create & parse the wildcard.
6975     */
6976     wild = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY, node);
6977     if (wild == NULL)
6978 	return (NULL);
6979     xmlSchemaParseWildcardNs(ctxt, schema, wild, node);
6980     /*
6981     * And now for the children...
6982     */
6983     child = node->children;
6984     if (IS_SCHEMA(child, "annotation")) {
6985         annot = xmlSchemaParseAnnotation(ctxt, child, 1);
6986         child = child->next;
6987     }
6988     if (child != NULL) {
6989 	xmlSchemaPContentErr(ctxt,
6990 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6991 	    NULL, node, child,
6992 	    NULL, "(annotation?)");
6993     }
6994     /*
6995     * No component if minOccurs==maxOccurs==0.
6996     */
6997     if ((min == 0) && (max == 0)) {
6998 	/* Don't free the wildcard, since it's already on the list. */
6999 	return (NULL);
7000     }
7001     /*
7002     * Create the particle.
7003     */
7004     particle = xmlSchemaAddParticle(ctxt, node, min, max);
7005     if (particle == NULL)
7006         return (NULL);
7007     particle->annot = annot;
7008     particle->children = (xmlSchemaTreeItemPtr) wild;
7009 
7010     return (particle);
7011 }
7012 
7013 /**
7014  * xmlSchemaParseNotation:
7015  * @ctxt:  a schema validation context
7016  * @schema:  the schema being built
7017  * @node:  a subtree containing XML Schema informations
7018  *
7019  * parse a XML schema Notation declaration
7020  *
7021  * Returns the new structure or NULL in case of error
7022  */
7023 static xmlSchemaNotationPtr
xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)7024 xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
7025                        xmlNodePtr node)
7026 {
7027     const xmlChar *name;
7028     xmlSchemaNotationPtr ret;
7029     xmlNodePtr child = NULL;
7030 
7031     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7032         return (NULL);
7033     name = xmlSchemaGetProp(ctxt, node, "name");
7034     if (name == NULL) {
7035         xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
7036                        "Notation has no name\n", NULL, NULL);
7037         return (NULL);
7038     }
7039     ret = xmlSchemaAddNotation(ctxt, schema, name,
7040 	ctxt->targetNamespace, node);
7041     if (ret == NULL)
7042         return (NULL);
7043     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
7044 
7045     child = node->children;
7046     if (IS_SCHEMA(child, "annotation")) {
7047         ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
7048         child = child->next;
7049     }
7050     if (child != NULL) {
7051 	xmlSchemaPContentErr(ctxt,
7052 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7053 	    NULL, node, child,
7054 	    NULL, "(annotation?)");
7055     }
7056 
7057     return (ret);
7058 }
7059 
7060 /**
7061  * xmlSchemaParseAnyAttribute:
7062  * @ctxt:  a schema validation context
7063  * @schema:  the schema being built
7064  * @node:  a subtree containing XML Schema informations
7065  *
7066  * parse a XML schema AnyAttrribute declaration
7067  * *WARNING* this interface is highly subject to change
7068  *
7069  * Returns a wildcard or NULL.
7070  */
7071 static xmlSchemaWildcardPtr
xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)7072 xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
7073                            xmlSchemaPtr schema, xmlNodePtr node)
7074 {
7075     xmlSchemaWildcardPtr ret;
7076     xmlNodePtr child = NULL;
7077     xmlAttrPtr attr;
7078 
7079     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7080         return (NULL);
7081 
7082     ret = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
7083 	node);
7084     if (ret == NULL) {
7085         return (NULL);
7086     }
7087     /*
7088     * Check for illegal attributes.
7089     */
7090     attr = node->properties;
7091     while (attr != NULL) {
7092 	if (attr->ns == NULL) {
7093 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7094 	        (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
7095 		(!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
7096 		xmlSchemaPIllegalAttrErr(ctxt,
7097 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7098 	    }
7099 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7100 	    xmlSchemaPIllegalAttrErr(ctxt,
7101 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7102 	}
7103 	attr = attr->next;
7104     }
7105     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
7106     /*
7107     * Parse the namespace list.
7108     */
7109     if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0)
7110 	return (NULL);
7111     /*
7112     * And now for the children...
7113     */
7114     child = node->children;
7115     if (IS_SCHEMA(child, "annotation")) {
7116         ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
7117         child = child->next;
7118     }
7119     if (child != NULL) {
7120 	xmlSchemaPContentErr(ctxt,
7121 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7122 	    NULL, node, child,
7123 	    NULL, "(annotation?)");
7124     }
7125 
7126     return (ret);
7127 }
7128 
7129 
7130 /**
7131  * xmlSchemaParseAttribute:
7132  * @ctxt:  a schema validation context
7133  * @schema:  the schema being built
7134  * @node:  a subtree containing XML Schema informations
7135  *
7136  * parse a XML schema Attrribute declaration
7137  * *WARNING* this interface is highly subject to change
7138  *
7139  * Returns the attribute declaration.
7140  */
7141 static xmlSchemaBasicItemPtr
xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node,xmlSchemaItemListPtr uses,int parentType)7142 xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
7143 			     xmlSchemaPtr schema,
7144 			     xmlNodePtr node,
7145 			     xmlSchemaItemListPtr uses,
7146 			     int parentType)
7147 {
7148     const xmlChar *attrValue, *name = NULL, *ns = NULL;
7149     xmlSchemaAttributeUsePtr use = NULL;
7150     xmlNodePtr child = NULL;
7151     xmlAttrPtr attr;
7152     const xmlChar *tmpNs = NULL, *tmpName = NULL, *defValue = NULL;
7153     int isRef = 0, occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7154     int	nberrors, hasForm = 0, defValueType = 0;
7155 
7156 #define WXS_ATTR_DEF_VAL_DEFAULT 1
7157 #define WXS_ATTR_DEF_VAL_FIXED 2
7158 
7159     /*
7160      * 3.2.3 Constraints on XML Representations of Attribute Declarations
7161      */
7162 
7163     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7164         return (NULL);
7165     attr = xmlSchemaGetPropNode(node, "ref");
7166     if (attr != NULL) {
7167 	if (xmlSchemaPValAttrNodeQName(pctxt, schema,
7168 	    NULL, attr, &tmpNs, &tmpName) != 0) {
7169 	    return (NULL);
7170 	}
7171 	if (xmlSchemaCheckReference(pctxt, schema, node, attr, tmpNs) != 0)
7172 	    return(NULL);
7173 	isRef = 1;
7174     }
7175     nberrors = pctxt->nberrors;
7176     /*
7177     * Check for illegal attributes.
7178     */
7179     attr = node->properties;
7180     while (attr != NULL) {
7181 	if (attr->ns == NULL) {
7182 	    if (isRef) {
7183 		if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7184 		    xmlSchemaPValAttrNodeID(pctxt, attr);
7185 		    goto attr_next;
7186 		} else if (xmlStrEqual(attr->name, BAD_CAST "ref")) {
7187 		    goto attr_next;
7188 		}
7189 	    } else {
7190 		if (xmlStrEqual(attr->name, BAD_CAST "name")) {
7191 		    goto attr_next;
7192 		} else if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7193 		    xmlSchemaPValAttrNodeID(pctxt, attr);
7194 		    goto attr_next;
7195 		} else if (xmlStrEqual(attr->name, BAD_CAST "type")) {
7196 		    xmlSchemaPValAttrNodeQName(pctxt, schema, NULL,
7197 			attr, &tmpNs, &tmpName);
7198 		    goto attr_next;
7199 		} else if (xmlStrEqual(attr->name, BAD_CAST "form")) {
7200 		    /*
7201 		    * Evaluate the target namespace
7202 		    */
7203 		    hasForm = 1;
7204 		    attrValue = xmlSchemaGetNodeContent(pctxt,
7205 			(xmlNodePtr) attr);
7206 		    if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
7207 			ns = pctxt->targetNamespace;
7208 		    } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified"))
7209 		    {
7210 			xmlSchemaPSimpleTypeErr(pctxt,
7211 			    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7212 			    NULL, (xmlNodePtr) attr,
7213 			    NULL, "(qualified | unqualified)",
7214 			    attrValue, NULL, NULL, NULL);
7215 		    }
7216 		    goto attr_next;
7217 		}
7218 	    }
7219 	    if (xmlStrEqual(attr->name, BAD_CAST "use")) {
7220 
7221 		attrValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7222 		/* TODO: Maybe we need to normalize the value beforehand. */
7223 		if (xmlStrEqual(attrValue, BAD_CAST "optional"))
7224 		    occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7225 		else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
7226 		    occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
7227 		else if (xmlStrEqual(attrValue, BAD_CAST "required"))
7228 		    occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
7229 		else {
7230 		    xmlSchemaPSimpleTypeErr(pctxt,
7231 			XML_SCHEMAP_INVALID_ATTR_USE,
7232 			NULL, (xmlNodePtr) attr,
7233 			NULL, "(optional | prohibited | required)",
7234 			attrValue, NULL, NULL, NULL);
7235 		}
7236 		goto attr_next;
7237 	    } else if (xmlStrEqual(attr->name, BAD_CAST "default")) {
7238 		/*
7239 		* 3.2.3 : 1
7240 		* default and fixed must not both be present.
7241 		*/
7242 		if (defValue) {
7243 		    xmlSchemaPMutualExclAttrErr(pctxt,
7244 			XML_SCHEMAP_SRC_ATTRIBUTE_1,
7245 			NULL, attr, "default", "fixed");
7246 		} else {
7247 		    defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7248 		    defValueType = WXS_ATTR_DEF_VAL_DEFAULT;
7249 		}
7250 		goto attr_next;
7251 	    } else if (xmlStrEqual(attr->name, BAD_CAST "fixed")) {
7252 		/*
7253 		* 3.2.3 : 1
7254 		* default and fixed must not both be present.
7255 		*/
7256 		if (defValue) {
7257 		    xmlSchemaPMutualExclAttrErr(pctxt,
7258 			XML_SCHEMAP_SRC_ATTRIBUTE_1,
7259 			NULL, attr, "default", "fixed");
7260 		} else {
7261 		    defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7262 		    defValueType = WXS_ATTR_DEF_VAL_FIXED;
7263 		}
7264 		goto attr_next;
7265 	    }
7266 	} else if (! xmlStrEqual(attr->ns->href, xmlSchemaNs))
7267 	    goto attr_next;
7268 
7269 	xmlSchemaPIllegalAttrErr(pctxt,
7270 	    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7271 
7272 attr_next:
7273 	attr = attr->next;
7274     }
7275     /*
7276     * 3.2.3 : 2
7277     * If default and use are both present, use must have
7278     * the actual value optional.
7279     */
7280     if ((defValueType == WXS_ATTR_DEF_VAL_DEFAULT) &&
7281 	(occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL)) {
7282 	xmlSchemaPSimpleTypeErr(pctxt,
7283 	    XML_SCHEMAP_SRC_ATTRIBUTE_2,
7284 	    NULL, node, NULL,
7285 	    "(optional | prohibited | required)", NULL,
7286 	    "The value of the attribute 'use' must be 'optional' "
7287 	    "if the attribute 'default' is present",
7288 	    NULL, NULL);
7289     }
7290     /*
7291     * We want correct attributes.
7292     */
7293     if (nberrors != pctxt->nberrors)
7294 	return(NULL);
7295     if (! isRef) {
7296 	xmlSchemaAttributePtr attrDecl;
7297 
7298 	/* TODO: move XML_SCHEMAS_QUALIF_ATTR to the parser. */
7299 	if ((! hasForm) && (schema->flags & XML_SCHEMAS_QUALIF_ATTR))
7300 	    ns = pctxt->targetNamespace;
7301 	/*
7302 	* 3.2.6 Schema Component Constraint: xsi: Not Allowed
7303 	* TODO: Move this to the component layer.
7304 	*/
7305 	if (xmlStrEqual(ns, xmlSchemaInstanceNs)) {
7306 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
7307 		XML_SCHEMAP_NO_XSI,
7308 		node, NULL,
7309 		"The target namespace must not match '%s'",
7310 		xmlSchemaInstanceNs, NULL);
7311 	}
7312 	attr = xmlSchemaGetPropNode(node, "name");
7313 	if (attr == NULL) {
7314 	    xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7315 		NULL, node, "name", NULL);
7316 	    return (NULL);
7317 	}
7318 	if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7319 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7320 	    return (NULL);
7321 	}
7322 	/*
7323 	* 3.2.6 Schema Component Constraint: xmlns Not Allowed
7324 	* TODO: Move this to the component layer.
7325 	*/
7326 	if (xmlStrEqual(name, BAD_CAST "xmlns")) {
7327 	    xmlSchemaPSimpleTypeErr(pctxt,
7328 		XML_SCHEMAP_NO_XMLNS,
7329 		NULL, (xmlNodePtr) attr,
7330 		xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7331 		"The value of the attribute must not match 'xmlns'",
7332 		NULL, NULL);
7333 	    return (NULL);
7334 	}
7335 	if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED)
7336 	    goto check_children;
7337 	/*
7338 	* Create the attribute use component.
7339 	*/
7340 	use = xmlSchemaAddAttributeUse(pctxt, node);
7341 	if (use == NULL)
7342 	    return(NULL);
7343 	use->occurs = occurs;
7344 	/*
7345 	* Create the attribute declaration.
7346 	*/
7347 	attrDecl = xmlSchemaAddAttribute(pctxt, schema, name, ns, node, 0);
7348 	if (attrDecl == NULL)
7349 	    return (NULL);
7350 	if (tmpName != NULL) {
7351 	    attrDecl->typeName = tmpName;
7352 	    attrDecl->typeNs = tmpNs;
7353 	}
7354 	use->attrDecl = attrDecl;
7355 	/*
7356 	* Value constraint.
7357 	*/
7358 	if (defValue != NULL) {
7359 	    attrDecl->defValue = defValue;
7360 	    if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7361 		attrDecl->flags |= XML_SCHEMAS_ATTR_FIXED;
7362 	}
7363     } else if (occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7364 	xmlSchemaQNameRefPtr ref;
7365 
7366 	/*
7367 	* Create the attribute use component.
7368 	*/
7369 	use = xmlSchemaAddAttributeUse(pctxt, node);
7370 	if (use == NULL)
7371 	    return(NULL);
7372 	/*
7373 	* We need to resolve the reference at later stage.
7374 	*/
7375 	WXS_ADD_PENDING(pctxt, use);
7376 	use->occurs = occurs;
7377 	/*
7378 	* Create a QName reference to the attribute declaration.
7379 	*/
7380 	ref = xmlSchemaNewQNameRef(pctxt, XML_SCHEMA_TYPE_ATTRIBUTE,
7381 	    tmpName, tmpNs);
7382 	if (ref == NULL)
7383 	    return(NULL);
7384 	/*
7385 	* Assign the reference. This will be substituted for the
7386 	* referenced attribute declaration when the QName is resolved.
7387 	*/
7388 	use->attrDecl = WXS_ATTR_CAST ref;
7389 	/*
7390 	* Value constraint.
7391 	*/
7392 	if (defValue != NULL)
7393 	    use->defValue = defValue;
7394 	if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7395 	    use->flags |= XML_SCHEMA_ATTR_USE_FIXED;
7396     }
7397 
7398 check_children:
7399     /*
7400     * And now for the children...
7401     */
7402     child = node->children;
7403     if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7404 	xmlSchemaAttributeUseProhibPtr prohib;
7405 
7406 	if (IS_SCHEMA(child, "annotation")) {
7407 	    xmlSchemaParseAnnotation(pctxt, child, 0);
7408 	    child = child->next;
7409 	}
7410 	if (child != NULL) {
7411 	    xmlSchemaPContentErr(pctxt,
7412 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7413 		NULL, node, child, NULL,
7414 		"(annotation?)");
7415 	}
7416 	/*
7417 	* Check for pointlessness of attribute prohibitions.
7418 	*/
7419 	if (parentType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
7420 	    xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7421 		XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7422 		node, NULL,
7423 		"Skipping attribute use prohibition, since it is "
7424 		"pointless inside an <attributeGroup>",
7425 		NULL, NULL, NULL);
7426 	    return(NULL);
7427 	} else if (parentType == XML_SCHEMA_TYPE_EXTENSION) {
7428 	    xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7429 		XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7430 		node, NULL,
7431 		"Skipping attribute use prohibition, since it is "
7432 		"pointless when extending a type",
7433 		NULL, NULL, NULL);
7434 	    return(NULL);
7435 	}
7436 	if (! isRef) {
7437 	    tmpName = name;
7438 	    tmpNs = ns;
7439 	}
7440 	/*
7441 	* Check for duplicate attribute prohibitions.
7442 	*/
7443 	if (uses) {
7444 	    int i;
7445 
7446 	    for (i = 0; i < uses->nbItems; i++) {
7447 		use = uses->items[i];
7448 		if ((use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) &&
7449 		    (tmpName == (WXS_ATTR_PROHIB_CAST use)->name) &&
7450 		    (tmpNs == (WXS_ATTR_PROHIB_CAST use)->targetNamespace))
7451 		{
7452 		    xmlChar *str = NULL;
7453 
7454 		    xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7455 			XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7456 			node, NULL,
7457 			"Skipping duplicate attribute use prohibition '%s'",
7458 			xmlSchemaFormatQName(&str, tmpNs, tmpName),
7459 			NULL, NULL);
7460 		    FREE_AND_NULL(str)
7461 		    return(NULL);
7462 		}
7463 	    }
7464 	}
7465 	/*
7466 	* Create the attribute prohibition helper component.
7467 	*/
7468 	prohib = xmlSchemaAddAttributeUseProhib(pctxt);
7469 	if (prohib == NULL)
7470 	    return(NULL);
7471 	prohib->node = node;
7472 	prohib->name = tmpName;
7473 	prohib->targetNamespace = tmpNs;
7474 	if (isRef) {
7475 	    /*
7476 	    * We need at least to resolve to the attribute declaration.
7477 	    */
7478 	    WXS_ADD_PENDING(pctxt, prohib);
7479 	}
7480 	return(WXS_BASIC_CAST prohib);
7481     } else {
7482 	if (IS_SCHEMA(child, "annotation")) {
7483 	    /*
7484 	    * TODO: Should this go into the attr decl?
7485 	    */
7486 	    use->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7487 	    child = child->next;
7488 	}
7489 	if (isRef) {
7490 	    if (child != NULL) {
7491 		if (IS_SCHEMA(child, "simpleType"))
7492 		    /*
7493 		    * 3.2.3 : 3.2
7494 		    * If ref is present, then all of <simpleType>,
7495 		    * form and type must be absent.
7496 		    */
7497 		    xmlSchemaPContentErr(pctxt,
7498 			XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
7499 			NULL, node, child, NULL,
7500 			"(annotation?)");
7501 		else
7502 		    xmlSchemaPContentErr(pctxt,
7503 			XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7504 			NULL, node, child, NULL,
7505 			"(annotation?)");
7506 	    }
7507 	} else {
7508 	    if (IS_SCHEMA(child, "simpleType")) {
7509 		if (WXS_ATTRUSE_DECL(use)->typeName != NULL) {
7510 		    /*
7511 		    * 3.2.3 : 4
7512 		    * type and <simpleType> must not both be present.
7513 		    */
7514 		    xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7515 			NULL, node, child,
7516 			"The attribute 'type' and the <simpleType> child "
7517 			"are mutually exclusive", NULL);
7518 		} else
7519 		    WXS_ATTRUSE_TYPEDEF(use) =
7520 			xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7521 		child = child->next;
7522 	    }
7523 	    if (child != NULL)
7524 		xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7525 		NULL, node, child, NULL,
7526 		"(annotation?, simpleType?)");
7527 	}
7528     }
7529     return (WXS_BASIC_CAST use);
7530 }
7531 
7532 
7533 static xmlSchemaAttributePtr
xmlSchemaParseGlobalAttribute(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node)7534 xmlSchemaParseGlobalAttribute(xmlSchemaParserCtxtPtr pctxt,
7535 			      xmlSchemaPtr schema,
7536 			      xmlNodePtr node)
7537 {
7538     const xmlChar *attrValue;
7539     xmlSchemaAttributePtr ret;
7540     xmlNodePtr child = NULL;
7541     xmlAttrPtr attr;
7542 
7543     /*
7544      * Note that the w3c spec assumes the schema to be validated with schema
7545      * for schemas beforehand.
7546      *
7547      * 3.2.3 Constraints on XML Representations of Attribute Declarations
7548      */
7549     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7550         return (NULL);
7551     /*
7552     * 3.2.3 : 3.1
7553     * One of ref or name must be present, but not both
7554     */
7555     attr = xmlSchemaGetPropNode(node, "name");
7556     if (attr == NULL) {
7557 	xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7558 	    NULL, node, "name", NULL);
7559 	return (NULL);
7560     }
7561     if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7562 	xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
7563 	return (NULL);
7564     }
7565     /*
7566     * 3.2.6 Schema Component Constraint: xmlns Not Allowed
7567     * TODO: Move this to the component layer.
7568     */
7569     if (xmlStrEqual(attrValue, BAD_CAST "xmlns")) {
7570 	xmlSchemaPSimpleTypeErr(pctxt,
7571 	    XML_SCHEMAP_NO_XMLNS,
7572 	    NULL, (xmlNodePtr) attr,
7573 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7574 	    "The value of the attribute must not match 'xmlns'",
7575 	    NULL, NULL);
7576 	return (NULL);
7577     }
7578     /*
7579     * 3.2.6 Schema Component Constraint: xsi: Not Allowed
7580     * TODO: Move this to the component layer.
7581     *       Or better leave it here and add it to the component layer
7582     *       if we have a schema construction API.
7583     */
7584     if (xmlStrEqual(pctxt->targetNamespace, xmlSchemaInstanceNs)) {
7585 	xmlSchemaCustomErr(ACTXT_CAST pctxt,
7586 	    XML_SCHEMAP_NO_XSI, node, NULL,
7587 	    "The target namespace must not match '%s'",
7588 	    xmlSchemaInstanceNs, NULL);
7589     }
7590 
7591     ret = xmlSchemaAddAttribute(pctxt, schema, attrValue,
7592 	pctxt->targetNamespace, node, 1);
7593     if (ret == NULL)
7594 	return (NULL);
7595     ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
7596 
7597     /*
7598     * Check for illegal attributes.
7599     */
7600     attr = node->properties;
7601     while (attr != NULL) {
7602 	if (attr->ns == NULL) {
7603 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7604 		(!xmlStrEqual(attr->name, BAD_CAST "default")) &&
7605 		(!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
7606 		(!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7607 		(!xmlStrEqual(attr->name, BAD_CAST "type")))
7608 	    {
7609 		xmlSchemaPIllegalAttrErr(pctxt,
7610 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7611 	    }
7612 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7613 	    xmlSchemaPIllegalAttrErr(pctxt,
7614 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7615 	}
7616 	attr = attr->next;
7617     }
7618     xmlSchemaPValAttrQName(pctxt, schema, NULL,
7619 	node, "type", &ret->typeNs, &ret->typeName);
7620 
7621     xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7622     /*
7623     * Attribute "fixed".
7624     */
7625     ret->defValue = xmlSchemaGetProp(pctxt, node, "fixed");
7626     if (ret->defValue != NULL)
7627 	ret->flags |= XML_SCHEMAS_ATTR_FIXED;
7628     /*
7629     * Attribute "default".
7630     */
7631     attr = xmlSchemaGetPropNode(node, "default");
7632     if (attr != NULL) {
7633 	/*
7634 	* 3.2.3 : 1
7635 	* default and fixed must not both be present.
7636 	*/
7637 	if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
7638 	    xmlSchemaPMutualExclAttrErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
7639 		WXS_BASIC_CAST ret, attr, "default", "fixed");
7640 	} else
7641 	    ret->defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7642     }
7643     /*
7644     * And now for the children...
7645     */
7646     child = node->children;
7647     if (IS_SCHEMA(child, "annotation")) {
7648         ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7649         child = child->next;
7650     }
7651     if (IS_SCHEMA(child, "simpleType")) {
7652 	if (ret->typeName != NULL) {
7653 	    /*
7654 	    * 3.2.3 : 4
7655 	    * type and <simpleType> must not both be present.
7656 	    */
7657 	    xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7658 		NULL, node, child,
7659 		"The attribute 'type' and the <simpleType> child "
7660 		"are mutually exclusive", NULL);
7661 	} else
7662 	    ret->subtypes = xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7663 	child = child->next;
7664     }
7665     if (child != NULL)
7666 	xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7667 	    NULL, node, child, NULL,
7668 	    "(annotation?, simpleType?)");
7669 
7670     return (ret);
7671 }
7672 
7673 /**
7674  * xmlSchemaParseAttributeGroupRef:
7675  * @ctxt:  a schema validation context
7676  * @schema:  the schema being built
7677  * @node:  a subtree containing XML Schema informations
7678  *
7679  * Parse an attribute group definition reference.
7680  * Note that a reference to an attribute group does not
7681  * correspond to any component at all.
7682  * *WARNING* this interface is highly subject to change
7683  *
7684  * Returns the attribute group or NULL in case of error.
7685  */
7686 static xmlSchemaQNameRefPtr
xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node)7687 xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,
7688 				xmlSchemaPtr schema,
7689 				xmlNodePtr node)
7690 {
7691     xmlSchemaQNameRefPtr ret;
7692     xmlNodePtr child = NULL;
7693     xmlAttrPtr attr;
7694     const xmlChar *refNs = NULL, *ref = NULL;
7695 
7696     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7697         return (NULL);
7698 
7699     attr = xmlSchemaGetPropNode(node, "ref");
7700     if (attr == NULL) {
7701 	xmlSchemaPMissingAttrErr(pctxt,
7702 	    XML_SCHEMAP_S4S_ATTR_MISSING,
7703 	    NULL, node, "ref", NULL);
7704 	return (NULL);
7705     }
7706     xmlSchemaPValAttrNodeQName(pctxt, schema,
7707 	NULL, attr, &refNs, &ref);
7708     if (xmlSchemaCheckReference(pctxt, schema, node, attr, refNs) != 0)
7709 	return(NULL);
7710 
7711     /*
7712     * Check for illegal attributes.
7713     */
7714     attr = node->properties;
7715     while (attr != NULL) {
7716 	if (attr->ns == NULL) {
7717 	    if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
7718 		(!xmlStrEqual(attr->name, BAD_CAST "id")))
7719 	    {
7720 		xmlSchemaPIllegalAttrErr(pctxt,
7721 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7722 	    }
7723 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7724 	    xmlSchemaPIllegalAttrErr(pctxt,
7725 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7726 	}
7727 	attr = attr->next;
7728     }
7729     /* Attribute ID */
7730     xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7731 
7732     /*
7733     * And now for the children...
7734     */
7735     child = node->children;
7736     if (IS_SCHEMA(child, "annotation")) {
7737 	/*
7738 	* TODO: We do not have a place to store the annotation, do we?
7739 	*/
7740         xmlSchemaParseAnnotation(pctxt, child, 0);
7741         child = child->next;
7742     }
7743     if (child != NULL) {
7744 	xmlSchemaPContentErr(pctxt,
7745 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7746 	    NULL, node, child, NULL,
7747 	    "(annotation?)");
7748     }
7749 
7750     /*
7751     * Handle attribute group redefinitions.
7752     */
7753     if (pctxt->isRedefine && pctxt->redef &&
7754 	(pctxt->redef->item->type ==
7755 	    XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
7756 	(ref == pctxt->redef->refName) &&
7757 	(refNs == pctxt->redef->refTargetNs))
7758     {
7759 	/*
7760 	* SPEC src-redefine:
7761 	* (7.1) "If it has an <attributeGroup> among its contents
7762 	* the `actual value` of whose ref [attribute] is the same
7763 	* as the `actual value` of its own name attribute plus
7764 	* target namespace, then it must have exactly one such group."
7765 	*/
7766 	if (pctxt->redefCounter != 0) {
7767 	    xmlChar *str = NULL;
7768 
7769 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
7770 		XML_SCHEMAP_SRC_REDEFINE, node, NULL,
7771 		"The redefining attribute group definition "
7772 		"'%s' must not contain more than one "
7773 		"reference to the redefined definition",
7774 		xmlSchemaFormatQName(&str, refNs, ref), NULL);
7775 	    FREE_AND_NULL(str);
7776 	    return(NULL);
7777 	}
7778 	pctxt->redefCounter++;
7779 	/*
7780 	* URGENT TODO: How to ensure that the reference will not be
7781 	* handled by the normal component resolution mechanism?
7782 	*/
7783 	ret = xmlSchemaNewQNameRef(pctxt,
7784 	    XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7785 	if (ret == NULL)
7786 	    return(NULL);
7787 	ret->node = node;
7788 	pctxt->redef->reference = WXS_BASIC_CAST ret;
7789     } else {
7790 	/*
7791 	* Create a QName-reference helper component. We will substitute this
7792 	* component for the attribute uses of the referenced attribute group
7793 	* definition.
7794 	*/
7795 	ret = xmlSchemaNewQNameRef(pctxt,
7796 	    XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7797 	if (ret == NULL)
7798 	    return(NULL);
7799 	ret->node = node;
7800 	/* Add to pending items, to be able to resolve the reference. */
7801 	WXS_ADD_PENDING(pctxt, ret);
7802     }
7803     return (ret);
7804 }
7805 
7806 /**
7807  * xmlSchemaParseAttributeGroupDefinition:
7808  * @pctxt:  a schema validation context
7809  * @schema:  the schema being built
7810  * @node:  a subtree containing XML Schema informations
7811  *
7812  * parse a XML schema Attribute Group declaration
7813  * *WARNING* this interface is highly subject to change
7814  *
7815  * Returns the attribute group definition or NULL in case of error.
7816  */
7817 static xmlSchemaAttributeGroupPtr
xmlSchemaParseAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node)7818 xmlSchemaParseAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
7819 				       xmlSchemaPtr schema,
7820 				       xmlNodePtr node)
7821 {
7822     const xmlChar *name;
7823     xmlSchemaAttributeGroupPtr ret;
7824     xmlNodePtr child = NULL;
7825     xmlAttrPtr attr;
7826     int hasRefs = 0;
7827 
7828     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7829         return (NULL);
7830 
7831     attr = xmlSchemaGetPropNode(node, "name");
7832     if (attr == NULL) {
7833 	xmlSchemaPMissingAttrErr(pctxt,
7834 	    XML_SCHEMAP_S4S_ATTR_MISSING,
7835 	    NULL, node, "name", NULL);
7836 	return (NULL);
7837     }
7838     /*
7839     * The name is crucial, exit if invalid.
7840     */
7841     if (xmlSchemaPValAttrNode(pctxt,
7842 	NULL, attr,
7843 	xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7844 	return (NULL);
7845     }
7846     ret = xmlSchemaAddAttributeGroupDefinition(pctxt, schema,
7847 	name, pctxt->targetNamespace, node);
7848     if (ret == NULL)
7849 	return (NULL);
7850     /*
7851     * Check for illegal attributes.
7852     */
7853     attr = node->properties;
7854     while (attr != NULL) {
7855 	if (attr->ns == NULL) {
7856 	    if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7857 		(!xmlStrEqual(attr->name, BAD_CAST "id")))
7858 	    {
7859 		xmlSchemaPIllegalAttrErr(pctxt,
7860 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7861 	    }
7862 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7863 	    xmlSchemaPIllegalAttrErr(pctxt,
7864 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7865 	}
7866 	attr = attr->next;
7867     }
7868     /* Attribute ID */
7869     xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7870     /*
7871     * And now for the children...
7872     */
7873     child = node->children;
7874     if (IS_SCHEMA(child, "annotation")) {
7875         ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7876         child = child->next;
7877     }
7878     /*
7879     * Parse contained attribute decls/refs.
7880     */
7881     if (xmlSchemaParseLocalAttributes(pctxt, schema, &child,
7882 	(xmlSchemaItemListPtr *) &(ret->attrUses),
7883 	XML_SCHEMA_TYPE_ATTRIBUTEGROUP, &hasRefs) == -1)
7884 	return(NULL);
7885     if (hasRefs)
7886 	ret->flags |= XML_SCHEMAS_ATTRGROUP_HAS_REFS;
7887     /*
7888     * Parse the attribute wildcard.
7889     */
7890     if (IS_SCHEMA(child, "anyAttribute")) {
7891 	ret->attributeWildcard = xmlSchemaParseAnyAttribute(pctxt,
7892 	    schema, child);
7893 	child = child->next;
7894     }
7895     if (child != NULL) {
7896 	xmlSchemaPContentErr(pctxt,
7897 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7898 	    NULL, node, child, NULL,
7899 	    "(annotation?, ((attribute | attributeGroup)*, anyAttribute?))");
7900     }
7901     return (ret);
7902 }
7903 
7904 /**
7905  * xmlSchemaPValAttrFormDefault:
7906  * @value:  the value
7907  * @flags: the flags to be modified
7908  * @flagQualified: the specific flag for "qualified"
7909  *
7910  * Returns 0 if the value is valid, 1 otherwise.
7911  */
7912 static int
xmlSchemaPValAttrFormDefault(const xmlChar * value,int * flags,int flagQualified)7913 xmlSchemaPValAttrFormDefault(const xmlChar *value,
7914 			     int *flags,
7915 			     int flagQualified)
7916 {
7917     if (xmlStrEqual(value, BAD_CAST "qualified")) {
7918 	if  ((*flags & flagQualified) == 0)
7919 	    *flags |= flagQualified;
7920     } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
7921 	return (1);
7922 
7923     return (0);
7924 }
7925 
7926 /**
7927  * xmlSchemaPValAttrBlockFinal:
7928  * @value:  the value
7929  * @flags: the flags to be modified
7930  * @flagAll: the specific flag for "#all"
7931  * @flagExtension: the specific flag for "extension"
7932  * @flagRestriction: the specific flag for "restriction"
7933  * @flagSubstitution: the specific flag for "substitution"
7934  * @flagList: the specific flag for "list"
7935  * @flagUnion: the specific flag for "union"
7936  *
7937  * Validates the value of the attribute "final" and "block". The value
7938  * is converted into the specified flag values and returned in @flags.
7939  *
7940  * Returns 0 if the value is valid, 1 otherwise.
7941  */
7942 
7943 static int
xmlSchemaPValAttrBlockFinal(const xmlChar * value,int * flags,int flagAll,int flagExtension,int flagRestriction,int flagSubstitution,int flagList,int flagUnion)7944 xmlSchemaPValAttrBlockFinal(const xmlChar *value,
7945 			    int *flags,
7946 			    int flagAll,
7947 			    int flagExtension,
7948 			    int flagRestriction,
7949 			    int flagSubstitution,
7950 			    int flagList,
7951 			    int flagUnion)
7952 {
7953     int ret = 0;
7954 
7955     /*
7956     * TODO: This does not check for dublicate entries.
7957     */
7958     if ((flags == NULL) || (value == NULL))
7959 	return (-1);
7960     if (value[0] == 0)
7961 	return (0);
7962     if (xmlStrEqual(value, BAD_CAST "#all")) {
7963 	if (flagAll != -1)
7964 	    *flags |= flagAll;
7965 	else {
7966 	    if (flagExtension != -1)
7967 		*flags |= flagExtension;
7968 	    if (flagRestriction != -1)
7969 		*flags |= flagRestriction;
7970 	    if (flagSubstitution != -1)
7971 		*flags |= flagSubstitution;
7972 	    if (flagList != -1)
7973 		*flags |= flagList;
7974 	    if (flagUnion != -1)
7975 		*flags |= flagUnion;
7976 	}
7977     } else {
7978 	const xmlChar *end, *cur = value;
7979 	xmlChar *item;
7980 
7981 	do {
7982 	    while (IS_BLANK_CH(*cur))
7983 		cur++;
7984 	    end = cur;
7985 	    while ((*end != 0) && (!(IS_BLANK_CH(*end))))
7986 		end++;
7987 	    if (end == cur)
7988 		break;
7989 	    item = xmlStrndup(cur, end - cur);
7990 	    if (xmlStrEqual(item, BAD_CAST "extension")) {
7991 		if (flagExtension != -1) {
7992 		    if ((*flags & flagExtension) == 0)
7993 			*flags |= flagExtension;
7994 		} else
7995 		    ret = 1;
7996 	    } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
7997 		if (flagRestriction != -1) {
7998 		    if ((*flags & flagRestriction) == 0)
7999 			*flags |= flagRestriction;
8000 		} else
8001 		    ret = 1;
8002 	    } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
8003 		if (flagSubstitution != -1) {
8004 		    if ((*flags & flagSubstitution) == 0)
8005 			*flags |= flagSubstitution;
8006 		} else
8007 		    ret = 1;
8008 	    } else if (xmlStrEqual(item, BAD_CAST "list")) {
8009 		if (flagList != -1) {
8010 		    if ((*flags & flagList) == 0)
8011 			*flags |= flagList;
8012 		} else
8013 		    ret = 1;
8014 	    } else if (xmlStrEqual(item, BAD_CAST "union")) {
8015 		if (flagUnion != -1) {
8016 		    if ((*flags & flagUnion) == 0)
8017 			*flags |= flagUnion;
8018 		} else
8019 		    ret = 1;
8020 	    } else
8021 		ret = 1;
8022 	    if (item != NULL)
8023 		xmlFree(item);
8024 	    cur = end;
8025 	} while ((ret == 0) && (*cur != 0));
8026     }
8027 
8028     return (ret);
8029 }
8030 
8031 static int
xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,xmlSchemaIDCPtr idc,xmlSchemaIDCSelectPtr selector,xmlAttrPtr attr,int isField)8032 xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
8033 			     xmlSchemaIDCPtr idc,
8034 			     xmlSchemaIDCSelectPtr selector,
8035 			     xmlAttrPtr attr,
8036 			     int isField)
8037 {
8038     xmlNodePtr node;
8039 
8040     /*
8041     * c-selector-xpath:
8042     * Schema Component Constraint: Selector Value OK
8043     *
8044     * TODO: 1 The {selector} must be a valid XPath expression, as defined
8045     * in [XPath].
8046     */
8047     if (selector == NULL) {
8048 	xmlSchemaPErr(ctxt, idc->node,
8049 	    XML_SCHEMAP_INTERNAL,
8050 	    "Internal error: xmlSchemaCheckCSelectorXPath, "
8051 	    "the selector is not specified.\n", NULL, NULL);
8052 	return (-1);
8053     }
8054     if (attr == NULL)
8055 	node = idc->node;
8056     else
8057 	node = (xmlNodePtr) attr;
8058     if (selector->xpath == NULL) {
8059 	xmlSchemaPCustomErr(ctxt,
8060 	    /* TODO: Adjust error code. */
8061 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8062 	    NULL, node,
8063 	    "The XPath expression of the selector is not valid", NULL);
8064 	return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
8065     } else {
8066 	const xmlChar **nsArray = NULL;
8067 	xmlNsPtr *nsList = NULL;
8068 	/*
8069 	* Compile the XPath expression.
8070 	*/
8071 	/*
8072 	* TODO: We need the array of in-scope namespaces for compilation.
8073 	* TODO: Call xmlPatterncompile with different options for selector/
8074 	* field.
8075 	*/
8076 	if (attr == NULL)
8077 	    nsList = NULL;
8078 	else
8079 	    nsList = xmlGetNsList(attr->doc, attr->parent);
8080 	/*
8081 	* Build an array of prefixes and namespaces.
8082 	*/
8083 	if (nsList != NULL) {
8084 	    int i, count = 0;
8085 
8086 	    for (i = 0; nsList[i] != NULL; i++)
8087 		count++;
8088 
8089 	    nsArray = (const xmlChar **) xmlMalloc(
8090 		(count * 2 + 1) * sizeof(const xmlChar *));
8091 	    if (nsArray == NULL) {
8092 		xmlSchemaPErrMemory(ctxt, "allocating a namespace array",
8093 		    NULL);
8094 		xmlFree(nsList);
8095 		return (-1);
8096 	    }
8097 	    for (i = 0; i < count; i++) {
8098 		nsArray[2 * i] = nsList[i]->href;
8099 		nsArray[2 * i + 1] = nsList[i]->prefix;
8100 	    }
8101 	    nsArray[count * 2] = NULL;
8102 	    xmlFree(nsList);
8103 	}
8104 	/*
8105 	* TODO: Differentiate between "selector" and "field".
8106 	*/
8107 	if (isField)
8108 	    selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
8109 		NULL, XML_PATTERN_XSFIELD, nsArray);
8110 	else
8111 	    selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
8112 		NULL, XML_PATTERN_XSSEL, nsArray);
8113 	if (nsArray != NULL)
8114 	    xmlFree((xmlChar **) nsArray);
8115 
8116 	if (selector->xpathComp == NULL) {
8117 	    xmlSchemaPCustomErr(ctxt,
8118 		/* TODO: Adjust error code? */
8119 		XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8120 		NULL, node,
8121 		"The XPath expression '%s' could not be "
8122 		"compiled", selector->xpath);
8123 	    return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
8124 	}
8125     }
8126     return (0);
8127 }
8128 
8129 #define ADD_ANNOTATION(annot)   \
8130     xmlSchemaAnnotPtr cur = item->annot; \
8131     if (item->annot == NULL) {  \
8132 	item->annot = annot;    \
8133 	return (annot);         \
8134     }                           \
8135     cur = item->annot;          \
8136     if (cur->next != NULL) {    \
8137 	cur = cur->next;	\
8138     }                           \
8139     cur->next = annot;
8140 
8141 /**
8142  * xmlSchemaAssignAnnotation:
8143  * @item: the schema component
8144  * @annot: the annotation
8145  *
8146  * Adds the annotation to the given schema component.
8147  *
8148  * Returns the given annotaion.
8149  */
8150 static xmlSchemaAnnotPtr
xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem,xmlSchemaAnnotPtr annot)8151 xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem,
8152 		       xmlSchemaAnnotPtr annot)
8153 {
8154     if ((annItem == NULL) || (annot == NULL))
8155 	return (NULL);
8156     switch (annItem->type) {
8157 	case XML_SCHEMA_TYPE_ELEMENT: {
8158 		xmlSchemaElementPtr item = (xmlSchemaElementPtr) annItem;
8159 		ADD_ANNOTATION(annot)
8160 	    }
8161 	    break;
8162 	case XML_SCHEMA_TYPE_ATTRIBUTE: {
8163 		xmlSchemaAttributePtr item = (xmlSchemaAttributePtr) annItem;
8164 		ADD_ANNOTATION(annot)
8165 	    }
8166 	    break;
8167 	case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
8168 	case XML_SCHEMA_TYPE_ANY: {
8169 		xmlSchemaWildcardPtr item = (xmlSchemaWildcardPtr) annItem;
8170 		ADD_ANNOTATION(annot)
8171 	    }
8172 	    break;
8173 	case XML_SCHEMA_TYPE_PARTICLE:
8174 	case XML_SCHEMA_TYPE_IDC_KEY:
8175 	case XML_SCHEMA_TYPE_IDC_KEYREF:
8176 	case XML_SCHEMA_TYPE_IDC_UNIQUE: {
8177 		xmlSchemaAnnotItemPtr item = (xmlSchemaAnnotItemPtr) annItem;
8178 		ADD_ANNOTATION(annot)
8179 	    }
8180 	    break;
8181 	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: {
8182 		xmlSchemaAttributeGroupPtr item =
8183 		    (xmlSchemaAttributeGroupPtr) annItem;
8184 		ADD_ANNOTATION(annot)
8185 	    }
8186 	    break;
8187 	case XML_SCHEMA_TYPE_NOTATION: {
8188 		xmlSchemaNotationPtr item = (xmlSchemaNotationPtr) annItem;
8189 		ADD_ANNOTATION(annot)
8190 	    }
8191 	    break;
8192 	case XML_SCHEMA_FACET_MININCLUSIVE:
8193 	case XML_SCHEMA_FACET_MINEXCLUSIVE:
8194 	case XML_SCHEMA_FACET_MAXINCLUSIVE:
8195 	case XML_SCHEMA_FACET_MAXEXCLUSIVE:
8196 	case XML_SCHEMA_FACET_TOTALDIGITS:
8197 	case XML_SCHEMA_FACET_FRACTIONDIGITS:
8198 	case XML_SCHEMA_FACET_PATTERN:
8199 	case XML_SCHEMA_FACET_ENUMERATION:
8200 	case XML_SCHEMA_FACET_WHITESPACE:
8201 	case XML_SCHEMA_FACET_LENGTH:
8202 	case XML_SCHEMA_FACET_MAXLENGTH:
8203 	case XML_SCHEMA_FACET_MINLENGTH: {
8204 		xmlSchemaFacetPtr item = (xmlSchemaFacetPtr) annItem;
8205 		ADD_ANNOTATION(annot)
8206 	    }
8207 	    break;
8208 	case XML_SCHEMA_TYPE_SIMPLE:
8209 	case XML_SCHEMA_TYPE_COMPLEX: {
8210 		xmlSchemaTypePtr item = (xmlSchemaTypePtr) annItem;
8211 		ADD_ANNOTATION(annot)
8212 	    }
8213 	    break;
8214 	case XML_SCHEMA_TYPE_GROUP: {
8215 		xmlSchemaModelGroupDefPtr item = (xmlSchemaModelGroupDefPtr) annItem;
8216 		ADD_ANNOTATION(annot)
8217 	    }
8218 	    break;
8219 	case XML_SCHEMA_TYPE_SEQUENCE:
8220 	case XML_SCHEMA_TYPE_CHOICE:
8221 	case XML_SCHEMA_TYPE_ALL: {
8222 		xmlSchemaModelGroupPtr item = (xmlSchemaModelGroupPtr) annItem;
8223 		ADD_ANNOTATION(annot)
8224 	    }
8225 	    break;
8226 	default:
8227 	     xmlSchemaPCustomErr(NULL,
8228 		XML_SCHEMAP_INTERNAL,
8229 		NULL, NULL,
8230 		"Internal error: xmlSchemaAddAnnotation, "
8231 		"The item is not a annotated schema component", NULL);
8232 	     break;
8233     }
8234     return (annot);
8235 }
8236 
8237 /**
8238  * xmlSchemaParseIDCSelectorAndField:
8239  * @ctxt:  a schema validation context
8240  * @schema:  the schema being built
8241  * @node:  a subtree containing XML Schema informations
8242  *
8243  * Parses a XML Schema identity-contraint definition's
8244  * <selector> and <field> elements.
8245  *
8246  * Returns the parsed identity-constraint definition.
8247  */
8248 static xmlSchemaIDCSelectPtr
xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,xmlSchemaIDCPtr idc,xmlNodePtr node,int isField)8249 xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
8250 			  xmlSchemaIDCPtr idc,
8251 			  xmlNodePtr node,
8252 			  int isField)
8253 {
8254     xmlSchemaIDCSelectPtr item;
8255     xmlNodePtr child = NULL;
8256     xmlAttrPtr attr;
8257 
8258     /*
8259     * Check for illegal attributes.
8260     */
8261     attr = node->properties;
8262     while (attr != NULL) {
8263 	if (attr->ns == NULL) {
8264 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8265 		(!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
8266 		xmlSchemaPIllegalAttrErr(ctxt,
8267 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8268 	    }
8269 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8270 	    xmlSchemaPIllegalAttrErr(ctxt,
8271 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8272 	}
8273 	attr = attr->next;
8274     }
8275     /*
8276     * Create the item.
8277     */
8278     item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
8279     if (item == NULL) {
8280         xmlSchemaPErrMemory(ctxt,
8281 	    "allocating a 'selector' of an identity-constraint definition",
8282 	    NULL);
8283         return (NULL);
8284     }
8285     memset(item, 0, sizeof(xmlSchemaIDCSelect));
8286     /*
8287     * Attribute "xpath" (mandatory).
8288     */
8289     attr = xmlSchemaGetPropNode(node, "xpath");
8290     if (attr == NULL) {
8291 	xmlSchemaPMissingAttrErr(ctxt,
8292 	    XML_SCHEMAP_S4S_ATTR_MISSING,
8293 	    NULL, node,
8294 	    "name", NULL);
8295     } else {
8296 	item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8297 	/*
8298 	* URGENT TODO: "field"s have an other syntax than "selector"s.
8299 	*/
8300 
8301 	if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr,
8302 	    isField) == -1) {
8303 	    xmlSchemaPErr(ctxt,
8304 		(xmlNodePtr) attr,
8305 		XML_SCHEMAP_INTERNAL,
8306 		"Internal error: xmlSchemaParseIDCSelectorAndField, "
8307 		"validating the XPath expression of a IDC selector.\n",
8308 		NULL, NULL);
8309 	}
8310 
8311     }
8312     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8313     /*
8314     * And now for the children...
8315     */
8316     child = node->children;
8317     if (IS_SCHEMA(child, "annotation")) {
8318 	/*
8319 	* Add the annotation to the parent IDC.
8320 	*/
8321 	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) idc,
8322 	    xmlSchemaParseAnnotation(ctxt, child, 1));
8323 	child = child->next;
8324     }
8325     if (child != NULL) {
8326 	xmlSchemaPContentErr(ctxt,
8327 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8328 	    NULL, node, child,
8329 	    NULL, "(annotation?)");
8330     }
8331 
8332     return (item);
8333 }
8334 
8335 /**
8336  * xmlSchemaParseIDC:
8337  * @ctxt:  a schema validation context
8338  * @schema:  the schema being built
8339  * @node:  a subtree containing XML Schema informations
8340  *
8341  * Parses a XML Schema identity-contraint definition.
8342  *
8343  * Returns the parsed identity-constraint definition.
8344  */
8345 static xmlSchemaIDCPtr
xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,xmlSchemaTypeType idcCategory,const xmlChar * targetNamespace)8346 xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
8347 		  xmlSchemaPtr schema,
8348 		  xmlNodePtr node,
8349 		  xmlSchemaTypeType idcCategory,
8350 		  const xmlChar *targetNamespace)
8351 {
8352     xmlSchemaIDCPtr item = NULL;
8353     xmlNodePtr child = NULL;
8354     xmlAttrPtr attr;
8355     const xmlChar *name = NULL;
8356     xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
8357 
8358     /*
8359     * Check for illegal attributes.
8360     */
8361     attr = node->properties;
8362     while (attr != NULL) {
8363 	if (attr->ns == NULL) {
8364 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8365 		(!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8366 		((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
8367 		 (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
8368 		xmlSchemaPIllegalAttrErr(ctxt,
8369 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8370 	    }
8371 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8372 	    xmlSchemaPIllegalAttrErr(ctxt,
8373 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8374 	}
8375 	attr = attr->next;
8376     }
8377     /*
8378     * Attribute "name" (mandatory).
8379     */
8380     attr = xmlSchemaGetPropNode(node, "name");
8381     if (attr == NULL) {
8382 	xmlSchemaPMissingAttrErr(ctxt,
8383 	    XML_SCHEMAP_S4S_ATTR_MISSING,
8384 	    NULL, node,
8385 	    "name", NULL);
8386 	return (NULL);
8387     } else if (xmlSchemaPValAttrNode(ctxt,
8388 	NULL, attr,
8389 	xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
8390 	return (NULL);
8391     }
8392     /* Create the component. */
8393     item = xmlSchemaAddIDC(ctxt, schema, name, targetNamespace,
8394 	idcCategory, node);
8395     if (item == NULL)
8396 	return(NULL);
8397 
8398     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8399     if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
8400 	/*
8401 	* Attribute "refer" (mandatory).
8402 	*/
8403 	attr = xmlSchemaGetPropNode(node, "refer");
8404 	if (attr == NULL) {
8405 	    xmlSchemaPMissingAttrErr(ctxt,
8406 		XML_SCHEMAP_S4S_ATTR_MISSING,
8407 		NULL, node,
8408 		"refer", NULL);
8409 	} else {
8410 	    /*
8411 	    * Create a reference item.
8412 	    */
8413 	    item->ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_IDC_KEY,
8414 		NULL, NULL);
8415 	    if (item->ref == NULL)
8416 		return (NULL);
8417 	    xmlSchemaPValAttrNodeQName(ctxt, schema,
8418 		NULL, attr,
8419 		&(item->ref->targetNamespace),
8420 		&(item->ref->name));
8421 	    xmlSchemaCheckReference(ctxt, schema, node, attr,
8422 		item->ref->targetNamespace);
8423 	}
8424     }
8425     /*
8426     * And now for the children...
8427     */
8428     child = node->children;
8429     if (IS_SCHEMA(child, "annotation")) {
8430 	item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
8431 	child = child->next;
8432     }
8433     if (child == NULL) {
8434 	xmlSchemaPContentErr(ctxt,
8435 		XML_SCHEMAP_S4S_ELEM_MISSING,
8436 		NULL, node, child,
8437 		"A child element is missing",
8438 		"(annotation?, (selector, field+))");
8439     }
8440     /*
8441     * Child element <selector>.
8442     */
8443     if (IS_SCHEMA(child, "selector")) {
8444 	item->selector = xmlSchemaParseIDCSelectorAndField(ctxt,
8445 	    item, child, 0);
8446 	child = child->next;
8447 	/*
8448 	* Child elements <field>.
8449 	*/
8450 	if (IS_SCHEMA(child, "field")) {
8451 	    do {
8452 		field = xmlSchemaParseIDCSelectorAndField(ctxt,
8453 		    item, child, 1);
8454 		if (field != NULL) {
8455 		    field->index = item->nbFields;
8456 		    item->nbFields++;
8457 		    if (lastField != NULL)
8458 			lastField->next = field;
8459 		    else
8460 			item->fields = field;
8461 		    lastField = field;
8462 		}
8463 		child = child->next;
8464 	    } while (IS_SCHEMA(child, "field"));
8465 	} else {
8466 	    xmlSchemaPContentErr(ctxt,
8467 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8468 		NULL, node, child,
8469 		NULL, "(annotation?, (selector, field+))");
8470 	}
8471     }
8472     if (child != NULL) {
8473 	xmlSchemaPContentErr(ctxt,
8474 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8475 	    NULL, node, child,
8476 	    NULL, "(annotation?, (selector, field+))");
8477     }
8478 
8479     return (item);
8480 }
8481 
8482 /**
8483  * xmlSchemaParseElement:
8484  * @ctxt:  a schema validation context
8485  * @schema:  the schema being built
8486  * @node:  a subtree containing XML Schema informations
8487  * @topLevel: indicates if this is global declaration
8488  *
8489  * Parses a XML schema element declaration.
8490  * *WARNING* this interface is highly subject to change
8491  *
8492  * Returns the element declaration or a particle; NULL in case
8493  * of an error or if the particle has minOccurs==maxOccurs==0.
8494  */
8495 static xmlSchemaBasicItemPtr
xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,int * isElemRef,int topLevel)8496 xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
8497                       xmlNodePtr node, int *isElemRef, int topLevel)
8498 {
8499     xmlSchemaElementPtr decl = NULL;
8500     xmlSchemaParticlePtr particle = NULL;
8501     xmlSchemaAnnotPtr annot = NULL;
8502     xmlNodePtr child = NULL;
8503     xmlAttrPtr attr, nameAttr;
8504     int min, max, isRef = 0;
8505     xmlChar *des = NULL;
8506 
8507     /* 3.3.3 Constraints on XML Representations of Element Declarations */
8508     /* TODO: Complete implementation of 3.3.6 */
8509 
8510     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8511         return (NULL);
8512 
8513     if (isElemRef != NULL)
8514 	*isElemRef = 0;
8515     /*
8516     * If we get a "ref" attribute on a local <element> we will assume it's
8517     * a reference - even if there's a "name" attribute; this seems to be more
8518     * robust.
8519     */
8520     nameAttr = xmlSchemaGetPropNode(node, "name");
8521     attr = xmlSchemaGetPropNode(node, "ref");
8522     if ((topLevel) || (attr == NULL)) {
8523 	if (nameAttr == NULL) {
8524 	    xmlSchemaPMissingAttrErr(ctxt,
8525 		XML_SCHEMAP_S4S_ATTR_MISSING,
8526 		NULL, node, "name", NULL);
8527 	    return (NULL);
8528 	}
8529     } else
8530 	isRef = 1;
8531 
8532     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8533     child = node->children;
8534     if (IS_SCHEMA(child, "annotation")) {
8535 	annot = xmlSchemaParseAnnotation(ctxt, child, 1);
8536 	child = child->next;
8537     }
8538     /*
8539     * Skip particle part if a global declaration.
8540     */
8541     if (topLevel)
8542 	goto declaration_part;
8543     /*
8544     * The particle part ==================================================
8545     */
8546     min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
8547     max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(xs:nonNegativeInteger | unbounded)");
8548     xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
8549     particle = xmlSchemaAddParticle(ctxt, node, min, max);
8550     if (particle == NULL)
8551 	goto return_null;
8552 
8553     /* ret->flags |= XML_SCHEMAS_ELEM_REF; */
8554 
8555     if (isRef) {
8556 	const xmlChar *refNs = NULL, *ref = NULL;
8557 	xmlSchemaQNameRefPtr refer = NULL;
8558 	/*
8559 	* The reference part =============================================
8560 	*/
8561 	if (isElemRef != NULL)
8562 	    *isElemRef = 1;
8563 
8564 	xmlSchemaPValAttrNodeQName(ctxt, schema,
8565 	    NULL, attr, &refNs, &ref);
8566 	xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
8567 	/*
8568 	* SPEC (3.3.3 : 2.1) "One of ref or name must be present, but not both"
8569 	*/
8570 	if (nameAttr != NULL) {
8571 	    xmlSchemaPMutualExclAttrErr(ctxt,
8572 		XML_SCHEMAP_SRC_ELEMENT_2_1, NULL, nameAttr, "ref", "name");
8573 	}
8574 	/*
8575 	* Check for illegal attributes.
8576 	*/
8577 	attr = node->properties;
8578 	while (attr != NULL) {
8579 	    if (attr->ns == NULL) {
8580 		if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
8581 		    xmlStrEqual(attr->name, BAD_CAST "name") ||
8582 		    xmlStrEqual(attr->name, BAD_CAST "id") ||
8583 		    xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
8584 		    xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
8585 		{
8586 		    attr = attr->next;
8587 		    continue;
8588 		} else {
8589 		    /* SPEC (3.3.3 : 2.2) */
8590 		    xmlSchemaPCustomAttrErr(ctxt,
8591 			XML_SCHEMAP_SRC_ELEMENT_2_2,
8592 			NULL, NULL, attr,
8593 			"Only the attributes 'minOccurs', 'maxOccurs' and "
8594 			"'id' are allowed in addition to 'ref'");
8595 		    break;
8596 		}
8597 	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8598 		xmlSchemaPIllegalAttrErr(ctxt,
8599 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8600 	    }
8601 	    attr = attr->next;
8602 	}
8603 	/*
8604 	* No children except <annotation> expected.
8605 	*/
8606 	if (child != NULL) {
8607 	    xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8608 		NULL, node, child, NULL, "(annotation?)");
8609 	}
8610 	if ((min == 0) && (max == 0))
8611 	    goto return_null;
8612 	/*
8613 	* Create the reference item and attach it to the particle.
8614 	*/
8615 	refer = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_ELEMENT,
8616 	    ref, refNs);
8617 	if (refer == NULL)
8618 	    goto return_null;
8619 	particle->children = (xmlSchemaTreeItemPtr) refer;
8620 	particle->annot = annot;
8621 	/*
8622 	* Add the particle to pending components, since the reference
8623 	* need to be resolved.
8624 	*/
8625 	WXS_ADD_PENDING(ctxt, particle);
8626 	return ((xmlSchemaBasicItemPtr) particle);
8627     }
8628     /*
8629     * The declaration part ===============================================
8630     */
8631 declaration_part:
8632     {
8633 	const xmlChar *ns = NULL, *fixed, *name, *attrValue;
8634 	xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;
8635 
8636 	if (xmlSchemaPValAttrNode(ctxt, NULL, nameAttr,
8637 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
8638 	    goto return_null;
8639 	/*
8640 	* Evaluate the target namespace.
8641 	*/
8642 	if (topLevel) {
8643 	    ns = ctxt->targetNamespace;
8644 	} else {
8645 	    attr = xmlSchemaGetPropNode(node, "form");
8646 	    if (attr != NULL) {
8647 		attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8648 		if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
8649 		    ns = ctxt->targetNamespace;
8650 		} else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
8651 		    xmlSchemaPSimpleTypeErr(ctxt,
8652 			XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8653 			NULL, (xmlNodePtr) attr,
8654 			NULL, "(qualified | unqualified)",
8655 			attrValue, NULL, NULL, NULL);
8656 		}
8657 	    } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
8658 		ns = ctxt->targetNamespace;
8659 	}
8660 	decl = xmlSchemaAddElement(ctxt, name, ns, node, topLevel);
8661 	if (decl == NULL) {
8662 	    goto return_null;
8663 	}
8664 	/*
8665 	* Check for illegal attributes.
8666 	*/
8667 	attr = node->properties;
8668 	while (attr != NULL) {
8669 	    if (attr->ns == NULL) {
8670 		if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8671 		    (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
8672 		    (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8673 		    (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
8674 		    (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
8675 		    (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
8676 		    (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
8677 		{
8678 		    if (topLevel == 0) {
8679 			if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
8680 			    (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
8681 			    (!xmlStrEqual(attr->name, BAD_CAST "form")))
8682 			{
8683 			    xmlSchemaPIllegalAttrErr(ctxt,
8684 				XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8685 			}
8686 		    } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
8687 			(!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
8688 			(!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
8689 
8690 			xmlSchemaPIllegalAttrErr(ctxt,
8691 			    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8692 		    }
8693 		}
8694 	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8695 
8696 		xmlSchemaPIllegalAttrErr(ctxt,
8697 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8698 	    }
8699 	    attr = attr->next;
8700 	}
8701 	/*
8702 	* Extract/validate attributes.
8703 	*/
8704 	if (topLevel) {
8705 	    /*
8706 	    * Process top attributes of global element declarations here.
8707 	    */
8708 	    decl->flags |= XML_SCHEMAS_ELEM_GLOBAL;
8709 	    decl->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
8710 	    xmlSchemaPValAttrQName(ctxt, schema,
8711 		NULL, node, "substitutionGroup",
8712 		&(decl->substGroupNs), &(decl->substGroup));
8713 	    if (xmlGetBooleanProp(ctxt, node, "abstract", 0))
8714 		decl->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
8715 	    /*
8716 	    * Attribute "final".
8717 	    */
8718 	    attr = xmlSchemaGetPropNode(node, "final");
8719 	    if (attr == NULL) {
8720 		if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
8721 		    decl->flags |= XML_SCHEMAS_ELEM_FINAL_EXTENSION;
8722 		if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8723 		    decl->flags |= XML_SCHEMAS_ELEM_FINAL_RESTRICTION;
8724 	    } else {
8725 		attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8726 		if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
8727 		    -1,
8728 		    XML_SCHEMAS_ELEM_FINAL_EXTENSION,
8729 		    XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
8730 		    xmlSchemaPSimpleTypeErr(ctxt,
8731 			XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8732 			NULL, (xmlNodePtr) attr,
8733 			NULL, "(#all | List of (extension | restriction))",
8734 			attrValue, NULL, NULL, NULL);
8735 		}
8736 	    }
8737 	}
8738 	/*
8739 	* Attribute "block".
8740 	*/
8741 	attr = xmlSchemaGetPropNode(node, "block");
8742 	if (attr == NULL) {
8743 	    /*
8744 	    * Apply default "block" values.
8745 	    */
8746 	    if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
8747 		decl->flags |= XML_SCHEMAS_ELEM_BLOCK_RESTRICTION;
8748 	    if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
8749 		decl->flags |= XML_SCHEMAS_ELEM_BLOCK_EXTENSION;
8750 	    if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
8751 		decl->flags |= XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION;
8752 	} else {
8753 	    attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8754 	    if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
8755 		-1,
8756 		XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
8757 		XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
8758 		XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
8759 		xmlSchemaPSimpleTypeErr(ctxt,
8760 		    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8761 		    NULL, (xmlNodePtr) attr,
8762 		    NULL, "(#all | List of (extension | "
8763 		    "restriction | substitution))", attrValue,
8764 		    NULL, NULL, NULL);
8765 	    }
8766 	}
8767 	if (xmlGetBooleanProp(ctxt, node, "nillable", 0))
8768 	    decl->flags |= XML_SCHEMAS_ELEM_NILLABLE;
8769 
8770 	attr = xmlSchemaGetPropNode(node, "type");
8771 	if (attr != NULL) {
8772 	    xmlSchemaPValAttrNodeQName(ctxt, schema,
8773 		NULL, attr,
8774 		&(decl->namedTypeNs), &(decl->namedType));
8775 	    xmlSchemaCheckReference(ctxt, schema, node,
8776 		attr, decl->namedTypeNs);
8777 	}
8778 	decl->value = xmlSchemaGetProp(ctxt, node, "default");
8779 	attr = xmlSchemaGetPropNode(node, "fixed");
8780 	if (attr != NULL) {
8781 	    fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8782 	    if (decl->value != NULL) {
8783 		/*
8784 		* 3.3.3 : 1
8785 		* default and fixed must not both be present.
8786 		*/
8787 		xmlSchemaPMutualExclAttrErr(ctxt,
8788 		    XML_SCHEMAP_SRC_ELEMENT_1,
8789 		    NULL, attr, "default", "fixed");
8790 	    } else {
8791 		decl->flags |= XML_SCHEMAS_ELEM_FIXED;
8792 		decl->value = fixed;
8793 	    }
8794 	}
8795 	/*
8796 	* And now for the children...
8797 	*/
8798 	if (IS_SCHEMA(child, "complexType")) {
8799 	    /*
8800 	    * 3.3.3 : 3
8801 	    * "type" and either <simpleType> or <complexType> are mutually
8802 	    * exclusive
8803 	    */
8804 	    if (decl->namedType != NULL) {
8805 		xmlSchemaPContentErr(ctxt,
8806 		    XML_SCHEMAP_SRC_ELEMENT_3,
8807 		    NULL, node, child,
8808 		    "The attribute 'type' and the <complexType> child are "
8809 		    "mutually exclusive", NULL);
8810 	    } else
8811 		WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseComplexType(ctxt, schema, child, 0);
8812 	    child = child->next;
8813 	} else if (IS_SCHEMA(child, "simpleType")) {
8814 	    /*
8815 	    * 3.3.3 : 3
8816 	    * "type" and either <simpleType> or <complexType> are
8817 	    * mutually exclusive
8818 	    */
8819 	    if (decl->namedType != NULL) {
8820 		xmlSchemaPContentErr(ctxt,
8821 		    XML_SCHEMAP_SRC_ELEMENT_3,
8822 		    NULL, node, child,
8823 		    "The attribute 'type' and the <simpleType> child are "
8824 		    "mutually exclusive", NULL);
8825 	    } else
8826 		WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8827 	    child = child->next;
8828 	}
8829 	while ((IS_SCHEMA(child, "unique")) ||
8830 	    (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
8831 	    if (IS_SCHEMA(child, "unique")) {
8832 		curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8833 		    XML_SCHEMA_TYPE_IDC_UNIQUE, decl->targetNamespace);
8834 	    } else if (IS_SCHEMA(child, "key")) {
8835 		curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8836 		    XML_SCHEMA_TYPE_IDC_KEY, decl->targetNamespace);
8837 	    } else if (IS_SCHEMA(child, "keyref")) {
8838 		curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8839 		    XML_SCHEMA_TYPE_IDC_KEYREF, decl->targetNamespace);
8840 	    }
8841 	    if (lastIDC != NULL)
8842 		lastIDC->next = curIDC;
8843 	    else
8844 		decl->idcs = (void *) curIDC;
8845 	    lastIDC = curIDC;
8846 	    child = child->next;
8847 	}
8848 	if (child != NULL) {
8849 	    xmlSchemaPContentErr(ctxt,
8850 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8851 		NULL, node, child,
8852 		NULL, "(annotation?, ((simpleType | complexType)?, "
8853 		"(unique | key | keyref)*))");
8854 	}
8855 	decl->annot = annot;
8856     }
8857     /*
8858     * NOTE: Element Declaration Representation OK 4. will be checked at a
8859     * different layer.
8860     */
8861     FREE_AND_NULL(des)
8862     if (topLevel)
8863 	return ((xmlSchemaBasicItemPtr) decl);
8864     else {
8865 	particle->children = (xmlSchemaTreeItemPtr) decl;
8866 	return ((xmlSchemaBasicItemPtr) particle);
8867     }
8868 
8869 return_null:
8870     FREE_AND_NULL(des);
8871     if (annot != NULL) {
8872 	if (particle != NULL)
8873 	    particle->annot = NULL;
8874 	if (decl != NULL)
8875 	    decl->annot = NULL;
8876 	xmlSchemaFreeAnnot(annot);
8877     }
8878     return (NULL);
8879 }
8880 
8881 /**
8882  * xmlSchemaParseUnion:
8883  * @ctxt:  a schema validation context
8884  * @schema:  the schema being built
8885  * @node:  a subtree containing XML Schema informations
8886  *
8887  * parse a XML schema Union definition
8888  * *WARNING* this interface is highly subject to change
8889  *
8890  * Returns -1 in case of internal error, 0 in case of success and a positive
8891  * error code otherwise.
8892  */
8893 static int
xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)8894 xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
8895                     xmlNodePtr node)
8896 {
8897     xmlSchemaTypePtr type;
8898     xmlNodePtr child = NULL;
8899     xmlAttrPtr attr;
8900     const xmlChar *cur = NULL;
8901 
8902     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8903         return (-1);
8904     /* Not a component, don't create it. */
8905     type = ctxt->ctxtType;
8906     /*
8907     * Mark the simple type as being of variety "union".
8908     */
8909     type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
8910     /*
8911     * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
8912     * then the `simple ur-type definition`."
8913     */
8914     type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
8915     /*
8916     * Check for illegal attributes.
8917     */
8918     attr = node->properties;
8919     while (attr != NULL) {
8920 	if (attr->ns == NULL) {
8921 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8922 		(!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
8923 		xmlSchemaPIllegalAttrErr(ctxt,
8924 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8925 	    }
8926 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8927 	    xmlSchemaPIllegalAttrErr(ctxt,
8928 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8929 	}
8930 	attr = attr->next;
8931     }
8932     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8933     /*
8934     * Attribute "memberTypes". This is a list of QNames.
8935     * TODO: Check the value to contain anything.
8936     */
8937     attr = xmlSchemaGetPropNode(node, "memberTypes");
8938     if (attr != NULL) {
8939 	const xmlChar *end;
8940 	xmlChar *tmp;
8941 	const xmlChar *localName, *nsName;
8942 	xmlSchemaTypeLinkPtr link, lastLink = NULL;
8943 	xmlSchemaQNameRefPtr ref;
8944 
8945 	cur = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8946 	type->base = cur;
8947 	do {
8948 	    while (IS_BLANK_CH(*cur))
8949 		cur++;
8950 	    end = cur;
8951 	    while ((*end != 0) && (!(IS_BLANK_CH(*end))))
8952 		end++;
8953 	    if (end == cur)
8954 		break;
8955 	    tmp = xmlStrndup(cur, end - cur);
8956 	    if (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
8957 		NULL, attr, BAD_CAST tmp, &nsName, &localName) == 0) {
8958 		/*
8959 		* Create the member type link.
8960 		*/
8961 		link = (xmlSchemaTypeLinkPtr)
8962 		    xmlMalloc(sizeof(xmlSchemaTypeLink));
8963 		if (link == NULL) {
8964 		    xmlSchemaPErrMemory(ctxt, "xmlSchemaParseUnion, "
8965 			"allocating a type link", NULL);
8966 		    return (-1);
8967 		}
8968 		link->type = NULL;
8969 		link->next = NULL;
8970 		if (lastLink == NULL)
8971 		    type->memberTypes = link;
8972 		else
8973 		    lastLink->next = link;
8974 		lastLink = link;
8975 		/*
8976 		* Create a reference item.
8977 		*/
8978 		ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_SIMPLE,
8979 		    localName, nsName);
8980 		if (ref == NULL) {
8981 		    FREE_AND_NULL(tmp)
8982 		    return (-1);
8983 		}
8984 		/*
8985 		* Assign the reference to the link, it will be resolved
8986 		* later during fixup of the union simple type.
8987 		*/
8988 		link->type = (xmlSchemaTypePtr) ref;
8989 	    }
8990 	    FREE_AND_NULL(tmp)
8991 	    cur = end;
8992 	} while (*cur != 0);
8993 
8994     }
8995     /*
8996     * And now for the children...
8997     */
8998     child = node->children;
8999     if (IS_SCHEMA(child, "annotation")) {
9000 	/*
9001 	* Add the annotation to the simple type ancestor.
9002 	*/
9003 	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
9004 	    xmlSchemaParseAnnotation(ctxt, child, 1));
9005         child = child->next;
9006     }
9007     if (IS_SCHEMA(child, "simpleType")) {
9008 	xmlSchemaTypePtr subtype, last = NULL;
9009 
9010 	/*
9011 	* Anchor the member types in the "subtypes" field of the
9012 	* simple type.
9013 	*/
9014 	while (IS_SCHEMA(child, "simpleType")) {
9015 	    subtype = (xmlSchemaTypePtr)
9016 		xmlSchemaParseSimpleType(ctxt, schema, child, 0);
9017 	    if (subtype != NULL) {
9018 		if (last == NULL) {
9019 		    type->subtypes = subtype;
9020 		    last = subtype;
9021 		} else {
9022 		    last->next = subtype;
9023 		    last = subtype;
9024 		}
9025 		last->next = NULL;
9026 	    }
9027 	    child = child->next;
9028 	}
9029     }
9030     if (child != NULL) {
9031 	xmlSchemaPContentErr(ctxt,
9032 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9033 	    NULL, node, child, NULL, "(annotation?, simpleType*)");
9034     }
9035     if ((attr == NULL) && (type->subtypes == NULL)) {
9036 	 /*
9037 	* src-union-memberTypes-or-simpleTypes
9038 	* Either the memberTypes [attribute] of the <union> element must
9039 	* be non-empty or there must be at least one simpleType [child].
9040 	*/
9041 	xmlSchemaPCustomErr(ctxt,
9042 	    XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
9043 	    NULL, node,
9044 	    "Either the attribute 'memberTypes' or "
9045 	    "at least one <simpleType> child must be present", NULL);
9046     }
9047     return (0);
9048 }
9049 
9050 /**
9051  * xmlSchemaParseList:
9052  * @ctxt:  a schema validation context
9053  * @schema:  the schema being built
9054  * @node:  a subtree containing XML Schema informations
9055  *
9056  * parse a XML schema List definition
9057  * *WARNING* this interface is highly subject to change
9058  *
9059  * Returns -1 in case of error, 0 if the declaration is improper and
9060  *         1 in case of success.
9061  */
9062 static xmlSchemaTypePtr
xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)9063 xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9064                    xmlNodePtr node)
9065 {
9066     xmlSchemaTypePtr type;
9067     xmlNodePtr child = NULL;
9068     xmlAttrPtr attr;
9069 
9070     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9071         return (NULL);
9072     /* Not a component, don't create it. */
9073     type = ctxt->ctxtType;
9074     /*
9075     * Mark the type as being of variety "list".
9076     */
9077     type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
9078     /*
9079     * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
9080     * then the `simple ur-type definition`."
9081     */
9082     type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
9083     /*
9084     * Check for illegal attributes.
9085     */
9086     attr = node->properties;
9087     while (attr != NULL) {
9088 	if (attr->ns == NULL) {
9089 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9090 		(!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
9091 		xmlSchemaPIllegalAttrErr(ctxt,
9092 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9093 	    }
9094 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9095 	    xmlSchemaPIllegalAttrErr(ctxt,
9096 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9097 	}
9098 	attr = attr->next;
9099     }
9100 
9101     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9102 
9103     /*
9104     * Attribute "itemType". NOTE that we will use the "ref" and "refNs"
9105     * fields for holding the reference to the itemType.
9106     *
9107     * REVAMP TODO: Use the "base" and "baseNs" fields, since we will remove
9108     * the "ref" fields.
9109     */
9110     xmlSchemaPValAttrQName(ctxt, schema, NULL,
9111 	node, "itemType", &(type->baseNs), &(type->base));
9112     /*
9113     * And now for the children...
9114     */
9115     child = node->children;
9116     if (IS_SCHEMA(child, "annotation")) {
9117 	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
9118 	    xmlSchemaParseAnnotation(ctxt, child, 1));
9119         child = child->next;
9120     }
9121     if (IS_SCHEMA(child, "simpleType")) {
9122 	/*
9123 	* src-list-itemType-or-simpleType
9124 	* Either the itemType [attribute] or the <simpleType> [child] of
9125 	* the <list> element must be present, but not both.
9126 	*/
9127 	if (type->base != NULL) {
9128 	    xmlSchemaPCustomErr(ctxt,
9129 		XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9130 		NULL, node,
9131 		"The attribute 'itemType' and the <simpleType> child "
9132 		"are mutually exclusive", NULL);
9133 	} else {
9134 	    type->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
9135 	}
9136         child = child->next;
9137     } else if (type->base == NULL) {
9138 	xmlSchemaPCustomErr(ctxt,
9139 	    XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9140 	    NULL, node,
9141 	    "Either the attribute 'itemType' or the <simpleType> child "
9142 	    "must be present", NULL);
9143     }
9144     if (child != NULL) {
9145 	xmlSchemaPContentErr(ctxt,
9146 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9147 	    NULL, node, child, NULL, "(annotation?, simpleType?)");
9148     }
9149     if ((type->base == NULL) &&
9150 	(type->subtypes == NULL) &&
9151 	(xmlSchemaGetPropNode(node, "itemType") == NULL)) {
9152 	xmlSchemaPCustomErr(ctxt,
9153 	    XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9154 	    NULL, node,
9155 	    "Either the attribute 'itemType' or the <simpleType> child "
9156 	    "must be present", NULL);
9157     }
9158     return (NULL);
9159 }
9160 
9161 /**
9162  * xmlSchemaParseSimpleType:
9163  * @ctxt:  a schema validation context
9164  * @schema:  the schema being built
9165  * @node:  a subtree containing XML Schema informations
9166  *
9167  * parse a XML schema Simple Type definition
9168  * *WARNING* this interface is highly subject to change
9169  *
9170  * Returns -1 in case of error, 0 if the declaration is improper and
9171  * 1 in case of success.
9172  */
9173 static xmlSchemaTypePtr
xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,int topLevel)9174 xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9175                          xmlNodePtr node, int topLevel)
9176 {
9177     xmlSchemaTypePtr type, oldCtxtType;
9178     xmlNodePtr child = NULL;
9179     const xmlChar *attrValue = NULL;
9180     xmlAttrPtr attr;
9181     int hasRestriction = 0;
9182 
9183     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9184         return (NULL);
9185 
9186     if (topLevel) {
9187 	attr = xmlSchemaGetPropNode(node, "name");
9188 	if (attr == NULL) {
9189 	    xmlSchemaPMissingAttrErr(ctxt,
9190 		XML_SCHEMAP_S4S_ATTR_MISSING,
9191 		NULL, node,
9192 		"name", NULL);
9193 	    return (NULL);
9194 	} else {
9195 	    if (xmlSchemaPValAttrNode(ctxt,
9196 		NULL, attr,
9197 		xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0)
9198 		return (NULL);
9199 	    /*
9200 	    * Skip built-in types.
9201 	    */
9202 	    if (ctxt->isS4S) {
9203 		xmlSchemaTypePtr biType;
9204 
9205 		if (ctxt->isRedefine) {
9206 		    /*
9207 		    * REDEFINE: Disallow redefinition of built-in-types.
9208 		    * TODO: It seems that the spec does not say anything
9209 		    * about this case.
9210 		    */
9211 		    xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
9212 			NULL, node,
9213 			"Redefinition of built-in simple types is not "
9214 			"supported", NULL);
9215 		    return(NULL);
9216 		}
9217 		biType = xmlSchemaGetPredefinedType(attrValue, xmlSchemaNs);
9218 		if (biType != NULL)
9219 		    return (biType);
9220 	    }
9221 	}
9222     }
9223     /*
9224     * TargetNamespace:
9225     * SPEC "The `actual value` of the targetNamespace [attribute]
9226     * of the <schema> ancestor element information item if present,
9227     * otherwise `absent`.
9228     */
9229     if (topLevel == 0) {
9230 #ifdef ENABLE_NAMED_LOCALS
9231         char buf[40];
9232 #endif
9233 	/*
9234 	* Parse as local simple type definition.
9235 	*/
9236 #ifdef ENABLE_NAMED_LOCALS
9237         snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
9238 	type = xmlSchemaAddType(ctxt, schema,
9239 	    XML_SCHEMA_TYPE_SIMPLE,
9240 	    xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
9241 	    ctxt->targetNamespace, node, 0);
9242 #else
9243 	type = xmlSchemaAddType(ctxt, schema,
9244 	    XML_SCHEMA_TYPE_SIMPLE,
9245 	    NULL, ctxt->targetNamespace, node, 0);
9246 #endif
9247 	if (type == NULL)
9248 	    return (NULL);
9249 	type->type = XML_SCHEMA_TYPE_SIMPLE;
9250 	type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
9251 	/*
9252 	* Check for illegal attributes.
9253 	*/
9254 	attr = node->properties;
9255 	while (attr != NULL) {
9256 	    if (attr->ns == NULL) {
9257 		if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
9258 		    xmlSchemaPIllegalAttrErr(ctxt,
9259 			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9260 		}
9261 	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9262 		    xmlSchemaPIllegalAttrErr(ctxt,
9263 			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9264 	    }
9265 	    attr = attr->next;
9266 	}
9267     } else {
9268 	/*
9269 	* Parse as global simple type definition.
9270 	*
9271 	* Note that attrValue is the value of the attribute "name" here.
9272 	*/
9273 	type = xmlSchemaAddType(ctxt, schema, XML_SCHEMA_TYPE_SIMPLE,
9274 	    attrValue, ctxt->targetNamespace, node, 1);
9275 	if (type == NULL)
9276 	    return (NULL);
9277 	type->type = XML_SCHEMA_TYPE_SIMPLE;
9278 	type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
9279 	type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
9280 	/*
9281 	* Check for illegal attributes.
9282 	*/
9283 	attr = node->properties;
9284 	while (attr != NULL) {
9285 	    if (attr->ns == NULL) {
9286 		if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9287 		    (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
9288 		    (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
9289 		    xmlSchemaPIllegalAttrErr(ctxt,
9290 			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9291 		}
9292 	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9293 		xmlSchemaPIllegalAttrErr(ctxt,
9294 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9295 	    }
9296 	    attr = attr->next;
9297 	}
9298 	/*
9299 	* Attribute "final".
9300 	*/
9301 	attr = xmlSchemaGetPropNode(node, "final");
9302 	if (attr == NULL) {
9303 	    if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9304 		type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
9305 	    if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9306 		type->flags |= XML_SCHEMAS_TYPE_FINAL_LIST;
9307 	    if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9308 		type->flags |= XML_SCHEMAS_TYPE_FINAL_UNION;
9309 	} else {
9310 	    attrValue = xmlSchemaGetProp(ctxt, node, "final");
9311 	    if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
9312 		-1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
9313 		XML_SCHEMAS_TYPE_FINAL_LIST,
9314 		XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
9315 
9316 		xmlSchemaPSimpleTypeErr(ctxt,
9317 		    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9318 		    WXS_BASIC_CAST type, (xmlNodePtr) attr,
9319 		    NULL, "(#all | List of (list | union | restriction)",
9320 		    attrValue, NULL, NULL, NULL);
9321 	    }
9322 	}
9323     }
9324     type->targetNamespace = ctxt->targetNamespace;
9325     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9326     /*
9327     * And now for the children...
9328     */
9329     oldCtxtType = ctxt->ctxtType;
9330 
9331     ctxt->ctxtType = type;
9332 
9333     child = node->children;
9334     if (IS_SCHEMA(child, "annotation")) {
9335         type->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9336         child = child->next;
9337     }
9338     if (child == NULL) {
9339 	xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_MISSING,
9340 	    NULL, node, child, NULL,
9341 	    "(annotation?, (restriction | list | union))");
9342     } else if (IS_SCHEMA(child, "restriction")) {
9343         xmlSchemaParseRestriction(ctxt, schema, child,
9344 	    XML_SCHEMA_TYPE_SIMPLE);
9345 	hasRestriction = 1;
9346         child = child->next;
9347     } else if (IS_SCHEMA(child, "list")) {
9348         xmlSchemaParseList(ctxt, schema, child);
9349         child = child->next;
9350     } else if (IS_SCHEMA(child, "union")) {
9351         xmlSchemaParseUnion(ctxt, schema, child);
9352         child = child->next;
9353     }
9354     if (child != NULL) {
9355 	xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9356 	    NULL, node, child, NULL,
9357 	    "(annotation?, (restriction | list | union))");
9358     }
9359     /*
9360     * REDEFINE: SPEC src-redefine (5)
9361     * "Within the [children], each <simpleType> must have a
9362     * <restriction> among its [children] ... the `actual value` of whose
9363     * base [attribute] must be the same as the `actual value` of its own
9364     * name attribute plus target namespace;"
9365     */
9366     if (topLevel && ctxt->isRedefine && (! hasRestriction)) {
9367 	xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
9368 	    NULL, node, "This is a redefinition, thus the "
9369 	    "<simpleType> must have a <restriction> child", NULL);
9370     }
9371 
9372     ctxt->ctxtType = oldCtxtType;
9373     return (type);
9374 }
9375 
9376 /**
9377  * xmlSchemaParseModelGroupDefRef:
9378  * @ctxt:  the parser context
9379  * @schema: the schema being built
9380  * @node:  the node
9381  *
9382  * Parses a reference to a model group definition.
9383  *
9384  * We will return a particle component with a qname-component or
9385  * NULL in case of an error.
9386  */
9387 static xmlSchemaTreeItemPtr
xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)9388 xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt,
9389 			       xmlSchemaPtr schema,
9390 			       xmlNodePtr node)
9391 {
9392     xmlSchemaParticlePtr item;
9393     xmlNodePtr child = NULL;
9394     xmlAttrPtr attr;
9395     const xmlChar *ref = NULL, *refNs = NULL;
9396     int min, max;
9397 
9398     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9399         return (NULL);
9400 
9401     attr = xmlSchemaGetPropNode(node, "ref");
9402     if (attr == NULL) {
9403 	xmlSchemaPMissingAttrErr(ctxt,
9404 	    XML_SCHEMAP_S4S_ATTR_MISSING,
9405 	    NULL, node, "ref", NULL);
9406 	return (NULL);
9407     } else if (xmlSchemaPValAttrNodeQName(ctxt, schema, NULL,
9408 	attr, &refNs, &ref) != 0) {
9409 	return (NULL);
9410     }
9411     xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
9412     min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
9413     max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
9414 	"(xs:nonNegativeInteger | unbounded)");
9415     /*
9416     * Check for illegal attributes.
9417     */
9418     attr = node->properties;
9419     while (attr != NULL) {
9420 	if (attr->ns == NULL) {
9421 	    if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
9422 		(!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9423 		(!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
9424 		(!xmlStrEqual(attr->name, BAD_CAST "maxOccurs"))) {
9425 		xmlSchemaPIllegalAttrErr(ctxt,
9426 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9427 	    }
9428 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9429 	    xmlSchemaPIllegalAttrErr(ctxt,
9430 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9431 	}
9432 	attr = attr->next;
9433     }
9434     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9435     item = xmlSchemaAddParticle(ctxt, node, min, max);
9436     if (item == NULL)
9437 	return (NULL);
9438     /*
9439     * Create a qname-reference and set as the term; it will be substituted
9440     * for the model group after the reference has been resolved.
9441     */
9442     item->children = (xmlSchemaTreeItemPtr)
9443 	xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_GROUP, ref, refNs);
9444     xmlSchemaPCheckParticleCorrect_2(ctxt, item, node, min, max);
9445     /*
9446     * And now for the children...
9447     */
9448     child = node->children;
9449     /* TODO: Is annotation even allowed for a model group reference? */
9450     if (IS_SCHEMA(child, "annotation")) {
9451 	/*
9452 	* TODO: What to do exactly with the annotation?
9453 	*/
9454 	item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9455 	child = child->next;
9456     }
9457     if (child != NULL) {
9458 	xmlSchemaPContentErr(ctxt,
9459 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9460 	    NULL, node, child, NULL,
9461 	    "(annotation?)");
9462     }
9463     /*
9464     * Corresponds to no component at all if minOccurs==maxOccurs==0.
9465     */
9466     if ((min == 0) && (max == 0))
9467 	return (NULL);
9468 
9469     return ((xmlSchemaTreeItemPtr) item);
9470 }
9471 
9472 /**
9473  * xmlSchemaParseModelGroupDefinition:
9474  * @ctxt:  a schema validation context
9475  * @schema:  the schema being built
9476  * @node:  a subtree containing XML Schema informations
9477  *
9478  * Parses a XML schema model group definition.
9479  *
9480  * Note that the contraint src-redefine (6.2) can't be applied until
9481  * references have been resolved. So we will do this at the
9482  * component fixup level.
9483  *
9484  * *WARNING* this interface is highly subject to change
9485  *
9486  * Returns -1 in case of error, 0 if the declaration is improper and
9487  *         1 in case of success.
9488  */
9489 static xmlSchemaModelGroupDefPtr
xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)9490 xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
9491 				   xmlSchemaPtr schema,
9492 				   xmlNodePtr node)
9493 {
9494     xmlSchemaModelGroupDefPtr item;
9495     xmlNodePtr child = NULL;
9496     xmlAttrPtr attr;
9497     const xmlChar *name;
9498 
9499     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9500         return (NULL);
9501 
9502     attr = xmlSchemaGetPropNode(node, "name");
9503     if (attr == NULL) {
9504 	xmlSchemaPMissingAttrErr(ctxt,
9505 	    XML_SCHEMAP_S4S_ATTR_MISSING,
9506 	    NULL, node,
9507 	    "name", NULL);
9508 	return (NULL);
9509     } else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
9510 	xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
9511 	return (NULL);
9512     }
9513     item = xmlSchemaAddModelGroupDefinition(ctxt, schema, name,
9514 	ctxt->targetNamespace, node);
9515     if (item == NULL)
9516 	return (NULL);
9517     /*
9518     * Check for illegal attributes.
9519     */
9520     attr = node->properties;
9521     while (attr != NULL) {
9522 	if (attr->ns == NULL) {
9523 	    if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
9524 		(!xmlStrEqual(attr->name, BAD_CAST "id"))) {
9525 		xmlSchemaPIllegalAttrErr(ctxt,
9526 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9527 	    }
9528 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9529 	    xmlSchemaPIllegalAttrErr(ctxt,
9530 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9531 	}
9532 	attr = attr->next;
9533     }
9534     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9535     /*
9536     * And now for the children...
9537     */
9538     child = node->children;
9539     if (IS_SCHEMA(child, "annotation")) {
9540 	item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9541 	child = child->next;
9542     }
9543     if (IS_SCHEMA(child, "all")) {
9544 	item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9545 	    XML_SCHEMA_TYPE_ALL, 0);
9546 	child = child->next;
9547     } else if (IS_SCHEMA(child, "choice")) {
9548 	item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9549 	    XML_SCHEMA_TYPE_CHOICE, 0);
9550 	child = child->next;
9551     } else if (IS_SCHEMA(child, "sequence")) {
9552 	item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9553 	    XML_SCHEMA_TYPE_SEQUENCE, 0);
9554 	child = child->next;
9555     }
9556 
9557 
9558 
9559     if (child != NULL) {
9560 	xmlSchemaPContentErr(ctxt,
9561 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9562 	    NULL, node, child, NULL,
9563 	    "(annotation?, (all | choice | sequence)?)");
9564     }
9565     return (item);
9566 }
9567 
9568 /**
9569  * xmlSchemaCleanupDoc:
9570  * @ctxt:  a schema validation context
9571  * @node:  the root of the document.
9572  *
9573  * removes unwanted nodes in a schemas document tree
9574  */
9575 static void
xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr root)9576 xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
9577 {
9578     xmlNodePtr delete, cur;
9579 
9580     if ((ctxt == NULL) || (root == NULL)) return;
9581 
9582     /*
9583      * Remove all the blank text nodes
9584      */
9585     delete = NULL;
9586     cur = root;
9587     while (cur != NULL) {
9588         if (delete != NULL) {
9589             xmlUnlinkNode(delete);
9590             xmlFreeNode(delete);
9591             delete = NULL;
9592         }
9593         if (cur->type == XML_TEXT_NODE) {
9594             if (IS_BLANK_NODE(cur)) {
9595                 if (xmlNodeGetSpacePreserve(cur) != 1) {
9596                     delete = cur;
9597                 }
9598             }
9599         } else if ((cur->type != XML_ELEMENT_NODE) &&
9600                    (cur->type != XML_CDATA_SECTION_NODE)) {
9601             delete = cur;
9602             goto skip_children;
9603         }
9604 
9605         /*
9606          * Skip to next node
9607          */
9608         if (cur->children != NULL) {
9609             if ((cur->children->type != XML_ENTITY_DECL) &&
9610                 (cur->children->type != XML_ENTITY_REF_NODE) &&
9611                 (cur->children->type != XML_ENTITY_NODE)) {
9612                 cur = cur->children;
9613                 continue;
9614             }
9615         }
9616       skip_children:
9617         if (cur->next != NULL) {
9618             cur = cur->next;
9619             continue;
9620         }
9621 
9622         do {
9623             cur = cur->parent;
9624             if (cur == NULL)
9625                 break;
9626             if (cur == root) {
9627                 cur = NULL;
9628                 break;
9629             }
9630             if (cur->next != NULL) {
9631                 cur = cur->next;
9632                 break;
9633             }
9634         } while (cur != NULL);
9635     }
9636     if (delete != NULL) {
9637         xmlUnlinkNode(delete);
9638         xmlFreeNode(delete);
9639         delete = NULL;
9640     }
9641 }
9642 
9643 
9644 static void
xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)9645 xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
9646 {
9647     if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
9648 	schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
9649 
9650     if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
9651 	schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
9652 
9653     if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
9654 	schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
9655     if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9656 	schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
9657     if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9658 	schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
9659     if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9660 	schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
9661 
9662     if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
9663 	schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
9664     if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
9665 	schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
9666     if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
9667 	schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
9668 }
9669 
9670 static int
xmlSchemaParseSchemaElement(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)9671 xmlSchemaParseSchemaElement(xmlSchemaParserCtxtPtr ctxt,
9672 			     xmlSchemaPtr schema,
9673 			     xmlNodePtr node)
9674 {
9675     xmlAttrPtr attr;
9676     const xmlChar *val;
9677     int res = 0, oldErrs = ctxt->nberrors;
9678 
9679     /*
9680     * Those flags should be moved to the parser context flags,
9681     * since they are not visible at the component level. I.e.
9682     * they are used if processing schema *documents* only.
9683     */
9684     res = xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9685     HFAILURE;
9686 
9687     /*
9688     * Since the version is of type xs:token, we won't bother to
9689     * check it.
9690     */
9691     /* REMOVED:
9692     attr = xmlSchemaGetPropNode(node, "version");
9693     if (attr != NULL) {
9694 	res = xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
9695 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &val);
9696 	HFAILURE;
9697     }
9698     */
9699     attr = xmlSchemaGetPropNode(node, "targetNamespace");
9700     if (attr != NULL) {
9701 	res = xmlSchemaPValAttrNode(ctxt, NULL, attr,
9702 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
9703 	HFAILURE;
9704 	if (res != 0) {
9705 	    ctxt->stop = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
9706 	    goto exit;
9707 	}
9708     }
9709     attr = xmlSchemaGetPropNode(node, "elementFormDefault");
9710     if (attr != NULL) {
9711 	val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9712 	res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9713 	    XML_SCHEMAS_QUALIF_ELEM);
9714 	HFAILURE;
9715 	if (res != 0) {
9716 	    xmlSchemaPSimpleTypeErr(ctxt,
9717 		XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
9718 		NULL, (xmlNodePtr) attr, NULL,
9719 		"(qualified | unqualified)", val, NULL, NULL, NULL);
9720 	}
9721     }
9722     attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
9723     if (attr != NULL) {
9724 	val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9725 	res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9726 	    XML_SCHEMAS_QUALIF_ATTR);
9727 	HFAILURE;
9728 	if (res != 0) {
9729 	    xmlSchemaPSimpleTypeErr(ctxt,
9730 		XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
9731 		NULL, (xmlNodePtr) attr, NULL,
9732 		"(qualified | unqualified)", val, NULL, NULL, NULL);
9733 	}
9734     }
9735     attr = xmlSchemaGetPropNode(node, "finalDefault");
9736     if (attr != NULL) {
9737 	val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9738 	res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
9739 	    XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
9740 	    XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
9741 	    -1,
9742 	    XML_SCHEMAS_FINAL_DEFAULT_LIST,
9743 	    XML_SCHEMAS_FINAL_DEFAULT_UNION);
9744 	HFAILURE;
9745 	if (res != 0) {
9746 	    xmlSchemaPSimpleTypeErr(ctxt,
9747 		XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9748 		NULL, (xmlNodePtr) attr, NULL,
9749 		"(#all | List of (extension | restriction | list | union))",
9750 		val, NULL, NULL, NULL);
9751 	}
9752     }
9753     attr = xmlSchemaGetPropNode(node, "blockDefault");
9754     if (attr != NULL) {
9755 	val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9756 	res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
9757 	    XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
9758 	    XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
9759 	    XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1);
9760 	HFAILURE;
9761 	if (res != 0) {
9762 	    xmlSchemaPSimpleTypeErr(ctxt,
9763 		XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9764 		NULL, (xmlNodePtr) attr, NULL,
9765 		"(#all | List of (extension | restriction | substitution))",
9766 		val, NULL, NULL, NULL);
9767 	}
9768     }
9769 
9770 exit:
9771     if (oldErrs != ctxt->nberrors)
9772 	res = ctxt->err;
9773     return(res);
9774 exit_failure:
9775     return(-1);
9776 }
9777 
9778 /**
9779  * xmlSchemaParseSchemaTopLevel:
9780  * @ctxt:  a schema validation context
9781  * @schema:  the schemas
9782  * @nodes:  the list of top level nodes
9783  *
9784  * Returns the internal XML Schema structure built from the resource or
9785  *         NULL in case of error
9786  */
9787 static int
xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr nodes)9788 xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
9789                              xmlSchemaPtr schema, xmlNodePtr nodes)
9790 {
9791     xmlNodePtr child;
9792     xmlSchemaAnnotPtr annot;
9793     int res = 0, oldErrs, tmpOldErrs;
9794 
9795     if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
9796         return(-1);
9797 
9798     oldErrs = ctxt->nberrors;
9799     child = nodes;
9800     while ((IS_SCHEMA(child, "include")) ||
9801 	   (IS_SCHEMA(child, "import")) ||
9802 	   (IS_SCHEMA(child, "redefine")) ||
9803 	   (IS_SCHEMA(child, "annotation"))) {
9804 	if (IS_SCHEMA(child, "annotation")) {
9805 	    annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9806 	    if (schema->annot == NULL)
9807 		schema->annot = annot;
9808 	    else
9809 		xmlSchemaFreeAnnot(annot);
9810 	} else if (IS_SCHEMA(child, "import")) {
9811 	    tmpOldErrs = ctxt->nberrors;
9812 	    res = xmlSchemaParseImport(ctxt, schema, child);
9813 	    HFAILURE;
9814 	    HSTOP(ctxt);
9815 	    if (tmpOldErrs != ctxt->nberrors)
9816 		goto exit;
9817 	} else if (IS_SCHEMA(child, "include")) {
9818 	    tmpOldErrs = ctxt->nberrors;
9819 	    res = xmlSchemaParseInclude(ctxt, schema, child);
9820 	    HFAILURE;
9821 	    HSTOP(ctxt);
9822 	    if (tmpOldErrs != ctxt->nberrors)
9823 		goto exit;
9824 	} else if (IS_SCHEMA(child, "redefine")) {
9825 	    tmpOldErrs = ctxt->nberrors;
9826 	    res = xmlSchemaParseRedefine(ctxt, schema, child);
9827 	    HFAILURE;
9828 	    HSTOP(ctxt);
9829 	    if (tmpOldErrs != ctxt->nberrors)
9830 		goto exit;
9831 	}
9832 	child = child->next;
9833     }
9834     /*
9835     * URGENT TODO: Change the functions to return int results.
9836     * We need especially to catch internal errors.
9837     */
9838     while (child != NULL) {
9839 	if (IS_SCHEMA(child, "complexType")) {
9840 	    xmlSchemaParseComplexType(ctxt, schema, child, 1);
9841 	    child = child->next;
9842 	} else if (IS_SCHEMA(child, "simpleType")) {
9843 	    xmlSchemaParseSimpleType(ctxt, schema, child, 1);
9844 	    child = child->next;
9845 	} else if (IS_SCHEMA(child, "element")) {
9846 	    xmlSchemaParseElement(ctxt, schema, child, NULL, 1);
9847 	    child = child->next;
9848 	} else if (IS_SCHEMA(child, "attribute")) {
9849 	    xmlSchemaParseGlobalAttribute(ctxt, schema, child);
9850 	    child = child->next;
9851 	} else if (IS_SCHEMA(child, "attributeGroup")) {
9852 	    xmlSchemaParseAttributeGroupDefinition(ctxt, schema, child);
9853 	    child = child->next;
9854 	} else if (IS_SCHEMA(child, "group")) {
9855 	    xmlSchemaParseModelGroupDefinition(ctxt, schema, child);
9856 	    child = child->next;
9857 	} else if (IS_SCHEMA(child, "notation")) {
9858 	    xmlSchemaParseNotation(ctxt, schema, child);
9859 	    child = child->next;
9860 	} else {
9861 	    xmlSchemaPContentErr(ctxt,
9862 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9863 		NULL, child->parent, child,
9864 		NULL, "((include | import | redefine | annotation)*, "
9865 		"(((simpleType | complexType | group | attributeGroup) "
9866 		"| element | attribute | notation), annotation*)*)");
9867 	    child = child->next;
9868 	}
9869 	while (IS_SCHEMA(child, "annotation")) {
9870 	    /*
9871 	    * TODO: We should add all annotations.
9872 	    */
9873 	    annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9874 	    if (schema->annot == NULL)
9875 		schema->annot = annot;
9876 	    else
9877 		xmlSchemaFreeAnnot(annot);
9878 	    child = child->next;
9879 	}
9880     }
9881 exit:
9882     ctxt->ctxtType = NULL;
9883     if (oldErrs != ctxt->nberrors)
9884 	res = ctxt->err;
9885     return(res);
9886 exit_failure:
9887     return(-1);
9888 }
9889 
9890 static xmlSchemaSchemaRelationPtr
xmlSchemaSchemaRelationCreate(void)9891 xmlSchemaSchemaRelationCreate(void)
9892 {
9893     xmlSchemaSchemaRelationPtr ret;
9894 
9895     ret = (xmlSchemaSchemaRelationPtr)
9896 	xmlMalloc(sizeof(xmlSchemaSchemaRelation));
9897     if (ret == NULL) {
9898 	xmlSchemaPErrMemory(NULL, "allocating schema relation", NULL);
9899 	return(NULL);
9900     }
9901     memset(ret, 0, sizeof(xmlSchemaSchemaRelation));
9902     return(ret);
9903 }
9904 
9905 #if 0
9906 static void
9907 xmlSchemaSchemaRelationFree(xmlSchemaSchemaRelationPtr rel)
9908 {
9909     xmlFree(rel);
9910 }
9911 #endif
9912 
9913 static void
xmlSchemaRedefListFree(xmlSchemaRedefPtr redef)9914 xmlSchemaRedefListFree(xmlSchemaRedefPtr redef)
9915 {
9916     xmlSchemaRedefPtr prev;
9917 
9918     while (redef != NULL) {
9919 	prev = redef;
9920 	redef = redef->next;
9921 	xmlFree(prev);
9922     }
9923 }
9924 
9925 static void
xmlSchemaConstructionCtxtFree(xmlSchemaConstructionCtxtPtr con)9926 xmlSchemaConstructionCtxtFree(xmlSchemaConstructionCtxtPtr con)
9927 {
9928     /*
9929     * After the construction context has been freed, there will be
9930     * no schema graph available any more. Only the schema buckets
9931     * will stay alive, which are put into the "schemasImports" and
9932     * "includes" slots of the xmlSchema.
9933     */
9934     if (con->buckets != NULL)
9935 	xmlSchemaItemListFree(con->buckets);
9936     if (con->pending != NULL)
9937 	xmlSchemaItemListFree(con->pending);
9938     if (con->substGroups != NULL)
9939 	xmlHashFree(con->substGroups, xmlSchemaSubstGroupFreeEntry);
9940     if (con->redefs != NULL)
9941 	xmlSchemaRedefListFree(con->redefs);
9942     if (con->dict != NULL)
9943 	xmlDictFree(con->dict);
9944     xmlFree(con);
9945 }
9946 
9947 static xmlSchemaConstructionCtxtPtr
xmlSchemaConstructionCtxtCreate(xmlDictPtr dict)9948 xmlSchemaConstructionCtxtCreate(xmlDictPtr dict)
9949 {
9950     xmlSchemaConstructionCtxtPtr ret;
9951 
9952     ret = (xmlSchemaConstructionCtxtPtr)
9953 	xmlMalloc(sizeof(xmlSchemaConstructionCtxt));
9954     if (ret == NULL) {
9955         xmlSchemaPErrMemory(NULL,
9956 	    "allocating schema construction context", NULL);
9957         return (NULL);
9958     }
9959     memset(ret, 0, sizeof(xmlSchemaConstructionCtxt));
9960 
9961     ret->buckets = xmlSchemaItemListCreate();
9962     if (ret->buckets == NULL) {
9963 	xmlSchemaPErrMemory(NULL,
9964 	    "allocating list of schema buckets", NULL);
9965 	xmlFree(ret);
9966         return (NULL);
9967     }
9968     ret->pending = xmlSchemaItemListCreate();
9969     if (ret->pending == NULL) {
9970 	xmlSchemaPErrMemory(NULL,
9971 	    "allocating list of pending global components", NULL);
9972 	xmlSchemaConstructionCtxtFree(ret);
9973         return (NULL);
9974     }
9975     ret->dict = dict;
9976     xmlDictReference(dict);
9977     return(ret);
9978 }
9979 
9980 static xmlSchemaParserCtxtPtr
xmlSchemaParserCtxtCreate(void)9981 xmlSchemaParserCtxtCreate(void)
9982 {
9983     xmlSchemaParserCtxtPtr ret;
9984 
9985     ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9986     if (ret == NULL) {
9987         xmlSchemaPErrMemory(NULL, "allocating schema parser context",
9988                             NULL);
9989         return (NULL);
9990     }
9991     memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9992     ret->type = XML_SCHEMA_CTXT_PARSER;
9993     ret->attrProhibs = xmlSchemaItemListCreate();
9994     if (ret->attrProhibs == NULL) {
9995 	xmlFree(ret);
9996 	return(NULL);
9997     }
9998     return(ret);
9999 }
10000 
10001 /**
10002  * xmlSchemaNewParserCtxtUseDict:
10003  * @URL:  the location of the schema
10004  * @dict: the dictionary to be used
10005  *
10006  * Create an XML Schemas parse context for that file/resource expected
10007  * to contain an XML Schemas file.
10008  *
10009  * Returns the parser context or NULL in case of error
10010  */
10011 static xmlSchemaParserCtxtPtr
xmlSchemaNewParserCtxtUseDict(const char * URL,xmlDictPtr dict)10012 xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
10013 {
10014     xmlSchemaParserCtxtPtr ret;
10015 
10016     ret = xmlSchemaParserCtxtCreate();
10017     if (ret == NULL)
10018         return (NULL);
10019     ret->dict = dict;
10020     xmlDictReference(dict);
10021     if (URL != NULL)
10022 	ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
10023     return (ret);
10024 }
10025 
10026 static int
xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)10027 xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
10028 {
10029     if (vctxt->pctxt == NULL) {
10030         if (vctxt->schema != NULL)
10031 	    vctxt->pctxt =
10032 		xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
10033 	else
10034 	    vctxt->pctxt = xmlSchemaNewParserCtxt("*");
10035 	if (vctxt->pctxt == NULL) {
10036 	    VERROR_INT("xmlSchemaCreatePCtxtOnVCtxt",
10037 		"failed to create a temp. parser context");
10038 	    return (-1);
10039 	}
10040 	/* TODO: Pass user data. */
10041 	xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error,
10042 	    vctxt->warning, vctxt->errCtxt);
10043 	xmlSchemaSetParserStructuredErrors(vctxt->pctxt, vctxt->serror,
10044 	    vctxt->errCtxt);
10045     }
10046     return (0);
10047 }
10048 
10049 /**
10050  * xmlSchemaGetSchemaBucket:
10051  * @pctxt: the schema parser context
10052  * @schemaLocation: the URI of the schema document
10053  *
10054  * Returns a schema bucket if it was already parsed.
10055  *
10056  * Returns a schema bucket if it was already parsed from
10057  *         @schemaLocation, NULL otherwise.
10058  */
10059 static xmlSchemaBucketPtr
xmlSchemaGetSchemaBucket(xmlSchemaParserCtxtPtr pctxt,const xmlChar * schemaLocation)10060 xmlSchemaGetSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
10061 			    const xmlChar *schemaLocation)
10062 {
10063     xmlSchemaBucketPtr cur;
10064     xmlSchemaItemListPtr list;
10065 
10066     list = pctxt->constructor->buckets;
10067     if (list->nbItems == 0)
10068 	return(NULL);
10069     else {
10070 	int i;
10071 	for (i = 0; i < list->nbItems; i++) {
10072 	    cur = (xmlSchemaBucketPtr) list->items[i];
10073 	    /* Pointer comparison! */
10074 	    if (cur->schemaLocation == schemaLocation)
10075 		return(cur);
10076 	}
10077     }
10078     return(NULL);
10079 }
10080 
10081 static xmlSchemaBucketPtr
xmlSchemaGetChameleonSchemaBucket(xmlSchemaParserCtxtPtr pctxt,const xmlChar * schemaLocation,const xmlChar * targetNamespace)10082 xmlSchemaGetChameleonSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
10083 				     const xmlChar *schemaLocation,
10084 				     const xmlChar *targetNamespace)
10085 {
10086     xmlSchemaBucketPtr cur;
10087     xmlSchemaItemListPtr list;
10088 
10089     list = pctxt->constructor->buckets;
10090     if (list->nbItems == 0)
10091 	return(NULL);
10092     else {
10093 	int i;
10094 	for (i = 0; i < list->nbItems; i++) {
10095 	    cur = (xmlSchemaBucketPtr) list->items[i];
10096 	    /* Pointer comparison! */
10097 	    if ((cur->origTargetNamespace == NULL) &&
10098 		(cur->schemaLocation == schemaLocation) &&
10099 		(cur->targetNamespace == targetNamespace))
10100 		return(cur);
10101 	}
10102     }
10103     return(NULL);
10104 }
10105 
10106 
10107 #define IS_BAD_SCHEMA_DOC(b) \
10108     (((b)->doc == NULL) && ((b)->schemaLocation != NULL))
10109 
10110 static xmlSchemaBucketPtr
xmlSchemaGetSchemaBucketByTNS(xmlSchemaParserCtxtPtr pctxt,const xmlChar * targetNamespace,int imported)10111 xmlSchemaGetSchemaBucketByTNS(xmlSchemaParserCtxtPtr pctxt,
10112 				 const xmlChar *targetNamespace,
10113 				 int imported)
10114 {
10115     xmlSchemaBucketPtr cur;
10116     xmlSchemaItemListPtr list;
10117 
10118     list = pctxt->constructor->buckets;
10119     if (list->nbItems == 0)
10120 	return(NULL);
10121     else {
10122 	int i;
10123 	for (i = 0; i < list->nbItems; i++) {
10124 	    cur = (xmlSchemaBucketPtr) list->items[i];
10125 	    if ((! IS_BAD_SCHEMA_DOC(cur)) &&
10126 		(cur->origTargetNamespace == targetNamespace) &&
10127 		((imported && cur->imported) ||
10128 		 ((!imported) && (!cur->imported))))
10129 		return(cur);
10130 	}
10131     }
10132     return(NULL);
10133 }
10134 
10135 static int
xmlSchemaParseNewDocWithContext(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlSchemaBucketPtr bucket)10136 xmlSchemaParseNewDocWithContext(xmlSchemaParserCtxtPtr pctxt,
10137 		     xmlSchemaPtr schema,
10138 		     xmlSchemaBucketPtr bucket)
10139 {
10140     int oldFlags;
10141     xmlDocPtr oldDoc;
10142     xmlNodePtr node;
10143     int ret, oldErrs;
10144     xmlSchemaBucketPtr oldbucket = pctxt->constructor->bucket;
10145 
10146     /*
10147     * Save old values; reset the *main* schema.
10148     * URGENT TODO: This is not good; move the per-document information
10149     * to the parser. Get rid of passing the main schema to the
10150     * parsing functions.
10151     */
10152     oldFlags = schema->flags;
10153     oldDoc = schema->doc;
10154     if (schema->flags != 0)
10155 	xmlSchemaClearSchemaDefaults(schema);
10156     schema->doc = bucket->doc;
10157     pctxt->schema = schema;
10158     /*
10159     * Keep the current target namespace on the parser *not* on the
10160     * main schema.
10161     */
10162     pctxt->targetNamespace = bucket->targetNamespace;
10163     WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
10164 
10165     if ((bucket->targetNamespace != NULL) &&
10166 	xmlStrEqual(bucket->targetNamespace, xmlSchemaNs)) {
10167 	/*
10168 	* We are parsing the schema for schemas!
10169 	*/
10170 	pctxt->isS4S = 1;
10171     }
10172     /* Mark it as parsed, even if parsing fails. */
10173     bucket->parsed++;
10174     /* Compile the schema doc. */
10175     node = xmlDocGetRootElement(bucket->doc);
10176     ret = xmlSchemaParseSchemaElement(pctxt, schema, node);
10177     if (ret != 0)
10178 	goto exit;
10179     /* An empty schema; just get out. */
10180     if (node->children == NULL)
10181 	goto exit;
10182     oldErrs = pctxt->nberrors;
10183     ret = xmlSchemaParseSchemaTopLevel(pctxt, schema, node->children);
10184     if (ret != 0)
10185 	goto exit;
10186     /*
10187     * TODO: Not nice, but I'm not 100% sure we will get always an error
10188     * as a result of the obove functions; so better rely on pctxt->err
10189     * as well.
10190     */
10191     if ((ret == 0) && (oldErrs != pctxt->nberrors)) {
10192 	ret = pctxt->err;
10193 	goto exit;
10194     }
10195 
10196 exit:
10197     WXS_CONSTRUCTOR(pctxt)->bucket = oldbucket;
10198     /* Restore schema values. */
10199     schema->doc = oldDoc;
10200     schema->flags = oldFlags;
10201     return(ret);
10202 }
10203 
10204 static int
xmlSchemaParseNewDoc(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlSchemaBucketPtr bucket)10205 xmlSchemaParseNewDoc(xmlSchemaParserCtxtPtr pctxt,
10206 		     xmlSchemaPtr schema,
10207 		     xmlSchemaBucketPtr bucket)
10208 {
10209     xmlSchemaParserCtxtPtr newpctxt;
10210     int res = 0;
10211 
10212     if (bucket == NULL)
10213 	return(0);
10214     if (bucket->parsed) {
10215 	PERROR_INT("xmlSchemaParseNewDoc",
10216 	    "reparsing a schema doc");
10217 	return(-1);
10218     }
10219     if (bucket->doc == NULL) {
10220 	PERROR_INT("xmlSchemaParseNewDoc",
10221 	    "parsing a schema doc, but there's no doc");
10222 	return(-1);
10223     }
10224     if (pctxt->constructor == NULL) {
10225 	PERROR_INT("xmlSchemaParseNewDoc",
10226 	    "no constructor");
10227 	return(-1);
10228     }
10229     /* Create and init the temporary parser context. */
10230     newpctxt = xmlSchemaNewParserCtxtUseDict(
10231 	(const char *) bucket->schemaLocation, pctxt->dict);
10232     if (newpctxt == NULL)
10233 	return(-1);
10234     newpctxt->constructor = pctxt->constructor;
10235     /*
10236     * TODO: Can we avoid that the parser knows about the main schema?
10237     * It would be better if he knows about the current schema bucket
10238     * only.
10239     */
10240     newpctxt->schema = schema;
10241     xmlSchemaSetParserErrors(newpctxt, pctxt->error, pctxt->warning,
10242 	pctxt->errCtxt);
10243     xmlSchemaSetParserStructuredErrors(newpctxt, pctxt->serror,
10244 	pctxt->errCtxt);
10245     newpctxt->counter = pctxt->counter;
10246 
10247 
10248     res = xmlSchemaParseNewDocWithContext(newpctxt, schema, bucket);
10249 
10250     /* Channel back errors and cleanup the temporary parser context. */
10251     if (res != 0)
10252 	pctxt->err = res;
10253     pctxt->nberrors += newpctxt->nberrors;
10254     pctxt->counter = newpctxt->counter;
10255     newpctxt->constructor = NULL;
10256     /* Free the parser context. */
10257     xmlSchemaFreeParserCtxt(newpctxt);
10258     return(res);
10259 }
10260 
10261 static void
xmlSchemaSchemaRelationAddChild(xmlSchemaBucketPtr bucket,xmlSchemaSchemaRelationPtr rel)10262 xmlSchemaSchemaRelationAddChild(xmlSchemaBucketPtr bucket,
10263 				xmlSchemaSchemaRelationPtr rel)
10264 {
10265     xmlSchemaSchemaRelationPtr cur = bucket->relations;
10266 
10267     if (cur == NULL) {
10268 	bucket->relations = rel;
10269 	return;
10270     }
10271     while (cur->next != NULL)
10272 	cur = cur->next;
10273     cur->next = rel;
10274 }
10275 
10276 
10277 static const xmlChar *
xmlSchemaBuildAbsoluteURI(xmlDictPtr dict,const xmlChar * location,xmlNodePtr ctxtNode)10278 xmlSchemaBuildAbsoluteURI(xmlDictPtr dict, const xmlChar* location,
10279 			  xmlNodePtr ctxtNode)
10280 {
10281     /*
10282     * Build an absolue location URI.
10283     */
10284     if (location != NULL) {
10285 	if (ctxtNode == NULL)
10286 	    return(location);
10287 	else {
10288 	    xmlChar *base, *URI;
10289 	    const xmlChar *ret = NULL;
10290 
10291 	    base = xmlNodeGetBase(ctxtNode->doc, ctxtNode);
10292 	    if (base == NULL) {
10293 		URI = xmlBuildURI(location, ctxtNode->doc->URL);
10294 	    } else {
10295 		URI = xmlBuildURI(location, base);
10296 		xmlFree(base);
10297 	    }
10298 	    if (URI != NULL) {
10299 		ret = xmlDictLookup(dict, URI, -1);
10300 		xmlFree(URI);
10301 		return(ret);
10302 	    }
10303 	}
10304     }
10305     return(NULL);
10306 }
10307 
10308 
10309 
10310 /**
10311  * xmlSchemaAddSchemaDoc:
10312  * @pctxt:  a schema validation context
10313  * @schema:  the schema being built
10314  * @node:  a subtree containing XML Schema informations
10315  *
10316  * Parse an included (and to-be-redefined) XML schema document.
10317  *
10318  * Returns 0 on success, a positive error code on errors and
10319  *         -1 in case of an internal or API error.
10320  */
10321 
10322 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)10323 xmlSchemaAddSchemaDoc(xmlSchemaParserCtxtPtr pctxt,
10324 		int type, /* import or include or redefine */
10325 		const xmlChar *schemaLocation,
10326 		xmlDocPtr schemaDoc,
10327 		const char *schemaBuffer,
10328 		int schemaBufferLen,
10329 		xmlNodePtr invokingNode,
10330 		const xmlChar *sourceTargetNamespace,
10331 		const xmlChar *importNamespace,
10332 		xmlSchemaBucketPtr *bucket)
10333 {
10334     const xmlChar *targetNamespace = NULL;
10335     xmlSchemaSchemaRelationPtr relation = NULL;
10336     xmlDocPtr doc = NULL;
10337     int res = 0, err = 0, located = 0, preserveDoc = 0;
10338     xmlSchemaBucketPtr bkt = NULL;
10339 
10340     if (bucket != NULL)
10341 	*bucket = NULL;
10342 
10343     switch (type) {
10344 	case XML_SCHEMA_SCHEMA_IMPORT:
10345 	case XML_SCHEMA_SCHEMA_MAIN:
10346 	    err = XML_SCHEMAP_SRC_IMPORT;
10347 	    break;
10348 	case XML_SCHEMA_SCHEMA_INCLUDE:
10349 	    err = XML_SCHEMAP_SRC_INCLUDE;
10350 	    break;
10351 	case XML_SCHEMA_SCHEMA_REDEFINE:
10352 	    err = XML_SCHEMAP_SRC_REDEFINE;
10353 	    break;
10354     }
10355 
10356 
10357     /* Special handling for the main schema:
10358     * skip the location and relation logic and just parse the doc.
10359     * We need just a bucket to be returned in this case.
10360     */
10361     if ((type == XML_SCHEMA_SCHEMA_MAIN) || (! WXS_HAS_BUCKETS(pctxt)))
10362 	goto doc_load;
10363 
10364     /* Note that we expect the location to be an absulute URI. */
10365     if (schemaLocation != NULL) {
10366 	bkt = xmlSchemaGetSchemaBucket(pctxt, schemaLocation);
10367 	if ((bkt != NULL) &&
10368 	    (pctxt->constructor->bucket == bkt)) {
10369 	    /* Report self-imports/inclusions/redefinitions. */
10370 
10371 	    xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10372 		invokingNode, NULL,
10373 		"The schema must not import/include/redefine itself",
10374 		NULL, NULL);
10375 	    goto exit;
10376 	}
10377     }
10378     /*
10379     * Create a relation for the graph of schemas.
10380     */
10381     relation = xmlSchemaSchemaRelationCreate();
10382     if (relation == NULL)
10383 	return(-1);
10384     xmlSchemaSchemaRelationAddChild(pctxt->constructor->bucket,
10385 	relation);
10386     relation->type = type;
10387 
10388     /*
10389     * Save the namespace import information.
10390     */
10391     if (WXS_IS_BUCKET_IMPMAIN(type)) {
10392 	relation->importNamespace = importNamespace;
10393 	if (schemaLocation == NULL) {
10394 	    /*
10395 	    * No location; this is just an import of the namespace.
10396 	    * Note that we don't assign a bucket to the relation
10397 	    * in this case.
10398 	    */
10399 	    goto exit;
10400 	}
10401 	targetNamespace = importNamespace;
10402     }
10403 
10404     /* Did we already fetch the doc? */
10405     if (bkt != NULL) {
10406 	if ((WXS_IS_BUCKET_IMPMAIN(type)) && (! bkt->imported)) {
10407 	    /*
10408 	    * We included/redefined and then try to import a schema,
10409 	    * but the new location provided for import was different.
10410 	    */
10411 	    if (schemaLocation == NULL)
10412 		schemaLocation = BAD_CAST "in_memory_buffer";
10413 	    if (!xmlStrEqual(schemaLocation,
10414 		bkt->schemaLocation)) {
10415 		xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10416 		    invokingNode, NULL,
10417 		    "The schema document '%s' cannot be imported, since "
10418 		    "it was already included or redefined",
10419 		    schemaLocation, NULL);
10420 		goto exit;
10421 	    }
10422 	} else if ((! WXS_IS_BUCKET_IMPMAIN(type)) && (bkt->imported)) {
10423 	    /*
10424 	    * We imported and then try to include/redefine a schema,
10425 	    * but the new location provided for the include/redefine
10426 	    * was different.
10427 	    */
10428 	    if (schemaLocation == NULL)
10429 		schemaLocation = BAD_CAST "in_memory_buffer";
10430 	    if (!xmlStrEqual(schemaLocation,
10431 		bkt->schemaLocation)) {
10432 		xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10433 		    invokingNode, NULL,
10434 		    "The schema document '%s' cannot be included or "
10435 		    "redefined, since it was already imported",
10436 		    schemaLocation, NULL);
10437 		goto exit;
10438 	    }
10439 	}
10440     }
10441 
10442     if (WXS_IS_BUCKET_IMPMAIN(type)) {
10443 	/*
10444 	* Given that the schemaLocation [attribute] is only a hint, it is open
10445 	* to applications to ignore all but the first <import> for a given
10446 	* namespace, regardless of the `actual value` of schemaLocation, but
10447 	* such a strategy risks missing useful information when new
10448 	* schemaLocations are offered.
10449 	*
10450 	* We will use the first <import> that comes with a location.
10451 	* Further <import>s *with* a location, will result in an error.
10452 	* TODO: Better would be to just report a warning here, but
10453 	* we'll try it this way until someone complains.
10454 	*
10455 	* Schema Document Location Strategy:
10456 	* 3 Based on the namespace name, identify an existing schema document,
10457 	* either as a resource which is an XML document or a <schema> element
10458 	* information item, in some local schema repository;
10459 	* 5 Attempt to resolve the namespace name to locate such a resource.
10460 	*
10461 	* NOTE: (3) and (5) are not supported.
10462 	*/
10463 	if (bkt != NULL) {
10464 	    relation->bucket = bkt;
10465 	    goto exit;
10466 	}
10467 	bkt = xmlSchemaGetSchemaBucketByTNS(pctxt,
10468 	    importNamespace, 1);
10469 
10470 	if (bkt != NULL) {
10471 	    relation->bucket = bkt;
10472 	    if (bkt->schemaLocation == NULL) {
10473 		/* First given location of the schema; load the doc. */
10474 		bkt->schemaLocation = schemaLocation;
10475 	    } else {
10476 		if (!xmlStrEqual(schemaLocation,
10477 		    bkt->schemaLocation)) {
10478 		    /*
10479 		    * Additional location given; just skip it.
10480 		    * URGENT TODO: We should report a warning here.
10481 		    * res = XML_SCHEMAP_SRC_IMPORT;
10482 		    */
10483 		    if (schemaLocation == NULL)
10484 			schemaLocation = BAD_CAST "in_memory_buffer";
10485 
10486 		    xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10487 			XML_SCHEMAP_WARN_SKIP_SCHEMA,
10488 			invokingNode, NULL,
10489 			"Skipping import of schema located at '%s' for the "
10490 			"namespace '%s', since this namespace was already "
10491 			"imported with the schema located at '%s'",
10492 			schemaLocation, importNamespace, bkt->schemaLocation);
10493 		}
10494 		goto exit;
10495 	    }
10496 	}
10497 	/*
10498 	* No bucket + first location: load the doc and create a
10499 	* bucket.
10500 	*/
10501     } else {
10502 	/* <include> and <redefine> */
10503 	if (bkt != NULL) {
10504 
10505 	    if ((bkt->origTargetNamespace == NULL) &&
10506 		(bkt->targetNamespace != sourceTargetNamespace)) {
10507 		xmlSchemaBucketPtr chamel;
10508 
10509 		/*
10510 		* Chameleon include/redefine: skip loading only if it was
10511 		* aleady build for the targetNamespace of the including
10512 		* schema.
10513 		*/
10514 		/*
10515 		* URGENT TODO: If the schema is a chameleon-include then copy
10516 		* the components into the including schema and modify the
10517 		* targetNamespace of those components, do nothing otherwise.
10518 		* NOTE: This is currently worked-around by compiling the
10519 		* chameleon for every destinct including targetNamespace; thus
10520 		* not performant at the moment.
10521 		* TODO: Check when the namespace in wildcards for chameleons
10522 		* needs to be converted: before we built wildcard intersections
10523 		* or after.
10524 		*   Answer: after!
10525 		*/
10526 		chamel = xmlSchemaGetChameleonSchemaBucket(pctxt,
10527 		    schemaLocation, sourceTargetNamespace);
10528 		if (chamel != NULL) {
10529 		    /* A fitting chameleon was already parsed; NOP. */
10530 		    relation->bucket = chamel;
10531 		    goto exit;
10532 		}
10533 		/*
10534 		* We need to parse the chameleon again for a different
10535 		* targetNamespace.
10536 		* CHAMELEON TODO: Optimize this by only parsing the
10537 		* chameleon once, and then copying the components to
10538 		* the new targetNamespace.
10539 		*/
10540 		bkt = NULL;
10541 	    } else {
10542 		relation->bucket = bkt;
10543 		goto exit;
10544 	    }
10545 	}
10546     }
10547     if ((bkt != NULL) && (bkt->doc != NULL)) {
10548 	PERROR_INT("xmlSchemaAddSchemaDoc",
10549 	    "trying to load a schema doc, but a doc is already "
10550 	    "assigned to the schema bucket");
10551 	goto exit_failure;
10552     }
10553 
10554 doc_load:
10555     /*
10556     * Load the document.
10557     */
10558     if (schemaDoc != NULL) {
10559 	doc = schemaDoc;
10560 	/* Don' free this one, since it was provided by the caller. */
10561 	preserveDoc = 1;
10562 	/* TODO: Does the context or the doc hold the location? */
10563 	if (schemaDoc->URL != NULL)
10564 	    schemaLocation = xmlDictLookup(pctxt->dict,
10565 		schemaDoc->URL, -1);
10566         else
10567 	    schemaLocation = BAD_CAST "in_memory_buffer";
10568     } else if ((schemaLocation != NULL) || (schemaBuffer != NULL)) {
10569 	xmlParserCtxtPtr parserCtxt;
10570 
10571 	parserCtxt = xmlNewParserCtxt();
10572 	if (parserCtxt == NULL) {
10573 	    xmlSchemaPErrMemory(NULL, "xmlSchemaGetDoc, "
10574 		"allocating a parser context", NULL);
10575 	    goto exit_failure;
10576 	}
10577 	if ((pctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
10578 	    /*
10579 	    * TODO: Do we have to burden the schema parser dict with all
10580 	    * the content of the schema doc?
10581 	    */
10582 	    xmlDictFree(parserCtxt->dict);
10583 	    parserCtxt->dict = pctxt->dict;
10584 	    xmlDictReference(parserCtxt->dict);
10585 	}
10586 	if (schemaLocation != NULL) {
10587 	    /* Parse from file. */
10588 	    doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
10589 		NULL, SCHEMAS_PARSE_OPTIONS);
10590 	} else if (schemaBuffer != NULL) {
10591 	    /* Parse from memory buffer. */
10592 	    doc = xmlCtxtReadMemory(parserCtxt, schemaBuffer, schemaBufferLen,
10593 		NULL, NULL, SCHEMAS_PARSE_OPTIONS);
10594 	    schemaLocation = BAD_CAST "in_memory_buffer";
10595 	    if (doc != NULL)
10596 		doc->URL = xmlStrdup(schemaLocation);
10597 	}
10598 	/*
10599 	* For <import>:
10600 	* 2.1 The referent is (a fragment of) a resource which is an
10601 	* XML document (see clause 1.1), which in turn corresponds to
10602 	* a <schema> element information item in a well-formed information
10603 	* set, which in turn corresponds to a valid schema.
10604 	* TODO: (2.1) fragments of XML documents are not supported.
10605 	*
10606 	* 2.2 The referent is a <schema> element information item in
10607 	* a well-formed information set, which in turn corresponds
10608 	* to a valid schema.
10609 	* TODO: (2.2) is not supported.
10610 	*/
10611 	if (doc == NULL) {
10612 	    xmlErrorPtr lerr;
10613 	    lerr = xmlGetLastError();
10614 	    /*
10615 	    * Check if this a parser error, or if the document could
10616 	    * just not be located.
10617 	    * TODO: Try to find specific error codes to react only on
10618 	    * localisation failures.
10619 	    */
10620 	    if ((lerr == NULL) || (lerr->domain != XML_FROM_IO)) {
10621 		/*
10622 		* We assume a parser error here.
10623 		*/
10624 		located = 1;
10625 		/* TODO: Error code ?? */
10626 		res = XML_SCHEMAP_SRC_IMPORT_2_1;
10627 		xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10628 		    invokingNode, NULL,
10629 		    "Failed to parse the XML resource '%s'",
10630 		    schemaLocation, NULL);
10631 	    }
10632 	}
10633 	xmlFreeParserCtxt(parserCtxt);
10634 	if ((doc == NULL) && located)
10635 	    goto exit_error;
10636     } else {
10637 	xmlSchemaPErr(pctxt, NULL,
10638 	    XML_SCHEMAP_NOTHING_TO_PARSE,
10639 	    "No information for parsing was provided with the "
10640 	    "given schema parser context.\n",
10641 	    NULL, NULL);
10642 	goto exit_failure;
10643     }
10644     /*
10645     * Preprocess the document.
10646     */
10647     if (doc != NULL) {
10648 	xmlNodePtr docElem = NULL;
10649 
10650 	located = 1;
10651 	docElem = xmlDocGetRootElement(doc);
10652 	if (docElem == NULL) {
10653 	    xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOROOT,
10654 		invokingNode, NULL,
10655 		"The document '%s' has no document element",
10656 		schemaLocation, NULL);
10657 	    goto exit_error;
10658 	}
10659 	/*
10660 	* Remove all the blank text nodes.
10661 	*/
10662 	xmlSchemaCleanupDoc(pctxt, docElem);
10663 	/*
10664 	* Check the schema's top level element.
10665 	*/
10666 	if (!IS_SCHEMA(docElem, "schema")) {
10667 	    xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOT_SCHEMA,
10668 		invokingNode, NULL,
10669 		"The XML document '%s' is not a schema document",
10670 		schemaLocation, NULL);
10671 	    goto exit_error;
10672 	}
10673 	/*
10674 	* Note that we don't apply a type check for the
10675 	* targetNamespace value here.
10676 	*/
10677 	targetNamespace = xmlSchemaGetProp(pctxt, docElem,
10678 	    "targetNamespace");
10679     }
10680 
10681 /* after_doc_loading: */
10682     if ((bkt == NULL) && located) {
10683 	/* Only create a bucket if the schema was located. */
10684         bkt = xmlSchemaBucketCreate(pctxt, type,
10685 	    targetNamespace);
10686 	if (bkt == NULL)
10687 	    goto exit_failure;
10688     }
10689     if (bkt != NULL) {
10690 	bkt->schemaLocation = schemaLocation;
10691 	bkt->located = located;
10692 	if (doc != NULL) {
10693 	    bkt->doc = doc;
10694 	    bkt->targetNamespace = targetNamespace;
10695 	    bkt->origTargetNamespace = targetNamespace;
10696 	    if (preserveDoc)
10697 		bkt->preserveDoc = 1;
10698 	}
10699 	if (WXS_IS_BUCKET_IMPMAIN(type))
10700 	    bkt->imported++;
10701 	    /*
10702 	    * Add it to the graph of schemas.
10703 	    */
10704 	if (relation != NULL)
10705 	    relation->bucket = bkt;
10706     }
10707 
10708 exit:
10709     /*
10710     * Return the bucket explicitely; this is needed for the
10711     * main schema.
10712     */
10713     if (bucket != NULL)
10714 	*bucket = bkt;
10715     return (0);
10716 
10717 exit_error:
10718     if ((doc != NULL) && (! preserveDoc)) {
10719 	xmlFreeDoc(doc);
10720 	if (bkt != NULL)
10721 	    bkt->doc = NULL;
10722     }
10723     return(pctxt->err);
10724 
10725 exit_failure:
10726     if ((doc != NULL) && (! preserveDoc)) {
10727 	xmlFreeDoc(doc);
10728 	if (bkt != NULL)
10729 	    bkt->doc = NULL;
10730     }
10731     return (-1);
10732 }
10733 
10734 /**
10735  * xmlSchemaParseImport:
10736  * @ctxt:  a schema validation context
10737  * @schema:  the schema being built
10738  * @node:  a subtree containing XML Schema informations
10739  *
10740  * parse a XML schema Import definition
10741  * *WARNING* this interface is highly subject to change
10742  *
10743  * Returns 0 in case of success, a positive error code if
10744  * not valid and -1 in case of an internal error.
10745  */
10746 static int
xmlSchemaParseImport(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node)10747 xmlSchemaParseImport(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
10748                      xmlNodePtr node)
10749 {
10750     xmlNodePtr child;
10751     const xmlChar *namespaceName = NULL, *schemaLocation = NULL;
10752     const xmlChar *thisTargetNamespace;
10753     xmlAttrPtr attr;
10754     int ret = 0;
10755     xmlSchemaBucketPtr bucket = NULL;
10756 
10757     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
10758         return (-1);
10759 
10760     /*
10761     * Check for illegal attributes.
10762     */
10763     attr = node->properties;
10764     while (attr != NULL) {
10765 	if (attr->ns == NULL) {
10766 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10767 		(!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
10768 		(!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
10769 		xmlSchemaPIllegalAttrErr(pctxt,
10770 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10771 	    }
10772 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10773 	    xmlSchemaPIllegalAttrErr(pctxt,
10774 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10775 	}
10776 	attr = attr->next;
10777     }
10778     /*
10779     * Extract and validate attributes.
10780     */
10781     if (xmlSchemaPValAttr(pctxt, NULL, node,
10782 	"namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10783 	&namespaceName) != 0) {
10784 	xmlSchemaPSimpleTypeErr(pctxt,
10785 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
10786 	    NULL, node,
10787 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10788 	    NULL, namespaceName, NULL, NULL, NULL);
10789 	return (pctxt->err);
10790     }
10791 
10792     if (xmlSchemaPValAttr(pctxt, NULL, node,
10793 	"schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10794 	&schemaLocation) != 0) {
10795 	xmlSchemaPSimpleTypeErr(pctxt,
10796 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
10797 	    NULL, node,
10798 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10799 	    NULL, schemaLocation, NULL, NULL, NULL);
10800 	return (pctxt->err);
10801     }
10802     /*
10803     * And now for the children...
10804     */
10805     child = node->children;
10806     if (IS_SCHEMA(child, "annotation")) {
10807         /*
10808          * the annotation here is simply discarded ...
10809 	 * TODO: really?
10810          */
10811         child = child->next;
10812     }
10813     if (child != NULL) {
10814 	xmlSchemaPContentErr(pctxt,
10815 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10816 	    NULL, node, child, NULL,
10817 	    "(annotation?)");
10818     }
10819     /*
10820     * Apply additional constraints.
10821     *
10822     * Note that it is important to use the original @targetNamespace
10823     * (or none at all), to rule out imports of schemas _with_ a
10824     * @targetNamespace if the importing schema is a chameleon schema
10825     * (with no @targetNamespace).
10826     */
10827     thisTargetNamespace = WXS_BUCKET(pctxt)->origTargetNamespace;
10828     if (namespaceName != NULL) {
10829 	/*
10830 	* 1.1 If the namespace [attribute] is present, then its `actual value`
10831 	* must not match the `actual value` of the enclosing <schema>'s
10832 	* targetNamespace [attribute].
10833 	*/
10834 	if (xmlStrEqual(thisTargetNamespace, namespaceName)) {
10835 	    xmlSchemaPCustomErr(pctxt,
10836 		XML_SCHEMAP_SRC_IMPORT_1_1,
10837 		NULL, node,
10838 		"The value of the attribute 'namespace' must not match "
10839 		"the target namespace '%s' of the importing schema",
10840 		thisTargetNamespace);
10841 	    return (pctxt->err);
10842 	}
10843     } else {
10844 	/*
10845 	* 1.2 If the namespace [attribute] is not present, then the enclosing
10846 	* <schema> must have a targetNamespace [attribute].
10847 	*/
10848 	if (thisTargetNamespace == NULL) {
10849 	    xmlSchemaPCustomErr(pctxt,
10850 		XML_SCHEMAP_SRC_IMPORT_1_2,
10851 		NULL, node,
10852 		"The attribute 'namespace' must be existent if "
10853 		"the importing schema has no target namespace",
10854 		NULL);
10855 	    return (pctxt->err);
10856 	}
10857     }
10858     /*
10859     * Locate and acquire the schema document.
10860     */
10861     if (schemaLocation != NULL)
10862 	schemaLocation = xmlSchemaBuildAbsoluteURI(pctxt->dict,
10863 	    schemaLocation, node);
10864     ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
10865 	schemaLocation, NULL, NULL, 0, node, thisTargetNamespace,
10866 	namespaceName, &bucket);
10867 
10868     if (ret != 0)
10869 	return(ret);
10870 
10871     /*
10872     * For <import>: "It is *not* an error for the application
10873     * schema reference strategy to fail."
10874     * So just don't parse if no schema document was found.
10875     * Note that we will get no bucket if the schema could not be
10876     * located or if there was no schemaLocation.
10877     */
10878     if ((bucket == NULL) && (schemaLocation != NULL)) {
10879 	xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10880 	    XML_SCHEMAP_WARN_UNLOCATED_SCHEMA,
10881 	    node, NULL,
10882 	    "Failed to locate a schema at location '%s'. "
10883 	    "Skipping the import", schemaLocation, NULL, NULL);
10884     }
10885 
10886     if ((bucket != NULL) && CAN_PARSE_SCHEMA(bucket)) {
10887 	ret = xmlSchemaParseNewDoc(pctxt, schema, bucket);
10888     }
10889 
10890     return (ret);
10891 }
10892 
10893 static int
xmlSchemaParseIncludeOrRedefineAttrs(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node,xmlChar ** schemaLocation,int type)10894 xmlSchemaParseIncludeOrRedefineAttrs(xmlSchemaParserCtxtPtr pctxt,
10895 				     xmlSchemaPtr schema,
10896 				     xmlNodePtr node,
10897 				     xmlChar **schemaLocation,
10898 				     int type)
10899 {
10900     xmlAttrPtr attr;
10901 
10902     if ((pctxt == NULL) || (schema == NULL) || (node == NULL) ||
10903 	(schemaLocation == NULL))
10904         return (-1);
10905 
10906     *schemaLocation = NULL;
10907     /*
10908     * Check for illegal attributes.
10909     * Applies for both <include> and <redefine>.
10910     */
10911     attr = node->properties;
10912     while (attr != NULL) {
10913 	if (attr->ns == NULL) {
10914 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10915 		(!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
10916 		xmlSchemaPIllegalAttrErr(pctxt,
10917 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10918 	    }
10919 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10920 	    xmlSchemaPIllegalAttrErr(pctxt,
10921 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10922 	}
10923 	attr = attr->next;
10924     }
10925     xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
10926     /*
10927     * Preliminary step, extract the URI-Reference and make an URI
10928     * from the base.
10929     */
10930     /*
10931     * Attribute "schemaLocation" is mandatory.
10932     */
10933     attr = xmlSchemaGetPropNode(node, "schemaLocation");
10934     if (attr != NULL) {
10935         xmlChar *base = NULL;
10936         xmlChar *uri = NULL;
10937 
10938 	if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
10939 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10940 	    (const xmlChar **) schemaLocation) != 0)
10941 	    goto exit_error;
10942 	base = xmlNodeGetBase(node->doc, node);
10943 	if (base == NULL) {
10944 	    uri = xmlBuildURI(*schemaLocation, node->doc->URL);
10945 	} else {
10946 	    uri = xmlBuildURI(*schemaLocation, base);
10947 	    xmlFree(base);
10948 	}
10949 	if (uri == NULL) {
10950 	    PERROR_INT("xmlSchemaParseIncludeOrRedefine",
10951 		"could not build an URI from the schemaLocation")
10952 	    goto exit_failure;
10953 	}
10954 	(*schemaLocation) = (xmlChar *) xmlDictLookup(pctxt->dict, uri, -1);
10955 	xmlFree(uri);
10956     } else {
10957 	xmlSchemaPMissingAttrErr(pctxt,
10958 	    XML_SCHEMAP_S4S_ATTR_MISSING,
10959 	    NULL, node, "schemaLocation", NULL);
10960 	goto exit_error;
10961     }
10962     /*
10963     * Report self-inclusion and self-redefinition.
10964     */
10965     if (xmlStrEqual(*schemaLocation, pctxt->URL)) {
10966 	if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
10967 	    xmlSchemaPCustomErr(pctxt,
10968 		XML_SCHEMAP_SRC_REDEFINE,
10969 		NULL, node,
10970 		"The schema document '%s' cannot redefine itself.",
10971 		*schemaLocation);
10972 	} else {
10973 	    xmlSchemaPCustomErr(pctxt,
10974 		XML_SCHEMAP_SRC_INCLUDE,
10975 		NULL, node,
10976 		"The schema document '%s' cannot include itself.",
10977 		*schemaLocation);
10978 	}
10979 	goto exit_error;
10980     }
10981 
10982     return(0);
10983 exit_error:
10984     return(pctxt->err);
10985 exit_failure:
10986     return(-1);
10987 }
10988 
10989 static int
xmlSchemaParseIncludeOrRedefine(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node,int type)10990 xmlSchemaParseIncludeOrRedefine(xmlSchemaParserCtxtPtr pctxt,
10991 				xmlSchemaPtr schema,
10992 				xmlNodePtr node,
10993 				int type)
10994 {
10995     xmlNodePtr child = NULL;
10996     const xmlChar *schemaLocation = NULL;
10997     int res = 0; /* hasRedefinitions = 0 */
10998     int isChameleon = 0, wasChameleon = 0;
10999     xmlSchemaBucketPtr bucket = NULL;
11000 
11001     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
11002         return (-1);
11003 
11004     /*
11005     * Parse attributes. Note that the returned schemaLocation will
11006     * be already converted to an absolute URI.
11007     */
11008     res = xmlSchemaParseIncludeOrRedefineAttrs(pctxt, schema,
11009 	node, (xmlChar **) (&schemaLocation), type);
11010     if (res != 0)
11011 	return(res);
11012     /*
11013     * Load and add the schema document.
11014     */
11015     res = xmlSchemaAddSchemaDoc(pctxt, type, schemaLocation, NULL,
11016 	NULL, 0, node, pctxt->targetNamespace, NULL, &bucket);
11017     if (res != 0)
11018 	return(res);
11019     /*
11020     * If we get no schema bucket back, then this means that the schema
11021     * document could not be located or was broken XML or was not
11022     * a schema document.
11023     */
11024     if ((bucket == NULL) || (bucket->doc == NULL)) {
11025 	if (type == XML_SCHEMA_SCHEMA_INCLUDE) {
11026 	    /*
11027 	    * WARNING for <include>:
11028 	    * We will raise an error if the schema cannot be located
11029 	    * for inclusions, since the that was the feedback from the
11030 	    * schema people. I.e. the following spec piece will *not* be
11031 	    * satisfied:
11032 	    * SPEC src-include: "It is not an error for the `actual value` of the
11033 	    * schemaLocation [attribute] to fail to resolve it all, in which
11034 	    * case no corresponding inclusion is performed.
11035 	    * So do we need a warning report here?"
11036 	    */
11037 	    res = XML_SCHEMAP_SRC_INCLUDE;
11038 	    xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
11039 		node, NULL,
11040 		"Failed to load the document '%s' for inclusion",
11041 		schemaLocation, NULL);
11042 	} else {
11043 	    /*
11044 	    * NOTE: This was changed to raise an error even if no redefinitions
11045 	    * are specified.
11046 	    *
11047 	    * SPEC src-redefine (1)
11048 	    * "If there are any element information items among the [children]
11049 	    * other than <annotation> then the `actual value` of the
11050 	    * schemaLocation [attribute] must successfully resolve."
11051 	    * TODO: Ask the WG if a the location has always to resolve
11052 	    * here as well!
11053 	    */
11054 	    res = XML_SCHEMAP_SRC_REDEFINE;
11055 	    xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
11056 		node, NULL,
11057 		"Failed to load the document '%s' for redefinition",
11058 		schemaLocation, NULL);
11059 	}
11060     } else {
11061 	/*
11062 	* Check targetNamespace sanity before parsing the new schema.
11063 	* TODO: Note that we won't check further content if the
11064 	* targetNamespace was bad.
11065 	*/
11066 	if (bucket->origTargetNamespace != NULL) {
11067 	    /*
11068 	    * SPEC src-include (2.1)
11069 	    * "SII has a targetNamespace [attribute], and its `actual
11070 	    * value` is identical to the `actual value` of the targetNamespace
11071 	    * [attribute] of SII' (which must have such an [attribute])."
11072 	    */
11073 	    if (pctxt->targetNamespace == NULL) {
11074 		xmlSchemaCustomErr(ACTXT_CAST pctxt,
11075 		    XML_SCHEMAP_SRC_INCLUDE,
11076 		    node, NULL,
11077 		    "The target namespace of the included/redefined schema "
11078 		    "'%s' has to be absent, since the including/redefining "
11079 		    "schema has no target namespace",
11080 		    schemaLocation, NULL);
11081 		goto exit_error;
11082 	    } else if (!xmlStrEqual(bucket->origTargetNamespace,
11083 		pctxt->targetNamespace)) {
11084 		/* TODO: Change error function. */
11085 		xmlSchemaPCustomErrExt(pctxt,
11086 		    XML_SCHEMAP_SRC_INCLUDE,
11087 		    NULL, node,
11088 		    "The target namespace '%s' of the included/redefined "
11089 		    "schema '%s' differs from '%s' of the "
11090 		    "including/redefining schema",
11091 		    bucket->origTargetNamespace, schemaLocation,
11092 		    pctxt->targetNamespace);
11093 		goto exit_error;
11094 	    }
11095 	} else if (pctxt->targetNamespace != NULL) {
11096 	    /*
11097 	    * Chameleons: the original target namespace will
11098 	    * differ from the resulting namespace.
11099 	    */
11100 	    isChameleon = 1;
11101 	    if (bucket->parsed &&
11102 		bucket->origTargetNamespace != NULL) {
11103 		xmlSchemaCustomErr(ACTXT_CAST pctxt,
11104 		    XML_SCHEMAP_SRC_INCLUDE,
11105 		    node, NULL,
11106 		    "The target namespace of the included/redefined schema "
11107 		    "'%s' has to be absent or the same as the "
11108 		    "including/redefining schema's target namespace",
11109 		    schemaLocation, NULL);
11110 		goto exit_error;
11111 	    }
11112 	    bucket->targetNamespace = pctxt->targetNamespace;
11113 	}
11114     }
11115     /*
11116     * Parse the schema.
11117     */
11118     if (bucket && (!bucket->parsed) && (bucket->doc != NULL)) {
11119 	if (isChameleon) {
11120 	    /* TODO: Get rid of this flag on the schema itself. */
11121 	    if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
11122 		schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11123 	    } else
11124 		wasChameleon = 1;
11125 	}
11126 	xmlSchemaParseNewDoc(pctxt, schema, bucket);
11127 	/* Restore chameleon flag. */
11128 	if (isChameleon && (!wasChameleon))
11129 	    schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11130     }
11131     /*
11132     * And now for the children...
11133     */
11134     child = node->children;
11135     if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
11136 	/*
11137 	* Parse (simpleType | complexType | group | attributeGroup))*
11138 	*/
11139 	pctxt->redefined = bucket;
11140 	/*
11141 	* How to proceed if the redefined schema was not located?
11142 	*/
11143 	pctxt->isRedefine = 1;
11144 	while (IS_SCHEMA(child, "annotation") ||
11145 	    IS_SCHEMA(child, "simpleType") ||
11146 	    IS_SCHEMA(child, "complexType") ||
11147 	    IS_SCHEMA(child, "group") ||
11148 	    IS_SCHEMA(child, "attributeGroup")) {
11149 	    if (IS_SCHEMA(child, "annotation")) {
11150 		/*
11151 		* TODO: discard or not?
11152 		*/
11153 	    } else if (IS_SCHEMA(child, "simpleType")) {
11154 		xmlSchemaParseSimpleType(pctxt, schema, child, 1);
11155 	    } else if (IS_SCHEMA(child, "complexType")) {
11156 		xmlSchemaParseComplexType(pctxt, schema, child, 1);
11157 		/* hasRedefinitions = 1; */
11158 	    } else if (IS_SCHEMA(child, "group")) {
11159 		/* hasRedefinitions = 1; */
11160 		xmlSchemaParseModelGroupDefinition(pctxt,
11161 		    schema, child);
11162 	    } else if (IS_SCHEMA(child, "attributeGroup")) {
11163 		/* hasRedefinitions = 1; */
11164 		xmlSchemaParseAttributeGroupDefinition(pctxt, schema,
11165 		    child);
11166 	    }
11167 	    child = child->next;
11168 	}
11169 	pctxt->redefined = NULL;
11170 	pctxt->isRedefine = 0;
11171     } else {
11172 	if (IS_SCHEMA(child, "annotation")) {
11173 	    /*
11174 	    * TODO: discard or not?
11175 	    */
11176 	    child = child->next;
11177 	}
11178     }
11179     if (child != NULL) {
11180 	res = XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED;
11181 	if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
11182 	    xmlSchemaPContentErr(pctxt, res,
11183 		NULL, node, child, NULL,
11184 		"(annotation | (simpleType | complexType | group | attributeGroup))*");
11185 	} else {
11186 	     xmlSchemaPContentErr(pctxt, res,
11187 		NULL, node, child, NULL,
11188 		"(annotation?)");
11189 	}
11190     }
11191     return(res);
11192 
11193 exit_error:
11194     return(pctxt->err);
11195 }
11196 
11197 static int
xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node)11198 xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11199                        xmlNodePtr node)
11200 {
11201     int res;
11202 #ifndef ENABLE_REDEFINE
11203     TODO
11204     return(0);
11205 #endif
11206     res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11207 	XML_SCHEMA_SCHEMA_REDEFINE);
11208     if (res != 0)
11209 	return(res);
11210     return(0);
11211 }
11212 
11213 static int
xmlSchemaParseInclude(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node)11214 xmlSchemaParseInclude(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11215                        xmlNodePtr node)
11216 {
11217     int res;
11218 
11219     res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11220 	XML_SCHEMA_SCHEMA_INCLUDE);
11221     if (res != 0)
11222 	return(res);
11223     return(0);
11224 }
11225 
11226 /**
11227  * xmlSchemaParseModelGroup:
11228  * @ctxt:  a schema validation context
11229  * @schema:  the schema being built
11230  * @node:  a subtree containing XML Schema informations
11231  * @type: the "compositor" type
11232  * @particleNeeded: if a a model group with a particle
11233  *
11234  * parse a XML schema Sequence definition.
11235  * Applies parts of:
11236  *   Schema Representation Constraint:
11237  *     Redefinition Constraints and Semantics (src-redefine)
11238  *     (6.1), (6.1.1), (6.1.2)
11239  *
11240  *   Schema Component Constraint:
11241  *     All Group Limited (cos-all-limited) (2)
11242  *     TODO: Actually this should go to component-level checks,
11243  *     but is done here due to performance. Move it to an other layer
11244  *     is schema construction via an API is implemented.
11245  *
11246  * *WARNING* this interface is highly subject to change
11247  *
11248  * Returns -1 in case of error, 0 if the declaration is improper and
11249  *         1 in case of success.
11250  */
11251 static xmlSchemaTreeItemPtr
xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,xmlSchemaTypeType type,int withParticle)11252 xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11253 			 xmlNodePtr node, xmlSchemaTypeType type,
11254 			 int withParticle)
11255 {
11256     xmlSchemaModelGroupPtr item;
11257     xmlSchemaParticlePtr particle = NULL;
11258     xmlNodePtr child = NULL;
11259     xmlAttrPtr attr;
11260     int min = 1, max = 1, isElemRef, hasRefs = 0;
11261 
11262     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11263         return (NULL);
11264     /*
11265     * Create a model group with the given compositor.
11266     */
11267     item = xmlSchemaAddModelGroup(ctxt, schema, type, node);
11268     if (item == NULL)
11269 	return (NULL);
11270 
11271     if (withParticle) {
11272 	if (type == XML_SCHEMA_TYPE_ALL) {
11273 	    min = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
11274 	    max = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
11275 	} else {
11276 	    /* choice + sequence */
11277 	    min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
11278 	    max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
11279 		"(xs:nonNegativeInteger | unbounded)");
11280 	}
11281 	xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
11282 	/*
11283 	* Create a particle
11284 	*/
11285 	particle = xmlSchemaAddParticle(ctxt, node, min, max);
11286 	if (particle == NULL)
11287 	    return (NULL);
11288 	particle->children = (xmlSchemaTreeItemPtr) item;
11289 	/*
11290 	* Check for illegal attributes.
11291 	*/
11292 	attr = node->properties;
11293 	while (attr != NULL) {
11294 	    if (attr->ns == NULL) {
11295 		if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11296 		    (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
11297 		    (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
11298 		    xmlSchemaPIllegalAttrErr(ctxt,
11299 			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11300 		}
11301 	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11302 		xmlSchemaPIllegalAttrErr(ctxt,
11303 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11304 	    }
11305 	    attr = attr->next;
11306 	}
11307     } else {
11308 	/*
11309 	* Check for illegal attributes.
11310 	*/
11311 	attr = node->properties;
11312 	while (attr != NULL) {
11313 	    if (attr->ns == NULL) {
11314 		if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
11315 		    xmlSchemaPIllegalAttrErr(ctxt,
11316 			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11317 		}
11318 	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11319 		xmlSchemaPIllegalAttrErr(ctxt,
11320 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11321 	    }
11322 	    attr = attr->next;
11323 	}
11324     }
11325 
11326     /*
11327     * Extract and validate attributes.
11328     */
11329     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11330     /*
11331     * And now for the children...
11332     */
11333     child = node->children;
11334     if (IS_SCHEMA(child, "annotation")) {
11335         item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
11336         child = child->next;
11337     }
11338     if (type == XML_SCHEMA_TYPE_ALL) {
11339 	xmlSchemaParticlePtr part, last = NULL;
11340 
11341 	while (IS_SCHEMA(child, "element")) {
11342 	    part = (xmlSchemaParticlePtr) xmlSchemaParseElement(ctxt,
11343 		schema, child, &isElemRef, 0);
11344 	    /*
11345 	    * SPEC cos-all-limited (2)
11346 	    * "The {max occurs} of all the particles in the {particles}
11347 	    * of the ('all') group must be 0 or 1.
11348 	    */
11349 	    if (part != NULL) {
11350 		if (isElemRef)
11351 		    hasRefs++;
11352 		if (part->minOccurs > 1) {
11353 		    xmlSchemaPCustomErr(ctxt,
11354 			XML_SCHEMAP_COS_ALL_LIMITED,
11355 			NULL, child,
11356 			"Invalid value for minOccurs (must be 0 or 1)",
11357 			NULL);
11358 		    /* Reset to 1. */
11359 		    part->minOccurs = 1;
11360 		}
11361 		if (part->maxOccurs > 1) {
11362 		    xmlSchemaPCustomErr(ctxt,
11363 			XML_SCHEMAP_COS_ALL_LIMITED,
11364 			NULL, child,
11365 			"Invalid value for maxOccurs (must be 0 or 1)",
11366 			NULL);
11367 		    /* Reset to 1. */
11368 		    part->maxOccurs = 1;
11369 		}
11370 		if (last == NULL)
11371 		    item->children = (xmlSchemaTreeItemPtr) part;
11372 		else
11373 		    last->next = (xmlSchemaTreeItemPtr) part;
11374 		last = part;
11375 	    }
11376 	    child = child->next;
11377 	}
11378 	if (child != NULL) {
11379 	    xmlSchemaPContentErr(ctxt,
11380 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11381 		NULL, node, child, NULL,
11382 		"(annotation?, (annotation?, element*)");
11383 	}
11384     } else {
11385 	/* choice + sequence */
11386 	xmlSchemaTreeItemPtr part = NULL, last = NULL;
11387 
11388 	while ((IS_SCHEMA(child, "element")) ||
11389 	    (IS_SCHEMA(child, "group")) ||
11390 	    (IS_SCHEMA(child, "any")) ||
11391 	    (IS_SCHEMA(child, "choice")) ||
11392 	    (IS_SCHEMA(child, "sequence"))) {
11393 
11394 	    if (IS_SCHEMA(child, "element")) {
11395 		part = (xmlSchemaTreeItemPtr)
11396 		    xmlSchemaParseElement(ctxt, schema, child, &isElemRef, 0);
11397 		if (part && isElemRef)
11398 		    hasRefs++;
11399 	    } else if (IS_SCHEMA(child, "group")) {
11400 		part =
11401 		    xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11402 		if (part != NULL)
11403 		    hasRefs++;
11404 		/*
11405 		* Handle redefinitions.
11406 		*/
11407 		if (ctxt->isRedefine && ctxt->redef &&
11408 		    (ctxt->redef->item->type == XML_SCHEMA_TYPE_GROUP) &&
11409 		    part && part->children)
11410 		{
11411 		    if ((xmlSchemaGetQNameRefName(part->children) ==
11412 			    ctxt->redef->refName) &&
11413 			(xmlSchemaGetQNameRefTargetNs(part->children) ==
11414 			    ctxt->redef->refTargetNs))
11415 		    {
11416 			/*
11417 			* SPEC src-redefine:
11418 			* (6.1) "If it has a <group> among its contents at
11419 			* some level the `actual value` of whose ref
11420 			* [attribute] is the same as the `actual value` of
11421 			* its own name attribute plus target namespace, then
11422 			* all of the following must be true:"
11423 			* (6.1.1) "It must have exactly one such group."
11424 			*/
11425 			if (ctxt->redefCounter != 0) {
11426 			    xmlChar *str = NULL;
11427 
11428 			    xmlSchemaCustomErr(ACTXT_CAST ctxt,
11429 				XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11430 				"The redefining model group definition "
11431 				"'%s' must not contain more than one "
11432 				"reference to the redefined definition",
11433 				xmlSchemaFormatQName(&str,
11434 				    ctxt->redef->refTargetNs,
11435 				    ctxt->redef->refName),
11436 				NULL);
11437 			    FREE_AND_NULL(str)
11438 			    part = NULL;
11439 			} else if (((WXS_PARTICLE(part))->minOccurs != 1) ||
11440 			    ((WXS_PARTICLE(part))->maxOccurs != 1))
11441 			{
11442 			    xmlChar *str = NULL;
11443 			    /*
11444 			    * SPEC src-redefine:
11445 			    * (6.1.2) "The `actual value` of both that
11446 			    * group's minOccurs and maxOccurs [attribute]
11447 			    * must be 1 (or `absent`).
11448 			    */
11449 			    xmlSchemaCustomErr(ACTXT_CAST ctxt,
11450 				XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11451 				"The redefining model group definition "
11452 				"'%s' must not contain a reference to the "
11453 				"redefined definition with a "
11454 				"maxOccurs/minOccurs other than 1",
11455 				xmlSchemaFormatQName(&str,
11456 				    ctxt->redef->refTargetNs,
11457 				    ctxt->redef->refName),
11458 				NULL);
11459 			    FREE_AND_NULL(str)
11460 			    part = NULL;
11461 			}
11462 			ctxt->redef->reference = WXS_BASIC_CAST part;
11463 			ctxt->redefCounter++;
11464 		    }
11465 		}
11466 	    } else if (IS_SCHEMA(child, "any")) {
11467 		part = (xmlSchemaTreeItemPtr)
11468 		    xmlSchemaParseAny(ctxt, schema, child);
11469 	    } else if (IS_SCHEMA(child, "choice")) {
11470 		part = xmlSchemaParseModelGroup(ctxt, schema, child,
11471 		    XML_SCHEMA_TYPE_CHOICE, 1);
11472 	    } else if (IS_SCHEMA(child, "sequence")) {
11473 		part = xmlSchemaParseModelGroup(ctxt, schema, child,
11474 		    XML_SCHEMA_TYPE_SEQUENCE, 1);
11475 	    }
11476 	    if (part != NULL) {
11477 		if (last == NULL)
11478 		    item->children = part;
11479 		else
11480 		    last->next = part;
11481 		last = part;
11482 	    }
11483 	    child = child->next;
11484 	}
11485 	if (child != NULL) {
11486 	    xmlSchemaPContentErr(ctxt,
11487 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11488 		NULL, node, child, NULL,
11489 		"(annotation?, (element | group | choice | sequence | any)*)");
11490 	}
11491     }
11492     if ((max == 0) && (min == 0))
11493 	return (NULL);
11494     if (hasRefs) {
11495 	/*
11496 	* We need to resolve references.
11497 	*/
11498 	WXS_ADD_PENDING(ctxt, item);
11499     }
11500     if (withParticle)
11501 	return ((xmlSchemaTreeItemPtr) particle);
11502     else
11503 	return ((xmlSchemaTreeItemPtr) item);
11504 }
11505 
11506 /**
11507  * xmlSchemaParseRestriction:
11508  * @ctxt:  a schema validation context
11509  * @schema:  the schema being built
11510  * @node:  a subtree containing XML Schema informations
11511  *
11512  * parse a XML schema Restriction definition
11513  * *WARNING* this interface is highly subject to change
11514  *
11515  * Returns the type definition or NULL in case of error
11516  */
11517 static xmlSchemaTypePtr
xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,xmlSchemaTypeType parentType)11518 xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11519                           xmlNodePtr node, xmlSchemaTypeType parentType)
11520 {
11521     xmlSchemaTypePtr type;
11522     xmlNodePtr child = NULL;
11523     xmlAttrPtr attr;
11524 
11525     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11526         return (NULL);
11527     /* Not a component, don't create it. */
11528     type = ctxt->ctxtType;
11529     type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
11530 
11531     /*
11532     * Check for illegal attributes.
11533     */
11534     attr = node->properties;
11535     while (attr != NULL) {
11536 	if (attr->ns == NULL) {
11537 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11538 		(!xmlStrEqual(attr->name, BAD_CAST "base"))) {
11539 		xmlSchemaPIllegalAttrErr(ctxt,
11540 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11541 	    }
11542 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11543 	    xmlSchemaPIllegalAttrErr(ctxt,
11544 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11545 	}
11546 	attr = attr->next;
11547     }
11548     /*
11549     * Extract and validate attributes.
11550     */
11551     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11552     /*
11553     * Attribute
11554     */
11555     /*
11556     * Extract the base type. The "base" attribute is mandatory if inside
11557     * a complex type or if redefining.
11558     *
11559     * SPEC (1.2) "...otherwise (<restriction> has no <simpleType> "
11560     * among its [children]), the simple type definition which is
11561     * the {content type} of the type definition `resolved` to by
11562     * the `actual value` of the base [attribute]"
11563     */
11564     if (xmlSchemaPValAttrQName(ctxt, schema, NULL, node, "base",
11565 	&(type->baseNs), &(type->base)) == 0)
11566     {
11567 	if ((type->base == NULL) && (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
11568 	    xmlSchemaPMissingAttrErr(ctxt,
11569 		XML_SCHEMAP_S4S_ATTR_MISSING,
11570 		NULL, node, "base", NULL);
11571 	} else if ((ctxt->isRedefine) &&
11572 	    (type->flags & XML_SCHEMAS_TYPE_GLOBAL))
11573 	{
11574 	    if (type->base == NULL) {
11575 		xmlSchemaPMissingAttrErr(ctxt,
11576 		    XML_SCHEMAP_S4S_ATTR_MISSING,
11577 		    NULL, node, "base", NULL);
11578 	    } else if ((! xmlStrEqual(type->base, type->name)) ||
11579 		(! xmlStrEqual(type->baseNs, type->targetNamespace)))
11580 	    {
11581 		xmlChar *str1 = NULL, *str2 = NULL;
11582 		/*
11583 		* REDEFINE: SPEC src-redefine (5)
11584 		* "Within the [children], each <simpleType> must have a
11585 		* <restriction> among its [children] ... the `actual value` of
11586 		* whose base [attribute] must be the same as the `actual value`
11587 		* of its own name attribute plus target namespace;"
11588 		*/
11589 		xmlSchemaPCustomErrExt(ctxt, XML_SCHEMAP_SRC_REDEFINE,
11590 		    NULL, node, "This is a redefinition, but the QName "
11591 		    "value '%s' of the 'base' attribute does not match the "
11592 		    "type's designation '%s'",
11593 		    xmlSchemaFormatQName(&str1, type->baseNs, type->base),
11594 		    xmlSchemaFormatQName(&str2, type->targetNamespace,
11595 			type->name), NULL);
11596 		FREE_AND_NULL(str1);
11597 		FREE_AND_NULL(str2);
11598 		/* Avoid confusion and erase the values. */
11599 		type->base = NULL;
11600 		type->baseNs = NULL;
11601 	    }
11602 	}
11603     }
11604     /*
11605     * And now for the children...
11606     */
11607     child = node->children;
11608     if (IS_SCHEMA(child, "annotation")) {
11609 	/*
11610 	* Add the annotation to the simple type ancestor.
11611 	*/
11612 	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11613 	    xmlSchemaParseAnnotation(ctxt, child, 1));
11614         child = child->next;
11615     }
11616     if (parentType == XML_SCHEMA_TYPE_SIMPLE) {
11617 	/*
11618 	* Corresponds to <simpleType><restriction><simpleType>.
11619 	*/
11620 	if (IS_SCHEMA(child, "simpleType")) {
11621 	    if (type->base != NULL) {
11622 		/*
11623 		* src-restriction-base-or-simpleType
11624 		* Either the base [attribute] or the simpleType [child] of the
11625 		* <restriction> element must be present, but not both.
11626 		*/
11627 		xmlSchemaPContentErr(ctxt,
11628 		    XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
11629 		    NULL, node, child,
11630 		    "The attribute 'base' and the <simpleType> child are "
11631 		    "mutually exclusive", NULL);
11632 	    } else {
11633 		type->baseType = (xmlSchemaTypePtr)
11634 		    xmlSchemaParseSimpleType(ctxt, schema, child, 0);
11635 	    }
11636 	    child = child->next;
11637 	} else if (type->base == NULL) {
11638 	    xmlSchemaPContentErr(ctxt,
11639 		XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
11640 		NULL, node, child,
11641 		"Either the attribute 'base' or a <simpleType> child "
11642 		"must be present", NULL);
11643 	}
11644     } else if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11645 	/*
11646 	* Corresponds to <complexType><complexContent><restriction>...
11647 	* followed by:
11648 	*
11649 	* Model groups <all>, <choice> and <sequence>.
11650 	*/
11651 	if (IS_SCHEMA(child, "all")) {
11652 	    type->subtypes = (xmlSchemaTypePtr)
11653 		xmlSchemaParseModelGroup(ctxt, schema, child,
11654 		    XML_SCHEMA_TYPE_ALL, 1);
11655 	    child = child->next;
11656 	} else if (IS_SCHEMA(child, "choice")) {
11657 	    type->subtypes = (xmlSchemaTypePtr)
11658 		xmlSchemaParseModelGroup(ctxt,
11659 		    schema, child, XML_SCHEMA_TYPE_CHOICE, 1);
11660 	    child = child->next;
11661 	} else if (IS_SCHEMA(child, "sequence")) {
11662 	    type->subtypes = (xmlSchemaTypePtr)
11663 		xmlSchemaParseModelGroup(ctxt, schema, child,
11664 		    XML_SCHEMA_TYPE_SEQUENCE, 1);
11665 	    child = child->next;
11666 	/*
11667 	* Model group reference <group>.
11668 	*/
11669 	} else if (IS_SCHEMA(child, "group")) {
11670 	    type->subtypes = (xmlSchemaTypePtr)
11671 		xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11672 	    /*
11673 	    * Note that the reference will be resolved in
11674 	    * xmlSchemaResolveTypeReferences();
11675 	    */
11676 	    child = child->next;
11677 	}
11678     } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
11679 	/*
11680 	* Corresponds to <complexType><simpleContent><restriction>...
11681 	*
11682 	* "1.1 the simple type definition corresponding to the <simpleType>
11683 	* among the [children] of <restriction> if there is one;"
11684 	*/
11685 	if (IS_SCHEMA(child, "simpleType")) {
11686 	    /*
11687 	    * We will store the to-be-restricted simple type in
11688 	    * type->contentTypeDef *temporarily*.
11689 	    */
11690 	    type->contentTypeDef = (xmlSchemaTypePtr)
11691 		xmlSchemaParseSimpleType(ctxt, schema, child, 0);
11692 	    if ( type->contentTypeDef == NULL)
11693 		return (NULL);
11694 	    child = child->next;
11695 	}
11696     }
11697 
11698     if ((parentType == XML_SCHEMA_TYPE_SIMPLE) ||
11699 	(parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
11700 	xmlSchemaFacetPtr facet, lastfacet = NULL;
11701 	/*
11702 	* Corresponds to <complexType><simpleContent><restriction>...
11703 	* <simpleType><restriction>...
11704 	*/
11705 
11706 	/*
11707 	* Add the facets to the simple type ancestor.
11708 	*/
11709 	/*
11710 	* TODO: Datatypes: 4.1.3 Constraints on XML Representation of
11711 	* Simple Type Definition Schema Representation Constraint:
11712 	* *Single Facet Value*
11713 	*/
11714 	while ((IS_SCHEMA(child, "minInclusive")) ||
11715 	    (IS_SCHEMA(child, "minExclusive")) ||
11716 	    (IS_SCHEMA(child, "maxInclusive")) ||
11717 	    (IS_SCHEMA(child, "maxExclusive")) ||
11718 	    (IS_SCHEMA(child, "totalDigits")) ||
11719 	    (IS_SCHEMA(child, "fractionDigits")) ||
11720 	    (IS_SCHEMA(child, "pattern")) ||
11721 	    (IS_SCHEMA(child, "enumeration")) ||
11722 	    (IS_SCHEMA(child, "whiteSpace")) ||
11723 	    (IS_SCHEMA(child, "length")) ||
11724 	    (IS_SCHEMA(child, "maxLength")) ||
11725 	    (IS_SCHEMA(child, "minLength"))) {
11726 	    facet = xmlSchemaParseFacet(ctxt, schema, child);
11727 	    if (facet != NULL) {
11728 		if (lastfacet == NULL)
11729 		    type->facets = facet;
11730 		else
11731 		    lastfacet->next = facet;
11732 		lastfacet = facet;
11733 		lastfacet->next = NULL;
11734 	    }
11735 	    child = child->next;
11736 	}
11737 	/*
11738 	* Create links for derivation and validation.
11739 	*/
11740 	if (type->facets != NULL) {
11741 	    xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
11742 
11743 	    facet = type->facets;
11744 	    do {
11745 		facetLink = (xmlSchemaFacetLinkPtr)
11746 		    xmlMalloc(sizeof(xmlSchemaFacetLink));
11747 		if (facetLink == NULL) {
11748 		    xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
11749 		    xmlFree(facetLink);
11750 		    return (NULL);
11751 		}
11752 		facetLink->facet = facet;
11753 		facetLink->next = NULL;
11754 		if (lastFacetLink == NULL)
11755 		    type->facetSet = facetLink;
11756 		else
11757 		    lastFacetLink->next = facetLink;
11758 		lastFacetLink = facetLink;
11759 		facet = facet->next;
11760 	    } while (facet != NULL);
11761 	}
11762     }
11763     if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
11764 	/*
11765 	* Attribute uses/declarations.
11766 	*/
11767 	if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11768 	    (xmlSchemaItemListPtr *) &(type->attrUses),
11769 	    XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
11770 	    return(NULL);
11771 	/*
11772 	* Attribute wildcard.
11773 	*/
11774 	if (IS_SCHEMA(child, "anyAttribute")) {
11775 	    type->attributeWildcard =
11776 		xmlSchemaParseAnyAttribute(ctxt, schema, child);
11777 	    child = child->next;
11778 	}
11779     }
11780     if (child != NULL) {
11781 	if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11782 	    xmlSchemaPContentErr(ctxt,
11783 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11784 		NULL, node, child, NULL,
11785 		"annotation?, (group | all | choice | sequence)?, "
11786 		"((attribute | attributeGroup)*, anyAttribute?))");
11787 	} else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
11788 	     xmlSchemaPContentErr(ctxt,
11789 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11790 		NULL, node, child, NULL,
11791 		"(annotation?, (simpleType?, (minExclusive | minInclusive | "
11792 		"maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11793 		"length | minLength | maxLength | enumeration | whiteSpace | "
11794 		"pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
11795 	} else {
11796 	    /* Simple type */
11797 	    xmlSchemaPContentErr(ctxt,
11798 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11799 		NULL, node, child, NULL,
11800 		"(annotation?, (simpleType?, (minExclusive | minInclusive | "
11801 		"maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11802 		"length | minLength | maxLength | enumeration | whiteSpace | "
11803 		"pattern)*))");
11804 	}
11805     }
11806     return (NULL);
11807 }
11808 
11809 /**
11810  * xmlSchemaParseExtension:
11811  * @ctxt:  a schema validation context
11812  * @schema:  the schema being built
11813  * @node:  a subtree containing XML Schema informations
11814  *
11815  * Parses an <extension>, which is found inside a
11816  * <simpleContent> or <complexContent>.
11817  * *WARNING* this interface is highly subject to change.
11818  *
11819  * TODO: Returns the type definition or NULL in case of error
11820  */
11821 static xmlSchemaTypePtr
xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,xmlSchemaTypeType parentType)11822 xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11823                         xmlNodePtr node, xmlSchemaTypeType parentType)
11824 {
11825     xmlSchemaTypePtr type;
11826     xmlNodePtr child = NULL;
11827     xmlAttrPtr attr;
11828 
11829     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11830         return (NULL);
11831     /* Not a component, don't create it. */
11832     type = ctxt->ctxtType;
11833     type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
11834 
11835     /*
11836     * Check for illegal attributes.
11837     */
11838     attr = node->properties;
11839     while (attr != NULL) {
11840 	if (attr->ns == NULL) {
11841 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11842 		(!xmlStrEqual(attr->name, BAD_CAST "base"))) {
11843 		xmlSchemaPIllegalAttrErr(ctxt,
11844 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11845 	    }
11846 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11847 	    xmlSchemaPIllegalAttrErr(ctxt,
11848 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11849 	}
11850 	attr = attr->next;
11851     }
11852 
11853     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11854 
11855     /*
11856     * Attribute "base" - mandatory.
11857     */
11858     if ((xmlSchemaPValAttrQName(ctxt, schema, NULL, node,
11859 	"base", &(type->baseNs), &(type->base)) == 0) &&
11860 	(type->base == NULL)) {
11861 	xmlSchemaPMissingAttrErr(ctxt,
11862 	    XML_SCHEMAP_S4S_ATTR_MISSING,
11863 	    NULL, node, "base", NULL);
11864     }
11865     /*
11866     * And now for the children...
11867     */
11868     child = node->children;
11869     if (IS_SCHEMA(child, "annotation")) {
11870 	/*
11871 	* Add the annotation to the type ancestor.
11872 	*/
11873 	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11874 	    xmlSchemaParseAnnotation(ctxt, child, 1));
11875         child = child->next;
11876     }
11877     if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11878 	/*
11879 	* Corresponds to <complexType><complexContent><extension>... and:
11880 	*
11881 	* Model groups <all>, <choice>, <sequence> and <group>.
11882 	*/
11883 	if (IS_SCHEMA(child, "all")) {
11884 	    type->subtypes = (xmlSchemaTypePtr)
11885 		xmlSchemaParseModelGroup(ctxt, schema,
11886 		    child, XML_SCHEMA_TYPE_ALL, 1);
11887 	    child = child->next;
11888 	} else if (IS_SCHEMA(child, "choice")) {
11889 	    type->subtypes = (xmlSchemaTypePtr)
11890 		xmlSchemaParseModelGroup(ctxt, schema,
11891 		    child, XML_SCHEMA_TYPE_CHOICE, 1);
11892 	    child = child->next;
11893 	} else if (IS_SCHEMA(child, "sequence")) {
11894 	    type->subtypes = (xmlSchemaTypePtr)
11895 		xmlSchemaParseModelGroup(ctxt, schema,
11896 		child, XML_SCHEMA_TYPE_SEQUENCE, 1);
11897 	    child = child->next;
11898 	} else if (IS_SCHEMA(child, "group")) {
11899 	    type->subtypes = (xmlSchemaTypePtr)
11900 		xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11901 	    /*
11902 	    * Note that the reference will be resolved in
11903 	    * xmlSchemaResolveTypeReferences();
11904 	    */
11905 	    child = child->next;
11906 	}
11907     }
11908     if (child != NULL) {
11909 	/*
11910 	* Attribute uses/declarations.
11911 	*/
11912 	if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11913 	    (xmlSchemaItemListPtr *) &(type->attrUses),
11914 	    XML_SCHEMA_TYPE_EXTENSION, NULL) == -1)
11915 	    return(NULL);
11916 	/*
11917 	* Attribute wildcard.
11918 	*/
11919 	if (IS_SCHEMA(child, "anyAttribute")) {
11920 	    ctxt->ctxtType->attributeWildcard =
11921 		xmlSchemaParseAnyAttribute(ctxt, schema, child);
11922 	    child = child->next;
11923 	}
11924     }
11925     if (child != NULL) {
11926 	if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11927 	    /* Complex content extension. */
11928 	    xmlSchemaPContentErr(ctxt,
11929 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11930 		NULL, node, child, NULL,
11931 		"(annotation?, ((group | all | choice | sequence)?, "
11932 		"((attribute | attributeGroup)*, anyAttribute?)))");
11933 	} else {
11934 	    /* Simple content extension. */
11935 	    xmlSchemaPContentErr(ctxt,
11936 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11937 		NULL, node, child, NULL,
11938 		"(annotation?, ((attribute | attributeGroup)*, "
11939 		"anyAttribute?))");
11940 	}
11941     }
11942     return (NULL);
11943 }
11944 
11945 /**
11946  * xmlSchemaParseSimpleContent:
11947  * @ctxt:  a schema validation context
11948  * @schema:  the schema being built
11949  * @node:  a subtree containing XML Schema informations
11950  *
11951  * parse a XML schema SimpleContent definition
11952  * *WARNING* this interface is highly subject to change
11953  *
11954  * Returns the type definition or NULL in case of error
11955  */
11956 static int
xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,int * hasRestrictionOrExtension)11957 xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
11958                             xmlSchemaPtr schema, xmlNodePtr node,
11959 			    int *hasRestrictionOrExtension)
11960 {
11961     xmlSchemaTypePtr type;
11962     xmlNodePtr child = NULL;
11963     xmlAttrPtr attr;
11964 
11965     if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
11966 	(hasRestrictionOrExtension == NULL))
11967         return (-1);
11968     *hasRestrictionOrExtension = 0;
11969     /* Not a component, don't create it. */
11970     type = ctxt->ctxtType;
11971     type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
11972     /*
11973     * Check for illegal attributes.
11974     */
11975     attr = node->properties;
11976     while (attr != NULL) {
11977 	if (attr->ns == NULL) {
11978 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id"))) {
11979 		xmlSchemaPIllegalAttrErr(ctxt,
11980 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11981 	    }
11982 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11983 	    xmlSchemaPIllegalAttrErr(ctxt,
11984 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11985 	}
11986 	attr = attr->next;
11987     }
11988 
11989     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11990 
11991     /*
11992     * And now for the children...
11993     */
11994     child = node->children;
11995     if (IS_SCHEMA(child, "annotation")) {
11996 	/*
11997 	* Add the annotation to the complex type ancestor.
11998 	*/
11999 	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
12000 	    xmlSchemaParseAnnotation(ctxt, child, 1));
12001         child = child->next;
12002     }
12003     if (child == NULL) {
12004 	xmlSchemaPContentErr(ctxt,
12005 	    XML_SCHEMAP_S4S_ELEM_MISSING,
12006 	    NULL, node, NULL, NULL,
12007 	    "(annotation?, (restriction | extension))");
12008     }
12009     if (child == NULL) {
12010 	xmlSchemaPContentErr(ctxt,
12011 	    XML_SCHEMAP_S4S_ELEM_MISSING,
12012 	    NULL, node, NULL, NULL,
12013 	    "(annotation?, (restriction | extension))");
12014     }
12015     if (IS_SCHEMA(child, "restriction")) {
12016         xmlSchemaParseRestriction(ctxt, schema, child,
12017 	    XML_SCHEMA_TYPE_SIMPLE_CONTENT);
12018 	(*hasRestrictionOrExtension) = 1;
12019         child = child->next;
12020     } else if (IS_SCHEMA(child, "extension")) {
12021         xmlSchemaParseExtension(ctxt, schema, child,
12022 	    XML_SCHEMA_TYPE_SIMPLE_CONTENT);
12023 	(*hasRestrictionOrExtension) = 1;
12024         child = child->next;
12025     }
12026     if (child != NULL) {
12027 	xmlSchemaPContentErr(ctxt,
12028 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
12029 	    NULL, node, child, NULL,
12030 	    "(annotation?, (restriction | extension))");
12031     }
12032     return (0);
12033 }
12034 
12035 /**
12036  * xmlSchemaParseComplexContent:
12037  * @ctxt:  a schema validation context
12038  * @schema:  the schema being built
12039  * @node:  a subtree containing XML Schema informations
12040  *
12041  * parse a XML schema ComplexContent definition
12042  * *WARNING* this interface is highly subject to change
12043  *
12044  * Returns the type definition or NULL in case of error
12045  */
12046 static int
xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,int * hasRestrictionOrExtension)12047 xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
12048                              xmlSchemaPtr schema, xmlNodePtr node,
12049 			     int *hasRestrictionOrExtension)
12050 {
12051     xmlSchemaTypePtr type;
12052     xmlNodePtr child = NULL;
12053     xmlAttrPtr attr;
12054 
12055     if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
12056 	(hasRestrictionOrExtension == NULL))
12057         return (-1);
12058     *hasRestrictionOrExtension = 0;
12059     /* Not a component, don't create it. */
12060     type = ctxt->ctxtType;
12061     /*
12062     * Check for illegal attributes.
12063     */
12064     attr = node->properties;
12065     while (attr != NULL) {
12066 	if (attr->ns == NULL) {
12067 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
12068 		(!xmlStrEqual(attr->name, BAD_CAST "mixed")))
12069 	    {
12070 		xmlSchemaPIllegalAttrErr(ctxt,
12071 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12072 	    }
12073 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
12074 	    xmlSchemaPIllegalAttrErr(ctxt,
12075 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12076 	}
12077 	attr = attr->next;
12078     }
12079 
12080     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
12081 
12082     /*
12083     * Set the 'mixed' on the complex type ancestor.
12084     */
12085     if (xmlGetBooleanProp(ctxt, node, "mixed", 0))  {
12086 	if ((type->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
12087 	    type->flags |= XML_SCHEMAS_TYPE_MIXED;
12088     }
12089     child = node->children;
12090     if (IS_SCHEMA(child, "annotation")) {
12091 	/*
12092 	* Add the annotation to the complex type ancestor.
12093 	*/
12094 	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
12095 	    xmlSchemaParseAnnotation(ctxt, child, 1));
12096         child = child->next;
12097     }
12098     if (child == NULL) {
12099 	xmlSchemaPContentErr(ctxt,
12100 	    XML_SCHEMAP_S4S_ELEM_MISSING,
12101 	    NULL, node, NULL,
12102 	    NULL, "(annotation?, (restriction | extension))");
12103     }
12104     if (child == NULL) {
12105 	xmlSchemaPContentErr(ctxt,
12106 	    XML_SCHEMAP_S4S_ELEM_MISSING,
12107 	    NULL, node, NULL,
12108 	    NULL, "(annotation?, (restriction | extension))");
12109     }
12110     if (IS_SCHEMA(child, "restriction")) {
12111         xmlSchemaParseRestriction(ctxt, schema, child,
12112 	    XML_SCHEMA_TYPE_COMPLEX_CONTENT);
12113 	(*hasRestrictionOrExtension) = 1;
12114         child = child->next;
12115     } else if (IS_SCHEMA(child, "extension")) {
12116         xmlSchemaParseExtension(ctxt, schema, child,
12117 	    XML_SCHEMA_TYPE_COMPLEX_CONTENT);
12118 	(*hasRestrictionOrExtension) = 1;
12119         child = child->next;
12120     }
12121     if (child != NULL) {
12122 	xmlSchemaPContentErr(ctxt,
12123 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
12124 	    NULL, node, child,
12125 	    NULL, "(annotation?, (restriction | extension))");
12126     }
12127     return (0);
12128 }
12129 
12130 /**
12131  * xmlSchemaParseComplexType:
12132  * @ctxt:  a schema validation context
12133  * @schema:  the schema being built
12134  * @node:  a subtree containing XML Schema informations
12135  *
12136  * parse a XML schema Complex Type definition
12137  * *WARNING* this interface is highly subject to change
12138  *
12139  * Returns the type definition or NULL in case of error
12140  */
12141 static xmlSchemaTypePtr
xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,int topLevel)12142 xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
12143                           xmlNodePtr node, int topLevel)
12144 {
12145     xmlSchemaTypePtr type, ctxtType;
12146     xmlNodePtr child = NULL;
12147     const xmlChar *name = NULL;
12148     xmlAttrPtr attr;
12149     const xmlChar *attrValue;
12150 #ifdef ENABLE_NAMED_LOCALS
12151     char buf[40];
12152 #endif
12153     int final = 0, block = 0, hasRestrictionOrExtension = 0;
12154 
12155 
12156     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
12157         return (NULL);
12158 
12159     ctxtType = ctxt->ctxtType;
12160 
12161     if (topLevel) {
12162 	attr = xmlSchemaGetPropNode(node, "name");
12163 	if (attr == NULL) {
12164 	    xmlSchemaPMissingAttrErr(ctxt,
12165 		XML_SCHEMAP_S4S_ATTR_MISSING, NULL, node, "name", NULL);
12166 	    return (NULL);
12167 	} else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
12168 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
12169 	    return (NULL);
12170 	}
12171     }
12172 
12173     if (topLevel == 0) {
12174 	/*
12175 	* Parse as local complex type definition.
12176 	*/
12177 #ifdef ENABLE_NAMED_LOCALS
12178         snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
12179 	type = xmlSchemaAddType(ctxt, schema,
12180 	    XML_SCHEMA_TYPE_COMPLEX,
12181 	    xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
12182 	    ctxt->targetNamespace, node, 0);
12183 #else
12184 	type = xmlSchemaAddType(ctxt, schema,
12185 	    XML_SCHEMA_TYPE_COMPLEX,
12186 	    NULL, ctxt->targetNamespace, node, 0);
12187 #endif
12188 	if (type == NULL)
12189 	    return (NULL);
12190 	name = type->name;
12191 	type->node = node;
12192 	type->type = XML_SCHEMA_TYPE_COMPLEX;
12193 	/*
12194 	* TODO: We need the target namespace.
12195 	*/
12196     } else {
12197 	/*
12198 	* Parse as global complex type definition.
12199 	*/
12200 	type = xmlSchemaAddType(ctxt, schema,
12201 	    XML_SCHEMA_TYPE_COMPLEX,
12202 	    name, ctxt->targetNamespace, node, 1);
12203 	if (type == NULL)
12204 	    return (NULL);
12205 	type->node = node;
12206 	type->type = XML_SCHEMA_TYPE_COMPLEX;
12207 	type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
12208     }
12209     type->targetNamespace = ctxt->targetNamespace;
12210     /*
12211     * Handle attributes.
12212     */
12213     attr = node->properties;
12214     while (attr != NULL) {
12215 	if (attr->ns == NULL) {
12216 	    if (xmlStrEqual(attr->name, BAD_CAST "id")) {
12217 		/*
12218 		* Attribute "id".
12219 		*/
12220 		xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
12221 	    } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
12222 		/*
12223 		* Attribute "mixed".
12224 		*/
12225 		if (xmlSchemaPGetBoolNodeValue(ctxt,
12226 			NULL, (xmlNodePtr) attr))
12227 		    type->flags |= XML_SCHEMAS_TYPE_MIXED;
12228 	    } else if (topLevel) {
12229 		/*
12230 		* Attributes of global complex type definitions.
12231 		*/
12232 		if (xmlStrEqual(attr->name, BAD_CAST "name")) {
12233 		    /* Pass. */
12234 		} else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
12235 		    /*
12236 		    * Attribute "abstract".
12237 		    */
12238 		    if (xmlSchemaPGetBoolNodeValue(ctxt,
12239 			    NULL, (xmlNodePtr) attr))
12240 			type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
12241 		} else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
12242 		    /*
12243 		    * Attribute "final".
12244 		    */
12245 		    attrValue = xmlSchemaGetNodeContent(ctxt,
12246 			(xmlNodePtr) attr);
12247 		    if (xmlSchemaPValAttrBlockFinal(attrValue,
12248 			&(type->flags),
12249 			-1,
12250 			XML_SCHEMAS_TYPE_FINAL_EXTENSION,
12251 			XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
12252 			-1, -1, -1) != 0)
12253 		    {
12254 			xmlSchemaPSimpleTypeErr(ctxt,
12255 			    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
12256 			    NULL, (xmlNodePtr) attr, NULL,
12257 			    "(#all | List of (extension | restriction))",
12258 			    attrValue, NULL, NULL, NULL);
12259 		    } else
12260 			final = 1;
12261 		} else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
12262 		    /*
12263 		    * Attribute "block".
12264 		    */
12265 		    attrValue = xmlSchemaGetNodeContent(ctxt,
12266 			(xmlNodePtr) attr);
12267 		    if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
12268 			-1,
12269 			XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
12270 			XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
12271 			-1, -1, -1) != 0) {
12272 			xmlSchemaPSimpleTypeErr(ctxt,
12273 			    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
12274 			    NULL, (xmlNodePtr) attr, NULL,
12275 			    "(#all | List of (extension | restriction)) ",
12276 			    attrValue, NULL, NULL, NULL);
12277 		    } else
12278 			block = 1;
12279 		} else {
12280 			xmlSchemaPIllegalAttrErr(ctxt,
12281 			    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12282 		}
12283 	    } else {
12284 		xmlSchemaPIllegalAttrErr(ctxt,
12285 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12286 	    }
12287 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
12288 	    xmlSchemaPIllegalAttrErr(ctxt,
12289 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12290 	}
12291 	attr = attr->next;
12292     }
12293     if (! block) {
12294 	/*
12295 	* Apply default "block" values.
12296 	*/
12297 	if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
12298 	    type->flags |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
12299 	if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
12300 	    type->flags |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
12301     }
12302     if (! final) {
12303 	/*
12304 	* Apply default "block" values.
12305 	*/
12306 	if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
12307 	    type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
12308 	if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
12309 	    type->flags |= XML_SCHEMAS_TYPE_FINAL_EXTENSION;
12310     }
12311     /*
12312     * And now for the children...
12313     */
12314     child = node->children;
12315     if (IS_SCHEMA(child, "annotation")) {
12316         type->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
12317         child = child->next;
12318     }
12319     ctxt->ctxtType = type;
12320     if (IS_SCHEMA(child, "simpleContent")) {
12321 	/*
12322 	* <complexType><simpleContent>...
12323 	* 3.4.3 : 2.2
12324 	* Specifying mixed='true' when the <simpleContent>
12325 	* alternative is chosen has no effect
12326 	*/
12327 	if (type->flags & XML_SCHEMAS_TYPE_MIXED)
12328 	    type->flags ^= XML_SCHEMAS_TYPE_MIXED;
12329         xmlSchemaParseSimpleContent(ctxt, schema, child,
12330 	    &hasRestrictionOrExtension);
12331         child = child->next;
12332     } else if (IS_SCHEMA(child, "complexContent")) {
12333 	/*
12334 	* <complexType><complexContent>...
12335 	*/
12336 	type->contentType = XML_SCHEMA_CONTENT_EMPTY;
12337         xmlSchemaParseComplexContent(ctxt, schema, child,
12338 	    &hasRestrictionOrExtension);
12339         child = child->next;
12340     } else {
12341 	/*
12342 	* E.g <complexType><sequence>... or <complexType><attribute>... etc.
12343 	*
12344 	* SPEC
12345 	* "...the third alternative (neither <simpleContent> nor
12346 	* <complexContent>) is chosen. This case is understood as shorthand
12347 	* for complex content restricting the `ur-type definition`, and the
12348 	* details of the mappings should be modified as necessary.
12349 	*/
12350 	type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
12351 	type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
12352 	/*
12353 	* Parse model groups.
12354 	*/
12355         if (IS_SCHEMA(child, "all")) {
12356             type->subtypes = (xmlSchemaTypePtr)
12357 		xmlSchemaParseModelGroup(ctxt, schema, child,
12358 		    XML_SCHEMA_TYPE_ALL, 1);
12359             child = child->next;
12360         } else if (IS_SCHEMA(child, "choice")) {
12361             type->subtypes = (xmlSchemaTypePtr)
12362 		xmlSchemaParseModelGroup(ctxt, schema, child,
12363 		    XML_SCHEMA_TYPE_CHOICE, 1);
12364             child = child->next;
12365         } else if (IS_SCHEMA(child, "sequence")) {
12366             type->subtypes = (xmlSchemaTypePtr)
12367 		xmlSchemaParseModelGroup(ctxt, schema, child,
12368 		    XML_SCHEMA_TYPE_SEQUENCE, 1);
12369             child = child->next;
12370         } else if (IS_SCHEMA(child, "group")) {
12371             type->subtypes = (xmlSchemaTypePtr)
12372 		xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
12373 	    /*
12374 	    * Note that the reference will be resolved in
12375 	    * xmlSchemaResolveTypeReferences();
12376 	    */
12377             child = child->next;
12378         }
12379 	/*
12380 	* Parse attribute decls/refs.
12381 	*/
12382         if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
12383 	    (xmlSchemaItemListPtr *) &(type->attrUses),
12384 	    XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
12385 	    return(NULL);
12386 	/*
12387 	* Parse attribute wildcard.
12388 	*/
12389 	if (IS_SCHEMA(child, "anyAttribute")) {
12390 	    type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
12391 	    child = child->next;
12392 	}
12393     }
12394     if (child != NULL) {
12395 	xmlSchemaPContentErr(ctxt,
12396 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
12397 	    NULL, node, child,
12398 	    NULL, "(annotation?, (simpleContent | complexContent | "
12399 	    "((group | all | choice | sequence)?, ((attribute | "
12400 	    "attributeGroup)*, anyAttribute?))))");
12401     }
12402     /*
12403     * REDEFINE: SPEC src-redefine (5)
12404     */
12405     if (topLevel && ctxt->isRedefine && (! hasRestrictionOrExtension)) {
12406 	xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
12407 	    NULL, node, "This is a redefinition, thus the "
12408 	    "<complexType> must have a <restriction> or <extension> "
12409 	    "grand-child", NULL);
12410     }
12411     ctxt->ctxtType = ctxtType;
12412     return (type);
12413 }
12414 
12415 /************************************************************************
12416  *									*
12417  *			Validating using Schemas			*
12418  *									*
12419  ************************************************************************/
12420 
12421 /************************************************************************
12422  *									*
12423  *			Reading/Writing Schemas				*
12424  *									*
12425  ************************************************************************/
12426 
12427 #if 0 /* Will be enabled if it is clear what options are needed. */
12428 /**
12429  * xmlSchemaParserCtxtSetOptions:
12430  * @ctxt:	a schema parser context
12431  * @options: a combination of xmlSchemaParserOption
12432  *
12433  * Sets the options to be used during the parse.
12434  *
12435  * Returns 0 in case of success, -1 in case of an
12436  * API error.
12437  */
12438 static int
12439 xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
12440 			      int options)
12441 
12442 {
12443     int i;
12444 
12445     if (ctxt == NULL)
12446 	return (-1);
12447     /*
12448     * WARNING: Change the start value if adding to the
12449     * xmlSchemaParseOption.
12450     */
12451     for (i = 1; i < (int) sizeof(int) * 8; i++) {
12452         if (options & 1<<i) {
12453 	    return (-1);
12454         }
12455     }
12456     ctxt->options = options;
12457     return (0);
12458 }
12459 
12460 /**
12461  * xmlSchemaValidCtxtGetOptions:
12462  * @ctxt: a schema parser context
12463  *
12464  * Returns the option combination of the parser context.
12465  */
12466 static int
12467 xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
12468 
12469 {
12470     if (ctxt == NULL)
12471 	return (-1);
12472     else
12473 	return (ctxt->options);
12474 }
12475 #endif
12476 
12477 /**
12478  * xmlSchemaNewParserCtxt:
12479  * @URL:  the location of the schema
12480  *
12481  * Create an XML Schemas parse context for that file/resource expected
12482  * to contain an XML Schemas file.
12483  *
12484  * Returns the parser context or NULL in case of error
12485  */
12486 xmlSchemaParserCtxtPtr
xmlSchemaNewParserCtxt(const char * URL)12487 xmlSchemaNewParserCtxt(const char *URL)
12488 {
12489     xmlSchemaParserCtxtPtr ret;
12490 
12491     if (URL == NULL)
12492         return (NULL);
12493 
12494     ret = xmlSchemaParserCtxtCreate();
12495     if (ret == NULL)
12496 	return(NULL);
12497     ret->dict = xmlDictCreate();
12498     ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
12499     return (ret);
12500 }
12501 
12502 /**
12503  * xmlSchemaNewMemParserCtxt:
12504  * @buffer:  a pointer to a char array containing the schemas
12505  * @size:  the size of the array
12506  *
12507  * Create an XML Schemas parse context for that memory buffer expected
12508  * to contain an XML Schemas file.
12509  *
12510  * Returns the parser context or NULL in case of error
12511  */
12512 xmlSchemaParserCtxtPtr
xmlSchemaNewMemParserCtxt(const char * buffer,int size)12513 xmlSchemaNewMemParserCtxt(const char *buffer, int size)
12514 {
12515     xmlSchemaParserCtxtPtr ret;
12516 
12517     if ((buffer == NULL) || (size <= 0))
12518         return (NULL);
12519     ret = xmlSchemaParserCtxtCreate();
12520     if (ret == NULL)
12521 	return(NULL);
12522     ret->buffer = buffer;
12523     ret->size = size;
12524     ret->dict = xmlDictCreate();
12525     return (ret);
12526 }
12527 
12528 /**
12529  * xmlSchemaNewDocParserCtxt:
12530  * @doc:  a preparsed document tree
12531  *
12532  * Create an XML Schemas parse context for that document.
12533  * NB. The document may be modified during the parsing process.
12534  *
12535  * Returns the parser context or NULL in case of error
12536  */
12537 xmlSchemaParserCtxtPtr
xmlSchemaNewDocParserCtxt(xmlDocPtr doc)12538 xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
12539 {
12540     xmlSchemaParserCtxtPtr ret;
12541 
12542     if (doc == NULL)
12543       return (NULL);
12544     ret = xmlSchemaParserCtxtCreate();
12545     if (ret == NULL)
12546 	return(NULL);
12547     ret->doc = doc;
12548     ret->dict = xmlDictCreate();
12549     /* The application has responsibility for the document */
12550     ret->preserve = 1;
12551 
12552     return (ret);
12553 }
12554 
12555 /**
12556  * xmlSchemaFreeParserCtxt:
12557  * @ctxt:  the schema parser context
12558  *
12559  * Free the resources associated to the schema parser context
12560  */
12561 void
xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)12562 xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
12563 {
12564     if (ctxt == NULL)
12565         return;
12566     if (ctxt->doc != NULL && !ctxt->preserve)
12567         xmlFreeDoc(ctxt->doc);
12568     if (ctxt->vctxt != NULL) {
12569 	xmlSchemaFreeValidCtxt(ctxt->vctxt);
12570     }
12571     if (ctxt->ownsConstructor && (ctxt->constructor != NULL)) {
12572 	xmlSchemaConstructionCtxtFree(ctxt->constructor);
12573 	ctxt->constructor = NULL;
12574 	ctxt->ownsConstructor = 0;
12575     }
12576     if (ctxt->attrProhibs != NULL)
12577 	xmlSchemaItemListFree(ctxt->attrProhibs);
12578     xmlDictFree(ctxt->dict);
12579     xmlFree(ctxt);
12580 }
12581 
12582 /************************************************************************
12583  *									*
12584  *			Building the content models			*
12585  *									*
12586  ************************************************************************/
12587 
12588 /**
12589  * xmlSchemaBuildContentModelForSubstGroup:
12590  *
12591  * Returns 1 if nillable, 0 otherwise
12592  */
12593 static int
xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,xmlSchemaParticlePtr particle,int counter,xmlAutomataStatePtr end)12594 xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,
12595 	xmlSchemaParticlePtr particle, int counter, xmlAutomataStatePtr end)
12596 {
12597     xmlAutomataStatePtr start, tmp;
12598     xmlSchemaElementPtr elemDecl, member;
12599     xmlSchemaSubstGroupPtr substGroup;
12600     int i;
12601     int ret = 0;
12602 
12603     elemDecl = (xmlSchemaElementPtr) particle->children;
12604     /*
12605     * Wrap the substitution group with a CHOICE.
12606     */
12607     start = pctxt->state;
12608     if (end == NULL)
12609 	end = xmlAutomataNewState(pctxt->am);
12610     substGroup = xmlSchemaSubstGroupGet(pctxt, elemDecl);
12611     if (substGroup == NULL) {
12612 	xmlSchemaPErr(pctxt, WXS_ITEM_NODE(particle),
12613 	    XML_SCHEMAP_INTERNAL,
12614 	    "Internal error: xmlSchemaBuildContentModelForSubstGroup, "
12615 	    "declaration is marked having a subst. group but none "
12616 	    "available.\n", elemDecl->name, NULL);
12617 	return(0);
12618     }
12619     if (counter >= 0) {
12620 	/*
12621 	* NOTE that we put the declaration in, even if it's abstract.
12622 	* However, an error will be raised during *validation* if an element
12623 	* information item shall be validated against an abstract element
12624 	* declaration.
12625 	*/
12626 	tmp = xmlAutomataNewCountedTrans(pctxt->am, start, NULL, counter);
12627         xmlAutomataNewTransition2(pctxt->am, tmp, end,
12628 	            elemDecl->name, elemDecl->targetNamespace, elemDecl);
12629 	/*
12630 	* Add subst. group members.
12631 	*/
12632 	for (i = 0; i < substGroup->members->nbItems; i++) {
12633 	    member = (xmlSchemaElementPtr) substGroup->members->items[i];
12634             xmlAutomataNewTransition2(pctxt->am, tmp, end,
12635 		               member->name, member->targetNamespace, member);
12636 	}
12637     } else if (particle->maxOccurs == 1) {
12638 	/*
12639 	* NOTE that we put the declaration in, even if it's abstract,
12640 	*/
12641 	xmlAutomataNewEpsilon(pctxt->am,
12642 	    xmlAutomataNewTransition2(pctxt->am,
12643 	    start, NULL,
12644 	    elemDecl->name, elemDecl->targetNamespace, elemDecl), end);
12645 	/*
12646 	* Add subst. group members.
12647 	*/
12648 	for (i = 0; i < substGroup->members->nbItems; i++) {
12649 	    member = (xmlSchemaElementPtr) substGroup->members->items[i];
12650 	    /*
12651 	    * NOTE: This fixes bug #341150. xmlAutomataNewOnceTrans2()
12652 	    *  was incorrectly used instead of xmlAutomataNewTransition2()
12653 	    *  (seems like a copy&paste bug from the XML_SCHEMA_TYPE_ALL
12654 	    *  section in xmlSchemaBuildAContentModel() ).
12655 	    * TODO: Check if xmlAutomataNewOnceTrans2() was instead
12656 	    *  intended for the above "counter" section originally. I.e.,
12657 	    *  check xs:all with subst-groups.
12658 	    *
12659 	    * tmp = xmlAutomataNewOnceTrans2(pctxt->am, start, NULL,
12660 	    *	               member->name, member->targetNamespace,
12661 	    *		       1, 1, member);
12662 	    */
12663 	    tmp = xmlAutomataNewTransition2(pctxt->am, start, NULL,
12664 		member->name, member->targetNamespace, member);
12665 	    xmlAutomataNewEpsilon(pctxt->am, tmp, end);
12666 	}
12667     } else {
12668 	xmlAutomataStatePtr hop;
12669 	int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12670 	    UNBOUNDED : particle->maxOccurs - 1;
12671 	int minOccurs = particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12672 
12673 	counter =
12674 	    xmlAutomataNewCounter(pctxt->am, minOccurs,
12675 	    maxOccurs);
12676 	hop = xmlAutomataNewState(pctxt->am);
12677 
12678 	xmlAutomataNewEpsilon(pctxt->am,
12679 	    xmlAutomataNewTransition2(pctxt->am,
12680 	    start, NULL,
12681 	    elemDecl->name, elemDecl->targetNamespace, elemDecl),
12682 	    hop);
12683 	/*
12684 	 * Add subst. group members.
12685 	 */
12686 	for (i = 0; i < substGroup->members->nbItems; i++) {
12687 	    member = (xmlSchemaElementPtr) substGroup->members->items[i];
12688 	    xmlAutomataNewEpsilon(pctxt->am,
12689 		xmlAutomataNewTransition2(pctxt->am,
12690 		start, NULL,
12691 		member->name, member->targetNamespace, member),
12692 		hop);
12693 	}
12694 	xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12695 	xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12696     }
12697     if (particle->minOccurs == 0) {
12698 	xmlAutomataNewEpsilon(pctxt->am, start, end);
12699         ret = 1;
12700     }
12701     pctxt->state = end;
12702     return(ret);
12703 }
12704 
12705 /**
12706  * xmlSchemaBuildContentModelForElement:
12707  *
12708  * Returns 1 if nillable, 0 otherwise
12709  */
12710 static int
xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr particle)12711 xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,
12712 				     xmlSchemaParticlePtr particle)
12713 {
12714     int ret = 0;
12715 
12716     if (((xmlSchemaElementPtr) particle->children)->flags &
12717 	XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
12718 	/*
12719 	* Substitution groups.
12720 	*/
12721 	ret = xmlSchemaBuildContentModelForSubstGroup(ctxt, particle, -1, NULL);
12722     } else {
12723 	xmlSchemaElementPtr elemDecl;
12724 	xmlAutomataStatePtr start;
12725 
12726 	elemDecl = (xmlSchemaElementPtr) particle->children;
12727 
12728 	if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT)
12729 	    return(0);
12730 	if (particle->maxOccurs == 1) {
12731 	    start = ctxt->state;
12732 	    ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12733 		    elemDecl->name, elemDecl->targetNamespace, elemDecl);
12734 	} else if ((particle->maxOccurs >= UNBOUNDED) &&
12735 	           (particle->minOccurs < 2)) {
12736 	    /* Special case. */
12737 	    start = ctxt->state;
12738 	    ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12739 		elemDecl->name, elemDecl->targetNamespace, elemDecl);
12740 	    ctxt->state = xmlAutomataNewTransition2(ctxt->am, ctxt->state, ctxt->state,
12741 		elemDecl->name, elemDecl->targetNamespace, elemDecl);
12742 	} else {
12743 	    int counter;
12744 	    int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12745 			    UNBOUNDED : particle->maxOccurs - 1;
12746 	    int minOccurs = particle->minOccurs < 1 ?
12747 			    0 : particle->minOccurs - 1;
12748 
12749 	    start = xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
12750 	    counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
12751 	    ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12752 		elemDecl->name, elemDecl->targetNamespace, elemDecl);
12753 	    xmlAutomataNewCountedTrans(ctxt->am, ctxt->state, start, counter);
12754 	    ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, ctxt->state,
12755 		NULL, counter);
12756 	}
12757 	if (particle->minOccurs == 0) {
12758 	    xmlAutomataNewEpsilon(ctxt->am, start, ctxt->state);
12759             ret = 1;
12760         }
12761     }
12762     return(ret);
12763 }
12764 
12765 /**
12766  * xmlSchemaBuildAContentModel:
12767  * @ctxt:  the schema parser context
12768  * @particle:  the particle component
12769  * @name:  the complex type's name whose content is being built
12770  *
12771  * Create the automaton for the {content type} of a complex type.
12772  *
12773  * Returns 1 if the content is nillable, 0 otherwise
12774  */
12775 static int
xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,xmlSchemaParticlePtr particle)12776 xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,
12777 			    xmlSchemaParticlePtr particle)
12778 {
12779     int ret = 0, tmp2;
12780 
12781     if (particle == NULL) {
12782 	PERROR_INT("xmlSchemaBuildAContentModel", "particle is NULL");
12783 	return(1);
12784     }
12785     if (particle->children == NULL) {
12786 	/*
12787 	* Just return in this case. A missing "term" of the particle
12788 	* might arise due to an invalid "term" component.
12789 	*/
12790 	return(1);
12791     }
12792 
12793     switch (particle->children->type) {
12794 	case XML_SCHEMA_TYPE_ANY: {
12795 	    xmlAutomataStatePtr start, end;
12796 	    xmlSchemaWildcardPtr wild;
12797 	    xmlSchemaWildcardNsPtr ns;
12798 
12799 	    wild = (xmlSchemaWildcardPtr) particle->children;
12800 
12801 	    start = pctxt->state;
12802 	    end = xmlAutomataNewState(pctxt->am);
12803 
12804 	    if (particle->maxOccurs == 1) {
12805 		if (wild->any == 1) {
12806 		    /*
12807 		    * We need to add both transitions:
12808 		    *
12809 		    * 1. the {"*", "*"} for elements in a namespace.
12810 		    */
12811 		    pctxt->state =
12812 			xmlAutomataNewTransition2(pctxt->am,
12813 			start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
12814 		    xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12815 		    /*
12816 		    * 2. the {"*"} for elements in no namespace.
12817 		    */
12818 		    pctxt->state =
12819 			xmlAutomataNewTransition2(pctxt->am,
12820 			start, NULL, BAD_CAST "*", NULL, wild);
12821 		    xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12822 
12823 		} else if (wild->nsSet != NULL) {
12824 		    ns = wild->nsSet;
12825 		    do {
12826 			pctxt->state = start;
12827 			pctxt->state = xmlAutomataNewTransition2(pctxt->am,
12828 			    pctxt->state, NULL, BAD_CAST "*", ns->value, wild);
12829 			xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12830 			ns = ns->next;
12831 		    } while (ns != NULL);
12832 
12833 		} else if (wild->negNsSet != NULL) {
12834 		    pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
12835 			start, end, BAD_CAST "*", wild->negNsSet->value,
12836 			wild);
12837 		}
12838 	    } else {
12839 		int counter;
12840 		xmlAutomataStatePtr hop;
12841 		int maxOccurs =
12842 		    particle->maxOccurs == UNBOUNDED ? UNBOUNDED :
12843                                            particle->maxOccurs - 1;
12844 		int minOccurs =
12845 		    particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12846 
12847 		counter = xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
12848 		hop = xmlAutomataNewState(pctxt->am);
12849 		if (wild->any == 1) {
12850 		    pctxt->state =
12851 			xmlAutomataNewTransition2(pctxt->am,
12852 			start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
12853 		    xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12854 		    pctxt->state =
12855 			xmlAutomataNewTransition2(pctxt->am,
12856 			start, NULL, BAD_CAST "*", NULL, wild);
12857 		    xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12858 		} else if (wild->nsSet != NULL) {
12859 		    ns = wild->nsSet;
12860 		    do {
12861 			pctxt->state =
12862 			    xmlAutomataNewTransition2(pctxt->am,
12863 				start, NULL, BAD_CAST "*", ns->value, wild);
12864 			xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12865 			ns = ns->next;
12866 		    } while (ns != NULL);
12867 
12868 		} else if (wild->negNsSet != NULL) {
12869 		    pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
12870 			start, hop, BAD_CAST "*", wild->negNsSet->value,
12871 			wild);
12872 		}
12873 		xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12874 		xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12875 	    }
12876 	    if (particle->minOccurs == 0) {
12877 		xmlAutomataNewEpsilon(pctxt->am, start, end);
12878                 ret = 1;
12879 	    }
12880 	    pctxt->state = end;
12881             break;
12882 	}
12883         case XML_SCHEMA_TYPE_ELEMENT:
12884 	    ret = xmlSchemaBuildContentModelForElement(pctxt, particle);
12885 	    break;
12886         case XML_SCHEMA_TYPE_SEQUENCE:{
12887             xmlSchemaTreeItemPtr sub;
12888 
12889             ret = 1;
12890             /*
12891              * If max and min occurances are default (1) then
12892              * simply iterate over the particles of the <sequence>.
12893              */
12894             if ((particle->minOccurs == 1) && (particle->maxOccurs == 1)) {
12895                 sub = particle->children->children;
12896 
12897                 while (sub != NULL) {
12898                     tmp2 = xmlSchemaBuildAContentModel(pctxt,
12899                                         (xmlSchemaParticlePtr) sub);
12900                     if (tmp2 != 1) ret = 0;
12901                     sub = sub->next;
12902                 }
12903             } else {
12904                 xmlAutomataStatePtr oldstate = pctxt->state;
12905 
12906                 if (particle->maxOccurs >= UNBOUNDED) {
12907                     if (particle->minOccurs > 1) {
12908                         xmlAutomataStatePtr tmp;
12909                         int counter;
12910 
12911                         pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12912                             oldstate, NULL);
12913                         oldstate = pctxt->state;
12914 
12915                         counter = xmlAutomataNewCounter(pctxt->am,
12916                             particle->minOccurs - 1, UNBOUNDED);
12917 
12918                         sub = particle->children->children;
12919                         while (sub != NULL) {
12920                             tmp2 = xmlSchemaBuildAContentModel(pctxt,
12921                                             (xmlSchemaParticlePtr) sub);
12922                             if (tmp2 != 1) ret = 0;
12923                             sub = sub->next;
12924                         }
12925                         tmp = pctxt->state;
12926                         xmlAutomataNewCountedTrans(pctxt->am, tmp,
12927                                                    oldstate, counter);
12928                         pctxt->state =
12929                             xmlAutomataNewCounterTrans(pctxt->am, tmp,
12930                                                        NULL, counter);
12931                         if (ret == 1)
12932                             xmlAutomataNewEpsilon(pctxt->am,
12933                                                 oldstate, pctxt->state);
12934 
12935                     } else {
12936                         pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12937                             oldstate, NULL);
12938                         oldstate = pctxt->state;
12939 
12940                         sub = particle->children->children;
12941                         while (sub != NULL) {
12942                             tmp2 = xmlSchemaBuildAContentModel(pctxt,
12943                                         (xmlSchemaParticlePtr) sub);
12944                             if (tmp2 != 1) ret = 0;
12945                             sub = sub->next;
12946                         }
12947                         xmlAutomataNewEpsilon(pctxt->am, pctxt->state,
12948                                               oldstate);
12949                         /*
12950                          * epsilon needed to block previous trans from
12951                          * being allowed to enter back from another
12952                          * construct
12953                          */
12954                         pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12955                                             pctxt->state, NULL);
12956                         if (particle->minOccurs == 0) {
12957                             xmlAutomataNewEpsilon(pctxt->am,
12958                                 oldstate, pctxt->state);
12959                             ret = 1;
12960                         }
12961                     }
12962                 } else if ((particle->maxOccurs > 1)
12963                            || (particle->minOccurs > 1)) {
12964                     xmlAutomataStatePtr tmp;
12965                     int counter;
12966 
12967                     pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12968                         oldstate, NULL);
12969                     oldstate = pctxt->state;
12970 
12971                     counter = xmlAutomataNewCounter(pctxt->am,
12972                         particle->minOccurs - 1,
12973                         particle->maxOccurs - 1);
12974 
12975                     sub = particle->children->children;
12976                     while (sub != NULL) {
12977                         tmp2 = xmlSchemaBuildAContentModel(pctxt,
12978                                         (xmlSchemaParticlePtr) sub);
12979                         if (tmp2 != 1) ret = 0;
12980                         sub = sub->next;
12981                     }
12982                     tmp = pctxt->state;
12983                     xmlAutomataNewCountedTrans(pctxt->am,
12984                         tmp, oldstate, counter);
12985                     pctxt->state =
12986                         xmlAutomataNewCounterTrans(pctxt->am, tmp, NULL,
12987                                                    counter);
12988                     if ((particle->minOccurs == 0) || (ret == 1)) {
12989                         xmlAutomataNewEpsilon(pctxt->am,
12990                                             oldstate, pctxt->state);
12991                         ret = 1;
12992                     }
12993                 } else {
12994                     sub = particle->children->children;
12995                     while (sub != NULL) {
12996                         tmp2 = xmlSchemaBuildAContentModel(pctxt,
12997                                         (xmlSchemaParticlePtr) sub);
12998                         if (tmp2 != 1) ret = 0;
12999                         sub = sub->next;
13000                     }
13001 
13002 		    /*
13003 		     * epsilon needed to block previous trans from
13004 		     * being allowed to enter back from another
13005 		     * construct
13006 		     */
13007 		    pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
13008 					pctxt->state, NULL);
13009 
13010                     if (particle->minOccurs == 0) {
13011                         xmlAutomataNewEpsilon(pctxt->am, oldstate,
13012                                               pctxt->state);
13013                         ret = 1;
13014                     }
13015                 }
13016             }
13017             break;
13018         }
13019         case XML_SCHEMA_TYPE_CHOICE:{
13020             xmlSchemaTreeItemPtr sub;
13021             xmlAutomataStatePtr start, end;
13022 
13023             ret = 0;
13024             start = pctxt->state;
13025             end = xmlAutomataNewState(pctxt->am);
13026 
13027             /*
13028              * iterate over the subtypes and remerge the end with an
13029              * epsilon transition
13030              */
13031             if (particle->maxOccurs == 1) {
13032                 sub = particle->children->children;
13033                 while (sub != NULL) {
13034                     pctxt->state = start;
13035                     tmp2 = xmlSchemaBuildAContentModel(pctxt,
13036                                         (xmlSchemaParticlePtr) sub);
13037                     if (tmp2 == 1) ret = 1;
13038                     xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
13039                     sub = sub->next;
13040                 }
13041             } else {
13042                 int counter;
13043                 xmlAutomataStatePtr hop, base;
13044                 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
13045                     UNBOUNDED : particle->maxOccurs - 1;
13046                 int minOccurs =
13047                     particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
13048 
13049                 /*
13050                  * use a counter to keep track of the number of transtions
13051                  * which went through the choice.
13052                  */
13053                 counter =
13054                     xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
13055                 hop = xmlAutomataNewState(pctxt->am);
13056                 base = xmlAutomataNewState(pctxt->am);
13057 
13058                 sub = particle->children->children;
13059                 while (sub != NULL) {
13060                     pctxt->state = base;
13061                     tmp2 = xmlSchemaBuildAContentModel(pctxt,
13062                                         (xmlSchemaParticlePtr) sub);
13063                     if (tmp2 == 1) ret = 1;
13064                     xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
13065                     sub = sub->next;
13066                 }
13067                 xmlAutomataNewEpsilon(pctxt->am, start, base);
13068                 xmlAutomataNewCountedTrans(pctxt->am, hop, base, counter);
13069                 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
13070                 if (ret == 1)
13071                     xmlAutomataNewEpsilon(pctxt->am, base, end);
13072             }
13073             if (particle->minOccurs == 0) {
13074                 xmlAutomataNewEpsilon(pctxt->am, start, end);
13075                 ret = 1;
13076             }
13077             pctxt->state = end;
13078             break;
13079         }
13080         case XML_SCHEMA_TYPE_ALL:{
13081             xmlAutomataStatePtr start, tmp;
13082             xmlSchemaParticlePtr sub;
13083             xmlSchemaElementPtr elemDecl;
13084 
13085             ret = 1;
13086 
13087             sub = (xmlSchemaParticlePtr) particle->children->children;
13088             if (sub == NULL)
13089                 break;
13090 
13091             ret = 0;
13092 
13093             start = pctxt->state;
13094             tmp = xmlAutomataNewState(pctxt->am);
13095             xmlAutomataNewEpsilon(pctxt->am, pctxt->state, tmp);
13096             pctxt->state = tmp;
13097             while (sub != NULL) {
13098                 pctxt->state = tmp;
13099 
13100                 elemDecl = (xmlSchemaElementPtr) sub->children;
13101                 if (elemDecl == NULL) {
13102                     PERROR_INT("xmlSchemaBuildAContentModel",
13103                         "<element> particle has no term");
13104                     return(ret);
13105                 };
13106                 /*
13107                 * NOTE: The {max occurs} of all the particles in the
13108                 * {particles} of the group must be 0 or 1; this is
13109                 * already ensured during the parse of the content of
13110                 * <all>.
13111                 */
13112                 if (elemDecl->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
13113                     int counter;
13114 
13115                     /*
13116                      * This is an abstract group, we need to share
13117                      * the same counter for all the element transitions
13118                      * derived from the group
13119                      */
13120                     counter = xmlAutomataNewCounter(pctxt->am,
13121                                        sub->minOccurs, sub->maxOccurs);
13122                     xmlSchemaBuildContentModelForSubstGroup(pctxt,
13123                                        sub, counter, pctxt->state);
13124                 } else {
13125                     if ((sub->minOccurs == 1) &&
13126                         (sub->maxOccurs == 1)) {
13127                         xmlAutomataNewOnceTrans2(pctxt->am, pctxt->state,
13128                                                 pctxt->state,
13129                                                 elemDecl->name,
13130                                                 elemDecl->targetNamespace,
13131                                                 1, 1, elemDecl);
13132                     } else if ((sub->minOccurs == 0) &&
13133                         (sub->maxOccurs == 1)) {
13134 
13135                         xmlAutomataNewCountTrans2(pctxt->am, pctxt->state,
13136                                                  pctxt->state,
13137                                                  elemDecl->name,
13138                                                  elemDecl->targetNamespace,
13139                                                  0,
13140                                                  1,
13141                                                  elemDecl);
13142                     }
13143                 }
13144                 sub = (xmlSchemaParticlePtr) sub->next;
13145             }
13146             pctxt->state =
13147                 xmlAutomataNewAllTrans(pctxt->am, pctxt->state, NULL, 0);
13148             if (particle->minOccurs == 0) {
13149                 xmlAutomataNewEpsilon(pctxt->am, start, pctxt->state);
13150                 ret = 1;
13151             }
13152             break;
13153         }
13154 	case XML_SCHEMA_TYPE_GROUP:
13155 	    /*
13156 	    * If we hit a model group definition, then this means that
13157 	    * it was empty, thus was not substituted for the containing
13158 	    * model group. Just do nothing in this case.
13159 	    * TODO: But the group should be substituted and not occur at
13160 	    * all in the content model at this point. Fix this.
13161 	    */
13162             ret = 1;
13163 	    break;
13164         default:
13165 	    xmlSchemaInternalErr2(ACTXT_CAST pctxt,
13166 		"xmlSchemaBuildAContentModel",
13167 		"found unexpected term of type '%s' in content model",
13168 		WXS_ITEM_TYPE_NAME(particle->children), NULL);
13169             return(ret);
13170     }
13171     return(ret);
13172 }
13173 
13174 /**
13175  * xmlSchemaBuildContentModel:
13176  * @ctxt:  the schema parser context
13177  * @type:  the complex type definition
13178  * @name:  the element name
13179  *
13180  * Builds the content model of the complex type.
13181  */
13182 static void
xmlSchemaBuildContentModel(xmlSchemaTypePtr type,xmlSchemaParserCtxtPtr ctxt)13183 xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
13184 			   xmlSchemaParserCtxtPtr ctxt)
13185 {
13186     if ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
13187 	(type->contModel != NULL) ||
13188 	((type->contentType != XML_SCHEMA_CONTENT_ELEMENTS) &&
13189 	(type->contentType != XML_SCHEMA_CONTENT_MIXED)))
13190 	return;
13191 
13192 #ifdef DEBUG_CONTENT
13193     xmlGenericError(xmlGenericErrorContext,
13194                     "Building content model for %s\n", name);
13195 #endif
13196     ctxt->am = NULL;
13197     ctxt->am = xmlNewAutomata();
13198     if (ctxt->am == NULL) {
13199         xmlGenericError(xmlGenericErrorContext,
13200 	    "Cannot create automata for complex type %s\n", type->name);
13201         return;
13202     }
13203     ctxt->state = xmlAutomataGetInitState(ctxt->am);
13204     /*
13205     * Build the automaton.
13206     */
13207     xmlSchemaBuildAContentModel(ctxt, WXS_TYPE_PARTICLE(type));
13208     xmlAutomataSetFinalState(ctxt->am, ctxt->state);
13209     type->contModel = xmlAutomataCompile(ctxt->am);
13210     if (type->contModel == NULL) {
13211         xmlSchemaPCustomErr(ctxt,
13212 	    XML_SCHEMAP_INTERNAL,
13213 	    WXS_BASIC_CAST type, type->node,
13214 	    "Failed to compile the content model", NULL);
13215     } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
13216         xmlSchemaPCustomErr(ctxt,
13217 	    XML_SCHEMAP_NOT_DETERMINISTIC,
13218 	    /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
13219 	    WXS_BASIC_CAST type, type->node,
13220 	    "The content model is not determinist", NULL);
13221     } else {
13222 #ifdef DEBUG_CONTENT_REGEXP
13223         xmlGenericError(xmlGenericErrorContext,
13224                         "Content model of %s:\n", type->name);
13225         xmlRegexpPrint(stderr, type->contModel);
13226 #endif
13227     }
13228     ctxt->state = NULL;
13229     xmlFreeAutomata(ctxt->am);
13230     ctxt->am = NULL;
13231 }
13232 
13233 /**
13234  * xmlSchemaResolveElementReferences:
13235  * @elem:  the schema element context
13236  * @ctxt:  the schema parser context
13237  *
13238  * Resolves the references of an element declaration
13239  * or particle, which has an element declaration as it's
13240  * term.
13241  */
13242 static void
xmlSchemaResolveElementReferences(xmlSchemaElementPtr elemDecl,xmlSchemaParserCtxtPtr ctxt)13243 xmlSchemaResolveElementReferences(xmlSchemaElementPtr elemDecl,
13244 				  xmlSchemaParserCtxtPtr ctxt)
13245 {
13246     if ((ctxt == NULL) || (elemDecl == NULL) ||
13247 	((elemDecl != NULL) &&
13248 	(elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
13249         return;
13250     elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
13251 
13252     if ((elemDecl->subtypes == NULL) && (elemDecl->namedType != NULL)) {
13253 	xmlSchemaTypePtr type;
13254 
13255 	/* (type definition) ... otherwise the type definition `resolved`
13256 	* to by the `actual value` of the type [attribute] ...
13257 	*/
13258 	type = xmlSchemaGetType(ctxt->schema, elemDecl->namedType,
13259 	    elemDecl->namedTypeNs);
13260 	if (type == NULL) {
13261 	    xmlSchemaPResCompAttrErr(ctxt,
13262 		XML_SCHEMAP_SRC_RESOLVE,
13263 		WXS_BASIC_CAST elemDecl, elemDecl->node,
13264 		"type", elemDecl->namedType, elemDecl->namedTypeNs,
13265 		XML_SCHEMA_TYPE_BASIC, "type definition");
13266 	} else
13267 	    elemDecl->subtypes = type;
13268     }
13269     if (elemDecl->substGroup != NULL) {
13270 	xmlSchemaElementPtr substHead;
13271 
13272 	/*
13273 	* FIXME TODO: Do we need a new field in _xmlSchemaElement for
13274 	* substitutionGroup?
13275 	*/
13276 	substHead = xmlSchemaGetElem(ctxt->schema, elemDecl->substGroup,
13277 	    elemDecl->substGroupNs);
13278 	if (substHead == NULL) {
13279 	    xmlSchemaPResCompAttrErr(ctxt,
13280 		XML_SCHEMAP_SRC_RESOLVE,
13281 		WXS_BASIC_CAST elemDecl, NULL,
13282 		"substitutionGroup", elemDecl->substGroup,
13283 		elemDecl->substGroupNs, XML_SCHEMA_TYPE_ELEMENT, NULL);
13284 	} else {
13285 	    xmlSchemaResolveElementReferences(substHead, ctxt);
13286 	    /*
13287 	    * Set the "substitution group affiliation".
13288 	    * NOTE that now we use the "refDecl" field for this.
13289 	    */
13290 	    WXS_SUBST_HEAD(elemDecl) = substHead;
13291 	    /*
13292 	    * The type definitions is set to:
13293 	    * SPEC "...the {type definition} of the element
13294 	    * declaration `resolved` to by the `actual value`
13295 	    * of the substitutionGroup [attribute], if present"
13296 	    */
13297 	    if (elemDecl->subtypes == NULL)
13298 		elemDecl->subtypes = substHead->subtypes;
13299 	}
13300     }
13301     /*
13302     * SPEC "The definition of anyType serves as the default type definition
13303     * for element declarations whose XML representation does not specify one."
13304     */
13305     if ((elemDecl->subtypes == NULL) &&
13306 	(elemDecl->namedType == NULL) &&
13307 	(elemDecl->substGroup == NULL))
13308 	elemDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
13309 }
13310 
13311 /**
13312  * xmlSchemaResolveUnionMemberTypes:
13313  * @ctxt:  the schema parser context
13314  * @type:  the schema simple type definition
13315  *
13316  * Checks and builds the "member type definitions" property of the union
13317  * simple type. This handles part (1), part (2) is done in
13318  * xmlSchemaFinishMemberTypeDefinitionsProperty()
13319  *
13320  * Returns -1 in case of an internal error, 0 otherwise.
13321  */
13322 static int
xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,xmlSchemaTypePtr type)13323 xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,
13324 				 xmlSchemaTypePtr type)
13325 {
13326 
13327     xmlSchemaTypeLinkPtr link, lastLink, newLink;
13328     xmlSchemaTypePtr memberType;
13329 
13330     /*
13331     * SPEC (1) "If the <union> alternative is chosen, then [Definition:]
13332     * define the explicit members as the type definitions `resolved`
13333     * to by the items in the `actual value` of the memberTypes [attribute],
13334     * if any, followed by the type definitions corresponding to the
13335     * <simpleType>s among the [children] of <union>, if any."
13336     */
13337     /*
13338     * Resolve references.
13339     */
13340     link = type->memberTypes;
13341     lastLink = NULL;
13342     while (link != NULL) {
13343 	const xmlChar *name, *nsName;
13344 
13345 	name = ((xmlSchemaQNameRefPtr) link->type)->name;
13346 	nsName = ((xmlSchemaQNameRefPtr) link->type)->targetNamespace;
13347 
13348 	memberType = xmlSchemaGetType(ctxt->schema, name, nsName);
13349 	if ((memberType == NULL) || (! WXS_IS_SIMPLE(memberType))) {
13350 	    xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
13351 		WXS_BASIC_CAST type, type->node, "memberTypes",
13352 		name, nsName, XML_SCHEMA_TYPE_SIMPLE, NULL);
13353 	    /*
13354 	    * Remove the member type link.
13355 	    */
13356 	    if (lastLink == NULL)
13357 		type->memberTypes = link->next;
13358 	    else
13359 		lastLink->next = link->next;
13360 	    newLink = link;
13361 	    link = link->next;
13362 	    xmlFree(newLink);
13363 	} else {
13364 	    link->type = memberType;
13365 	    lastLink = link;
13366 	    link = link->next;
13367 	}
13368     }
13369     /*
13370     * Add local simple types,
13371     */
13372     memberType = type->subtypes;
13373     while (memberType != NULL) {
13374 	link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
13375 	if (link == NULL) {
13376 	    xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
13377 	    return (-1);
13378 	}
13379 	link->type = memberType;
13380 	link->next = NULL;
13381 	if (lastLink == NULL)
13382 	    type->memberTypes = link;
13383 	else
13384 	    lastLink->next = link;
13385 	lastLink = link;
13386 	memberType = memberType->next;
13387     }
13388     return (0);
13389 }
13390 
13391 /**
13392  * xmlSchemaIsDerivedFromBuiltInType:
13393  * @ctxt:  the schema parser context
13394  * @type:  the type definition
13395  * @valType: the value type
13396  *
13397  *
13398  * Returns 1 if the type has the given value type, or
13399  * is derived from such a type.
13400  */
13401 static int
xmlSchemaIsDerivedFromBuiltInType(xmlSchemaTypePtr type,int valType)13402 xmlSchemaIsDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
13403 {
13404     if (type == NULL)
13405 	return (0);
13406     if (WXS_IS_COMPLEX(type))
13407 	return (0);
13408     if (type->type == XML_SCHEMA_TYPE_BASIC) {
13409 	if (type->builtInType == valType)
13410 	    return(1);
13411 	if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13412 	    (type->builtInType == XML_SCHEMAS_ANYTYPE))
13413 	    return (0);
13414 	return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13415     }
13416     return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13417 }
13418 
13419 #if 0
13420 /**
13421  * xmlSchemaIsDerivedFromBuiltInType:
13422  * @ctxt:  the schema parser context
13423  * @type:  the type definition
13424  * @valType: the value type
13425  *
13426  *
13427  * Returns 1 if the type has the given value type, or
13428  * is derived from such a type.
13429  */
13430 static int
13431 xmlSchemaIsUserDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
13432 {
13433     if (type == NULL)
13434 	return (0);
13435     if (WXS_IS_COMPLEX(type))
13436 	return (0);
13437     if (type->type == XML_SCHEMA_TYPE_BASIC) {
13438 	if (type->builtInType == valType)
13439 	    return(1);
13440 	return (0);
13441     } else
13442 	return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13443 
13444     return (0);
13445 }
13446 
13447 static xmlSchemaTypePtr
13448 xmlSchemaQueryBuiltInType(xmlSchemaTypePtr type)
13449 {
13450     if (type == NULL)
13451 	return (NULL);
13452     if (WXS_IS_COMPLEX(type))
13453 	return (NULL);
13454     if (type->type == XML_SCHEMA_TYPE_BASIC)
13455 	return(type);
13456     return(xmlSchemaQueryBuiltInType(type->subtypes));
13457 }
13458 #endif
13459 
13460 /**
13461  * xmlSchemaGetPrimitiveType:
13462  * @type:  the simpleType definition
13463  *
13464  * Returns the primitive type of the given type or
13465  * NULL in case of error.
13466  */
13467 static xmlSchemaTypePtr
xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)13468 xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
13469 {
13470 
13471     while (type != NULL) {
13472 	/*
13473 	* Note that anySimpleType is actually not a primitive type
13474 	* but we need that here.
13475 	*/
13476 	if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13477 	   (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
13478 	    return (type);
13479 	type = type->baseType;
13480     }
13481 
13482     return (NULL);
13483 }
13484 
13485 #if 0
13486 /**
13487  * xmlSchemaGetBuiltInTypeAncestor:
13488  * @type:  the simpleType definition
13489  *
13490  * Returns the primitive type of the given type or
13491  * NULL in case of error.
13492  */
13493 static xmlSchemaTypePtr
13494 xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
13495 {
13496     if (WXS_IS_LIST(type) || WXS_IS_UNION(type))
13497 	return (0);
13498     while (type != NULL) {
13499 	if (type->type == XML_SCHEMA_TYPE_BASIC)
13500 	    return (type);
13501 	type = type->baseType;
13502     }
13503 
13504     return (NULL);
13505 }
13506 #endif
13507 
13508 /**
13509  * xmlSchemaCloneWildcardNsConstraints:
13510  * @ctxt:  the schema parser context
13511  * @dest:  the destination wildcard
13512  * @source: the source wildcard
13513  *
13514  * Clones the namespace constraints of source
13515  * and assignes them to dest.
13516  * Returns -1 on internal error, 0 otherwise.
13517  */
13518 static int
xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,xmlSchemaWildcardPtr dest,xmlSchemaWildcardPtr source)13519 xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
13520 				    xmlSchemaWildcardPtr dest,
13521 				    xmlSchemaWildcardPtr source)
13522 {
13523     xmlSchemaWildcardNsPtr cur, tmp, last;
13524 
13525     if ((source == NULL) || (dest == NULL))
13526 	return(-1);
13527     dest->any = source->any;
13528     cur = source->nsSet;
13529     last = NULL;
13530     while (cur != NULL) {
13531 	tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
13532 	if (tmp == NULL)
13533 	    return(-1);
13534 	tmp->value = cur->value;
13535 	if (last == NULL)
13536 	    dest->nsSet = tmp;
13537 	else
13538 	    last->next = tmp;
13539 	last = tmp;
13540 	cur = cur->next;
13541     }
13542     if (dest->negNsSet != NULL)
13543 	xmlSchemaFreeWildcardNsSet(dest->negNsSet);
13544     if (source->negNsSet != NULL) {
13545 	dest->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13546 	if (dest->negNsSet == NULL)
13547 	    return(-1);
13548 	dest->negNsSet->value = source->negNsSet->value;
13549     } else
13550 	dest->negNsSet = NULL;
13551     return(0);
13552 }
13553 
13554 /**
13555  * xmlSchemaUnionWildcards:
13556  * @ctxt:  the schema parser context
13557  * @completeWild:  the first wildcard
13558  * @curWild: the second wildcard
13559  *
13560  * Unions the namespace constraints of the given wildcards.
13561  * @completeWild will hold the resulting union.
13562  * Returns a positive error code on failure, -1 in case of an
13563  * internal error, 0 otherwise.
13564  */
13565 static int
xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,xmlSchemaWildcardPtr completeWild,xmlSchemaWildcardPtr curWild)13566 xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
13567 			    xmlSchemaWildcardPtr completeWild,
13568 			    xmlSchemaWildcardPtr curWild)
13569 {
13570     xmlSchemaWildcardNsPtr cur, curB, tmp;
13571 
13572     /*
13573     * 1 If O1 and O2 are the same value, then that value must be the
13574     * value.
13575     */
13576     if ((completeWild->any == curWild->any) &&
13577 	((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13578 	((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
13579 
13580 	if ((completeWild->negNsSet == NULL) ||
13581 	    (completeWild->negNsSet->value == curWild->negNsSet->value)) {
13582 
13583 	    if (completeWild->nsSet != NULL) {
13584 		int found = 0;
13585 
13586 		/*
13587 		* Check equality of sets.
13588 		*/
13589 		cur = completeWild->nsSet;
13590 		while (cur != NULL) {
13591 		    found = 0;
13592 		    curB = curWild->nsSet;
13593 		    while (curB != NULL) {
13594 			if (cur->value == curB->value) {
13595 			    found = 1;
13596 			    break;
13597 			}
13598 			curB = curB->next;
13599 		    }
13600 		    if (!found)
13601 			break;
13602 		    cur = cur->next;
13603 		}
13604 		if (found)
13605 		    return(0);
13606 	    } else
13607 		return(0);
13608 	}
13609     }
13610     /*
13611     * 2 If either O1 or O2 is any, then any must be the value
13612     */
13613     if (completeWild->any != curWild->any) {
13614 	if (completeWild->any == 0) {
13615 	    completeWild->any = 1;
13616 	    if (completeWild->nsSet != NULL) {
13617 		xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13618 		completeWild->nsSet = NULL;
13619 	    }
13620 	    if (completeWild->negNsSet != NULL) {
13621 		xmlFree(completeWild->negNsSet);
13622 		completeWild->negNsSet = NULL;
13623 	    }
13624 	}
13625 	return (0);
13626     }
13627     /*
13628     * 3 If both O1 and O2 are sets of (namespace names or `absent`),
13629     * then the union of those sets must be the value.
13630     */
13631     if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
13632 	int found;
13633 	xmlSchemaWildcardNsPtr start;
13634 
13635 	cur = curWild->nsSet;
13636 	start = completeWild->nsSet;
13637 	while (cur != NULL) {
13638 	    found = 0;
13639 	    curB = start;
13640 	    while (curB != NULL) {
13641 		if (cur->value == curB->value) {
13642 		    found = 1;
13643 		    break;
13644 		}
13645 		curB = curB->next;
13646 	    }
13647 	    if (!found) {
13648 		tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
13649 		if (tmp == NULL)
13650 		    return (-1);
13651 		tmp->value = cur->value;
13652 		tmp->next = completeWild->nsSet;
13653 		completeWild->nsSet = tmp;
13654 	    }
13655 	    cur = cur->next;
13656 	}
13657 
13658 	return(0);
13659     }
13660     /*
13661     * 4 If the two are negations of different values (namespace names
13662     * or `absent`), then a pair of not and `absent` must be the value.
13663     */
13664     if ((completeWild->negNsSet != NULL) &&
13665 	(curWild->negNsSet != NULL) &&
13666 	(completeWild->negNsSet->value != curWild->negNsSet->value)) {
13667 	completeWild->negNsSet->value = NULL;
13668 
13669 	return(0);
13670     }
13671     /*
13672      * 5.
13673      */
13674     if (((completeWild->negNsSet != NULL) &&
13675 	(completeWild->negNsSet->value != NULL) &&
13676 	(curWild->nsSet != NULL)) ||
13677 	((curWild->negNsSet != NULL) &&
13678 	(curWild->negNsSet->value != NULL) &&
13679 	(completeWild->nsSet != NULL))) {
13680 
13681 	int nsFound, absentFound = 0;
13682 
13683 	if (completeWild->nsSet != NULL) {
13684 	    cur = completeWild->nsSet;
13685 	    curB = curWild->negNsSet;
13686 	} else {
13687 	    cur = curWild->nsSet;
13688 	    curB = completeWild->negNsSet;
13689 	}
13690 	nsFound = 0;
13691 	while (cur != NULL) {
13692 	    if (cur->value == NULL)
13693 		absentFound = 1;
13694 	    else if (cur->value == curB->value)
13695 		nsFound = 1;
13696 	    if (nsFound && absentFound)
13697 		break;
13698 	    cur = cur->next;
13699 	}
13700 
13701 	if (nsFound && absentFound) {
13702 	    /*
13703 	    * 5.1 If the set S includes both the negated namespace
13704 	    * name and `absent`, then any must be the value.
13705 	    */
13706 	    completeWild->any = 1;
13707 	    if (completeWild->nsSet != NULL) {
13708 		xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13709 		completeWild->nsSet = NULL;
13710 	    }
13711 	    if (completeWild->negNsSet != NULL) {
13712 		xmlFree(completeWild->negNsSet);
13713 		completeWild->negNsSet = NULL;
13714 	    }
13715 	} else if (nsFound && (!absentFound)) {
13716 	    /*
13717 	    * 5.2 If the set S includes the negated namespace name
13718 	    * but not `absent`, then a pair of not and `absent` must
13719 	    * be the value.
13720 	    */
13721 	    if (completeWild->nsSet != NULL) {
13722 		xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13723 		completeWild->nsSet = NULL;
13724 	    }
13725 	    if (completeWild->negNsSet == NULL) {
13726 		completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13727 		if (completeWild->negNsSet == NULL)
13728 		    return (-1);
13729 	    }
13730 	    completeWild->negNsSet->value = NULL;
13731 	} else if ((!nsFound) && absentFound) {
13732 	    /*
13733 	    * 5.3 If the set S includes `absent` but not the negated
13734 	    * namespace name, then the union is not expressible.
13735 	    */
13736 	    xmlSchemaPErr(ctxt, completeWild->node,
13737 		XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
13738 		"The union of the wilcard is not expressible.\n",
13739 		NULL, NULL);
13740 	    return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
13741 	} else if ((!nsFound) && (!absentFound)) {
13742 	    /*
13743 	    * 5.4 If the set S does not include either the negated namespace
13744 	    * name or `absent`, then whichever of O1 or O2 is a pair of not
13745 	    * and a namespace name must be the value.
13746 	    */
13747 	    if (completeWild->negNsSet == NULL) {
13748 		if (completeWild->nsSet != NULL) {
13749 		    xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13750 		    completeWild->nsSet = NULL;
13751 		}
13752 		completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13753 		if (completeWild->negNsSet == NULL)
13754 		    return (-1);
13755 		completeWild->negNsSet->value = curWild->negNsSet->value;
13756 	    }
13757 	}
13758 	return (0);
13759     }
13760     /*
13761      * 6.
13762      */
13763     if (((completeWild->negNsSet != NULL) &&
13764 	(completeWild->negNsSet->value == NULL) &&
13765 	(curWild->nsSet != NULL)) ||
13766 	((curWild->negNsSet != NULL) &&
13767 	(curWild->negNsSet->value == NULL) &&
13768 	(completeWild->nsSet != NULL))) {
13769 
13770 	if (completeWild->nsSet != NULL) {
13771 	    cur = completeWild->nsSet;
13772 	} else {
13773 	    cur = curWild->nsSet;
13774 	}
13775 	while (cur != NULL) {
13776 	    if (cur->value == NULL) {
13777 		/*
13778 		* 6.1 If the set S includes `absent`, then any must be the
13779 		* value.
13780 		*/
13781 		completeWild->any = 1;
13782 		if (completeWild->nsSet != NULL) {
13783 		    xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13784 		    completeWild->nsSet = NULL;
13785 		}
13786 		if (completeWild->negNsSet != NULL) {
13787 		    xmlFree(completeWild->negNsSet);
13788 		    completeWild->negNsSet = NULL;
13789 		}
13790 		return (0);
13791 	    }
13792 	    cur = cur->next;
13793 	}
13794 	if (completeWild->negNsSet == NULL) {
13795 	    /*
13796 	    * 6.2 If the set S does not include `absent`, then a pair of not
13797 	    * and `absent` must be the value.
13798 	    */
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 = NULL;
13807 	}
13808 	return (0);
13809     }
13810     return (0);
13811 
13812 }
13813 
13814 /**
13815  * xmlSchemaIntersectWildcards:
13816  * @ctxt:  the schema parser context
13817  * @completeWild:  the first wildcard
13818  * @curWild: the second wildcard
13819  *
13820  * Intersects the namespace constraints of the given wildcards.
13821  * @completeWild will hold the resulting intersection.
13822  * Returns a positive error code on failure, -1 in case of an
13823  * internal error, 0 otherwise.
13824  */
13825 static int
xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,xmlSchemaWildcardPtr completeWild,xmlSchemaWildcardPtr curWild)13826 xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
13827 			    xmlSchemaWildcardPtr completeWild,
13828 			    xmlSchemaWildcardPtr curWild)
13829 {
13830     xmlSchemaWildcardNsPtr cur, curB, prev,  tmp;
13831 
13832     /*
13833     * 1 If O1 and O2 are the same value, then that value must be the
13834     * value.
13835     */
13836     if ((completeWild->any == curWild->any) &&
13837 	((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13838 	((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
13839 
13840 	if ((completeWild->negNsSet == NULL) ||
13841 	    (completeWild->negNsSet->value == curWild->negNsSet->value)) {
13842 
13843 	    if (completeWild->nsSet != NULL) {
13844 		int found = 0;
13845 
13846 		/*
13847 		* Check equality of sets.
13848 		*/
13849 		cur = completeWild->nsSet;
13850 		while (cur != NULL) {
13851 		    found = 0;
13852 		    curB = curWild->nsSet;
13853 		    while (curB != NULL) {
13854 			if (cur->value == curB->value) {
13855 			    found = 1;
13856 			    break;
13857 			}
13858 			curB = curB->next;
13859 		    }
13860 		    if (!found)
13861 			break;
13862 		    cur = cur->next;
13863 		}
13864 		if (found)
13865 		    return(0);
13866 	    } else
13867 		return(0);
13868 	}
13869     }
13870     /*
13871     * 2 If either O1 or O2 is any, then the other must be the value.
13872     */
13873     if ((completeWild->any != curWild->any) && (completeWild->any)) {
13874 	if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
13875 	    return(-1);
13876 	return(0);
13877     }
13878     /*
13879     * 3 If either O1 or O2 is a pair of not and a value (a namespace
13880     * name or `absent`) and the other is a set of (namespace names or
13881     * `absent`), then that set, minus the negated value if it was in
13882     * the set, minus `absent` if it was in the set, must be the value.
13883     */
13884     if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
13885 	((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
13886 	const xmlChar *neg;
13887 
13888 	if (completeWild->nsSet == NULL) {
13889 	    neg = completeWild->negNsSet->value;
13890 	    if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
13891 		return(-1);
13892 	} else
13893 	    neg = curWild->negNsSet->value;
13894 	/*
13895 	* Remove absent and negated.
13896 	*/
13897 	prev = NULL;
13898 	cur = completeWild->nsSet;
13899 	while (cur != NULL) {
13900 	    if (cur->value == NULL) {
13901 		if (prev == NULL)
13902 		    completeWild->nsSet = cur->next;
13903 		else
13904 		    prev->next = cur->next;
13905 		xmlFree(cur);
13906 		break;
13907 	    }
13908 	    prev = cur;
13909 	    cur = cur->next;
13910 	}
13911 	if (neg != NULL) {
13912 	    prev = NULL;
13913 	    cur = completeWild->nsSet;
13914 	    while (cur != NULL) {
13915 		if (cur->value == neg) {
13916 		    if (prev == NULL)
13917 			completeWild->nsSet = cur->next;
13918 		    else
13919 			prev->next = cur->next;
13920 		    xmlFree(cur);
13921 		    break;
13922 		}
13923 		prev = cur;
13924 		cur = cur->next;
13925 	    }
13926 	}
13927 
13928 	return(0);
13929     }
13930     /*
13931     * 4 If both O1 and O2 are sets of (namespace names or `absent`),
13932     * then the intersection of those sets must be the value.
13933     */
13934     if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
13935 	int found;
13936 
13937 	cur = completeWild->nsSet;
13938 	prev = NULL;
13939 	while (cur != NULL) {
13940 	    found = 0;
13941 	    curB = curWild->nsSet;
13942 	    while (curB != NULL) {
13943 		if (cur->value == curB->value) {
13944 		    found = 1;
13945 		    break;
13946 		}
13947 		curB = curB->next;
13948 	    }
13949 	    if (!found) {
13950 		if (prev == NULL)
13951 		    completeWild->nsSet = cur->next;
13952 		else
13953 		    prev->next = cur->next;
13954 		tmp = cur->next;
13955 		xmlFree(cur);
13956 		cur = tmp;
13957 		continue;
13958 	    }
13959 	    prev = cur;
13960 	    cur = cur->next;
13961 	}
13962 
13963 	return(0);
13964     }
13965     /* 5 If the two are negations of different namespace names,
13966     * then the intersection is not expressible
13967     */
13968     if ((completeWild->negNsSet != NULL) &&
13969 	(curWild->negNsSet != NULL) &&
13970 	(completeWild->negNsSet->value != curWild->negNsSet->value) &&
13971 	(completeWild->negNsSet->value != NULL) &&
13972 	(curWild->negNsSet->value != NULL)) {
13973 
13974 	xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
13975 	    "The intersection of the wilcard is not expressible.\n",
13976 	    NULL, NULL);
13977 	return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
13978     }
13979     /*
13980     * 6 If the one is a negation of a namespace name and the other
13981     * is a negation of `absent`, then the one which is the negation
13982     * of a namespace name must be the value.
13983     */
13984     if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
13985 	(completeWild->negNsSet->value != curWild->negNsSet->value) &&
13986 	(completeWild->negNsSet->value == NULL)) {
13987 	completeWild->negNsSet->value =  curWild->negNsSet->value;
13988     }
13989     return(0);
13990 }
13991 
13992 /**
13993  * xmlSchemaIsWildcardNsConstraintSubset:
13994  * @ctxt:  the schema parser context
13995  * @sub:  the first wildcard
13996  * @super: the second wildcard
13997  *
13998  * Schema Component Constraint: Wildcard Subset (cos-ns-subset)
13999  *
14000  * Returns 0 if the namespace constraint of @sub is an intensional
14001  * subset of @super, 1 otherwise.
14002  */
14003 static int
xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub,xmlSchemaWildcardPtr super)14004 xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub,
14005 			  xmlSchemaWildcardPtr super)
14006 {
14007     /*
14008     * 1 super must be any.
14009     */
14010     if (super->any)
14011 	return (0);
14012     /*
14013     * 2.1 sub must be a pair of not and a namespace name or `absent`.
14014     * 2.2 super must be a pair of not and the same value.
14015     */
14016     if ((sub->negNsSet != NULL) &&
14017 	(super->negNsSet != NULL) &&
14018 	(sub->negNsSet->value == super->negNsSet->value))
14019 	return (0);
14020     /*
14021     * 3.1 sub must be a set whose members are either namespace names or `absent`.
14022     */
14023     if (sub->nsSet != NULL) {
14024 	/*
14025 	* 3.2.1 super must be the same set or a superset thereof.
14026 	*/
14027 	if (super->nsSet != NULL) {
14028 	    xmlSchemaWildcardNsPtr cur, curB;
14029 	    int found = 0;
14030 
14031 	    cur = sub->nsSet;
14032 	    while (cur != NULL) {
14033 		found = 0;
14034 		curB = super->nsSet;
14035 		while (curB != NULL) {
14036 		    if (cur->value == curB->value) {
14037 			found = 1;
14038 			break;
14039 		    }
14040 		    curB = curB->next;
14041 		}
14042 		if (!found)
14043 		    return (1);
14044 		cur = cur->next;
14045 	    }
14046 	    if (found)
14047 		return (0);
14048 	} else if (super->negNsSet != NULL) {
14049 	    xmlSchemaWildcardNsPtr cur;
14050 	    /*
14051 	    * 3.2.2 super must be a pair of not and a namespace name or
14052 	    * `absent` and that value must not be in sub's set.
14053 	    */
14054 	    cur = sub->nsSet;
14055 	    while (cur != NULL) {
14056 		if (cur->value == super->negNsSet->value)
14057 		    return (1);
14058 		cur = cur->next;
14059 	    }
14060 	    return (0);
14061 	}
14062     }
14063     return (1);
14064 }
14065 
14066 static int
xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributeUsePtr attruse,int * fixed,const xmlChar ** value,xmlSchemaValPtr * val)14067 xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributeUsePtr attruse,
14068 				     int *fixed,
14069 				     const xmlChar **value,
14070 				     xmlSchemaValPtr *val)
14071 {
14072     *fixed = 0;
14073     *value = NULL;
14074     if (val != 0)
14075 	*val = NULL;
14076 
14077     if (attruse->defValue != NULL) {
14078 	*value = attruse->defValue;
14079 	if (val != NULL)
14080 	    *val = attruse->defVal;
14081 	if (attruse->flags & XML_SCHEMA_ATTR_USE_FIXED)
14082 	    *fixed = 1;
14083 	return(1);
14084     } else if ((attruse->attrDecl != NULL) &&
14085 	(attruse->attrDecl->defValue != NULL)) {
14086 	*value = attruse->attrDecl->defValue;
14087 	if (val != NULL)
14088 	    *val = attruse->attrDecl->defVal;
14089 	if (attruse->attrDecl->flags & XML_SCHEMAS_ATTR_FIXED)
14090 	    *fixed = 1;
14091 	return(1);
14092     }
14093     return(0);
14094 }
14095 /**
14096  * xmlSchemaCheckCVCWildcardNamespace:
14097  * @wild:  the wildcard
14098  * @ns:  the namespace
14099  *
14100  * Validation Rule: Wildcard allows Namespace Name
14101  * (cvc-wildcard-namespace)
14102  *
14103  * Returns 0 if the given namespace matches the wildcard,
14104  * 1 otherwise and -1 on API errors.
14105  */
14106 static int
xmlSchemaCheckCVCWildcardNamespace(xmlSchemaWildcardPtr wild,const xmlChar * ns)14107 xmlSchemaCheckCVCWildcardNamespace(xmlSchemaWildcardPtr wild,
14108 				   const xmlChar* ns)
14109 {
14110     if (wild == NULL)
14111 	return(-1);
14112 
14113     if (wild->any)
14114 	return(0);
14115     else if (wild->nsSet != NULL) {
14116 	xmlSchemaWildcardNsPtr cur;
14117 
14118 	cur = wild->nsSet;
14119 	while (cur != NULL) {
14120 	    if (xmlStrEqual(cur->value, ns))
14121 		return(0);
14122 	    cur = cur->next;
14123 	}
14124     } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
14125 	(!xmlStrEqual(wild->negNsSet->value, ns)))
14126 	return(0);
14127 
14128     return(1);
14129 }
14130 
14131 #define XML_SCHEMA_ACTION_DERIVE 0
14132 #define XML_SCHEMA_ACTION_REDEFINE 1
14133 
14134 #define WXS_ACTION_STR(a) \
14135 ((a) == XML_SCHEMA_ACTION_DERIVE) ? (const xmlChar *) "base" : (const xmlChar *) "redefined"
14136 
14137 /*
14138 * Schema Component Constraint:
14139 *   Derivation Valid (Restriction, Complex)
14140 *   derivation-ok-restriction (2) - (4)
14141 *
14142 * ATTENTION:
14143 * In XML Schema 1.1 this will be:
14144 * Validation Rule:
14145 *     Checking complex type subsumption (practicalSubsumption) (1, 2 and 3)
14146 *
14147 */
14148 static int
xmlSchemaCheckDerivationOKRestriction2to4(xmlSchemaParserCtxtPtr pctxt,int action,xmlSchemaBasicItemPtr item,xmlSchemaBasicItemPtr baseItem,xmlSchemaItemListPtr uses,xmlSchemaItemListPtr baseUses,xmlSchemaWildcardPtr wild,xmlSchemaWildcardPtr baseWild)14149 xmlSchemaCheckDerivationOKRestriction2to4(xmlSchemaParserCtxtPtr pctxt,
14150 				       int action,
14151 				       xmlSchemaBasicItemPtr item,
14152 				       xmlSchemaBasicItemPtr baseItem,
14153 				       xmlSchemaItemListPtr uses,
14154 				       xmlSchemaItemListPtr baseUses,
14155 				       xmlSchemaWildcardPtr wild,
14156 				       xmlSchemaWildcardPtr baseWild)
14157 {
14158     xmlSchemaAttributeUsePtr cur = NULL, bcur;
14159     int i, j, found; /* err = 0; */
14160     const xmlChar *bEffValue;
14161     int effFixed;
14162 
14163     if (uses != NULL) {
14164 	for (i = 0; i < uses->nbItems; i++) {
14165 	    cur = uses->items[i];
14166 	    found = 0;
14167 	    if (baseUses == NULL)
14168 		goto not_found;
14169 	    for (j = 0; j < baseUses->nbItems; j++) {
14170 		bcur = baseUses->items[j];
14171 		if ((WXS_ATTRUSE_DECL_NAME(cur) ==
14172 			WXS_ATTRUSE_DECL_NAME(bcur)) &&
14173 		    (WXS_ATTRUSE_DECL_TNS(cur) ==
14174 			WXS_ATTRUSE_DECL_TNS(bcur)))
14175 		{
14176 		    /*
14177 		    * (2.1) "If there is an attribute use in the {attribute
14178 		    * uses} of the {base type definition} (call this B) whose
14179 		    * {attribute declaration} has the same {name} and {target
14180 		    * namespace}, then  all of the following must be true:"
14181 		    */
14182 		    found = 1;
14183 
14184 		    if ((cur->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
14185 			(bcur->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED))
14186 		    {
14187 			xmlChar *str = NULL;
14188 			/*
14189 			* (2.1.1) "one of the following must be true:"
14190 			* (2.1.1.1) "B's {required} is false."
14191 			* (2.1.1.2) "R's {required} is true."
14192 			*/
14193 			xmlSchemaPAttrUseErr4(pctxt,
14194 			    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
14195 			    WXS_ITEM_NODE(item), item, cur,
14196 			    "The 'optional' attribute use is inconsistent "
14197 			    "with the corresponding 'required' attribute use of "
14198 			    "the %s %s",
14199 			    WXS_ACTION_STR(action),
14200 			    xmlSchemaGetComponentDesignation(&str, baseItem),
14201 			    NULL, NULL);
14202 			FREE_AND_NULL(str);
14203 			/* err = pctxt->err; */
14204 		    } else if (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
14205 			WXS_ATTRUSE_TYPEDEF(cur),
14206 			WXS_ATTRUSE_TYPEDEF(bcur), 0) != 0)
14207 		    {
14208 			xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
14209 
14210 			/*
14211 			* SPEC (2.1.2) "R's {attribute declaration}'s
14212 			* {type definition} must be validly derived from
14213 			* B's {type definition} given the empty set as
14214 			* defined in Type Derivation OK (Simple) ($3.14.6)."
14215 			*/
14216 			xmlSchemaPAttrUseErr4(pctxt,
14217 			    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_2,
14218 			    WXS_ITEM_NODE(item), item, cur,
14219 			    "The attribute declaration's %s "
14220 			    "is not validly derived from "
14221 			    "the corresponding %s of the "
14222 			    "attribute declaration in the %s %s",
14223 			    xmlSchemaGetComponentDesignation(&strA,
14224 				WXS_ATTRUSE_TYPEDEF(cur)),
14225 			    xmlSchemaGetComponentDesignation(&strB,
14226 				WXS_ATTRUSE_TYPEDEF(bcur)),
14227 			    WXS_ACTION_STR(action),
14228 			    xmlSchemaGetComponentDesignation(&strC, baseItem));
14229 			    /* xmlSchemaGetComponentDesignation(&str, baseItem), */
14230 			FREE_AND_NULL(strA);
14231 			FREE_AND_NULL(strB);
14232 			FREE_AND_NULL(strC);
14233 			/* err = pctxt->err; */
14234 		    } else {
14235 			/*
14236 			* 2.1.3 [Definition:]  Let the effective value
14237 			* constraint of an attribute use be its {value
14238 			* constraint}, if present, otherwise its {attribute
14239 			* declaration}'s {value constraint} .
14240 			*/
14241 			xmlSchemaGetEffectiveValueConstraint(bcur,
14242 			    &effFixed, &bEffValue, NULL);
14243 			/*
14244 			* 2.1.3 ... one of the following must be true
14245 			*
14246 			* 2.1.3.1 B's `effective value constraint` is
14247 			* `absent` or default.
14248 			*/
14249 			if ((bEffValue != NULL) &&
14250 			    (effFixed == 1)) {
14251 			    const xmlChar *rEffValue = NULL;
14252 
14253 			    xmlSchemaGetEffectiveValueConstraint(bcur,
14254 				&effFixed, &rEffValue, NULL);
14255 			    /*
14256 			    * 2.1.3.2 R's `effective value constraint` is
14257 			    * fixed with the same string as B's.
14258 			    * MAYBE TODO: Compare the computed values.
14259 			    *       Hmm, it says "same string" so
14260 			    *       string-equality might really be sufficient.
14261 			    */
14262 			    if ((effFixed == 0) ||
14263 				(! WXS_ARE_DEFAULT_STR_EQUAL(rEffValue, bEffValue)))
14264 			    {
14265 				xmlChar *str = NULL;
14266 
14267 				xmlSchemaPAttrUseErr4(pctxt,
14268 				    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
14269 				    WXS_ITEM_NODE(item), item, cur,
14270 				    "The effective value constraint of the "
14271 				    "attribute use is inconsistent with "
14272 				    "its correspondent in the %s %s",
14273 				    WXS_ACTION_STR(action),
14274 				    xmlSchemaGetComponentDesignation(&str,
14275 					baseItem),
14276 				    NULL, NULL);
14277 				FREE_AND_NULL(str);
14278 				/* err = pctxt->err; */
14279 			    }
14280 			}
14281 		    }
14282 		    break;
14283 		}
14284 	    }
14285 not_found:
14286 	    if (!found) {
14287 		/*
14288 		* (2.2) "otherwise the {base type definition} must have an
14289 		* {attribute wildcard} and the {target namespace} of the
14290 		* R's {attribute declaration} must be `valid` with respect
14291 		* to that wildcard, as defined in Wildcard allows Namespace
14292 		* Name ($3.10.4)."
14293 		*/
14294 		if ((baseWild == NULL) ||
14295 		    (xmlSchemaCheckCVCWildcardNamespace(baseWild,
14296 		    (WXS_ATTRUSE_DECL(cur))->targetNamespace) != 0))
14297 		{
14298 		    xmlChar *str = NULL;
14299 
14300 		    xmlSchemaPAttrUseErr4(pctxt,
14301 			XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
14302 			WXS_ITEM_NODE(item), item, cur,
14303 			"Neither a matching attribute use, "
14304 			"nor a matching wildcard exists in the %s %s",
14305 			WXS_ACTION_STR(action),
14306 			xmlSchemaGetComponentDesignation(&str, baseItem),
14307 			NULL, NULL);
14308 		    FREE_AND_NULL(str);
14309 		    /* err = pctxt->err; */
14310 		}
14311 	    }
14312 	}
14313     }
14314     /*
14315     * SPEC derivation-ok-restriction (3):
14316     * (3) "For each attribute use in the {attribute uses} of the {base type
14317     * definition} whose {required} is true, there must be an attribute
14318     * use with an {attribute declaration} with the same {name} and
14319     * {target namespace} as its {attribute declaration} in the {attribute
14320     * uses} of the complex type definition itself whose {required} is true.
14321     */
14322     if (baseUses != NULL) {
14323 	for (j = 0; j < baseUses->nbItems; j++) {
14324 	    bcur = baseUses->items[j];
14325 	    if (bcur->occurs != XML_SCHEMAS_ATTR_USE_REQUIRED)
14326 		continue;
14327 	    found = 0;
14328 	    if (uses != NULL) {
14329 		for (i = 0; i < uses->nbItems; i++) {
14330 		    cur = uses->items[i];
14331 		    if ((WXS_ATTRUSE_DECL_NAME(cur) ==
14332 			WXS_ATTRUSE_DECL_NAME(bcur)) &&
14333 			(WXS_ATTRUSE_DECL_TNS(cur) ==
14334 			WXS_ATTRUSE_DECL_TNS(bcur))) {
14335 			found = 1;
14336 			break;
14337 		    }
14338 		}
14339 	    }
14340 	    if (!found) {
14341 		xmlChar *strA = NULL, *strB = NULL;
14342 
14343 		xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14344 		    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
14345 		    NULL, item,
14346 		    "A matching attribute use for the "
14347 		    "'required' %s of the %s %s is missing",
14348 		    xmlSchemaGetComponentDesignation(&strA, bcur),
14349 		    WXS_ACTION_STR(action),
14350 		    xmlSchemaGetComponentDesignation(&strB, baseItem),
14351 		    NULL);
14352 		FREE_AND_NULL(strA);
14353 		FREE_AND_NULL(strB);
14354 	    }
14355 	}
14356     }
14357     /*
14358     * derivation-ok-restriction (4)
14359     */
14360     if (wild != NULL) {
14361 	/*
14362 	* (4) "If there is an {attribute wildcard}, all of the
14363 	* following must be true:"
14364 	*/
14365 	if (baseWild == NULL) {
14366 	    xmlChar *str = NULL;
14367 
14368 	    /*
14369 	    * (4.1) "The {base type definition} must also have one."
14370 	    */
14371 	    xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14372 		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
14373 		NULL, item,
14374 		"The %s has an attribute wildcard, "
14375 		"but the %s %s '%s' does not have one",
14376 		WXS_ITEM_TYPE_NAME(item),
14377 		WXS_ACTION_STR(action),
14378 		WXS_ITEM_TYPE_NAME(baseItem),
14379 		xmlSchemaGetComponentQName(&str, baseItem));
14380 	    FREE_AND_NULL(str);
14381 	    return(pctxt->err);
14382 	} else if ((baseWild->any == 0) &&
14383 		xmlSchemaCheckCOSNSSubset(wild, baseWild))
14384 	{
14385 	    xmlChar *str = NULL;
14386 	    /*
14387 	    * (4.2) "The complex type definition's {attribute wildcard}'s
14388 	    * {namespace constraint} must be a subset of the {base type
14389 	    * definition}'s {attribute wildcard}'s {namespace constraint},
14390 	    * as defined by Wildcard Subset ($3.10.6)."
14391 	    */
14392 	    xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14393 		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
14394 		NULL, item,
14395 		"The attribute wildcard is not a valid "
14396 		"subset of the wildcard in the %s %s '%s'",
14397 		WXS_ACTION_STR(action),
14398 		WXS_ITEM_TYPE_NAME(baseItem),
14399 		xmlSchemaGetComponentQName(&str, baseItem),
14400 		NULL);
14401 	    FREE_AND_NULL(str);
14402 	    return(pctxt->err);
14403 	}
14404 	/* 4.3 Unless the {base type definition} is the `ur-type
14405 	* definition`, the complex type definition's {attribute
14406 	* wildcard}'s {process contents} must be identical to or
14407 	* stronger than the {base type definition}'s {attribute
14408 	* wildcard}'s {process contents}, where strict is stronger
14409 	* than lax is stronger than skip.
14410 	*/
14411 	if ((! WXS_IS_ANYTYPE(baseItem)) &&
14412 	    (wild->processContents < baseWild->processContents)) {
14413 	    xmlChar *str = NULL;
14414 	    xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14415 		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
14416 		NULL, baseItem,
14417 		"The {process contents} of the attribute wildcard is "
14418 		"weaker than the one in the %s %s '%s'",
14419 		WXS_ACTION_STR(action),
14420 		WXS_ITEM_TYPE_NAME(baseItem),
14421 		xmlSchemaGetComponentQName(&str, baseItem),
14422 		NULL);
14423 	    FREE_AND_NULL(str)
14424 		return(pctxt->err);
14425 	}
14426     }
14427     return(0);
14428 }
14429 
14430 
14431 static int
14432 xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
14433 				  xmlSchemaBasicItemPtr item,
14434 				  xmlSchemaWildcardPtr *completeWild,
14435 				  xmlSchemaItemListPtr list,
14436 				  xmlSchemaItemListPtr prohibs);
14437 /**
14438  * xmlSchemaFixupTypeAttributeUses:
14439  * @ctxt:  the schema parser context
14440  * @type:  the complex type definition
14441  *
14442  *
14443  * Builds the wildcard and the attribute uses on the given complex type.
14444  * Returns -1 if an internal error occurs, 0 otherwise.
14445  *
14446  * ATTENTION TODO: Experimantally this uses pointer comparisons for
14447  * strings, so recheck this if we start to hardcode some schemata, since
14448  * they might not be in the same dict.
14449  * NOTE: It is allowed to "extend" the xs:anyType type.
14450  */
14451 static int
xmlSchemaFixupTypeAttributeUses(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)14452 xmlSchemaFixupTypeAttributeUses(xmlSchemaParserCtxtPtr pctxt,
14453 				  xmlSchemaTypePtr type)
14454 {
14455     xmlSchemaTypePtr baseType = NULL;
14456     xmlSchemaAttributeUsePtr use;
14457     xmlSchemaItemListPtr uses, baseUses, prohibs = NULL;
14458 
14459     if (type->baseType == NULL) {
14460 	PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14461 	    "no base type");
14462         return (-1);
14463     }
14464     baseType = type->baseType;
14465     if (WXS_IS_TYPE_NOT_FIXED(baseType))
14466 	if (xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt) == -1)
14467 	    return(-1);
14468 
14469     uses = type->attrUses;
14470     baseUses = baseType->attrUses;
14471     /*
14472     * Expand attribute group references. And build the 'complete'
14473     * wildcard, i.e. intersect multiple wildcards.
14474     * Move attribute prohibitions into a separate list.
14475     */
14476     if (uses != NULL) {
14477 	if (WXS_IS_RESTRICTION(type)) {
14478 	    /*
14479 	    * This one will transfer all attr. prohibitions
14480 	    * into pctxt->attrProhibs.
14481 	    */
14482 	    if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14483 		WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14484 		pctxt->attrProhibs) == -1)
14485 	    {
14486 		PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14487 		"failed to expand attributes");
14488 	    }
14489 	    if (pctxt->attrProhibs->nbItems != 0)
14490 		prohibs = pctxt->attrProhibs;
14491 	} else {
14492 	    if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14493 		WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14494 		NULL) == -1)
14495 	    {
14496 		PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14497 		"failed to expand attributes");
14498 	    }
14499 	}
14500     }
14501     /*
14502     * Inherit the attribute uses of the base type.
14503     */
14504     if (baseUses != NULL) {
14505 	int i, j;
14506 	xmlSchemaAttributeUseProhibPtr pro;
14507 
14508 	if (WXS_IS_RESTRICTION(type)) {
14509 	    int usesCount;
14510 	    xmlSchemaAttributeUsePtr tmp;
14511 
14512 	    if (uses != NULL)
14513 		usesCount = uses->nbItems;
14514 	    else
14515 		usesCount = 0;
14516 
14517 	    /* Restriction. */
14518 	    for (i = 0; i < baseUses->nbItems; i++) {
14519 		use = baseUses->items[i];
14520 		if (prohibs) {
14521 		    /*
14522 		    * Filter out prohibited uses.
14523 		    */
14524 		    for (j = 0; j < prohibs->nbItems; j++) {
14525 			pro = prohibs->items[j];
14526 			if ((WXS_ATTRUSE_DECL_NAME(use) == pro->name) &&
14527 			    (WXS_ATTRUSE_DECL_TNS(use) ==
14528 				pro->targetNamespace))
14529 			{
14530 			    goto inherit_next;
14531 			}
14532 		    }
14533 		}
14534 		if (usesCount) {
14535 		    /*
14536 		    * Filter out existing uses.
14537 		    */
14538 		    for (j = 0; j < usesCount; j++) {
14539 			tmp = uses->items[j];
14540 			if ((WXS_ATTRUSE_DECL_NAME(use) ==
14541 				WXS_ATTRUSE_DECL_NAME(tmp)) &&
14542 			    (WXS_ATTRUSE_DECL_TNS(use) ==
14543 				WXS_ATTRUSE_DECL_TNS(tmp)))
14544 			{
14545 			    goto inherit_next;
14546 			}
14547 		    }
14548 		}
14549 		if (uses == NULL) {
14550 		    type->attrUses = xmlSchemaItemListCreate();
14551 		    if (type->attrUses == NULL)
14552 			goto exit_failure;
14553 		    uses = type->attrUses;
14554 		}
14555 		xmlSchemaItemListAddSize(uses, 2, use);
14556 inherit_next: {}
14557 	    }
14558 	} else {
14559 	    /* Extension. */
14560 	    for (i = 0; i < baseUses->nbItems; i++) {
14561 		use = baseUses->items[i];
14562 		if (uses == NULL) {
14563 		    type->attrUses = xmlSchemaItemListCreate();
14564 		    if (type->attrUses == NULL)
14565 			goto exit_failure;
14566 		    uses = type->attrUses;
14567 		}
14568 		xmlSchemaItemListAddSize(uses, baseUses->nbItems, use);
14569 	    }
14570 	}
14571     }
14572     /*
14573     * Shrink attr. uses.
14574     */
14575     if (uses) {
14576 	if (uses->nbItems == 0) {
14577 	    xmlSchemaItemListFree(uses);
14578 	    type->attrUses = NULL;
14579 	}
14580 	/*
14581 	* TODO: We could shrink the size of the array
14582 	* to fit the actual number of items.
14583 	*/
14584     }
14585     /*
14586     * Compute the complete wildcard.
14587     */
14588     if (WXS_IS_EXTENSION(type)) {
14589 	if (baseType->attributeWildcard != NULL) {
14590 	    /*
14591 	    * (3.2.2.1) "If the `base wildcard` is non-`absent`, then
14592 	    * the appropriate case among the following:"
14593 	    */
14594 	    if (type->attributeWildcard != NULL) {
14595 		/*
14596 		* Union the complete wildcard with the base wildcard.
14597 		* SPEC {attribute wildcard}
14598 		* (3.2.2.1.2) "otherwise a wildcard whose {process contents}
14599 		* and {annotation} are those of the `complete wildcard`,
14600 		* and whose {namespace constraint} is the intensional union
14601 		* of the {namespace constraint} of the `complete wildcard`
14602 		* and of the `base wildcard`, as defined in Attribute
14603 		* Wildcard Union ($3.10.6)."
14604 		*/
14605 		if (xmlSchemaUnionWildcards(pctxt, type->attributeWildcard,
14606 		    baseType->attributeWildcard) == -1)
14607 		    goto exit_failure;
14608 	    } else {
14609 		/*
14610 		* (3.2.2.1.1) "If the `complete wildcard` is `absent`,
14611 		* then the `base wildcard`."
14612 		*/
14613 		type->attributeWildcard = baseType->attributeWildcard;
14614 	    }
14615 	} else {
14616 	    /*
14617 	    * (3.2.2.2) "otherwise (the `base wildcard` is `absent`) the
14618 	    * `complete wildcard`"
14619 	    * NOOP
14620 	    */
14621 	}
14622     } else {
14623 	/*
14624 	* SPEC {attribute wildcard}
14625 	* (3.1) "If the <restriction> alternative is chosen, then the
14626 	* `complete wildcard`;"
14627 	* NOOP
14628 	*/
14629     }
14630 
14631     return (0);
14632 
14633 exit_failure:
14634     return(-1);
14635 }
14636 
14637 /**
14638  * xmlSchemaTypeFinalContains:
14639  * @schema:  the schema
14640  * @type:  the type definition
14641  * @final: the final
14642  *
14643  * Evaluates if a type definition contains the given "final".
14644  * This does take "finalDefault" into account as well.
14645  *
14646  * Returns 1 if the type does containt the given "final",
14647  * 0 otherwise.
14648  */
14649 static int
xmlSchemaTypeFinalContains(xmlSchemaTypePtr type,int final)14650 xmlSchemaTypeFinalContains(xmlSchemaTypePtr type, int final)
14651 {
14652     if (type == NULL)
14653 	return (0);
14654     if (type->flags & final)
14655 	return (1);
14656     else
14657 	return (0);
14658 }
14659 
14660 /**
14661  * xmlSchemaGetUnionSimpleTypeMemberTypes:
14662  * @type:  the Union Simple Type
14663  *
14664  * Returns a list of member types of @type if existing,
14665  * returns NULL otherwise.
14666  */
14667 static xmlSchemaTypeLinkPtr
xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)14668 xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
14669 {
14670     while ((type != NULL) && (type->type == XML_SCHEMA_TYPE_SIMPLE)) {
14671 	if (type->memberTypes != NULL)
14672 	    return (type->memberTypes);
14673 	else
14674 	    type = type->baseType;
14675     }
14676     return (NULL);
14677 }
14678 
14679 /**
14680  * xmlSchemaGetParticleTotalRangeMin:
14681  * @particle: the particle
14682  *
14683  * Schema Component Constraint: Effective Total Range
14684  * (all and sequence) + (choice)
14685  *
14686  * Returns the minimun Effective Total Range.
14687  */
14688 static int
xmlSchemaGetParticleTotalRangeMin(xmlSchemaParticlePtr particle)14689 xmlSchemaGetParticleTotalRangeMin(xmlSchemaParticlePtr particle)
14690 {
14691     if ((particle->children == NULL) ||
14692 	(particle->minOccurs == 0))
14693 	return (0);
14694     if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14695 	int min = -1, cur;
14696 	xmlSchemaParticlePtr part =
14697 	    (xmlSchemaParticlePtr) particle->children->children;
14698 
14699 	if (part == NULL)
14700 	    return (0);
14701 	while (part != NULL) {
14702 	    if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14703 		(part->children->type == XML_SCHEMA_TYPE_ANY))
14704 		cur = part->minOccurs;
14705 	    else
14706 		cur = xmlSchemaGetParticleTotalRangeMin(part);
14707 	    if (cur == 0)
14708 		return (0);
14709 	    if ((min > cur) || (min == -1))
14710 		min = cur;
14711 	    part = (xmlSchemaParticlePtr) part->next;
14712 	}
14713 	return (particle->minOccurs * min);
14714     } else {
14715 	/* <all> and <sequence> */
14716 	int sum = 0;
14717 	xmlSchemaParticlePtr part =
14718 	    (xmlSchemaParticlePtr) particle->children->children;
14719 
14720 	if (part == NULL)
14721 	    return (0);
14722 	do {
14723 	    if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14724 		(part->children->type == XML_SCHEMA_TYPE_ANY))
14725 		sum += part->minOccurs;
14726 	    else
14727 		sum += xmlSchemaGetParticleTotalRangeMin(part);
14728 	    part = (xmlSchemaParticlePtr) part->next;
14729 	} while (part != NULL);
14730 	return (particle->minOccurs * sum);
14731     }
14732 }
14733 
14734 #if 0
14735 /**
14736  * xmlSchemaGetParticleTotalRangeMax:
14737  * @particle: the particle
14738  *
14739  * Schema Component Constraint: Effective Total Range
14740  * (all and sequence) + (choice)
14741  *
14742  * Returns the maximum Effective Total Range.
14743  */
14744 static int
14745 xmlSchemaGetParticleTotalRangeMax(xmlSchemaParticlePtr particle)
14746 {
14747     if ((particle->children == NULL) ||
14748 	(particle->children->children == NULL))
14749 	return (0);
14750     if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14751 	int max = -1, cur;
14752 	xmlSchemaParticlePtr part =
14753 	    (xmlSchemaParticlePtr) particle->children->children;
14754 
14755 	for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14756 	    if (part->children == NULL)
14757 		continue;
14758 	    if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14759 		(part->children->type == XML_SCHEMA_TYPE_ANY))
14760 		cur = part->maxOccurs;
14761 	    else
14762 		cur = xmlSchemaGetParticleTotalRangeMax(part);
14763 	    if (cur == UNBOUNDED)
14764 		return (UNBOUNDED);
14765 	    if ((max < cur) || (max == -1))
14766 		max = cur;
14767 	}
14768 	/* TODO: Handle overflows? */
14769 	return (particle->maxOccurs * max);
14770     } else {
14771 	/* <all> and <sequence> */
14772 	int sum = 0, cur;
14773 	xmlSchemaParticlePtr part =
14774 	    (xmlSchemaParticlePtr) particle->children->children;
14775 
14776 	for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14777 	    if (part->children == NULL)
14778 		continue;
14779 	    if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14780 		(part->children->type == XML_SCHEMA_TYPE_ANY))
14781 		cur = part->maxOccurs;
14782 	    else
14783 		cur = xmlSchemaGetParticleTotalRangeMax(part);
14784 	    if (cur == UNBOUNDED)
14785 		return (UNBOUNDED);
14786 	    if ((cur > 0) && (particle->maxOccurs == UNBOUNDED))
14787 		return (UNBOUNDED);
14788 	    sum += cur;
14789 	}
14790 	/* TODO: Handle overflows? */
14791 	return (particle->maxOccurs * sum);
14792     }
14793 }
14794 #endif
14795 
14796 /**
14797  * xmlSchemaIsParticleEmptiable:
14798  * @particle: the particle
14799  *
14800  * Schema Component Constraint: Particle Emptiable
14801  * Checks whether the given particle is emptiable.
14802  *
14803  * Returns 1 if emptiable, 0 otherwise.
14804  */
14805 static int
xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)14806 xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)
14807 {
14808     /*
14809     * SPEC (1) "Its {min occurs} is 0."
14810     */
14811     if ((particle == NULL) || (particle->minOccurs == 0) ||
14812 	(particle->children == NULL))
14813 	return (1);
14814     /*
14815     * SPEC (2) "Its {term} is a group and the minimum part of the
14816     * effective total range of that group, [...] is 0."
14817     */
14818     if (WXS_IS_MODEL_GROUP(particle->children)) {
14819 	if (xmlSchemaGetParticleTotalRangeMin(particle) == 0)
14820 	    return (1);
14821     }
14822     return (0);
14823 }
14824 
14825 /**
14826  * xmlSchemaCheckCOSSTDerivedOK:
14827  * @actxt: a context
14828  * @type:  the derived simple type definition
14829  * @baseType:  the base type definition
14830  * @subset: the subset of ('restriction', ect.)
14831  *
14832  * Schema Component Constraint:
14833  * Type Derivation OK (Simple) (cos-st-derived-OK)
14834  *
14835  * Checks wheter @type can be validly
14836  * derived from @baseType.
14837  *
14838  * Returns 0 on success, an positive error code otherwise.
14839  */
14840 static int
xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,xmlSchemaTypePtr type,xmlSchemaTypePtr baseType,int subset)14841 xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
14842 			     xmlSchemaTypePtr type,
14843 			     xmlSchemaTypePtr baseType,
14844 			     int subset)
14845 {
14846     /*
14847     * 1 They are the same type definition.
14848     * TODO: The identy check might have to be more complex than this.
14849     */
14850     if (type == baseType)
14851 	return (0);
14852     /*
14853     * 2.1 restriction is not in the subset, or in the {final}
14854     * of its own {base type definition};
14855     *
14856     * NOTE that this will be used also via "xsi:type".
14857     *
14858     * TODO: Revise this, it looks strange. How can the "type"
14859     * not be fixed or *in* fixing?
14860     */
14861     if (WXS_IS_TYPE_NOT_FIXED(type))
14862 	if (xmlSchemaTypeFixup(type, actxt) == -1)
14863 	    return(-1);
14864     if (WXS_IS_TYPE_NOT_FIXED(baseType))
14865 	if (xmlSchemaTypeFixup(baseType, actxt) == -1)
14866 	    return(-1);
14867     if ((subset & SUBSET_RESTRICTION) ||
14868 	(xmlSchemaTypeFinalContains(type->baseType,
14869 	    XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
14870 	return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
14871     }
14872     /* 2.2 */
14873     if (type->baseType == baseType) {
14874 	/*
14875 	* 2.2.1 D's `base type definition` is B.
14876 	*/
14877 	return (0);
14878     }
14879     /*
14880     * 2.2.2 D's `base type definition` is not the `ur-type definition`
14881     * and is validly derived from B given the subset, as defined by this
14882     * constraint.
14883     */
14884     if ((! WXS_IS_ANYTYPE(type->baseType)) &&
14885 	(xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
14886 	    baseType, subset) == 0)) {
14887 	return (0);
14888     }
14889     /*
14890     * 2.2.3 D's {variety} is list or union and B is the `simple ur-type
14891     * definition`.
14892     */
14893     if (WXS_IS_ANY_SIMPLE_TYPE(baseType) &&
14894 	(WXS_IS_LIST(type) || WXS_IS_UNION(type))) {
14895 	return (0);
14896     }
14897     /*
14898     * 2.2.4 B's {variety} is union and D is validly derived from a type
14899     * definition in B's {member type definitions} given the subset, as
14900     * defined by this constraint.
14901     *
14902     * NOTE: This seems not to involve built-in types, since there is no
14903     * built-in Union Simple Type.
14904     */
14905     if (WXS_IS_UNION(baseType)) {
14906 	xmlSchemaTypeLinkPtr cur;
14907 
14908 	cur = baseType->memberTypes;
14909 	while (cur != NULL) {
14910 	    if (WXS_IS_TYPE_NOT_FIXED(cur->type))
14911 		if (xmlSchemaTypeFixup(cur->type, actxt) == -1)
14912 		    return(-1);
14913 	    if (xmlSchemaCheckCOSSTDerivedOK(actxt,
14914 		    type, cur->type, subset) == 0)
14915 	    {
14916 		/*
14917 		* It just has to be validly derived from at least one
14918 		* member-type.
14919 		*/
14920 		return (0);
14921 	    }
14922 	    cur = cur->next;
14923 	}
14924     }
14925     return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
14926 }
14927 
14928 /**
14929  * xmlSchemaCheckTypeDefCircularInternal:
14930  * @pctxt:  the schema parser context
14931  * @ctxtType:  the type definition
14932  * @ancestor: an ancestor of @ctxtType
14933  *
14934  * Checks st-props-correct (2) + ct-props-correct (3).
14935  * Circular type definitions are not allowed.
14936  *
14937  * Returns XML_SCHEMAP_ST_PROPS_CORRECT_2 if the given type is
14938  * circular, 0 otherwise.
14939  */
14940 static int
xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr ctxtType,xmlSchemaTypePtr ancestor)14941 xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,
14942 			   xmlSchemaTypePtr ctxtType,
14943 			   xmlSchemaTypePtr ancestor)
14944 {
14945     int ret;
14946 
14947     if ((ancestor == NULL) || (ancestor->type == XML_SCHEMA_TYPE_BASIC))
14948 	return (0);
14949 
14950     if (ctxtType == ancestor) {
14951 	xmlSchemaPCustomErr(pctxt,
14952 	    XML_SCHEMAP_ST_PROPS_CORRECT_2,
14953 	    WXS_BASIC_CAST ctxtType, WXS_ITEM_NODE(ctxtType),
14954 	    "The definition is circular", NULL);
14955 	return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
14956     }
14957     if (ancestor->flags & XML_SCHEMAS_TYPE_MARKED) {
14958 	/*
14959 	* Avoid inifinite recursion on circular types not yet checked.
14960 	*/
14961 	return (0);
14962     }
14963     ancestor->flags |= XML_SCHEMAS_TYPE_MARKED;
14964     ret = xmlSchemaCheckTypeDefCircularInternal(pctxt, ctxtType,
14965 	ancestor->baseType);
14966     ancestor->flags ^= XML_SCHEMAS_TYPE_MARKED;
14967     return (ret);
14968 }
14969 
14970 /**
14971  * xmlSchemaCheckTypeDefCircular:
14972  * @item:  the complex/simple type definition
14973  * @ctxt:  the parser context
14974  * @name:  the name
14975  *
14976  * Checks for circular type definitions.
14977  */
14978 static void
xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,xmlSchemaParserCtxtPtr ctxt)14979 xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,
14980 			      xmlSchemaParserCtxtPtr ctxt)
14981 {
14982     if ((item == NULL) ||
14983 	(item->type == XML_SCHEMA_TYPE_BASIC) ||
14984 	(item->baseType == NULL))
14985 	return;
14986     xmlSchemaCheckTypeDefCircularInternal(ctxt, item,
14987 	item->baseType);
14988 }
14989 
14990 /*
14991 * Simple Type Definition Representation OK (src-simple-type) 4
14992 *
14993 * "4 Circular union type definition is disallowed. That is, if the
14994 * <union> alternative is chosen, there must not be any entries in the
14995 * memberTypes [attribute] at any depth which resolve to the component
14996 * corresponding to the <simpleType>."
14997 *
14998 * Note that this should work on the *representation* of a component,
14999 * thus assumes any union types in the member types not being yet
15000 * substituted. At this stage we need the variety of the types
15001 * to be already computed.
15002 */
15003 static int
xmlSchemaCheckUnionTypeDefCircularRecur(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr ctxType,xmlSchemaTypeLinkPtr members)15004 xmlSchemaCheckUnionTypeDefCircularRecur(xmlSchemaParserCtxtPtr pctxt,
15005 					xmlSchemaTypePtr ctxType,
15006 					xmlSchemaTypeLinkPtr members)
15007 {
15008     xmlSchemaTypeLinkPtr member;
15009     xmlSchemaTypePtr memberType;
15010 
15011     member = members;
15012     while (member != NULL) {
15013 	memberType = member->type;
15014 	while ((memberType != NULL) &&
15015 	    (memberType->type != XML_SCHEMA_TYPE_BASIC)) {
15016 	    if (memberType == ctxType) {
15017 		xmlSchemaPCustomErr(pctxt,
15018 		    XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
15019 		    WXS_BASIC_CAST ctxType, NULL,
15020 		    "The union type definition is circular", NULL);
15021 		return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
15022 	    }
15023 	    if ((WXS_IS_UNION(memberType)) &&
15024 		((memberType->flags & XML_SCHEMAS_TYPE_MARKED) == 0))
15025 	    {
15026 		int res;
15027 		memberType->flags |= XML_SCHEMAS_TYPE_MARKED;
15028 		res = xmlSchemaCheckUnionTypeDefCircularRecur(pctxt,
15029 		    ctxType,
15030 		    xmlSchemaGetUnionSimpleTypeMemberTypes(memberType));
15031 		memberType->flags ^= XML_SCHEMAS_TYPE_MARKED;
15032 		if (res != 0)
15033 		    return(res);
15034 	    }
15035 	    memberType = memberType->baseType;
15036 	}
15037 	member = member->next;
15038     }
15039     return(0);
15040 }
15041 
15042 static int
xmlSchemaCheckUnionTypeDefCircular(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)15043 xmlSchemaCheckUnionTypeDefCircular(xmlSchemaParserCtxtPtr pctxt,
15044 				   xmlSchemaTypePtr type)
15045 {
15046     if (! WXS_IS_UNION(type))
15047 	return(0);
15048     return(xmlSchemaCheckUnionTypeDefCircularRecur(pctxt, type,
15049 	type->memberTypes));
15050 }
15051 
15052 /**
15053  * xmlSchemaResolveTypeReferences:
15054  * @item:  the complex/simple type definition
15055  * @ctxt:  the parser context
15056  * @name:  the name
15057  *
15058  * Resolvese type definition references
15059  */
15060 static void
xmlSchemaResolveTypeReferences(xmlSchemaTypePtr typeDef,xmlSchemaParserCtxtPtr ctxt)15061 xmlSchemaResolveTypeReferences(xmlSchemaTypePtr typeDef,
15062 			 xmlSchemaParserCtxtPtr ctxt)
15063 {
15064     if (typeDef == NULL)
15065 	return;
15066 
15067     /*
15068     * Resolve the base type.
15069     */
15070     if (typeDef->baseType == NULL) {
15071 	typeDef->baseType = xmlSchemaGetType(ctxt->schema,
15072 	    typeDef->base, typeDef->baseNs);
15073 	if (typeDef->baseType == NULL) {
15074 	    xmlSchemaPResCompAttrErr(ctxt,
15075 		XML_SCHEMAP_SRC_RESOLVE,
15076 		WXS_BASIC_CAST typeDef, typeDef->node,
15077 		"base", typeDef->base, typeDef->baseNs,
15078 		XML_SCHEMA_TYPE_SIMPLE, NULL);
15079 	    return;
15080 	}
15081     }
15082     if (WXS_IS_SIMPLE(typeDef)) {
15083 	if (WXS_IS_UNION(typeDef)) {
15084 	    /*
15085 	    * Resolve the memberTypes.
15086 	    */
15087 	    xmlSchemaResolveUnionMemberTypes(ctxt, typeDef);
15088 	    return;
15089 	} else if (WXS_IS_LIST(typeDef)) {
15090 	    /*
15091 	    * Resolve the itemType.
15092 	    */
15093 	    if ((typeDef->subtypes == NULL) && (typeDef->base != NULL)) {
15094 
15095 		typeDef->subtypes = xmlSchemaGetType(ctxt->schema,
15096 		    typeDef->base, typeDef->baseNs);
15097 
15098 		if ((typeDef->subtypes == NULL) ||
15099 		    (! WXS_IS_SIMPLE(typeDef->subtypes)))
15100 		{
15101 		    typeDef->subtypes = NULL;
15102 		    xmlSchemaPResCompAttrErr(ctxt,
15103 			XML_SCHEMAP_SRC_RESOLVE,
15104 			WXS_BASIC_CAST typeDef, typeDef->node,
15105 			"itemType", typeDef->base, typeDef->baseNs,
15106 			XML_SCHEMA_TYPE_SIMPLE, NULL);
15107 		}
15108 	    }
15109 	    return;
15110 	}
15111     }
15112     /*
15113     * The ball of letters below means, that if we have a particle
15114     * which has a QName-helper component as its {term}, we want
15115     * to resolve it...
15116     */
15117     else if ((WXS_TYPE_CONTENTTYPE(typeDef) != NULL) &&
15118 	((WXS_TYPE_CONTENTTYPE(typeDef))->type ==
15119 	    XML_SCHEMA_TYPE_PARTICLE) &&
15120 	(WXS_TYPE_PARTICLE_TERM(typeDef) != NULL) &&
15121 	((WXS_TYPE_PARTICLE_TERM(typeDef))->type ==
15122 	    XML_SCHEMA_EXTRA_QNAMEREF))
15123     {
15124 	xmlSchemaQNameRefPtr ref =
15125 	    WXS_QNAME_CAST WXS_TYPE_PARTICLE_TERM(typeDef);
15126 	xmlSchemaModelGroupDefPtr groupDef;
15127 
15128 	/*
15129 	* URGENT TODO: Test this.
15130 	*/
15131 	WXS_TYPE_PARTICLE_TERM(typeDef) = NULL;
15132 	/*
15133 	* Resolve the MG definition reference.
15134 	*/
15135 	groupDef =
15136 	    WXS_MODEL_GROUPDEF_CAST xmlSchemaGetNamedComponent(ctxt->schema,
15137 		ref->itemType, ref->name, ref->targetNamespace);
15138 	if (groupDef == NULL) {
15139 	    xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
15140 		NULL, WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)),
15141 		"ref", ref->name, ref->targetNamespace, ref->itemType,
15142 		NULL);
15143 	    /* Remove the particle. */
15144 	    WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
15145 	} else if (WXS_MODELGROUPDEF_MODEL(groupDef) == NULL)
15146 	    /* Remove the particle. */
15147 	    WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
15148 	else {
15149 	    /*
15150 	    * Assign the MG definition's {model group} to the
15151 	    * particle's {term}.
15152 	    */
15153 	    WXS_TYPE_PARTICLE_TERM(typeDef) = WXS_MODELGROUPDEF_MODEL(groupDef);
15154 
15155 	    if (WXS_MODELGROUPDEF_MODEL(groupDef)->type == XML_SCHEMA_TYPE_ALL) {
15156 		/*
15157 		* SPEC cos-all-limited (1.2)
15158 		* "1.2 the {term} property of a particle with
15159 		* {max occurs}=1 which is part of a pair which constitutes
15160 		* the {content type} of a complex type definition."
15161 		*/
15162 		if ((WXS_TYPE_PARTICLE(typeDef))->maxOccurs != 1) {
15163 		    xmlSchemaCustomErr(ACTXT_CAST ctxt,
15164 			/* TODO: error code */
15165 			XML_SCHEMAP_COS_ALL_LIMITED,
15166 			WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)), NULL,
15167 			"The particle's {max occurs} must be 1, since the "
15168 			"reference resolves to an 'all' model group",
15169 			NULL, NULL);
15170 		}
15171 	    }
15172 	}
15173     }
15174 }
15175 
15176 
15177 
15178 /**
15179  * xmlSchemaCheckSTPropsCorrect:
15180  * @ctxt:  the schema parser context
15181  * @type:  the simple type definition
15182  *
15183  * Checks st-props-correct.
15184  *
15185  * Returns 0 if the properties are correct,
15186  * if not, a positive error code and -1 on internal
15187  * errors.
15188  */
15189 static int
xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,xmlSchemaTypePtr type)15190 xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
15191 			     xmlSchemaTypePtr type)
15192 {
15193     xmlSchemaTypePtr baseType = type->baseType;
15194     xmlChar *str = NULL;
15195 
15196     /* STATE: error funcs converted. */
15197     /*
15198     * Schema Component Constraint: Simple Type Definition Properties Correct
15199     *
15200     * NOTE: This is somehow redundant, since we actually built a simple type
15201     * to have all the needed information; this acts as an self test.
15202     */
15203     /* Base type: If the datatype has been `derived` by `restriction`
15204     * then the Simple Type Definition component from which it is `derived`,
15205     * otherwise the Simple Type Definition for anySimpleType ($4.1.6).
15206     */
15207     if (baseType == NULL) {
15208 	/*
15209 	* TODO: Think about: "modulo the impact of Missing
15210 	* Sub-components ($5.3)."
15211 	*/
15212 	xmlSchemaPCustomErr(ctxt,
15213 	    XML_SCHEMAP_ST_PROPS_CORRECT_1,
15214 	    WXS_BASIC_CAST type, NULL,
15215 	    "No base type existent", NULL);
15216 	return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15217 
15218     }
15219     if (! WXS_IS_SIMPLE(baseType)) {
15220 	xmlSchemaPCustomErr(ctxt,
15221 	    XML_SCHEMAP_ST_PROPS_CORRECT_1,
15222 	    WXS_BASIC_CAST type, NULL,
15223 	    "The base type '%s' is not a simple type",
15224 	    xmlSchemaGetComponentQName(&str, baseType));
15225 	FREE_AND_NULL(str)
15226 	return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15227     }
15228     if ((WXS_IS_LIST(type) || WXS_IS_UNION(type)) &&
15229 	(WXS_IS_RESTRICTION(type) == 0) &&
15230 	((! WXS_IS_ANY_SIMPLE_TYPE(baseType)) &&
15231          (baseType->type != XML_SCHEMA_TYPE_SIMPLE))) {
15232 	xmlSchemaPCustomErr(ctxt,
15233 	    XML_SCHEMAP_ST_PROPS_CORRECT_1,
15234 	    WXS_BASIC_CAST type, NULL,
15235 	    "A type, derived by list or union, must have "
15236 	    "the simple ur-type definition as base type, not '%s'",
15237 	    xmlSchemaGetComponentQName(&str, baseType));
15238 	FREE_AND_NULL(str)
15239 	return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15240     }
15241     /*
15242     * Variety: One of {atomic, list, union}.
15243     */
15244     if ((! WXS_IS_ATOMIC(type)) && (! WXS_IS_UNION(type)) &&
15245 	(! WXS_IS_LIST(type))) {
15246 	xmlSchemaPCustomErr(ctxt,
15247 	    XML_SCHEMAP_ST_PROPS_CORRECT_1,
15248 	    WXS_BASIC_CAST type, NULL,
15249 	    "The variety is absent", NULL);
15250 	return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15251     }
15252     /* TODO: Finish this. Hmm, is this finished? */
15253 
15254     /*
15255     * 3 The {final} of the {base type definition} must not contain restriction.
15256     */
15257     if (xmlSchemaTypeFinalContains(baseType,
15258 	XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15259 	xmlSchemaPCustomErr(ctxt,
15260 	    XML_SCHEMAP_ST_PROPS_CORRECT_3,
15261 	    WXS_BASIC_CAST type, NULL,
15262 	    "The 'final' of its base type '%s' must not contain "
15263 	    "'restriction'",
15264 	    xmlSchemaGetComponentQName(&str, baseType));
15265 	FREE_AND_NULL(str)
15266 	return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
15267     }
15268 
15269     /*
15270     * 2 All simple type definitions must be derived ultimately from the `simple
15271     * ur-type definition` (so circular definitions are disallowed). That is, it
15272     * must be possible to reach a built-in primitive datatype or the `simple
15273     * ur-type definition` by repeatedly following the {base type definition}.
15274     *
15275     * NOTE: this is done in xmlSchemaCheckTypeDefCircular().
15276     */
15277     return (0);
15278 }
15279 
15280 /**
15281  * xmlSchemaCheckCOSSTRestricts:
15282  * @ctxt:  the schema parser context
15283  * @type:  the simple type definition
15284  *
15285  * Schema Component Constraint:
15286  * Derivation Valid (Restriction, Simple) (cos-st-restricts)
15287 
15288  * Checks if the given @type (simpleType) is derived validly by restriction.
15289  * STATUS:
15290  *
15291  * Returns -1 on internal errors, 0 if the type is validly derived,
15292  * a positive error code otherwise.
15293  */
15294 static int
xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)15295 xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt,
15296 			     xmlSchemaTypePtr type)
15297 {
15298     xmlChar *str = NULL;
15299 
15300     if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
15301 	PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15302 	    "given type is not a user-derived simpleType");
15303 	return (-1);
15304     }
15305 
15306     if (WXS_IS_ATOMIC(type)) {
15307 	xmlSchemaTypePtr primitive;
15308 	/*
15309 	* 1.1 The {base type definition} must be an atomic simple
15310 	* type definition or a built-in primitive datatype.
15311 	*/
15312 	if (! WXS_IS_ATOMIC(type->baseType)) {
15313 	    xmlSchemaPCustomErr(pctxt,
15314 		XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
15315 		WXS_BASIC_CAST type, NULL,
15316 		"The base type '%s' is not an atomic simple type",
15317 		xmlSchemaGetComponentQName(&str, type->baseType));
15318 	    FREE_AND_NULL(str)
15319 	    return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
15320 	}
15321 	/* 1.2 The {final} of the {base type definition} must not contain
15322 	* restriction.
15323 	*/
15324 	/* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
15325 	if (xmlSchemaTypeFinalContains(type->baseType,
15326 	    XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15327 	    xmlSchemaPCustomErr(pctxt,
15328 		XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
15329 		WXS_BASIC_CAST type, NULL,
15330 		"The final of its base type '%s' must not contain 'restriction'",
15331 		xmlSchemaGetComponentQName(&str, type->baseType));
15332 	    FREE_AND_NULL(str)
15333 	    return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
15334 	}
15335 
15336 	/*
15337 	* 1.3.1 DF must be an allowed constraining facet for the {primitive
15338 	* type definition}, as specified in the appropriate subsection of 3.2
15339 	* Primitive datatypes.
15340 	*/
15341 	if (type->facets != NULL) {
15342 	    xmlSchemaFacetPtr facet;
15343 	    int ok = 1;
15344 
15345 	    primitive = xmlSchemaGetPrimitiveType(type);
15346 	    if (primitive == NULL) {
15347 		PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15348 		    "failed to get primitive type");
15349 		return (-1);
15350 	    }
15351 	    facet = type->facets;
15352 	    do {
15353 		if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
15354 		    ok = 0;
15355 		    xmlSchemaPIllegalFacetAtomicErr(pctxt,
15356 			XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
15357 			type, primitive, facet);
15358 		}
15359 		facet = facet->next;
15360 	    } while (facet != NULL);
15361 	    if (ok == 0)
15362 		return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
15363 	}
15364 	/*
15365 	* SPEC (1.3.2) "If there is a facet of the same kind in the {facets}
15366 	* of the {base type definition} (call this BF),then the DF's {value}
15367 	* must be a valid restriction of BF's {value} as defined in
15368 	* [XML Schemas: Datatypes]."
15369 	*
15370 	* NOTE (1.3.2) Facet derivation constraints are currently handled in
15371 	* xmlSchemaDeriveAndValidateFacets()
15372 	*/
15373     } else if (WXS_IS_LIST(type)) {
15374 	xmlSchemaTypePtr itemType = NULL;
15375 
15376 	itemType = type->subtypes;
15377 	if ((itemType == NULL) || (! WXS_IS_SIMPLE(itemType))) {
15378 	    PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15379 		"failed to evaluate the item type");
15380 	    return (-1);
15381 	}
15382 	if (WXS_IS_TYPE_NOT_FIXED(itemType))
15383 	    xmlSchemaTypeFixup(itemType, ACTXT_CAST pctxt);
15384 	/*
15385 	* 2.1 The {item type definition} must have a {variety} of atomic or
15386 	* union (in which case all the {member type definitions}
15387 	* must be atomic).
15388 	*/
15389 	if ((! WXS_IS_ATOMIC(itemType)) &&
15390 	    (! WXS_IS_UNION(itemType))) {
15391 	    xmlSchemaPCustomErr(pctxt,
15392 		XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
15393 		WXS_BASIC_CAST type, NULL,
15394 		"The item type '%s' does not have a variety of atomic or union",
15395 		xmlSchemaGetComponentQName(&str, itemType));
15396 	    FREE_AND_NULL(str)
15397 	    return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
15398 	} else if (WXS_IS_UNION(itemType)) {
15399 	    xmlSchemaTypeLinkPtr member;
15400 
15401 	    member = itemType->memberTypes;
15402 	    while (member != NULL) {
15403 		if (! WXS_IS_ATOMIC(member->type)) {
15404 		    xmlSchemaPCustomErr(pctxt,
15405 			XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
15406 			WXS_BASIC_CAST type, NULL,
15407 			"The item type is a union type, but the "
15408 			"member type '%s' of this item type is not atomic",
15409 			xmlSchemaGetComponentQName(&str, member->type));
15410 		    FREE_AND_NULL(str)
15411 		    return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
15412 		}
15413 		member = member->next;
15414 	    }
15415 	}
15416 
15417 	if (WXS_IS_ANY_SIMPLE_TYPE(type->baseType)) {
15418 	    xmlSchemaFacetPtr facet;
15419 	    /*
15420 	    * This is the case if we have: <simpleType><list ..
15421 	    */
15422 	    /*
15423 	    * 2.3.1
15424 	    * 2.3.1.1 The {final} of the {item type definition} must not
15425 	    * contain list.
15426 	    */
15427 	    if (xmlSchemaTypeFinalContains(itemType,
15428 		XML_SCHEMAS_TYPE_FINAL_LIST)) {
15429 		xmlSchemaPCustomErr(pctxt,
15430 		    XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
15431 		    WXS_BASIC_CAST type, NULL,
15432 		    "The final of its item type '%s' must not contain 'list'",
15433 		    xmlSchemaGetComponentQName(&str, itemType));
15434 		FREE_AND_NULL(str)
15435 		return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
15436 	    }
15437 	    /*
15438 	    * 2.3.1.2 The {facets} must only contain the whiteSpace
15439 	    * facet component.
15440 	    * OPTIMIZE TODO: the S4S already disallows any facet
15441 	    * to be specified.
15442 	    */
15443 	    if (type->facets != NULL) {
15444 		facet = type->facets;
15445 		do {
15446 		    if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
15447 			xmlSchemaPIllegalFacetListUnionErr(pctxt,
15448 			    XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
15449 			    type, facet);
15450 			return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
15451 		    }
15452 		    facet = facet->next;
15453 		} while (facet != NULL);
15454 	    }
15455 	    /*
15456 	    * MAYBE TODO: (Hmm, not really) Datatypes states:
15457 	    * A `list` datatype can be `derived` from an `atomic` datatype
15458 	    * whose `lexical space` allows space (such as string or anyURI)or
15459 	    * a `union` datatype any of whose {member type definitions}'s
15460 	    * `lexical space` allows space.
15461 	    */
15462 	} else {
15463 	    /*
15464 	    * This is the case if we have: <simpleType><restriction ...
15465 	    * I.e. the variety of "list" is inherited.
15466 	    */
15467 	    /*
15468 	    * 2.3.2
15469 	    * 2.3.2.1 The {base type definition} must have a {variety} of list.
15470 	    */
15471 	    if (! WXS_IS_LIST(type->baseType)) {
15472 		xmlSchemaPCustomErr(pctxt,
15473 		    XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
15474 		    WXS_BASIC_CAST type, NULL,
15475 		    "The base type '%s' must be a list type",
15476 		    xmlSchemaGetComponentQName(&str, type->baseType));
15477 		FREE_AND_NULL(str)
15478 		return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
15479 	    }
15480 	    /*
15481 	    * 2.3.2.2 The {final} of the {base type definition} must not
15482 	    * contain restriction.
15483 	    */
15484 	    if (xmlSchemaTypeFinalContains(type->baseType,
15485 		XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15486 		xmlSchemaPCustomErr(pctxt,
15487 		    XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
15488 		    WXS_BASIC_CAST type, NULL,
15489 		    "The 'final' of the base type '%s' must not contain 'restriction'",
15490 		    xmlSchemaGetComponentQName(&str, type->baseType));
15491 		FREE_AND_NULL(str)
15492 		return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
15493 	    }
15494 	    /*
15495 	    * 2.3.2.3 The {item type definition} must be validly derived
15496 	    * from the {base type definition}'s {item type definition} given
15497 	    * the empty set, as defined in Type Derivation OK (Simple) ($3.14.6).
15498 	    */
15499 	    {
15500 		xmlSchemaTypePtr baseItemType;
15501 
15502 		baseItemType = type->baseType->subtypes;
15503 		if ((baseItemType == NULL) || (! WXS_IS_SIMPLE(baseItemType))) {
15504 		    PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15505 			"failed to eval the item type of a base type");
15506 		    return (-1);
15507 		}
15508 		if ((itemType != baseItemType) &&
15509 		    (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt, itemType,
15510 			baseItemType, 0) != 0)) {
15511 		    xmlChar *strBIT = NULL, *strBT = NULL;
15512 		    xmlSchemaPCustomErrExt(pctxt,
15513 			XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
15514 			WXS_BASIC_CAST type, NULL,
15515 			"The item type '%s' is not validly derived from "
15516 			"the item type '%s' of the base type '%s'",
15517 			xmlSchemaGetComponentQName(&str, itemType),
15518 			xmlSchemaGetComponentQName(&strBIT, baseItemType),
15519 			xmlSchemaGetComponentQName(&strBT, type->baseType));
15520 
15521 		    FREE_AND_NULL(str)
15522 		    FREE_AND_NULL(strBIT)
15523 		    FREE_AND_NULL(strBT)
15524 		    return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
15525 		}
15526 	    }
15527 
15528 	    if (type->facets != NULL) {
15529 		xmlSchemaFacetPtr facet;
15530 		int ok = 1;
15531 		/*
15532 		* 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
15533 		* and enumeration facet components are allowed among the {facets}.
15534 		*/
15535 		facet = type->facets;
15536 		do {
15537 		    switch (facet->type) {
15538 			case XML_SCHEMA_FACET_LENGTH:
15539 			case XML_SCHEMA_FACET_MINLENGTH:
15540 			case XML_SCHEMA_FACET_MAXLENGTH:
15541 			case XML_SCHEMA_FACET_WHITESPACE:
15542 			    /*
15543 			    * TODO: 2.5.1.2 List datatypes
15544 			    * The value of `whiteSpace` is fixed to the value collapse.
15545 			    */
15546 			case XML_SCHEMA_FACET_PATTERN:
15547 			case XML_SCHEMA_FACET_ENUMERATION:
15548 			    break;
15549 			default: {
15550 			    xmlSchemaPIllegalFacetListUnionErr(pctxt,
15551 				XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
15552 				type, facet);
15553 			    /*
15554 			    * We could return, but it's nicer to report all
15555 			    * invalid facets.
15556 			    */
15557 			    ok = 0;
15558 			}
15559 		    }
15560 		    facet = facet->next;
15561 		} while (facet != NULL);
15562 		if (ok == 0)
15563 		    return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
15564 		/*
15565 		* SPEC (2.3.2.5) (same as 1.3.2)
15566 		*
15567 		* NOTE (2.3.2.5) This is currently done in
15568 		* xmlSchemaDeriveAndValidateFacets()
15569 		*/
15570 	    }
15571 	}
15572     } else if (WXS_IS_UNION(type)) {
15573 	/*
15574 	* 3.1 The {member type definitions} must all have {variety} of
15575 	* atomic or list.
15576 	*/
15577 	xmlSchemaTypeLinkPtr member;
15578 
15579 	member = type->memberTypes;
15580 	while (member != NULL) {
15581 	    if (WXS_IS_TYPE_NOT_FIXED(member->type))
15582 		xmlSchemaTypeFixup(member->type, ACTXT_CAST pctxt);
15583 
15584 	    if ((! WXS_IS_ATOMIC(member->type)) &&
15585 		(! WXS_IS_LIST(member->type))) {
15586 		xmlSchemaPCustomErr(pctxt,
15587 		    XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
15588 		    WXS_BASIC_CAST type, NULL,
15589 		    "The member type '%s' is neither an atomic, nor a list type",
15590 		    xmlSchemaGetComponentQName(&str, member->type));
15591 		FREE_AND_NULL(str)
15592 		return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
15593 	    }
15594 	    member = member->next;
15595 	}
15596 	/*
15597 	* 3.3.1 If the {base type definition} is the `simple ur-type
15598 	* definition`
15599 	*/
15600 	if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) {
15601 	    /*
15602 	    * 3.3.1.1 All of the {member type definitions} must have a
15603 	    * {final} which does not contain union.
15604 	    */
15605 	    member = type->memberTypes;
15606 	    while (member != NULL) {
15607 		if (xmlSchemaTypeFinalContains(member->type,
15608 		    XML_SCHEMAS_TYPE_FINAL_UNION)) {
15609 		    xmlSchemaPCustomErr(pctxt,
15610 			XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
15611 			WXS_BASIC_CAST type, NULL,
15612 			"The 'final' of member type '%s' contains 'union'",
15613 			xmlSchemaGetComponentQName(&str, member->type));
15614 		    FREE_AND_NULL(str)
15615 		    return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
15616 		}
15617 		member = member->next;
15618 	    }
15619 	    /*
15620 	    * 3.3.1.2 The {facets} must be empty.
15621 	    */
15622 	    if (type->facetSet != NULL) {
15623 		xmlSchemaPCustomErr(pctxt,
15624 		    XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
15625 		    WXS_BASIC_CAST type, NULL,
15626 		    "No facets allowed", NULL);
15627 		return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
15628 	    }
15629 	} else {
15630 	    /*
15631 	    * 3.3.2.1 The {base type definition} must have a {variety} of union.
15632 	    * I.e. the variety of "list" is inherited.
15633 	    */
15634 	    if (! WXS_IS_UNION(type->baseType)) {
15635 		xmlSchemaPCustomErr(pctxt,
15636 		    XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
15637 		    WXS_BASIC_CAST type, NULL,
15638 		    "The base type '%s' is not a union type",
15639 		    xmlSchemaGetComponentQName(&str, type->baseType));
15640 		FREE_AND_NULL(str)
15641 		return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
15642 	    }
15643 	    /*
15644 	    * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
15645 	    */
15646 	    if (xmlSchemaTypeFinalContains(type->baseType,
15647 		XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15648 		xmlSchemaPCustomErr(pctxt,
15649 		    XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
15650 		    WXS_BASIC_CAST type, NULL,
15651 		    "The 'final' of its base type '%s' must not contain 'restriction'",
15652 		    xmlSchemaGetComponentQName(&str, type->baseType));
15653 		FREE_AND_NULL(str)
15654 		return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
15655 	    }
15656 	    /*
15657 	    * 3.3.2.3 The {member type definitions}, in order, must be validly
15658 	    * derived from the corresponding type definitions in the {base
15659 	    * type definition}'s {member type definitions} given the empty set,
15660 	    * as defined in Type Derivation OK (Simple) ($3.14.6).
15661 	    */
15662 	    {
15663 		xmlSchemaTypeLinkPtr baseMember;
15664 
15665 		/*
15666 		* OPTIMIZE: if the type is restricting, it has no local defined
15667 		* member types and inherits the member types of the base type;
15668 		* thus a check for equality can be skipped.
15669 		*/
15670 		/*
15671 		* Even worse: I cannot see a scenario where a restricting
15672 		* union simple type can have other member types as the member
15673 		* types of it's base type. This check seems not necessary with
15674 		* respect to the derivation process in libxml2.
15675 		* But necessary if constructing types with an API.
15676 		*/
15677 		if (type->memberTypes != NULL) {
15678 		    member = type->memberTypes;
15679 		    baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
15680 		    if ((member == NULL) && (baseMember != NULL)) {
15681 			PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15682 			    "different number of member types in base");
15683 		    }
15684 		    while (member != NULL) {
15685 			if (baseMember == NULL) {
15686 			    PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15687 			    "different number of member types in base");
15688 			} else if ((member->type != baseMember->type) &&
15689 			    (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
15690 				member->type, baseMember->type, 0) != 0)) {
15691 			    xmlChar *strBMT = NULL, *strBT = NULL;
15692 
15693 			    xmlSchemaPCustomErrExt(pctxt,
15694 				XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
15695 				WXS_BASIC_CAST type, NULL,
15696 				"The member type %s is not validly "
15697 				"derived from its corresponding member "
15698 				"type %s of the base type %s",
15699 				xmlSchemaGetComponentQName(&str, member->type),
15700 				xmlSchemaGetComponentQName(&strBMT, baseMember->type),
15701 				xmlSchemaGetComponentQName(&strBT, type->baseType));
15702 			    FREE_AND_NULL(str)
15703 			    FREE_AND_NULL(strBMT)
15704 			    FREE_AND_NULL(strBT)
15705 			    return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
15706 			}
15707 			member = member->next;
15708                         if (baseMember != NULL)
15709                             baseMember = baseMember->next;
15710 		    }
15711 		}
15712 	    }
15713 	    /*
15714 	    * 3.3.2.4 Only pattern and enumeration facet components are
15715 	    * allowed among the {facets}.
15716 	    */
15717 	    if (type->facets != NULL) {
15718 		xmlSchemaFacetPtr facet;
15719 		int ok = 1;
15720 
15721 		facet = type->facets;
15722 		do {
15723 		    if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
15724 			(facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
15725 			xmlSchemaPIllegalFacetListUnionErr(pctxt,
15726 				XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
15727 				type, facet);
15728 			ok = 0;
15729 		    }
15730 		    facet = facet->next;
15731 		} while (facet != NULL);
15732 		if (ok == 0)
15733 		    return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
15734 
15735 	    }
15736 	    /*
15737 	    * SPEC (3.3.2.5) (same as 1.3.2)
15738 	    *
15739 	    * NOTE (3.3.2.5) This is currently done in
15740 	    * xmlSchemaDeriveAndValidateFacets()
15741 	    */
15742 	}
15743     }
15744 
15745     return (0);
15746 }
15747 
15748 /**
15749  * xmlSchemaCheckSRCSimpleType:
15750  * @ctxt:  the schema parser context
15751  * @type:  the simple type definition
15752  *
15753  * Checks crc-simple-type constraints.
15754  *
15755  * Returns 0 if the constraints are satisfied,
15756  * if not a positive error code and -1 on internal
15757  * errors.
15758  */
15759 #if 0
15760 static int
15761 xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
15762 			    xmlSchemaTypePtr type)
15763 {
15764     /*
15765     * src-simple-type.1 The corresponding simple type definition, if any,
15766     * must satisfy the conditions set out in Constraints on Simple Type
15767     * Definition Schema Components ($3.14.6).
15768     */
15769     if (WXS_IS_RESTRICTION(type)) {
15770 	/*
15771 	* src-simple-type.2 "If the <restriction> alternative is chosen,
15772 	* either it must have a base [attribute] or a <simpleType> among its
15773 	* [children], but not both."
15774 	* NOTE: This is checked in the parse function of <restriction>.
15775 	*/
15776 	/*
15777 	*
15778 	*/
15779     } else if (WXS_IS_LIST(type)) {
15780 	/* src-simple-type.3 "If the <list> alternative is chosen, either it must have
15781 	* an itemType [attribute] or a <simpleType> among its [children],
15782 	* but not both."
15783 	*
15784 	* NOTE: This is checked in the parse function of <list>.
15785 	*/
15786     } else if (WXS_IS_UNION(type)) {
15787 	/*
15788 	* src-simple-type.4 is checked in xmlSchemaCheckUnionTypeDefCircular().
15789 	*/
15790     }
15791     return (0);
15792 }
15793 #endif
15794 
15795 static int
xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)15796 xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
15797 {
15798    if (ctxt->vctxt == NULL) {
15799 	ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
15800 	if (ctxt->vctxt == NULL) {
15801 	    xmlSchemaPErr(ctxt, NULL,
15802 		XML_SCHEMAP_INTERNAL,
15803 		"Internal error: xmlSchemaCreateVCtxtOnPCtxt, "
15804 		"failed to create a temp. validation context.\n",
15805 		NULL, NULL);
15806 	    return (-1);
15807 	}
15808 	/* TODO: Pass user data. */
15809 	xmlSchemaSetValidErrors(ctxt->vctxt,
15810 	    ctxt->error, ctxt->warning, ctxt->errCtxt);
15811 	xmlSchemaSetValidStructuredErrors(ctxt->vctxt,
15812 	    ctxt->serror, ctxt->errCtxt);
15813     }
15814     return (0);
15815 }
15816 
15817 static int
15818 xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
15819 			     xmlNodePtr node,
15820 			     xmlSchemaTypePtr type,
15821 			     const xmlChar *value,
15822 			     xmlSchemaValPtr *retVal,
15823 			     int fireErrors,
15824 			     int normalize,
15825 			     int isNormalized);
15826 
15827 /**
15828  * xmlSchemaParseCheckCOSValidDefault:
15829  * @pctxt:  the schema parser context
15830  * @type:  the simple type definition
15831  * @value: the default value
15832  * @node: an optional node (the holder of the value)
15833  *
15834  * Schema Component Constraint: Element Default Valid (Immediate)
15835  * (cos-valid-default)
15836  * This will be used by the parser only. For the validator there's
15837  * an other version.
15838  *
15839  * Returns 0 if the constraints are satisfied,
15840  * if not, a positive error code and -1 on internal
15841  * errors.
15842  */
15843 static int
xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,xmlNodePtr node,xmlSchemaTypePtr type,const xmlChar * value,xmlSchemaValPtr * val)15844 xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
15845 				   xmlNodePtr node,
15846 				   xmlSchemaTypePtr type,
15847 				   const xmlChar *value,
15848 				   xmlSchemaValPtr *val)
15849 {
15850     int ret = 0;
15851 
15852     /*
15853     * cos-valid-default:
15854     * Schema Component Constraint: Element Default Valid (Immediate)
15855     * For a string to be a valid default with respect to a type
15856     * definition the appropriate case among the following must be true:
15857     */
15858     if WXS_IS_COMPLEX(type) {
15859 	/*
15860 	* Complex type.
15861 	*
15862 	* SPEC (2.1) "its {content type} must be a simple type definition
15863 	* or mixed."
15864 	* SPEC (2.2.2) "If the {content type} is mixed, then the {content
15865 	* type}'s particle must be `emptiable` as defined by
15866 	* Particle Emptiable ($3.9.6)."
15867 	*/
15868 	if ((! WXS_HAS_SIMPLE_CONTENT(type)) &&
15869 	    ((! WXS_HAS_MIXED_CONTENT(type)) || (! WXS_EMPTIABLE(type)))) {
15870 	    /* NOTE that this covers (2.2.2) as well. */
15871 	    xmlSchemaPCustomErr(pctxt,
15872 		XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
15873 		WXS_BASIC_CAST type, type->node,
15874 		"For a string to be a valid default, the type definition "
15875 		"must be a simple type or a complex type with mixed content "
15876 		"and a particle emptiable", NULL);
15877 	    return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
15878 	}
15879     }
15880     /*
15881     * 1 If the type definition is a simple type definition, then the string
15882     * must be `valid` with respect to that definition as defined by String
15883     * Valid ($3.14.4).
15884     *
15885     * AND
15886     *
15887     * 2.2.1 If the {content type} is a simple type definition, then the
15888     * string must be `valid` with respect to that simple type definition
15889     * as defined by String Valid ($3.14.4).
15890     */
15891     if (WXS_IS_SIMPLE(type))
15892 	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
15893 	    type, value, val, 1, 1, 0);
15894     else if (WXS_HAS_SIMPLE_CONTENT(type))
15895 	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
15896 	    type->contentTypeDef, value, val, 1, 1, 0);
15897     else
15898 	return (ret);
15899 
15900     if (ret < 0) {
15901 	PERROR_INT("xmlSchemaParseCheckCOSValidDefault",
15902 	    "calling xmlSchemaVCheckCVCSimpleType()");
15903     }
15904 
15905     return (ret);
15906 }
15907 
15908 /**
15909  * xmlSchemaCheckCTPropsCorrect:
15910  * @ctxt:  the schema parser context
15911  * @type:  the complex type definition
15912  *
15913  *.(4.6) Constraints on Complex Type Definition Schema Components
15914  * Schema Component Constraint:
15915  * Complex Type Definition Properties Correct (ct-props-correct)
15916  * STATUS: (seems) complete
15917  *
15918  * Returns 0 if the constraints are satisfied, a positive
15919  * error code if not and -1 if an internal error occurred.
15920  */
15921 static int
xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)15922 xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
15923 			     xmlSchemaTypePtr type)
15924 {
15925     /*
15926     * TODO: Correct the error code; XML_SCHEMAP_SRC_CT_1 is used temporarily.
15927     *
15928     * SPEC (1) "The values of the properties of a complex type definition must
15929     * be as described in the property tableau in The Complex Type Definition
15930     * Schema Component ($3.4.1), modulo the impact of Missing
15931     * Sub-components ($5.3)."
15932     */
15933     if ((type->baseType != NULL) &&
15934 	(WXS_IS_SIMPLE(type->baseType)) &&
15935 	(WXS_IS_EXTENSION(type) == 0)) {
15936 	/*
15937 	* SPEC (2) "If the {base type definition} is a simple type definition,
15938 	* the {derivation method} must be extension."
15939 	*/
15940 	xmlSchemaCustomErr(ACTXT_CAST pctxt,
15941 	    XML_SCHEMAP_SRC_CT_1,
15942 	    NULL, WXS_BASIC_CAST type,
15943 	    "If the base type is a simple type, the derivation method must be "
15944 	    "'extension'", NULL, NULL);
15945 	return (XML_SCHEMAP_SRC_CT_1);
15946     }
15947     /*
15948     * SPEC (3) "Circular definitions are disallowed, except for the `ur-type
15949     * definition`. That is, it must be possible to reach the `ur-type
15950     * definition` by repeatedly following the {base type definition}."
15951     *
15952     * NOTE (3) is done in xmlSchemaCheckTypeDefCircular().
15953     */
15954     /*
15955     * NOTE that (4) and (5) need the following:
15956     *   - attribute uses need to be already inherited (apply attr. prohibitions)
15957     *   - attribute group references need to be expanded already
15958     *   - simple types need to be typefixed already
15959     */
15960     if (type->attrUses &&
15961 	(((xmlSchemaItemListPtr) type->attrUses)->nbItems > 1))
15962     {
15963 	xmlSchemaItemListPtr uses = (xmlSchemaItemListPtr) type->attrUses;
15964 	xmlSchemaAttributeUsePtr use, tmp;
15965 	int i, j, hasId = 0;
15966 
15967 	for (i = uses->nbItems -1; i >= 0; i--) {
15968 	    use = uses->items[i];
15969 
15970 	    /*
15971 	    * SPEC ct-props-correct
15972 	    * (4) "Two distinct attribute declarations in the
15973 	    * {attribute uses} must not have identical {name}s and
15974 	    * {target namespace}s."
15975 	    */
15976 	    if (i > 0) {
15977 		for (j = i -1; j >= 0; j--) {
15978 		    tmp = uses->items[j];
15979 		    if ((WXS_ATTRUSE_DECL_NAME(use) ==
15980 			WXS_ATTRUSE_DECL_NAME(tmp)) &&
15981 			(WXS_ATTRUSE_DECL_TNS(use) ==
15982 			WXS_ATTRUSE_DECL_TNS(tmp)))
15983 		    {
15984 			xmlChar *str = NULL;
15985 
15986 			xmlSchemaCustomErr(ACTXT_CAST pctxt,
15987 			    XML_SCHEMAP_AG_PROPS_CORRECT,
15988 			    NULL, WXS_BASIC_CAST type,
15989 			    "Duplicate %s",
15990 			    xmlSchemaGetComponentDesignation(&str, use),
15991 			    NULL);
15992 			FREE_AND_NULL(str);
15993 			/*
15994 			* Remove the duplicate.
15995 			*/
15996 			if (xmlSchemaItemListRemove(uses, i) == -1)
15997 			    goto exit_failure;
15998 			goto next_use;
15999 		    }
16000 		}
16001 	    }
16002 	    /*
16003 	    * SPEC ct-props-correct
16004 	    * (5) "Two distinct attribute declarations in the
16005 	    * {attribute uses} must not have {type definition}s which
16006 	    * are or are derived from ID."
16007 	    */
16008 	    if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
16009 		if (xmlSchemaIsDerivedFromBuiltInType(
16010 		    WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
16011 		{
16012 		    if (hasId) {
16013 			xmlChar *str = NULL;
16014 
16015 			xmlSchemaCustomErr(ACTXT_CAST pctxt,
16016 			    XML_SCHEMAP_AG_PROPS_CORRECT,
16017 			    NULL, WXS_BASIC_CAST type,
16018 			    "There must not exist more than one attribute "
16019 			    "declaration of type 'xs:ID' "
16020 			    "(or derived from 'xs:ID'). The %s violates this "
16021 			    "constraint",
16022 			    xmlSchemaGetComponentDesignation(&str, use),
16023 			    NULL);
16024 			FREE_AND_NULL(str);
16025 			if (xmlSchemaItemListRemove(uses, i) == -1)
16026 			    goto exit_failure;
16027 		    }
16028 
16029 		    hasId = 1;
16030 		}
16031 	    }
16032 next_use: {}
16033 	}
16034     }
16035     return (0);
16036 exit_failure:
16037     return(-1);
16038 }
16039 
16040 static int
xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,xmlSchemaTypePtr typeB)16041 xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,
16042 		       xmlSchemaTypePtr typeB)
16043 {
16044     /*
16045     * TODO: This should implement component-identity
16046     * in the future.
16047     */
16048     if ((typeA == NULL) || (typeB == NULL))
16049 	return (0);
16050     return (typeA == typeB);
16051 }
16052 
16053 /**
16054  * xmlSchemaCheckCOSCTDerivedOK:
16055  * @ctxt:  the schema parser context
16056  * @type:  the to-be derived complex type definition
16057  * @baseType:  the base complex type definition
16058  * @set: the given set
16059  *
16060  * Schema Component Constraint:
16061  * Type Derivation OK (Complex) (cos-ct-derived-ok)
16062  *
16063  * STATUS: completed
16064  *
16065  * Returns 0 if the constraints are satisfied, or 1
16066  * if not.
16067  */
16068 static int
xmlSchemaCheckCOSCTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,xmlSchemaTypePtr type,xmlSchemaTypePtr baseType,int set)16069 xmlSchemaCheckCOSCTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
16070 			     xmlSchemaTypePtr type,
16071 			     xmlSchemaTypePtr baseType,
16072 			     int set)
16073 {
16074     int equal = xmlSchemaAreEqualTypes(type, baseType);
16075     /* TODO: Error codes. */
16076     /*
16077     * SPEC "For a complex type definition (call it D, for derived)
16078     * to be validly derived from a type definition (call this
16079     * B, for base) given a subset of {extension, restriction}
16080     * all of the following must be true:"
16081     */
16082     if (! equal) {
16083 	/*
16084 	* SPEC (1) "If B and D are not the same type definition, then the
16085 	* {derivation method} of D must not be in the subset."
16086 	*/
16087 	if (((set & SUBSET_EXTENSION) && (WXS_IS_EXTENSION(type))) ||
16088 	    ((set & SUBSET_RESTRICTION) && (WXS_IS_RESTRICTION(type))))
16089 	    return (1);
16090     } else {
16091 	/*
16092 	* SPEC (2.1) "B and D must be the same type definition."
16093 	*/
16094 	return (0);
16095     }
16096     /*
16097     * SPEC (2.2) "B must be D's {base type definition}."
16098     */
16099     if (type->baseType == baseType)
16100 	return (0);
16101     /*
16102     * SPEC (2.3.1) "D's {base type definition} must not be the `ur-type
16103     * definition`."
16104     */
16105     if (WXS_IS_ANYTYPE(type->baseType))
16106 	return (1);
16107 
16108     if (WXS_IS_COMPLEX(type->baseType)) {
16109 	/*
16110 	* SPEC (2.3.2.1) "If D's {base type definition} is complex, then it
16111 	* must be validly derived from B given the subset as defined by this
16112 	* constraint."
16113 	*/
16114 	return (xmlSchemaCheckCOSCTDerivedOK(actxt, type->baseType,
16115 	    baseType, set));
16116     } else {
16117 	/*
16118 	* SPEC (2.3.2.2) "If D's {base type definition} is simple, then it
16119 	* must be validly derived from B given the subset as defined in Type
16120 	* Derivation OK (Simple) ($3.14.6).
16121 	*/
16122 	return (xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
16123 	    baseType, set));
16124     }
16125 }
16126 
16127 /**
16128  * xmlSchemaCheckCOSDerivedOK:
16129  * @type:  the derived simple type definition
16130  * @baseType:  the base type definition
16131  *
16132  * Calls:
16133  * Type Derivation OK (Simple) AND Type Derivation OK (Complex)
16134  *
16135  * Checks wheter @type can be validly derived from @baseType.
16136  *
16137  * Returns 0 on success, an positive error code otherwise.
16138  */
16139 static int
xmlSchemaCheckCOSDerivedOK(xmlSchemaAbstractCtxtPtr actxt,xmlSchemaTypePtr type,xmlSchemaTypePtr baseType,int set)16140 xmlSchemaCheckCOSDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
16141 			   xmlSchemaTypePtr type,
16142 			   xmlSchemaTypePtr baseType,
16143 			   int set)
16144 {
16145     if (WXS_IS_SIMPLE(type))
16146 	return (xmlSchemaCheckCOSSTDerivedOK(actxt, type, baseType, set));
16147     else
16148 	return (xmlSchemaCheckCOSCTDerivedOK(actxt, type, baseType, set));
16149 }
16150 
16151 /**
16152  * xmlSchemaCheckCOSCTExtends:
16153  * @ctxt:  the schema parser context
16154  * @type:  the complex type definition
16155  *
16156  * (3.4.6) Constraints on Complex Type Definition Schema Components
16157  * Schema Component Constraint:
16158  * Derivation Valid (Extension) (cos-ct-extends)
16159  *
16160  * STATUS:
16161  *   missing:
16162  *     (1.5)
16163  *     (1.4.3.2.2.2) "Particle Valid (Extension)"
16164  *
16165  * Returns 0 if the constraints are satisfied, a positive
16166  * error code if not and -1 if an internal error occurred.
16167  */
16168 static int
xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,xmlSchemaTypePtr type)16169 xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
16170 			   xmlSchemaTypePtr type)
16171 {
16172     xmlSchemaTypePtr base = type->baseType;
16173     /*
16174     * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
16175     * temporarily only.
16176     */
16177     /*
16178     * SPEC (1) "If the {base type definition} is a complex type definition,
16179     * then all of the following must be true:"
16180     */
16181     if (WXS_IS_COMPLEX(base)) {
16182 	/*
16183 	* SPEC (1.1) "The {final} of the {base type definition} must not
16184 	* contain extension."
16185 	*/
16186 	if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16187 	    xmlSchemaPCustomErr(ctxt,
16188 		XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16189 		WXS_BASIC_CAST type, NULL,
16190 		"The 'final' of the base type definition "
16191 		"contains 'extension'", NULL);
16192 	    return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16193 	}
16194 
16195 	/*
16196 	* ATTENTION: The constrains (1.2) and (1.3) are not applied,
16197 	* since they are automatically satisfied through the
16198 	* inheriting mechanism.
16199 	* Note that even if redefining components, the inheriting mechanism
16200 	* is used.
16201 	*/
16202 #if 0
16203 	/*
16204 	* SPEC (1.2) "Its {attribute uses} must be a subset of the {attribute
16205 	* uses}
16206 	* of the complex type definition itself, that is, for every attribute
16207 	* use in the {attribute uses} of the {base type definition}, there
16208 	* must be an attribute use in the {attribute uses} of the complex
16209 	* type definition itself whose {attribute declaration} has the same
16210 	* {name}, {target namespace} and {type definition} as its attribute
16211 	* declaration"
16212 	*/
16213 	if (base->attrUses != NULL) {
16214 	    int i, j, found;
16215 	    xmlSchemaAttributeUsePtr use, buse;
16216 
16217 	    for (i = 0; i < (WXS_LIST_CAST base->attrUses)->nbItems; i ++) {
16218 		buse = (WXS_LIST_CAST base->attrUses)->items[i];
16219 		found = 0;
16220 		if (type->attrUses != NULL) {
16221 		    use = (WXS_LIST_CAST type->attrUses)->items[j];
16222 		    for (j = 0; j < (WXS_LIST_CAST type->attrUses)->nbItems; j ++)
16223 		    {
16224 			if ((WXS_ATTRUSE_DECL_NAME(use) ==
16225 				WXS_ATTRUSE_DECL_NAME(buse)) &&
16226 			    (WXS_ATTRUSE_DECL_TNS(use) ==
16227 				WXS_ATTRUSE_DECL_TNS(buse)) &&
16228 			    (WXS_ATTRUSE_TYPEDEF(use) ==
16229 				WXS_ATTRUSE_TYPEDEF(buse))
16230 			{
16231 			    found = 1;
16232 			    break;
16233 			}
16234 		    }
16235 		}
16236 		if (! found) {
16237 		    xmlChar *str = NULL;
16238 
16239 		    xmlSchemaCustomErr(ACTXT_CAST ctxt,
16240 			XML_SCHEMAP_COS_CT_EXTENDS_1_2,
16241 			NULL, WXS_BASIC_CAST type,
16242 			/*
16243 			* TODO: The report does not indicate that also the
16244 			* type needs to be the same.
16245 			*/
16246 			"This type is missing a matching correspondent "
16247 			"for its {base type}'s %s in its {attribute uses}",
16248 			xmlSchemaGetComponentDesignation(&str,
16249 			    buse->children),
16250 			NULL);
16251 		    FREE_AND_NULL(str)
16252 		}
16253 	    }
16254 	}
16255 	/*
16256 	* SPEC (1.3) "If it has an {attribute wildcard}, the complex type
16257 	* definition must also have one, and the base type definition's
16258 	* {attribute  wildcard}'s {namespace constraint} must be a subset
16259 	* of the complex  type definition's {attribute wildcard}'s {namespace
16260 	* constraint}, as defined by Wildcard Subset ($3.10.6)."
16261 	*/
16262 
16263 	/*
16264 	* MAYBE TODO: Enable if ever needed. But this will be needed only
16265 	* if created the type via a schema construction API.
16266 	*/
16267 	if (base->attributeWildcard != NULL) {
16268 	    if (type->attributeWilcard == NULL) {
16269 		xmlChar *str = NULL;
16270 
16271 		xmlSchemaCustomErr(ACTXT_CAST pctxt,
16272 		    XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16273 		    NULL, type,
16274 		    "The base %s has an attribute wildcard, "
16275 		    "but this type is missing an attribute wildcard",
16276 		    xmlSchemaGetComponentDesignation(&str, base));
16277 		FREE_AND_NULL(str)
16278 
16279 	    } else if (xmlSchemaCheckCOSNSSubset(
16280 		base->attributeWildcard, type->attributeWildcard))
16281 	    {
16282 		xmlChar *str = NULL;
16283 
16284 		xmlSchemaCustomErr(ACTXT_CAST pctxt,
16285 		    XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16286 		    NULL, type,
16287 		    "The attribute wildcard is not a valid "
16288 		    "superset of the one in the base %s",
16289 		    xmlSchemaGetComponentDesignation(&str, base));
16290 		FREE_AND_NULL(str)
16291 	    }
16292 	}
16293 #endif
16294 	/*
16295 	* SPEC (1.4) "One of the following must be true:"
16296 	*/
16297 	if ((type->contentTypeDef != NULL) &&
16298 	    (type->contentTypeDef == base->contentTypeDef)) {
16299 	    /*
16300 	    * SPEC (1.4.1) "The {content type} of the {base type definition}
16301 	    * and the {content type} of the complex type definition itself
16302 	    * must be the same simple type definition"
16303 	    * PASS
16304 	    */
16305 	} else if ((type->contentType == XML_SCHEMA_CONTENT_EMPTY) &&
16306 	    (base->contentType == XML_SCHEMA_CONTENT_EMPTY) ) {
16307 	    /*
16308 	    * SPEC (1.4.2) "The {content type} of both the {base type
16309 	    * definition} and the complex type definition itself must
16310 	    * be empty."
16311 	    * PASS
16312 	    */
16313 	} else {
16314 	    /*
16315 	    * SPEC (1.4.3) "All of the following must be true:"
16316 	    */
16317 	    if (type->subtypes == NULL) {
16318 		/*
16319 		* SPEC 1.4.3.1 The {content type} of the complex type
16320 		* definition itself must specify a particle.
16321 		*/
16322 		xmlSchemaPCustomErr(ctxt,
16323 		    XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16324 		    WXS_BASIC_CAST type, NULL,
16325 		    "The content type must specify a particle", NULL);
16326 		return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16327 	    }
16328 	    /*
16329 	    * SPEC (1.4.3.2) "One of the following must be true:"
16330 	    */
16331 	    if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16332 		/*
16333 		* SPEC (1.4.3.2.1) "The {content type} of the {base type
16334 		* definition} must be empty.
16335 		* PASS
16336 		*/
16337 	    } else {
16338 		/*
16339 		* SPEC (1.4.3.2.2) "All of the following must be true:"
16340 		*/
16341 		if ((type->contentType != base->contentType) ||
16342 		    ((type->contentType != XML_SCHEMA_CONTENT_MIXED) &&
16343 		    (type->contentType != XML_SCHEMA_CONTENT_ELEMENTS))) {
16344 		    /*
16345 		    * SPEC (1.4.3.2.2.1) "Both {content type}s must be mixed
16346 		    * or both must be element-only."
16347 		    */
16348 		    xmlSchemaPCustomErr(ctxt,
16349 			XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16350 			WXS_BASIC_CAST type, NULL,
16351 			"The content type of both, the type and its base "
16352 			"type, must either 'mixed' or 'element-only'", NULL);
16353 		    return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16354 		}
16355 		/*
16356 		* URGENT TODO SPEC (1.4.3.2.2.2) "The particle of the
16357 		* complex type definition must be a `valid extension`
16358 		* of the {base type definition}'s particle, as defined
16359 		* in Particle Valid (Extension) ($3.9.6)."
16360 		*
16361 		* NOTE that we won't check "Particle Valid (Extension)",
16362 		* since it is ensured by the derivation process in
16363 		* xmlSchemaTypeFixup(). We need to implement this when heading
16364 		* for a construction API
16365 		* TODO: !! This is needed to be checked if redefining a type !!
16366 		*/
16367 	    }
16368 	    /*
16369 	    * URGENT TODO (1.5)
16370 	    */
16371 	}
16372     } else {
16373 	/*
16374 	* SPEC (2) "If the {base type definition} is a simple type definition,
16375 	* then all of the following must be true:"
16376 	*/
16377 	if (type->contentTypeDef != base) {
16378 	    /*
16379 	    * SPEC (2.1) "The {content type} must be the same simple type
16380 	    * definition."
16381 	    */
16382 	    xmlSchemaPCustomErr(ctxt,
16383 		XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16384 		WXS_BASIC_CAST type, NULL,
16385 		"The content type must be the simple base type", NULL);
16386 	    return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16387 	}
16388 	if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16389 	    /*
16390 	    * SPEC (2.2) "The {final} of the {base type definition} must not
16391 	    * contain extension"
16392 	    * NOTE that this is the same as (1.1).
16393 	    */
16394 	    xmlSchemaPCustomErr(ctxt,
16395 		XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16396 		WXS_BASIC_CAST type, NULL,
16397 		"The 'final' of the base type definition "
16398 		"contains 'extension'", NULL);
16399 	    return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16400 	}
16401     }
16402     return (0);
16403 }
16404 
16405 /**
16406  * xmlSchemaCheckDerivationOKRestriction:
16407  * @ctxt:  the schema parser context
16408  * @type:  the complex type definition
16409  *
16410  * (3.4.6) Constraints on Complex Type Definition Schema Components
16411  * Schema Component Constraint:
16412  * Derivation Valid (Restriction, Complex) (derivation-ok-restriction)
16413  *
16414  * STATUS:
16415  *   missing:
16416  *     (5.4.2) ???
16417  *
16418  * ATTENTION:
16419  * In XML Schema 1.1 this will be:
16420  * Validation Rule: Checking complex type subsumption
16421  *
16422  * Returns 0 if the constraints are satisfied, a positive
16423  * error code if not and -1 if an internal error occurred.
16424  */
16425 static int
xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,xmlSchemaTypePtr type)16426 xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,
16427 				      xmlSchemaTypePtr type)
16428 {
16429     xmlSchemaTypePtr base;
16430 
16431     /*
16432     * TODO: Correct the error code; XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1 is used
16433     * temporarily only.
16434     */
16435     base = type->baseType;
16436     if (! WXS_IS_COMPLEX(base)) {
16437 	xmlSchemaCustomErr(ACTXT_CAST ctxt,
16438 	    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16439 	    type->node, WXS_BASIC_CAST type,
16440 	    "The base type must be a complex type", NULL, NULL);
16441 	return(ctxt->err);
16442     }
16443     if (base->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) {
16444 	/*
16445 	* SPEC (1) "The {base type definition} must be a complex type
16446 	* definition whose {final} does not contain restriction."
16447 	*/
16448 	xmlSchemaCustomErr(ACTXT_CAST ctxt,
16449 	    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16450 	    type->node, WXS_BASIC_CAST type,
16451 	    "The 'final' of the base type definition "
16452 	    "contains 'restriction'", NULL, NULL);
16453 	return (ctxt->err);
16454     }
16455     /*
16456     * SPEC (2), (3) and (4)
16457     * Those are handled in a separate function, since the
16458     * same constraints are needed for redefinition of
16459     * attribute groups as well.
16460     */
16461     if (xmlSchemaCheckDerivationOKRestriction2to4(ctxt,
16462 	XML_SCHEMA_ACTION_DERIVE,
16463 	WXS_BASIC_CAST type, WXS_BASIC_CAST base,
16464 	type->attrUses, base->attrUses,
16465 	type->attributeWildcard,
16466 	base->attributeWildcard) == -1)
16467     {
16468 	return(-1);
16469     }
16470     /*
16471     * SPEC (5) "One of the following must be true:"
16472     */
16473     if (base->builtInType == XML_SCHEMAS_ANYTYPE) {
16474 	/*
16475 	* SPEC (5.1) "The {base type definition} must be the
16476 	* `ur-type definition`."
16477 	* PASS
16478 	*/
16479     } else if ((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16480 	    (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16481 	/*
16482 	* SPEC (5.2.1) "The {content type} of the complex type definition
16483 	* must be a simple type definition"
16484 	*
16485 	* SPEC (5.2.2) "One of the following must be true:"
16486 	*/
16487 	if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16488 	    (base->contentType == XML_SCHEMA_CONTENT_BASIC))
16489 	{
16490 	    int err;
16491 	    /*
16492 	    * SPEC (5.2.2.1) "The {content type} of the {base type
16493 	    * definition} must be a simple type definition from which
16494 	    * the {content type} is validly derived given the empty
16495 	    * set as defined in Type Derivation OK (Simple) ($3.14.6)."
16496 	    *
16497 	    * ATTENTION TODO: This seems not needed if the type implicitely
16498 	    * derived from the base type.
16499 	    *
16500 	    */
16501 	    err = xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST ctxt,
16502 		type->contentTypeDef, base->contentTypeDef, 0);
16503 	    if (err != 0) {
16504 		xmlChar *strA = NULL, *strB = NULL;
16505 
16506 		if (err == -1)
16507 		    return(-1);
16508 		xmlSchemaCustomErr(ACTXT_CAST ctxt,
16509 		    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16510 		    NULL, WXS_BASIC_CAST type,
16511 		    "The {content type} %s is not validly derived from the "
16512 		    "base type's {content type} %s",
16513 		    xmlSchemaGetComponentDesignation(&strA,
16514 			type->contentTypeDef),
16515 		    xmlSchemaGetComponentDesignation(&strB,
16516 			base->contentTypeDef));
16517 		FREE_AND_NULL(strA);
16518 		FREE_AND_NULL(strB);
16519 		return(ctxt->err);
16520 	    }
16521 	} else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16522 	    (xmlSchemaIsParticleEmptiable(
16523 		(xmlSchemaParticlePtr) base->subtypes))) {
16524 	    /*
16525 	    * SPEC (5.2.2.2) "The {base type definition} must be mixed
16526 	    * and have a particle which is `emptiable` as defined in
16527 	    * Particle Emptiable ($3.9.6)."
16528 	    * PASS
16529 	    */
16530 	} else {
16531 	    xmlSchemaPCustomErr(ctxt,
16532 		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16533 		WXS_BASIC_CAST type, NULL,
16534 		"The content type of the base type must be either "
16535 		"a simple type or 'mixed' and an emptiable particle", NULL);
16536 	    return (ctxt->err);
16537 	}
16538     } else if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16539 	/*
16540 	* SPEC (5.3.1) "The {content type} of the complex type itself must
16541 	* be empty"
16542 	*/
16543 	if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16544 	    /*
16545 	    * SPEC (5.3.2.1) "The {content type} of the {base type
16546 	    * definition} must also be empty."
16547 	    * PASS
16548 	    */
16549 	} else if (((base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16550 	    (base->contentType == XML_SCHEMA_CONTENT_MIXED)) &&
16551 	    xmlSchemaIsParticleEmptiable(
16552 		(xmlSchemaParticlePtr) base->subtypes)) {
16553 	    /*
16554 	    * SPEC (5.3.2.2) "The {content type} of the {base type
16555 	    * definition} must be elementOnly or mixed and have a particle
16556 	    * which is `emptiable` as defined in Particle Emptiable ($3.9.6)."
16557 	    * PASS
16558 	    */
16559 	} else {
16560 	    xmlSchemaPCustomErr(ctxt,
16561 		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16562 		WXS_BASIC_CAST type, NULL,
16563 		"The content type of the base type must be either "
16564 		"empty or 'mixed' (or 'elements-only') and an emptiable "
16565 		"particle", NULL);
16566 	    return (ctxt->err);
16567 	}
16568     } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16569 	WXS_HAS_MIXED_CONTENT(type)) {
16570 	/*
16571 	* SPEC (5.4.1.1) "The {content type} of the complex type definition
16572 	* itself must be element-only"
16573 	*/
16574 	if (WXS_HAS_MIXED_CONTENT(type) && (! WXS_HAS_MIXED_CONTENT(base))) {
16575 	    /*
16576 	    * SPEC (5.4.1.2) "The {content type} of the complex type
16577 	    * definition itself and of the {base type definition} must be
16578 	    * mixed"
16579 	    */
16580 	    xmlSchemaPCustomErr(ctxt,
16581 		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16582 		WXS_BASIC_CAST type, NULL,
16583 		"If the content type is 'mixed', then the content type of the "
16584 		"base type must also be 'mixed'", NULL);
16585 	    return (ctxt->err);
16586 	}
16587 	/*
16588 	* SPEC (5.4.2) "The particle of the complex type definition itself
16589 	* must be a `valid restriction` of the particle of the {content
16590 	* type} of the {base type definition} as defined in Particle Valid
16591 	* (Restriction) ($3.9.6).
16592 	*
16593 	* URGENT TODO: (5.4.2)
16594 	*/
16595     } else {
16596 	xmlSchemaPCustomErr(ctxt,
16597 	    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16598 	    WXS_BASIC_CAST type, NULL,
16599 	    "The type is not a valid restriction of its base type", NULL);
16600 	return (ctxt->err);
16601     }
16602     return (0);
16603 }
16604 
16605 /**
16606  * xmlSchemaCheckCTComponent:
16607  * @ctxt:  the schema parser context
16608  * @type:  the complex type definition
16609  *
16610  * (3.4.6) Constraints on Complex Type Definition Schema Components
16611  *
16612  * Returns 0 if the constraints are satisfied, a positive
16613  * error code if not and -1 if an internal error occurred.
16614  */
16615 static int
xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,xmlSchemaTypePtr type)16616 xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,
16617 			  xmlSchemaTypePtr type)
16618 {
16619     int ret;
16620     /*
16621     * Complex Type Definition Properties Correct
16622     */
16623     ret = xmlSchemaCheckCTPropsCorrect(ctxt, type);
16624     if (ret != 0)
16625 	return (ret);
16626     if (WXS_IS_EXTENSION(type))
16627 	ret = xmlSchemaCheckCOSCTExtends(ctxt, type);
16628     else
16629 	ret = xmlSchemaCheckDerivationOKRestriction(ctxt, type);
16630     return (ret);
16631 }
16632 
16633 /**
16634  * xmlSchemaCheckSRCCT:
16635  * @ctxt:  the schema parser context
16636  * @type:  the complex type definition
16637  *
16638  * (3.4.3) Constraints on XML Representations of Complex Type Definitions:
16639  * Schema Representation Constraint:
16640  * Complex Type Definition Representation OK (src-ct)
16641  *
16642  * Returns 0 if the constraints are satisfied, a positive
16643  * error code if not and -1 if an internal error occurred.
16644  */
16645 static int
xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,xmlSchemaTypePtr type)16646 xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
16647 		    xmlSchemaTypePtr type)
16648 {
16649     xmlSchemaTypePtr base;
16650     int ret = 0;
16651 
16652     /*
16653     * TODO: Adjust the error codes here, as I used
16654     * XML_SCHEMAP_SRC_CT_1 only yet.
16655     */
16656     base = type->baseType;
16657     if (! WXS_HAS_SIMPLE_CONTENT(type)) {
16658 	/*
16659 	* 1 If the <complexContent> alternative is chosen, the type definition
16660 	* `resolved` to by the `actual value` of the base [attribute]
16661 	* must be a complex type definition;
16662 	*/
16663 	if (! WXS_IS_COMPLEX(base)) {
16664 	    xmlChar *str = NULL;
16665 	    xmlSchemaPCustomErr(ctxt,
16666 		XML_SCHEMAP_SRC_CT_1,
16667 		WXS_BASIC_CAST type, type->node,
16668 		"If using <complexContent>, the base type is expected to be "
16669 		"a complex type. The base type '%s' is a simple type",
16670 		xmlSchemaFormatQName(&str, base->targetNamespace,
16671 		base->name));
16672 	    FREE_AND_NULL(str)
16673 	    return (XML_SCHEMAP_SRC_CT_1);
16674 	}
16675     } else {
16676 	/*
16677 	* SPEC
16678 	* 2 If the <simpleContent> alternative is chosen, all of the
16679 	* following must be true:
16680 	* 2.1 The type definition `resolved` to by the `actual value` of the
16681 	* base [attribute] must be one of the following:
16682 	*/
16683 	if (WXS_IS_SIMPLE(base)) {
16684 	    if (WXS_IS_EXTENSION(type) == 0) {
16685 		xmlChar *str = NULL;
16686 		/*
16687 		* 2.1.3 only if the <extension> alternative is also
16688 		* chosen, a simple type definition.
16689 		*/
16690 		/* TODO: Change error code to ..._SRC_CT_2_1_3. */
16691 		xmlSchemaPCustomErr(ctxt,
16692 		    XML_SCHEMAP_SRC_CT_1,
16693 		    WXS_BASIC_CAST type, NULL,
16694 		    "If using <simpleContent> and <restriction>, the base "
16695 		    "type must be a complex type. The base type '%s' is "
16696 		    "a simple type",
16697 		    xmlSchemaFormatQName(&str, base->targetNamespace,
16698 			base->name));
16699 		FREE_AND_NULL(str)
16700 		return (XML_SCHEMAP_SRC_CT_1);
16701 	    }
16702 	} else {
16703 	    /* Base type is a complex type. */
16704 	    if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16705 		(base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16706 		/*
16707 		* 2.1.1 a complex type definition whose {content type} is a
16708 		* simple type definition;
16709 		* PASS
16710 		*/
16711 		if (base->contentTypeDef == NULL) {
16712 		    xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
16713 			WXS_BASIC_CAST type, NULL,
16714 			"Internal error: xmlSchemaCheckSRCCT, "
16715 			"'%s', base type has no content type",
16716 			type->name);
16717 		    return (-1);
16718 		}
16719 	    } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16720 		(WXS_IS_RESTRICTION(type))) {
16721 
16722 		/*
16723 		* 2.1.2 only if the <restriction> alternative is also
16724 		* chosen, a complex type definition whose {content type}
16725 		* is mixed and a particle emptiable.
16726 		*/
16727 		if (! xmlSchemaIsParticleEmptiable(
16728 		    (xmlSchemaParticlePtr) base->subtypes)) {
16729 		    ret = XML_SCHEMAP_SRC_CT_1;
16730 		} else
16731 		    /*
16732 		    * Attention: at this point the <simpleType> child is in
16733 		    * ->contentTypeDef (put there during parsing).
16734 		    */
16735 		    if (type->contentTypeDef == NULL) {
16736 		    xmlChar *str = NULL;
16737 		    /*
16738 		    * 2.2 If clause 2.1.2 above is satisfied, then there
16739 		    * must be a <simpleType> among the [children] of
16740 		    * <restriction>.
16741 		    */
16742 		    /* TODO: Change error code to ..._SRC_CT_2_2. */
16743 		    xmlSchemaPCustomErr(ctxt,
16744 			XML_SCHEMAP_SRC_CT_1,
16745 			WXS_BASIC_CAST type, NULL,
16746 			"A <simpleType> is expected among the children "
16747 			"of <restriction>, if <simpleContent> is used and "
16748 			"the base type '%s' is a complex type",
16749 			xmlSchemaFormatQName(&str, base->targetNamespace,
16750 			base->name));
16751 		    FREE_AND_NULL(str)
16752 		    return (XML_SCHEMAP_SRC_CT_1);
16753 		}
16754 	    } else {
16755 		ret = XML_SCHEMAP_SRC_CT_1;
16756 	    }
16757 	}
16758 	if (ret > 0) {
16759 	    xmlChar *str = NULL;
16760 	    if (WXS_IS_RESTRICTION(type)) {
16761 		xmlSchemaPCustomErr(ctxt,
16762 		    XML_SCHEMAP_SRC_CT_1,
16763 		    WXS_BASIC_CAST type, NULL,
16764 		    "If <simpleContent> and <restriction> is used, the "
16765 		    "base type must be a simple type or a complex type with "
16766 		    "mixed content and particle emptiable. The base type "
16767 		    "'%s' is none of those",
16768 		    xmlSchemaFormatQName(&str, base->targetNamespace,
16769 		    base->name));
16770 	    } else {
16771 		xmlSchemaPCustomErr(ctxt,
16772 		    XML_SCHEMAP_SRC_CT_1,
16773 		    WXS_BASIC_CAST type, NULL,
16774 		    "If <simpleContent> and <extension> is used, the "
16775 		    "base type must be a simple type. The base type '%s' "
16776 		    "is a complex type",
16777 		    xmlSchemaFormatQName(&str, base->targetNamespace,
16778 		    base->name));
16779 	    }
16780 	    FREE_AND_NULL(str)
16781 	}
16782     }
16783     /*
16784     * SPEC (3) "The corresponding complex type definition component must
16785     * satisfy the conditions set out in Constraints on Complex Type
16786     * Definition Schema Components ($3.4.6);"
16787     * NOTE (3) will be done in xmlSchemaTypeFixup().
16788     */
16789     /*
16790     * SPEC (4) If clause 2.2.1 or clause 2.2.2 in the correspondence specification
16791     * above for {attribute wildcard} is satisfied, the intensional
16792     * intersection must be expressible, as defined in Attribute Wildcard
16793     * Intersection ($3.10.6).
16794     * NOTE (4) is done in xmlSchemaFixupTypeAttributeUses().
16795     */
16796     return (ret);
16797 }
16798 
16799 #ifdef ENABLE_PARTICLE_RESTRICTION
16800 /**
16801  * xmlSchemaCheckParticleRangeOK:
16802  * @ctxt:  the schema parser context
16803  * @type:  the complex type definition
16804  *
16805  * (3.9.6) Constraints on Particle Schema Components
16806  * Schema Component Constraint:
16807  * Occurrence Range OK (range-ok)
16808  *
16809  * STATUS: complete
16810  *
16811  * Returns 0 if the constraints are satisfied, a positive
16812  * error code if not and -1 if an internal error occurred.
16813  */
16814 static int
xmlSchemaCheckParticleRangeOK(int rmin,int rmax,int bmin,int bmax)16815 xmlSchemaCheckParticleRangeOK(int rmin, int rmax,
16816 			      int bmin, int bmax)
16817 {
16818     if (rmin < bmin)
16819 	return (1);
16820     if ((bmax != UNBOUNDED) &&
16821 	(rmax > bmax))
16822 	return (1);
16823     return (0);
16824 }
16825 
16826 /**
16827  * xmlSchemaCheckRCaseNameAndTypeOK:
16828  * @ctxt:  the schema parser context
16829  * @r: the restricting element declaration particle
16830  * @b: the base element declaration particle
16831  *
16832  * (3.9.6) Constraints on Particle Schema Components
16833  * Schema Component Constraint:
16834  * Particle Restriction OK (Elt:Elt -- NameAndTypeOK)
16835  * (rcase-NameAndTypeOK)
16836  *
16837  * STATUS:
16838  *   MISSING (3.2.3)
16839  *   CLARIFY: (3.2.2)
16840  *
16841  * Returns 0 if the constraints are satisfied, a positive
16842  * error code if not and -1 if an internal error occurred.
16843  */
16844 static int
xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr r,xmlSchemaParticlePtr b)16845 xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,
16846 				 xmlSchemaParticlePtr r,
16847 				 xmlSchemaParticlePtr b)
16848 {
16849     xmlSchemaElementPtr elemR, elemB;
16850 
16851     /* TODO: Error codes (rcase-NameAndTypeOK). */
16852     elemR = (xmlSchemaElementPtr) r->children;
16853     elemB = (xmlSchemaElementPtr) b->children;
16854     /*
16855     * SPEC (1) "The declarations' {name}s and {target namespace}s are
16856     * the same."
16857     */
16858     if ((elemR != elemB) &&
16859 	((! xmlStrEqual(elemR->name, elemB->name)) ||
16860 	(! xmlStrEqual(elemR->targetNamespace, elemB->targetNamespace))))
16861 	return (1);
16862     /*
16863     * SPEC (2) "R's occurrence range is a valid restriction of B's
16864     * occurrence range as defined by Occurrence Range OK ($3.9.6)."
16865     */
16866     if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16867 	    b->minOccurs, b->maxOccurs) != 0)
16868 	return (1);
16869     /*
16870     * SPEC (3.1) "Both B's declaration's {scope} and R's declaration's
16871     * {scope} are global."
16872     */
16873     if (elemR == elemB)
16874 	return (0);
16875     /*
16876     * SPEC (3.2.1) "Either B's {nillable} is true or R's {nillable} is false."
16877     */
16878     if (((elemB->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) &&
16879 	(elemR->flags & XML_SCHEMAS_ELEM_NILLABLE))
16880 	 return (1);
16881     /*
16882     * SPEC (3.2.2) "either B's declaration's {value constraint} is absent,
16883     * or is not fixed, or R's declaration's {value constraint} is fixed
16884     * with the same value."
16885     */
16886     if ((elemB->value != NULL) && (elemB->flags & XML_SCHEMAS_ELEM_FIXED) &&
16887 	((elemR->value == NULL) ||
16888 	 ((elemR->flags & XML_SCHEMAS_ELEM_FIXED) == 0) ||
16889 	 /* TODO: Equality of the initial value or normalized or canonical? */
16890 	 (! xmlStrEqual(elemR->value, elemB->value))))
16891 	 return (1);
16892     /*
16893     * TODO: SPEC (3.2.3) "R's declaration's {identity-constraint
16894     * definitions} is a subset of B's declaration's {identity-constraint
16895     * definitions}, if any."
16896     */
16897     if (elemB->idcs != NULL) {
16898 	/* TODO */
16899     }
16900     /*
16901     * SPEC (3.2.4) "R's declaration's {disallowed substitutions} is a
16902     * superset of B's declaration's {disallowed substitutions}."
16903     */
16904     if (((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) &&
16905 	 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) == 0)) ||
16906 	((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) &&
16907 	 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) == 0)) ||
16908 	((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) &&
16909 	 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) == 0)))
16910 	 return (1);
16911     /*
16912     * SPEC (3.2.5) "R's {type definition} is validly derived given
16913     * {extension, list, union} from B's {type definition}"
16914     *
16915     * BADSPEC TODO: What's the point of adding "list" and "union" to the
16916     * set, if the corresponding constraints handle "restriction" and
16917     * "extension" only?
16918     *
16919     */
16920     {
16921 	int set = 0;
16922 
16923 	set |= SUBSET_EXTENSION;
16924 	set |= SUBSET_LIST;
16925 	set |= SUBSET_UNION;
16926 	if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST ctxt, elemR->subtypes,
16927 	    elemB->subtypes, set) != 0)
16928 	    return (1);
16929     }
16930     return (0);
16931 }
16932 
16933 /**
16934  * xmlSchemaCheckRCaseNSCompat:
16935  * @ctxt:  the schema parser context
16936  * @r: the restricting element declaration particle
16937  * @b: the base wildcard particle
16938  *
16939  * (3.9.6) Constraints on Particle Schema Components
16940  * Schema Component Constraint:
16941  * Particle Derivation OK (Elt:Any -- NSCompat)
16942  * (rcase-NSCompat)
16943  *
16944  * STATUS: complete
16945  *
16946  * Returns 0 if the constraints are satisfied, a positive
16947  * error code if not and -1 if an internal error occurred.
16948  */
16949 static int
xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr r,xmlSchemaParticlePtr b)16950 xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,
16951 			    xmlSchemaParticlePtr r,
16952 			    xmlSchemaParticlePtr b)
16953 {
16954     /* TODO:Error codes (rcase-NSCompat). */
16955     /*
16956     * SPEC "For an element declaration particle to be a `valid restriction`
16957     * of a wildcard particle all of the following must be true:"
16958     *
16959     * SPEC (1) "The element declaration's {target namespace} is `valid`
16960     * with respect to the wildcard's {namespace constraint} as defined by
16961     * Wildcard allows Namespace Name ($3.10.4)."
16962     */
16963     if (xmlSchemaCheckCVCWildcardNamespace((xmlSchemaWildcardPtr) b->children,
16964 	((xmlSchemaElementPtr) r->children)->targetNamespace) != 0)
16965 	return (1);
16966     /*
16967     * SPEC (2) "R's occurrence range is a valid restriction of B's
16968     * occurrence range as defined by Occurrence Range OK ($3.9.6)."
16969     */
16970     if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16971 	    b->minOccurs, b->maxOccurs) != 0)
16972 	return (1);
16973 
16974     return (0);
16975 }
16976 
16977 /**
16978  * xmlSchemaCheckRCaseRecurseAsIfGroup:
16979  * @ctxt:  the schema parser context
16980  * @r: the restricting element declaration particle
16981  * @b: the base model group particle
16982  *
16983  * (3.9.6) Constraints on Particle Schema Components
16984  * Schema Component Constraint:
16985  * Particle Derivation OK (Elt:All/Choice/Sequence -- RecurseAsIfGroup)
16986  * (rcase-RecurseAsIfGroup)
16987  *
16988  * STATUS: TODO
16989  *
16990  * Returns 0 if the constraints are satisfied, a positive
16991  * error code if not and -1 if an internal error occurred.
16992  */
16993 static int
xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr r,xmlSchemaParticlePtr b)16994 xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,
16995 				    xmlSchemaParticlePtr r,
16996 				    xmlSchemaParticlePtr b)
16997 {
16998     /* TODO: Error codes (rcase-RecurseAsIfGroup). */
16999     TODO
17000     return (0);
17001 }
17002 
17003 /**
17004  * xmlSchemaCheckRCaseNSSubset:
17005  * @ctxt:  the schema parser context
17006  * @r: the restricting wildcard particle
17007  * @b: the base wildcard particle
17008  *
17009  * (3.9.6) Constraints on Particle Schema Components
17010  * Schema Component Constraint:
17011  * Particle Derivation OK (Any:Any -- NSSubset)
17012  * (rcase-NSSubset)
17013  *
17014  * STATUS: complete
17015  *
17016  * Returns 0 if the constraints are satisfied, a positive
17017  * error code if not and -1 if an internal error occurred.
17018  */
17019 static int
xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr r,xmlSchemaParticlePtr b,int isAnyTypeBase)17020 xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,
17021 				    xmlSchemaParticlePtr r,
17022 				    xmlSchemaParticlePtr b,
17023 				    int isAnyTypeBase)
17024 {
17025     /* TODO: Error codes (rcase-NSSubset). */
17026     /*
17027     * SPEC (1) "R's occurrence range is a valid restriction of B's
17028     * occurrence range as defined by Occurrence Range OK ($3.9.6)."
17029     */
17030     if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
17031 	    b->minOccurs, b->maxOccurs))
17032 	return (1);
17033     /*
17034     * SPEC (2) "R's {namespace constraint} must be an intensional subset
17035     * of B's {namespace constraint} as defined by Wildcard Subset ($3.10.6)."
17036     */
17037     if (xmlSchemaCheckCOSNSSubset((xmlSchemaWildcardPtr) r->children,
17038 	(xmlSchemaWildcardPtr) b->children))
17039 	return (1);
17040     /*
17041     * SPEC (3) "Unless B is the content model wildcard of the `ur-type
17042     * definition`, R's {process contents} must be identical to or stronger
17043     * than B's {process contents}, where strict is stronger than lax is
17044     * stronger than skip."
17045     */
17046     if (! isAnyTypeBase) {
17047 	if ( ((xmlSchemaWildcardPtr) r->children)->processContents <
17048 	    ((xmlSchemaWildcardPtr) b->children)->processContents)
17049 	    return (1);
17050     }
17051 
17052     return (0);
17053 }
17054 
17055 /**
17056  * xmlSchemaCheckCOSParticleRestrict:
17057  * @ctxt:  the schema parser context
17058  * @type:  the complex type definition
17059  *
17060  * (3.9.6) Constraints on Particle Schema Components
17061  * Schema Component Constraint:
17062  * Particle Valid (Restriction) (cos-particle-restrict)
17063  *
17064  * STATUS: TODO
17065  *
17066  * Returns 0 if the constraints are satisfied, a positive
17067  * error code if not and -1 if an internal error occurred.
17068  */
17069 static int
xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr r,xmlSchemaParticlePtr b)17070 xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,
17071 				  xmlSchemaParticlePtr r,
17072 				  xmlSchemaParticlePtr b)
17073 {
17074     int ret = 0;
17075 
17076     /*part = WXS_TYPE_PARTICLE(type);
17077     basePart = WXS_TYPE_PARTICLE(base);
17078     */
17079 
17080     TODO
17081 
17082     /*
17083     * SPEC (1) "They are the same particle."
17084     */
17085     if (r == b)
17086 	return (0);
17087 
17088 
17089     return (0);
17090 }
17091 
17092 #if 0
17093 /**
17094  * xmlSchemaCheckRCaseNSRecurseCheckCardinality:
17095  * @ctxt:  the schema parser context
17096  * @r: the model group particle
17097  * @b: the base wildcard particle
17098  *
17099  * (3.9.6) Constraints on Particle Schema Components
17100  * Schema Component Constraint:
17101  * Particle Derivation OK (All/Choice/Sequence:Any --
17102  *                         NSRecurseCheckCardinality)
17103  * (rcase-NSRecurseCheckCardinality)
17104  *
17105  * STATUS: TODO: subst-groups
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
17111 xmlSchemaCheckRCaseNSRecurseCheckCardinality(xmlSchemaParserCtxtPtr ctxt,
17112 					     xmlSchemaParticlePtr r,
17113 					     xmlSchemaParticlePtr b)
17114 {
17115     xmlSchemaParticlePtr part;
17116     /* TODO: Error codes (rcase-NSRecurseCheckCardinality). */
17117     if ((r->children == NULL) || (r->children->children == NULL))
17118 	return (-1);
17119     /*
17120     * SPEC "For a group particle to be a `valid restriction` of a
17121     * wildcard particle..."
17122     *
17123     * SPEC (1) "Every member of the {particles} of the group is a `valid
17124     * restriction` of the wildcard as defined by
17125     * Particle Valid (Restriction) ($3.9.6)."
17126     */
17127     part = (xmlSchemaParticlePtr) r->children->children;
17128     do {
17129 	if (xmlSchemaCheckCOSParticleRestrict(ctxt, part, b))
17130 	    return (1);
17131 	part = (xmlSchemaParticlePtr) part->next;
17132     } while (part != NULL);
17133     /*
17134     * SPEC (2) "The effective total range of the group [...] is a
17135     * valid restriction of B's occurrence range as defined by
17136     * Occurrence Range OK ($3.9.6)."
17137     */
17138     if (xmlSchemaCheckParticleRangeOK(
17139 	    xmlSchemaGetParticleTotalRangeMin(r),
17140 	    xmlSchemaGetParticleTotalRangeMax(r),
17141 	    b->minOccurs, b->maxOccurs) != 0)
17142 	return (1);
17143     return (0);
17144 }
17145 #endif
17146 
17147 /**
17148  * xmlSchemaCheckRCaseRecurse:
17149  * @ctxt:  the schema parser context
17150  * @r: the <all> or <sequence> model group particle
17151  * @b: the base <all> or <sequence> model group particle
17152  *
17153  * (3.9.6) Constraints on Particle Schema Components
17154  * Schema Component Constraint:
17155  * Particle Derivation OK (All:All,Sequence:Sequence --
17156                            Recurse)
17157  * (rcase-Recurse)
17158  *
17159  * STATUS:  ?
17160  * TODO: subst-groups
17161  *
17162  * Returns 0 if the constraints are satisfied, a positive
17163  * error code if not and -1 if an internal error occurred.
17164  */
17165 static int
xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr r,xmlSchemaParticlePtr b)17166 xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,
17167 			   xmlSchemaParticlePtr r,
17168 			   xmlSchemaParticlePtr b)
17169 {
17170     /* xmlSchemaParticlePtr part; */
17171     /* TODO: Error codes (rcase-Recurse). */
17172     if ((r->children == NULL) || (b->children == NULL) ||
17173 	(r->children->type != b->children->type))
17174 	return (-1);
17175     /*
17176     * SPEC "For an all or sequence group particle to be a `valid
17177     * restriction` of another group particle with the same {compositor}..."
17178     *
17179     * SPEC (1) "R's occurrence range is a valid restriction of B's
17180     * occurrence range as defined by Occurrence Range OK ($3.9.6)."
17181     */
17182     if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
17183 	    b->minOccurs, b->maxOccurs))
17184 	return (1);
17185 
17186 
17187     return (0);
17188 }
17189 
17190 #endif
17191 
17192 #define FACET_RESTR_MUTUAL_ERR(fac1, fac2) \
17193     xmlSchemaPCustomErrExt(pctxt,      \
17194 	XML_SCHEMAP_INVALID_FACET_VALUE, \
17195 	WXS_BASIC_CAST fac1, fac1->node, \
17196 	"It is an error for both '%s' and '%s' to be specified on the "\
17197 	"same type definition", \
17198 	BAD_CAST xmlSchemaFacetTypeToString(fac1->type), \
17199 	BAD_CAST xmlSchemaFacetTypeToString(fac2->type), NULL);
17200 
17201 #define FACET_RESTR_ERR(fac1, msg) \
17202     xmlSchemaPCustomErr(pctxt,      \
17203 	XML_SCHEMAP_INVALID_FACET_VALUE, \
17204 	WXS_BASIC_CAST fac1, fac1->node, \
17205 	msg, NULL);
17206 
17207 #define FACET_RESTR_FIXED_ERR(fac) \
17208     xmlSchemaPCustomErr(pctxt, \
17209 	XML_SCHEMAP_INVALID_FACET_VALUE, \
17210 	WXS_BASIC_CAST fac, fac->node, \
17211 	"The base type's facet is 'fixed', thus the value must not " \
17212 	"differ", NULL);
17213 
17214 static void
xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,xmlSchemaFacetPtr facet1,xmlSchemaFacetPtr facet2,int lessGreater,int orEqual,int ofBase)17215 xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,
17216 			xmlSchemaFacetPtr facet1,
17217 			xmlSchemaFacetPtr facet2,
17218 			int lessGreater,
17219 			int orEqual,
17220 			int ofBase)
17221 {
17222     xmlChar *msg = NULL;
17223 
17224     msg = xmlStrdup(BAD_CAST "'");
17225     msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet1->type));
17226     msg = xmlStrcat(msg, BAD_CAST "' has to be");
17227     if (lessGreater == 0)
17228 	msg = xmlStrcat(msg, BAD_CAST " equal to");
17229     if (lessGreater == 1)
17230 	msg = xmlStrcat(msg, BAD_CAST " greater than");
17231     else
17232 	msg = xmlStrcat(msg, BAD_CAST " less than");
17233 
17234     if (orEqual)
17235 	msg = xmlStrcat(msg, BAD_CAST " or equal to");
17236     msg = xmlStrcat(msg, BAD_CAST " '");
17237     msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet2->type));
17238     if (ofBase)
17239 	msg = xmlStrcat(msg, BAD_CAST "' of the base type");
17240     else
17241 	msg = xmlStrcat(msg, BAD_CAST "'");
17242 
17243     xmlSchemaPCustomErr(pctxt,
17244 	XML_SCHEMAP_INVALID_FACET_VALUE,
17245 	WXS_BASIC_CAST facet1, NULL,
17246 	(const char *) msg, NULL);
17247 
17248     if (msg != NULL)
17249 	xmlFree(msg);
17250 }
17251 
17252 /*
17253 * xmlSchemaDeriveAndValidateFacets:
17254 *
17255 * Schema Component Constraint: Simple Type Restriction (Facets)
17256 * (st-restrict-facets)
17257 */
17258 static int
xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)17259 xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,
17260 				 xmlSchemaTypePtr type)
17261 {
17262     xmlSchemaTypePtr base = type->baseType;
17263     xmlSchemaFacetLinkPtr link, cur, last = NULL;
17264     xmlSchemaFacetPtr facet, bfacet,
17265 	flength = NULL, ftotdig = NULL, ffracdig = NULL,
17266 	fmaxlen = NULL, fminlen = NULL, /* facets of the current type */
17267 	fmininc = NULL, fmaxinc = NULL,
17268 	fminexc = NULL, fmaxexc = NULL,
17269 	bflength = NULL, bftotdig = NULL, bffracdig = NULL,
17270 	bfmaxlen = NULL, bfminlen = NULL, /* facets of the base type */
17271 	bfmininc = NULL, bfmaxinc = NULL,
17272 	bfminexc = NULL, bfmaxexc = NULL;
17273     int res; /* err = 0, fixedErr; */
17274 
17275     /*
17276     * SPEC st-restrict-facets 1:
17277     * "The {variety} of R is the same as that of B."
17278     */
17279     /*
17280     * SPEC st-restrict-facets 2:
17281     * "If {variety} is atomic, the {primitive type definition}
17282     * of R is the same as that of B."
17283     *
17284     * NOTE: we leave 1 & 2 out for now, since this will be
17285     * satisfied by the derivation process.
17286     * CONSTRUCTION TODO: Maybe needed if using a construction API.
17287     */
17288     /*
17289     * SPEC st-restrict-facets 3:
17290     * "The {facets} of R are the union of S and the {facets}
17291     * of B, eliminating duplicates. To eliminate duplicates,
17292     * when a facet of the same kind occurs in both S and the
17293     * {facets} of B, the one in the {facets} of B is not
17294     * included, with the exception of enumeration and pattern
17295     * facets, for which multiple occurrences with distinct values
17296     * are allowed."
17297     */
17298 
17299     if ((type->facetSet == NULL) && (base->facetSet == NULL))
17300 	return (0);
17301 
17302     last = type->facetSet;
17303     if (last != NULL)
17304 	while (last->next != NULL)
17305 	    last = last->next;
17306 
17307     for (cur = type->facetSet; cur != NULL; cur = cur->next) {
17308 	facet = cur->facet;
17309 	switch (facet->type) {
17310 	    case XML_SCHEMA_FACET_LENGTH:
17311 		flength = facet; break;
17312 	    case XML_SCHEMA_FACET_MINLENGTH:
17313 		fminlen = facet; break;
17314 	    case XML_SCHEMA_FACET_MININCLUSIVE:
17315 		fmininc = facet; break;
17316 	    case XML_SCHEMA_FACET_MINEXCLUSIVE:
17317 		fminexc = facet; break;
17318 	    case XML_SCHEMA_FACET_MAXLENGTH:
17319 		fmaxlen = facet; break;
17320 	    case XML_SCHEMA_FACET_MAXINCLUSIVE:
17321 		fmaxinc = facet; break;
17322 	    case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17323 		fmaxexc = facet; break;
17324 	    case XML_SCHEMA_FACET_TOTALDIGITS:
17325 		ftotdig = facet; break;
17326 	    case XML_SCHEMA_FACET_FRACTIONDIGITS:
17327 		ffracdig = facet; break;
17328 	    default:
17329 		break;
17330 	}
17331     }
17332     for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17333 	facet = cur->facet;
17334 	switch (facet->type) {
17335 	    case XML_SCHEMA_FACET_LENGTH:
17336 		bflength = facet; break;
17337 	    case XML_SCHEMA_FACET_MINLENGTH:
17338 		bfminlen = facet; break;
17339 	    case XML_SCHEMA_FACET_MININCLUSIVE:
17340 		bfmininc = facet; break;
17341 	    case XML_SCHEMA_FACET_MINEXCLUSIVE:
17342 		bfminexc = facet; break;
17343 	    case XML_SCHEMA_FACET_MAXLENGTH:
17344 		bfmaxlen = facet; break;
17345 	    case XML_SCHEMA_FACET_MAXINCLUSIVE:
17346 		bfmaxinc = facet; break;
17347 	    case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17348 		bfmaxexc = facet; break;
17349 	    case XML_SCHEMA_FACET_TOTALDIGITS:
17350 		bftotdig = facet; break;
17351 	    case XML_SCHEMA_FACET_FRACTIONDIGITS:
17352 		bffracdig = facet; break;
17353 	    default:
17354 		break;
17355 	}
17356     }
17357     /*
17358     * length and minLength or maxLength (2.2) + (3.2)
17359     */
17360     if (flength && (fminlen || fmaxlen)) {
17361 	FACET_RESTR_ERR(flength, "It is an error for both 'length' and "
17362 	    "either of 'minLength' or 'maxLength' to be specified on "
17363 	    "the same type definition")
17364     }
17365     /*
17366     * Mutual exclusions in the same derivation step.
17367     */
17368     if ((fmaxinc) && (fmaxexc)) {
17369 	/*
17370 	* SCC "maxInclusive and maxExclusive"
17371 	*/
17372 	FACET_RESTR_MUTUAL_ERR(fmaxinc, fmaxexc)
17373     }
17374     if ((fmininc) && (fminexc)) {
17375 	/*
17376 	* SCC "minInclusive and minExclusive"
17377 	*/
17378 	FACET_RESTR_MUTUAL_ERR(fmininc, fminexc)
17379     }
17380 
17381     if (flength && bflength) {
17382 	/*
17383 	* SCC "length valid restriction"
17384 	* The values have to be equal.
17385 	*/
17386 	res = xmlSchemaCompareValues(flength->val, bflength->val);
17387 	if (res == -2)
17388 	    goto internal_error;
17389 	if (res != 0)
17390 	    xmlSchemaDeriveFacetErr(pctxt, flength, bflength, 0, 0, 1);
17391 	if ((res != 0) && (bflength->fixed)) {
17392 	    FACET_RESTR_FIXED_ERR(flength)
17393 	}
17394 
17395     }
17396     if (fminlen && bfminlen) {
17397 	/*
17398 	* SCC "minLength valid restriction"
17399 	* minLength >= BASE minLength
17400 	*/
17401 	res = xmlSchemaCompareValues(fminlen->val, bfminlen->val);
17402 	if (res == -2)
17403 	    goto internal_error;
17404 	if (res == -1)
17405 	    xmlSchemaDeriveFacetErr(pctxt, fminlen, bfminlen, 1, 1, 1);
17406 	if ((res != 0) && (bfminlen->fixed)) {
17407 	    FACET_RESTR_FIXED_ERR(fminlen)
17408 	}
17409     }
17410     if (fmaxlen && bfmaxlen) {
17411 	/*
17412 	* SCC "maxLength valid restriction"
17413 	* maxLength <= BASE minLength
17414 	*/
17415 	res = xmlSchemaCompareValues(fmaxlen->val, bfmaxlen->val);
17416 	if (res == -2)
17417 	    goto internal_error;
17418 	if (res == 1)
17419 	    xmlSchemaDeriveFacetErr(pctxt, fmaxlen, bfmaxlen, -1, 1, 1);
17420 	if ((res != 0) && (bfmaxlen->fixed)) {
17421 	    FACET_RESTR_FIXED_ERR(fmaxlen)
17422 	}
17423     }
17424     /*
17425     * SCC "length and minLength or maxLength"
17426     */
17427     if (! flength)
17428 	flength = bflength;
17429     if (flength) {
17430 	if (! fminlen)
17431 	    fminlen = bfminlen;
17432 	if (fminlen) {
17433 	    /* (1.1) length >= minLength */
17434 	    res = xmlSchemaCompareValues(flength->val, fminlen->val);
17435 	    if (res == -2)
17436 		goto internal_error;
17437 	    if (res == -1)
17438 		xmlSchemaDeriveFacetErr(pctxt, flength, fminlen, 1, 1, 0);
17439 	}
17440 	if (! fmaxlen)
17441 	    fmaxlen = bfmaxlen;
17442 	if (fmaxlen) {
17443 	    /* (2.1) length <= maxLength */
17444 	    res = xmlSchemaCompareValues(flength->val, fmaxlen->val);
17445 	    if (res == -2)
17446 		goto internal_error;
17447 	    if (res == 1)
17448 		xmlSchemaDeriveFacetErr(pctxt, flength, fmaxlen, -1, 1, 0);
17449 	}
17450     }
17451     if (fmaxinc) {
17452 	/*
17453 	* "maxInclusive"
17454 	*/
17455 	if (fmininc) {
17456 	    /* SCC "maxInclusive >= minInclusive" */
17457 	    res = xmlSchemaCompareValues(fmaxinc->val, fmininc->val);
17458 	    if (res == -2)
17459 		goto internal_error;
17460 	    if (res == -1) {
17461 		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, fmininc, 1, 1, 0);
17462 	    }
17463 	}
17464 	/*
17465 	* SCC "maxInclusive valid restriction"
17466 	*/
17467 	if (bfmaxinc) {
17468 	    /* maxInclusive <= BASE maxInclusive */
17469 	    res = xmlSchemaCompareValues(fmaxinc->val, bfmaxinc->val);
17470 	    if (res == -2)
17471 		goto internal_error;
17472 	    if (res == 1)
17473 		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxinc, -1, 1, 1);
17474 	    if ((res != 0) && (bfmaxinc->fixed)) {
17475 		FACET_RESTR_FIXED_ERR(fmaxinc)
17476 	    }
17477 	}
17478 	if (bfmaxexc) {
17479 	    /* maxInclusive < BASE maxExclusive */
17480 	    res = xmlSchemaCompareValues(fmaxinc->val, bfmaxexc->val);
17481 	    if (res == -2)
17482 		goto internal_error;
17483 	    if (res != -1) {
17484 		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxexc, -1, 0, 1);
17485 	    }
17486 	}
17487 	if (bfmininc) {
17488 	    /* maxInclusive >= BASE minInclusive */
17489 	    res = xmlSchemaCompareValues(fmaxinc->val, bfmininc->val);
17490 	    if (res == -2)
17491 		goto internal_error;
17492 	    if (res == -1) {
17493 		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmininc, 1, 1, 1);
17494 	    }
17495 	}
17496 	if (bfminexc) {
17497 	    /* maxInclusive > BASE minExclusive */
17498 	    res = xmlSchemaCompareValues(fmaxinc->val, bfminexc->val);
17499 	    if (res == -2)
17500 		goto internal_error;
17501 	    if (res != 1) {
17502 		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfminexc, 1, 0, 1);
17503 	    }
17504 	}
17505     }
17506     if (fmaxexc) {
17507 	/*
17508 	* "maxExclusive >= minExclusive"
17509 	*/
17510 	if (fminexc) {
17511 	    res = xmlSchemaCompareValues(fmaxexc->val, fminexc->val);
17512 	    if (res == -2)
17513 		goto internal_error;
17514 	    if (res == -1) {
17515 		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, fminexc, 1, 1, 0);
17516 	    }
17517 	}
17518 	/*
17519 	* "maxExclusive valid restriction"
17520 	*/
17521 	if (bfmaxexc) {
17522 	    /* maxExclusive <= BASE maxExclusive */
17523 	    res = xmlSchemaCompareValues(fmaxexc->val, bfmaxexc->val);
17524 	    if (res == -2)
17525 		goto internal_error;
17526 	    if (res == 1) {
17527 		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxexc, -1, 1, 1);
17528 	    }
17529 	    if ((res != 0) && (bfmaxexc->fixed)) {
17530 		FACET_RESTR_FIXED_ERR(fmaxexc)
17531 	    }
17532 	}
17533 	if (bfmaxinc) {
17534 	    /* maxExclusive <= BASE maxInclusive */
17535 	    res = xmlSchemaCompareValues(fmaxexc->val, bfmaxinc->val);
17536 	    if (res == -2)
17537 		goto internal_error;
17538 	    if (res == 1) {
17539 		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxinc, -1, 1, 1);
17540 	    }
17541 	}
17542 	if (bfmininc) {
17543 	    /* maxExclusive > BASE minInclusive */
17544 	    res = xmlSchemaCompareValues(fmaxexc->val, bfmininc->val);
17545 	    if (res == -2)
17546 		goto internal_error;
17547 	    if (res != 1) {
17548 		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmininc, 1, 0, 1);
17549 	    }
17550 	}
17551 	if (bfminexc) {
17552 	    /* maxExclusive > BASE minExclusive */
17553 	    res = xmlSchemaCompareValues(fmaxexc->val, bfminexc->val);
17554 	    if (res == -2)
17555 		goto internal_error;
17556 	    if (res != 1) {
17557 		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfminexc, 1, 0, 1);
17558 	    }
17559 	}
17560     }
17561     if (fminexc) {
17562 	/*
17563 	* "minExclusive < maxInclusive"
17564 	*/
17565 	if (fmaxinc) {
17566 	    res = xmlSchemaCompareValues(fminexc->val, fmaxinc->val);
17567 	    if (res == -2)
17568 		goto internal_error;
17569 	    if (res != -1) {
17570 		xmlSchemaDeriveFacetErr(pctxt, fminexc, fmaxinc, -1, 0, 0);
17571 	    }
17572 	}
17573 	/*
17574 	* "minExclusive valid restriction"
17575 	*/
17576 	if (bfminexc) {
17577 	    /* minExclusive >= BASE minExclusive */
17578 	    res = xmlSchemaCompareValues(fminexc->val, bfminexc->val);
17579 	    if (res == -2)
17580 		goto internal_error;
17581 	    if (res == -1) {
17582 		xmlSchemaDeriveFacetErr(pctxt, fminexc, bfminexc, 1, 1, 1);
17583 	    }
17584 	    if ((res != 0) && (bfminexc->fixed)) {
17585 		FACET_RESTR_FIXED_ERR(fminexc)
17586 	    }
17587 	}
17588 	if (bfmaxinc) {
17589 	    /* minExclusive <= BASE maxInclusive */
17590 	    res = xmlSchemaCompareValues(fminexc->val, bfmaxinc->val);
17591 	    if (res == -2)
17592 		goto internal_error;
17593 	    if (res == 1) {
17594 		xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxinc, -1, 1, 1);
17595 	    }
17596 	}
17597 	if (bfmininc) {
17598 	    /* minExclusive >= BASE minInclusive */
17599 	    res = xmlSchemaCompareValues(fminexc->val, bfmininc->val);
17600 	    if (res == -2)
17601 		goto internal_error;
17602 	    if (res == -1) {
17603 		xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmininc, 1, 1, 1);
17604 	    }
17605 	}
17606 	if (bfmaxexc) {
17607 	    /* minExclusive < BASE maxExclusive */
17608 	    res = xmlSchemaCompareValues(fminexc->val, bfmaxexc->val);
17609 	    if (res == -2)
17610 		goto internal_error;
17611 	    if (res != -1) {
17612 		xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxexc, -1, 0, 1);
17613 	    }
17614 	}
17615     }
17616     if (fmininc) {
17617 	/*
17618 	* "minInclusive < maxExclusive"
17619 	*/
17620 	if (fmaxexc) {
17621 	    res = xmlSchemaCompareValues(fmininc->val, fmaxexc->val);
17622 	    if (res == -2)
17623 		goto internal_error;
17624 	    if (res != -1) {
17625 		xmlSchemaDeriveFacetErr(pctxt, fmininc, fmaxexc, -1, 0, 0);
17626 	    }
17627 	}
17628 	/*
17629 	* "minExclusive valid restriction"
17630 	*/
17631 	if (bfmininc) {
17632 	    /* minInclusive >= BASE minInclusive */
17633 	    res = xmlSchemaCompareValues(fmininc->val, bfmininc->val);
17634 	    if (res == -2)
17635 		goto internal_error;
17636 	    if (res == -1) {
17637 		xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmininc, 1, 1, 1);
17638 	    }
17639 	    if ((res != 0) && (bfmininc->fixed)) {
17640 		FACET_RESTR_FIXED_ERR(fmininc)
17641 	    }
17642 	}
17643 	if (bfmaxinc) {
17644 	    /* minInclusive <= BASE maxInclusive */
17645 	    res = xmlSchemaCompareValues(fmininc->val, bfmaxinc->val);
17646 	    if (res == -2)
17647 		goto internal_error;
17648 	    if (res == 1) {
17649 		xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxinc, -1, 1, 1);
17650 	    }
17651 	}
17652 	if (bfminexc) {
17653 	    /* minInclusive > BASE minExclusive */
17654 	    res = xmlSchemaCompareValues(fmininc->val, bfminexc->val);
17655 	    if (res == -2)
17656 		goto internal_error;
17657 	    if (res != 1)
17658 		xmlSchemaDeriveFacetErr(pctxt, fmininc, bfminexc, 1, 0, 1);
17659 	}
17660 	if (bfmaxexc) {
17661 	    /* minInclusive < BASE maxExclusive */
17662 	    res = xmlSchemaCompareValues(fmininc->val, bfmaxexc->val);
17663 	    if (res == -2)
17664 		goto internal_error;
17665 	    if (res != -1)
17666 		xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxexc, -1, 0, 1);
17667 	}
17668     }
17669     if (ftotdig && bftotdig) {
17670 	/*
17671 	* SCC " totalDigits valid restriction"
17672 	* totalDigits <= BASE totalDigits
17673 	*/
17674 	res = xmlSchemaCompareValues(ftotdig->val, bftotdig->val);
17675 	if (res == -2)
17676 	    goto internal_error;
17677 	if (res == 1)
17678 	    xmlSchemaDeriveFacetErr(pctxt, ftotdig, bftotdig,
17679 	    -1, 1, 1);
17680 	if ((res != 0) && (bftotdig->fixed)) {
17681 	    FACET_RESTR_FIXED_ERR(ftotdig)
17682 	}
17683     }
17684     if (ffracdig && bffracdig) {
17685 	/*
17686 	* SCC  "fractionDigits valid restriction"
17687 	* fractionDigits <= BASE fractionDigits
17688 	*/
17689 	res = xmlSchemaCompareValues(ffracdig->val, bffracdig->val);
17690 	if (res == -2)
17691 	    goto internal_error;
17692 	if (res == 1)
17693 	    xmlSchemaDeriveFacetErr(pctxt, ffracdig, bffracdig,
17694 	    -1, 1, 1);
17695 	if ((res != 0) && (bffracdig->fixed)) {
17696 	    FACET_RESTR_FIXED_ERR(ffracdig)
17697 	}
17698     }
17699     /*
17700     * SCC "fractionDigits less than or equal to totalDigits"
17701     */
17702     if (! ftotdig)
17703 	ftotdig = bftotdig;
17704     if (! ffracdig)
17705 	ffracdig = bffracdig;
17706     if (ftotdig && ffracdig) {
17707 	res = xmlSchemaCompareValues(ffracdig->val, ftotdig->val);
17708 	if (res == -2)
17709 	    goto internal_error;
17710 	if (res == 1)
17711 	    xmlSchemaDeriveFacetErr(pctxt, ffracdig, ftotdig,
17712 		-1, 1, 0);
17713     }
17714     /*
17715     * *Enumerations* won' be added here, since only the first set
17716     * of enumerations in the ancestor-or-self axis is used
17717     * for validation, plus we need to use the base type of those
17718     * enumerations for whitespace.
17719     *
17720     * *Patterns*: won't be add here, since they are ORed at
17721     * type level and ANDed at ancestor level. This will
17722     * happed during validation by walking the base axis
17723     * of the type.
17724     */
17725     for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17726 	bfacet = cur->facet;
17727 	/*
17728 	* Special handling of enumerations and patterns.
17729 	* TODO: hmm, they should not appear in the set, so remove this.
17730 	*/
17731 	if ((bfacet->type == XML_SCHEMA_FACET_PATTERN) ||
17732 	    (bfacet->type == XML_SCHEMA_FACET_ENUMERATION))
17733 	    continue;
17734 	/*
17735 	* Search for a duplicate facet in the current type.
17736 	*/
17737 	link = type->facetSet;
17738 	/* err = 0; */
17739 	/* fixedErr = 0; */
17740 	while (link != NULL) {
17741 	    facet = link->facet;
17742 	    if (facet->type == bfacet->type) {
17743 		switch (facet->type) {
17744 		    case XML_SCHEMA_FACET_WHITESPACE:
17745 			/*
17746 			* The whitespace must be stronger.
17747 			*/
17748 			if (facet->whitespace < bfacet->whitespace) {
17749 			    FACET_RESTR_ERR(facet,
17750 				"The 'whitespace' value has to be equal to "
17751 				"or stronger than the 'whitespace' value of "
17752 				"the base type")
17753 			}
17754 			if ((bfacet->fixed) &&
17755 			    (facet->whitespace != bfacet->whitespace)) {
17756 			    FACET_RESTR_FIXED_ERR(facet)
17757 			}
17758 			break;
17759 		    default:
17760 			break;
17761 		}
17762 		/* Duplicate found. */
17763 		break;
17764 	    }
17765 	    link = link->next;
17766 	}
17767 	/*
17768 	* If no duplicate was found: add the base types's facet
17769 	* to the set.
17770 	*/
17771 	if (link == NULL) {
17772 	    link = (xmlSchemaFacetLinkPtr)
17773 		xmlMalloc(sizeof(xmlSchemaFacetLink));
17774 	    if (link == NULL) {
17775 		xmlSchemaPErrMemory(pctxt,
17776 		    "deriving facets, creating a facet link", NULL);
17777 		return (-1);
17778 	    }
17779 	    link->facet = cur->facet;
17780 	    link->next = NULL;
17781 	    if (last == NULL)
17782 		type->facetSet = link;
17783 	    else
17784 		last->next = link;
17785 	    last = link;
17786 	}
17787 
17788     }
17789 
17790     return (0);
17791 internal_error:
17792     PERROR_INT("xmlSchemaDeriveAndValidateFacets",
17793 	"an error occurred");
17794     return (-1);
17795 }
17796 
17797 static int
xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)17798 xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,
17799 					     xmlSchemaTypePtr type)
17800 {
17801     xmlSchemaTypeLinkPtr link, lastLink, prevLink, subLink, newLink;
17802     /*
17803     * The actual value is then formed by replacing any union type
17804     * definition in the `explicit members` with the members of their
17805     * {member type definitions}, in order.
17806     *
17807     * TODO: There's a bug entry at
17808     * "http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0287.html"
17809     * which indicates that we'll keep the union types the future.
17810     */
17811     link = type->memberTypes;
17812     while (link != NULL) {
17813 
17814 	if (WXS_IS_TYPE_NOT_FIXED(link->type))
17815 	    xmlSchemaTypeFixup(link->type, ACTXT_CAST pctxt);
17816 
17817 	if (WXS_IS_UNION(link->type)) {
17818 	    subLink = xmlSchemaGetUnionSimpleTypeMemberTypes(link->type);
17819 	    if (subLink != NULL) {
17820 		link->type = subLink->type;
17821 		if (subLink->next != NULL) {
17822 		    lastLink = link->next;
17823 		    subLink = subLink->next;
17824 		    prevLink = link;
17825 		    while (subLink != NULL) {
17826 			newLink = (xmlSchemaTypeLinkPtr)
17827 			    xmlMalloc(sizeof(xmlSchemaTypeLink));
17828 			if (newLink == NULL) {
17829 			    xmlSchemaPErrMemory(pctxt, "allocating a type link",
17830 				NULL);
17831 			    return (-1);
17832 			}
17833 			newLink->type = subLink->type;
17834 			prevLink->next = newLink;
17835 			prevLink = newLink;
17836 			newLink->next = lastLink;
17837 
17838 			subLink = subLink->next;
17839 		    }
17840 		}
17841 	    }
17842 	}
17843 	link = link->next;
17844     }
17845     return (0);
17846 }
17847 
17848 static void
xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type)17849 xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type)
17850 {
17851     int has = 0, needVal = 0, normVal = 0;
17852 
17853     has	= (type->baseType->flags & XML_SCHEMAS_TYPE_HAS_FACETS) ? 1 : 0;
17854     if (has) {
17855 	needVal = (type->baseType->flags &
17856 	    XML_SCHEMAS_TYPE_FACETSNEEDVALUE) ? 1 : 0;
17857 	normVal = (type->baseType->flags &
17858 	    XML_SCHEMAS_TYPE_NORMVALUENEEDED) ? 1 : 0;
17859     }
17860     if (type->facets != NULL) {
17861 	xmlSchemaFacetPtr fac;
17862 
17863 	for (fac = type->facets; fac != NULL; fac = fac->next) {
17864 	    switch (fac->type) {
17865 		case XML_SCHEMA_FACET_WHITESPACE:
17866 		    break;
17867 		case XML_SCHEMA_FACET_PATTERN:
17868 		    normVal = 1;
17869 		    has = 1;
17870 		    break;
17871 		case XML_SCHEMA_FACET_ENUMERATION:
17872 		    needVal = 1;
17873 		    normVal = 1;
17874 		    has = 1;
17875 		    break;
17876 		default:
17877 		    has = 1;
17878 		    break;
17879 	    }
17880 	}
17881     }
17882     if (normVal)
17883 	type->flags |= XML_SCHEMAS_TYPE_NORMVALUENEEDED;
17884     if (needVal)
17885 	type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17886     if (has)
17887 	type->flags |= XML_SCHEMAS_TYPE_HAS_FACETS;
17888 
17889     if (has && (! needVal) && WXS_IS_ATOMIC(type)) {
17890 	xmlSchemaTypePtr prim = xmlSchemaGetPrimitiveType(type);
17891 	/*
17892 	* OPTIMIZE VAL TODO: Some facets need a computed value.
17893 	*/
17894 	if ((prim->builtInType != XML_SCHEMAS_ANYSIMPLETYPE) &&
17895 	    (prim->builtInType != XML_SCHEMAS_STRING)) {
17896 	    type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17897 	}
17898     }
17899 }
17900 
17901 static int
xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type)17902 xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type)
17903 {
17904 
17905 
17906     /*
17907     * Evaluate the whitespace-facet value.
17908     */
17909     if (WXS_IS_LIST(type)) {
17910 	type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17911 	return (0);
17912     } else if (WXS_IS_UNION(type))
17913 	return (0);
17914 
17915     if (type->facetSet != NULL) {
17916 	xmlSchemaFacetLinkPtr lin;
17917 
17918 	for (lin = type->facetSet; lin != NULL; lin = lin->next) {
17919 	    if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
17920 		switch (lin->facet->whitespace) {
17921 		case XML_SCHEMAS_FACET_PRESERVE:
17922 		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
17923 		    break;
17924 		case XML_SCHEMAS_FACET_REPLACE:
17925 		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
17926 		    break;
17927 		case XML_SCHEMAS_FACET_COLLAPSE:
17928 		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17929 		    break;
17930 		default:
17931 		    return (-1);
17932 		}
17933 		return (0);
17934 	    }
17935 	}
17936     }
17937     /*
17938     * For all `atomic` datatypes other than string (and types `derived`
17939     * by `restriction` from it) the value of whiteSpace is fixed to
17940     * collapse
17941     */
17942     {
17943 	xmlSchemaTypePtr anc;
17944 
17945 	for (anc = type->baseType; anc != NULL &&
17946 		anc->builtInType != XML_SCHEMAS_ANYTYPE;
17947 		anc = anc->baseType) {
17948 
17949 	    if (anc->type == XML_SCHEMA_TYPE_BASIC) {
17950 		if (anc->builtInType == XML_SCHEMAS_NORMSTRING) {
17951 		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
17952 
17953 		} else if ((anc->builtInType == XML_SCHEMAS_STRING) ||
17954 		    (anc->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)) {
17955 		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
17956 
17957 		} else
17958 		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17959 		break;
17960 	    }
17961 	}
17962     }
17963     return (0);
17964 }
17965 
17966 static int
xmlSchemaFixupSimpleTypeStageOne(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)17967 xmlSchemaFixupSimpleTypeStageOne(xmlSchemaParserCtxtPtr pctxt,
17968 			  xmlSchemaTypePtr type)
17969 {
17970     if (type->type != XML_SCHEMA_TYPE_SIMPLE)
17971 	return(0);
17972     if (! WXS_IS_TYPE_NOT_FIXED_1(type))
17973 	return(0);
17974     type->flags |= XML_SCHEMAS_TYPE_FIXUP_1;
17975 
17976     if (WXS_IS_LIST(type)) {
17977 	/*
17978 	* Corresponds to <simpleType><list>...
17979 	*/
17980 	if (type->subtypes == NULL) {
17981 	    /*
17982 	    * This one is really needed, so get out.
17983 	    */
17984 	    PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17985 		"list type has no item-type assigned");
17986 	    return(-1);
17987 	}
17988     } else if (WXS_IS_UNION(type)) {
17989 	/*
17990 	* Corresponds to <simpleType><union>...
17991 	*/
17992 	if (type->memberTypes == NULL) {
17993 	    /*
17994 	    * This one is really needed, so get out.
17995 	    */
17996 	    PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17997 		"union type has no member-types assigned");
17998 	    return(-1);
17999 	}
18000     } else {
18001 	/*
18002 	* Corresponds to <simpleType><restriction>...
18003 	*/
18004 	if (type->baseType == NULL) {
18005 	    PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
18006 		"type has no base-type assigned");
18007 	    return(-1);
18008 	}
18009 	if (WXS_IS_TYPE_NOT_FIXED_1(type->baseType))
18010 	    if (xmlSchemaFixupSimpleTypeStageOne(pctxt, type->baseType) == -1)
18011 		return(-1);
18012 	/*
18013 	* Variety
18014 	* If the <restriction> alternative is chosen, then the
18015 	* {variety} of the {base type definition}.
18016 	*/
18017 	if (WXS_IS_ATOMIC(type->baseType))
18018 	    type->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
18019 	else if (WXS_IS_LIST(type->baseType)) {
18020 	    type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
18021 	    /*
18022 	    * Inherit the itemType.
18023 	    */
18024 	    type->subtypes = type->baseType->subtypes;
18025 	} else if (WXS_IS_UNION(type->baseType)) {
18026 	    type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
18027 	    /*
18028 	    * NOTE that we won't assign the memberTypes of the base,
18029 	    * since this will make trouble when freeing them; we will
18030 	    * use a lookup function to access them instead.
18031 	    */
18032 	}
18033     }
18034     return(0);
18035 }
18036 
18037 #ifdef DEBUG_TYPE
18038 static void
xmlSchemaDebugFixedType(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)18039 xmlSchemaDebugFixedType(xmlSchemaParserCtxtPtr pctxt,
18040 		       xmlSchemaTypePtr type)
18041 {
18042     if (type->node != NULL) {
18043         xmlGenericError(xmlGenericErrorContext,
18044                         "Type of %s : %s:%d :", name,
18045                         type->node->doc->URL,
18046                         xmlGetLineNo(type->node));
18047     } else {
18048         xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
18049     }
18050     if ((WXS_IS_SIMPLE(type)) || (WXS_IS_COMPLEX(type))) {
18051 	switch (type->contentType) {
18052 	    case XML_SCHEMA_CONTENT_SIMPLE:
18053 		xmlGenericError(xmlGenericErrorContext, "simple\n");
18054 		break;
18055 	    case XML_SCHEMA_CONTENT_ELEMENTS:
18056 		xmlGenericError(xmlGenericErrorContext, "elements\n");
18057 		break;
18058 	    case XML_SCHEMA_CONTENT_UNKNOWN:
18059 		xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
18060 		break;
18061 	    case XML_SCHEMA_CONTENT_EMPTY:
18062 		xmlGenericError(xmlGenericErrorContext, "empty\n");
18063 		break;
18064 	    case XML_SCHEMA_CONTENT_MIXED:
18065 		if (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr)
18066 		    type->subtypes))
18067 		    xmlGenericError(xmlGenericErrorContext,
18068 			"mixed as emptiable particle\n");
18069 		else
18070 		    xmlGenericError(xmlGenericErrorContext, "mixed\n");
18071 		break;
18072 		/* Removed, since not used. */
18073 		/*
18074 		case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
18075 		xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
18076 		break;
18077 		*/
18078 	    case XML_SCHEMA_CONTENT_BASIC:
18079 		xmlGenericError(xmlGenericErrorContext, "basic\n");
18080 		break;
18081 	    default:
18082 		xmlGenericError(xmlGenericErrorContext,
18083 		    "not registered !!!\n");
18084 		break;
18085 	}
18086     }
18087 }
18088 #endif
18089 
18090 /*
18091 * 3.14.6 Constraints on Simple Type Definition Schema Components
18092 */
18093 static int
xmlSchemaFixupSimpleTypeStageTwo(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)18094 xmlSchemaFixupSimpleTypeStageTwo(xmlSchemaParserCtxtPtr pctxt,
18095 				 xmlSchemaTypePtr type)
18096 {
18097     int res, olderrs = pctxt->nberrors;
18098 
18099     if (type->type != XML_SCHEMA_TYPE_SIMPLE)
18100 	return(-1);
18101 
18102     if (! WXS_IS_TYPE_NOT_FIXED(type))
18103 	return(0);
18104 
18105     type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
18106     type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
18107 
18108     if (type->baseType == NULL) {
18109 	PERROR_INT("xmlSchemaFixupSimpleTypeStageTwo",
18110 	    "missing baseType");
18111 	goto exit_failure;
18112     }
18113     if (WXS_IS_TYPE_NOT_FIXED(type->baseType))
18114 	xmlSchemaTypeFixup(type->baseType, ACTXT_CAST pctxt);
18115     /*
18116     * If a member type of a union is a union itself, we need to substitute
18117     * that member type for its member types.
18118     * NOTE that this might change in WXS 1.1; i.e. we will keep the union
18119     * types in WXS 1.1.
18120     */
18121     if ((type->memberTypes != NULL) &&
18122 	(xmlSchemaFinishMemberTypeDefinitionsProperty(pctxt, type) == -1))
18123 	return(-1);
18124     /*
18125     * SPEC src-simple-type 1
18126     * "The corresponding simple type definition, if any, must satisfy
18127     * the conditions set out in Constraints on Simple Type Definition
18128     * Schema Components ($3.14.6)."
18129     */
18130     /*
18131     * Schema Component Constraint: Simple Type Definition Properties Correct
18132     * (st-props-correct)
18133     */
18134     res = xmlSchemaCheckSTPropsCorrect(pctxt, type);
18135     HFAILURE HERROR
18136     /*
18137     * Schema Component Constraint: Derivation Valid (Restriction, Simple)
18138     * (cos-st-restricts)
18139     */
18140     res = xmlSchemaCheckCOSSTRestricts(pctxt, type);
18141     HFAILURE HERROR
18142     /*
18143     * TODO: Removed the error report, since it got annoying to get an
18144     * extra error report, if anything failed until now.
18145     * Enable this if needed.
18146     *
18147     * xmlSchemaPErr(ctxt, type->node,
18148     *    XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
18149     *    "Simple type '%s' does not satisfy the constraints "
18150     *    "on simple type definitions.\n",
18151     *    type->name, NULL);
18152     */
18153     /*
18154     * Schema Component Constraint: Simple Type Restriction (Facets)
18155     * (st-restrict-facets)
18156     */
18157     res = xmlSchemaCheckFacetValues(type, pctxt);
18158     HFAILURE HERROR
18159     if ((type->facetSet != NULL) ||
18160 	(type->baseType->facetSet != NULL)) {
18161 	res = xmlSchemaDeriveAndValidateFacets(pctxt, type);
18162 	HFAILURE HERROR
18163     }
18164     /*
18165     * Whitespace value.
18166     */
18167     res = xmlSchemaTypeFixupWhitespace(type);
18168     HFAILURE HERROR
18169     xmlSchemaTypeFixupOptimFacets(type);
18170 
18171 exit_error:
18172 #ifdef DEBUG_TYPE
18173     xmlSchemaDebugFixedType(pctxt, type);
18174 #endif
18175     if (olderrs != pctxt->nberrors)
18176 	return(pctxt->err);
18177     return(0);
18178 
18179 exit_failure:
18180 #ifdef DEBUG_TYPE
18181     xmlSchemaDebugFixedType(pctxt, type);
18182 #endif
18183     return(-1);
18184 }
18185 
18186 static int
xmlSchemaFixupComplexType(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)18187 xmlSchemaFixupComplexType(xmlSchemaParserCtxtPtr pctxt,
18188 			  xmlSchemaTypePtr type)
18189 {
18190     int res = 0, olderrs = pctxt->nberrors;
18191     xmlSchemaTypePtr baseType = type->baseType;
18192 
18193     if (! WXS_IS_TYPE_NOT_FIXED(type))
18194 	return(0);
18195     type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
18196     if (baseType == NULL) {
18197 	PERROR_INT("xmlSchemaFixupComplexType",
18198 	    "missing baseType");
18199 	goto exit_failure;
18200     }
18201     /*
18202     * Fixup the base type.
18203     */
18204     if (WXS_IS_TYPE_NOT_FIXED(baseType))
18205 	xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt);
18206     if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) {
18207 	/*
18208 	* Skip fixup if the base type is invalid.
18209 	* TODO: Generate a warning!
18210 	*/
18211 	return(0);
18212     }
18213     /*
18214     * This basically checks if the base type can be derived.
18215     */
18216     res = xmlSchemaCheckSRCCT(pctxt, type);
18217     HFAILURE HERROR
18218     /*
18219     * Fixup the content type.
18220     */
18221     if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) {
18222 	/*
18223 	* Corresponds to <complexType><simpleContent>...
18224 	*/
18225 	if ((WXS_IS_COMPLEX(baseType)) &&
18226 	    (baseType->contentTypeDef != NULL) &&
18227 	    (WXS_IS_RESTRICTION(type))) {
18228 	    xmlSchemaTypePtr contentBase, content;
18229 #ifdef ENABLE_NAMED_LOCALS
18230 	    char buf[30];
18231 	    const xmlChar *tmpname;
18232 #endif
18233 	    /*
18234 	    * SPEC (1) If <restriction> + base type is <complexType>,
18235 	    * "whose own {content type} is a simple type..."
18236 	    */
18237 	    if (type->contentTypeDef != NULL) {
18238 		/*
18239 		* SPEC (1.1) "the simple type definition corresponding to the
18240 		* <simpleType> among the [children] of <restriction> if there
18241 		* is one;"
18242 		* Note that this "<simpleType> among the [children]" was put
18243 		* into ->contentTypeDef during parsing.
18244 		*/
18245 		contentBase = type->contentTypeDef;
18246 		type->contentTypeDef = NULL;
18247 	    } else {
18248 		/*
18249 		* (1.2) "...otherwise (<restriction> has no <simpleType>
18250 		* among its [children]), the simple type definition which
18251 		* is the {content type} of the ... base type."
18252 		*/
18253 		contentBase = baseType->contentTypeDef;
18254 	    }
18255 	    /*
18256 	    * SPEC
18257 	    * "... a simple type definition which restricts the simple
18258 	    * type definition identified in clause 1.1 or clause 1.2
18259 	    * with a set of facet components"
18260 	    *
18261 	    * Create the anonymous simple type, which will be the content
18262 	    * type of the complex type.
18263 	    */
18264 #ifdef ENABLE_NAMED_LOCALS
18265 	    snprintf(buf, 29, "#scST%d", ++(pctxt->counter));
18266 	    tmpname = xmlDictLookup(pctxt->dict, BAD_CAST buf, -1);
18267 	    content = xmlSchemaAddType(pctxt, pctxt->schema,
18268 		XML_SCHEMA_TYPE_SIMPLE, tmpname, type->targetNamespace,
18269 		type->node, 0);
18270 #else
18271 	    content = xmlSchemaAddType(pctxt, pctxt->schema,
18272 		XML_SCHEMA_TYPE_SIMPLE, NULL, type->targetNamespace,
18273 		type->node, 0);
18274 #endif
18275 	    if (content == NULL)
18276 		goto exit_failure;
18277 	    /*
18278 	    * We will use the same node as for the <complexType>
18279 	    * to have it somehow anchored in the schema doc.
18280 	    */
18281 	    content->type = XML_SCHEMA_TYPE_SIMPLE;
18282 	    content->baseType = contentBase;
18283 	    /*
18284 	    * Move the facets, previously anchored on the
18285 	    * complexType during parsing.
18286 	    */
18287 	    content->facets = type->facets;
18288 	    type->facets = NULL;
18289 	    content->facetSet = type->facetSet;
18290 	    type->facetSet = NULL;
18291 
18292 	    type->contentTypeDef = content;
18293 	    if (WXS_IS_TYPE_NOT_FIXED(contentBase))
18294 		xmlSchemaTypeFixup(contentBase, ACTXT_CAST pctxt);
18295 	    /*
18296 	    * Fixup the newly created type. We don't need to check
18297 	    * for circularity here.
18298 	    */
18299 	    res = xmlSchemaFixupSimpleTypeStageOne(pctxt, content);
18300 	    HFAILURE HERROR
18301 	    res = xmlSchemaFixupSimpleTypeStageTwo(pctxt, content);
18302 	    HFAILURE HERROR
18303 
18304 	} else if ((WXS_IS_COMPLEX(baseType)) &&
18305 	    (baseType->contentType == XML_SCHEMA_CONTENT_MIXED) &&
18306 	    (WXS_IS_RESTRICTION(type))) {
18307 	    /*
18308 	    * SPEC (2) If <restriction> + base is a mixed <complexType> with
18309 	    * an emptiable particle, then a simple type definition which
18310 	    * restricts the <restriction>'s <simpleType> child.
18311 	    */
18312 	    if ((type->contentTypeDef == NULL) ||
18313 		(type->contentTypeDef->baseType == NULL)) {
18314 		/*
18315 		* TODO: Check if this ever happens.
18316 		*/
18317 		xmlSchemaPCustomErr(pctxt,
18318 		    XML_SCHEMAP_INTERNAL,
18319 		    WXS_BASIC_CAST type, NULL,
18320 		    "Internal error: xmlSchemaTypeFixup, "
18321 		    "complex type '%s': the <simpleContent><restriction> "
18322 		    "is missing a <simpleType> child, but was not catched "
18323 		    "by xmlSchemaCheckSRCCT()", type->name);
18324 		goto exit_failure;
18325 	    }
18326 	} else if ((WXS_IS_COMPLEX(baseType)) && WXS_IS_EXTENSION(type)) {
18327 	    /*
18328 	    * SPEC (3) If <extension> + base is <complexType> with
18329 	    * <simpleType> content, "...then the {content type} of that
18330 	    * complex type definition"
18331 	    */
18332 	    if (baseType->contentTypeDef == NULL) {
18333 		/*
18334 		* TODO: Check if this ever happens. xmlSchemaCheckSRCCT
18335 		* should have catched this already.
18336 		*/
18337 		xmlSchemaPCustomErr(pctxt,
18338 		    XML_SCHEMAP_INTERNAL,
18339 		    WXS_BASIC_CAST type, NULL,
18340 		    "Internal error: xmlSchemaTypeFixup, "
18341 		    "complex type '%s': the <extension>ed base type is "
18342 		    "a complex type with no simple content type",
18343 		    type->name);
18344 		goto exit_failure;
18345 	    }
18346 	    type->contentTypeDef = baseType->contentTypeDef;
18347 	} else if ((WXS_IS_SIMPLE(baseType)) && WXS_IS_EXTENSION(type)) {
18348 	    /*
18349 	    * SPEC (4) <extension> + base is <simpleType>
18350 	    * "... then that simple type definition"
18351 	    */
18352 	    type->contentTypeDef = baseType;
18353 	} else {
18354 	    /*
18355 	    * TODO: Check if this ever happens.
18356 	    */
18357 	    xmlSchemaPCustomErr(pctxt,
18358 		XML_SCHEMAP_INTERNAL,
18359 		WXS_BASIC_CAST type, NULL,
18360 		"Internal error: xmlSchemaTypeFixup, "
18361 		"complex type '%s' with <simpleContent>: unhandled "
18362 		"derivation case", type->name);
18363 	    goto exit_failure;
18364 	}
18365     } else {
18366 	int dummySequence = 0;
18367 	xmlSchemaParticlePtr particle =
18368 	    (xmlSchemaParticlePtr) type->subtypes;
18369 	/*
18370 	* Corresponds to <complexType><complexContent>...
18371 	*
18372 	* NOTE that the effective mixed was already set during parsing of
18373 	* <complexType> and <complexContent>; its flag value is
18374 	* XML_SCHEMAS_TYPE_MIXED.
18375 	*
18376 	* Compute the "effective content":
18377 	* (2.1.1) + (2.1.2) + (2.1.3)
18378 	*/
18379 	if ((particle == NULL) ||
18380 	    ((particle->type == XML_SCHEMA_TYPE_PARTICLE) &&
18381 	    ((particle->children->type == XML_SCHEMA_TYPE_ALL) ||
18382 	    (particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) ||
18383 	    ((particle->children->type == XML_SCHEMA_TYPE_CHOICE) &&
18384 	    (particle->minOccurs == 0))) &&
18385 	    ( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) {
18386 	    if (type->flags & XML_SCHEMAS_TYPE_MIXED) {
18387 		/*
18388 		* SPEC (2.1.4) "If the `effective mixed` is true, then
18389 		* a particle whose properties are as follows:..."
18390 		*
18391 		* Empty sequence model group with
18392 		* minOccurs/maxOccurs = 1 (i.e. a "particle emptiable").
18393 		* NOTE that we sill assign it the <complexType> node to
18394 		* somehow anchor it in the doc.
18395 		*/
18396 		if ((particle == NULL) ||
18397 		    (particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) {
18398 		    /*
18399 		    * Create the particle.
18400 		    */
18401 		    particle = xmlSchemaAddParticle(pctxt,
18402 			type->node, 1, 1);
18403 		    if (particle == NULL)
18404 			goto exit_failure;
18405 		    /*
18406 		    * Create the model group.
18407 		    */ /* URGENT TODO: avoid adding to pending items. */
18408 		    particle->children = (xmlSchemaTreeItemPtr)
18409 			xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18410 			XML_SCHEMA_TYPE_SEQUENCE, type->node);
18411 		    if (particle->children == NULL)
18412 			goto exit_failure;
18413 
18414 		    type->subtypes = (xmlSchemaTypePtr) particle;
18415 		}
18416 		dummySequence = 1;
18417 		type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18418 	    } else {
18419 		/*
18420 		* SPEC (2.1.5) "otherwise empty"
18421 		*/
18422 		type->contentType = XML_SCHEMA_CONTENT_EMPTY;
18423 	    }
18424 	} else {
18425 	    /*
18426 	    * SPEC (2.2) "otherwise the particle corresponding to the
18427 	    * <all>, <choice>, <group> or <sequence> among the
18428 	    * [children]."
18429 	    */
18430 	    type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18431 	}
18432 	/*
18433 	* Compute the "content type".
18434 	*/
18435 	if (WXS_IS_RESTRICTION(type)) {
18436 	    /*
18437 	    * SPEC (3.1) "If <restriction>..."
18438 	    * (3.1.1) + (3.1.2) */
18439 	    if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) {
18440 		if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18441 		    type->contentType = XML_SCHEMA_CONTENT_MIXED;
18442 	    }
18443 	} else {
18444 	    /*
18445 	    * SPEC (3.2) "If <extension>..."
18446 	    */
18447 	    if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18448 		/*
18449 		* SPEC (3.2.1)
18450 		* "If the `effective content` is empty, then the
18451 		*  {content type} of the [...] base ..."
18452 		*/
18453 		type->contentType = baseType->contentType;
18454 		type->subtypes = baseType->subtypes;
18455 		/*
18456 		* Fixes bug #347316:
18457 		* This is the case when the base type has a simple
18458 		* type definition as content.
18459 		*/
18460 		type->contentTypeDef = baseType->contentTypeDef;
18461 		/*
18462 		* NOTE that the effective mixed is ignored here.
18463 		*/
18464 	    } else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18465 		/*
18466 		* SPEC (3.2.2)
18467 		*/
18468 		if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18469 		    type->contentType = XML_SCHEMA_CONTENT_MIXED;
18470 	    } else {
18471 		/*
18472 		* SPEC (3.2.3)
18473 		*/
18474 		if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18475 		    type->contentType = XML_SCHEMA_CONTENT_MIXED;
18476 		    /*
18477 		    * "A model group whose {compositor} is sequence and whose
18478 		    * {particles} are..."
18479 		    */
18480 		if ((WXS_TYPE_PARTICLE(type) != NULL) &&
18481 		    (WXS_TYPE_PARTICLE_TERM(type) != NULL) &&
18482 		    ((WXS_TYPE_PARTICLE_TERM(type))->type ==
18483 			XML_SCHEMA_TYPE_ALL))
18484 		{
18485 		    /*
18486 		    * SPEC cos-all-limited (1)
18487 		    */
18488 		    xmlSchemaCustomErr(ACTXT_CAST pctxt,
18489 			/* TODO: error code */
18490 			XML_SCHEMAP_COS_ALL_LIMITED,
18491 			WXS_ITEM_NODE(type), NULL,
18492 			"The type has an 'all' model group in its "
18493 			"{content type} and thus cannot be derived from "
18494 			"a non-empty type, since this would produce a "
18495 			"'sequence' model group containing the 'all' "
18496 			"model group; 'all' model groups are not "
18497 			"allowed to appear inside other model groups",
18498 			NULL, NULL);
18499 
18500 		} else if ((WXS_TYPE_PARTICLE(baseType) != NULL) &&
18501 		    (WXS_TYPE_PARTICLE_TERM(baseType) != NULL) &&
18502 		    ((WXS_TYPE_PARTICLE_TERM(baseType))->type ==
18503 			XML_SCHEMA_TYPE_ALL))
18504 		{
18505 		    /*
18506 		    * SPEC cos-all-limited (1)
18507 		    */
18508 		    xmlSchemaCustomErr(ACTXT_CAST pctxt,
18509 			/* TODO: error code */
18510 			XML_SCHEMAP_COS_ALL_LIMITED,
18511 			WXS_ITEM_NODE(type), NULL,
18512 			"A type cannot be derived by extension from a type "
18513 			"which has an 'all' model group in its "
18514 			"{content type}, since this would produce a "
18515 			"'sequence' model group containing the 'all' "
18516 			"model group; 'all' model groups are not "
18517 			"allowed to appear inside other model groups",
18518 			NULL, NULL);
18519 
18520 		} else if (! dummySequence) {
18521 		    xmlSchemaTreeItemPtr effectiveContent =
18522 			(xmlSchemaTreeItemPtr) type->subtypes;
18523 		    /*
18524 		    * Create the particle.
18525 		    */
18526 		    particle = xmlSchemaAddParticle(pctxt,
18527 			type->node, 1, 1);
18528 		    if (particle == NULL)
18529 			goto exit_failure;
18530 		    /*
18531 		    * Create the "sequence" model group.
18532 		    */
18533 		    particle->children = (xmlSchemaTreeItemPtr)
18534 			xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18535 			XML_SCHEMA_TYPE_SEQUENCE, type->node);
18536 		    if (particle->children == NULL)
18537 			goto exit_failure;
18538 		    WXS_TYPE_CONTENTTYPE(type) = (xmlSchemaTypePtr) particle;
18539 		    /*
18540 		    * SPEC "the particle of the {content type} of
18541 		    * the ... base ..."
18542 		    * Create a duplicate of the base type's particle
18543 		    * and assign its "term" to it.
18544 		    */
18545 		    particle->children->children =
18546 			(xmlSchemaTreeItemPtr) xmlSchemaAddParticle(pctxt,
18547 			type->node,
18548 			((xmlSchemaParticlePtr) baseType->subtypes)->minOccurs,
18549 			((xmlSchemaParticlePtr) baseType->subtypes)->maxOccurs);
18550 		    if (particle->children->children == NULL)
18551 			goto exit_failure;
18552 		    particle = (xmlSchemaParticlePtr)
18553 			particle->children->children;
18554 		    particle->children =
18555 			((xmlSchemaParticlePtr) baseType->subtypes)->children;
18556 		    /*
18557 		    * SPEC "followed by the `effective content`."
18558 		    */
18559 		    particle->next = effectiveContent;
18560 		    /*
18561 		    * This all will result in:
18562 		    * new-particle
18563 		    *   --> new-sequence(
18564 		    *         new-particle
18565 		    *           --> base-model,
18566 		    *         this-particle
18567 		    *	        --> this-model
18568 		    *	    )
18569 		    */
18570 		} else {
18571 		    /*
18572 		    * This is the case when there is already an empty
18573 		    * <sequence> with minOccurs==maxOccurs==1.
18574 		    * Just add the base types's content type.
18575 		    * NOTE that, although we miss to add an intermediate
18576 		    * <sequence>, this should produce no difference to
18577 		    * neither the regex compilation of the content model,
18578 		    * nor to the complex type contraints.
18579 		    */
18580 		    particle->children->children =
18581 			(xmlSchemaTreeItemPtr) baseType->subtypes;
18582 		}
18583 	    }
18584 	}
18585     }
18586     /*
18587     * Now fixup attribute uses:
18588     *   - expand attr. group references
18589     *     - intersect attribute wildcards
18590     *   - inherit attribute uses of the base type
18591     *   - inherit or union attr. wildcards if extending
18592     *   - apply attr. use prohibitions if restricting
18593     */
18594     res = xmlSchemaFixupTypeAttributeUses(pctxt, type);
18595     HFAILURE HERROR
18596     /*
18597     * Apply the complex type component constraints; this will not
18598     * check attributes, since this is done in
18599     * xmlSchemaFixupTypeAttributeUses().
18600     */
18601     res = xmlSchemaCheckCTComponent(pctxt, type);
18602     HFAILURE HERROR
18603 
18604 #ifdef DEBUG_TYPE
18605     xmlSchemaDebugFixedType(pctxt, type);
18606 #endif
18607     if (olderrs != pctxt->nberrors)
18608 	return(pctxt->err);
18609     else
18610 	return(0);
18611 
18612 exit_error:
18613     type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18614 #ifdef DEBUG_TYPE
18615     xmlSchemaDebugFixedType(pctxt, type);
18616 #endif
18617     return(pctxt->err);
18618 
18619 exit_failure:
18620     type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18621 #ifdef DEBUG_TYPE
18622     xmlSchemaDebugFixedType(pctxt, type);
18623 #endif
18624     return(-1);
18625 }
18626 
18627 
18628 /**
18629  * xmlSchemaTypeFixup:
18630  * @typeDecl:  the schema type definition
18631  * @ctxt:  the schema parser context
18632  *
18633  * Fixes the content model of the type.
18634  * URGENT TODO: We need an int result!
18635  */
18636 static int
xmlSchemaTypeFixup(xmlSchemaTypePtr type,xmlSchemaAbstractCtxtPtr actxt)18637 xmlSchemaTypeFixup(xmlSchemaTypePtr type,
18638                    xmlSchemaAbstractCtxtPtr actxt)
18639 {
18640     if (type == NULL)
18641         return(0);
18642     if (actxt->type != XML_SCHEMA_CTXT_PARSER) {
18643 	AERROR_INT("xmlSchemaTypeFixup",
18644 	    "this function needs a parser context");
18645 	return(-1);
18646     }
18647     if (! WXS_IS_TYPE_NOT_FIXED(type))
18648 	return(0);
18649     if (type->type == XML_SCHEMA_TYPE_COMPLEX)
18650 	return(xmlSchemaFixupComplexType(PCTXT_CAST actxt, type));
18651     else if (type->type == XML_SCHEMA_TYPE_SIMPLE)
18652 	return(xmlSchemaFixupSimpleTypeStageTwo(PCTXT_CAST actxt, type));
18653     return(0);
18654 }
18655 
18656 /**
18657  * xmlSchemaCheckFacet:
18658  * @facet:  the facet
18659  * @typeDecl:  the schema type definition
18660  * @pctxt:  the schema parser context or NULL
18661  * @name: the optional name of the type
18662  *
18663  * Checks and computes the values of facets.
18664  *
18665  * Returns 0 if valid, a positive error code if not valid and
18666  *         -1 in case of an internal or API error.
18667  */
18668 int
xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,xmlSchemaTypePtr typeDecl,xmlSchemaParserCtxtPtr pctxt,const xmlChar * name ATTRIBUTE_UNUSED)18669 xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
18670                     xmlSchemaTypePtr typeDecl,
18671                     xmlSchemaParserCtxtPtr pctxt,
18672 		    const xmlChar * name ATTRIBUTE_UNUSED)
18673 {
18674     int ret = 0, ctxtGiven;
18675 
18676     if ((facet == NULL) || (typeDecl == NULL))
18677         return(-1);
18678     /*
18679     * TODO: will the parser context be given if used from
18680     * the relaxNG module?
18681     */
18682     if (pctxt == NULL)
18683 	ctxtGiven = 0;
18684     else
18685 	ctxtGiven = 1;
18686 
18687     switch (facet->type) {
18688         case XML_SCHEMA_FACET_MININCLUSIVE:
18689         case XML_SCHEMA_FACET_MINEXCLUSIVE:
18690         case XML_SCHEMA_FACET_MAXINCLUSIVE:
18691         case XML_SCHEMA_FACET_MAXEXCLUSIVE:
18692 	case XML_SCHEMA_FACET_ENUMERATION: {
18693                 /*
18694                  * Okay we need to validate the value
18695                  * at that point.
18696                  */
18697 		xmlSchemaTypePtr base;
18698 
18699 		/* 4.3.5.5 Constraints on enumeration Schema Components
18700 		* Schema Component Constraint: enumeration valid restriction
18701 		* It is an `error` if any member of {value} is not in the
18702 		* `value space` of {base type definition}.
18703 		*
18704 		* minInclusive, maxInclusive, minExclusive, maxExclusive:
18705 		* The value `must` be in the
18706 		* `value space` of the `base type`.
18707 		*/
18708 		/*
18709 		* This function is intended to deliver a compiled value
18710 		* on the facet. In this implementation of XML Schemata the
18711 		* type holding a facet, won't be a built-in type.
18712 		* Thus to ensure that other API
18713 		* calls (relaxng) do work, if the given type is a built-in
18714 		* type, we will assume that the given built-in type *is
18715 		* already* the base type.
18716 		*/
18717 		if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
18718 		    base = typeDecl->baseType;
18719 		    if (base == NULL) {
18720 			PERROR_INT("xmlSchemaCheckFacet",
18721 			    "a type user derived type has no base type");
18722 			return (-1);
18723 		    }
18724 		} else
18725 		    base = typeDecl;
18726 
18727 		if (! ctxtGiven) {
18728 		    /*
18729 		    * A context is needed if called from RelaxNG.
18730 		    */
18731 		    pctxt = xmlSchemaNewParserCtxt("*");
18732 		    if (pctxt == NULL)
18733 			return (-1);
18734 		}
18735 		/*
18736 		* NOTE: This call does not check the content nodes,
18737 		* since they are not available:
18738 		* facet->node is just the node holding the facet
18739 		* definition, *not* the attribute holding the *value*
18740 		* of the facet.
18741 		*/
18742 		ret = xmlSchemaVCheckCVCSimpleType(
18743 		    ACTXT_CAST pctxt, facet->node, base,
18744 		    facet->value, &(facet->val), 1, 1, 0);
18745                 if (ret != 0) {
18746 		    if (ret < 0) {
18747 			/* No error message for RelaxNG. */
18748 			if (ctxtGiven) {
18749 			    xmlSchemaCustomErr(ACTXT_CAST pctxt,
18750 				XML_SCHEMAP_INTERNAL, facet->node, NULL,
18751 				"Internal error: xmlSchemaCheckFacet, "
18752 				"failed to validate the value '%s' of the "
18753 				"facet '%s' against the base type",
18754 				facet->value, xmlSchemaFacetTypeToString(facet->type));
18755 			}
18756 			goto internal_error;
18757 		    }
18758 		    ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18759 		    /* No error message for RelaxNG. */
18760 		    if (ctxtGiven) {
18761 			xmlChar *str = NULL;
18762 
18763 			xmlSchemaCustomErr(ACTXT_CAST pctxt,
18764 			    ret, facet->node, WXS_BASIC_CAST facet,
18765 			    "The value '%s' of the facet does not validate "
18766 			    "against the base type '%s'",
18767 			    facet->value,
18768 			    xmlSchemaFormatQName(&str,
18769 				base->targetNamespace, base->name));
18770 			FREE_AND_NULL(str);
18771 		    }
18772 		    goto exit;
18773                 } else if (facet->val == NULL) {
18774 		    if (ctxtGiven) {
18775 			PERROR_INT("xmlSchemaCheckFacet",
18776 			    "value was not computed");
18777 		    }
18778 		    TODO
18779 		}
18780                 break;
18781             }
18782         case XML_SCHEMA_FACET_PATTERN:
18783             facet->regexp = xmlRegexpCompile(facet->value);
18784             if (facet->regexp == NULL) {
18785 		ret = XML_SCHEMAP_REGEXP_INVALID;
18786 		/* No error message for RelaxNG. */
18787 		if (ctxtGiven) {
18788 		    xmlSchemaCustomErr(ACTXT_CAST pctxt,
18789 			ret, facet->node, WXS_BASIC_CAST typeDecl,
18790 			"The value '%s' of the facet 'pattern' is not a "
18791 			"valid regular expression",
18792 			facet->value, NULL);
18793 		}
18794             }
18795             break;
18796         case XML_SCHEMA_FACET_TOTALDIGITS:
18797         case XML_SCHEMA_FACET_FRACTIONDIGITS:
18798         case XML_SCHEMA_FACET_LENGTH:
18799         case XML_SCHEMA_FACET_MAXLENGTH:
18800         case XML_SCHEMA_FACET_MINLENGTH:
18801 
18802 	    if (facet->type == XML_SCHEMA_FACET_TOTALDIGITS) {
18803 		ret = xmlSchemaValidatePredefinedType(
18804 		    xmlSchemaGetBuiltInType(XML_SCHEMAS_PINTEGER),
18805 		    facet->value, &(facet->val));
18806 	    } else {
18807 		ret = xmlSchemaValidatePredefinedType(
18808 		    xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER),
18809 		    facet->value, &(facet->val));
18810 	    }
18811 	    if (ret != 0) {
18812 		if (ret < 0) {
18813 		    /* No error message for RelaxNG. */
18814 		    if (ctxtGiven) {
18815 			PERROR_INT("xmlSchemaCheckFacet",
18816 			    "validating facet value");
18817 		    }
18818 		    goto internal_error;
18819 		}
18820 		ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18821 		/* No error message for RelaxNG. */
18822 		if (ctxtGiven) {
18823 		    /* error code */
18824 		    xmlSchemaCustomErr4(ACTXT_CAST pctxt,
18825 			ret, facet->node, WXS_BASIC_CAST typeDecl,
18826 			"The value '%s' of the facet '%s' is not a valid '%s'",
18827 			facet->value,
18828 			xmlSchemaFacetTypeToString(facet->type),
18829 			(facet->type != XML_SCHEMA_FACET_TOTALDIGITS) ?
18830 			    BAD_CAST "nonNegativeInteger" :
18831 			    BAD_CAST "positiveInteger",
18832 			NULL);
18833 		}
18834 	    }
18835 	    break;
18836 
18837         case XML_SCHEMA_FACET_WHITESPACE:{
18838                 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
18839                     facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
18840                 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
18841                     facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
18842                 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
18843                     facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
18844                 } else {
18845 		    ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18846                     /* No error message for RelaxNG. */
18847 		    if (ctxtGiven) {
18848 			/* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */
18849 			xmlSchemaCustomErr(ACTXT_CAST pctxt,
18850 			    ret, facet->node, WXS_BASIC_CAST typeDecl,
18851 			    "The value '%s' of the facet 'whitespace' is not "
18852 			    "valid", facet->value, NULL);
18853                     }
18854                 }
18855             }
18856         default:
18857             break;
18858     }
18859 exit:
18860     if ((! ctxtGiven) && (pctxt != NULL))
18861 	xmlSchemaFreeParserCtxt(pctxt);
18862     return (ret);
18863 internal_error:
18864     if ((! ctxtGiven) && (pctxt != NULL))
18865 	xmlSchemaFreeParserCtxt(pctxt);
18866     return (-1);
18867 }
18868 
18869 /**
18870  * xmlSchemaCheckFacetValues:
18871  * @typeDecl:  the schema type definition
18872  * @ctxt:  the schema parser context
18873  *
18874  * Checks the default values types, especially for facets
18875  */
18876 static int
xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,xmlSchemaParserCtxtPtr pctxt)18877 xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
18878 			  xmlSchemaParserCtxtPtr pctxt)
18879 {
18880     int res, olderrs = pctxt->nberrors;
18881     const xmlChar *name = typeDecl->name;
18882     /*
18883     * NOTE: It is intended to use the facets list, instead
18884     * of facetSet.
18885     */
18886     if (typeDecl->facets != NULL) {
18887 	xmlSchemaFacetPtr facet = typeDecl->facets;
18888 
18889 	/*
18890 	* Temporarily assign the "schema" to the validation context
18891 	* of the parser context. This is needed for NOTATION validation.
18892 	*/
18893 	if (pctxt->vctxt == NULL) {
18894 	    if (xmlSchemaCreateVCtxtOnPCtxt(pctxt) == -1)
18895 		return(-1);
18896 	}
18897 	pctxt->vctxt->schema = pctxt->schema;
18898 	while (facet != NULL) {
18899 	    res = xmlSchemaCheckFacet(facet, typeDecl, pctxt, name);
18900 	    HFAILURE
18901 	    facet = facet->next;
18902 	}
18903 	pctxt->vctxt->schema = NULL;
18904     }
18905     if (olderrs != pctxt->nberrors)
18906 	return(pctxt->err);
18907     return(0);
18908 exit_failure:
18909     return(-1);
18910 }
18911 
18912 /**
18913  * xmlSchemaGetCircModelGrDefRef:
18914  * @ctxtMGroup: the searched model group
18915  * @selfMGroup: the second searched model group
18916  * @particle: the first particle
18917  *
18918  * This one is intended to be used by
18919  * xmlSchemaCheckGroupDefCircular only.
18920  *
18921  * Returns the particle with the circular model group definition reference,
18922  * otherwise NULL.
18923  */
18924 static xmlSchemaTreeItemPtr
xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,xmlSchemaTreeItemPtr particle)18925 xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,
18926 			      xmlSchemaTreeItemPtr particle)
18927 {
18928     xmlSchemaTreeItemPtr circ = NULL;
18929     xmlSchemaTreeItemPtr term;
18930     xmlSchemaModelGroupDefPtr gdef;
18931 
18932     for (; particle != NULL; particle = particle->next) {
18933 	term = particle->children;
18934 	if (term == NULL)
18935 	    continue;
18936 	switch (term->type) {
18937 	    case XML_SCHEMA_TYPE_GROUP:
18938 		gdef = (xmlSchemaModelGroupDefPtr) term;
18939 		if (gdef == groupDef)
18940 		    return (particle);
18941 		/*
18942 		* Mark this model group definition to avoid infinite
18943 		* recursion on circular references not yet examined.
18944 		*/
18945 		if (gdef->flags & XML_SCHEMA_MODEL_GROUP_DEF_MARKED)
18946 		    continue;
18947 		if (gdef->children != NULL) {
18948 		    gdef->flags |= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18949 		    circ = xmlSchemaGetCircModelGrDefRef(groupDef,
18950 			gdef->children->children);
18951 		    gdef->flags ^= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18952 		    if (circ != NULL)
18953 			return (circ);
18954 		}
18955 		break;
18956 	    case XML_SCHEMA_TYPE_SEQUENCE:
18957 	    case XML_SCHEMA_TYPE_CHOICE:
18958 	    case XML_SCHEMA_TYPE_ALL:
18959 		circ = xmlSchemaGetCircModelGrDefRef(groupDef, term->children);
18960 		if (circ != NULL)
18961 		    return (circ);
18962 		break;
18963 	    default:
18964 		break;
18965 	}
18966     }
18967     return (NULL);
18968 }
18969 
18970 /**
18971  * xmlSchemaCheckGroupDefCircular:
18972  * @item:  the model group definition
18973  * @ctxt:  the parser context
18974  * @name:  the name
18975  *
18976  * Checks for circular references to model group definitions.
18977  */
18978 static void
xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,xmlSchemaParserCtxtPtr ctxt)18979 xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,
18980 			       xmlSchemaParserCtxtPtr ctxt)
18981 {
18982     /*
18983     * Schema Component Constraint: Model Group Correct
18984     * 2 Circular groups are disallowed. That is, within the {particles}
18985     * of a group there must not be at any depth a particle whose {term}
18986     * is the group itself.
18987     */
18988     if ((item == NULL) ||
18989 	(item->type != XML_SCHEMA_TYPE_GROUP) ||
18990 	(item->children == NULL))
18991 	return;
18992     {
18993 	xmlSchemaTreeItemPtr circ;
18994 
18995 	circ = xmlSchemaGetCircModelGrDefRef(item, item->children->children);
18996 	if (circ != NULL) {
18997 	    xmlChar *str = NULL;
18998 	    /*
18999 	    * TODO: The error report is not adequate: this constraint
19000 	    * is defined for model groups but not definitions, but since
19001 	    * there cannot be any circular model groups without a model group
19002 	    * definition (if not using a construction API), we check those
19003 	    * defintions only.
19004 	    */
19005 	    xmlSchemaPCustomErr(ctxt,
19006 		XML_SCHEMAP_MG_PROPS_CORRECT_2,
19007 		NULL, WXS_ITEM_NODE(circ),
19008 		"Circular reference to the model group definition '%s' "
19009 		"defined", xmlSchemaFormatQName(&str,
19010 		    item->targetNamespace, item->name));
19011 	    FREE_AND_NULL(str)
19012 	    /*
19013 	    * NOTE: We will cut the reference to avoid further
19014 	    * confusion of the processor. This is a fatal error.
19015 	    */
19016 	    circ->children = NULL;
19017 	}
19018     }
19019 }
19020 
19021 /**
19022  * xmlSchemaModelGroupToModelGroupDefFixup:
19023  * @ctxt:  the parser context
19024  * @mg:  the model group
19025  *
19026  * Assigns the model group of model group definitions to the "term"
19027  * of the referencing particle.
19028  * In xmlSchemaResolveModelGroupParticleReferences the model group
19029  * definitions were assigned to the "term", since needed for the
19030  * circularity check.
19031  *
19032  * Schema Component Constraint:
19033  *     All Group Limited (cos-all-limited) (1.2)
19034  */
19035 static void
xmlSchemaModelGroupToModelGroupDefFixup(xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,xmlSchemaModelGroupPtr mg)19036 xmlSchemaModelGroupToModelGroupDefFixup(
19037     xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
19038     xmlSchemaModelGroupPtr mg)
19039 {
19040     xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
19041 
19042     while (particle != NULL) {
19043 	if ((WXS_PARTICLE_TERM(particle) == NULL) ||
19044 	    ((WXS_PARTICLE_TERM(particle))->type !=
19045 		XML_SCHEMA_TYPE_GROUP))
19046 	{
19047 	    particle = WXS_PTC_CAST particle->next;
19048 	    continue;
19049 	}
19050 	if (WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle)) == NULL) {
19051 	    /*
19052 	    * TODO: Remove the particle.
19053 	    */
19054 	    WXS_PARTICLE_TERM(particle) = NULL;
19055 	    particle = WXS_PTC_CAST particle->next;
19056 	    continue;
19057 	}
19058 	/*
19059 	* Assign the model group to the {term} of the particle.
19060 	*/
19061 	WXS_PARTICLE_TERM(particle) =
19062 	    WXS_TREE_CAST WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle));
19063 
19064 	particle = WXS_PTC_CAST particle->next;
19065     }
19066 }
19067 
19068 /**
19069  * xmlSchemaCheckAttrGroupCircularRecur:
19070  * @ctxtGr: the searched attribute group
19071  * @attr: the current attribute list to be processed
19072  *
19073  * This one is intended to be used by
19074  * xmlSchemaCheckAttrGroupCircular only.
19075  *
19076  * Returns the circular attribute grou reference, otherwise NULL.
19077  */
19078 static xmlSchemaQNameRefPtr
xmlSchemaCheckAttrGroupCircularRecur(xmlSchemaAttributeGroupPtr ctxtGr,xmlSchemaItemListPtr list)19079 xmlSchemaCheckAttrGroupCircularRecur(xmlSchemaAttributeGroupPtr ctxtGr,
19080 				     xmlSchemaItemListPtr list)
19081 {
19082     xmlSchemaAttributeGroupPtr gr;
19083     xmlSchemaQNameRefPtr ref, circ;
19084     int i;
19085     /*
19086     * We will search for an attribute group reference which
19087     * references the context attribute group.
19088     */
19089     for (i = 0; i < list->nbItems; i++) {
19090 	ref = list->items[i];
19091 	if ((ref->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
19092 	    (ref->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
19093 	    (ref->item != NULL))
19094 	{
19095 	    gr = WXS_ATTR_GROUP_CAST ref->item;
19096 	    if (gr == ctxtGr)
19097 		return(ref);
19098 	    if (gr->flags & XML_SCHEMAS_ATTRGROUP_MARKED)
19099 		continue;
19100 	    /*
19101 	    * Mark as visited to avoid infinite recursion on
19102 	    * circular references not yet examined.
19103 	    */
19104 	    if ((gr->attrUses) &&
19105 		(gr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS))
19106 	    {
19107 		gr->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
19108 		circ = xmlSchemaCheckAttrGroupCircularRecur(ctxtGr,
19109 		    (xmlSchemaItemListPtr) gr->attrUses);
19110 		gr->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
19111 		if (circ != NULL)
19112 		    return (circ);
19113 	    }
19114 
19115 	}
19116     }
19117     return (NULL);
19118 }
19119 
19120 /**
19121  * xmlSchemaCheckAttrGroupCircular:
19122  * attrGr:  the attribute group definition
19123  * @ctxt:  the parser context
19124  * @name:  the name
19125  *
19126  * Checks for circular references of attribute groups.
19127  */
19128 static int
xmlSchemaCheckAttrGroupCircular(xmlSchemaAttributeGroupPtr attrGr,xmlSchemaParserCtxtPtr ctxt)19129 xmlSchemaCheckAttrGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
19130 				xmlSchemaParserCtxtPtr ctxt)
19131 {
19132     /*
19133     * Schema Representation Constraint:
19134     * Attribute Group Definition Representation OK
19135     * 3 Circular group reference is disallowed outside <redefine>.
19136     * That is, unless this element information item's parent is
19137     * <redefine>, then among the [children], if any, there must
19138     * not be an <attributeGroup> with ref [attribute] which resolves
19139     * to the component corresponding to this <attributeGroup>. Indirect
19140     * circularity is also ruled out. That is, when QName resolution
19141     * (Schema Document) ($3.15.3) is applied to a `QName` arising from
19142     * any <attributeGroup>s with a ref [attribute] among the [children],
19143     * it must not be the case that a `QName` is encountered at any depth
19144     * which resolves to the component corresponding to this <attributeGroup>.
19145     */
19146     if (attrGr->attrUses == NULL)
19147 	return(0);
19148     else if ((attrGr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS) == 0)
19149 	return(0);
19150     else {
19151 	xmlSchemaQNameRefPtr circ;
19152 
19153 	circ = xmlSchemaCheckAttrGroupCircularRecur(attrGr,
19154 	    (xmlSchemaItemListPtr) attrGr->attrUses);
19155 	if (circ != NULL) {
19156 	    xmlChar *str = NULL;
19157 	    /*
19158 	    * TODO: Report the referenced attr group as QName.
19159 	    */
19160 	    xmlSchemaPCustomErr(ctxt,
19161 		XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
19162 		NULL, WXS_ITEM_NODE(WXS_BASIC_CAST circ),
19163 		"Circular reference to the attribute group '%s' "
19164 		"defined", xmlSchemaGetComponentQName(&str, attrGr));
19165 	    FREE_AND_NULL(str);
19166 	    /*
19167 	    * NOTE: We will cut the reference to avoid further
19168 	    * confusion of the processor.
19169 	    * BADSPEC TODO: The spec should define how to process in this case.
19170 	    */
19171 	    circ->item = NULL;
19172 	    return(ctxt->err);
19173 	}
19174     }
19175     return(0);
19176 }
19177 
19178 static int
19179 xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19180 				  xmlSchemaAttributeGroupPtr attrGr);
19181 
19182 /**
19183  * xmlSchemaExpandAttributeGroupRefs:
19184  * @pctxt: the parser context
19185  * @node: the node of the component holding the attribute uses
19186  * @completeWild: the intersected wildcard to be returned
19187  * @list: the attribute uses
19188  *
19189  * Substitutes contained attribute group references
19190  * for their attribute uses. Wilcards are intersected.
19191  * Attribute use prohibitions are removed from the list
19192  * and returned via the @prohibs list.
19193  * Pointlessness of attr. prohibs, if a matching attr. decl
19194  * is existent a well, are checked.
19195  */
19196 static int
xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,xmlSchemaBasicItemPtr item,xmlSchemaWildcardPtr * completeWild,xmlSchemaItemListPtr list,xmlSchemaItemListPtr prohibs)19197 xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
19198 				  xmlSchemaBasicItemPtr item,
19199 				  xmlSchemaWildcardPtr *completeWild,
19200 				  xmlSchemaItemListPtr list,
19201 				  xmlSchemaItemListPtr prohibs)
19202 {
19203     xmlSchemaAttributeGroupPtr gr;
19204     xmlSchemaAttributeUsePtr use;
19205     xmlSchemaItemListPtr sublist;
19206     int i, j;
19207     int created = (*completeWild == NULL) ? 0 : 1;
19208 
19209     if (prohibs)
19210 	prohibs->nbItems = 0;
19211 
19212     for (i = 0; i < list->nbItems; i++) {
19213 	use = list->items[i];
19214 
19215 	if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
19216 	    if (prohibs == NULL) {
19217 		PERROR_INT("xmlSchemaExpandAttributeGroupRefs",
19218 		    "unexpected attr prohibition found");
19219 		return(-1);
19220 	    }
19221 	    /*
19222 	    * Remove from attribute uses.
19223 	    */
19224 	    if (xmlSchemaItemListRemove(list, i) == -1)
19225 		return(-1);
19226 	    i--;
19227 	    /*
19228 	    * Note that duplicate prohibitions were already
19229 	    * handled at parsing time.
19230 	    */
19231 	    /*
19232 	    * Add to list of prohibitions.
19233 	    */
19234 	    xmlSchemaItemListAddSize(prohibs, 2, use);
19235 	    continue;
19236 	}
19237 	if ((use->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
19238 	    ((WXS_QNAME_CAST use)->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP))
19239 	{
19240 	    if ((WXS_QNAME_CAST use)->item == NULL)
19241 		return(-1);
19242 	    gr = WXS_ATTR_GROUP_CAST (WXS_QNAME_CAST use)->item;
19243 	    /*
19244 	    * Expand the referenced attr. group.
19245 	    * TODO: remove this, this is done in a previous step, so
19246 	    * already done here.
19247 	    */
19248 	    if ((gr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
19249 		if (xmlSchemaAttributeGroupExpandRefs(pctxt, gr) == -1)
19250 		    return(-1);
19251 	    }
19252 	    /*
19253 	    * Build the 'complete' wildcard; i.e. intersect multiple
19254 	    * wildcards.
19255 	    */
19256 	    if (gr->attributeWildcard != NULL) {
19257 		if (*completeWild == NULL) {
19258 		    *completeWild = gr->attributeWildcard;
19259 		} else {
19260 		    if (! created) {
19261 			xmlSchemaWildcardPtr tmpWild;
19262 
19263 			 /*
19264 			* Copy the first encountered wildcard as context,
19265 			* except for the annotation.
19266 			*
19267 			* Although the complete wildcard might not correspond
19268 			* to any node in the schema, we will anchor it on
19269 			* the node of the owner component.
19270 			*/
19271 			tmpWild =  xmlSchemaAddWildcard(pctxt, pctxt->schema,
19272 			    XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
19273 			    WXS_ITEM_NODE(item));
19274 			if (tmpWild == NULL)
19275 			    return(-1);
19276 			if (xmlSchemaCloneWildcardNsConstraints(pctxt,
19277 			    tmpWild, *completeWild) == -1)
19278 			    return (-1);
19279 			tmpWild->processContents = (*completeWild)->processContents;
19280 			*completeWild = tmpWild;
19281 			created = 1;
19282 		    }
19283 
19284 		    if (xmlSchemaIntersectWildcards(pctxt, *completeWild,
19285 			gr->attributeWildcard) == -1)
19286 			return(-1);
19287 		}
19288 	    }
19289 	    /*
19290 	    * Just remove the reference if the referenced group does not
19291 	    * contain any attribute uses.
19292 	    */
19293 	    sublist = ((xmlSchemaItemListPtr) gr->attrUses);
19294 	    if ((sublist == NULL) || sublist->nbItems == 0) {
19295 		if (xmlSchemaItemListRemove(list, i) == -1)
19296 		    return(-1);
19297 		i--;
19298 		continue;
19299 	    }
19300 	    /*
19301 	    * Add the attribute uses.
19302 	    */
19303 	    list->items[i] = sublist->items[0];
19304 	    if (sublist->nbItems != 1) {
19305 		for (j = 1; j < sublist->nbItems; j++) {
19306 		    i++;
19307 		    if (xmlSchemaItemListInsert(list,
19308 			    sublist->items[j], i) == -1)
19309 			return(-1);
19310 		}
19311 	    }
19312 	}
19313 
19314     }
19315     /*
19316     * Handle pointless prohibitions of declared attributes.
19317     */
19318     if (prohibs && (prohibs->nbItems != 0) && (list->nbItems != 0)) {
19319 	xmlSchemaAttributeUseProhibPtr prohib;
19320 
19321 	for (i = prohibs->nbItems -1; i >= 0; i--) {
19322 	    prohib = prohibs->items[i];
19323 	    for (j = 0; j < list->nbItems; j++) {
19324 		use = list->items[j];
19325 
19326 		if ((prohib->name == WXS_ATTRUSE_DECL_NAME(use)) &&
19327 		    (prohib->targetNamespace == WXS_ATTRUSE_DECL_TNS(use)))
19328 		{
19329 		    xmlChar *str = NULL;
19330 
19331 		    xmlSchemaCustomWarning(ACTXT_CAST pctxt,
19332 			XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
19333 			prohib->node, NULL,
19334 			"Skipping pointless attribute use prohibition "
19335 			"'%s', since a corresponding attribute use "
19336 			"exists already in the type definition",
19337 			xmlSchemaFormatQName(&str,
19338 			    prohib->targetNamespace, prohib->name),
19339 			NULL, NULL);
19340 		    FREE_AND_NULL(str);
19341 		    /*
19342 		    * Remove the prohibition.
19343 		    */
19344 		    if (xmlSchemaItemListRemove(prohibs, i) == -1)
19345 			return(-1);
19346 		    break;
19347 		}
19348 	    }
19349 	}
19350     }
19351     return(0);
19352 }
19353 
19354 /**
19355  * xmlSchemaAttributeGroupExpandRefs:
19356  * @pctxt:  the parser context
19357  * @attrGr:  the attribute group definition
19358  *
19359  * Computation of:
19360  * {attribute uses} property
19361  * {attribute wildcard} property
19362  *
19363  * Substitutes contained attribute group references
19364  * for their attribute uses. Wilcards are intersected.
19365  */
19366 static int
xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,xmlSchemaAttributeGroupPtr attrGr)19367 xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19368 				  xmlSchemaAttributeGroupPtr attrGr)
19369 {
19370     if ((attrGr->attrUses == NULL) ||
19371 	(attrGr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED))
19372 	return(0);
19373 
19374     attrGr->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
19375     if (xmlSchemaExpandAttributeGroupRefs(pctxt, WXS_BASIC_CAST attrGr,
19376 	&(attrGr->attributeWildcard), attrGr->attrUses, NULL) == -1)
19377 	return(-1);
19378     return(0);
19379 }
19380 
19381 /**
19382  * xmlSchemaAttributeGroupExpandRefs:
19383  * @pctxt:  the parser context
19384  * @attrGr:  the attribute group definition
19385  *
19386  * Substitutes contained attribute group references
19387  * for their attribute uses. Wilcards are intersected.
19388  *
19389  * Schema Component Constraint:
19390  *    Attribute Group Definition Properties Correct (ag-props-correct)
19391  */
19392 static int
xmlSchemaCheckAGPropsCorrect(xmlSchemaParserCtxtPtr pctxt,xmlSchemaAttributeGroupPtr attrGr)19393 xmlSchemaCheckAGPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19394 				  xmlSchemaAttributeGroupPtr attrGr)
19395 {
19396     /*
19397     * SPEC ag-props-correct
19398     * (1) "The values of the properties of an attribute group definition
19399     * must be as described in the property tableau in The Attribute
19400     * Group Definition Schema Component ($3.6.1), modulo the impact of
19401     * Missing Sub-components ($5.3);"
19402     */
19403 
19404     if ((attrGr->attrUses != NULL) &&
19405 	(WXS_LIST_CAST attrGr->attrUses)->nbItems > 1)
19406     {
19407 	xmlSchemaItemListPtr uses = WXS_LIST_CAST attrGr->attrUses;
19408 	xmlSchemaAttributeUsePtr use, tmp;
19409 	int i, j, hasId = 0;
19410 
19411 	for (i = uses->nbItems -1; i >= 0; i--) {
19412 	    use = uses->items[i];
19413 	    /*
19414 	    * SPEC ag-props-correct
19415 	    * (2) "Two distinct members of the {attribute uses} must not have
19416 	    * {attribute declaration}s both of whose {name}s match and whose
19417 	    * {target namespace}s are identical."
19418 	    */
19419 	    if (i > 0) {
19420 		for (j = i -1; j >= 0; j--) {
19421 		    tmp = uses->items[j];
19422 		    if ((WXS_ATTRUSE_DECL_NAME(use) ==
19423 			WXS_ATTRUSE_DECL_NAME(tmp)) &&
19424 			(WXS_ATTRUSE_DECL_TNS(use) ==
19425 			WXS_ATTRUSE_DECL_TNS(tmp)))
19426 		    {
19427 			xmlChar *str = NULL;
19428 
19429 			xmlSchemaCustomErr(ACTXT_CAST pctxt,
19430 			    XML_SCHEMAP_AG_PROPS_CORRECT,
19431 			    attrGr->node, WXS_BASIC_CAST attrGr,
19432 			    "Duplicate %s",
19433 			    xmlSchemaGetComponentDesignation(&str, use),
19434 			    NULL);
19435 			FREE_AND_NULL(str);
19436 			/*
19437 			* Remove the duplicate.
19438 			*/
19439 			if (xmlSchemaItemListRemove(uses, i) == -1)
19440 			    return(-1);
19441 			goto next_use;
19442 		    }
19443 		}
19444 	    }
19445 	    /*
19446 	    * SPEC ag-props-correct
19447 	    * (3) "Two distinct members of the {attribute uses} must not have
19448 	    * {attribute declaration}s both of whose {type definition}s are or
19449 	    * are derived from ID."
19450 	    * TODO: Does 'derived' include member-types of unions?
19451 	    */
19452 	    if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
19453 		if (xmlSchemaIsDerivedFromBuiltInType(
19454 		    WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
19455 		{
19456 		    if (hasId) {
19457 			xmlChar *str = NULL;
19458 
19459 			xmlSchemaCustomErr(ACTXT_CAST pctxt,
19460 			    XML_SCHEMAP_AG_PROPS_CORRECT,
19461 			    attrGr->node, WXS_BASIC_CAST attrGr,
19462 			    "There must not exist more than one attribute "
19463 			    "declaration of type 'xs:ID' "
19464 			    "(or derived from 'xs:ID'). The %s violates this "
19465 			    "constraint",
19466 			    xmlSchemaGetComponentDesignation(&str, use),
19467 			    NULL);
19468 			FREE_AND_NULL(str);
19469 			if (xmlSchemaItemListRemove(uses, i) == -1)
19470 			    return(-1);
19471 		    }
19472 		    hasId = 1;
19473 		}
19474 	    }
19475 next_use: {}
19476 	}
19477     }
19478     return(0);
19479 }
19480 
19481 /**
19482  * xmlSchemaResolveAttrGroupReferences:
19483  * @attrgrpDecl:  the schema attribute definition
19484  * @ctxt:  the schema parser context
19485  * @name:  the attribute name
19486  *
19487  * Resolves references to attribute group definitions.
19488  */
19489 static int
xmlSchemaResolveAttrGroupReferences(xmlSchemaQNameRefPtr ref,xmlSchemaParserCtxtPtr ctxt)19490 xmlSchemaResolveAttrGroupReferences(xmlSchemaQNameRefPtr ref,
19491 				    xmlSchemaParserCtxtPtr ctxt)
19492 {
19493     xmlSchemaAttributeGroupPtr group;
19494 
19495     if (ref->item != NULL)
19496         return(0);
19497     group = xmlSchemaGetAttributeGroup(ctxt->schema,
19498 	ref->name,
19499 	ref->targetNamespace);
19500     if (group == NULL) {
19501 	xmlSchemaPResCompAttrErr(ctxt,
19502 	    XML_SCHEMAP_SRC_RESOLVE,
19503 	    NULL, ref->node,
19504 	    "ref", ref->name, ref->targetNamespace,
19505 	    ref->itemType, NULL);
19506 	return(ctxt->err);
19507     }
19508     ref->item = WXS_BASIC_CAST group;
19509     return(0);
19510 }
19511 
19512 /**
19513  * xmlSchemaCheckAttrPropsCorrect:
19514  * @item:  an schema attribute declaration/use
19515  * @ctxt:  a schema parser context
19516  * @name:  the name of the attribute
19517  *
19518  *
19519  * Schema Component Constraint:
19520  *    Attribute Declaration Properties Correct (a-props-correct)
19521  *
19522  * Validates the value constraints of an attribute declaration/use.
19523  * NOTE that this needs the simle type definitions to be already
19524  *   builded and checked.
19525  */
19526 static int
xmlSchemaCheckAttrPropsCorrect(xmlSchemaParserCtxtPtr pctxt,xmlSchemaAttributePtr attr)19527 xmlSchemaCheckAttrPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19528 			       xmlSchemaAttributePtr attr)
19529 {
19530 
19531     /*
19532     * SPEC a-props-correct (1)
19533     * "The values of the properties of an attribute declaration must
19534     * be as described in the property tableau in The Attribute
19535     * Declaration Schema Component ($3.2.1), modulo the impact of
19536     * Missing Sub-components ($5.3)."
19537     */
19538 
19539     if (WXS_ATTR_TYPEDEF(attr) == NULL)
19540 	return(0);
19541 
19542     if (attr->defValue != NULL) {
19543 	int ret;
19544 
19545 	/*
19546 	* SPEC a-props-correct (3)
19547 	* "If the {type definition} is or is derived from ID then there
19548 	* must not be a {value constraint}."
19549 	*/
19550 	if (xmlSchemaIsDerivedFromBuiltInType(
19551 	    WXS_ATTR_TYPEDEF(attr), XML_SCHEMAS_ID))
19552 	{
19553 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
19554 		XML_SCHEMAP_A_PROPS_CORRECT_3,
19555 		NULL, WXS_BASIC_CAST attr,
19556 		"Value constraints are not allowed if the type definition "
19557 		"is or is derived from xs:ID",
19558 		NULL, NULL);
19559 	    return(pctxt->err);
19560 	}
19561 	/*
19562 	* SPEC a-props-correct (2)
19563 	* "if there is a {value constraint}, the canonical lexical
19564 	* representation of its value must be `valid` with respect
19565 	* to the {type definition} as defined in String Valid ($3.14.4)."
19566 	* TODO: Don't care about the *canonical* stuff here, this requirement
19567 	* will be removed in WXS 1.1 anyway.
19568 	*/
19569 	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt,
19570 	    attr->node, WXS_ATTR_TYPEDEF(attr),
19571 	    attr->defValue, &(attr->defVal),
19572 	    1, 1, 0);
19573 	if (ret != 0) {
19574 	    if (ret < 0) {
19575 		PERROR_INT("xmlSchemaCheckAttrPropsCorrect",
19576 		    "calling xmlSchemaVCheckCVCSimpleType()");
19577 		return(-1);
19578 	    }
19579 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
19580 		XML_SCHEMAP_A_PROPS_CORRECT_2,
19581 		NULL, WXS_BASIC_CAST attr,
19582 		"The value of the value constraint is not valid",
19583 		NULL, NULL);
19584 	    return(pctxt->err);
19585 	}
19586     }
19587 
19588     return(0);
19589 }
19590 
19591 static xmlSchemaElementPtr
xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,xmlSchemaElementPtr ancestor)19592 xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,
19593 				 xmlSchemaElementPtr ancestor)
19594 {
19595     xmlSchemaElementPtr ret;
19596 
19597     if (WXS_SUBST_HEAD(ancestor) == NULL)
19598 	return (NULL);
19599     if (WXS_SUBST_HEAD(ancestor) == elemDecl)
19600 	return (ancestor);
19601 
19602     if (WXS_SUBST_HEAD(ancestor)->flags & XML_SCHEMAS_ELEM_CIRCULAR)
19603 	return (NULL);
19604     WXS_SUBST_HEAD(ancestor)->flags |= XML_SCHEMAS_ELEM_CIRCULAR;
19605     ret = xmlSchemaCheckSubstGroupCircular(elemDecl,
19606 	WXS_SUBST_HEAD(ancestor));
19607     WXS_SUBST_HEAD(ancestor)->flags ^= XML_SCHEMAS_ELEM_CIRCULAR;
19608 
19609     return (ret);
19610 }
19611 
19612 /**
19613  * xmlSchemaCheckElemPropsCorrect:
19614  * @ctxt:  a schema parser context
19615  * @decl: the element declaration
19616  * @name:  the name of the attribute
19617  *
19618  * Schema Component Constraint:
19619  * Element Declaration Properties Correct (e-props-correct)
19620  *
19621  * STATUS:
19622  *   missing: (6)
19623  */
19624 static int
xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,xmlSchemaElementPtr elemDecl)19625 xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19626 			       xmlSchemaElementPtr elemDecl)
19627 {
19628     int ret = 0;
19629     xmlSchemaTypePtr typeDef = WXS_ELEM_TYPEDEF(elemDecl);
19630     /*
19631     * SPEC (1) "The values of the properties of an element declaration
19632     * must be as described in the property tableau in The Element
19633     * Declaration Schema Component ($3.3.1), modulo the impact of Missing
19634     * Sub-components ($5.3)."
19635     */
19636     if (WXS_SUBST_HEAD(elemDecl) != NULL) {
19637 	xmlSchemaElementPtr head = WXS_SUBST_HEAD(elemDecl), circ;
19638 
19639 	xmlSchemaCheckElementDeclComponent(head, pctxt);
19640 	/*
19641 	* SPEC (3) "If there is a non-`absent` {substitution group
19642 	* affiliation}, then {scope} must be global."
19643 	*/
19644 	if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
19645 	    xmlSchemaPCustomErr(pctxt,
19646 		XML_SCHEMAP_E_PROPS_CORRECT_3,
19647 		WXS_BASIC_CAST elemDecl, NULL,
19648 		"Only global element declarations can have a "
19649 		"substitution group affiliation", NULL);
19650 	    ret = XML_SCHEMAP_E_PROPS_CORRECT_3;
19651 	}
19652 	/*
19653 	* TODO: SPEC (6) "Circular substitution groups are disallowed.
19654 	* That is, it must not be possible to return to an element declaration
19655 	* by repeatedly following the {substitution group affiliation}
19656 	* property."
19657 	*/
19658 	if (head == elemDecl)
19659 	    circ = head;
19660 	else if (WXS_SUBST_HEAD(head) != NULL)
19661 	    circ = xmlSchemaCheckSubstGroupCircular(head, head);
19662 	else
19663 	    circ = NULL;
19664 	if (circ != NULL) {
19665 	    xmlChar *strA = NULL, *strB = NULL;
19666 
19667 	    xmlSchemaPCustomErrExt(pctxt,
19668 		XML_SCHEMAP_E_PROPS_CORRECT_6,
19669 		WXS_BASIC_CAST circ, NULL,
19670 		"The element declaration '%s' defines a circular "
19671 		"substitution group to element declaration '%s'",
19672 		xmlSchemaGetComponentQName(&strA, circ),
19673 		xmlSchemaGetComponentQName(&strB, head),
19674 		NULL);
19675 	    FREE_AND_NULL(strA)
19676 	    FREE_AND_NULL(strB)
19677 	    ret = XML_SCHEMAP_E_PROPS_CORRECT_6;
19678 	}
19679 	/*
19680 	* SPEC (4) "If there is a {substitution group affiliation},
19681 	* the {type definition}
19682 	* of the element declaration must be validly derived from the {type
19683 	* definition} of the {substitution group affiliation}, given the value
19684 	* of the {substitution group exclusions} of the {substitution group
19685 	* affiliation}, as defined in Type Derivation OK (Complex) ($3.4.6)
19686 	* (if the {type definition} is complex) or as defined in
19687 	* Type Derivation OK (Simple) ($3.14.6) (if the {type definition} is
19688 	* simple)."
19689 	*
19690 	* NOTE: {substitution group exclusions} means the values of the
19691 	* attribute "final".
19692 	*/
19693 
19694 	if (typeDef != WXS_ELEM_TYPEDEF(WXS_SUBST_HEAD(elemDecl))) {
19695 	    int set = 0;
19696 
19697 	    if (head->flags & XML_SCHEMAS_ELEM_FINAL_EXTENSION)
19698 		set |= SUBSET_EXTENSION;
19699 	    if (head->flags & XML_SCHEMAS_ELEM_FINAL_RESTRICTION)
19700 		set |= SUBSET_RESTRICTION;
19701 
19702 	    if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST pctxt, typeDef,
19703 		WXS_ELEM_TYPEDEF(head), set) != 0) {
19704 		xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
19705 
19706 		ret = XML_SCHEMAP_E_PROPS_CORRECT_4;
19707 		xmlSchemaPCustomErrExt(pctxt,
19708 		    XML_SCHEMAP_E_PROPS_CORRECT_4,
19709 		    WXS_BASIC_CAST elemDecl, NULL,
19710 		    "The type definition '%s' was "
19711 		    "either rejected by the substitution group "
19712 		    "affiliation '%s', or not validly derived from its type "
19713 		    "definition '%s'",
19714 		    xmlSchemaGetComponentQName(&strA, typeDef),
19715 		    xmlSchemaGetComponentQName(&strB, head),
19716 		    xmlSchemaGetComponentQName(&strC, WXS_ELEM_TYPEDEF(head)));
19717 		FREE_AND_NULL(strA)
19718 		FREE_AND_NULL(strB)
19719 		FREE_AND_NULL(strC)
19720 	    }
19721 	}
19722     }
19723     /*
19724     * SPEC (5) "If the {type definition} or {type definition}'s
19725     * {content type}
19726     * is or is derived from ID then there must not be a {value constraint}.
19727     * Note: The use of ID as a type definition for elements goes beyond
19728     * XML 1.0, and should be avoided if backwards compatibility is desired"
19729     */
19730     if ((elemDecl->value != NULL) &&
19731 	((WXS_IS_SIMPLE(typeDef) &&
19732 	  xmlSchemaIsDerivedFromBuiltInType(typeDef, XML_SCHEMAS_ID)) ||
19733 	 (WXS_IS_COMPLEX(typeDef) &&
19734 	  WXS_HAS_SIMPLE_CONTENT(typeDef) &&
19735 	  xmlSchemaIsDerivedFromBuiltInType(typeDef->contentTypeDef,
19736 	    XML_SCHEMAS_ID)))) {
19737 
19738 	ret = XML_SCHEMAP_E_PROPS_CORRECT_5;
19739 	xmlSchemaPCustomErr(pctxt,
19740 	    XML_SCHEMAP_E_PROPS_CORRECT_5,
19741 	    WXS_BASIC_CAST elemDecl, NULL,
19742 	    "The type definition (or type definition's content type) is or "
19743 	    "is derived from ID; value constraints are not allowed in "
19744 	    "conjunction with such a type definition", NULL);
19745     } else if (elemDecl->value != NULL) {
19746 	int vcret;
19747 	xmlNodePtr node = NULL;
19748 
19749 	/*
19750 	* SPEC (2) "If there is a {value constraint}, the canonical lexical
19751 	* representation of its value must be `valid` with respect to the
19752 	* {type definition} as defined in Element Default Valid (Immediate)
19753 	* ($3.3.6)."
19754 	*/
19755 	if (typeDef == NULL) {
19756 	    xmlSchemaPErr(pctxt, elemDecl->node,
19757 		XML_SCHEMAP_INTERNAL,
19758 		"Internal error: xmlSchemaCheckElemPropsCorrect, "
19759 		"type is missing... skipping validation of "
19760 		"the value constraint", NULL, NULL);
19761 	    return (-1);
19762 	}
19763 	if (elemDecl->node != NULL) {
19764 	    if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
19765 		node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19766 		    BAD_CAST "fixed");
19767 	    else
19768 		node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19769 		    BAD_CAST "default");
19770 	}
19771 	vcret = xmlSchemaParseCheckCOSValidDefault(pctxt, node,
19772 	    typeDef, elemDecl->value, &(elemDecl->defVal));
19773 	if (vcret != 0) {
19774 	    if (vcret < 0) {
19775 		PERROR_INT("xmlSchemaElemCheckValConstr",
19776 		    "failed to validate the value constraint of an "
19777 		    "element declaration");
19778 		return (-1);
19779 	    }
19780 	    return (vcret);
19781 	}
19782     }
19783 
19784     return (ret);
19785 }
19786 
19787 /**
19788  * xmlSchemaCheckElemSubstGroup:
19789  * @ctxt:  a schema parser context
19790  * @decl: the element declaration
19791  * @name:  the name of the attribute
19792  *
19793  * Schema Component Constraint:
19794  * Substitution Group (cos-equiv-class)
19795  *
19796  * In Libxml2 the subst. groups will be precomputed, in terms of that
19797  * a list will be built for each subst. group head, holding all direct
19798  * referents to this head.
19799  * NOTE that this function needs:
19800  *   1. circular subst. groups to be checked beforehand
19801  *   2. the declaration's type to be derived from the head's type
19802  *
19803  * STATUS:
19804  *
19805  */
19806 static void
xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,xmlSchemaElementPtr elemDecl)19807 xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,
19808 			     xmlSchemaElementPtr elemDecl)
19809 {
19810     if ((WXS_SUBST_HEAD(elemDecl) == NULL) ||
19811 	/* SPEC (1) "Its {abstract} is false." */
19812 	(elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT))
19813 	return;
19814     {
19815 	xmlSchemaElementPtr head;
19816 	xmlSchemaTypePtr headType, type;
19817 	int set, methSet;
19818 	/*
19819 	* SPEC (2) "It is validly substitutable for HEAD subject to HEAD's
19820 	* {disallowed substitutions} as the blocking constraint, as defined in
19821 	* Substitution Group OK (Transitive) ($3.3.6)."
19822 	*/
19823 	for (head = WXS_SUBST_HEAD(elemDecl); head != NULL;
19824 	    head = WXS_SUBST_HEAD(head)) {
19825 	    set = 0;
19826 	    methSet = 0;
19827 	    /*
19828 	    * The blocking constraints.
19829 	    */
19830 	    if (head->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION)
19831 		continue;
19832 	    headType = head->subtypes;
19833 	    type = elemDecl->subtypes;
19834 	    if (headType == type)
19835 		goto add_member;
19836 	    if (head->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION)
19837 		set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19838 	    if (head->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION)
19839 		set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19840 	    /*
19841 	    * SPEC: Substitution Group OK (Transitive) (2.3)
19842 	    * "The set of all {derivation method}s involved in the
19843 	    * derivation of D's {type definition} from C's {type definition}
19844 	    * does not intersect with the union of the blocking constraint,
19845 	    * C's {prohibited substitutions} (if C is complex, otherwise the
19846 	    * empty set) and the {prohibited substitutions} (respectively the
19847 	    * empty set) of any intermediate {type definition}s in the
19848 	    * derivation of D's {type definition} from C's {type definition}."
19849 	    */
19850 	    /*
19851 	    * OPTIMIZE TODO: Optimize this a bit, since, if traversing the
19852 	    * subst.head axis, the methSet does not need to be computed for
19853 	    * the full depth over and over.
19854 	    */
19855 	    /*
19856 	    * The set of all {derivation method}s involved in the derivation
19857 	    */
19858 	    while ((type != NULL) && (type != headType)) {
19859 		if ((WXS_IS_EXTENSION(type)) &&
19860 		    ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19861 		    methSet |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19862 
19863 		if (WXS_IS_RESTRICTION(type) &&
19864 		    ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19865 		    methSet |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19866 
19867 		type = type->baseType;
19868 	    }
19869 	    /*
19870 	    * The {prohibited substitutions} of all intermediate types +
19871 	    * the head's type.
19872 	    */
19873 	    type = elemDecl->subtypes->baseType;
19874 	    while (type != NULL) {
19875 		if (WXS_IS_COMPLEX(type)) {
19876 		    if ((type->flags &
19877 			    XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19878 			((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) == 0))
19879 		    set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19880 		    if ((type->flags &
19881 			    XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19882 			((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19883 		    set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19884 		} else
19885 		    break;
19886 		if (type == headType)
19887 		    break;
19888 		type = type->baseType;
19889 	    }
19890 	    if ((set != 0) &&
19891 		(((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19892 		(methSet & XML_SCHEMAS_TYPE_BLOCK_EXTENSION)) ||
19893 		((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19894 		(methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION)))) {
19895 		continue;
19896 	    }
19897 add_member:
19898 	    xmlSchemaAddElementSubstitutionMember(ctxt, head, elemDecl);
19899 	    if ((head->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) == 0)
19900 		head->flags |= XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD;
19901 	}
19902     }
19903 }
19904 
19905 #ifdef WXS_ELEM_DECL_CONS_ENABLED /* enable when finished */
19906 /**
19907  * xmlSchemaCheckElementDeclComponent
19908  * @pctxt: the schema parser context
19909  * @ctxtComponent: the context component (an element declaration)
19910  * @ctxtParticle: the first particle of the context component
19911  * @searchParticle: the element declaration particle to be analysed
19912  *
19913  * Schema Component Constraint: Element Declarations Consistent
19914  */
19915 static int
xmlSchemaCheckElementDeclConsistent(xmlSchemaParserCtxtPtr pctxt,xmlSchemaBasicItemPtr ctxtComponent,xmlSchemaParticlePtr ctxtParticle,xmlSchemaParticlePtr searchParticle,xmlSchemaParticlePtr curParticle,int search)19916 xmlSchemaCheckElementDeclConsistent(xmlSchemaParserCtxtPtr pctxt,
19917 				    xmlSchemaBasicItemPtr ctxtComponent,
19918 				    xmlSchemaParticlePtr ctxtParticle,
19919 				    xmlSchemaParticlePtr searchParticle,
19920 				    xmlSchemaParticlePtr curParticle,
19921 				    int search)
19922 {
19923     return(0);
19924 
19925     int ret = 0;
19926     xmlSchemaParticlePtr cur = curParticle;
19927     if (curParticle == NULL) {
19928 	return(0);
19929     }
19930     if (WXS_PARTICLE_TERM(curParticle) == NULL) {
19931 	/*
19932 	* Just return in this case. A missing "term" of the particle
19933 	* might arise due to an invalid "term" component.
19934 	*/
19935 	return(0);
19936     }
19937     while (cur != NULL) {
19938 	switch (WXS_PARTICLE_TERM(cur)->type) {
19939 	    case XML_SCHEMA_TYPE_ANY:
19940 		break;
19941 	    case XML_SCHEMA_TYPE_ELEMENT:
19942 		if (search == 0) {
19943 		    ret = xmlSchemaCheckElementDeclConsistent(pctxt,
19944 			ctxtComponent, ctxtParticle, cur, ctxtParticle, 1);
19945 		    if (ret != 0)
19946 			return(ret);
19947 		} else {
19948 		    xmlSchemaElementPtr elem =
19949 			WXS_ELEM_CAST(WXS_PARTICLE_TERM(cur));
19950 		    /*
19951 		    * SPEC Element Declarations Consistent:
19952 		    * "If the {particles} contains, either directly,
19953 		    * indirectly (that is, within the {particles} of a
19954 		    * contained model group, recursively) or `implicitly`
19955 		    * two or more element declaration particles with
19956 		    * the same {name} and {target namespace}, then
19957 		    * all their type definitions must be the same
19958 		    * top-level definition [...]"
19959 		    */
19960 		    if (xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->name,
19961 			    WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->name) &&
19962 			xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamespace,
19963 			    WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->targetNamespace))
19964 		    {
19965 			xmlChar *strA = NULL, *strB = NULL;
19966 
19967 			xmlSchemaCustomErr(ACTXT_CAST pctxt,
19968 			    /* TODO: error code */
19969 			    XML_SCHEMAP_COS_NONAMBIG,
19970 			    WXS_ITEM_NODE(cur), NULL,
19971 			    "In the content model of %s, there are multiple "
19972 			    "element declarations for '%s' with different "
19973 			    "type definitions",
19974 			    xmlSchemaGetComponentDesignation(&strA,
19975 				ctxtComponent),
19976 			    xmlSchemaFormatQName(&strB,
19977 				WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamespace,
19978 				WXS_PARTICLE_TERM_AS_ELEM(cur)->name));
19979 			FREE_AND_NULL(strA);
19980 			FREE_AND_NULL(strB);
19981 			return(XML_SCHEMAP_COS_NONAMBIG);
19982 		    }
19983 		}
19984 		break;
19985 	    case XML_SCHEMA_TYPE_SEQUENCE: {
19986 		break;
19987 		}
19988 	    case XML_SCHEMA_TYPE_CHOICE:{
19989 		/*
19990 		xmlSchemaTreeItemPtr sub;
19991 
19992 		sub = WXS_PARTICLE_TERM(particle)->children;  (xmlSchemaParticlePtr)
19993 		while (sub != NULL) {
19994 		    ret = xmlSchemaCheckElementDeclConsistent(pctxt, ctxtComponent,
19995 			ctxtParticle, ctxtElem);
19996 		    if (ret != 0)
19997 			return(ret);
19998 		    sub = sub->next;
19999 		}
20000 		*/
20001 		break;
20002 		}
20003 	    case XML_SCHEMA_TYPE_ALL:
20004 		break;
20005 	    case XML_SCHEMA_TYPE_GROUP:
20006 		break;
20007 	    default:
20008 		xmlSchemaInternalErr2(ACTXT_CAST pctxt,
20009 		    "xmlSchemaCheckElementDeclConsistent",
20010 		    "found unexpected term of type '%s' in content model",
20011 		    WXS_ITEM_TYPE_NAME(WXS_PARTICLE_TERM(cur)), NULL);
20012 		return(-1);
20013 	}
20014 	cur = (xmlSchemaParticlePtr) cur->next;
20015     }
20016 
20017 exit:
20018     return(ret);
20019 }
20020 #endif
20021 
20022 /**
20023  * xmlSchemaCheckElementDeclComponent
20024  * @item:  an schema element declaration/particle
20025  * @ctxt:  a schema parser context
20026  * @name:  the name of the attribute
20027  *
20028  * Validates the value constraints of an element declaration.
20029  * Adds substitution group members.
20030  */
20031 static void
xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,xmlSchemaParserCtxtPtr ctxt)20032 xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
20033 				   xmlSchemaParserCtxtPtr ctxt)
20034 {
20035     if (elemDecl == NULL)
20036 	return;
20037     if (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED)
20038 	return;
20039     elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_CHECKED;
20040     if (xmlSchemaCheckElemPropsCorrect(ctxt, elemDecl) == 0) {
20041 	/*
20042 	* Adds substitution group members.
20043 	*/
20044 	xmlSchemaCheckElemSubstGroup(ctxt, elemDecl);
20045     }
20046 }
20047 
20048 /**
20049  * xmlSchemaResolveModelGroupParticleReferences:
20050  * @particle:  a particle component
20051  * @ctxt:  a parser context
20052  *
20053  * Resolves references of a model group's {particles} to
20054  * model group definitions and to element declarations.
20055  */
20056 static void
xmlSchemaResolveModelGroupParticleReferences(xmlSchemaParserCtxtPtr ctxt,xmlSchemaModelGroupPtr mg)20057 xmlSchemaResolveModelGroupParticleReferences(
20058     xmlSchemaParserCtxtPtr ctxt,
20059     xmlSchemaModelGroupPtr mg)
20060 {
20061     xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
20062     xmlSchemaQNameRefPtr ref;
20063     xmlSchemaBasicItemPtr refItem;
20064 
20065     /*
20066     * URGENT TODO: Test this.
20067     */
20068     while (particle != NULL) {
20069 	if ((WXS_PARTICLE_TERM(particle) == NULL) ||
20070 	    ((WXS_PARTICLE_TERM(particle))->type !=
20071 		XML_SCHEMA_EXTRA_QNAMEREF))
20072 	{
20073 	    goto next_particle;
20074 	}
20075 	ref = WXS_QNAME_CAST WXS_PARTICLE_TERM(particle);
20076 	/*
20077 	* Resolve the reference.
20078 	* NULL the {term} by default.
20079 	*/
20080 	particle->children = NULL;
20081 
20082 	refItem = xmlSchemaGetNamedComponent(ctxt->schema,
20083 	    ref->itemType, ref->name, ref->targetNamespace);
20084 	if (refItem == NULL) {
20085 	    xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
20086 		NULL, WXS_ITEM_NODE(particle), "ref", ref->name,
20087 		ref->targetNamespace, ref->itemType, NULL);
20088 	    /* TODO: remove the particle. */
20089 	    goto next_particle;
20090 	}
20091 	if (refItem->type == XML_SCHEMA_TYPE_GROUP) {
20092 	    if (WXS_MODELGROUPDEF_MODEL(refItem) == NULL)
20093 		/* TODO: remove the particle. */
20094 		goto next_particle;
20095 	    /*
20096 	    * NOTE that we will assign the model group definition
20097 	    * itself to the "term" of the particle. This will ease
20098 	    * the check for circular model group definitions. After
20099 	    * that the "term" will be assigned the model group of the
20100 	    * model group definition.
20101 	    */
20102 	    if ((WXS_MODELGROUPDEF_MODEL(refItem))->type ==
20103 		    XML_SCHEMA_TYPE_ALL) {
20104 		/*
20105 		* SPEC cos-all-limited (1)
20106 		* SPEC cos-all-limited (1.2)
20107 		* "It appears only as the value of one or both of the
20108 		* following properties:"
20109 		* (1.1) "the {model group} property of a model group
20110 		*        definition."
20111 		* (1.2) "the {term} property of a particle [... of] the "
20112 		* {content type} of a complex type definition."
20113 		*/
20114 		xmlSchemaCustomErr(ACTXT_CAST ctxt,
20115 		    /* TODO: error code */
20116 		    XML_SCHEMAP_COS_ALL_LIMITED,
20117 		    WXS_ITEM_NODE(particle), NULL,
20118 		    "A model group definition is referenced, but "
20119 		    "it contains an 'all' model group, which "
20120 		    "cannot be contained by model groups",
20121 		    NULL, NULL);
20122 		/* TODO: remove the particle. */
20123 		goto next_particle;
20124 	    }
20125 	    particle->children = (xmlSchemaTreeItemPtr) refItem;
20126 	} else {
20127 	    /*
20128 	    * TODO: Are referenced element declarations the only
20129 	    * other components we expect here?
20130 	    */
20131 	    particle->children = (xmlSchemaTreeItemPtr) refItem;
20132 	}
20133 next_particle:
20134 	particle = WXS_PTC_CAST particle->next;
20135     }
20136 }
20137 
20138 static int
xmlSchemaAreValuesEqual(xmlSchemaValPtr x,xmlSchemaValPtr y)20139 xmlSchemaAreValuesEqual(xmlSchemaValPtr x,
20140 		       xmlSchemaValPtr y)
20141 {
20142     xmlSchemaTypePtr tx, ty, ptx, pty;
20143     int ret;
20144 
20145     while (x != NULL) {
20146 	/* Same types. */
20147 	tx = xmlSchemaGetBuiltInType(xmlSchemaGetValType(x));
20148 	ty = xmlSchemaGetBuiltInType(xmlSchemaGetValType(y));
20149 	ptx = xmlSchemaGetPrimitiveType(tx);
20150 	pty = xmlSchemaGetPrimitiveType(ty);
20151 	/*
20152 	* (1) if a datatype T' is `derived` by `restriction` from an
20153 	* atomic datatype T then the `value space` of T' is a subset of
20154 	* the `value space` of T. */
20155 	/*
20156 	* (2) if datatypes T' and T'' are `derived` by `restriction`
20157 	* from a common atomic ancestor T then the `value space`s of T'
20158 	* and T'' may overlap.
20159 	*/
20160 	if (ptx != pty)
20161 	    return(0);
20162 	/*
20163 	* We assume computed values to be normalized, so do a fast
20164 	* string comparison for string based types.
20165 	*/
20166 	if ((ptx->builtInType == XML_SCHEMAS_STRING) ||
20167 	    WXS_IS_ANY_SIMPLE_TYPE(ptx)) {
20168 	    if (! xmlStrEqual(
20169 		xmlSchemaValueGetAsString(x),
20170 		xmlSchemaValueGetAsString(y)))
20171 		return (0);
20172 	} else {
20173 	    ret = xmlSchemaCompareValuesWhtsp(
20174 		x, XML_SCHEMA_WHITESPACE_PRESERVE,
20175 		y, XML_SCHEMA_WHITESPACE_PRESERVE);
20176 	    if (ret == -2)
20177 		return(-1);
20178 	    if (ret != 0)
20179 		return(0);
20180 	}
20181 	/*
20182 	* Lists.
20183 	*/
20184 	x = xmlSchemaValueGetNext(x);
20185 	if (x != NULL) {
20186 	    y = xmlSchemaValueGetNext(y);
20187 	    if (y == NULL)
20188 		return (0);
20189 	} else if (xmlSchemaValueGetNext(y) != NULL)
20190 	    return (0);
20191 	else
20192 	    return (1);
20193     }
20194     return (0);
20195 }
20196 
20197 /**
20198  * xmlSchemaResolveAttrUseReferences:
20199  * @item:  an attribute use
20200  * @ctxt:  a parser context
20201  *
20202  * Resolves the referenced attribute declaration.
20203  */
20204 static int
xmlSchemaResolveAttrUseReferences(xmlSchemaAttributeUsePtr ause,xmlSchemaParserCtxtPtr ctxt)20205 xmlSchemaResolveAttrUseReferences(xmlSchemaAttributeUsePtr ause,
20206 				  xmlSchemaParserCtxtPtr ctxt)
20207 {
20208     if ((ctxt == NULL) || (ause == NULL))
20209 	return(-1);
20210     if ((ause->attrDecl == NULL) ||
20211 	(ause->attrDecl->type != XML_SCHEMA_EXTRA_QNAMEREF))
20212 	return(0);
20213 
20214     {
20215 	xmlSchemaQNameRefPtr ref = WXS_QNAME_CAST ause->attrDecl;
20216 
20217 	/*
20218 	* TODO: Evaluate, what errors could occur if the declaration is not
20219 	* found.
20220 	*/
20221 	ause->attrDecl = xmlSchemaGetAttributeDecl(ctxt->schema,
20222 	    ref->name, ref->targetNamespace);
20223         if (ause->attrDecl == NULL) {
20224 	    xmlSchemaPResCompAttrErr(ctxt,
20225 		XML_SCHEMAP_SRC_RESOLVE,
20226 		WXS_BASIC_CAST ause, ause->node,
20227 		"ref", ref->name, ref->targetNamespace,
20228 		XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20229             return(ctxt->err);;
20230         }
20231     }
20232     return(0);
20233 }
20234 
20235 /**
20236  * xmlSchemaCheckAttrUsePropsCorrect:
20237  * @ctxt:  a parser context
20238  * @use:  an attribute use
20239  *
20240  * Schema Component Constraint:
20241  * Attribute Use Correct (au-props-correct)
20242  *
20243  */
20244 static int
xmlSchemaCheckAttrUsePropsCorrect(xmlSchemaParserCtxtPtr ctxt,xmlSchemaAttributeUsePtr use)20245 xmlSchemaCheckAttrUsePropsCorrect(xmlSchemaParserCtxtPtr ctxt,
20246 			     xmlSchemaAttributeUsePtr use)
20247 {
20248     if ((ctxt == NULL) || (use == NULL))
20249 	return(-1);
20250     if ((use->defValue == NULL) || (WXS_ATTRUSE_DECL(use) == NULL) ||
20251 	((WXS_ATTRUSE_DECL(use))->type != XML_SCHEMA_TYPE_ATTRIBUTE))
20252 	return(0);
20253 
20254     /*
20255     * SPEC au-props-correct (1)
20256     * "The values of the properties of an attribute use must be as
20257     * described in the property tableau in The Attribute Use Schema
20258     * Component ($3.5.1), modulo the impact of Missing
20259     * Sub-components ($5.3)."
20260     */
20261 
20262     if (((WXS_ATTRUSE_DECL(use))->defValue != NULL) &&
20263 	((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMAS_ATTR_FIXED) &&
20264         ((use->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20265     {
20266 	xmlSchemaPCustomErr(ctxt,
20267 	    XML_SCHEMAP_AU_PROPS_CORRECT_2,
20268 	    WXS_BASIC_CAST use, NULL,
20269 	    "The attribute declaration has a 'fixed' value constraint "
20270 	    ", thus the attribute use must also have a 'fixed' value "
20271 	    "constraint",
20272 	    NULL);
20273 	return(ctxt->err);
20274     }
20275     /*
20276     * Compute and check the value constraint's value.
20277     */
20278     if ((use->defVal != NULL) && (WXS_ATTRUSE_TYPEDEF(use) != NULL)) {
20279 	int ret;
20280 	/*
20281 	* TODO: The spec seems to be missing a check of the
20282 	* value constraint of the attribute use. We will do it here.
20283 	*/
20284 	/*
20285 	* SPEC a-props-correct (3)
20286 	*/
20287 	if (xmlSchemaIsDerivedFromBuiltInType(
20288 	    WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
20289 	{
20290 	    xmlSchemaCustomErr(ACTXT_CAST ctxt,
20291 		XML_SCHEMAP_AU_PROPS_CORRECT,
20292 		NULL, WXS_BASIC_CAST use,
20293 		"Value constraints are not allowed if the type definition "
20294 		"is or is derived from xs:ID",
20295 		NULL, NULL);
20296 	    return(ctxt->err);
20297 	}
20298 
20299 	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST ctxt,
20300 	    use->node, WXS_ATTRUSE_TYPEDEF(use),
20301 	    use->defValue, &(use->defVal),
20302 	    1, 1, 0);
20303 	if (ret != 0) {
20304 	    if (ret < 0) {
20305 		PERROR_INT2("xmlSchemaCheckAttrUsePropsCorrect",
20306 		    "calling xmlSchemaVCheckCVCSimpleType()");
20307 		return(-1);
20308 	    }
20309 	    xmlSchemaCustomErr(ACTXT_CAST ctxt,
20310 		XML_SCHEMAP_AU_PROPS_CORRECT,
20311 		NULL, WXS_BASIC_CAST use,
20312 		"The value of the value constraint is not valid",
20313 		NULL, NULL);
20314 	    return(ctxt->err);
20315 	}
20316     }
20317     /*
20318     * SPEC au-props-correct (2)
20319     * "If the {attribute declaration} has a fixed
20320     * {value constraint}, then if the attribute use itself has a
20321     * {value constraint}, it must also be fixed and its value must match
20322     * that of the {attribute declaration}'s {value constraint}."
20323     */
20324     if (((WXS_ATTRUSE_DECL(use))->defVal != NULL) &&
20325 	(((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20326     {
20327 	if (! xmlSchemaAreValuesEqual(use->defVal,
20328 		(WXS_ATTRUSE_DECL(use))->defVal))
20329 	{
20330 	    xmlSchemaPCustomErr(ctxt,
20331 		XML_SCHEMAP_AU_PROPS_CORRECT_2,
20332 		WXS_BASIC_CAST use, NULL,
20333 		"The 'fixed' value constraint of the attribute use "
20334 		"must match the attribute declaration's value "
20335 		"constraint '%s'",
20336 		(WXS_ATTRUSE_DECL(use))->defValue);
20337 	}
20338 	return(ctxt->err);
20339     }
20340     return(0);
20341 }
20342 
20343 
20344 
20345 
20346 /**
20347  * xmlSchemaResolveAttrTypeReferences:
20348  * @item:  an attribute declaration
20349  * @ctxt:  a parser context
20350  *
20351  * Resolves the referenced type definition component.
20352  */
20353 static int
xmlSchemaResolveAttrTypeReferences(xmlSchemaAttributePtr item,xmlSchemaParserCtxtPtr ctxt)20354 xmlSchemaResolveAttrTypeReferences(xmlSchemaAttributePtr item,
20355 				   xmlSchemaParserCtxtPtr ctxt)
20356 {
20357     /*
20358     * The simple type definition corresponding to the <simpleType> element
20359     * information item in the [children], if present, otherwise the simple
20360     * type definition `resolved` to by the `actual value` of the type
20361     * [attribute], if present, otherwise the `simple ur-type definition`.
20362     */
20363     if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
20364 	return(0);
20365     item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
20366     if (item->subtypes != NULL)
20367         return(0);
20368     if (item->typeName != NULL) {
20369         xmlSchemaTypePtr type;
20370 
20371 	type = xmlSchemaGetType(ctxt->schema, item->typeName,
20372 	    item->typeNs);
20373 	if ((type == NULL) || (! WXS_IS_SIMPLE(type))) {
20374 	    xmlSchemaPResCompAttrErr(ctxt,
20375 		XML_SCHEMAP_SRC_RESOLVE,
20376 		WXS_BASIC_CAST item, item->node,
20377 		"type", item->typeName, item->typeNs,
20378 		XML_SCHEMA_TYPE_SIMPLE, NULL);
20379 	    return(ctxt->err);
20380 	} else
20381 	    item->subtypes = type;
20382 
20383     } else {
20384 	/*
20385 	* The type defaults to the xs:anySimpleType.
20386 	*/
20387 	item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
20388     }
20389     return(0);
20390 }
20391 
20392 /**
20393  * xmlSchemaResolveIDCKeyReferences:
20394  * @idc:  the identity-constraint definition
20395  * @ctxt:  the schema parser context
20396  * @name:  the attribute name
20397  *
20398  * Resolve keyRef references to key/unique IDCs.
20399  * Schema Component Constraint:
20400  *   Identity-constraint Definition Properties Correct (c-props-correct)
20401  */
20402 static int
xmlSchemaResolveIDCKeyReferences(xmlSchemaIDCPtr idc,xmlSchemaParserCtxtPtr pctxt)20403 xmlSchemaResolveIDCKeyReferences(xmlSchemaIDCPtr idc,
20404 			  xmlSchemaParserCtxtPtr pctxt)
20405 {
20406     if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
20407         return(0);
20408     if (idc->ref->name != NULL) {
20409 	idc->ref->item = (xmlSchemaBasicItemPtr)
20410 	    xmlSchemaGetIDC(pctxt->schema, idc->ref->name,
20411 		idc->ref->targetNamespace);
20412         if (idc->ref->item == NULL) {
20413 	    /*
20414 	    * TODO: It is actually not an error to fail to resolve
20415 	    * at this stage. BUT we need to be that strict!
20416 	    */
20417 	    xmlSchemaPResCompAttrErr(pctxt,
20418 		XML_SCHEMAP_SRC_RESOLVE,
20419 		WXS_BASIC_CAST idc, idc->node,
20420 		"refer", idc->ref->name,
20421 		idc->ref->targetNamespace,
20422 		XML_SCHEMA_TYPE_IDC_KEY, NULL);
20423             return(pctxt->err);
20424 	} else if (idc->ref->item->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
20425 	    /*
20426 	    * SPEC c-props-correct (1)
20427 	    */
20428 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
20429 		XML_SCHEMAP_C_PROPS_CORRECT,
20430 		NULL, WXS_BASIC_CAST idc,
20431 		"The keyref references a keyref",
20432 		NULL, NULL);
20433 	    idc->ref->item = NULL;
20434 	    return(pctxt->err);
20435 	} else {
20436 	    if (idc->nbFields !=
20437 		((xmlSchemaIDCPtr) idc->ref->item)->nbFields) {
20438 		xmlChar *str = NULL;
20439 		xmlSchemaIDCPtr refer;
20440 
20441 		refer = (xmlSchemaIDCPtr) idc->ref->item;
20442 		/*
20443 		* SPEC c-props-correct(2)
20444 		* "If the {identity-constraint category} is keyref,
20445 		* the cardinality of the {fields} must equal that of
20446 		* the {fields} of the {referenced key}.
20447 		*/
20448 		xmlSchemaCustomErr(ACTXT_CAST pctxt,
20449 		    XML_SCHEMAP_C_PROPS_CORRECT,
20450 		    NULL, WXS_BASIC_CAST idc,
20451 		    "The cardinality of the keyref differs from the "
20452 		    "cardinality of the referenced key/unique '%s'",
20453 		    xmlSchemaFormatQName(&str, refer->targetNamespace,
20454 			refer->name),
20455 		    NULL);
20456 		FREE_AND_NULL(str)
20457 		return(pctxt->err);
20458 	    }
20459 	}
20460     }
20461     return(0);
20462 }
20463 
20464 static int
xmlSchemaResolveAttrUseProhibReferences(xmlSchemaAttributeUseProhibPtr prohib,xmlSchemaParserCtxtPtr pctxt)20465 xmlSchemaResolveAttrUseProhibReferences(xmlSchemaAttributeUseProhibPtr prohib,
20466 				       xmlSchemaParserCtxtPtr pctxt)
20467 {
20468     if (xmlSchemaGetAttributeDecl(pctxt->schema, prohib->name,
20469 	prohib->targetNamespace) == NULL) {
20470 
20471 	xmlSchemaPResCompAttrErr(pctxt,
20472 	    XML_SCHEMAP_SRC_RESOLVE,
20473 	    NULL, prohib->node,
20474 	    "ref", prohib->name, prohib->targetNamespace,
20475 	    XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20476 	return(XML_SCHEMAP_SRC_RESOLVE);
20477     }
20478     return(0);
20479 }
20480 
20481 #define WXS_REDEFINED_TYPE(c) \
20482 (((xmlSchemaTypePtr) item)->flags & XML_SCHEMAS_TYPE_REDEFINED)
20483 
20484 #define WXS_REDEFINED_MODEL_GROUP_DEF(c) \
20485 (((xmlSchemaModelGroupDefPtr) item)->flags & XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20486 
20487 #define WXS_REDEFINED_ATTR_GROUP(c) \
20488 (((xmlSchemaAttributeGroupPtr) item)->flags & XML_SCHEMAS_ATTRGROUP_REDEFINED)
20489 
20490 static int
xmlSchemaCheckSRCRedefineFirst(xmlSchemaParserCtxtPtr pctxt)20491 xmlSchemaCheckSRCRedefineFirst(xmlSchemaParserCtxtPtr pctxt)
20492 {
20493     int err = 0;
20494     xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20495     xmlSchemaBasicItemPtr prev, item;
20496     int wasRedefined;
20497 
20498     if (redef == NULL)
20499 	return(0);
20500 
20501     do {
20502 	item = redef->item;
20503 	/*
20504 	* First try to locate the redefined component in the
20505 	* schema graph starting with the redefined schema.
20506 	* NOTE: According to this schema bug entry:
20507 	*   http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005OctDec/0019.html
20508 	*   it's not clear if the referenced component needs to originate
20509 	*   from the <redefine>d schema _document_ or the schema; the latter
20510 	*   would include all imported and included sub-schemas of the
20511 	*   <redefine>d schema. Currenlty we latter approach is used.
20512 	*   SUPPLEMENT: It seems that the WG moves towards the latter
20513 	*   approach, so we are doing it right.
20514 	*
20515 	*/
20516 	prev = xmlSchemaFindRedefCompInGraph(
20517 	    redef->targetBucket, item->type,
20518 	    redef->refName, redef->refTargetNs);
20519 	if (prev == NULL) {
20520 	    xmlChar *str = NULL;
20521 	    xmlNodePtr node;
20522 
20523 	    /*
20524 	    * SPEC src-redefine:
20525 	    * (6.2.1) "The `actual value` of its own name attribute plus
20526 	    * target namespace must successfully `resolve` to a model
20527 	    * group definition in I."
20528 	    * (7.2.1) "The `actual value` of its own name attribute plus
20529 	    * target namespace must successfully `resolve` to an attribute
20530 	    * group definition in I."
20531 
20532 	    *
20533 	    * Note that, if we are redefining with the use of references
20534 	    * to components, the spec assumes the src-resolve to be used;
20535 	    * but this won't assure that we search only *inside* the
20536 	    * redefined schema.
20537 	    */
20538 	    if (redef->reference)
20539 		node = WXS_ITEM_NODE(redef->reference);
20540 	    else
20541 		node = WXS_ITEM_NODE(item);
20542 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
20543 		/*
20544 		* TODO: error code.
20545 		* Probably XML_SCHEMAP_SRC_RESOLVE, if this is using the
20546 		* reference kind.
20547 		*/
20548 		XML_SCHEMAP_SRC_REDEFINE, node, NULL,
20549 		"The %s '%s' to be redefined could not be found in "
20550 		"the redefined schema",
20551 		WXS_ITEM_TYPE_NAME(item),
20552 		xmlSchemaFormatQName(&str, redef->refTargetNs,
20553 		    redef->refName));
20554 	    FREE_AND_NULL(str);
20555 	    err = pctxt->err;
20556 	    redef = redef->next;
20557 	    continue;
20558 	}
20559 	/*
20560 	* TODO: Obtaining and setting the redefinition state is really
20561 	* clumsy.
20562 	*/
20563 	wasRedefined = 0;
20564 	switch (item->type) {
20565 	    case XML_SCHEMA_TYPE_COMPLEX:
20566 	    case XML_SCHEMA_TYPE_SIMPLE:
20567 		if ((WXS_TYPE_CAST prev)->flags &
20568 		    XML_SCHEMAS_TYPE_REDEFINED)
20569 		{
20570 		    wasRedefined = 1;
20571 		    break;
20572 		}
20573 		/* Mark it as redefined. */
20574 		(WXS_TYPE_CAST prev)->flags |= XML_SCHEMAS_TYPE_REDEFINED;
20575 		/*
20576 		* Assign the redefined type to the
20577 		* base type of the redefining type.
20578 		* TODO: How
20579 		*/
20580 		((xmlSchemaTypePtr) item)->baseType =
20581 		    (xmlSchemaTypePtr) prev;
20582 		break;
20583 	    case XML_SCHEMA_TYPE_GROUP:
20584 		if ((WXS_MODEL_GROUPDEF_CAST prev)->flags &
20585 		    XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20586 		{
20587 		    wasRedefined = 1;
20588 		    break;
20589 		}
20590 		/* Mark it as redefined. */
20591 		(WXS_MODEL_GROUPDEF_CAST prev)->flags |=
20592 		    XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED;
20593 		if (redef->reference != NULL) {
20594 		    /*
20595 		    * Overwrite the QName-reference with the
20596 		    * referenced model group def.
20597 		    */
20598 		    (WXS_PTC_CAST redef->reference)->children =
20599 			WXS_TREE_CAST prev;
20600 		}
20601 		redef->target = prev;
20602 		break;
20603 	    case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20604 		if ((WXS_ATTR_GROUP_CAST prev)->flags &
20605 		    XML_SCHEMAS_ATTRGROUP_REDEFINED)
20606 		{
20607 		    wasRedefined = 1;
20608 		    break;
20609 		}
20610 		(WXS_ATTR_GROUP_CAST prev)->flags |=
20611 		    XML_SCHEMAS_ATTRGROUP_REDEFINED;
20612 		if (redef->reference != NULL) {
20613 		    /*
20614 		    * Assign the redefined attribute group to the
20615 		    * QName-reference component.
20616 		    * This is the easy case, since we will just
20617 		    * expand the redefined group.
20618 		    */
20619 		    (WXS_QNAME_CAST redef->reference)->item = prev;
20620 		    redef->target = NULL;
20621 		} else {
20622 		    /*
20623 		    * This is the complicated case: we need
20624 		    * to apply src-redefine (7.2.2) at a later
20625 		    * stage, i.e. when attribute group references
20626 		    * have beed expanded and simple types have
20627 		    * beed fixed.
20628 		    */
20629 		    redef->target = prev;
20630 		}
20631 		break;
20632 	    default:
20633 		PERROR_INT("xmlSchemaResolveRedefReferences",
20634 		    "Unexpected redefined component type");
20635 		return(-1);
20636 	}
20637 	if (wasRedefined) {
20638 	    xmlChar *str = NULL;
20639 	    xmlNodePtr node;
20640 
20641 	    if (redef->reference)
20642 		node = WXS_ITEM_NODE(redef->reference);
20643 	    else
20644 		node = WXS_ITEM_NODE(redef->item);
20645 
20646 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
20647 		/* TODO: error code. */
20648 		XML_SCHEMAP_SRC_REDEFINE,
20649 		node, NULL,
20650 		"The referenced %s was already redefined. Multiple "
20651 		"redefinition of the same component is not supported",
20652 		xmlSchemaGetComponentDesignation(&str, prev),
20653 		NULL);
20654 	    FREE_AND_NULL(str)
20655 	    err = pctxt->err;
20656 	    redef = redef->next;
20657 	    continue;
20658 	}
20659 	redef = redef->next;
20660     } while (redef != NULL);
20661 
20662     return(err);
20663 }
20664 
20665 static int
xmlSchemaCheckSRCRedefineSecond(xmlSchemaParserCtxtPtr pctxt)20666 xmlSchemaCheckSRCRedefineSecond(xmlSchemaParserCtxtPtr pctxt)
20667 {
20668     int err = 0;
20669     xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20670     xmlSchemaBasicItemPtr item;
20671 
20672     if (redef == NULL)
20673 	return(0);
20674 
20675     do {
20676 	if (redef->target == NULL) {
20677 	    redef = redef->next;
20678 	    continue;
20679 	}
20680 	item = redef->item;
20681 
20682 	switch (item->type) {
20683 	    case XML_SCHEMA_TYPE_SIMPLE:
20684 	    case XML_SCHEMA_TYPE_COMPLEX:
20685 		/*
20686 		* Since the spec wants the {name} of the redefined
20687 		* type to be 'absent', we'll NULL it.
20688 		*/
20689 		(WXS_TYPE_CAST redef->target)->name = NULL;
20690 
20691 		/*
20692 		* TODO: Seems like there's nothing more to do. The normal
20693 		* inheritance mechanism is used. But not 100% sure.
20694 		*/
20695 		break;
20696 	    case XML_SCHEMA_TYPE_GROUP:
20697 		/*
20698 		* URGENT TODO:
20699 		* SPEC src-redefine:
20700 		* (6.2.2) "The {model group} of the model group definition
20701 		* which corresponds to it per XML Representation of Model
20702 		* Group Definition Schema Components ($3.7.2) must be a
20703 		* `valid restriction` of the {model group} of that model
20704 		* group definition in I, as defined in Particle Valid
20705 		* (Restriction) ($3.9.6)."
20706 		*/
20707 		break;
20708 	    case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20709 		/*
20710 		* SPEC src-redefine:
20711 		* (7.2.2) "The {attribute uses} and {attribute wildcard} of
20712 		* the attribute group definition which corresponds to it
20713 		* per XML Representation of Attribute Group Definition Schema
20714 		* Components ($3.6.2) must be `valid restrictions` of the
20715 		* {attribute uses} and {attribute wildcard} of that attribute
20716 		* group definition in I, as defined in clause 2, clause 3 and
20717 		* clause 4 of Derivation Valid (Restriction, Complex)
20718 		* ($3.4.6) (where references to the base type definition are
20719 		* understood as references to the attribute group definition
20720 		* in I)."
20721 		*/
20722 		err = xmlSchemaCheckDerivationOKRestriction2to4(pctxt,
20723 		    XML_SCHEMA_ACTION_REDEFINE,
20724 		    item, redef->target,
20725 		    (WXS_ATTR_GROUP_CAST item)->attrUses,
20726 		    (WXS_ATTR_GROUP_CAST redef->target)->attrUses,
20727 		    (WXS_ATTR_GROUP_CAST item)->attributeWildcard,
20728 		    (WXS_ATTR_GROUP_CAST redef->target)->attributeWildcard);
20729 		if (err == -1)
20730 		    return(-1);
20731 		break;
20732 	    default:
20733 		break;
20734 	}
20735 	redef = redef->next;
20736     } while (redef != NULL);
20737     return(0);
20738 }
20739 
20740 
20741 static int
xmlSchemaAddComponents(xmlSchemaParserCtxtPtr pctxt,xmlSchemaBucketPtr bucket)20742 xmlSchemaAddComponents(xmlSchemaParserCtxtPtr pctxt,
20743 		       xmlSchemaBucketPtr bucket)
20744 {
20745     xmlSchemaBasicItemPtr item;
20746     int err;
20747     xmlHashTablePtr *table;
20748     const xmlChar *name;
20749     int i;
20750 
20751 #define WXS_GET_GLOBAL_HASH(c, slot) { \
20752     if (WXS_IS_BUCKET_IMPMAIN((c)->type)) \
20753 	table = &(WXS_IMPBUCKET((c))->schema->slot); \
20754     else \
20755 	table = &(WXS_INCBUCKET((c))->ownerImport->schema->slot); }
20756 
20757     /*
20758     * Add global components to the schema's hash tables.
20759     * This is the place where duplicate components will be
20760     * detected.
20761     * TODO: I think normally we should support imports of the
20762     *   same namespace from multiple locations. We don't do currently,
20763     *   but if we do then according to:
20764     *   http://www.w3.org/Bugs/Public/show_bug.cgi?id=2224
20765     *   we would need, if imported directly, to import redefined
20766     *   components as well to be able to catch clashing components.
20767     *   (I hope I'll still know what this means after some months :-()
20768     */
20769     if (bucket == NULL)
20770 	return(-1);
20771     if (bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED)
20772 	return(0);
20773     bucket->flags |= XML_SCHEMA_BUCKET_COMPS_ADDED;
20774 
20775     for (i = 0; i < bucket->globals->nbItems; i++) {
20776 	item = bucket->globals->items[i];
20777 	table = NULL;
20778 	switch (item->type) {
20779 	    case XML_SCHEMA_TYPE_COMPLEX:
20780 	    case XML_SCHEMA_TYPE_SIMPLE:
20781 		if (WXS_REDEFINED_TYPE(item))
20782 		    continue;
20783 		name = (WXS_TYPE_CAST item)->name;
20784 		WXS_GET_GLOBAL_HASH(bucket, typeDecl)
20785 		break;
20786 	    case XML_SCHEMA_TYPE_ELEMENT:
20787 		name = (WXS_ELEM_CAST item)->name;
20788 		WXS_GET_GLOBAL_HASH(bucket, elemDecl)
20789 		break;
20790 	    case XML_SCHEMA_TYPE_ATTRIBUTE:
20791 		name = (WXS_ATTR_CAST item)->name;
20792 		WXS_GET_GLOBAL_HASH(bucket, attrDecl)
20793 		break;
20794 	    case XML_SCHEMA_TYPE_GROUP:
20795 		if (WXS_REDEFINED_MODEL_GROUP_DEF(item))
20796 		    continue;
20797 		name = (WXS_MODEL_GROUPDEF_CAST item)->name;
20798 		WXS_GET_GLOBAL_HASH(bucket, groupDecl)
20799 		break;
20800 	    case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20801 		if (WXS_REDEFINED_ATTR_GROUP(item))
20802 		    continue;
20803 		name = (WXS_ATTR_GROUP_CAST item)->name;
20804 		WXS_GET_GLOBAL_HASH(bucket, attrgrpDecl)
20805 		break;
20806 	    case XML_SCHEMA_TYPE_IDC_KEY:
20807 	    case XML_SCHEMA_TYPE_IDC_UNIQUE:
20808 	    case XML_SCHEMA_TYPE_IDC_KEYREF:
20809 		name = (WXS_IDC_CAST item)->name;
20810 		WXS_GET_GLOBAL_HASH(bucket, idcDef)
20811 		break;
20812 	    case XML_SCHEMA_TYPE_NOTATION:
20813 		name = ((xmlSchemaNotationPtr) item)->name;
20814 		WXS_GET_GLOBAL_HASH(bucket, notaDecl)
20815 		break;
20816 	    default:
20817 		PERROR_INT("xmlSchemaAddComponents",
20818 		    "Unexpected global component type");
20819 		continue;
20820 	}
20821 	if (*table == NULL) {
20822 	    *table = xmlHashCreateDict(10, pctxt->dict);
20823 	    if (*table == NULL) {
20824 		PERROR_INT("xmlSchemaAddComponents",
20825 		    "failed to create a component hash table");
20826 		return(-1);
20827 	    }
20828 	}
20829 	err = xmlHashAddEntry(*table, name, item);
20830 	if (err != 0) {
20831 	    xmlChar *str = NULL;
20832 
20833 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
20834 		XML_SCHEMAP_REDEFINED_TYPE,
20835 		WXS_ITEM_NODE(item),
20836 		WXS_BASIC_CAST item,
20837 		"A global %s '%s' does already exist",
20838 		WXS_ITEM_TYPE_NAME(item),
20839 		xmlSchemaGetComponentQName(&str, item));
20840 	    FREE_AND_NULL(str);
20841 	}
20842     }
20843     /*
20844     * Process imported/included schemas.
20845     */
20846     if (bucket->relations != NULL) {
20847 	xmlSchemaSchemaRelationPtr rel = bucket->relations;
20848 	do {
20849 	    if ((rel->bucket != NULL) &&
20850 		((rel->bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED) == 0)) {
20851 		if (xmlSchemaAddComponents(pctxt, rel->bucket) == -1)
20852 		    return(-1);
20853 	    }
20854 	    rel = rel->next;
20855 	} while (rel != NULL);
20856     }
20857     return(0);
20858 }
20859 
20860 static int
xmlSchemaFixupComponents(xmlSchemaParserCtxtPtr pctxt,xmlSchemaBucketPtr rootBucket)20861 xmlSchemaFixupComponents(xmlSchemaParserCtxtPtr pctxt,
20862 			 xmlSchemaBucketPtr rootBucket)
20863 {
20864     xmlSchemaConstructionCtxtPtr con = pctxt->constructor;
20865     xmlSchemaTreeItemPtr item, *items;
20866     int nbItems, i, ret = 0;
20867     xmlSchemaBucketPtr oldbucket = con->bucket;
20868     xmlSchemaElementPtr elemDecl;
20869 
20870 #define FIXHFAILURE if (pctxt->err == XML_SCHEMAP_INTERNAL) goto exit_failure;
20871 
20872     if ((con->pending == NULL) ||
20873 	(con->pending->nbItems == 0))
20874 	return(0);
20875 
20876     /*
20877     * Since xmlSchemaFixupComplexType() will create new particles
20878     * (local components), and those particle components need a bucket
20879     * on the constructor, we'll assure here that the constructor has
20880     * a bucket.
20881     * TODO: Think about storing locals _only_ on the main bucket.
20882     */
20883     if (con->bucket == NULL)
20884 	con->bucket = rootBucket;
20885 
20886     /* TODO:
20887     * SPEC (src-redefine):
20888     * (6.2) "If it has no such self-reference, then all of the
20889     * following must be true:"
20890 
20891     * (6.2.2) The {model group} of the model group definition which
20892     * corresponds to it per XML Representation of Model Group
20893     * Definition Schema Components ($3.7.2) must be a `valid
20894     * restriction` of the {model group} of that model group definition
20895     * in I, as defined in Particle Valid (Restriction) ($3.9.6)."
20896     */
20897     xmlSchemaCheckSRCRedefineFirst(pctxt);
20898 
20899     /*
20900     * Add global components to the schemata's hash tables.
20901     */
20902     xmlSchemaAddComponents(pctxt, rootBucket);
20903 
20904     pctxt->ctxtType = NULL;
20905     items = (xmlSchemaTreeItemPtr *) con->pending->items;
20906     nbItems = con->pending->nbItems;
20907     /*
20908     * Now that we have parsed *all* the schema document(s) and converted
20909     * them to schema components, we can resolve references, apply component
20910     * constraints, create the FSA from the content model, etc.
20911     */
20912     /*
20913     * Resolve references of..
20914     *
20915     * 1. element declarations:
20916     *   - the type definition
20917     *   - the substitution group affiliation
20918     * 2. simple/complex types:
20919     *   - the base type definition
20920     *   - the memberTypes of union types
20921     *   - the itemType of list types
20922     * 3. attributes declarations and attribute uses:
20923     *   - the type definition
20924     *   - if an attribute use, then the attribute declaration
20925     * 4. attribute group references:
20926     *   - the attribute group definition
20927     * 5. particles:
20928     *   - the term of the particle (e.g. a model group)
20929     * 6. IDC key-references:
20930     *   - the referenced IDC 'key' or 'unique' definition
20931     * 7. Attribute prohibitions which had a "ref" attribute.
20932     */
20933     for (i = 0; i < nbItems; i++) {
20934 	item = items[i];
20935 	switch (item->type) {
20936 	    case XML_SCHEMA_TYPE_ELEMENT:
20937 		xmlSchemaResolveElementReferences(
20938 		    (xmlSchemaElementPtr) item, pctxt);
20939 		FIXHFAILURE;
20940 		break;
20941 	    case XML_SCHEMA_TYPE_COMPLEX:
20942 	    case XML_SCHEMA_TYPE_SIMPLE:
20943 		xmlSchemaResolveTypeReferences(
20944 		    (xmlSchemaTypePtr) item, pctxt);
20945 		FIXHFAILURE;
20946 		break;
20947 	    case XML_SCHEMA_TYPE_ATTRIBUTE:
20948 		xmlSchemaResolveAttrTypeReferences(
20949 		    (xmlSchemaAttributePtr) item, pctxt);
20950 		FIXHFAILURE;
20951 		break;
20952 	    case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
20953 		xmlSchemaResolveAttrUseReferences(
20954 		    (xmlSchemaAttributeUsePtr) item, pctxt);
20955 		FIXHFAILURE;
20956 		break;
20957 	    case XML_SCHEMA_EXTRA_QNAMEREF:
20958 		if ((WXS_QNAME_CAST item)->itemType ==
20959 		    XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
20960 		{
20961 		    xmlSchemaResolveAttrGroupReferences(
20962 			WXS_QNAME_CAST item, pctxt);
20963 		}
20964 		FIXHFAILURE;
20965 		break;
20966 	    case XML_SCHEMA_TYPE_SEQUENCE:
20967 	    case XML_SCHEMA_TYPE_CHOICE:
20968 	    case XML_SCHEMA_TYPE_ALL:
20969 		xmlSchemaResolveModelGroupParticleReferences(pctxt,
20970 		    WXS_MODEL_GROUP_CAST item);
20971 		FIXHFAILURE;
20972 		break;
20973 	    case XML_SCHEMA_TYPE_IDC_KEY:
20974 	    case XML_SCHEMA_TYPE_IDC_UNIQUE:
20975 	    case XML_SCHEMA_TYPE_IDC_KEYREF:
20976 		xmlSchemaResolveIDCKeyReferences(
20977 		    (xmlSchemaIDCPtr) item, pctxt);
20978 		FIXHFAILURE;
20979 		break;
20980 	    case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
20981 		/*
20982 		* Handle attribue prohibition which had a
20983 		* "ref" attribute.
20984 		*/
20985 		xmlSchemaResolveAttrUseProhibReferences(
20986 		    WXS_ATTR_PROHIB_CAST item, pctxt);
20987 		FIXHFAILURE;
20988 		break;
20989 	    default:
20990 		break;
20991 	}
20992     }
20993     if (pctxt->nberrors != 0)
20994 	goto exit_error;
20995 
20996     /*
20997     * Now that all references are resolved we
20998     * can check for circularity of...
20999     * 1. the base axis of type definitions
21000     * 2. nested model group definitions
21001     * 3. nested attribute group definitions
21002     * TODO: check for circual substitution groups.
21003     */
21004     for (i = 0; i < nbItems; i++) {
21005 	item = items[i];
21006 	/*
21007 	* Let's better stop on the first error here.
21008 	*/
21009 	switch (item->type) {
21010 	    case XML_SCHEMA_TYPE_COMPLEX:
21011 	    case XML_SCHEMA_TYPE_SIMPLE:
21012 		xmlSchemaCheckTypeDefCircular(
21013 		    (xmlSchemaTypePtr) item, pctxt);
21014 		FIXHFAILURE;
21015 		if (pctxt->nberrors != 0)
21016 		    goto exit_error;
21017 		break;
21018 	    case XML_SCHEMA_TYPE_GROUP:
21019 		xmlSchemaCheckGroupDefCircular(
21020 		    (xmlSchemaModelGroupDefPtr) item, pctxt);
21021 		FIXHFAILURE;
21022 		if (pctxt->nberrors != 0)
21023 		    goto exit_error;
21024 		break;
21025 	    case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
21026 		xmlSchemaCheckAttrGroupCircular(
21027 		    (xmlSchemaAttributeGroupPtr) item, pctxt);
21028 		FIXHFAILURE;
21029 		if (pctxt->nberrors != 0)
21030 		    goto exit_error;
21031 		break;
21032 	    default:
21033 		break;
21034 	}
21035     }
21036     if (pctxt->nberrors != 0)
21037 	goto exit_error;
21038     /*
21039     * Model group definition references:
21040     * Such a reference is reflected by a particle at the component
21041     * level. Until now the 'term' of such particles pointed
21042     * to the model group definition; this was done, in order to
21043     * ease circularity checks. Now we need to set the 'term' of
21044     * such particles to the model group of the model group definition.
21045     */
21046     for (i = 0; i < nbItems; i++) {
21047 	item = items[i];
21048 	switch (item->type) {
21049 	    case XML_SCHEMA_TYPE_SEQUENCE:
21050 	    case XML_SCHEMA_TYPE_CHOICE:
21051 		xmlSchemaModelGroupToModelGroupDefFixup(pctxt,
21052 		    WXS_MODEL_GROUP_CAST item);
21053 		break;
21054 	    default:
21055 		break;
21056 	}
21057     }
21058     if (pctxt->nberrors != 0)
21059 	goto exit_error;
21060     /*
21061     * Expand attribute group references of attribute group definitions.
21062     */
21063     for (i = 0; i < nbItems; i++) {
21064 	item = items[i];
21065 	switch (item->type) {
21066             case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
21067 		if ((! WXS_ATTR_GROUP_EXPANDED(item)) &&
21068 		    WXS_ATTR_GROUP_HAS_REFS(item))
21069 		{
21070 		    xmlSchemaAttributeGroupExpandRefs(pctxt,
21071 			WXS_ATTR_GROUP_CAST item);
21072 		    FIXHFAILURE;
21073 		}
21074 		break;
21075 	    default:
21076 		break;
21077 	}
21078     }
21079     if (pctxt->nberrors != 0)
21080 	goto exit_error;
21081     /*
21082     * First compute the variety of simple types. This is needed as
21083     * a seperate step, since otherwise we won't be able to detect
21084     * circular union types in all cases.
21085     */
21086     for (i = 0; i < nbItems; i++) {
21087 	item = items[i];
21088 	switch (item->type) {
21089             case XML_SCHEMA_TYPE_SIMPLE:
21090 		if (WXS_IS_TYPE_NOT_FIXED_1((xmlSchemaTypePtr) item)) {
21091 		    xmlSchemaFixupSimpleTypeStageOne(pctxt,
21092 			(xmlSchemaTypePtr) item);
21093 		    FIXHFAILURE;
21094 		}
21095 		break;
21096 	    default:
21097 		break;
21098 	}
21099     }
21100     if (pctxt->nberrors != 0)
21101 	goto exit_error;
21102     /*
21103     * Detect circular union types. Note that this needs the variety to
21104     * be already computed.
21105     */
21106     for (i = 0; i < nbItems; i++) {
21107 	item = items[i];
21108 	switch (item->type) {
21109             case XML_SCHEMA_TYPE_SIMPLE:
21110 		if (((xmlSchemaTypePtr) item)->memberTypes != NULL) {
21111 		    xmlSchemaCheckUnionTypeDefCircular(pctxt,
21112 			(xmlSchemaTypePtr) item);
21113 		    FIXHFAILURE;
21114 		}
21115 		break;
21116 	    default:
21117 		break;
21118 	}
21119     }
21120     if (pctxt->nberrors != 0)
21121 	goto exit_error;
21122 
21123     /*
21124     * Do the complete type fixup for simple types.
21125     */
21126     for (i = 0; i < nbItems; i++) {
21127 	item = items[i];
21128 	switch (item->type) {
21129             case XML_SCHEMA_TYPE_SIMPLE:
21130 		if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
21131 		    xmlSchemaFixupSimpleTypeStageTwo(pctxt, WXS_TYPE_CAST item);
21132 		    FIXHFAILURE;
21133 		}
21134 		break;
21135 	    default:
21136 		break;
21137 	}
21138     }
21139     if (pctxt->nberrors != 0)
21140 	goto exit_error;
21141     /*
21142     * At this point we need build and check all simple types.
21143     */
21144     /*
21145     * Apply contraints for attribute declarations.
21146     */
21147     for (i = 0; i < nbItems; i++) {
21148 	item = items[i];
21149 	switch (item->type) {
21150 	    case XML_SCHEMA_TYPE_ATTRIBUTE:
21151 		xmlSchemaCheckAttrPropsCorrect(pctxt, WXS_ATTR_CAST item);
21152 		FIXHFAILURE;
21153 		break;
21154 	    default:
21155 		break;
21156 	}
21157     }
21158     if (pctxt->nberrors != 0)
21159 	goto exit_error;
21160     /*
21161     * Apply constraints for attribute uses.
21162     */
21163     for (i = 0; i < nbItems; i++) {
21164 	item = items[i];
21165 	switch (item->type) {
21166 	    case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
21167 		if (((xmlSchemaAttributeUsePtr)item)->defValue != NULL) {
21168 		    xmlSchemaCheckAttrUsePropsCorrect(pctxt,
21169 			WXS_ATTR_USE_CAST item);
21170 		    FIXHFAILURE;
21171 		}
21172 		break;
21173 	    default:
21174 		break;
21175 	}
21176     }
21177     if (pctxt->nberrors != 0)
21178 	goto exit_error;
21179 
21180     /*
21181     * Apply constraints for attribute group definitions.
21182     */
21183     for (i = 0; i < nbItems; i++) {
21184 	item = items[i];
21185 	switch (item->type) {
21186 	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
21187 	    if (( (WXS_ATTR_GROUP_CAST item)->attrUses != NULL) &&
21188 		( (WXS_LIST_CAST (WXS_ATTR_GROUP_CAST item)->attrUses)->nbItems > 1))
21189 	    {
21190 		xmlSchemaCheckAGPropsCorrect(pctxt, WXS_ATTR_GROUP_CAST item);
21191 		FIXHFAILURE;
21192 	    }
21193 	    break;
21194 	default:
21195 	    break;
21196 	}
21197     }
21198     if (pctxt->nberrors != 0)
21199 	goto exit_error;
21200 
21201     /*
21202     * Apply constraints for redefinitions.
21203     */
21204     if (WXS_CONSTRUCTOR(pctxt)->redefs != NULL)
21205 	xmlSchemaCheckSRCRedefineSecond(pctxt);
21206     if (pctxt->nberrors != 0)
21207 	goto exit_error;
21208 
21209     /*
21210     * Complex types are builded and checked.
21211     */
21212     for (i = 0; i < nbItems; i++) {
21213 	item = con->pending->items[i];
21214 	switch (item->type) {
21215 	    case XML_SCHEMA_TYPE_COMPLEX:
21216 		if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
21217 		    xmlSchemaFixupComplexType(pctxt, WXS_TYPE_CAST item);
21218 		    FIXHFAILURE;
21219 		}
21220 		break;
21221 	    default:
21222 		break;
21223 	}
21224     }
21225     if (pctxt->nberrors != 0)
21226 	goto exit_error;
21227 
21228     /*
21229     * The list could have changed, since xmlSchemaFixupComplexType()
21230     * will create particles and model groups in some cases.
21231     */
21232     items = (xmlSchemaTreeItemPtr *) con->pending->items;
21233     nbItems = con->pending->nbItems;
21234 
21235     /*
21236     * Apply some constraints for element declarations.
21237     */
21238     for (i = 0; i < nbItems; i++) {
21239 	item = items[i];
21240 	switch (item->type) {
21241 	    case XML_SCHEMA_TYPE_ELEMENT:
21242 		elemDecl = (xmlSchemaElementPtr) item;
21243 
21244 		if ((elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED) == 0)
21245 		{
21246 		    xmlSchemaCheckElementDeclComponent(
21247 			(xmlSchemaElementPtr) elemDecl, pctxt);
21248 		    FIXHFAILURE;
21249 		}
21250 
21251 #ifdef WXS_ELEM_DECL_CONS_ENABLED
21252 		/*
21253 		* Schema Component Constraint: Element Declarations Consistent
21254 		* Apply this constraint to local types of element declarations.
21255 		*/
21256 		if ((WXS_ELEM_TYPEDEF(elemDecl) != NULL) &&
21257 		    (WXS_IS_COMPLEX(WXS_ELEM_TYPEDEF(elemDecl))) &&
21258 		    (WXS_TYPE_IS_LOCAL(WXS_ELEM_TYPEDEF(elemDecl))))
21259 		{
21260 		    xmlSchemaCheckElementDeclConsistent(pctxt,
21261 			WXS_BASIC_CAST elemDecl,
21262 			WXS_TYPE_PARTICLE(WXS_ELEM_TYPEDEF(elemDecl)),
21263 			NULL, NULL, 0);
21264 		}
21265 #endif
21266 		break;
21267 	    default:
21268 		break;
21269 	}
21270     }
21271     if (pctxt->nberrors != 0)
21272 	goto exit_error;
21273 
21274     /*
21275     * Finally we can build the automaton from the content model of
21276     * complex types.
21277     */
21278 
21279     for (i = 0; i < nbItems; i++) {
21280 	item = items[i];
21281 	switch (item->type) {
21282 	    case XML_SCHEMA_TYPE_COMPLEX:
21283 		xmlSchemaBuildContentModel((xmlSchemaTypePtr) item, pctxt);
21284 		/* FIXHFAILURE; */
21285 		break;
21286 	    default:
21287 		break;
21288 	}
21289     }
21290     if (pctxt->nberrors != 0)
21291 	goto exit_error;
21292     /*
21293     * URGENT TODO: cos-element-consistent
21294     */
21295     goto exit;
21296 
21297 exit_error:
21298     ret = pctxt->err;
21299     goto exit;
21300 
21301 exit_failure:
21302     ret = -1;
21303 
21304 exit:
21305     /*
21306     * Reset the constructor. This is needed for XSI acquisition, since
21307     * those items will be processed over and over again for every XSI
21308     * if not cleared here.
21309     */
21310     con->bucket = oldbucket;
21311     con->pending->nbItems = 0;
21312     if (con->substGroups != NULL) {
21313 	xmlHashFree(con->substGroups, xmlSchemaSubstGroupFreeEntry);
21314 	con->substGroups = NULL;
21315     }
21316     if (con->redefs != NULL) {
21317 	xmlSchemaRedefListFree(con->redefs);
21318 	con->redefs = NULL;
21319     }
21320     return(ret);
21321 }
21322 /**
21323  * xmlSchemaParse:
21324  * @ctxt:  a schema validation context
21325  *
21326  * parse a schema definition resource and build an internal
21327  * XML Shema struture which can be used to validate instances.
21328  *
21329  * Returns the internal XML Schema structure built from the resource or
21330  *         NULL in case of error
21331  */
21332 xmlSchemaPtr
xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)21333 xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
21334 {
21335     xmlSchemaPtr mainSchema = NULL;
21336     xmlSchemaBucketPtr bucket = NULL;
21337     int res;
21338 
21339     /*
21340     * This one is used if the schema to be parsed was specified via
21341     * the API; i.e. not automatically by the validated instance document.
21342     */
21343 
21344     xmlSchemaInitTypes();
21345 
21346     if (ctxt == NULL)
21347         return (NULL);
21348 
21349     /* TODO: Init the context. Is this all we need?*/
21350     ctxt->nberrors = 0;
21351     ctxt->err = 0;
21352     ctxt->counter = 0;
21353 
21354     /* Create the *main* schema. */
21355     mainSchema = xmlSchemaNewSchema(ctxt);
21356     if (mainSchema == NULL)
21357 	goto exit_failure;
21358     /*
21359     * Create the schema constructor.
21360     */
21361     if (ctxt->constructor == NULL) {
21362 	ctxt->constructor = xmlSchemaConstructionCtxtCreate(ctxt->dict);
21363 	if (ctxt->constructor == NULL)
21364 	    return(NULL);
21365 	/* Take ownership of the constructor to be able to free it. */
21366 	ctxt->ownsConstructor = 1;
21367     }
21368     ctxt->constructor->mainSchema = mainSchema;
21369     /*
21370     * Locate and add the schema document.
21371     */
21372     res = xmlSchemaAddSchemaDoc(ctxt, XML_SCHEMA_SCHEMA_MAIN,
21373 	ctxt->URL, ctxt->doc, ctxt->buffer, ctxt->size, NULL,
21374 	NULL, NULL, &bucket);
21375     if (res == -1)
21376 	goto exit_failure;
21377     if (res != 0)
21378 	goto exit;
21379 
21380     if (bucket == NULL) {
21381 	/* TODO: Error code, actually we failed to *locate* the schema. */
21382 	if (ctxt->URL)
21383 	    xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21384 		NULL, NULL,
21385 		"Failed to locate the main schema resource at '%s'",
21386 		ctxt->URL, NULL);
21387 	else
21388 	    xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21389 		NULL, NULL,
21390 		"Failed to locate the main schema resource",
21391 		    NULL, NULL);
21392 	goto exit;
21393     }
21394     /* Then do the parsing for good. */
21395     if (xmlSchemaParseNewDocWithContext(ctxt, mainSchema, bucket) == -1)
21396 	goto exit_failure;
21397     if (ctxt->nberrors != 0)
21398 	goto exit;
21399 
21400     mainSchema->doc = bucket->doc;
21401     mainSchema->preserve = ctxt->preserve;
21402 
21403     ctxt->schema = mainSchema;
21404 
21405     if (xmlSchemaFixupComponents(ctxt, WXS_CONSTRUCTOR(ctxt)->mainBucket) == -1)
21406 	goto exit_failure;
21407 
21408     /*
21409     * TODO: This is not nice, since we cannot distinguish from the
21410     * result if there was an internal error or not.
21411     */
21412 exit:
21413     if (ctxt->nberrors != 0) {
21414 	if (mainSchema) {
21415 	    xmlSchemaFree(mainSchema);
21416 	    mainSchema = NULL;
21417 	}
21418 	if (ctxt->constructor) {
21419 	    xmlSchemaConstructionCtxtFree(ctxt->constructor);
21420 	    ctxt->constructor = NULL;
21421 	    ctxt->ownsConstructor = 0;
21422 	}
21423     }
21424     ctxt->schema = NULL;
21425     return(mainSchema);
21426 exit_failure:
21427     /*
21428     * Quite verbose, but should catch internal errors, which were
21429     * not communitated.
21430     */
21431     if (mainSchema) {
21432         xmlSchemaFree(mainSchema);
21433 	mainSchema = NULL;
21434     }
21435     if (ctxt->constructor) {
21436 	xmlSchemaConstructionCtxtFree(ctxt->constructor);
21437 	ctxt->constructor = NULL;
21438 	ctxt->ownsConstructor = 0;
21439     }
21440     PERROR_INT2("xmlSchemaParse",
21441 	"An internal error occurred");
21442     ctxt->schema = NULL;
21443     return(NULL);
21444 }
21445 
21446 /**
21447  * xmlSchemaSetParserErrors:
21448  * @ctxt:  a schema validation context
21449  * @err:  the error callback
21450  * @warn:  the warning callback
21451  * @ctx:  contextual data for the callbacks
21452  *
21453  * Set the callback functions used to handle errors for a validation context
21454  */
21455 void
xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,xmlSchemaValidityErrorFunc err,xmlSchemaValidityWarningFunc warn,void * ctx)21456 xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
21457                          xmlSchemaValidityErrorFunc err,
21458                          xmlSchemaValidityWarningFunc warn, void *ctx)
21459 {
21460     if (ctxt == NULL)
21461         return;
21462     ctxt->error = err;
21463     ctxt->warning = warn;
21464     ctxt->errCtxt = ctx;
21465     if (ctxt->vctxt != NULL)
21466 	xmlSchemaSetValidErrors(ctxt->vctxt, err, warn, ctx);
21467 }
21468 
21469 /**
21470  * xmlSchemaSetParserStructuredErrors:
21471  * @ctxt:  a schema parser context
21472  * @serror:  the structured error function
21473  * @ctx: the functions context
21474  *
21475  * Set the structured error callback
21476  */
21477 void
xmlSchemaSetParserStructuredErrors(xmlSchemaParserCtxtPtr ctxt,xmlStructuredErrorFunc serror,void * ctx)21478 xmlSchemaSetParserStructuredErrors(xmlSchemaParserCtxtPtr ctxt,
21479 				   xmlStructuredErrorFunc serror,
21480 				   void *ctx)
21481 {
21482     if (ctxt == NULL)
21483 	return;
21484     ctxt->serror = serror;
21485     ctxt->errCtxt = ctx;
21486     if (ctxt->vctxt != NULL)
21487 	xmlSchemaSetValidStructuredErrors(ctxt->vctxt, serror, ctx);
21488 }
21489 
21490 /**
21491  * xmlSchemaGetParserErrors:
21492  * @ctxt:  a XMl-Schema parser context
21493  * @err: the error callback result
21494  * @warn: the warning callback result
21495  * @ctx: contextual data for the callbacks result
21496  *
21497  * Get the callback information used to handle errors for a parser context
21498  *
21499  * Returns -1 in case of failure, 0 otherwise
21500  */
21501 int
xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,xmlSchemaValidityErrorFunc * err,xmlSchemaValidityWarningFunc * warn,void ** ctx)21502 xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
21503 			 xmlSchemaValidityErrorFunc * err,
21504 			 xmlSchemaValidityWarningFunc * warn, void **ctx)
21505 {
21506 	if (ctxt == NULL)
21507 		return(-1);
21508 	if (err != NULL)
21509 		*err = ctxt->error;
21510 	if (warn != NULL)
21511 		*warn = ctxt->warning;
21512 	if (ctx != NULL)
21513 		*ctx = ctxt->errCtxt;
21514 	return(0);
21515 }
21516 
21517 /**
21518  * xmlSchemaFacetTypeToString:
21519  * @type:  the facet type
21520  *
21521  * Convert the xmlSchemaTypeType to a char string.
21522  *
21523  * Returns the char string representation of the facet type if the
21524  *     type is a facet and an "Internal Error" string otherwise.
21525  */
21526 static const xmlChar *
xmlSchemaFacetTypeToString(xmlSchemaTypeType type)21527 xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
21528 {
21529     switch (type) {
21530         case XML_SCHEMA_FACET_PATTERN:
21531             return (BAD_CAST "pattern");
21532         case XML_SCHEMA_FACET_MAXEXCLUSIVE:
21533             return (BAD_CAST "maxExclusive");
21534         case XML_SCHEMA_FACET_MAXINCLUSIVE:
21535             return (BAD_CAST "maxInclusive");
21536         case XML_SCHEMA_FACET_MINEXCLUSIVE:
21537             return (BAD_CAST "minExclusive");
21538         case XML_SCHEMA_FACET_MININCLUSIVE:
21539             return (BAD_CAST "minInclusive");
21540         case XML_SCHEMA_FACET_WHITESPACE:
21541             return (BAD_CAST "whiteSpace");
21542         case XML_SCHEMA_FACET_ENUMERATION:
21543             return (BAD_CAST "enumeration");
21544         case XML_SCHEMA_FACET_LENGTH:
21545             return (BAD_CAST "length");
21546         case XML_SCHEMA_FACET_MAXLENGTH:
21547             return (BAD_CAST "maxLength");
21548         case XML_SCHEMA_FACET_MINLENGTH:
21549             return (BAD_CAST "minLength");
21550         case XML_SCHEMA_FACET_TOTALDIGITS:
21551             return (BAD_CAST "totalDigits");
21552         case XML_SCHEMA_FACET_FRACTIONDIGITS:
21553             return (BAD_CAST "fractionDigits");
21554         default:
21555             break;
21556     }
21557     return (BAD_CAST "Internal Error");
21558 }
21559 
21560 static xmlSchemaWhitespaceValueType
xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)21561 xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
21562 {
21563     /*
21564     * The normalization type can be changed only for types which are derived
21565     * from xsd:string.
21566     */
21567     if (type->type == XML_SCHEMA_TYPE_BASIC) {
21568 	/*
21569 	* Note that we assume a whitespace of preserve for anySimpleType.
21570 	*/
21571 	if ((type->builtInType == XML_SCHEMAS_STRING) ||
21572 	    (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
21573 	    return(XML_SCHEMA_WHITESPACE_PRESERVE);
21574 	else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
21575 	    return(XML_SCHEMA_WHITESPACE_REPLACE);
21576 	else {
21577 	    /*
21578 	    * For all `atomic` datatypes other than string (and types `derived`
21579 	    * by `restriction` from it) the value of whiteSpace is fixed to
21580 	    * collapse
21581 	    * Note that this includes built-in list datatypes.
21582 	    */
21583 	    return(XML_SCHEMA_WHITESPACE_COLLAPSE);
21584 	}
21585     } else if (WXS_IS_LIST(type)) {
21586 	/*
21587 	* For list types the facet "whiteSpace" is fixed to "collapse".
21588 	*/
21589 	return (XML_SCHEMA_WHITESPACE_COLLAPSE);
21590     } else if (WXS_IS_UNION(type)) {
21591 	return (XML_SCHEMA_WHITESPACE_UNKNOWN);
21592     } else if (WXS_IS_ATOMIC(type)) {
21593 	if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE)
21594 	    return (XML_SCHEMA_WHITESPACE_PRESERVE);
21595 	else if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_REPLACE)
21596 	    return (XML_SCHEMA_WHITESPACE_REPLACE);
21597 	else
21598 	    return (XML_SCHEMA_WHITESPACE_COLLAPSE);
21599     }
21600     return (-1);
21601 }
21602 
21603 /************************************************************************
21604  *									*
21605  *			Simple type validation				*
21606  *									*
21607  ************************************************************************/
21608 
21609 
21610 /************************************************************************
21611  *									*
21612  *			DOM Validation code				*
21613  *									*
21614  ************************************************************************/
21615 
21616 /**
21617  * xmlSchemaAssembleByLocation:
21618  * @pctxt:  a schema parser context
21619  * @vctxt:  a schema validation context
21620  * @schema: the existing schema
21621  * @node: the node that fired the assembling
21622  * @nsName: the namespace name of the new schema
21623  * @location: the location of the schema
21624  *
21625  * Expands an existing schema by an additional schema.
21626  *
21627  * Returns 0 if the new schema is correct, a positive error code
21628  * number otherwise and -1 in case of an internal or API error.
21629  */
21630 static int
xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,xmlSchemaPtr schema,xmlNodePtr node,const xmlChar * nsName,const xmlChar * location)21631 xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
21632 			    xmlSchemaPtr schema,
21633 			    xmlNodePtr node,
21634 			    const xmlChar *nsName,
21635 			    const xmlChar *location)
21636 {
21637     int ret = 0;
21638     xmlSchemaParserCtxtPtr pctxt;
21639     xmlSchemaBucketPtr bucket = NULL;
21640 
21641     if ((vctxt == NULL) || (schema == NULL))
21642 	return (-1);
21643 
21644     if (vctxt->pctxt == NULL) {
21645 	VERROR_INT("xmlSchemaAssembleByLocation",
21646 	    "no parser context available");
21647 	return(-1);
21648     }
21649     pctxt = vctxt->pctxt;
21650     if (pctxt->constructor == NULL) {
21651 	PERROR_INT("xmlSchemaAssembleByLocation",
21652 	    "no constructor");
21653 	return(-1);
21654     }
21655     /*
21656     * Acquire the schema document.
21657     */
21658     location = xmlSchemaBuildAbsoluteURI(pctxt->dict,
21659 	location, node);
21660     /*
21661     * Note that we pass XML_SCHEMA_SCHEMA_IMPORT here;
21662     * the process will automatically change this to
21663     * XML_SCHEMA_SCHEMA_MAIN if it is the first schema document.
21664     */
21665     ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
21666 	location, NULL, NULL, 0, node, NULL, nsName,
21667 	&bucket);
21668     if (ret != 0)
21669 	return(ret);
21670     if (bucket == NULL) {
21671 	/*
21672 	* Generate a warning that the document could not be located.
21673 	*/
21674 	xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC,
21675 	    node, NULL,
21676 	    "The document at location '%s' could not be acquired",
21677 	    location, NULL, NULL);
21678 	return(ret);
21679     }
21680     /*
21681     * The first located schema will be handled as if all other
21682     * schemas imported by XSI were imported by this first schema.
21683     */
21684     if ((bucket != NULL) &&
21685 	(WXS_CONSTRUCTOR(pctxt)->bucket == NULL))
21686 	WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
21687     /*
21688     * TODO: Is this handled like an import? I.e. is it not an error
21689     * if the schema cannot be located?
21690     */
21691     if ((bucket == NULL) || (! CAN_PARSE_SCHEMA(bucket)))
21692 	return(0);
21693     /*
21694     * We will reuse the parser context for every schema imported
21695     * directly via XSI. So reset the context.
21696     */
21697     pctxt->nberrors = 0;
21698     pctxt->err = 0;
21699     pctxt->doc = bucket->doc;
21700 
21701     ret = xmlSchemaParseNewDocWithContext(pctxt, schema, bucket);
21702     if (ret == -1) {
21703 	pctxt->doc = NULL;
21704 	goto exit_failure;
21705     }
21706     /* Paranoid error channelling. */
21707     if ((ret == 0) && (pctxt->nberrors != 0))
21708 	ret = pctxt->err;
21709     if (pctxt->nberrors == 0) {
21710 	/*
21711 	* Only bother to fixup pending components, if there was
21712 	* no error yet.
21713 	* For every XSI acquired schema (and its sub-schemata) we will
21714 	* fixup the components.
21715 	*/
21716 	xmlSchemaFixupComponents(pctxt, bucket);
21717 	ret = pctxt->err;
21718 	/*
21719 	* Not nice, but we need somehow to channel the schema parser
21720 	* error to the validation context.
21721 	*/
21722 	if ((ret != 0) && (vctxt->err == 0))
21723 	    vctxt->err = ret;
21724 	vctxt->nberrors += pctxt->nberrors;
21725     } else {
21726 	/* Add to validation error sum. */
21727 	vctxt->nberrors += pctxt->nberrors;
21728     }
21729     pctxt->doc = NULL;
21730     return(ret);
21731 exit_failure:
21732     pctxt->doc = NULL;
21733     return (-1);
21734 }
21735 
21736 static xmlSchemaAttrInfoPtr
xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,int metaType)21737 xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,
21738 			 int metaType)
21739 {
21740     if (vctxt->nbAttrInfos == 0)
21741 	return (NULL);
21742     {
21743 	int i;
21744 	xmlSchemaAttrInfoPtr iattr;
21745 
21746 	for (i = 0; i < vctxt->nbAttrInfos; i++) {
21747 	    iattr = vctxt->attrInfos[i];
21748 	    if (iattr->metaType == metaType)
21749 		return (iattr);
21750 	}
21751 
21752     }
21753     return (NULL);
21754 }
21755 
21756 /**
21757  * xmlSchemaAssembleByXSI:
21758  * @vctxt:  a schema validation context
21759  *
21760  * Expands an existing schema by an additional schema using
21761  * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
21762  * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
21763  * must be set to 1.
21764  *
21765  * Returns 0 if the new schema is correct, a positive error code
21766  * number otherwise and -1 in case of an internal or API error.
21767  */
21768 static int
xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)21769 xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)
21770 {
21771     const xmlChar *cur, *end;
21772     const xmlChar *nsname = NULL, *location;
21773     int count = 0;
21774     int ret = 0;
21775     xmlSchemaAttrInfoPtr iattr;
21776 
21777     /*
21778     * Parse the value; we will assume an even number of values
21779     * to be given (this is how Xerces and XSV work).
21780     *
21781     * URGENT TODO: !! This needs to work for both
21782     * @noNamespaceSchemaLocation AND @schemaLocation on the same
21783     * element !!
21784     */
21785     iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21786 	XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC);
21787     if (iattr == NULL)
21788 	iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21789 	XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC);
21790     if (iattr == NULL)
21791 	return (0);
21792     cur = iattr->value;
21793     do {
21794 	/*
21795 	* TODO: Move the string parsing mechanism away from here.
21796 	*/
21797 	if (iattr->metaType == XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC) {
21798 	    /*
21799 	    * Get the namespace name.
21800 	    */
21801 	    while (IS_BLANK_CH(*cur))
21802 		cur++;
21803 	    end = cur;
21804 	    while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21805 		end++;
21806 	    if (end == cur)
21807 		break;
21808 	    count++; /* TODO: Don't use the schema's dict. */
21809 	    nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
21810 	    cur = end;
21811 	}
21812 	/*
21813 	* Get the URI.
21814 	*/
21815 	while (IS_BLANK_CH(*cur))
21816 	    cur++;
21817 	end = cur;
21818 	while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21819 	    end++;
21820 	if (end == cur) {
21821 	    if (iattr->metaType ==
21822 		XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC)
21823 	    {
21824 		/*
21825 		* If using @schemaLocation then tuples are expected.
21826 		* I.e. the namespace name *and* the document's URI.
21827 		*/
21828 		xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC,
21829 		    iattr->node, NULL,
21830 		    "The value must consist of tuples: the target namespace "
21831 		    "name and the document's URI", NULL, NULL, NULL);
21832 	    }
21833 	    break;
21834 	}
21835 	count++; /* TODO: Don't use the schema's dict. */
21836 	location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
21837 	cur = end;
21838 	ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
21839 	    iattr->node, nsname, location);
21840 	if (ret == -1) {
21841 	    VERROR_INT("xmlSchemaAssembleByXSI",
21842 		"assembling schemata");
21843 	    return (-1);
21844 	}
21845     } while (*cur != 0);
21846     return (ret);
21847 }
21848 
21849 static const xmlChar *
xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,const xmlChar * prefix)21850 xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,
21851 			 const xmlChar *prefix)
21852 {
21853     if (vctxt->sax != NULL) {
21854 	int i, j;
21855 	xmlSchemaNodeInfoPtr inode;
21856 
21857 	for (i = vctxt->depth; i >= 0; i--) {
21858 	    if (vctxt->elemInfos[i]->nbNsBindings != 0) {
21859 		inode = vctxt->elemInfos[i];
21860 		for (j = 0; j < inode->nbNsBindings * 2; j += 2) {
21861 		    if (((prefix == NULL) &&
21862 			    (inode->nsBindings[j] == NULL)) ||
21863 			((prefix != NULL) && xmlStrEqual(prefix,
21864 			    inode->nsBindings[j]))) {
21865 
21866 			/*
21867 			* Note that the namespace bindings are already
21868 			* in a string dict.
21869 			*/
21870 			return (inode->nsBindings[j+1]);
21871 		    }
21872 		}
21873 	    }
21874 	}
21875 	return (NULL);
21876 #ifdef LIBXML_READER_ENABLED
21877     } else if (vctxt->reader != NULL) {
21878 	xmlChar *nsName;
21879 
21880 	nsName = xmlTextReaderLookupNamespace(vctxt->reader, prefix);
21881 	if (nsName != NULL) {
21882 	    const xmlChar *ret;
21883 
21884 	    ret = xmlDictLookup(vctxt->dict, nsName, -1);
21885 	    xmlFree(nsName);
21886 	    return (ret);
21887 	} else
21888 	    return (NULL);
21889 #endif
21890     } else {
21891 	xmlNsPtr ns;
21892 
21893 	if ((vctxt->inode->node == NULL) ||
21894 	    (vctxt->inode->node->doc == NULL)) {
21895 	    VERROR_INT("xmlSchemaLookupNamespace",
21896 		"no node or node's doc avaliable");
21897 	    return (NULL);
21898 	}
21899 	ns = xmlSearchNs(vctxt->inode->node->doc,
21900 	    vctxt->inode->node, prefix);
21901 	if (ns != NULL)
21902 	    return (ns->href);
21903 	return (NULL);
21904     }
21905 }
21906 
21907 /*
21908 * This one works on the schema of the validation context.
21909 */
21910 static int
xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,xmlSchemaPtr schema,xmlNodePtr node,const xmlChar * value,xmlSchemaValPtr * val,int valNeeded)21911 xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
21912 			  xmlSchemaPtr schema,
21913 			  xmlNodePtr node,
21914 			  const xmlChar *value,
21915 			  xmlSchemaValPtr *val,
21916 			  int valNeeded)
21917 {
21918     int ret;
21919 
21920     if (vctxt && (vctxt->schema == NULL)) {
21921 	VERROR_INT("xmlSchemaValidateNotation",
21922 	    "a schema is needed on the validation context");
21923 	return (-1);
21924     }
21925     ret = xmlValidateQName(value, 1);
21926     if (ret != 0)
21927 	return (ret);
21928     {
21929 	xmlChar *localName = NULL;
21930 	xmlChar *prefix = NULL;
21931 
21932 	localName = xmlSplitQName2(value, &prefix);
21933 	if (prefix != NULL) {
21934 	    const xmlChar *nsName = NULL;
21935 
21936 	    if (vctxt != NULL)
21937 		nsName = xmlSchemaLookupNamespace(vctxt, BAD_CAST prefix);
21938 	    else if (node != NULL) {
21939 		xmlNsPtr ns = xmlSearchNs(node->doc, node, prefix);
21940 		if (ns != NULL)
21941 		    nsName = ns->href;
21942 	    } else {
21943 		xmlFree(prefix);
21944 		xmlFree(localName);
21945 		return (1);
21946 	    }
21947 	    if (nsName == NULL) {
21948 		xmlFree(prefix);
21949 		xmlFree(localName);
21950 		return (1);
21951 	    }
21952 	    if (xmlSchemaGetNotation(schema, localName, nsName) != NULL) {
21953 		if ((valNeeded) && (val != NULL)) {
21954 		    (*val) = xmlSchemaNewNOTATIONValue(xmlStrdup(localName),
21955 						       xmlStrdup(nsName));
21956 		    if (*val == NULL)
21957 			ret = -1;
21958 		}
21959 	    } else
21960 		ret = 1;
21961 	    xmlFree(prefix);
21962 	    xmlFree(localName);
21963 	} else {
21964 	    if (xmlSchemaGetNotation(schema, value, NULL) != NULL) {
21965 		if (valNeeded && (val != NULL)) {
21966 		    (*val) = xmlSchemaNewNOTATIONValue(
21967 			BAD_CAST xmlStrdup(value), NULL);
21968 		    if (*val == NULL)
21969 			ret = -1;
21970 		}
21971 	    } else
21972 		return (1);
21973 	}
21974     }
21975     return (ret);
21976 }
21977 
21978 static int
xmlSchemaVAddNodeQName(xmlSchemaValidCtxtPtr vctxt,const xmlChar * lname,const xmlChar * nsname)21979 xmlSchemaVAddNodeQName(xmlSchemaValidCtxtPtr vctxt,
21980 		       const xmlChar* lname,
21981 		       const xmlChar* nsname)
21982 {
21983     int i;
21984 
21985     lname = xmlDictLookup(vctxt->dict, lname, -1);
21986     if (lname == NULL)
21987 	return(-1);
21988     if (nsname != NULL) {
21989 	nsname = xmlDictLookup(vctxt->dict, nsname, -1);
21990 	if (nsname == NULL)
21991 	    return(-1);
21992     }
21993     for (i = 0; i < vctxt->nodeQNames->nbItems; i += 2) {
21994 	if ((vctxt->nodeQNames->items [i] == lname) &&
21995 	    (vctxt->nodeQNames->items[i +1] == nsname))
21996 	    /* Already there */
21997 	    return(i);
21998     }
21999     /* Add new entry. */
22000     i = vctxt->nodeQNames->nbItems;
22001     xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) lname);
22002     xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) nsname);
22003     return(i);
22004 }
22005 
22006 /************************************************************************
22007  *									*
22008  *  Validation of identity-constraints (IDC)                            *
22009  *									*
22010  ************************************************************************/
22011 
22012 /**
22013  * xmlSchemaAugmentIDC:
22014  * @idcDef: the IDC definition
22015  *
22016  * Creates an augmented IDC definition item.
22017  *
22018  * Returns the item, or NULL on internal errors.
22019  */
22020 static void
xmlSchemaAugmentIDC(void * payload,void * data,const xmlChar * name ATTRIBUTE_UNUSED)22021 xmlSchemaAugmentIDC(void *payload, void *data,
22022                     const xmlChar *name ATTRIBUTE_UNUSED)
22023 {
22024     xmlSchemaIDCPtr idcDef = (xmlSchemaIDCPtr) payload;
22025     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) data;
22026     xmlSchemaIDCAugPtr aidc;
22027 
22028     aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
22029     if (aidc == NULL) {
22030 	xmlSchemaVErrMemory(vctxt,
22031 	    "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
22032 	    NULL);
22033 	return;
22034     }
22035     aidc->keyrefDepth = -1;
22036     aidc->def = idcDef;
22037     aidc->next = NULL;
22038     if (vctxt->aidcs == NULL)
22039 	vctxt->aidcs = aidc;
22040     else {
22041 	aidc->next = vctxt->aidcs;
22042 	vctxt->aidcs = aidc;
22043     }
22044     /*
22045     * Save if we have keyrefs at all.
22046     */
22047     if ((vctxt->hasKeyrefs == 0) &&
22048 	(idcDef->type == XML_SCHEMA_TYPE_IDC_KEYREF))
22049 	vctxt->hasKeyrefs = 1;
22050 }
22051 
22052 /**
22053  * xmlSchemaAugmentImportedIDC:
22054  * @imported: the imported schema
22055  *
22056  * Creates an augmented IDC definition for the imported schema.
22057  */
22058 static void
xmlSchemaAugmentImportedIDC(void * payload,void * data,const xmlChar * name ATTRIBUTE_UNUSED)22059 xmlSchemaAugmentImportedIDC(void *payload, void *data,
22060                             const xmlChar *name ATTRIBUTE_UNUSED) {
22061     xmlSchemaImportPtr imported = (xmlSchemaImportPtr) payload;
22062     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) data;
22063     if (imported->schema->idcDef != NULL) {
22064 	    xmlHashScan(imported->schema->idcDef, xmlSchemaAugmentIDC, vctxt);
22065     }
22066 }
22067 
22068 /**
22069  * xmlSchemaIDCNewBinding:
22070  * @idcDef: the IDC definition of this binding
22071  *
22072  * Creates a new IDC binding.
22073  *
22074  * Returns the new IDC binding, NULL on internal errors.
22075  */
22076 static xmlSchemaPSVIIDCBindingPtr
xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)22077 xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
22078 {
22079     xmlSchemaPSVIIDCBindingPtr ret;
22080 
22081     ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
22082 	    sizeof(xmlSchemaPSVIIDCBinding));
22083     if (ret == NULL) {
22084 	xmlSchemaVErrMemory(NULL,
22085 	    "allocating a PSVI IDC binding item", NULL);
22086 	return (NULL);
22087     }
22088     memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
22089     ret->definition = idcDef;
22090     return (ret);
22091 }
22092 
22093 /**
22094  * xmlSchemaIDCStoreNodeTableItem:
22095  * @vctxt: the WXS validation context
22096  * @item: the IDC node table item
22097  *
22098  * The validation context is used to store IDC node table items.
22099  * They are stored to avoid copying them if IDC node-tables are merged
22100  * with corresponding parent IDC node-tables (bubbling).
22101  *
22102  * Returns 0 if succeeded, -1 on internal errors.
22103  */
22104 static int
xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,xmlSchemaPSVIIDCNodePtr item)22105 xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
22106 			       xmlSchemaPSVIIDCNodePtr item)
22107 {
22108     /*
22109     * Add to gobal list.
22110     */
22111     if (vctxt->idcNodes == NULL) {
22112 	vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
22113 	    xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
22114 	if (vctxt->idcNodes == NULL) {
22115 	    xmlSchemaVErrMemory(vctxt,
22116 		"allocating the IDC node table item list", NULL);
22117 	    return (-1);
22118 	}
22119 	vctxt->sizeIdcNodes = 20;
22120     } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
22121 	vctxt->sizeIdcNodes *= 2;
22122 	vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
22123 	    xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
22124 	    sizeof(xmlSchemaPSVIIDCNodePtr));
22125 	if (vctxt->idcNodes == NULL) {
22126 	    xmlSchemaVErrMemory(vctxt,
22127 		"re-allocating the IDC node table item list", NULL);
22128 	    return (-1);
22129 	}
22130     }
22131     vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
22132 
22133     return (0);
22134 }
22135 
22136 /**
22137  * xmlSchemaIDCStoreKey:
22138  * @vctxt: the WXS validation context
22139  * @item: the IDC key
22140  *
22141  * The validation context is used to store an IDC key.
22142  *
22143  * Returns 0 if succeeded, -1 on internal errors.
22144  */
22145 static int
xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,xmlSchemaPSVIIDCKeyPtr key)22146 xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
22147 		     xmlSchemaPSVIIDCKeyPtr key)
22148 {
22149     /*
22150     * Add to gobal list.
22151     */
22152     if (vctxt->idcKeys == NULL) {
22153 	vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
22154 	    xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
22155 	if (vctxt->idcKeys == NULL) {
22156 	    xmlSchemaVErrMemory(vctxt,
22157 		"allocating the IDC key storage list", NULL);
22158 	    return (-1);
22159 	}
22160 	vctxt->sizeIdcKeys = 40;
22161     } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
22162 	vctxt->sizeIdcKeys *= 2;
22163 	vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
22164 	    xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
22165 	    sizeof(xmlSchemaPSVIIDCKeyPtr));
22166 	if (vctxt->idcKeys == NULL) {
22167 	    xmlSchemaVErrMemory(vctxt,
22168 		"re-allocating the IDC key storage list", NULL);
22169 	    return (-1);
22170 	}
22171     }
22172     vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
22173 
22174     return (0);
22175 }
22176 
22177 /**
22178  * xmlSchemaIDCAppendNodeTableItem:
22179  * @bind: the IDC binding
22180  * @ntItem: the node-table item
22181  *
22182  * Appends the IDC node-table item to the binding.
22183  *
22184  * Returns 0 on success and -1 on internal errors.
22185  */
22186 static int
xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,xmlSchemaPSVIIDCNodePtr ntItem)22187 xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
22188 				xmlSchemaPSVIIDCNodePtr ntItem)
22189 {
22190     if (bind->nodeTable == NULL) {
22191 	bind->sizeNodes = 10;
22192 	bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
22193 	    xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
22194 	if (bind->nodeTable == NULL) {
22195 	    xmlSchemaVErrMemory(NULL,
22196 		"allocating an array of IDC node-table items", NULL);
22197 	    return(-1);
22198 	}
22199     } else if (bind->sizeNodes <= bind->nbNodes) {
22200 	bind->sizeNodes *= 2;
22201 	bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
22202 	    xmlRealloc(bind->nodeTable, bind->sizeNodes *
22203 		sizeof(xmlSchemaPSVIIDCNodePtr));
22204 	if (bind->nodeTable == NULL) {
22205 	    xmlSchemaVErrMemory(NULL,
22206 		"re-allocating an array of IDC node-table items", NULL);
22207 	    return(-1);
22208 	}
22209     }
22210     bind->nodeTable[bind->nbNodes++] = ntItem;
22211     return(0);
22212 }
22213 
22214 /**
22215  * xmlSchemaIDCAcquireBinding:
22216  * @vctxt: the WXS validation context
22217  * @matcher: the IDC matcher
22218  *
22219  * Looks up an PSVI IDC binding, for the IDC definition and
22220  * of the given matcher. If none found, a new one is created
22221  * and added to the IDC table.
22222  *
22223  * Returns an IDC binding or NULL on internal errors.
22224  */
22225 static xmlSchemaPSVIIDCBindingPtr
xmlSchemaIDCAcquireBinding(xmlSchemaValidCtxtPtr vctxt,xmlSchemaIDCMatcherPtr matcher)22226 xmlSchemaIDCAcquireBinding(xmlSchemaValidCtxtPtr vctxt,
22227 			  xmlSchemaIDCMatcherPtr matcher)
22228 {
22229     xmlSchemaNodeInfoPtr ielem;
22230 
22231     ielem = vctxt->elemInfos[matcher->depth];
22232 
22233     if (ielem->idcTable == NULL) {
22234 	ielem->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
22235 	if (ielem->idcTable == NULL)
22236 	    return (NULL);
22237 	return(ielem->idcTable);
22238     } else {
22239 	xmlSchemaPSVIIDCBindingPtr bind = NULL;
22240 
22241 	bind = ielem->idcTable;
22242 	do {
22243 	    if (bind->definition == matcher->aidc->def)
22244 		return(bind);
22245 	    if (bind->next == NULL) {
22246 		bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
22247 		if (bind->next == NULL)
22248 		    return (NULL);
22249 		return(bind->next);
22250 	    }
22251 	    bind = bind->next;
22252 	} while (bind != NULL);
22253     }
22254     return (NULL);
22255 }
22256 
22257 static xmlSchemaItemListPtr
xmlSchemaIDCAcquireTargetList(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,xmlSchemaIDCMatcherPtr matcher)22258 xmlSchemaIDCAcquireTargetList(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
22259 			     xmlSchemaIDCMatcherPtr matcher)
22260 {
22261     if (matcher->targets == NULL)
22262 	matcher->targets = xmlSchemaItemListCreate();
22263     return(matcher->targets);
22264 }
22265 
22266 /**
22267  * xmlSchemaIDCFreeKey:
22268  * @key: the IDC key
22269  *
22270  * Frees an IDC key together with its compiled value.
22271  */
22272 static void
xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)22273 xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
22274 {
22275     if (key->val != NULL)
22276 	xmlSchemaFreeValue(key->val);
22277     xmlFree(key);
22278 }
22279 
22280 /**
22281  * xmlSchemaIDCFreeBinding:
22282  *
22283  * Frees an IDC binding. Note that the node table-items
22284  * are not freed.
22285  */
22286 static void
xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)22287 xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
22288 {
22289     if (bind->nodeTable != NULL)
22290 	xmlFree(bind->nodeTable);
22291     if (bind->dupls != NULL)
22292 	xmlSchemaItemListFree(bind->dupls);
22293     xmlFree(bind);
22294 }
22295 
22296 /**
22297  * xmlSchemaIDCFreeIDCTable:
22298  * @bind: the first IDC binding in the list
22299  *
22300  * Frees an IDC table, i.e. all the IDC bindings in the list.
22301  */
22302 static void
xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)22303 xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
22304 {
22305     xmlSchemaPSVIIDCBindingPtr prev;
22306 
22307     while (bind != NULL) {
22308 	prev = bind;
22309 	bind = bind->next;
22310 	xmlSchemaIDCFreeBinding(prev);
22311     }
22312 }
22313 
22314 /**
22315  * xmlSchemaIDCFreeMatcherList:
22316  * @matcher: the first IDC matcher in the list
22317  *
22318  * Frees a list of IDC matchers.
22319  */
22320 static void
xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)22321 xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
22322 {
22323     xmlSchemaIDCMatcherPtr next;
22324 
22325     while (matcher != NULL) {
22326 	next = matcher->next;
22327 	if (matcher->keySeqs != NULL) {
22328 	    int i;
22329 	    for (i = 0; i < matcher->sizeKeySeqs; i++)
22330 		if (matcher->keySeqs[i] != NULL)
22331 		    xmlFree(matcher->keySeqs[i]);
22332 	    xmlFree(matcher->keySeqs);
22333 	}
22334 	if (matcher->targets != NULL) {
22335 	    if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
22336 		int i;
22337 		xmlSchemaPSVIIDCNodePtr idcNode;
22338 		/*
22339 		* Node-table items for keyrefs are not stored globally
22340 		* to the validation context, since they are not bubbled.
22341 		* We need to free them here.
22342 		*/
22343 		for (i = 0; i < matcher->targets->nbItems; i++) {
22344 		    idcNode =
22345 			(xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
22346 		    xmlFree(idcNode->keys);
22347 		    xmlFree(idcNode);
22348 		}
22349 	    }
22350 	    xmlSchemaItemListFree(matcher->targets);
22351 	}
22352 	xmlFree(matcher);
22353 	matcher = next;
22354     }
22355 }
22356 
22357 /**
22358  * xmlSchemaIDCReleaseMatcherList:
22359  * @vctxt: the WXS validation context
22360  * @matcher: the first IDC matcher in the list
22361  *
22362  * Caches a list of IDC matchers for reuse.
22363  */
22364 static void
xmlSchemaIDCReleaseMatcherList(xmlSchemaValidCtxtPtr vctxt,xmlSchemaIDCMatcherPtr matcher)22365 xmlSchemaIDCReleaseMatcherList(xmlSchemaValidCtxtPtr vctxt,
22366 			       xmlSchemaIDCMatcherPtr matcher)
22367 {
22368     xmlSchemaIDCMatcherPtr next;
22369 
22370     while (matcher != NULL) {
22371 	next = matcher->next;
22372 	if (matcher->keySeqs != NULL) {
22373 	    int i;
22374 	    /*
22375 	    * Don't free the array, but only the content.
22376 	    */
22377 	    for (i = 0; i < matcher->sizeKeySeqs; i++)
22378 		if (matcher->keySeqs[i] != NULL) {
22379 		    xmlFree(matcher->keySeqs[i]);
22380 		    matcher->keySeqs[i] = NULL;
22381 		}
22382 	}
22383 	if (matcher->targets) {
22384 	    if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
22385 		int i;
22386 		xmlSchemaPSVIIDCNodePtr idcNode;
22387 		/*
22388 		* Node-table items for keyrefs are not stored globally
22389 		* to the validation context, since they are not bubbled.
22390 		* We need to free them here.
22391 		*/
22392 		for (i = 0; i < matcher->targets->nbItems; i++) {
22393 		    idcNode =
22394 			(xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
22395 		    xmlFree(idcNode->keys);
22396 		    xmlFree(idcNode);
22397 		}
22398 	    }
22399 	    xmlSchemaItemListFree(matcher->targets);
22400 	    matcher->targets = NULL;
22401 	}
22402 	matcher->next = NULL;
22403 	/*
22404 	* Cache the matcher.
22405 	*/
22406 	if (vctxt->idcMatcherCache != NULL)
22407 	    matcher->nextCached = vctxt->idcMatcherCache;
22408 	vctxt->idcMatcherCache = matcher;
22409 
22410 	matcher = next;
22411     }
22412 }
22413 
22414 /**
22415  * xmlSchemaIDCAddStateObject:
22416  * @vctxt: the WXS validation context
22417  * @matcher: the IDC matcher
22418  * @sel: the XPath information
22419  * @parent: the parent "selector" state object if any
22420  * @type: "selector" or "field"
22421  *
22422  * Creates/reuses and activates state objects for the given
22423  * XPath information; if the XPath expression consists of unions,
22424  * multiple state objects are created for every unioned expression.
22425  *
22426  * Returns 0 on success and -1 on internal errors.
22427  */
22428 static int
xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,xmlSchemaIDCMatcherPtr matcher,xmlSchemaIDCSelectPtr sel,int type)22429 xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
22430 			xmlSchemaIDCMatcherPtr matcher,
22431 			xmlSchemaIDCSelectPtr sel,
22432 			int type)
22433 {
22434     xmlSchemaIDCStateObjPtr sto;
22435 
22436     /*
22437     * Reuse the state objects from the pool.
22438     */
22439     if (vctxt->xpathStatePool != NULL) {
22440 	sto = vctxt->xpathStatePool;
22441 	vctxt->xpathStatePool = sto->next;
22442 	sto->next = NULL;
22443     } else {
22444 	/*
22445 	* Create a new state object.
22446 	*/
22447 	sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
22448 	if (sto == NULL) {
22449 	    xmlSchemaVErrMemory(NULL,
22450 		"allocating an IDC state object", NULL);
22451 	    return (-1);
22452 	}
22453 	memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
22454     }
22455     /*
22456     * Add to global list.
22457     */
22458     if (vctxt->xpathStates != NULL)
22459 	sto->next = vctxt->xpathStates;
22460     vctxt->xpathStates = sto;
22461 
22462     /*
22463     * Free the old xpath validation context.
22464     */
22465     if (sto->xpathCtxt != NULL)
22466 	xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
22467 
22468     /*
22469     * Create a new XPath (pattern) validation context.
22470     */
22471     sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
22472 	(xmlPatternPtr) sel->xpathComp);
22473     if (sto->xpathCtxt == NULL) {
22474 	VERROR_INT("xmlSchemaIDCAddStateObject",
22475 	    "failed to create an XPath validation context");
22476 	return (-1);
22477     }
22478     sto->type = type;
22479     sto->depth = vctxt->depth;
22480     sto->matcher = matcher;
22481     sto->sel = sel;
22482     sto->nbHistory = 0;
22483 
22484 #ifdef DEBUG_IDC
22485     xmlGenericError(xmlGenericErrorContext, "IDC:   STO push '%s'\n",
22486 	sto->sel->xpath);
22487 #endif
22488     return (0);
22489 }
22490 
22491 /**
22492  * xmlSchemaXPathEvaluate:
22493  * @vctxt: the WXS validation context
22494  * @nodeType: the nodeType of the current node
22495  *
22496  * Evaluates all active XPath state objects.
22497  *
22498  * Returns the number of IC "field" state objects which resolved to
22499  * this node, 0 if none resolved and -1 on internal errors.
22500  */
22501 static int
xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,xmlElementType nodeType)22502 xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
22503 		       xmlElementType nodeType)
22504 {
22505     xmlSchemaIDCStateObjPtr sto, head = NULL, first;
22506     int res, resolved = 0, depth = vctxt->depth;
22507 
22508     if (vctxt->xpathStates == NULL)
22509 	return (0);
22510 
22511     if (nodeType == XML_ATTRIBUTE_NODE)
22512 	depth++;
22513 #ifdef DEBUG_IDC
22514     {
22515 	xmlChar *str = NULL;
22516 	xmlGenericError(xmlGenericErrorContext,
22517 	    "IDC: EVAL on %s, depth %d, type %d\n",
22518 	    xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22519 		vctxt->inode->localName), depth, nodeType);
22520 	FREE_AND_NULL(str)
22521     }
22522 #endif
22523     /*
22524     * Process all active XPath state objects.
22525     */
22526     first = vctxt->xpathStates;
22527     sto = first;
22528     while (sto != head) {
22529 #ifdef DEBUG_IDC
22530 	if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
22531 	    xmlGenericError(xmlGenericErrorContext, "IDC:   ['%s'] selector '%s'\n",
22532 		sto->matcher->aidc->def->name, sto->sel->xpath);
22533 	else
22534 	    xmlGenericError(xmlGenericErrorContext, "IDC:   ['%s'] field '%s'\n",
22535 		sto->matcher->aidc->def->name, sto->sel->xpath);
22536 #endif
22537 	if (nodeType == XML_ELEMENT_NODE)
22538 	    res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
22539 		vctxt->inode->localName, vctxt->inode->nsName);
22540 	else
22541 	    res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
22542 		vctxt->inode->localName, vctxt->inode->nsName);
22543 
22544 	if (res == -1) {
22545 	    VERROR_INT("xmlSchemaXPathEvaluate",
22546 		"calling xmlStreamPush()");
22547 	    return (-1);
22548 	}
22549 	if (res == 0)
22550 	    goto next_sto;
22551 	/*
22552 	* Full match.
22553 	*/
22554 #ifdef DEBUG_IDC
22555 	xmlGenericError(xmlGenericErrorContext, "IDC:     "
22556 	    "MATCH\n");
22557 #endif
22558 	/*
22559 	* Register a match in the state object history.
22560 	*/
22561 	if (sto->history == NULL) {
22562 	    sto->history = (int *) xmlMalloc(5 * sizeof(int));
22563 	    if (sto->history == NULL) {
22564 		xmlSchemaVErrMemory(NULL,
22565 		    "allocating the state object history", NULL);
22566 		return(-1);
22567 	    }
22568 	    sto->sizeHistory = 5;
22569 	} else if (sto->sizeHistory <= sto->nbHistory) {
22570 	    sto->sizeHistory *= 2;
22571 	    sto->history = (int *) xmlRealloc(sto->history,
22572 		sto->sizeHistory * sizeof(int));
22573 	    if (sto->history == NULL) {
22574 		xmlSchemaVErrMemory(NULL,
22575 		    "re-allocating the state object history", NULL);
22576 		return(-1);
22577 	    }
22578 	}
22579 	sto->history[sto->nbHistory++] = depth;
22580 
22581 #ifdef DEBUG_IDC
22582 	xmlGenericError(xmlGenericErrorContext, "IDC:       push match '%d'\n",
22583 	    vctxt->depth);
22584 #endif
22585 
22586 	if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
22587 	    xmlSchemaIDCSelectPtr sel;
22588 	    /*
22589 	    * Activate state objects for the IDC fields of
22590 	    * the IDC selector.
22591 	    */
22592 #ifdef DEBUG_IDC
22593 	    xmlGenericError(xmlGenericErrorContext, "IDC:     "
22594 		"activating field states\n");
22595 #endif
22596 	    sel = sto->matcher->aidc->def->fields;
22597 	    while (sel != NULL) {
22598 		if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
22599 		    sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
22600 		    return (-1);
22601 		sel = sel->next;
22602 	    }
22603 	} else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22604 	    /*
22605 	    * An IDC key node was found by the IDC field.
22606 	    */
22607 #ifdef DEBUG_IDC
22608 	    xmlGenericError(xmlGenericErrorContext,
22609 		"IDC:     key found\n");
22610 #endif
22611 	    /*
22612 	    * Notify that the character value of this node is
22613 	    * needed.
22614 	    */
22615 	    if (resolved == 0) {
22616 		if ((vctxt->inode->flags &
22617 		    XML_SCHEMA_NODE_INFO_VALUE_NEEDED) == 0)
22618 		vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
22619 	    }
22620 	    resolved++;
22621 	}
22622 next_sto:
22623 	if (sto->next == NULL) {
22624 	    /*
22625 	    * Evaluate field state objects created on this node as well.
22626 	    */
22627 	    head = first;
22628 	    sto = vctxt->xpathStates;
22629 	} else
22630 	    sto = sto->next;
22631     }
22632     return (resolved);
22633 }
22634 
22635 static const xmlChar *
xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,xmlChar ** buf,xmlSchemaPSVIIDCKeyPtr * seq,int count)22636 xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,
22637 			      xmlChar **buf,
22638 			      xmlSchemaPSVIIDCKeyPtr *seq,
22639 			      int count)
22640 {
22641     int i, res;
22642     xmlChar *value = NULL;
22643 
22644     *buf = xmlStrdup(BAD_CAST "[");
22645     for (i = 0; i < count; i++) {
22646 	*buf = xmlStrcat(*buf, BAD_CAST "'");
22647 	res = xmlSchemaGetCanonValueWhtspExt(seq[i]->val,
22648 	    xmlSchemaGetWhiteSpaceFacetValue(seq[i]->type),
22649 	    &value);
22650 	if (res == 0)
22651 	    *buf = xmlStrcat(*buf, BAD_CAST value);
22652 	else {
22653 	    VERROR_INT("xmlSchemaFormatIDCKeySequence",
22654 		"failed to compute a canonical value");
22655 	    *buf = xmlStrcat(*buf, BAD_CAST "???");
22656 	}
22657 	if (i < count -1)
22658 	    *buf = xmlStrcat(*buf, BAD_CAST "', ");
22659 	else
22660 	    *buf = xmlStrcat(*buf, BAD_CAST "'");
22661 	if (value != NULL) {
22662 	    xmlFree(value);
22663 	    value = NULL;
22664 	}
22665     }
22666     *buf = xmlStrcat(*buf, BAD_CAST "]");
22667 
22668     return (BAD_CAST *buf);
22669 }
22670 
22671 /**
22672  * xmlSchemaXPathPop:
22673  * @vctxt: the WXS validation context
22674  *
22675  * Pops all XPath states.
22676  *
22677  * Returns 0 on success and -1 on internal errors.
22678  */
22679 static int
xmlSchemaXPathPop(xmlSchemaValidCtxtPtr vctxt)22680 xmlSchemaXPathPop(xmlSchemaValidCtxtPtr vctxt)
22681 {
22682     xmlSchemaIDCStateObjPtr sto;
22683     int res;
22684 
22685     if (vctxt->xpathStates == NULL)
22686 	return(0);
22687     sto = vctxt->xpathStates;
22688     do {
22689 	res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22690 	if (res == -1)
22691 	    return (-1);
22692 	sto = sto->next;
22693     } while (sto != NULL);
22694     return(0);
22695 }
22696 
22697 /**
22698  * xmlSchemaXPathProcessHistory:
22699  * @vctxt: the WXS validation context
22700  * @type: the simple/complex type of the current node if any at all
22701  * @val: the precompiled value
22702  *
22703  * Processes and pops the history items of the IDC state objects.
22704  * IDC key-sequences are validated/created on IDC bindings.
22705  *
22706  * Returns 0 on success and -1 on internal errors.
22707  */
22708 static int
xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,int depth)22709 xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
22710 			     int depth)
22711 {
22712     xmlSchemaIDCStateObjPtr sto, nextsto;
22713     int res, matchDepth;
22714     xmlSchemaPSVIIDCKeyPtr key = NULL;
22715     xmlSchemaTypePtr type = vctxt->inode->typeDef, simpleType = NULL;
22716 
22717     if (vctxt->xpathStates == NULL)
22718 	return (0);
22719     sto = vctxt->xpathStates;
22720 
22721 #ifdef DEBUG_IDC
22722     {
22723 	xmlChar *str = NULL;
22724 	xmlGenericError(xmlGenericErrorContext,
22725 	    "IDC: BACK on %s, depth %d\n",
22726 	    xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22727 		vctxt->inode->localName), vctxt->depth);
22728 	FREE_AND_NULL(str)
22729     }
22730 #endif
22731     /*
22732     * Evaluate the state objects.
22733     */
22734     while (sto != NULL) {
22735 	res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22736 	if (res == -1) {
22737 	    VERROR_INT("xmlSchemaXPathProcessHistory",
22738 		"calling xmlStreamPop()");
22739 	    return (-1);
22740 	}
22741 #ifdef DEBUG_IDC
22742 	xmlGenericError(xmlGenericErrorContext, "IDC:   stream pop '%s'\n",
22743 	    sto->sel->xpath);
22744 #endif
22745 	if (sto->nbHistory == 0)
22746 	    goto deregister_check;
22747 
22748 	matchDepth = sto->history[sto->nbHistory -1];
22749 
22750 	/*
22751 	* Only matches at the current depth are of interest.
22752 	*/
22753 	if (matchDepth != depth) {
22754 	    sto = sto->next;
22755 	    continue;
22756 	}
22757 	if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22758 	    /*
22759 	    * NOTE: According to
22760 	    *   http://www.w3.org/Bugs/Public/show_bug.cgi?id=2198
22761 	    *   ... the simple-content of complex types is also allowed.
22762 	    */
22763 
22764 	    if (WXS_IS_COMPLEX(type)) {
22765 		if (WXS_HAS_SIMPLE_CONTENT(type)) {
22766 		    /*
22767 		    * Sanity check for complex types with simple content.
22768 		    */
22769 		    simpleType = type->contentTypeDef;
22770 		    if (simpleType == NULL) {
22771 			VERROR_INT("xmlSchemaXPathProcessHistory",
22772 			    "field resolves to a CT with simple content "
22773 			    "but the CT is missing the ST definition");
22774 			return (-1);
22775 		    }
22776 		} else
22777 		    simpleType = NULL;
22778 	    } else
22779 		simpleType = type;
22780 	    if (simpleType == NULL) {
22781 		xmlChar *str = NULL;
22782 
22783 		/*
22784 		* Not qualified if the field resolves to a node of non
22785 		* simple type.
22786 		*/
22787 		xmlSchemaCustomErr(ACTXT_CAST vctxt,
22788 		    XML_SCHEMAV_CVC_IDC, NULL,
22789 		    WXS_BASIC_CAST sto->matcher->aidc->def,
22790 		    "The XPath '%s' of a field of %s does evaluate to a node of "
22791 		    "non-simple type",
22792 		    sto->sel->xpath,
22793 		    xmlSchemaGetIDCDesignation(&str, sto->matcher->aidc->def));
22794 		FREE_AND_NULL(str);
22795 		sto->nbHistory--;
22796 		goto deregister_check;
22797 	    }
22798 
22799 	    if ((key == NULL) && (vctxt->inode->val == NULL)) {
22800 		/*
22801 		* Failed to provide the normalized value; maybe
22802 		* the value was invalid.
22803 		*/
22804 		VERROR(XML_SCHEMAV_CVC_IDC,
22805 		    WXS_BASIC_CAST sto->matcher->aidc->def,
22806 		    "Warning: No precomputed value available, the value "
22807 		    "was either invalid or something strange happend");
22808 		sto->nbHistory--;
22809 		goto deregister_check;
22810 	    } else {
22811 		xmlSchemaIDCMatcherPtr matcher = sto->matcher;
22812 		xmlSchemaPSVIIDCKeyPtr *keySeq;
22813 		int pos, idx;
22814 
22815 		/*
22816 		* The key will be anchored on the matcher's list of
22817 		* key-sequences. The position in this list is determined
22818 		* by the target node's depth relative to the matcher's
22819 		* depth of creation (i.e. the depth of the scope element).
22820 		*
22821 		* Element        Depth    Pos   List-entries
22822 		* <scope>          0              NULL
22823 		*   <bar>          1              NULL
22824 		*     <target/>    2       2      target
22825 		*   <bar>
22826                 * </scope>
22827 		*
22828 		* The size of the list is only dependant on the depth of
22829 		* the tree.
22830 		* An entry will be NULLed in selector_leave, i.e. when
22831 		* we hit the target's
22832 		*/
22833 		pos = sto->depth - matcher->depth;
22834 		idx = sto->sel->index;
22835 
22836 		/*
22837 		* Create/grow the array of key-sequences.
22838 		*/
22839 		if (matcher->keySeqs == NULL) {
22840 		    if (pos > 9)
22841 			matcher->sizeKeySeqs = pos * 2;
22842 		    else
22843 			matcher->sizeKeySeqs = 10;
22844 		    matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22845 			xmlMalloc(matcher->sizeKeySeqs *
22846 			sizeof(xmlSchemaPSVIIDCKeyPtr *));
22847 		    if (matcher->keySeqs == NULL) {
22848 			xmlSchemaVErrMemory(NULL,
22849 			    "allocating an array of key-sequences",
22850 			    NULL);
22851 			return(-1);
22852 		    }
22853 		    memset(matcher->keySeqs, 0,
22854 			matcher->sizeKeySeqs *
22855 			sizeof(xmlSchemaPSVIIDCKeyPtr *));
22856 		} else if (pos >= matcher->sizeKeySeqs) {
22857 		    int i = matcher->sizeKeySeqs;
22858 
22859 		    matcher->sizeKeySeqs *= 2;
22860 		    matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22861 			xmlRealloc(matcher->keySeqs,
22862 			matcher->sizeKeySeqs *
22863 			sizeof(xmlSchemaPSVIIDCKeyPtr *));
22864 		    if (matcher->keySeqs == NULL) {
22865 			xmlSchemaVErrMemory(NULL,
22866 			    "reallocating an array of key-sequences",
22867 			    NULL);
22868 			return (-1);
22869 		    }
22870 		    /*
22871 		    * The array needs to be NULLed.
22872 		    * TODO: Use memset?
22873 		    */
22874 		    for (; i < matcher->sizeKeySeqs; i++)
22875 			matcher->keySeqs[i] = NULL;
22876 		}
22877 
22878 		/*
22879 		* Get/create the key-sequence.
22880 		*/
22881 		keySeq = matcher->keySeqs[pos];
22882 		if (keySeq == NULL) {
22883 		    goto create_sequence;
22884 		} else if (keySeq[idx] != NULL) {
22885 		    xmlChar *str = NULL;
22886 		    /*
22887 		    * cvc-identity-constraint:
22888 		    * 3 For each node in the `target node set` all
22889 		    * of the {fields}, with that node as the context
22890 		    * node, evaluate to either an empty node-set or
22891 		    * a node-set with exactly one member, which must
22892 		    * have a simple type.
22893 		    *
22894 		    * The key was already set; report an error.
22895 		    */
22896 		    xmlSchemaCustomErr(ACTXT_CAST vctxt,
22897 			XML_SCHEMAV_CVC_IDC, NULL,
22898 			WXS_BASIC_CAST matcher->aidc->def,
22899 			"The XPath '%s' of a field of %s evaluates to a "
22900 			"node-set with more than one member",
22901 			sto->sel->xpath,
22902 			xmlSchemaGetIDCDesignation(&str, matcher->aidc->def));
22903 		    FREE_AND_NULL(str);
22904 		    sto->nbHistory--;
22905 		    goto deregister_check;
22906 		} else
22907 		    goto create_key;
22908 
22909 create_sequence:
22910 		/*
22911 		* Create a key-sequence.
22912 		*/
22913 		keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
22914 		    matcher->aidc->def->nbFields *
22915 		    sizeof(xmlSchemaPSVIIDCKeyPtr));
22916 		if (keySeq == NULL) {
22917 		    xmlSchemaVErrMemory(NULL,
22918 			"allocating an IDC key-sequence", NULL);
22919 		    return(-1);
22920 		}
22921 		memset(keySeq, 0, matcher->aidc->def->nbFields *
22922 		    sizeof(xmlSchemaPSVIIDCKeyPtr));
22923 		matcher->keySeqs[pos] = keySeq;
22924 create_key:
22925 		/*
22926 		* Create a key once per node only.
22927 		*/
22928 		if (key == NULL) {
22929 		    key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
22930 			sizeof(xmlSchemaPSVIIDCKey));
22931 		    if (key == NULL) {
22932 			xmlSchemaVErrMemory(NULL,
22933 			    "allocating a IDC key", NULL);
22934 			xmlFree(keySeq);
22935 			matcher->keySeqs[pos] = NULL;
22936 			return(-1);
22937 		    }
22938 		    /*
22939 		    * Consume the compiled value.
22940 		    */
22941 		    key->type = simpleType;
22942 		    key->val = vctxt->inode->val;
22943 		    vctxt->inode->val = NULL;
22944 		    /*
22945 		    * Store the key in a global list.
22946 		    */
22947 		    if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
22948 			xmlSchemaIDCFreeKey(key);
22949 			return (-1);
22950 		    }
22951 		}
22952 		keySeq[idx] = key;
22953 	    }
22954 	} else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
22955 
22956 	    xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
22957 	    /* xmlSchemaPSVIIDCBindingPtr bind; */
22958 	    xmlSchemaPSVIIDCNodePtr ntItem;
22959 	    xmlSchemaIDCMatcherPtr matcher;
22960 	    xmlSchemaIDCPtr idc;
22961 	    xmlSchemaItemListPtr targets;
22962 	    int pos, i, j, nbKeys;
22963 	    /*
22964 	    * Here we have the following scenario:
22965 	    * An IDC 'selector' state object resolved to a target node,
22966 	    * during the time this target node was in the
22967 	    * ancestor-or-self axis, the 'field' state object(s) looked
22968 	    * out for matching nodes to create a key-sequence for this
22969 	    * target node. Now we are back to this target node and need
22970 	    * to put the key-sequence, together with the target node
22971 	    * itself, into the node-table of the corresponding IDC
22972 	    * binding.
22973 	    */
22974 	    matcher = sto->matcher;
22975 	    idc = matcher->aidc->def;
22976 	    nbKeys = idc->nbFields;
22977 	    pos = depth - matcher->depth;
22978 	    /*
22979 	    * Check if the matcher has any key-sequences at all, plus
22980 	    * if it has a key-sequence for the current target node.
22981 	    */
22982 	    if ((matcher->keySeqs == NULL) ||
22983 		(matcher->sizeKeySeqs <= pos)) {
22984 		if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
22985 		    goto selector_key_error;
22986 		else
22987 		    goto selector_leave;
22988 	    }
22989 
22990 	    keySeq = &(matcher->keySeqs[pos]);
22991 	    if (*keySeq == NULL) {
22992 		if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
22993 		    goto selector_key_error;
22994 		else
22995 		    goto selector_leave;
22996 	    }
22997 
22998 	    for (i = 0; i < nbKeys; i++) {
22999 		if ((*keySeq)[i] == NULL) {
23000 		    /*
23001 		    * Not qualified, if not all fields did resolve.
23002 		    */
23003 		    if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
23004 			/*
23005 			* All fields of a "key" IDC must resolve.
23006 			*/
23007 			goto selector_key_error;
23008 		    }
23009 		    goto selector_leave;
23010 		}
23011 	    }
23012 	    /*
23013 	    * All fields did resolve.
23014 	    */
23015 
23016 	    /*
23017 	    * 4.1 If the {identity-constraint category} is unique(/key),
23018 	    * then no two members of the `qualified node set` have
23019 	    * `key-sequences` whose members are pairwise equal, as
23020 	    * defined by Equal in [XML Schemas: Datatypes].
23021 	    *
23022 	    * Get the IDC binding from the matcher and check for
23023 	    * duplicate key-sequences.
23024 	    */
23025 #if 0
23026 	    bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
23027 #endif
23028 	    targets = xmlSchemaIDCAcquireTargetList(vctxt, matcher);
23029 	    if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
23030 		(targets->nbItems != 0)) {
23031 		xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
23032 
23033 		i = 0;
23034 		res = 0;
23035 		/*
23036 		* Compare the key-sequences, key by key.
23037 		*/
23038 		do {
23039 		    bkeySeq =
23040 			((xmlSchemaPSVIIDCNodePtr) targets->items[i])->keys;
23041 		    for (j = 0; j < nbKeys; j++) {
23042 			ckey = (*keySeq)[j];
23043 			bkey = bkeySeq[j];
23044 			res = xmlSchemaAreValuesEqual(ckey->val, bkey->val);
23045 			if (res == -1) {
23046 			    return (-1);
23047 			} else if (res == 0) {
23048 			    /*
23049 			    * One of the keys differs, so the key-sequence
23050 			    * won't be equal; get out.
23051 			    */
23052 			    break;
23053 			}
23054 		    }
23055 		    if (res == 1) {
23056 			/*
23057 			* Duplicate key-sequence found.
23058 			*/
23059 			break;
23060 		    }
23061 		    i++;
23062 		} while (i < targets->nbItems);
23063 		if (i != targets->nbItems) {
23064 		    xmlChar *str = NULL, *strB = NULL;
23065 		    /*
23066 		    * TODO: Try to report the key-sequence.
23067 		    */
23068 		    xmlSchemaCustomErr(ACTXT_CAST vctxt,
23069 			XML_SCHEMAV_CVC_IDC, NULL,
23070 			WXS_BASIC_CAST idc,
23071 			"Duplicate key-sequence %s in %s",
23072 			xmlSchemaFormatIDCKeySequence(vctxt, &str,
23073 			    (*keySeq), nbKeys),
23074 			xmlSchemaGetIDCDesignation(&strB, idc));
23075 		    FREE_AND_NULL(str);
23076 		    FREE_AND_NULL(strB);
23077 		    goto selector_leave;
23078 		}
23079 	    }
23080 	    /*
23081 	    * Add a node-table item to the IDC binding.
23082 	    */
23083 	    ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
23084 		sizeof(xmlSchemaPSVIIDCNode));
23085 	    if (ntItem == NULL) {
23086 		xmlSchemaVErrMemory(NULL,
23087 		    "allocating an IDC node-table item", NULL);
23088 		xmlFree(*keySeq);
23089 		*keySeq = NULL;
23090 		return(-1);
23091 	    }
23092 	    memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
23093 
23094 	    /*
23095 	    * Store the node-table item in a global list.
23096 	    */
23097 	    if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
23098 		if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
23099 		    xmlFree(ntItem);
23100 		    xmlFree(*keySeq);
23101 		    *keySeq = NULL;
23102 		    return (-1);
23103 		}
23104 		ntItem->nodeQNameID = -1;
23105 	    } else {
23106 		/*
23107 		* Save a cached QName for this node on the IDC node, to be
23108 		* able to report it, even if the node is not saved.
23109 		*/
23110 		ntItem->nodeQNameID = xmlSchemaVAddNodeQName(vctxt,
23111 		    vctxt->inode->localName, vctxt->inode->nsName);
23112 		if (ntItem->nodeQNameID == -1) {
23113 		    xmlFree(ntItem);
23114 		    xmlFree(*keySeq);
23115 		    *keySeq = NULL;
23116 		    return (-1);
23117 		}
23118 	    }
23119 	    /*
23120 	    * Init the node-table item: Save the node, position and
23121 	    * consume the key-sequence.
23122 	    */
23123 	    ntItem->node = vctxt->node;
23124 	    ntItem->nodeLine = vctxt->inode->nodeLine;
23125 	    ntItem->keys = *keySeq;
23126 	    *keySeq = NULL;
23127 #if 0
23128 	    if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1)
23129 #endif
23130 	    if (xmlSchemaItemListAdd(targets, ntItem) == -1) {
23131 		if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
23132 		    /*
23133 		    * Free the item, since keyref items won't be
23134 		    * put on a global list.
23135 		    */
23136 		    xmlFree(ntItem->keys);
23137 		    xmlFree(ntItem);
23138 		}
23139 		return (-1);
23140 	    }
23141 
23142 	    goto selector_leave;
23143 selector_key_error:
23144 	    {
23145 		xmlChar *str = NULL;
23146 		/*
23147 		* 4.2.1 (KEY) The `target node set` and the
23148 		* `qualified node set` are equal, that is, every
23149 		* member of the `target node set` is also a member
23150 		* of the `qualified node set` and vice versa.
23151 		*/
23152 		xmlSchemaCustomErr(ACTXT_CAST vctxt,
23153 		    XML_SCHEMAV_CVC_IDC, NULL,
23154 		    WXS_BASIC_CAST idc,
23155 		    "Not all fields of %s evaluate to a node",
23156 		    xmlSchemaGetIDCDesignation(&str, idc), NULL);
23157 		FREE_AND_NULL(str);
23158 	    }
23159 selector_leave:
23160 	    /*
23161 	    * Free the key-sequence if not added to the IDC table.
23162 	    */
23163 	    if ((keySeq != NULL) && (*keySeq != NULL)) {
23164 		xmlFree(*keySeq);
23165 		*keySeq = NULL;
23166 	    }
23167 	} /* if selector */
23168 
23169 	sto->nbHistory--;
23170 
23171 deregister_check:
23172 	/*
23173 	* Deregister state objects if they reach the depth of creation.
23174 	*/
23175 	if ((sto->nbHistory == 0) && (sto->depth == depth)) {
23176 #ifdef DEBUG_IDC
23177 	    xmlGenericError(xmlGenericErrorContext, "IDC:   STO pop '%s'\n",
23178 		sto->sel->xpath);
23179 #endif
23180 	    if (vctxt->xpathStates != sto) {
23181 		VERROR_INT("xmlSchemaXPathProcessHistory",
23182 		    "The state object to be removed is not the first "
23183 		    "in the list");
23184 	    }
23185 	    nextsto = sto->next;
23186 	    /*
23187 	    * Unlink from the list of active XPath state objects.
23188 	    */
23189 	    vctxt->xpathStates = sto->next;
23190 	    sto->next = vctxt->xpathStatePool;
23191 	    /*
23192 	    * Link it to the pool of reusable state objects.
23193 	    */
23194 	    vctxt->xpathStatePool = sto;
23195 	    sto = nextsto;
23196 	} else
23197 	    sto = sto->next;
23198     } /* while (sto != NULL) */
23199     return (0);
23200 }
23201 
23202 /**
23203  * xmlSchemaIDCRegisterMatchers:
23204  * @vctxt: the WXS validation context
23205  * @elemDecl: the element declaration
23206  *
23207  * Creates helper objects to evaluate IDC selectors/fields
23208  * successively.
23209  *
23210  * Returns 0 if OK and -1 on internal errors.
23211  */
23212 static int
xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,xmlSchemaElementPtr elemDecl)23213 xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
23214 			     xmlSchemaElementPtr elemDecl)
23215 {
23216     xmlSchemaIDCMatcherPtr matcher, last = NULL;
23217     xmlSchemaIDCPtr idc, refIdc;
23218     xmlSchemaIDCAugPtr aidc;
23219 
23220     idc = (xmlSchemaIDCPtr) elemDecl->idcs;
23221     if (idc == NULL)
23222 	return (0);
23223 
23224 #ifdef DEBUG_IDC
23225     {
23226 	xmlChar *str = NULL;
23227 	xmlGenericError(xmlGenericErrorContext,
23228 	    "IDC: REGISTER on %s, depth %d\n",
23229 	    (char *) xmlSchemaFormatQName(&str, vctxt->inode->nsName,
23230 		vctxt->inode->localName), vctxt->depth);
23231 	FREE_AND_NULL(str)
23232     }
23233 #endif
23234     if (vctxt->inode->idcMatchers != NULL) {
23235 	VERROR_INT("xmlSchemaIDCRegisterMatchers",
23236 	    "The chain of IDC matchers is expected to be empty");
23237 	return (-1);
23238     }
23239     do {
23240 	if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
23241 	    /*
23242 	    * Since IDCs bubbles are expensive we need to know the
23243 	    * depth at which the bubbles should stop; this will be
23244 	    * the depth of the top-most keyref IDC. If no keyref
23245 	    * references a key/unique IDC, the keyrefDepth will
23246 	    * be -1, indicating that no bubbles are needed.
23247 	    */
23248 	    refIdc = (xmlSchemaIDCPtr) idc->ref->item;
23249 	    if (refIdc != NULL) {
23250 		/*
23251 		* Remember that we have keyrefs on this node.
23252 		*/
23253 		vctxt->inode->hasKeyrefs = 1;
23254 		/*
23255 		* Lookup the referenced augmented IDC info.
23256 		*/
23257 		aidc = vctxt->aidcs;
23258 		while (aidc != NULL) {
23259 		    if (aidc->def == refIdc)
23260 			break;
23261 		    aidc = aidc->next;
23262 		}
23263 		if (aidc == NULL) {
23264 		    VERROR_INT("xmlSchemaIDCRegisterMatchers",
23265 			"Could not find an augmented IDC item for an IDC "
23266 			"definition");
23267 		    return (-1);
23268 		}
23269 		if ((aidc->keyrefDepth == -1) ||
23270 		    (vctxt->depth < aidc->keyrefDepth))
23271 		    aidc->keyrefDepth = vctxt->depth;
23272 	    }
23273 	}
23274 	/*
23275 	* Lookup the augmented IDC item for the IDC definition.
23276 	*/
23277 	aidc = vctxt->aidcs;
23278 	while (aidc != NULL) {
23279 	    if (aidc->def == idc)
23280 		break;
23281 	    aidc = aidc->next;
23282 	}
23283 	if (aidc == NULL) {
23284 	    VERROR_INT("xmlSchemaIDCRegisterMatchers",
23285 		"Could not find an augmented IDC item for an IDC definition");
23286 	    return (-1);
23287 	}
23288 	/*
23289 	* Create an IDC matcher for every IDC definition.
23290 	*/
23291 	if (vctxt->idcMatcherCache != NULL) {
23292 	    /*
23293 	    * Reuse a cached matcher.
23294 	    */
23295 	    matcher = vctxt->idcMatcherCache;
23296 	    vctxt->idcMatcherCache = matcher->nextCached;
23297 	    matcher->nextCached = NULL;
23298 	} else {
23299 	    matcher = (xmlSchemaIDCMatcherPtr)
23300 		xmlMalloc(sizeof(xmlSchemaIDCMatcher));
23301 	    if (matcher == NULL) {
23302 		xmlSchemaVErrMemory(vctxt,
23303 		    "allocating an IDC matcher", NULL);
23304 		return (-1);
23305 	    }
23306 	    memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
23307 	}
23308 	if (last == NULL)
23309 	    vctxt->inode->idcMatchers = matcher;
23310 	else
23311 	    last->next = matcher;
23312 	last = matcher;
23313 
23314 	matcher->type = IDC_MATCHER;
23315 	matcher->depth = vctxt->depth;
23316 	matcher->aidc = aidc;
23317 	matcher->idcType = aidc->def->type;
23318 #ifdef DEBUG_IDC
23319 	xmlGenericError(xmlGenericErrorContext, "IDC:   register matcher\n");
23320 #endif
23321 	/*
23322 	* Init the automaton state object.
23323 	*/
23324 	if (xmlSchemaIDCAddStateObject(vctxt, matcher,
23325 	    idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
23326 	    return (-1);
23327 
23328 	idc = idc->next;
23329     } while (idc != NULL);
23330     return (0);
23331 }
23332 
23333 static int
xmlSchemaIDCFillNodeTables(xmlSchemaValidCtxtPtr vctxt,xmlSchemaNodeInfoPtr ielem)23334 xmlSchemaIDCFillNodeTables(xmlSchemaValidCtxtPtr vctxt,
23335 			   xmlSchemaNodeInfoPtr ielem)
23336 {
23337     xmlSchemaPSVIIDCBindingPtr bind;
23338     int res, i, j, k, nbTargets, nbFields, nbDupls, nbNodeTable;
23339     xmlSchemaPSVIIDCKeyPtr *keys, *ntkeys;
23340     xmlSchemaPSVIIDCNodePtr *targets, *dupls;
23341 
23342     xmlSchemaIDCMatcherPtr matcher = ielem->idcMatchers;
23343     /* vctxt->createIDCNodeTables */
23344     while (matcher != NULL) {
23345 	/*
23346 	* Skip keyref IDCs and empty IDC target-lists.
23347 	*/
23348 	if ((matcher->aidc->def->type == XML_SCHEMA_TYPE_IDC_KEYREF) ||
23349 	    WXS_ILIST_IS_EMPTY(matcher->targets))
23350 	{
23351 	    matcher = matcher->next;
23352 	    continue;
23353 	}
23354 	/*
23355 	* If we _want_ the IDC node-table to be created in any case
23356 	* then do so. Otherwise create them only if keyrefs need them.
23357 	*/
23358 	if ((! vctxt->createIDCNodeTables) &&
23359 	    ((matcher->aidc->keyrefDepth == -1) ||
23360 	     (matcher->aidc->keyrefDepth > vctxt->depth)))
23361 	{
23362 	    matcher = matcher->next;
23363 	    continue;
23364 	}
23365 	/*
23366 	* Get/create the IDC binding on this element for the IDC definition.
23367 	*/
23368 	bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
23369 
23370 	if (! WXS_ILIST_IS_EMPTY(bind->dupls)) {
23371 	    dupls = (xmlSchemaPSVIIDCNodePtr *) bind->dupls->items;
23372 	    nbDupls = bind->dupls->nbItems;
23373 	} else {
23374 	    dupls = NULL;
23375 	    nbDupls = 0;
23376 	}
23377 	if (bind->nodeTable != NULL) {
23378 	    nbNodeTable = bind->nbNodes;
23379 	} else {
23380 	    nbNodeTable = 0;
23381 	}
23382 
23383 	if ((nbNodeTable == 0) && (nbDupls == 0)) {
23384 	    /*
23385 	    * Transfer all IDC target-nodes to the IDC node-table.
23386 	    */
23387 	    bind->nodeTable =
23388 		(xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
23389 	    bind->sizeNodes = matcher->targets->sizeItems;
23390 	    bind->nbNodes = matcher->targets->nbItems;
23391 
23392 	    matcher->targets->items = NULL;
23393 	    matcher->targets->sizeItems = 0;
23394 	    matcher->targets->nbItems = 0;
23395 	} else {
23396 	    /*
23397 	    * Compare the key-sequences and add to the IDC node-table.
23398 	    */
23399 	    nbTargets = matcher->targets->nbItems;
23400 	    targets = (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
23401 	    nbFields = matcher->aidc->def->nbFields;
23402 	    i = 0;
23403 	    do {
23404 		keys = targets[i]->keys;
23405 		if (nbDupls) {
23406 		    /*
23407 		    * Search in already found duplicates first.
23408 		    */
23409 		    j = 0;
23410 		    do {
23411 			if (nbFields == 1) {
23412 			    res = xmlSchemaAreValuesEqual(keys[0]->val,
23413 				dupls[j]->keys[0]->val);
23414 			    if (res == -1)
23415 				goto internal_error;
23416 			    if (res == 1) {
23417 				/*
23418 				* Equal key-sequence.
23419 				*/
23420 				goto next_target;
23421 			    }
23422 			} else {
23423 			    res = 0;
23424 			    ntkeys = dupls[j]->keys;
23425 			    for (k = 0; k < nbFields; k++) {
23426 				res = xmlSchemaAreValuesEqual(keys[k]->val,
23427 				    ntkeys[k]->val);
23428 				if (res == -1)
23429 				    goto internal_error;
23430 				if (res == 0) {
23431 				    /*
23432 				    * One of the keys differs.
23433 				    */
23434 				    break;
23435 				}
23436 			    }
23437 			    if (res == 1) {
23438 				/*
23439 				* Equal key-sequence found.
23440 				*/
23441 				goto next_target;
23442 			    }
23443 			}
23444 			j++;
23445 		    } while (j < nbDupls);
23446 		}
23447 		if (nbNodeTable) {
23448 		    j = 0;
23449 		    do {
23450 			if (nbFields == 1) {
23451 			    res = xmlSchemaAreValuesEqual(keys[0]->val,
23452 				bind->nodeTable[j]->keys[0]->val);
23453 			    if (res == -1)
23454 				goto internal_error;
23455 			    if (res == 0) {
23456 				/*
23457 				* The key-sequence differs.
23458 				*/
23459 				goto next_node_table_entry;
23460 			    }
23461 			} else {
23462 			    res = 0;
23463 			    ntkeys = bind->nodeTable[j]->keys;
23464 			    for (k = 0; k < nbFields; k++) {
23465 				res = xmlSchemaAreValuesEqual(keys[k]->val,
23466 				    ntkeys[k]->val);
23467 				if (res == -1)
23468 				    goto internal_error;
23469 				if (res == 0) {
23470 				    /*
23471 				    * One of the keys differs.
23472 				    */
23473 				    goto next_node_table_entry;
23474 				}
23475 			    }
23476 			}
23477 			/*
23478 			* Add the duplicate to the list of duplicates.
23479 			*/
23480 			if (bind->dupls == NULL) {
23481 			    bind->dupls = xmlSchemaItemListCreate();
23482 			    if (bind->dupls == NULL)
23483 				goto internal_error;
23484 			}
23485 			if (xmlSchemaItemListAdd(bind->dupls, bind->nodeTable[j]) == -1)
23486 			    goto internal_error;
23487 			/*
23488 			* Remove the duplicate entry from the IDC node-table.
23489 			*/
23490 			bind->nodeTable[j] = bind->nodeTable[bind->nbNodes -1];
23491 			bind->nbNodes--;
23492 
23493 			goto next_target;
23494 
23495 next_node_table_entry:
23496 			j++;
23497 		    } while (j < nbNodeTable);
23498 		}
23499 		/*
23500 		* If everything is fine, then add the IDC target-node to
23501 		* the IDC node-table.
23502 		*/
23503 		if (xmlSchemaIDCAppendNodeTableItem(bind, targets[i]) == -1)
23504 		    goto internal_error;
23505 
23506 next_target:
23507 		i++;
23508 	    } while (i < nbTargets);
23509 	}
23510 	matcher = matcher->next;
23511     }
23512     return(0);
23513 
23514 internal_error:
23515     return(-1);
23516 }
23517 
23518 /**
23519  * xmlSchemaBubbleIDCNodeTables:
23520  * @depth: the current tree depth
23521  *
23522  * Merges IDC bindings of an element at @depth into the corresponding IDC
23523  * bindings of its parent element. If a duplicate note-table entry is found,
23524  * both, the parent node-table entry and child entry are discarded from the
23525  * node-table of the parent.
23526  *
23527  * Returns 0 if OK and -1 on internal errors.
23528  */
23529 static int
xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)23530 xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
23531 {
23532     xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
23533     xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL; /* parent IDC bindings. */
23534     xmlSchemaPSVIIDCNodePtr node, parNode = NULL, *dupls, *parNodes; /* node-table entries. */
23535     xmlSchemaIDCAugPtr aidc;
23536     int i, j, k, ret = 0, nbFields, oldNum, oldDupls;
23537 
23538     bind = vctxt->inode->idcTable;
23539     if (bind == NULL) {
23540 	/* Fine, no table, no bubbles. */
23541 	return (0);
23542     }
23543 
23544     parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
23545     /*
23546     * Walk all bindings; create new or add to existing bindings.
23547     * Remove duplicate key-sequences.
23548     */
23549     while (bind != NULL) {
23550 
23551 	if ((bind->nbNodes == 0) && WXS_ILIST_IS_EMPTY(bind->dupls))
23552 	    goto next_binding;
23553 	/*
23554 	* Check if the key/unique IDC table needs to be bubbled.
23555 	*/
23556 	if (! vctxt->createIDCNodeTables) {
23557 	    aidc = vctxt->aidcs;
23558 	    do {
23559 		if (aidc->def == bind->definition) {
23560 		    if ((aidc->keyrefDepth == -1) ||
23561 			(aidc->keyrefDepth >= vctxt->depth)) {
23562 			goto next_binding;
23563 		    }
23564 		    break;
23565 		}
23566 		aidc = aidc->next;
23567 	    } while (aidc != NULL);
23568 	}
23569 
23570 	if (parTable != NULL)
23571 	    parBind = *parTable;
23572 	/*
23573 	* Search a matching parent binding for the
23574 	* IDC definition.
23575 	*/
23576 	while (parBind != NULL) {
23577 	    if (parBind->definition == bind->definition)
23578 		break;
23579 	    parBind = parBind->next;
23580 	}
23581 
23582 	if (parBind != NULL) {
23583 	    /*
23584 	    * Compare every node-table entry of the child node,
23585 	    * i.e. the key-sequence within, ...
23586 	    */
23587 	    oldNum = parBind->nbNodes; /* Skip newly added items. */
23588 
23589 	    if (! WXS_ILIST_IS_EMPTY(parBind->dupls)) {
23590 		oldDupls = parBind->dupls->nbItems;
23591 		dupls = (xmlSchemaPSVIIDCNodePtr *) parBind->dupls->items;
23592 	    } else {
23593 		dupls = NULL;
23594 		oldDupls = 0;
23595 	    }
23596 
23597 	    parNodes = parBind->nodeTable;
23598 	    nbFields = bind->definition->nbFields;
23599 
23600 	    for (i = 0; i < bind->nbNodes; i++) {
23601 		node = bind->nodeTable[i];
23602 		if (node == NULL)
23603 		    continue;
23604 		/*
23605 		* ...with every key-sequence of the parent node, already
23606 		* evaluated to be a duplicate key-sequence.
23607 		*/
23608 		if (oldDupls) {
23609 		    j = 0;
23610 		    while (j < oldDupls) {
23611 			if (nbFields == 1) {
23612 			    ret = xmlSchemaAreValuesEqual(
23613 				node->keys[0]->val,
23614 				dupls[j]->keys[0]->val);
23615 			    if (ret == -1)
23616 				goto internal_error;
23617 			    if (ret == 0) {
23618 				j++;
23619 				continue;
23620 			    }
23621 			} else {
23622 			    parNode = dupls[j];
23623 			    for (k = 0; k < nbFields; k++) {
23624 				ret = xmlSchemaAreValuesEqual(
23625 				    node->keys[k]->val,
23626 				    parNode->keys[k]->val);
23627 				if (ret == -1)
23628 				    goto internal_error;
23629 				if (ret == 0)
23630 				    break;
23631 			    }
23632 			}
23633 			if (ret == 1)
23634 			    /* Duplicate found. */
23635 			    break;
23636 			j++;
23637 		    }
23638 		    if (j != oldDupls) {
23639 			/* Duplicate found. Skip this entry. */
23640 			continue;
23641 		    }
23642 		}
23643 		/*
23644 		* ... and with every key-sequence of the parent node.
23645 		*/
23646 		if (oldNum) {
23647 		    j = 0;
23648 		    while (j < oldNum) {
23649 			parNode = parNodes[j];
23650 			if (nbFields == 1) {
23651 			    ret = xmlSchemaAreValuesEqual(
23652 				node->keys[0]->val,
23653 				parNode->keys[0]->val);
23654 			    if (ret == -1)
23655 				goto internal_error;
23656 			    if (ret == 0) {
23657 				j++;
23658 				continue;
23659 			    }
23660 			} else {
23661 			    for (k = 0; k < nbFields; k++) {
23662 				ret = xmlSchemaAreValuesEqual(
23663 				    node->keys[k]->val,
23664 				    parNode->keys[k]->val);
23665 				if (ret == -1)
23666 				    goto internal_error;
23667 				if (ret == 0)
23668 				    break;
23669 			    }
23670 			}
23671 			if (ret == 1)
23672 			    /* Duplicate found. */
23673 			    break;
23674 			j++;
23675 		    }
23676 		    if (j != oldNum) {
23677 			/*
23678 			* Handle duplicates. Move the duplicate in
23679 			* the parent's node-table to the list of
23680 			* duplicates.
23681 			*/
23682 			oldNum--;
23683 			parBind->nbNodes--;
23684 			/*
23685 			* Move last old item to pos of duplicate.
23686 			*/
23687 			parNodes[j] = parNodes[oldNum];
23688 
23689 			if (parBind->nbNodes != oldNum) {
23690 			    /*
23691 			    * If new items exist, move last new item to
23692 			    * last of old items.
23693 			    */
23694 			    parNodes[oldNum] =
23695 				parNodes[parBind->nbNodes];
23696 			}
23697 			if (parBind->dupls == NULL) {
23698 			    parBind->dupls = xmlSchemaItemListCreate();
23699 			    if (parBind->dupls == NULL)
23700 				goto internal_error;
23701 			}
23702 			xmlSchemaItemListAdd(parBind->dupls, parNode);
23703 		    } else {
23704 			/*
23705 			* Add the node-table entry (node and key-sequence) of
23706 			* the child node to the node table of the parent node.
23707 			*/
23708 			if (parBind->nodeTable == NULL) {
23709 			    parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23710 				xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
23711 			    if (parBind->nodeTable == NULL) {
23712 				xmlSchemaVErrMemory(NULL,
23713 				    "allocating IDC list of node-table items", NULL);
23714 				goto internal_error;
23715 			    }
23716 			    parBind->sizeNodes = 1;
23717 			} else if (parBind->nbNodes >= parBind->sizeNodes) {
23718 			    parBind->sizeNodes *= 2;
23719 			    parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23720 				xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
23721 				sizeof(xmlSchemaPSVIIDCNodePtr));
23722 			    if (parBind->nodeTable == NULL) {
23723 				xmlSchemaVErrMemory(NULL,
23724 				    "re-allocating IDC list of node-table items", NULL);
23725 				goto internal_error;
23726 			    }
23727 			}
23728 			parNodes = parBind->nodeTable;
23729 			/*
23730 			* Append the new node-table entry to the 'new node-table
23731 			* entries' section.
23732 			*/
23733 			parNodes[parBind->nbNodes++] = node;
23734 		    }
23735 
23736 		}
23737 
23738 	    }
23739 	} else {
23740 	    /*
23741 	    * No binding for the IDC was found: create a new one and
23742 	    * copy all node-tables.
23743 	    */
23744 	    parBind = xmlSchemaIDCNewBinding(bind->definition);
23745 	    if (parBind == NULL)
23746 		goto internal_error;
23747 
23748 	    /*
23749 	    * TODO: Hmm, how to optimize the initial number of
23750 	    * allocated entries?
23751 	    */
23752 	    if (bind->nbNodes != 0) {
23753 		/*
23754 		* Add all IDC node-table entries.
23755 		*/
23756 		if (! vctxt->psviExposeIDCNodeTables) {
23757 		    /*
23758 		    * Just move the entries.
23759 		    * NOTE: this is quite save here, since
23760 		    * all the keyref lookups have already been
23761 		    * performed.
23762 		    */
23763 		    parBind->nodeTable = bind->nodeTable;
23764 		    bind->nodeTable = NULL;
23765 		    parBind->sizeNodes = bind->sizeNodes;
23766 		    bind->sizeNodes = 0;
23767 		    parBind->nbNodes = bind->nbNodes;
23768 		    bind->nbNodes = 0;
23769 		} else {
23770 		    /*
23771 		    * Copy the entries.
23772 		    */
23773 		    parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23774 			xmlMalloc(bind->nbNodes *
23775 			sizeof(xmlSchemaPSVIIDCNodePtr));
23776 		    if (parBind->nodeTable == NULL) {
23777 			xmlSchemaVErrMemory(NULL,
23778 			    "allocating an array of IDC node-table "
23779 			    "items", NULL);
23780 			xmlSchemaIDCFreeBinding(parBind);
23781 			goto internal_error;
23782 		    }
23783 		    parBind->sizeNodes = bind->nbNodes;
23784 		    parBind->nbNodes = bind->nbNodes;
23785 		    memcpy(parBind->nodeTable, bind->nodeTable,
23786 			bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
23787 		}
23788 	    }
23789 	    if (bind->dupls) {
23790 		/*
23791 		* Move the duplicates.
23792 		*/
23793 		if (parBind->dupls != NULL)
23794 		    xmlSchemaItemListFree(parBind->dupls);
23795 		parBind->dupls = bind->dupls;
23796 		bind->dupls = NULL;
23797 	    }
23798             if (parTable != NULL) {
23799                 if (*parTable == NULL)
23800                     *parTable = parBind;
23801                 else {
23802                     parBind->next = *parTable;
23803                     *parTable = parBind;
23804                 }
23805             }
23806 	}
23807 
23808 next_binding:
23809 	bind = bind->next;
23810     }
23811     return (0);
23812 
23813 internal_error:
23814     return(-1);
23815 }
23816 
23817 /**
23818  * xmlSchemaCheckCVCIDCKeyRef:
23819  * @vctxt: the WXS validation context
23820  * @elemDecl: the element declaration
23821  *
23822  * Check the cvc-idc-keyref constraints.
23823  */
23824 static int
xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)23825 xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
23826 {
23827     xmlSchemaIDCMatcherPtr matcher;
23828     xmlSchemaPSVIIDCBindingPtr bind;
23829 
23830     matcher = vctxt->inode->idcMatchers;
23831     /*
23832     * Find a keyref.
23833     */
23834     while (matcher != NULL) {
23835 	if ((matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) &&
23836 	    matcher->targets &&
23837 	    matcher->targets->nbItems)
23838 	{
23839 	    int i, j, k, res, nbFields, hasDupls;
23840 	    xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
23841 	    xmlSchemaPSVIIDCNodePtr refNode = NULL;
23842 
23843 	    nbFields = matcher->aidc->def->nbFields;
23844 
23845 	    /*
23846 	    * Find the IDC node-table for the referenced IDC key/unique.
23847 	    */
23848 	    bind = vctxt->inode->idcTable;
23849 	    while (bind != NULL) {
23850 		if ((xmlSchemaIDCPtr) matcher->aidc->def->ref->item ==
23851 		    bind->definition)
23852 		    break;
23853 		bind = bind->next;
23854 	    }
23855 	    hasDupls = (bind && bind->dupls && bind->dupls->nbItems) ? 1 : 0;
23856 	    /*
23857 	    * Search for a matching key-sequences.
23858 	    */
23859 	    for (i = 0; i < matcher->targets->nbItems; i++) {
23860 		res = 0;
23861 		refNode = matcher->targets->items[i];
23862 		if (bind != NULL) {
23863 		    refKeys = refNode->keys;
23864 		    for (j = 0; j < bind->nbNodes; j++) {
23865 			keys = bind->nodeTable[j]->keys;
23866 			for (k = 0; k < nbFields; k++) {
23867 			    res = xmlSchemaAreValuesEqual(keys[k]->val,
23868 				refKeys[k]->val);
23869 			    if (res == 0)
23870 				break;
23871 			    else if (res == -1) {
23872 				return (-1);
23873 			    }
23874 			}
23875 			if (res == 1) {
23876 			    /*
23877 			    * Match found.
23878 			    */
23879 			    break;
23880 			}
23881 		    }
23882 		    if ((res == 0) && hasDupls) {
23883 			/*
23884 			* Search in duplicates
23885 			*/
23886 			for (j = 0; j < bind->dupls->nbItems; j++) {
23887 			    keys = ((xmlSchemaPSVIIDCNodePtr)
23888 				bind->dupls->items[j])->keys;
23889 			    for (k = 0; k < nbFields; k++) {
23890 				res = xmlSchemaAreValuesEqual(keys[k]->val,
23891 				    refKeys[k]->val);
23892 				if (res == 0)
23893 				    break;
23894 				else if (res == -1) {
23895 				    return (-1);
23896 				}
23897 			    }
23898 			    if (res == 1) {
23899 				/*
23900 				* Match in duplicates found.
23901 				*/
23902 				xmlChar *str = NULL, *strB = NULL;
23903 				xmlSchemaKeyrefErr(vctxt,
23904 				    XML_SCHEMAV_CVC_IDC, refNode,
23905 				    (xmlSchemaTypePtr) matcher->aidc->def,
23906 				    "More than one match found for "
23907 				    "key-sequence %s of keyref '%s'",
23908 				    xmlSchemaFormatIDCKeySequence(vctxt, &str,
23909 					refNode->keys, nbFields),
23910 				    xmlSchemaGetComponentQName(&strB,
23911 					matcher->aidc->def));
23912 				FREE_AND_NULL(str);
23913 				FREE_AND_NULL(strB);
23914 				break;
23915 			    }
23916 			}
23917 		    }
23918 		}
23919 
23920 		if (res == 0) {
23921 		    xmlChar *str = NULL, *strB = NULL;
23922 		    xmlSchemaKeyrefErr(vctxt,
23923 			XML_SCHEMAV_CVC_IDC, refNode,
23924 			(xmlSchemaTypePtr) matcher->aidc->def,
23925 			"No match found for key-sequence %s of keyref '%s'",
23926 			xmlSchemaFormatIDCKeySequence(vctxt, &str,
23927 			    refNode->keys, nbFields),
23928 			xmlSchemaGetComponentQName(&strB, matcher->aidc->def));
23929 		    FREE_AND_NULL(str);
23930 		    FREE_AND_NULL(strB);
23931 		}
23932 	    }
23933 	}
23934 	matcher = matcher->next;
23935     }
23936     /* TODO: Return an error if any error encountered. */
23937     return (0);
23938 }
23939 
23940 /************************************************************************
23941  *									*
23942  *			XML Reader validation code                      *
23943  *									*
23944  ************************************************************************/
23945 
23946 static xmlSchemaAttrInfoPtr
xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)23947 xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)
23948 {
23949     xmlSchemaAttrInfoPtr iattr;
23950     /*
23951     * Grow/create list of attribute infos.
23952     */
23953     if (vctxt->attrInfos == NULL) {
23954 	vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
23955 	    xmlMalloc(sizeof(xmlSchemaAttrInfoPtr));
23956 	vctxt->sizeAttrInfos = 1;
23957 	if (vctxt->attrInfos == NULL) {
23958 	    xmlSchemaVErrMemory(vctxt,
23959 		"allocating attribute info list", NULL);
23960 	    return (NULL);
23961 	}
23962     } else if (vctxt->sizeAttrInfos <= vctxt->nbAttrInfos) {
23963 	vctxt->sizeAttrInfos++;
23964 	vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
23965 	    xmlRealloc(vctxt->attrInfos,
23966 		vctxt->sizeAttrInfos * sizeof(xmlSchemaAttrInfoPtr));
23967 	if (vctxt->attrInfos == NULL) {
23968 	    xmlSchemaVErrMemory(vctxt,
23969 		"re-allocating attribute info list", NULL);
23970 	    return (NULL);
23971 	}
23972     } else {
23973 	iattr = vctxt->attrInfos[vctxt->nbAttrInfos++];
23974 	if (iattr->localName != NULL) {
23975 	    VERROR_INT("xmlSchemaGetFreshAttrInfo",
23976 		"attr info not cleared");
23977 	    return (NULL);
23978 	}
23979 	iattr->nodeType = XML_ATTRIBUTE_NODE;
23980 	return (iattr);
23981     }
23982     /*
23983     * Create an attribute info.
23984     */
23985     iattr = (xmlSchemaAttrInfoPtr)
23986 	xmlMalloc(sizeof(xmlSchemaAttrInfo));
23987     if (iattr == NULL) {
23988 	xmlSchemaVErrMemory(vctxt, "creating new attribute info", NULL);
23989 	return (NULL);
23990     }
23991     memset(iattr, 0, sizeof(xmlSchemaAttrInfo));
23992     iattr->nodeType = XML_ATTRIBUTE_NODE;
23993     vctxt->attrInfos[vctxt->nbAttrInfos++] = iattr;
23994 
23995     return (iattr);
23996 }
23997 
23998 static int
xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,xmlNodePtr attrNode,int nodeLine,const xmlChar * localName,const xmlChar * nsName,int ownedNames,xmlChar * value,int ownedValue)23999 xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,
24000 			xmlNodePtr attrNode,
24001 			int nodeLine,
24002 			const xmlChar *localName,
24003 			const xmlChar *nsName,
24004 			int ownedNames,
24005 			xmlChar *value,
24006 			int ownedValue)
24007 {
24008     xmlSchemaAttrInfoPtr attr;
24009 
24010     attr = xmlSchemaGetFreshAttrInfo(vctxt);
24011     if (attr == NULL) {
24012 	VERROR_INT("xmlSchemaPushAttribute",
24013 	    "calling xmlSchemaGetFreshAttrInfo()");
24014 	return (-1);
24015     }
24016     attr->node = attrNode;
24017     attr->nodeLine = nodeLine;
24018     attr->state = XML_SCHEMAS_ATTR_UNKNOWN;
24019     attr->localName = localName;
24020     attr->nsName = nsName;
24021     if (ownedNames)
24022 	attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
24023     /*
24024     * Evaluate if it's an XSI attribute.
24025     */
24026     if (nsName != NULL) {
24027 	if (xmlStrEqual(localName, BAD_CAST "nil")) {
24028 	    if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
24029 		attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NIL;
24030 	    }
24031 	} else if (xmlStrEqual(localName, BAD_CAST "type")) {
24032 	    if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
24033 		attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_TYPE;
24034 	    }
24035 	} else if (xmlStrEqual(localName, BAD_CAST "schemaLocation")) {
24036 	    if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
24037 		attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC;
24038 	    }
24039 	} else if (xmlStrEqual(localName, BAD_CAST "noNamespaceSchemaLocation")) {
24040 	    if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
24041 		attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC;
24042 	    }
24043 	} else if (xmlStrEqual(attr->nsName, xmlNamespaceNs)) {
24044 	    attr->metaType = XML_SCHEMA_ATTR_INFO_META_XMLNS;
24045 	}
24046     }
24047     attr->value = value;
24048     if (ownedValue)
24049 	attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
24050     if (attr->metaType != 0)
24051 	attr->state = XML_SCHEMAS_ATTR_META;
24052     return (0);
24053 }
24054 
24055 /**
24056  * xmlSchemaClearElemInfo:
24057  * @vctxt: the WXS validation context
24058  * @ielem: the element information item
24059  */
24060 static void
xmlSchemaClearElemInfo(xmlSchemaValidCtxtPtr vctxt,xmlSchemaNodeInfoPtr ielem)24061 xmlSchemaClearElemInfo(xmlSchemaValidCtxtPtr vctxt,
24062 		       xmlSchemaNodeInfoPtr ielem)
24063 {
24064     ielem->hasKeyrefs = 0;
24065     ielem->appliedXPath = 0;
24066     if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
24067 	FREE_AND_NULL(ielem->localName);
24068 	FREE_AND_NULL(ielem->nsName);
24069     } else {
24070 	ielem->localName = NULL;
24071 	ielem->nsName = NULL;
24072     }
24073     if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
24074 	FREE_AND_NULL(ielem->value);
24075     } else {
24076 	ielem->value = NULL;
24077     }
24078     if (ielem->val != NULL) {
24079 	/*
24080 	* PSVI TODO: Be careful not to free it when the value is
24081 	* exposed via PSVI.
24082 	*/
24083 	xmlSchemaFreeValue(ielem->val);
24084 	ielem->val = NULL;
24085     }
24086     if (ielem->idcMatchers != NULL) {
24087 	/*
24088 	* REVISIT OPTIMIZE TODO: Use a pool of IDC matchers.
24089 	*   Does it work?
24090 	*/
24091 	xmlSchemaIDCReleaseMatcherList(vctxt, ielem->idcMatchers);
24092 #if 0
24093 	xmlSchemaIDCFreeMatcherList(ielem->idcMatchers);
24094 #endif
24095 	ielem->idcMatchers = NULL;
24096     }
24097     if (ielem->idcTable != NULL) {
24098 	/*
24099 	* OPTIMIZE TODO: Use a pool of IDC tables??.
24100 	*/
24101 	xmlSchemaIDCFreeIDCTable(ielem->idcTable);
24102 	ielem->idcTable = NULL;
24103     }
24104     if (ielem->regexCtxt != NULL) {
24105 	xmlRegFreeExecCtxt(ielem->regexCtxt);
24106 	ielem->regexCtxt = NULL;
24107     }
24108     if (ielem->nsBindings != NULL) {
24109 	xmlFree((xmlChar **)ielem->nsBindings);
24110 	ielem->nsBindings = NULL;
24111 	ielem->nbNsBindings = 0;
24112 	ielem->sizeNsBindings = 0;
24113     }
24114 }
24115 
24116 /**
24117  * xmlSchemaGetFreshElemInfo:
24118  * @vctxt: the schema validation context
24119  *
24120  * Creates/reuses and initializes the element info item for
24121  * the currect tree depth.
24122  *
24123  * Returns the element info item or NULL on API or internal errors.
24124  */
24125 static xmlSchemaNodeInfoPtr
xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)24126 xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)
24127 {
24128     xmlSchemaNodeInfoPtr info = NULL;
24129 
24130     if (vctxt->depth > vctxt->sizeElemInfos) {
24131 	VERROR_INT("xmlSchemaGetFreshElemInfo",
24132 	    "inconsistent depth encountered");
24133 	return (NULL);
24134     }
24135     if (vctxt->elemInfos == NULL) {
24136 	vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
24137 	    xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
24138 	if (vctxt->elemInfos == NULL) {
24139 	    xmlSchemaVErrMemory(vctxt,
24140 		"allocating the element info array", NULL);
24141 	    return (NULL);
24142 	}
24143 	memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
24144 	vctxt->sizeElemInfos = 10;
24145     } else if (vctxt->sizeElemInfos <= vctxt->depth) {
24146 	int i = vctxt->sizeElemInfos;
24147 
24148 	vctxt->sizeElemInfos *= 2;
24149 	vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
24150 	    xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
24151 	    sizeof(xmlSchemaNodeInfoPtr));
24152 	if (vctxt->elemInfos == NULL) {
24153 	    xmlSchemaVErrMemory(vctxt,
24154 		"re-allocating the element info array", NULL);
24155 	    return (NULL);
24156 	}
24157 	/*
24158 	* We need the new memory to be NULLed.
24159 	* TODO: Use memset instead?
24160 	*/
24161 	for (; i < vctxt->sizeElemInfos; i++)
24162 	    vctxt->elemInfos[i] = NULL;
24163     } else
24164 	info = vctxt->elemInfos[vctxt->depth];
24165 
24166     if (info == NULL) {
24167 	info = (xmlSchemaNodeInfoPtr)
24168 	    xmlMalloc(sizeof(xmlSchemaNodeInfo));
24169 	if (info == NULL) {
24170 	    xmlSchemaVErrMemory(vctxt,
24171 		"allocating an element info", NULL);
24172 	    return (NULL);
24173 	}
24174 	vctxt->elemInfos[vctxt->depth] = info;
24175     } else {
24176 	if (info->localName != NULL) {
24177 	    VERROR_INT("xmlSchemaGetFreshElemInfo",
24178 		"elem info has not been cleared");
24179 	    return (NULL);
24180 	}
24181     }
24182     memset(info, 0, sizeof(xmlSchemaNodeInfo));
24183     info->nodeType = XML_ELEMENT_NODE;
24184     info->depth = vctxt->depth;
24185 
24186     return (info);
24187 }
24188 
24189 #define ACTIVATE_ATTRIBUTE(item) vctxt->inode = (xmlSchemaNodeInfoPtr) item;
24190 #define ACTIVATE_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth];
24191 #define ACTIVATE_PARENT_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth -1];
24192 
24193 static int
xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,xmlNodePtr node,xmlSchemaTypePtr type,xmlSchemaValType valType,const xmlChar * value,xmlSchemaValPtr val,unsigned long length,int fireErrors)24194 xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,
24195 			xmlNodePtr node,
24196 			xmlSchemaTypePtr type,
24197 			xmlSchemaValType valType,
24198 			const xmlChar * value,
24199 			xmlSchemaValPtr val,
24200 			unsigned long length,
24201 			int fireErrors)
24202 {
24203     int ret, error = 0;
24204 
24205     xmlSchemaTypePtr tmpType;
24206     xmlSchemaFacetLinkPtr facetLink;
24207     xmlSchemaFacetPtr facet;
24208     unsigned long len = 0;
24209     xmlSchemaWhitespaceValueType ws;
24210 
24211     /*
24212     * In Libxml2, derived built-in types have currently no explicit facets.
24213     */
24214     if (type->type == XML_SCHEMA_TYPE_BASIC)
24215 	return (0);
24216 
24217     /*
24218     * NOTE: Do not jump away, if the facetSet of the given type is
24219     * empty: until now, "pattern" and "enumeration" facets of the
24220     * *base types* need to be checked as well.
24221     */
24222     if (type->facetSet == NULL)
24223 	goto pattern_and_enum;
24224 
24225     if (! WXS_IS_ATOMIC(type)) {
24226 	if (WXS_IS_LIST(type))
24227 	    goto WXS_IS_LIST;
24228 	else
24229 	    goto pattern_and_enum;
24230     }
24231 
24232     /*
24233     * Whitespace handling is only of importance for string-based
24234     * types.
24235     */
24236     tmpType = xmlSchemaGetPrimitiveType(type);
24237     if ((tmpType->builtInType == XML_SCHEMAS_STRING) ||
24238 	WXS_IS_ANY_SIMPLE_TYPE(tmpType)) {
24239 	ws = xmlSchemaGetWhiteSpaceFacetValue(type);
24240     } else
24241 	ws = XML_SCHEMA_WHITESPACE_COLLAPSE;
24242 
24243     /*
24244     * If the value was not computed (for string or
24245     * anySimpleType based types), then use the provided
24246     * type.
24247     */
24248     if (val != NULL)
24249 	valType = xmlSchemaGetValType(val);
24250 
24251     ret = 0;
24252     for (facetLink = type->facetSet; facetLink != NULL;
24253 	facetLink = facetLink->next) {
24254 	/*
24255 	* Skip the pattern "whiteSpace": it is used to
24256 	* format the character content beforehand.
24257 	*/
24258 	switch (facetLink->facet->type) {
24259 	    case XML_SCHEMA_FACET_WHITESPACE:
24260 	    case XML_SCHEMA_FACET_PATTERN:
24261 	    case XML_SCHEMA_FACET_ENUMERATION:
24262 		continue;
24263 	    case XML_SCHEMA_FACET_LENGTH:
24264 	    case XML_SCHEMA_FACET_MINLENGTH:
24265 	    case XML_SCHEMA_FACET_MAXLENGTH:
24266 		ret = xmlSchemaValidateLengthFacetWhtsp(facetLink->facet,
24267 		    valType, value, val, &len, ws);
24268 		break;
24269 	    default:
24270 		ret = xmlSchemaValidateFacetWhtsp(facetLink->facet, ws,
24271 		    valType, value, val, ws);
24272 		break;
24273 	}
24274 	if (ret < 0) {
24275 	    AERROR_INT("xmlSchemaValidateFacets",
24276 		"validating against a atomic type facet");
24277 	    return (-1);
24278 	} else if (ret > 0) {
24279 	    if (fireErrors)
24280 		xmlSchemaFacetErr(actxt, ret, node,
24281 		value, len, type, facetLink->facet, NULL, NULL, NULL);
24282 	    else
24283 		return (ret);
24284 	    if (error == 0)
24285 		error = ret;
24286 	}
24287 	ret = 0;
24288     }
24289 
24290 WXS_IS_LIST:
24291     if (! WXS_IS_LIST(type))
24292 	goto pattern_and_enum;
24293     /*
24294     * "length", "minLength" and "maxLength" of list types.
24295     */
24296     ret = 0;
24297     for (facetLink = type->facetSet; facetLink != NULL;
24298 	facetLink = facetLink->next) {
24299 
24300 	switch (facetLink->facet->type) {
24301 	    case XML_SCHEMA_FACET_LENGTH:
24302 	    case XML_SCHEMA_FACET_MINLENGTH:
24303 	    case XML_SCHEMA_FACET_MAXLENGTH:
24304 		ret = xmlSchemaValidateListSimpleTypeFacet(facetLink->facet,
24305 		    value, length, NULL);
24306 		break;
24307 	    default:
24308 		continue;
24309 	}
24310 	if (ret < 0) {
24311 	    AERROR_INT("xmlSchemaValidateFacets",
24312 		"validating against a list type facet");
24313 	    return (-1);
24314 	} else if (ret > 0) {
24315 	    if (fireErrors)
24316 		xmlSchemaFacetErr(actxt, ret, node,
24317 		value, length, type, facetLink->facet, NULL, NULL, NULL);
24318 	    else
24319 		return (ret);
24320 	    if (error == 0)
24321 		error = ret;
24322 	}
24323 	ret = 0;
24324     }
24325 
24326 pattern_and_enum:
24327     if (error >= 0) {
24328 	int found = 0;
24329 	/*
24330 	* Process enumerations. Facet values are in the value space
24331 	* of the defining type's base type. This seems to be a bug in the
24332 	* XML Schema 1.0 spec. Use the whitespace type of the base type.
24333 	* Only the first set of enumerations in the ancestor-or-self axis
24334 	* is used for validation.
24335 	*/
24336 	ret = 0;
24337 	tmpType = type;
24338 	do {
24339 	    for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
24340 		if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
24341 		    continue;
24342 		found = 1;
24343 		ret = xmlSchemaAreValuesEqual(facet->val, val);
24344 		if (ret == 1)
24345 		    break;
24346 		else if (ret < 0) {
24347 		    AERROR_INT("xmlSchemaValidateFacets",
24348 			"validating against an enumeration facet");
24349 		    return (-1);
24350 		}
24351 	    }
24352 	    if (ret != 0)
24353 		break;
24354 	    /*
24355 	    * Break on the first set of enumerations. Any additional
24356 	    *  enumerations which might be existent on the ancestors
24357 	    *  of the current type are restricted by this set; thus
24358 	    *  *must* *not* be taken into account.
24359 	    */
24360 	    if (found)
24361 		break;
24362 	    tmpType = tmpType->baseType;
24363 	} while ((tmpType != NULL) &&
24364 	    (tmpType->type != XML_SCHEMA_TYPE_BASIC));
24365 	if (found && (ret == 0)) {
24366 	    ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
24367 	    if (fireErrors) {
24368 		xmlSchemaFacetErr(actxt, ret, node,
24369 		    value, 0, type, NULL, NULL, NULL, NULL);
24370 	    } else
24371 		return (ret);
24372 	    if (error == 0)
24373 		error = ret;
24374 	}
24375     }
24376 
24377     if (error >= 0) {
24378 	int found;
24379 	/*
24380 	* Process patters. Pattern facets are ORed at type level
24381 	* and ANDed if derived. Walk the base type axis.
24382 	*/
24383 	tmpType = type;
24384 	facet = NULL;
24385 	do {
24386 	    found = 0;
24387 	    for (facetLink = tmpType->facetSet; facetLink != NULL;
24388 		facetLink = facetLink->next) {
24389 		if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
24390 		    continue;
24391 		found = 1;
24392 		/*
24393 		* NOTE that for patterns, @value needs to be the
24394 		* normalized vaule.
24395 		*/
24396 		ret = xmlRegexpExec(facetLink->facet->regexp, value);
24397 		if (ret == 1)
24398 		    break;
24399 		else if (ret < 0) {
24400 		    AERROR_INT("xmlSchemaValidateFacets",
24401 			"validating against a pattern facet");
24402 		    return (-1);
24403 		} else {
24404 		    /*
24405 		    * Save the last non-validating facet.
24406 		    */
24407 		    facet = facetLink->facet;
24408 		}
24409 	    }
24410 	    if (found && (ret != 1)) {
24411 		ret = XML_SCHEMAV_CVC_PATTERN_VALID;
24412 		if (fireErrors) {
24413 		    xmlSchemaFacetErr(actxt, ret, node,
24414 			value, 0, type, facet, NULL, NULL, NULL);
24415 		} else
24416 		    return (ret);
24417 		if (error == 0)
24418 		    error = ret;
24419 		break;
24420 	    }
24421 	    tmpType = tmpType->baseType;
24422 	} while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
24423     }
24424 
24425     return (error);
24426 }
24427 
24428 static xmlChar *
xmlSchemaNormalizeValue(xmlSchemaTypePtr type,const xmlChar * value)24429 xmlSchemaNormalizeValue(xmlSchemaTypePtr type,
24430 			const xmlChar *value)
24431 {
24432     switch (xmlSchemaGetWhiteSpaceFacetValue(type)) {
24433 	case XML_SCHEMA_WHITESPACE_COLLAPSE:
24434 	    return (xmlSchemaCollapseString(value));
24435 	case XML_SCHEMA_WHITESPACE_REPLACE:
24436 	    return (xmlSchemaWhiteSpaceReplace(value));
24437 	default:
24438 	    return (NULL);
24439     }
24440 }
24441 
24442 static int
xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt,const xmlChar * value,xmlSchemaValPtr * val,int valNeeded)24443 xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt,
24444 		       const xmlChar *value,
24445 		       xmlSchemaValPtr *val,
24446 		       int valNeeded)
24447 {
24448     int ret;
24449     const xmlChar *nsName;
24450     xmlChar *local, *prefix = NULL;
24451 
24452     ret = xmlValidateQName(value, 1);
24453     if (ret != 0) {
24454 	if (ret == -1) {
24455 	    VERROR_INT("xmlSchemaValidateQName",
24456 		"calling xmlValidateQName()");
24457 	    return (-1);
24458 	}
24459 	return( XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
24460     }
24461     /*
24462     * NOTE: xmlSplitQName2 will always return a duplicated
24463     * strings.
24464     */
24465     local = xmlSplitQName2(value, &prefix);
24466     if (local == NULL)
24467 	local = xmlStrdup(value);
24468     /*
24469     * OPTIMIZE TODO: Use flags for:
24470     *  - is there any namespace binding?
24471     *  - is there a default namespace?
24472     */
24473     nsName = xmlSchemaLookupNamespace(vctxt, prefix);
24474 
24475     if (prefix != NULL) {
24476 	xmlFree(prefix);
24477 	/*
24478 	* A namespace must be found if the prefix is
24479 	* NOT NULL.
24480 	*/
24481 	if (nsName == NULL) {
24482 	    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24483 	    xmlSchemaCustomErr(ACTXT_CAST vctxt, ret, NULL,
24484 		WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24485 		"The QName value '%s' has no "
24486 		"corresponding namespace declaration in "
24487 		"scope", value, NULL);
24488 	    if (local != NULL)
24489 		xmlFree(local);
24490 	    return (ret);
24491 	}
24492     }
24493     if (valNeeded && val) {
24494 	if (nsName != NULL)
24495 	    *val = xmlSchemaNewQNameValue(
24496 		BAD_CAST xmlStrdup(nsName), BAD_CAST local);
24497 	else
24498 	    *val = xmlSchemaNewQNameValue(NULL,
24499 		BAD_CAST local);
24500     } else
24501 	xmlFree(local);
24502     return (0);
24503 }
24504 
24505 /*
24506 * cvc-simple-type
24507 */
24508 static int
xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,xmlNodePtr node,xmlSchemaTypePtr type,const xmlChar * value,xmlSchemaValPtr * retVal,int fireErrors,int normalize,int isNormalized)24509 xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
24510 			     xmlNodePtr node,
24511 			     xmlSchemaTypePtr type,
24512 			     const xmlChar *value,
24513 			     xmlSchemaValPtr *retVal,
24514 			     int fireErrors,
24515 			     int normalize,
24516 			     int isNormalized)
24517 {
24518     int ret = 0, valNeeded = (retVal) ? 1 : 0;
24519     xmlSchemaValPtr val = NULL;
24520     /* xmlSchemaWhitespaceValueType ws; */
24521     xmlChar *normValue = NULL;
24522 
24523 #define NORMALIZE(atype) \
24524     if ((! isNormalized) && \
24525     (normalize || (type->flags & XML_SCHEMAS_TYPE_NORMVALUENEEDED))) { \
24526 	normValue = xmlSchemaNormalizeValue(atype, value); \
24527 	if (normValue != NULL) \
24528 	    value = normValue; \
24529 	isNormalized = 1; \
24530     }
24531 
24532     if ((retVal != NULL) && (*retVal != NULL)) {
24533 	xmlSchemaFreeValue(*retVal);
24534 	*retVal = NULL;
24535     }
24536     /*
24537     * 3.14.4 Simple Type Definition Validation Rules
24538     * Validation Rule: String Valid
24539     */
24540     /*
24541     * 1 It is schema-valid with respect to that definition as defined
24542     * by Datatype Valid in [XML Schemas: Datatypes].
24543     */
24544     /*
24545     * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
24546     * the empty set, as defined in Type Derivation OK (Simple) ($3.14.6), then
24547     * the string must be a `declared entity name`.
24548     */
24549     /*
24550     * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
24551     * given the empty set, as defined in Type Derivation OK (Simple) ($3.14.6),
24552     * then every whitespace-delimited substring of the string must be a `declared
24553     * entity name`.
24554     */
24555     /*
24556     * 2.3 otherwise no further condition applies.
24557     */
24558     if ((! valNeeded) && (type->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
24559 	valNeeded = 1;
24560     if (value == NULL)
24561 	value = BAD_CAST "";
24562     if (WXS_IS_ANY_SIMPLE_TYPE(type) || WXS_IS_ATOMIC(type)) {
24563 	xmlSchemaTypePtr biType; /* The built-in type. */
24564 	/*
24565 	* SPEC (1.2.1) "if {variety} is `atomic` then the string must `match`
24566 	* a literal in the `lexical space` of {base type definition}"
24567 	*/
24568 	/*
24569 	* Whitespace-normalize.
24570 	*/
24571 	NORMALIZE(type);
24572 	if (type->type != XML_SCHEMA_TYPE_BASIC) {
24573 	    /*
24574 	    * Get the built-in type.
24575 	    */
24576 	    biType = type->baseType;
24577 	    while ((biType != NULL) &&
24578 		(biType->type != XML_SCHEMA_TYPE_BASIC))
24579 		biType = biType->baseType;
24580 
24581 	    if (biType == NULL) {
24582 		AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24583 		    "could not get the built-in type");
24584 		goto internal_error;
24585 	    }
24586 	} else
24587 	    biType = type;
24588 	/*
24589 	* NOTATIONs need to be processed here, since they need
24590 	* to lookup in the hashtable of NOTATION declarations of the schema.
24591 	*/
24592 	if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
24593 	    switch (biType->builtInType) {
24594 		case XML_SCHEMAS_NOTATION:
24595 		    ret = xmlSchemaValidateNotation(
24596 			(xmlSchemaValidCtxtPtr) actxt,
24597 			((xmlSchemaValidCtxtPtr) actxt)->schema,
24598 			NULL, value, &val, valNeeded);
24599 		    break;
24600 		case XML_SCHEMAS_QNAME:
24601 		    ret = xmlSchemaValidateQName((xmlSchemaValidCtxtPtr) actxt,
24602 			value, &val, valNeeded);
24603 		    break;
24604 		default:
24605 		    /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
24606 		    if (valNeeded)
24607 			ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24608 			    value, &val, node);
24609 		    else
24610 			ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24611 			    value, NULL, node);
24612 		    break;
24613 	    }
24614 	} else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
24615 	    switch (biType->builtInType) {
24616 		case XML_SCHEMAS_NOTATION:
24617 		    ret = xmlSchemaValidateNotation(NULL,
24618 			((xmlSchemaParserCtxtPtr) actxt)->schema, node,
24619 			value, &val, valNeeded);
24620 		    break;
24621 		default:
24622 		    /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
24623 		    if (valNeeded)
24624 			ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24625 			    value, &val, node);
24626 		    else
24627 			ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24628 			    value, NULL, node);
24629 		    break;
24630 	    }
24631 	} else {
24632 	    /*
24633 	    * Validation via a public API is not implemented yet.
24634 	    */
24635 	    TODO
24636 	    goto internal_error;
24637 	}
24638 	if (ret != 0) {
24639 	    if (ret < 0) {
24640 		AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24641 		    "validating against a built-in type");
24642 		goto internal_error;
24643 	    }
24644 	    if (WXS_IS_LIST(type))
24645 		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24646 	    else
24647 		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24648 	}
24649 	if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24650 	    /*
24651 	    * Check facets.
24652 	    */
24653 	    ret = xmlSchemaValidateFacets(actxt, node, type,
24654 		(xmlSchemaValType) biType->builtInType, value, val,
24655 		0, fireErrors);
24656 	    if (ret != 0) {
24657 		if (ret < 0) {
24658 		    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24659 			"validating facets of atomic simple type");
24660 		    goto internal_error;
24661 		}
24662 		if (WXS_IS_LIST(type))
24663 		    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24664 		else
24665 		    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24666 	    }
24667 	}
24668 	if (fireErrors && (ret > 0))
24669 	    xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24670     } else if (WXS_IS_LIST(type)) {
24671 
24672 	xmlSchemaTypePtr itemType;
24673 	const xmlChar *cur, *end;
24674 	xmlChar *tmpValue = NULL;
24675 	unsigned long len = 0;
24676 	xmlSchemaValPtr prevVal = NULL, curVal = NULL;
24677 	/* 1.2.2 if {variety} is `list` then the string must be a sequence
24678 	* of white space separated tokens, each of which `match`es a literal
24679 	* in the `lexical space` of {item type definition}
24680 	*/
24681 	/*
24682 	* Note that XML_SCHEMAS_TYPE_NORMVALUENEEDED will be set if
24683 	* the list type has an enum or pattern facet.
24684 	*/
24685 	NORMALIZE(type);
24686 	/*
24687 	* VAL TODO: Optimize validation of empty values.
24688 	* VAL TODO: We do not have computed values for lists.
24689 	*/
24690 	itemType = WXS_LIST_ITEMTYPE(type);
24691 	cur = value;
24692 	do {
24693 	    while (IS_BLANK_CH(*cur))
24694 		cur++;
24695 	    end = cur;
24696 	    while ((*end != 0) && (!(IS_BLANK_CH(*end))))
24697 		end++;
24698 	    if (end == cur)
24699 		break;
24700 	    tmpValue = xmlStrndup(cur, end - cur);
24701 	    len++;
24702 
24703 	    if (valNeeded)
24704 		ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24705 		    tmpValue, &curVal, fireErrors, 0, 1);
24706 	    else
24707 		ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24708 		    tmpValue, NULL, fireErrors, 0, 1);
24709 	    FREE_AND_NULL(tmpValue);
24710 	    if (curVal != NULL) {
24711 		/*
24712 		* Add to list of computed values.
24713 		*/
24714 		if (val == NULL)
24715 		    val = curVal;
24716 		else
24717 		    xmlSchemaValueAppend(prevVal, curVal);
24718 		prevVal = curVal;
24719 		curVal = NULL;
24720 	    }
24721 	    if (ret != 0) {
24722 		if (ret < 0) {
24723 		    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24724 			"validating an item of list simple type");
24725 		    goto internal_error;
24726 		}
24727 		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24728 		break;
24729 	    }
24730 	    cur = end;
24731 	} while (*cur != 0);
24732 	FREE_AND_NULL(tmpValue);
24733 	if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24734 	    /*
24735 	    * Apply facets (pattern, enumeration).
24736 	    */
24737 	    ret = xmlSchemaValidateFacets(actxt, node, type,
24738 		XML_SCHEMAS_UNKNOWN, value, val,
24739 		len, fireErrors);
24740 	    if (ret != 0) {
24741 		if (ret < 0) {
24742 		    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24743 			"validating facets of list simple type");
24744 		    goto internal_error;
24745 		}
24746 		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24747 	    }
24748 	}
24749 	if (fireErrors && (ret > 0)) {
24750 	    /*
24751 	    * Report the normalized value.
24752 	    */
24753 	    normalize = 1;
24754 	    NORMALIZE(type);
24755 	    xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24756 	}
24757     } else if (WXS_IS_UNION(type)) {
24758 	xmlSchemaTypeLinkPtr memberLink;
24759 	/*
24760 	* TODO: For all datatypes `derived` by `union`  whiteSpace does
24761 	* not apply directly; however, the normalization behavior of `union`
24762 	* types is controlled by the value of whiteSpace on that one of the
24763 	* `memberTypes` against which the `union` is successfully validated.
24764 	*
24765 	* This means that the value is normalized by the first validating
24766 	* member type, then the facets of the union type are applied. This
24767 	* needs changing of the value!
24768 	*/
24769 
24770 	/*
24771 	* 1.2.3 if {variety} is `union` then the string must `match` a
24772 	* literal in the `lexical space` of at least one member of
24773 	* {member type definitions}
24774 	*/
24775 	memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
24776 	if (memberLink == NULL) {
24777 	    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24778 		"union simple type has no member types");
24779 	    goto internal_error;
24780 	}
24781 	/*
24782 	* Always normalize union type values, since we currently
24783 	* cannot store the whitespace information with the value
24784 	* itself; otherwise a later value-comparison would be
24785 	* not possible.
24786 	*/
24787 	while (memberLink != NULL) {
24788 	    if (valNeeded)
24789 		ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24790 		    memberLink->type, value, &val, 0, 1, 0);
24791 	    else
24792 		ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24793 		    memberLink->type, value, NULL, 0, 1, 0);
24794 	    if (ret <= 0)
24795 		break;
24796 	    memberLink = memberLink->next;
24797 	}
24798 	if (ret != 0) {
24799 	    if (ret < 0) {
24800 		AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24801 		    "validating members of union simple type");
24802 		goto internal_error;
24803 	    }
24804 	    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
24805 	}
24806 	/*
24807 	* Apply facets (pattern, enumeration).
24808 	*/
24809 	if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24810 	    /*
24811 	    * The normalization behavior of `union` types is controlled by
24812 	    * the value of whiteSpace on that one of the `memberTypes`
24813 	    * against which the `union` is successfully validated.
24814 	    */
24815 	    NORMALIZE(memberLink->type);
24816 	    ret = xmlSchemaValidateFacets(actxt, node, type,
24817 		XML_SCHEMAS_UNKNOWN, value, val,
24818 		0, fireErrors);
24819 	    if (ret != 0) {
24820 		if (ret < 0) {
24821 		    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24822 			"validating facets of union simple type");
24823 		    goto internal_error;
24824 		}
24825 		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
24826 	    }
24827 	}
24828 	if (fireErrors && (ret > 0))
24829 	    xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24830     }
24831 
24832     if (normValue != NULL)
24833 	xmlFree(normValue);
24834     if (ret == 0) {
24835 	if (retVal != NULL)
24836 	    *retVal = val;
24837 	else if (val != NULL)
24838 	    xmlSchemaFreeValue(val);
24839     } else if (val != NULL)
24840 	xmlSchemaFreeValue(val);
24841     return (ret);
24842 internal_error:
24843     if (normValue != NULL)
24844 	xmlFree(normValue);
24845     if (val != NULL)
24846 	xmlSchemaFreeValue(val);
24847     return (-1);
24848 }
24849 
24850 static int
xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt,const xmlChar * value,const xmlChar ** nsName,const xmlChar ** localName)24851 xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt,
24852 			   const xmlChar *value,
24853 			   const xmlChar **nsName,
24854 			   const xmlChar **localName)
24855 {
24856     int ret = 0;
24857 
24858     if ((nsName == NULL) || (localName == NULL))
24859 	return (-1);
24860     *nsName = NULL;
24861     *localName = NULL;
24862 
24863     ret = xmlValidateQName(value, 1);
24864     if (ret == -1)
24865 	return (-1);
24866     if (ret > 0) {
24867 	xmlSchemaSimpleTypeErr(ACTXT_CAST vctxt,
24868 	    XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
24869 	    value, xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), 1);
24870 	return (1);
24871     }
24872     {
24873 	xmlChar *local = NULL;
24874 	xmlChar *prefix;
24875 
24876 	/*
24877 	* NOTE: xmlSplitQName2 will return a duplicated
24878 	* string.
24879 	*/
24880 	local = xmlSplitQName2(value, &prefix);
24881 	if (local == NULL)
24882 	    *localName = xmlDictLookup(vctxt->dict, value, -1);
24883 	else {
24884 	    *localName = xmlDictLookup(vctxt->dict, local, -1);
24885 	    xmlFree(local);
24886 	}
24887 
24888 	*nsName = xmlSchemaLookupNamespace(vctxt, prefix);
24889 
24890 	if (prefix != NULL) {
24891 	    xmlFree(prefix);
24892 	    /*
24893 	    * A namespace must be found if the prefix is NOT NULL.
24894 	    */
24895 	    if (*nsName == NULL) {
24896 		xmlSchemaCustomErr(ACTXT_CAST vctxt,
24897 		    XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
24898 		    WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24899 		    "The QName value '%s' has no "
24900 		    "corresponding namespace declaration in scope",
24901 		    value, NULL);
24902 		return (2);
24903 	    }
24904 	}
24905     }
24906     return (0);
24907 }
24908 
24909 static int
xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,xmlSchemaAttrInfoPtr iattr,xmlSchemaTypePtr * localType,xmlSchemaElementPtr elemDecl)24910 xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,
24911 			xmlSchemaAttrInfoPtr iattr,
24912 			xmlSchemaTypePtr *localType,
24913 			xmlSchemaElementPtr elemDecl)
24914 {
24915     int ret = 0;
24916     /*
24917     * cvc-elt (3.3.4) : (4)
24918     * AND
24919     * Schema-Validity Assessment (Element) (cvc-assess-elt)
24920     *   (1.2.1.2.1) - (1.2.1.2.4)
24921     * Handle 'xsi:type'.
24922     */
24923     if (localType == NULL)
24924 	return (-1);
24925     *localType = NULL;
24926     if (iattr == NULL)
24927 	return (0);
24928     else {
24929 	const xmlChar *nsName = NULL, *local = NULL;
24930 	/*
24931 	* TODO: We should report a *warning* that the type was overriden
24932 	* by the instance.
24933 	*/
24934 	ACTIVATE_ATTRIBUTE(iattr);
24935 	/*
24936 	* (cvc-elt) (3.3.4) : (4.1)
24937 	* (cvc-assess-elt) (1.2.1.2.2)
24938 	*/
24939 	ret = xmlSchemaVExpandQName(vctxt, iattr->value,
24940 	    &nsName, &local);
24941 	if (ret != 0) {
24942 	    if (ret < 0) {
24943 		VERROR_INT("xmlSchemaValidateElementByDeclaration",
24944 		    "calling xmlSchemaQNameExpand() to validate the "
24945 		    "attribute 'xsi:type'");
24946 		goto internal_error;
24947 	    }
24948 	    goto exit;
24949 	}
24950 	/*
24951 	* (cvc-elt) (3.3.4) : (4.2)
24952 	* (cvc-assess-elt) (1.2.1.2.3)
24953 	*/
24954 	*localType = xmlSchemaGetType(vctxt->schema, local, nsName);
24955 	if (*localType == NULL) {
24956 	    xmlChar *str = NULL;
24957 
24958 	    xmlSchemaCustomErr(ACTXT_CAST vctxt,
24959 		XML_SCHEMAV_CVC_ELT_4_2, NULL,
24960 		WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24961 		"The QName value '%s' of the xsi:type attribute does not "
24962 		"resolve to a type definition",
24963 		xmlSchemaFormatQName(&str, nsName, local), NULL);
24964 	    FREE_AND_NULL(str);
24965 	    ret = vctxt->err;
24966 	    goto exit;
24967 	}
24968 	if (elemDecl != NULL) {
24969 	    int set = 0;
24970 
24971 	    /*
24972 	    * SPEC cvc-elt (3.3.4) : (4.3) (Type Derivation OK)
24973 	    * "The `local type definition` must be validly
24974 	    * derived from the {type definition} given the union of
24975 	    * the {disallowed substitutions} and the {type definition}'s
24976 	    * {prohibited substitutions}, as defined in
24977 	    * Type Derivation OK (Complex) ($3.4.6)
24978 	    * (if it is a complex type definition),
24979 	    * or given {disallowed substitutions} as defined in Type
24980 	    * Derivation OK (Simple) ($3.14.6) (if it is a simple type
24981 	    * definition)."
24982 	    *
24983 	    * {disallowed substitutions}: the "block" on the element decl.
24984 	    * {prohibited substitutions}: the "block" on the type def.
24985 	    */
24986 	    /*
24987 	    * OPTIMIZE TODO: We could map types already evaluated
24988 	    * to be validly derived from other types to avoid checking
24989 	    * this over and over for the same types.
24990 	    */
24991 	    if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) ||
24992 		(elemDecl->subtypes->flags &
24993 		    XML_SCHEMAS_TYPE_BLOCK_EXTENSION))
24994 		set |= SUBSET_EXTENSION;
24995 
24996 	    if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) ||
24997 		(elemDecl->subtypes->flags &
24998 		    XML_SCHEMAS_TYPE_BLOCK_RESTRICTION))
24999 		set |= SUBSET_RESTRICTION;
25000 
25001 	    /*
25002 	    * REMOVED and CHANGED since this produced a parser context
25003 	    * which adds to the string dict of the schema. So this would
25004 	    * change the schema and we don't want this. We don't need
25005 	    * the parser context anymore.
25006 	    *
25007 	    * if ((vctxt->pctxt == NULL) &&
25008 	    *	(xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
25009 	    *	    return (-1);
25010 	    */
25011 
25012 	    if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST vctxt, *localType,
25013 		elemDecl->subtypes, set) != 0) {
25014 		xmlChar *str = NULL;
25015 
25016 		xmlSchemaCustomErr(ACTXT_CAST vctxt,
25017 		    XML_SCHEMAV_CVC_ELT_4_3, NULL, NULL,
25018 		    "The type definition '%s', specified by xsi:type, is "
25019 		    "blocked or not validly derived from the type definition "
25020 		    "of the element declaration",
25021 		    xmlSchemaFormatQName(&str,
25022 			(*localType)->targetNamespace,
25023 			(*localType)->name),
25024 		    NULL);
25025 		FREE_AND_NULL(str);
25026 		ret = vctxt->err;
25027 		*localType = NULL;
25028 	    }
25029 	}
25030     }
25031 exit:
25032     ACTIVATE_ELEM;
25033     return (ret);
25034 internal_error:
25035     ACTIVATE_ELEM;
25036     return (-1);
25037 }
25038 
25039 static int
xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt)25040 xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt)
25041 {
25042     xmlSchemaElementPtr elemDecl = vctxt->inode->decl;
25043     xmlSchemaTypePtr actualType;
25044 
25045     /*
25046     * cvc-elt (3.3.4) : 1
25047     */
25048     if (elemDecl == NULL) {
25049 	VERROR(XML_SCHEMAV_CVC_ELT_1, NULL,
25050 	    "No matching declaration available");
25051         return (vctxt->err);
25052     }
25053     actualType = WXS_ELEM_TYPEDEF(elemDecl);
25054     /*
25055     * cvc-elt (3.3.4) : 2
25056     */
25057     if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
25058 	VERROR(XML_SCHEMAV_CVC_ELT_2, NULL,
25059 	    "The element declaration is abstract");
25060         return (vctxt->err);
25061     }
25062     if (actualType == NULL) {
25063 	VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
25064 	    "The type definition is absent");
25065 	return (XML_SCHEMAV_CVC_TYPE_1);
25066     }
25067     if (vctxt->nbAttrInfos != 0) {
25068 	int ret;
25069 	xmlSchemaAttrInfoPtr iattr;
25070 	/*
25071 	* cvc-elt (3.3.4) : 3
25072 	* Handle 'xsi:nil'.
25073 	*/
25074 	iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25075 	    XML_SCHEMA_ATTR_INFO_META_XSI_NIL);
25076 	if (iattr) {
25077 	    ACTIVATE_ATTRIBUTE(iattr);
25078 	    /*
25079 	    * Validate the value.
25080 	    */
25081 	    ret = xmlSchemaVCheckCVCSimpleType(
25082 		ACTXT_CAST vctxt, NULL,
25083 		xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
25084 		iattr->value, &(iattr->val), 1, 0, 0);
25085 	    ACTIVATE_ELEM;
25086 	    if (ret < 0) {
25087 		VERROR_INT("xmlSchemaValidateElemDecl",
25088 		    "calling xmlSchemaVCheckCVCSimpleType() to "
25089 		    "validate the attribute 'xsi:nil'");
25090 		return (-1);
25091 	    }
25092 	    if (ret == 0) {
25093 		if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
25094 		    /*
25095 		    * cvc-elt (3.3.4) : 3.1
25096 		    */
25097 		    VERROR(XML_SCHEMAV_CVC_ELT_3_1, NULL,
25098 			"The element is not 'nillable'");
25099 		    /* Does not return an error on purpose. */
25100 		} else {
25101 		    if (xmlSchemaValueGetAsBoolean(iattr->val)) {
25102 			/*
25103 			* cvc-elt (3.3.4) : 3.2.2
25104 			*/
25105 			if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
25106 			    (elemDecl->value != NULL)) {
25107 			    VERROR(XML_SCHEMAV_CVC_ELT_3_2_2, NULL,
25108 				"The element cannot be 'nilled' because "
25109 				"there is a fixed value constraint defined "
25110 				"for it");
25111 			     /* Does not return an error on purpose. */
25112 			} else
25113 			    vctxt->inode->flags |=
25114 				XML_SCHEMA_ELEM_INFO_NILLED;
25115 		    }
25116 		}
25117 	    }
25118 	}
25119 	/*
25120 	* cvc-elt (3.3.4) : 4
25121 	* Handle 'xsi:type'.
25122 	*/
25123 	iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25124 	    XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
25125 	if (iattr) {
25126 	    xmlSchemaTypePtr localType = NULL;
25127 
25128 	    ret = xmlSchemaProcessXSIType(vctxt, iattr, &localType,
25129 		elemDecl);
25130 	    if (ret != 0) {
25131 		if (ret == -1) {
25132 		    VERROR_INT("xmlSchemaValidateElemDecl",
25133 			"calling xmlSchemaProcessXSIType() to "
25134 			"process the attribute 'xsi:type'");
25135 		    return (-1);
25136 		}
25137 		/* Does not return an error on purpose. */
25138 	    }
25139 	    if (localType != NULL) {
25140 		vctxt->inode->flags |= XML_SCHEMA_ELEM_INFO_LOCAL_TYPE;
25141 		actualType = localType;
25142 	    }
25143 	}
25144     }
25145     /*
25146     * IDC: Register identity-constraint XPath matchers.
25147     */
25148     if ((elemDecl->idcs != NULL) &&
25149 	(xmlSchemaIDCRegisterMatchers(vctxt, elemDecl) == -1))
25150 	    return (-1);
25151     /*
25152     * No actual type definition.
25153     */
25154     if (actualType == NULL) {
25155 	VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
25156 	    "The type definition is absent");
25157 	return (XML_SCHEMAV_CVC_TYPE_1);
25158     }
25159     /*
25160     * Remember the actual type definition.
25161     */
25162     vctxt->inode->typeDef = actualType;
25163 
25164     return (0);
25165 }
25166 
25167 static int
xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt)25168 xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt)
25169 {
25170     xmlSchemaAttrInfoPtr iattr;
25171     int ret = 0, i;
25172 
25173     /*
25174     * SPEC cvc-type (3.1.1)
25175     * "The attributes of must be empty, excepting those whose namespace
25176     * name is identical to http://www.w3.org/2001/XMLSchema-instance and
25177     * whose local name is one of type, nil, schemaLocation or
25178     * noNamespaceSchemaLocation."
25179     */
25180     if (vctxt->nbAttrInfos == 0)
25181 	return (0);
25182     for (i = 0; i < vctxt->nbAttrInfos; i++) {
25183 	iattr = vctxt->attrInfos[i];
25184 	if (! iattr->metaType) {
25185 	    ACTIVATE_ATTRIBUTE(iattr)
25186 	    xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25187 		XML_SCHEMAV_CVC_TYPE_3_1_1, iattr, NULL);
25188 	    ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
25189         }
25190     }
25191     ACTIVATE_ELEM
25192     return (ret);
25193 }
25194 
25195 /*
25196 * Cleanup currently used attribute infos.
25197 */
25198 static void
xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)25199 xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)
25200 {
25201     int i;
25202     xmlSchemaAttrInfoPtr attr;
25203 
25204     if (vctxt->nbAttrInfos == 0)
25205 	return;
25206     for (i = 0; i < vctxt->nbAttrInfos; i++) {
25207 	attr = vctxt->attrInfos[i];
25208 	if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
25209 	    if (attr->localName != NULL)
25210 		xmlFree((xmlChar *) attr->localName);
25211 	    if (attr->nsName != NULL)
25212 		xmlFree((xmlChar *) attr->nsName);
25213 	}
25214 	if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
25215 	    if (attr->value != NULL)
25216 		xmlFree((xmlChar *) attr->value);
25217 	}
25218 	if (attr->val != NULL) {
25219 	    xmlSchemaFreeValue(attr->val);
25220 	    attr->val = NULL;
25221 	}
25222 	memset(attr, 0, sizeof(xmlSchemaAttrInfo));
25223     }
25224     vctxt->nbAttrInfos = 0;
25225 }
25226 
25227 /*
25228 * 3.4.4 Complex Type Definition Validation Rules
25229 *   Element Locally Valid (Complex Type) (cvc-complex-type)
25230 * 3.2.4 Attribute Declaration Validation Rules
25231 *   Validation Rule: Attribute Locally Valid (cvc-attribute)
25232 *   Attribute Locally Valid (Use) (cvc-au)
25233 *
25234 * Only "assessed" attribute information items will be visible to
25235 * IDCs. I.e. not "lax" (without declaration) and "skip" wild attributes.
25236 */
25237 static int
xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)25238 xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)
25239 {
25240     xmlSchemaTypePtr type = vctxt->inode->typeDef;
25241     xmlSchemaItemListPtr attrUseList;
25242     xmlSchemaAttributeUsePtr attrUse = NULL;
25243     xmlSchemaAttributePtr attrDecl = NULL;
25244     xmlSchemaAttrInfoPtr iattr, tmpiattr;
25245     int i, j, found, nbAttrs, nbUses;
25246     int xpathRes = 0, res, wildIDs = 0, fixed;
25247     xmlNodePtr defAttrOwnerElem = NULL;
25248 
25249     /*
25250     * SPEC (cvc-attribute)
25251     * (1) "The declaration must not be `absent` (see Missing
25252     * Sub-components ($5.3) for how this can fail to be
25253     * the case)."
25254     * (2) "Its {type definition} must not be absent."
25255     *
25256     * NOTE (1) + (2): This is not handled here, since we currently do not
25257     * allow validation against schemas which have missing sub-components.
25258     *
25259     * SPEC (cvc-complex-type)
25260     * (3) "For each attribute information item in the element information
25261     * item's [attributes] excepting those whose [namespace name] is
25262     * identical to http://www.w3.org/2001/XMLSchema-instance and whose
25263     * [local name] is one of type, nil, schemaLocation or
25264     * noNamespaceSchemaLocation, the appropriate case among the following
25265     * must be true:
25266     *
25267     */
25268     attrUseList = (xmlSchemaItemListPtr) type->attrUses;
25269     /*
25270     * @nbAttrs is the number of attributes present in the instance.
25271     */
25272     nbAttrs = vctxt->nbAttrInfos;
25273     if (attrUseList != NULL)
25274 	nbUses = attrUseList->nbItems;
25275     else
25276 	nbUses = 0;
25277     for (i = 0; i < nbUses; i++) {
25278         found = 0;
25279 	attrUse = attrUseList->items[i];
25280 	attrDecl = WXS_ATTRUSE_DECL(attrUse);
25281         for (j = 0; j < nbAttrs; j++) {
25282 	    iattr = vctxt->attrInfos[j];
25283 	    /*
25284 	    * SPEC (cvc-complex-type) (3)
25285 	    * Skip meta attributes.
25286 	    */
25287 	    if (iattr->metaType)
25288 		continue;
25289 	    if (iattr->localName[0] != attrDecl->name[0])
25290 		continue;
25291 	    if (!xmlStrEqual(iattr->localName, attrDecl->name))
25292 		continue;
25293 	    if (!xmlStrEqual(iattr->nsName, attrDecl->targetNamespace))
25294 		continue;
25295 	    found = 1;
25296 	    /*
25297 	    * SPEC (cvc-complex-type)
25298 	    * (3.1) "If there is among the {attribute uses} an attribute
25299 	    * use with an {attribute declaration} whose {name} matches
25300 	    * the attribute information item's [local name] and whose
25301 	    * {target namespace} is identical to the attribute information
25302 	    * item's [namespace name] (where an `absent` {target namespace}
25303 	    * is taken to be identical to a [namespace name] with no value),
25304 	    * then the attribute information must be `valid` with respect
25305 	    * to that attribute use as per Attribute Locally Valid (Use)
25306 	    * ($3.5.4). In this case the {attribute declaration} of that
25307 	    * attribute use is the `context-determined declaration` for the
25308 	    * attribute information item with respect to Schema-Validity
25309 	    * Assessment (Attribute) ($3.2.4) and
25310 	    * Assessment Outcome (Attribute) ($3.2.5).
25311 	    */
25312 	    iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
25313 	    iattr->use = attrUse;
25314 	    /*
25315 	    * Context-determined declaration.
25316 	    */
25317 	    iattr->decl = attrDecl;
25318 	    iattr->typeDef = attrDecl->subtypes;
25319 	    break;
25320 	}
25321 
25322 	if (found)
25323 	    continue;
25324 
25325 	if (attrUse->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
25326 	    /*
25327 	    * Handle non-existent, required attributes.
25328 	    *
25329 	    * SPEC (cvc-complex-type)
25330 	    * (4) "The {attribute declaration} of each attribute use in
25331 	    * the {attribute uses} whose {required} is true matches one
25332 	    * of the attribute information items in the element information
25333 	    * item's [attributes] as per clause 3.1 above."
25334 	    */
25335 	    tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
25336 	    if (tmpiattr == NULL) {
25337 		VERROR_INT(
25338 		    "xmlSchemaVAttributesComplex",
25339 		    "calling xmlSchemaGetFreshAttrInfo()");
25340 		return (-1);
25341 	    }
25342 	    tmpiattr->state = XML_SCHEMAS_ATTR_ERR_MISSING;
25343 	    tmpiattr->use = attrUse;
25344 	    tmpiattr->decl = attrDecl;
25345 	} else if ((attrUse->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
25346 	    ((attrUse->defValue != NULL) ||
25347 	     (attrDecl->defValue != NULL))) {
25348 	    /*
25349 	    * Handle non-existent, optional, default/fixed attributes.
25350 	    */
25351 	    tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
25352 	    if (tmpiattr == NULL) {
25353 		VERROR_INT(
25354 		    "xmlSchemaVAttributesComplex",
25355 		    "calling xmlSchemaGetFreshAttrInfo()");
25356 		return (-1);
25357 	    }
25358 	    tmpiattr->state = XML_SCHEMAS_ATTR_DEFAULT;
25359 	    tmpiattr->use = attrUse;
25360 	    tmpiattr->decl = attrDecl;
25361 	    tmpiattr->typeDef = attrDecl->subtypes;
25362 	    tmpiattr->localName = attrDecl->name;
25363 	    tmpiattr->nsName = attrDecl->targetNamespace;
25364 	}
25365     }
25366 
25367     if (vctxt->nbAttrInfos == 0)
25368 	return (0);
25369     /*
25370     * Validate against the wildcard.
25371     */
25372     if (type->attributeWildcard != NULL) {
25373 	/*
25374 	* SPEC (cvc-complex-type)
25375 	* (3.2.1) "There must be an {attribute wildcard}."
25376 	*/
25377 	for (i = 0; i < nbAttrs; i++) {
25378 	    iattr = vctxt->attrInfos[i];
25379 	    /*
25380 	    * SPEC (cvc-complex-type) (3)
25381 	    * Skip meta attributes.
25382 	    */
25383 	    if (iattr->state != XML_SCHEMAS_ATTR_UNKNOWN)
25384 		continue;
25385 	    /*
25386 	    * SPEC (cvc-complex-type)
25387 	    * (3.2.2) "The attribute information item must be `valid` with
25388 	    * respect to it as defined in Item Valid (Wildcard) ($3.10.4)."
25389 	    *
25390 	    * SPEC Item Valid (Wildcard) (cvc-wildcard)
25391 	    * "... its [namespace name] must be `valid` with respect to
25392 	    * the wildcard constraint, as defined in Wildcard allows
25393 	    * Namespace Name ($3.10.4)."
25394 	    */
25395 	    if (xmlSchemaCheckCVCWildcardNamespace(type->attributeWildcard,
25396 		    iattr->nsName) == 0) {
25397 		/*
25398 		* Handle processContents.
25399 		*
25400 		* SPEC (cvc-wildcard):
25401 		* processContents | context-determined declaration:
25402 		* "strict"          "mustFind"
25403 		* "lax"             "none"
25404 		* "skip"            "skip"
25405 		*/
25406 		if (type->attributeWildcard->processContents ==
25407 		    XML_SCHEMAS_ANY_SKIP) {
25408 		     /*
25409 		    * context-determined declaration = "skip"
25410 		    *
25411 		    * SPEC PSVI Assessment Outcome (Attribute)
25412 		    * [validity] = "notKnown"
25413 		    * [validation attempted] = "none"
25414 		    */
25415 		    iattr->state = XML_SCHEMAS_ATTR_WILD_SKIP;
25416 		    continue;
25417 		}
25418 		/*
25419 		* Find an attribute declaration.
25420 		*/
25421 		iattr->decl = xmlSchemaGetAttributeDecl(vctxt->schema,
25422 		    iattr->localName, iattr->nsName);
25423 		if (iattr->decl != NULL) {
25424 		    iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
25425 		    /*
25426 		    * SPEC (cvc-complex-type)
25427 		    * (5) "Let [Definition:]  the wild IDs be the set of
25428 		    * all attribute information item to which clause 3.2
25429 		    * applied and whose `validation` resulted in a
25430 		    * `context-determined declaration` of mustFind or no
25431 		    * `context-determined declaration` at all, and whose
25432 		    * [local name] and [namespace name] resolve (as
25433 		    * defined by QName resolution (Instance) ($3.15.4)) to
25434 		    * an attribute declaration whose {type definition} is
25435 		    * or is derived from ID. Then all of the following
25436 		    * must be true:"
25437 		    */
25438 		    iattr->typeDef = WXS_ATTR_TYPEDEF(iattr->decl);
25439 		    if (xmlSchemaIsDerivedFromBuiltInType(
25440 			iattr->typeDef, XML_SCHEMAS_ID)) {
25441 			/*
25442 			* SPEC (5.1) "There must be no more than one
25443 			* item in `wild IDs`."
25444 			*/
25445 			if (wildIDs != 0) {
25446 			    /* VAL TODO */
25447 			    iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID;
25448 			    TODO
25449 			    continue;
25450 			}
25451 			wildIDs++;
25452 			/*
25453 			* SPEC (cvc-complex-type)
25454 			* (5.2) "If `wild IDs` is non-empty, there must not
25455 			* be any attribute uses among the {attribute uses}
25456 			* whose {attribute declaration}'s {type definition}
25457 			* is or is derived from ID."
25458 			*/
25459                         if (attrUseList != NULL) {
25460                             for (j = 0; j < attrUseList->nbItems; j++) {
25461                                 if (xmlSchemaIsDerivedFromBuiltInType(
25462                                     WXS_ATTRUSE_TYPEDEF(attrUseList->items[j]),
25463                                     XML_SCHEMAS_ID)) {
25464                                     /* URGENT VAL TODO: implement */
25465                             iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID;
25466                                     TODO
25467                                     break;
25468                                 }
25469                             }
25470                         }
25471 		    }
25472 		} else if (type->attributeWildcard->processContents ==
25473 		    XML_SCHEMAS_ANY_LAX) {
25474 		    iattr->state = XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL;
25475 		    /*
25476 		    * SPEC PSVI Assessment Outcome (Attribute)
25477 		    * [validity] = "notKnown"
25478 		    * [validation attempted] = "none"
25479 		    */
25480 		} else {
25481 		    iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL;
25482 		}
25483 	    }
25484 	}
25485     }
25486 
25487     if (vctxt->nbAttrInfos == 0)
25488 	return (0);
25489 
25490     /*
25491     * Get the owner element; needed for creation of default attributes.
25492     * This fixes bug #341337, reported by David Grohmann.
25493     */
25494     if (vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
25495 	xmlSchemaNodeInfoPtr ielem = vctxt->elemInfos[vctxt->depth];
25496 	if (ielem && ielem->node && ielem->node->doc)
25497 	    defAttrOwnerElem = ielem->node;
25498     }
25499     /*
25500     * Validate values, create default attributes, evaluate IDCs.
25501     */
25502     for (i = 0; i < vctxt->nbAttrInfos; i++) {
25503 	iattr = vctxt->attrInfos[i];
25504 	/*
25505 	* VAL TODO: Note that we won't try to resolve IDCs to
25506 	* "lax" and "skip" validated attributes. Check what to
25507 	* do in this case.
25508 	*/
25509 	if ((iattr->state != XML_SCHEMAS_ATTR_ASSESSED) &&
25510 	    (iattr->state != XML_SCHEMAS_ATTR_DEFAULT))
25511 	    continue;
25512 	/*
25513 	* VAL TODO: What to do if the type definition is missing?
25514 	*/
25515 	if (iattr->typeDef == NULL) {
25516 	    iattr->state = XML_SCHEMAS_ATTR_ERR_NO_TYPE;
25517 	    continue;
25518 	}
25519 
25520 	ACTIVATE_ATTRIBUTE(iattr);
25521 	fixed = 0;
25522 	xpathRes = 0;
25523 
25524 	if (vctxt->xpathStates != NULL) {
25525 	    /*
25526 	    * Evaluate IDCs.
25527 	    */
25528 	    xpathRes = xmlSchemaXPathEvaluate(vctxt,
25529 		XML_ATTRIBUTE_NODE);
25530 	    if (xpathRes == -1) {
25531 		VERROR_INT("xmlSchemaVAttributesComplex",
25532 		    "calling xmlSchemaXPathEvaluate()");
25533 		goto internal_error;
25534 	    }
25535 	}
25536 
25537 	if (iattr->state == XML_SCHEMAS_ATTR_DEFAULT) {
25538 	    /*
25539 	    * Default/fixed attributes.
25540 	    * We need the value only if we need to resolve IDCs or
25541 	    * will create default attributes.
25542 	    */
25543 	    if ((xpathRes) || (defAttrOwnerElem)) {
25544 		if (iattr->use->defValue != NULL) {
25545 		    iattr->value = (xmlChar *) iattr->use->defValue;
25546 		    iattr->val = iattr->use->defVal;
25547 		} else {
25548 		    iattr->value = (xmlChar *) iattr->decl->defValue;
25549 		    iattr->val = iattr->decl->defVal;
25550 		}
25551 		/*
25552 		* IDCs will consume the precomputed default value,
25553 		* so we need to clone it.
25554 		*/
25555 		if (iattr->val == NULL) {
25556 		    VERROR_INT("xmlSchemaVAttributesComplex",
25557 			"default/fixed value on an attribute use was "
25558 			"not precomputed");
25559 		    goto internal_error;
25560 		}
25561 		iattr->val = xmlSchemaCopyValue(iattr->val);
25562 		if (iattr->val == NULL) {
25563 		    VERROR_INT("xmlSchemaVAttributesComplex",
25564 			"calling xmlSchemaCopyValue()");
25565 		    goto internal_error;
25566 		}
25567 	    }
25568 	    /*
25569 	    * PSVI: Add the default attribute to the current element.
25570 	    * VAL TODO: Should we use the *normalized* value? This currently
25571 	    *   uses the *initial* value.
25572 	    */
25573 
25574 	    if (defAttrOwnerElem) {
25575 		xmlChar *normValue;
25576 		const xmlChar *value;
25577 
25578 		value = iattr->value;
25579 		/*
25580 		* Normalize the value.
25581 		*/
25582 		normValue = xmlSchemaNormalizeValue(iattr->typeDef,
25583 		    iattr->value);
25584 		if (normValue != NULL)
25585 		    value = BAD_CAST normValue;
25586 
25587 		if (iattr->nsName == NULL) {
25588 		    if (xmlNewProp(defAttrOwnerElem,
25589 			iattr->localName, value) == NULL) {
25590 			VERROR_INT("xmlSchemaVAttributesComplex",
25591 			    "calling xmlNewProp()");
25592 			if (normValue != NULL)
25593 			    xmlFree(normValue);
25594 			goto internal_error;
25595 		    }
25596 		} else {
25597 		    xmlNsPtr ns;
25598 
25599 		    ns = xmlSearchNsByHref(defAttrOwnerElem->doc,
25600 			defAttrOwnerElem, iattr->nsName);
25601 		    if (ns == NULL) {
25602 			xmlChar prefix[12];
25603 			int counter = 0;
25604 
25605 			/*
25606 			* Create a namespace declaration on the validation
25607 			* root node if no namespace declaration is in scope.
25608 			*/
25609 			do {
25610 			    snprintf((char *) prefix, 12, "p%d", counter++);
25611 			    ns = xmlSearchNs(defAttrOwnerElem->doc,
25612 				defAttrOwnerElem, BAD_CAST prefix);
25613 			    if (counter > 1000) {
25614 				VERROR_INT(
25615 				    "xmlSchemaVAttributesComplex",
25616 				    "could not compute a ns prefix for a "
25617 				    "default/fixed attribute");
25618 				if (normValue != NULL)
25619 				    xmlFree(normValue);
25620 				goto internal_error;
25621 			    }
25622 			} while (ns != NULL);
25623 			ns = xmlNewNs(vctxt->validationRoot,
25624 			    iattr->nsName, BAD_CAST prefix);
25625 		    }
25626 		    /*
25627 		    * TODO:
25628 		    * http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0406.html
25629 		    * If we have QNames: do we need to ensure there's a
25630 		    * prefix defined for the QName?
25631 		    */
25632 		    xmlNewNsProp(defAttrOwnerElem, ns, iattr->localName, value);
25633 		}
25634 		if (normValue != NULL)
25635 		    xmlFree(normValue);
25636 	    }
25637 	    /*
25638 	    * Go directly to IDC evaluation.
25639 	    */
25640 	    goto eval_idcs;
25641 	}
25642 	/*
25643 	* Validate the value.
25644 	*/
25645 	if (vctxt->value != NULL) {
25646 	    /*
25647 	    * Free last computed value; just for safety reasons.
25648 	    */
25649 	    xmlSchemaFreeValue(vctxt->value);
25650 	    vctxt->value = NULL;
25651 	}
25652 	/*
25653 	* Note that the attribute *use* can be unavailable, if
25654 	* the attribute was a wild attribute.
25655 	*/
25656 	if ((iattr->decl->flags & XML_SCHEMAS_ATTR_FIXED) ||
25657 	    ((iattr->use != NULL) &&
25658 	     (iattr->use->flags & XML_SCHEMAS_ATTR_FIXED)))
25659 	    fixed = 1;
25660 	else
25661 	    fixed = 0;
25662 	/*
25663 	* SPEC (cvc-attribute)
25664 	* (3) "The item's `normalized value` must be locally `valid`
25665 	* with respect to that {type definition} as per
25666 	* String Valid ($3.14.4)."
25667 	*
25668 	* VAL TODO: Do we already have the
25669 	* "normalized attribute value" here?
25670 	*/
25671 	if (xpathRes || fixed) {
25672 	    iattr->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
25673 	    /*
25674 	    * Request a computed value.
25675 	    */
25676 	    res = xmlSchemaVCheckCVCSimpleType(
25677 		ACTXT_CAST vctxt,
25678 		iattr->node, iattr->typeDef, iattr->value, &(iattr->val),
25679 		1, 1, 0);
25680 	} else {
25681 	    res = xmlSchemaVCheckCVCSimpleType(
25682 		ACTXT_CAST vctxt,
25683 		iattr->node, iattr->typeDef, iattr->value, NULL,
25684 		1, 0, 0);
25685 	}
25686 
25687 	if (res != 0) {
25688 	    if (res == -1) {
25689 		VERROR_INT("xmlSchemaVAttributesComplex",
25690 		    "calling xmlSchemaStreamValidateSimpleTypeValue()");
25691 		goto internal_error;
25692 	    }
25693 	    iattr->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
25694 	    /*
25695 	    * SPEC PSVI Assessment Outcome (Attribute)
25696 	    * [validity] = "invalid"
25697 	    */
25698 	    goto eval_idcs;
25699 	}
25700 
25701 	if (fixed) {
25702 	    /*
25703 	    * SPEC Attribute Locally Valid (Use) (cvc-au)
25704 	    * "For an attribute information item to be `valid`
25705 	    * with respect to an attribute use its *normalized*
25706 	    * value must match the *canonical* lexical
25707 	    * representation of the attribute use's {value
25708 	    * constraint}value, if it is present and fixed."
25709 	    *
25710 	    * VAL TODO: The requirement for the *canonical* value
25711 	    * will be removed in XML Schema 1.1.
25712 	    */
25713 	    /*
25714 	    * SPEC Attribute Locally Valid (cvc-attribute)
25715 	    * (4) "The item's *actual* value must match the *value* of
25716 	    * the {value constraint}, if it is present and fixed."
25717 	    */
25718 	    if (iattr->val == NULL) {
25719 		/* VAL TODO: A value was not precomputed. */
25720 		TODO
25721 		goto eval_idcs;
25722 	    }
25723 	    if ((iattr->use != NULL) &&
25724 		(iattr->use->defValue != NULL)) {
25725 		if (iattr->use->defVal == NULL) {
25726 		    /* VAL TODO: A default value was not precomputed. */
25727 		    TODO
25728 		    goto eval_idcs;
25729 		}
25730 		iattr->vcValue = iattr->use->defValue;
25731 		/*
25732 		if (xmlSchemaCompareValuesWhtsp(attr->val,
25733 		    (xmlSchemaWhitespaceValueType) ws,
25734 		    attr->use->defVal,
25735 		    (xmlSchemaWhitespaceValueType) ws) != 0) {
25736 		*/
25737 		if (! xmlSchemaAreValuesEqual(iattr->val, iattr->use->defVal))
25738 		    iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
25739 	    } else {
25740 		if (iattr->decl->defVal == NULL) {
25741 		    /* VAL TODO: A default value was not precomputed. */
25742 		    TODO
25743 		    goto eval_idcs;
25744 		}
25745 		iattr->vcValue = iattr->decl->defValue;
25746 		/*
25747 		if (xmlSchemaCompareValuesWhtsp(attr->val,
25748 		    (xmlSchemaWhitespaceValueType) ws,
25749 		    attrDecl->defVal,
25750 		    (xmlSchemaWhitespaceValueType) ws) != 0) {
25751 		*/
25752 		if (! xmlSchemaAreValuesEqual(iattr->val, iattr->decl->defVal))
25753 		    iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
25754 	    }
25755 	    /*
25756 	    * [validity] = "valid"
25757 	    */
25758 	}
25759 eval_idcs:
25760 	/*
25761 	* Evaluate IDCs.
25762 	*/
25763 	if (xpathRes) {
25764 	    if (xmlSchemaXPathProcessHistory(vctxt,
25765 		vctxt->depth +1) == -1) {
25766 		VERROR_INT("xmlSchemaVAttributesComplex",
25767 		    "calling xmlSchemaXPathEvaluate()");
25768 		goto internal_error;
25769 	    }
25770 	} else if (vctxt->xpathStates != NULL)
25771 	    xmlSchemaXPathPop(vctxt);
25772     }
25773 
25774     /*
25775     * Report errors.
25776     */
25777     for (i = 0; i < vctxt->nbAttrInfos; i++) {
25778 	iattr = vctxt->attrInfos[i];
25779 	if ((iattr->state == XML_SCHEMAS_ATTR_META) ||
25780 	    (iattr->state == XML_SCHEMAS_ATTR_ASSESSED) ||
25781 	    (iattr->state == XML_SCHEMAS_ATTR_WILD_SKIP) ||
25782 	    (iattr->state == XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL))
25783 	    continue;
25784 	ACTIVATE_ATTRIBUTE(iattr);
25785 	switch (iattr->state) {
25786 	    case XML_SCHEMAS_ATTR_ERR_MISSING: {
25787 		    xmlChar *str = NULL;
25788 		    ACTIVATE_ELEM;
25789 		    xmlSchemaCustomErr(ACTXT_CAST vctxt,
25790 			XML_SCHEMAV_CVC_COMPLEX_TYPE_4, NULL, NULL,
25791 			"The attribute '%s' is required but missing",
25792 			xmlSchemaFormatQName(&str,
25793 			    iattr->decl->targetNamespace,
25794 			    iattr->decl->name),
25795 			NULL);
25796 		    FREE_AND_NULL(str)
25797 		    break;
25798 		}
25799 	    case XML_SCHEMAS_ATTR_ERR_NO_TYPE:
25800 		VERROR(XML_SCHEMAV_CVC_ATTRIBUTE_2, NULL,
25801 		    "The type definition is absent");
25802 		break;
25803 	    case XML_SCHEMAS_ATTR_ERR_FIXED_VALUE:
25804 		xmlSchemaCustomErr(ACTXT_CAST vctxt,
25805 		    XML_SCHEMAV_CVC_AU, NULL, NULL,
25806 		    "The value '%s' does not match the fixed "
25807 		    "value constraint '%s'",
25808 		    iattr->value, iattr->vcValue);
25809 		break;
25810 	    case XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL:
25811 		VERROR(XML_SCHEMAV_CVC_WILDCARD, NULL,
25812 		    "No matching global attribute declaration available, but "
25813 		    "demanded by the strict wildcard");
25814 		break;
25815 	    case XML_SCHEMAS_ATTR_UNKNOWN:
25816 		if (iattr->metaType)
25817 		    break;
25818 		/*
25819 		* MAYBE VAL TODO: One might report different error messages
25820 		* for the following errors.
25821 		*/
25822 		if (type->attributeWildcard == NULL) {
25823 		    xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25824 			XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, iattr, NULL);
25825 		} else {
25826 		    xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25827 			XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, iattr, NULL);
25828 		}
25829 		break;
25830 	    default:
25831 		break;
25832 	}
25833     }
25834 
25835     ACTIVATE_ELEM;
25836     return (0);
25837 internal_error:
25838     ACTIVATE_ELEM;
25839     return (-1);
25840 }
25841 
25842 static int
xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt,int * skip)25843 xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt,
25844 			      int *skip)
25845 {
25846     xmlSchemaWildcardPtr wild = (xmlSchemaWildcardPtr) vctxt->inode->decl;
25847     /*
25848     * The namespace of the element was already identified to be
25849     * matching the wildcard.
25850     */
25851     if ((skip == NULL) || (wild == NULL) ||
25852 	(wild->type != XML_SCHEMA_TYPE_ANY)) {
25853 	VERROR_INT("xmlSchemaValidateElemWildcard",
25854 	    "bad arguments");
25855 	return (-1);
25856     }
25857     *skip = 0;
25858     if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
25859 	/*
25860 	* URGENT VAL TODO: Either we need to position the stream to the
25861 	* next sibling, or walk the whole subtree.
25862 	*/
25863 	*skip = 1;
25864 	return (0);
25865     }
25866     {
25867 	xmlSchemaElementPtr decl = NULL;
25868 
25869 	decl = xmlSchemaGetElem(vctxt->schema,
25870 	    vctxt->inode->localName, vctxt->inode->nsName);
25871 	if (decl != NULL) {
25872 	    vctxt->inode->decl = decl;
25873 	    return (0);
25874 	}
25875     }
25876     if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
25877 	/* VAL TODO: Change to proper error code. */
25878 	VERROR(XML_SCHEMAV_CVC_ELT_1, NULL, /* WXS_BASIC_CAST wild */
25879 	    "No matching global element declaration available, but "
25880 	    "demanded by the strict wildcard");
25881 	return (vctxt->err);
25882     }
25883     if (vctxt->nbAttrInfos != 0) {
25884 	xmlSchemaAttrInfoPtr iattr;
25885 	/*
25886 	* SPEC Validation Rule: Schema-Validity Assessment (Element)
25887 	* (1.2.1.2.1) - (1.2.1.2.3 )
25888 	*
25889 	* Use the xsi:type attribute for the type definition.
25890 	*/
25891 	iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25892 	    XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
25893 	if (iattr != NULL) {
25894 	    if (xmlSchemaProcessXSIType(vctxt, iattr,
25895 		&(vctxt->inode->typeDef), NULL) == -1) {
25896 		VERROR_INT("xmlSchemaValidateElemWildcard",
25897 		    "calling xmlSchemaProcessXSIType() to "
25898 		    "process the attribute 'xsi:nil'");
25899 		return (-1);
25900 	    }
25901 	    /*
25902 	    * Don't return an error on purpose.
25903 	    */
25904 	    return (0);
25905 	}
25906     }
25907     /*
25908     * SPEC Validation Rule: Schema-Validity Assessment (Element)
25909     *
25910     * Fallback to "anyType".
25911     */
25912     vctxt->inode->typeDef =
25913 	xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
25914     return (0);
25915 }
25916 
25917 /*
25918 * xmlSchemaCheckCOSValidDefault:
25919 *
25920 * This will be called if: not nilled, no content and a default/fixed
25921 * value is provided.
25922 */
25923 
25924 static int
xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt,const xmlChar * value,xmlSchemaValPtr * val)25925 xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt,
25926 			      const xmlChar *value,
25927 			      xmlSchemaValPtr *val)
25928 {
25929     int ret = 0;
25930     xmlSchemaNodeInfoPtr inode = vctxt->inode;
25931 
25932     /*
25933     * cos-valid-default:
25934     * Schema Component Constraint: Element Default Valid (Immediate)
25935     * For a string to be a valid default with respect to a type
25936     * definition the appropriate case among the following must be true:
25937     */
25938     if WXS_IS_COMPLEX(inode->typeDef) {
25939 	/*
25940 	* Complex type.
25941 	*
25942 	* SPEC (2.1) "its {content type} must be a simple type definition
25943 	* or mixed."
25944 	* SPEC (2.2.2) "If the {content type} is mixed, then the {content
25945 	* type}'s particle must be `emptiable` as defined by
25946 	* Particle Emptiable ($3.9.6)."
25947 	*/
25948 	if ((! WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) &&
25949 	    ((! WXS_HAS_MIXED_CONTENT(inode->typeDef)) ||
25950 	     (! WXS_EMPTIABLE(inode->typeDef)))) {
25951 	    ret = XML_SCHEMAP_COS_VALID_DEFAULT_2_1;
25952 	    /* NOTE that this covers (2.2.2) as well. */
25953 	    VERROR(ret, NULL,
25954 		"For a string to be a valid default, the type definition "
25955 		"must be a simple type or a complex type with simple content "
25956 		"or mixed content and a particle emptiable");
25957 	    return(ret);
25958 	}
25959     }
25960     /*
25961     * 1 If the type definition is a simple type definition, then the string
25962     * must be `valid` with respect to that definition as defined by String
25963     * Valid ($3.14.4).
25964     *
25965     * AND
25966     *
25967     * 2.2.1 If the {content type} is a simple type definition, then the
25968     * string must be `valid` with respect to that simple type definition
25969     * as defined by String Valid ($3.14.4).
25970     */
25971     if (WXS_IS_SIMPLE(inode->typeDef)) {
25972 
25973 	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
25974 	    NULL, inode->typeDef, value, val, 1, 1, 0);
25975 
25976     } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
25977 
25978 	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
25979 	    NULL, inode->typeDef->contentTypeDef, value, val, 1, 1, 0);
25980     }
25981     if (ret < 0) {
25982 	VERROR_INT("xmlSchemaCheckCOSValidDefault",
25983 	    "calling xmlSchemaVCheckCVCSimpleType()");
25984     }
25985     return (ret);
25986 }
25987 
25988 static void
xmlSchemaVContentModelCallback(xmlRegExecCtxtPtr exec ATTRIBUTE_UNUSED,const xmlChar * name ATTRIBUTE_UNUSED,void * transdata,void * inputdata)25989 xmlSchemaVContentModelCallback(xmlRegExecCtxtPtr exec ATTRIBUTE_UNUSED,
25990 			       const xmlChar * name ATTRIBUTE_UNUSED,
25991 			       void *transdata, void *inputdata)
25992 {
25993     xmlSchemaElementPtr item = (xmlSchemaElementPtr) transdata;
25994     xmlSchemaNodeInfoPtr inode = (xmlSchemaNodeInfoPtr) inputdata;
25995     inode->decl = item;
25996 #ifdef DEBUG_CONTENT
25997     {
25998 	xmlChar *str = NULL;
25999 
26000 	if (item->type == XML_SCHEMA_TYPE_ELEMENT) {
26001 	    xmlGenericError(xmlGenericErrorContext,
26002 		"AUTOMATON callback for '%s' [declaration]\n",
26003 		xmlSchemaFormatQName(&str,
26004 		inode->localName, inode->nsName));
26005 	} else {
26006 	    xmlGenericError(xmlGenericErrorContext,
26007 		    "AUTOMATON callback for '%s' [wildcard]\n",
26008 		    xmlSchemaFormatQName(&str,
26009 		    inode->localName, inode->nsName));
26010 
26011 	}
26012 	FREE_AND_NULL(str)
26013     }
26014 #endif
26015 }
26016 
26017 static int
xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt)26018 xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt)
26019 {
26020     vctxt->inode = xmlSchemaGetFreshElemInfo(vctxt);
26021     if (vctxt->inode == NULL) {
26022 	VERROR_INT("xmlSchemaValidatorPushElem",
26023 	    "calling xmlSchemaGetFreshElemInfo()");
26024 	return (-1);
26025     }
26026     vctxt->nbAttrInfos = 0;
26027     return (0);
26028 }
26029 
26030 static int
xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt,xmlSchemaNodeInfoPtr inode,xmlSchemaTypePtr type,const xmlChar * value)26031 xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt,
26032 			     xmlSchemaNodeInfoPtr inode,
26033 			     xmlSchemaTypePtr type,
26034 			     const xmlChar *value)
26035 {
26036     if (inode->flags & XML_SCHEMA_NODE_INFO_VALUE_NEEDED)
26037 	return (xmlSchemaVCheckCVCSimpleType(
26038 	    ACTXT_CAST vctxt, NULL,
26039 	    type, value, &(inode->val), 1, 1, 0));
26040     else
26041 	return (xmlSchemaVCheckCVCSimpleType(
26042 	    ACTXT_CAST vctxt, NULL,
26043 	    type, value, NULL, 1, 0, 0));
26044 }
26045 
26046 
26047 
26048 /*
26049 * Process END of element.
26050 */
26051 static int
xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)26052 xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)
26053 {
26054     int ret = 0;
26055     xmlSchemaNodeInfoPtr inode = vctxt->inode;
26056 
26057     if (vctxt->nbAttrInfos != 0)
26058 	xmlSchemaClearAttrInfos(vctxt);
26059     if (inode->flags & XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED) {
26060 	/*
26061 	* This element was not expected;
26062 	* we will not validate child elements of broken parents.
26063 	* Skip validation of all content of the parent.
26064 	*/
26065 	vctxt->skipDepth = vctxt->depth -1;
26066 	goto end_elem;
26067     }
26068     if ((inode->typeDef == NULL) ||
26069 	(inode->flags & XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE)) {
26070 	/*
26071 	* 1. the type definition might be missing if the element was
26072 	*    error prone
26073 	* 2. it might be abstract.
26074 	*/
26075 	goto end_elem;
26076     }
26077     /*
26078     * Check the content model.
26079     */
26080     if ((inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) ||
26081 	(inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)) {
26082 
26083 	/*
26084 	* Workaround for "anyType".
26085 	*/
26086 	if (inode->typeDef->builtInType == XML_SCHEMAS_ANYTYPE)
26087 	    goto character_content;
26088 
26089 	if ((inode->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0) {
26090 	    xmlChar *values[10];
26091 	    int terminal, nbval = 10, nbneg;
26092 
26093 	    if (inode->regexCtxt == NULL) {
26094 		/*
26095 		* Create the regex context.
26096 		*/
26097 		inode->regexCtxt =
26098 		    xmlRegNewExecCtxt(inode->typeDef->contModel,
26099 		    xmlSchemaVContentModelCallback, vctxt);
26100 		if (inode->regexCtxt == NULL) {
26101 		    VERROR_INT("xmlSchemaValidatorPopElem",
26102 			"failed to create a regex context");
26103 		    goto internal_error;
26104 		}
26105 #ifdef DEBUG_AUTOMATA
26106 		xmlGenericError(xmlGenericErrorContext,
26107 		    "AUTOMATON create on '%s'\n", inode->localName);
26108 #endif
26109 	    }
26110 
26111 	    /*
26112 	     * Do not check further content if the node has been nilled
26113 	     */
26114 	    if (INODE_NILLED(inode)) {
26115 		ret = 0;
26116 #ifdef DEBUG_AUTOMATA
26117 		xmlGenericError(xmlGenericErrorContext,
26118 		    "AUTOMATON succeeded on nilled '%s'\n",
26119 		    inode->localName);
26120 #endif
26121                 goto skip_nilled;
26122 	    }
26123 
26124 	    /*
26125 	    * Get hold of the still expected content, since a further
26126 	    * call to xmlRegExecPushString() will lose this information.
26127 	    */
26128 	    xmlRegExecNextValues(inode->regexCtxt,
26129 		&nbval, &nbneg, &values[0], &terminal);
26130 	    ret = xmlRegExecPushString(inode->regexCtxt, NULL, NULL);
26131 	    if ((ret<0) || ((ret==0) && (!INODE_NILLED(inode)))) {
26132 		/*
26133 		* Still missing something.
26134 		*/
26135 		ret = 1;
26136 		inode->flags |=
26137 		    XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
26138 		xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
26139 		    XML_SCHEMAV_ELEMENT_CONTENT, NULL, NULL,
26140 		    "Missing child element(s)",
26141 		    nbval, nbneg, values);
26142 #ifdef DEBUG_AUTOMATA
26143 		xmlGenericError(xmlGenericErrorContext,
26144 		    "AUTOMATON missing ERROR on '%s'\n",
26145 		    inode->localName);
26146 #endif
26147 	    } else {
26148 		/*
26149 		* Content model is satisfied.
26150 		*/
26151 		ret = 0;
26152 #ifdef DEBUG_AUTOMATA
26153 		xmlGenericError(xmlGenericErrorContext,
26154 		    "AUTOMATON succeeded on '%s'\n",
26155 		    inode->localName);
26156 #endif
26157 	    }
26158 
26159 	}
26160     }
26161 
26162 skip_nilled:
26163 
26164     if (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)
26165 	goto end_elem;
26166 
26167 character_content:
26168 
26169     if (vctxt->value != NULL) {
26170 	xmlSchemaFreeValue(vctxt->value);
26171 	vctxt->value = NULL;
26172     }
26173     /*
26174     * Check character content.
26175     */
26176     if (inode->decl == NULL) {
26177 	/*
26178 	* Speedup if no declaration exists.
26179 	*/
26180 	if (WXS_IS_SIMPLE(inode->typeDef)) {
26181 	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26182 		inode, inode->typeDef, inode->value);
26183 	} else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26184 	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26185 		inode, inode->typeDef->contentTypeDef,
26186 		inode->value);
26187 	}
26188 	if (ret < 0) {
26189 	    VERROR_INT("xmlSchemaValidatorPopElem",
26190 		"calling xmlSchemaVCheckCVCSimpleType()");
26191 	    goto internal_error;
26192 	}
26193 	goto end_elem;
26194     }
26195     /*
26196     * cvc-elt (3.3.4) : 5
26197     * The appropriate case among the following must be true:
26198     */
26199     /*
26200     * cvc-elt (3.3.4) : 5.1
26201     * If the declaration has a {value constraint},
26202     * the item has neither element nor character [children] and
26203     * clause 3.2 has not applied, then all of the following must be true:
26204     */
26205     if ((inode->decl->value != NULL) &&
26206 	(inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) &&
26207 	(! INODE_NILLED(inode))) {
26208 	/*
26209 	* cvc-elt (3.3.4) : 5.1.1
26210 	* If the `actual type definition` is a `local type definition`
26211 	* then the canonical lexical representation of the {value constraint}
26212 	* value must be a valid default for the `actual type definition` as
26213 	* defined in Element Default Valid (Immediate) ($3.3.6).
26214 	*/
26215 	/*
26216 	* NOTE: 'local' above means types acquired by xsi:type.
26217 	* NOTE: Although the *canonical* value is stated, it is not
26218 	* relevant if canonical or not. Additionally XML Schema 1.1
26219 	* will removed this requirement as well.
26220 	*/
26221 	if (inode->flags & XML_SCHEMA_ELEM_INFO_LOCAL_TYPE) {
26222 
26223 	    ret = xmlSchemaCheckCOSValidDefault(vctxt,
26224 		inode->decl->value, &(inode->val));
26225 	    if (ret != 0) {
26226 		if (ret < 0) {
26227 		    VERROR_INT("xmlSchemaValidatorPopElem",
26228 			"calling xmlSchemaCheckCOSValidDefault()");
26229 		    goto internal_error;
26230 		}
26231 		goto end_elem;
26232 	    }
26233 	    /*
26234 	    * Stop here, to avoid redundant validation of the value
26235 	    * (see following).
26236 	    */
26237 	    goto default_psvi;
26238 	}
26239 	/*
26240 	* cvc-elt (3.3.4) : 5.1.2
26241 	* The element information item with the canonical lexical
26242 	* representation of the {value constraint} value used as its
26243 	* `normalized value` must be `valid` with respect to the
26244 	* `actual type definition` as defined by Element Locally Valid (Type)
26245 	* ($3.3.4).
26246 	*/
26247 	if (WXS_IS_SIMPLE(inode->typeDef)) {
26248 	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26249 		inode, inode->typeDef, inode->decl->value);
26250 	} else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26251 	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26252 		inode, inode->typeDef->contentTypeDef,
26253 		inode->decl->value);
26254 	}
26255 	if (ret != 0) {
26256 	    if (ret < 0) {
26257 		VERROR_INT("xmlSchemaValidatorPopElem",
26258 		    "calling xmlSchemaVCheckCVCSimpleType()");
26259 		goto internal_error;
26260 	    }
26261 	    goto end_elem;
26262 	}
26263 
26264 default_psvi:
26265 	/*
26266 	* PSVI: Create a text node on the instance element.
26267 	*/
26268 	if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
26269 	    (inode->node != NULL)) {
26270 	    xmlNodePtr textChild;
26271 	    xmlChar *normValue;
26272 	    /*
26273 	    * VAL TODO: Normalize the value.
26274 	    */
26275 	    normValue = xmlSchemaNormalizeValue(inode->typeDef,
26276 		inode->decl->value);
26277 	    if (normValue != NULL) {
26278 		textChild = xmlNewText(BAD_CAST normValue);
26279 		xmlFree(normValue);
26280 	    } else
26281 		textChild = xmlNewText(inode->decl->value);
26282 	    if (textChild == NULL) {
26283 		VERROR_INT("xmlSchemaValidatorPopElem",
26284 		    "calling xmlNewText()");
26285 		goto internal_error;
26286 	    } else
26287 		xmlAddChild(inode->node, textChild);
26288 	}
26289 
26290     } else if (! INODE_NILLED(inode)) {
26291 	/*
26292 	* 5.2.1 The element information item must be `valid` with respect
26293 	* to the `actual type definition` as defined by Element Locally
26294 	* Valid (Type) ($3.3.4).
26295 	*/
26296 	if (WXS_IS_SIMPLE(inode->typeDef)) {
26297 	     /*
26298 	    * SPEC (cvc-type) (3.1)
26299 	    * "If the type definition is a simple type definition, ..."
26300 	    * (3.1.3) "If clause 3.2 of Element Locally Valid
26301 	    * (Element) ($3.3.4) did not apply, then the `normalized value`
26302 	    * must be `valid` with respect to the type definition as defined
26303 	    * by String Valid ($3.14.4).
26304 	    */
26305 	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26306 		    inode, inode->typeDef, inode->value);
26307 	} else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26308 	    /*
26309 	    * SPEC (cvc-type) (3.2) "If the type definition is a complex type
26310 	    * definition, then the element information item must be
26311 	    * `valid` with respect to the type definition as per
26312 	    * Element Locally Valid (Complex Type) ($3.4.4);"
26313 	    *
26314 	    * SPEC (cvc-complex-type) (2.2)
26315 	    * "If the {content type} is a simple type definition, ...
26316 	    * the `normalized value` of the element information item is
26317 	    * `valid` with respect to that simple type definition as
26318 	    * defined by String Valid ($3.14.4)."
26319 	    */
26320 	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26321 		inode, inode->typeDef->contentTypeDef, inode->value);
26322 	}
26323 	if (ret != 0) {
26324 	    if (ret < 0) {
26325 		VERROR_INT("xmlSchemaValidatorPopElem",
26326 		    "calling xmlSchemaVCheckCVCSimpleType()");
26327 		goto internal_error;
26328 	    }
26329 	    goto end_elem;
26330 	}
26331 	/*
26332 	* 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
26333 	* not applied, all of the following must be true:
26334 	*/
26335 	if ((inode->decl->value != NULL) &&
26336 	    (inode->decl->flags & XML_SCHEMAS_ELEM_FIXED)) {
26337 
26338 	    /*
26339 	    * TODO: We will need a computed value, when comparison is
26340 	    * done on computed values.
26341 	    */
26342 	    /*
26343 	    * 5.2.2.1 The element information item must have no element
26344 	    * information item [children].
26345 	    */
26346 	    if (inode->flags &
26347 		    XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT) {
26348 		ret = XML_SCHEMAV_CVC_ELT_5_2_2_1;
26349 		VERROR(ret, NULL,
26350 		    "The content must not containt element nodes since "
26351 		    "there is a fixed value constraint");
26352 		goto end_elem;
26353 	    } else {
26354 		/*
26355 		* 5.2.2.2 The appropriate case among the following must
26356 		* be true:
26357 		*/
26358 		if (WXS_HAS_MIXED_CONTENT(inode->typeDef)) {
26359 		    /*
26360 		    * 5.2.2.2.1 If the {content type} of the `actual type
26361 		    * definition` is mixed, then the *initial value* of the
26362 		    * item must match the canonical lexical representation
26363 		    * of the {value constraint} value.
26364 		    *
26365 		    * ... the *initial value* of an element information
26366 		    * item is the string composed of, in order, the
26367 		    * [character code] of each character information item in
26368 		    * the [children] of that element information item.
26369 		    */
26370 		    if (! xmlStrEqual(inode->value, inode->decl->value)){
26371 			/*
26372 			* VAL TODO: Report invalid & expected values as well.
26373 			* VAL TODO: Implement the canonical stuff.
26374 			*/
26375 			ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_1;
26376 			xmlSchemaCustomErr(ACTXT_CAST vctxt,
26377 			    ret, NULL, NULL,
26378 			    "The initial value '%s' does not match the fixed "
26379 			    "value constraint '%s'",
26380 			    inode->value, inode->decl->value);
26381 			goto end_elem;
26382 		    }
26383 		} else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26384 		    /*
26385 		    * 5.2.2.2.2 If the {content type} of the `actual type
26386 		    * definition` is a simple type definition, then the
26387 		    * *actual value* of the item must match the canonical
26388 		    * lexical representation of the {value constraint} value.
26389 		    */
26390 		    /*
26391 		    * VAL TODO: *actual value* is the normalized value, impl.
26392 		    *           this.
26393 		    * VAL TODO: Report invalid & expected values as well.
26394 		    * VAL TODO: Implement a comparison with the computed values.
26395 		    */
26396 		    if (! xmlStrEqual(inode->value,
26397 			    inode->decl->value)) {
26398 			ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_2;
26399 			xmlSchemaCustomErr(ACTXT_CAST vctxt,
26400 			    ret, NULL, NULL,
26401 			    "The actual value '%s' does not match the fixed "
26402 			    "value constraint '%s'",
26403 			    inode->value,
26404 			    inode->decl->value);
26405 			goto end_elem;
26406 		    }
26407 		}
26408 	    }
26409 	}
26410     }
26411 
26412 end_elem:
26413     if (vctxt->depth < 0) {
26414 	/* TODO: raise error? */
26415 	return (0);
26416     }
26417     if (vctxt->depth == vctxt->skipDepth)
26418 	vctxt->skipDepth = -1;
26419     /*
26420     * Evaluate the history of XPath state objects.
26421     */
26422     if (inode->appliedXPath &&
26423 	(xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1))
26424 	goto internal_error;
26425     /*
26426     * MAYBE TODO:
26427     * SPEC (6) "The element information item must be `valid` with
26428     * respect to each of the {identity-constraint definitions} as per
26429     * Identity-constraint Satisfied ($3.11.4)."
26430     */
26431     /*
26432     * PSVI TODO: If we expose IDC node-tables via PSVI then the tables
26433     *   need to be built in any case.
26434     *   We will currently build IDC node-tables and bubble them only if
26435     *   keyrefs do exist.
26436     */
26437 
26438     /*
26439     * Add the current IDC target-nodes to the IDC node-tables.
26440     */
26441     if ((inode->idcMatchers != NULL) &&
26442 	(vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
26443     {
26444 	if (xmlSchemaIDCFillNodeTables(vctxt, inode) == -1)
26445 	    goto internal_error;
26446     }
26447     /*
26448     * Validate IDC keyrefs.
26449     */
26450     if (vctxt->inode->hasKeyrefs)
26451 	if (xmlSchemaCheckCVCIDCKeyRef(vctxt) == -1)
26452 	    goto internal_error;
26453     /*
26454     * Merge/free the IDC table.
26455     */
26456     if (inode->idcTable != NULL) {
26457 #ifdef DEBUG_IDC_NODE_TABLE
26458 	xmlSchemaDebugDumpIDCTable(stdout,
26459 	    inode->nsName,
26460 	    inode->localName,
26461 	    inode->idcTable);
26462 #endif
26463 	if ((vctxt->depth > 0) &&
26464 	    (vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
26465 	{
26466 	    /*
26467 	    * Merge the IDC node table with the table of the parent node.
26468 	    */
26469 	    if (xmlSchemaBubbleIDCNodeTables(vctxt) == -1)
26470 		goto internal_error;
26471 	}
26472     }
26473     /*
26474     * Clear the current ielem.
26475     * VAL TODO: Don't free the PSVI IDC tables if they are
26476     * requested for the PSVI.
26477     */
26478     xmlSchemaClearElemInfo(vctxt, inode);
26479     /*
26480     * Skip further processing if we are on the validation root.
26481     */
26482     if (vctxt->depth == 0) {
26483 	vctxt->depth--;
26484 	vctxt->inode = NULL;
26485 	return (0);
26486     }
26487     /*
26488     * Reset the keyrefDepth if needed.
26489     */
26490     if (vctxt->aidcs != NULL) {
26491 	xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
26492 	do {
26493 	    if (aidc->keyrefDepth == vctxt->depth) {
26494 		/*
26495 		* A 'keyrefDepth' of a key/unique IDC matches the current
26496 		* depth, this means that we are leaving the scope of the
26497 		* top-most keyref IDC which refers to this IDC.
26498 		*/
26499 		aidc->keyrefDepth = -1;
26500 	    }
26501 	    aidc = aidc->next;
26502 	} while (aidc != NULL);
26503     }
26504     vctxt->depth--;
26505     vctxt->inode = vctxt->elemInfos[vctxt->depth];
26506     /*
26507     * VAL TODO: 7 If the element information item is the `validation root`, it must be
26508     * `valid` per Validation Root Valid (ID/IDREF) ($3.3.4).
26509     */
26510     return (ret);
26511 
26512 internal_error:
26513     vctxt->err = -1;
26514     return (-1);
26515 }
26516 
26517 /*
26518 * 3.4.4 Complex Type Definition Validation Rules
26519 * Validation Rule: Element Locally Valid (Complex Type) (cvc-complex-type)
26520 */
26521 static int
xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)26522 xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)
26523 {
26524     xmlSchemaNodeInfoPtr pielem;
26525     xmlSchemaTypePtr ptype;
26526     int ret = 0;
26527 
26528     if (vctxt->depth <= 0) {
26529 	VERROR_INT("xmlSchemaValidateChildElem",
26530 	    "not intended for the validation root");
26531 	return (-1);
26532     }
26533     pielem = vctxt->elemInfos[vctxt->depth -1];
26534     if (pielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26535 	pielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
26536     /*
26537     * Handle 'nilled' elements.
26538     */
26539     if (INODE_NILLED(pielem)) {
26540 	/*
26541 	* SPEC (cvc-elt) (3.3.4) : (3.2.1)
26542 	*/
26543 	ACTIVATE_PARENT_ELEM;
26544 	ret = XML_SCHEMAV_CVC_ELT_3_2_1;
26545 	VERROR(ret, NULL,
26546 	    "Neither character nor element content is allowed, "
26547 	    "because the element was 'nilled'");
26548 	ACTIVATE_ELEM;
26549 	goto unexpected_elem;
26550     }
26551 
26552     ptype = pielem->typeDef;
26553 
26554     if (ptype->builtInType == XML_SCHEMAS_ANYTYPE) {
26555 	/*
26556 	* Workaround for "anyType": we have currently no content model
26557 	* assigned for "anyType", so handle it explicitely.
26558 	* "anyType" has an unbounded, lax "any" wildcard.
26559 	*/
26560 	vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26561 	    vctxt->inode->localName,
26562 	    vctxt->inode->nsName);
26563 
26564 	if (vctxt->inode->decl == NULL) {
26565 	    xmlSchemaAttrInfoPtr iattr;
26566 	    /*
26567 	    * Process "xsi:type".
26568 	    * SPEC (cvc-assess-elt) (1.2.1.2.1) - (1.2.1.2.3)
26569 	    */
26570 	    iattr = xmlSchemaGetMetaAttrInfo(vctxt,
26571 		XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
26572 	    if (iattr != NULL) {
26573 		ret = xmlSchemaProcessXSIType(vctxt, iattr,
26574 		    &(vctxt->inode->typeDef), NULL);
26575 		if (ret != 0) {
26576 		    if (ret == -1) {
26577 			VERROR_INT("xmlSchemaValidateChildElem",
26578 			    "calling xmlSchemaProcessXSIType() to "
26579 			    "process the attribute 'xsi:nil'");
26580 			return (-1);
26581 		    }
26582 		    return (ret);
26583 		}
26584 	    } else {
26585 		 /*
26586 		 * Fallback to "anyType".
26587 		 *
26588 		 * SPEC (cvc-assess-elt)
26589 		 * "If the item cannot be `strictly assessed`, [...]
26590 		 * an element information item's schema validity may be laxly
26591 		 * assessed if its `context-determined declaration` is not
26592 		 * skip by `validating` with respect to the `ur-type
26593 		 * definition` as per Element Locally Valid (Type) ($3.3.4)."
26594 		*/
26595 		vctxt->inode->typeDef =
26596 		    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
26597 	    }
26598 	}
26599 	return (0);
26600     }
26601 
26602     switch (ptype->contentType) {
26603 	case XML_SCHEMA_CONTENT_EMPTY:
26604 	    /*
26605 	    * SPEC (2.1) "If the {content type} is empty, then the
26606 	    * element information item has no character or element
26607 	    * information item [children]."
26608 	    */
26609 	    ACTIVATE_PARENT_ELEM
26610 	    ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1;
26611 	    VERROR(ret, NULL,
26612 		"Element content is not allowed, "
26613 		"because the content type is empty");
26614 	    ACTIVATE_ELEM
26615 	    goto unexpected_elem;
26616 	    break;
26617 
26618 	case XML_SCHEMA_CONTENT_MIXED:
26619         case XML_SCHEMA_CONTENT_ELEMENTS: {
26620 	    xmlRegExecCtxtPtr regexCtxt;
26621 	    xmlChar *values[10];
26622 	    int terminal, nbval = 10, nbneg;
26623 
26624 	    /* VAL TODO: Optimized "anyType" validation.*/
26625 
26626 	    if (ptype->contModel == NULL) {
26627 		VERROR_INT("xmlSchemaValidateChildElem",
26628 		    "type has elem content but no content model");
26629 		return (-1);
26630 	    }
26631 	    /*
26632 	    * Safety belf for evaluation if the cont. model was already
26633 	    * examined to be invalid.
26634 	    */
26635 	    if (pielem->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) {
26636 		VERROR_INT("xmlSchemaValidateChildElem",
26637 		    "validating elem, but elem content is already invalid");
26638 		return (-1);
26639 	    }
26640 
26641 	    regexCtxt = pielem->regexCtxt;
26642 	    if (regexCtxt == NULL) {
26643 		/*
26644 		* Create the regex context.
26645 		*/
26646 		regexCtxt = xmlRegNewExecCtxt(ptype->contModel,
26647 		    xmlSchemaVContentModelCallback, vctxt);
26648 		if (regexCtxt == NULL) {
26649 		    VERROR_INT("xmlSchemaValidateChildElem",
26650 			"failed to create a regex context");
26651 		    return (-1);
26652 		}
26653 		pielem->regexCtxt = regexCtxt;
26654 #ifdef DEBUG_AUTOMATA
26655 		xmlGenericError(xmlGenericErrorContext, "AUTOMATA create on '%s'\n",
26656 		    pielem->localName);
26657 #endif
26658 	    }
26659 
26660 	    /*
26661 	    * SPEC (2.4) "If the {content type} is element-only or mixed,
26662 	    * then the sequence of the element information item's
26663 	    * element information item [children], if any, taken in
26664 	    * order, is `valid` with respect to the {content type}'s
26665 	    * particle, as defined in Element Sequence Locally Valid
26666 	    * (Particle) ($3.9.4)."
26667 	    */
26668 	    ret = xmlRegExecPushString2(regexCtxt,
26669 		vctxt->inode->localName,
26670 		vctxt->inode->nsName,
26671 		vctxt->inode);
26672 #ifdef DEBUG_AUTOMATA
26673 	    if (ret < 0)
26674 		xmlGenericError(xmlGenericErrorContext,
26675 		"AUTOMATON push ERROR for '%s' on '%s'\n",
26676 		vctxt->inode->localName, pielem->localName);
26677 	    else
26678 		xmlGenericError(xmlGenericErrorContext,
26679 		"AUTOMATON push OK for '%s' on '%s'\n",
26680 		vctxt->inode->localName, pielem->localName);
26681 #endif
26682 	    if (vctxt->err == XML_SCHEMAV_INTERNAL) {
26683 		VERROR_INT("xmlSchemaValidateChildElem",
26684 		    "calling xmlRegExecPushString2()");
26685 		return (-1);
26686 	    }
26687 	    if (ret < 0) {
26688 		xmlRegExecErrInfo(regexCtxt, NULL, &nbval, &nbneg,
26689 		    &values[0], &terminal);
26690 		xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
26691 		    XML_SCHEMAV_ELEMENT_CONTENT, NULL,NULL,
26692 		    "This element is not expected",
26693 		    nbval, nbneg, values);
26694 		ret = vctxt->err;
26695 		goto unexpected_elem;
26696 	    } else
26697 		ret = 0;
26698 	}
26699 	    break;
26700 	case XML_SCHEMA_CONTENT_SIMPLE:
26701 	case XML_SCHEMA_CONTENT_BASIC:
26702 	    ACTIVATE_PARENT_ELEM
26703 	    if (WXS_IS_COMPLEX(ptype)) {
26704 		/*
26705 		* SPEC (cvc-complex-type) (2.2)
26706 		* "If the {content type} is a simple type definition, then
26707 		* the element information item has no element information
26708 		* item [children], ..."
26709 		*/
26710 		ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
26711 		VERROR(ret, NULL, "Element content is not allowed, "
26712 		    "because the content type is a simple type definition");
26713 	    } else {
26714 		/*
26715 		* SPEC (cvc-type) (3.1.2) "The element information item must
26716 		* have no element information item [children]."
26717 		*/
26718 		ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
26719 		VERROR(ret, NULL, "Element content is not allowed, "
26720 		    "because the type definition is simple");
26721 	    }
26722 	    ACTIVATE_ELEM
26723 	    ret = vctxt->err;
26724 	    goto unexpected_elem;
26725 	    break;
26726 
26727 	default:
26728 	    break;
26729     }
26730     return (ret);
26731 unexpected_elem:
26732     /*
26733     * Pop this element and set the skipDepth to skip
26734     * all further content of the parent element.
26735     */
26736     vctxt->skipDepth = vctxt->depth;
26737     vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
26738     pielem->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
26739     return (ret);
26740 }
26741 
26742 #define XML_SCHEMA_PUSH_TEXT_PERSIST 1
26743 #define XML_SCHEMA_PUSH_TEXT_CREATED 2
26744 #define XML_SCHEMA_PUSH_TEXT_VOLATILE 3
26745 
26746 static int
xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,int nodeType,const xmlChar * value,int len,int mode,int * consumed)26747 xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,
26748 		  int nodeType, const xmlChar *value, int len,
26749 		  int mode, int *consumed)
26750 {
26751     /*
26752     * Unfortunately we have to duplicate the text sometimes.
26753     * OPTIMIZE: Maybe we could skip it, if:
26754     *   1. content type is simple
26755     *   2. whitespace is "collapse"
26756     *   3. it consists of whitespace only
26757     *
26758     * Process character content.
26759     */
26760     if (consumed != NULL)
26761 	*consumed = 0;
26762     if (INODE_NILLED(vctxt->inode)) {
26763 	/*
26764 	* SPEC cvc-elt (3.3.4 - 3.2.1)
26765 	* "The element information item must have no character or
26766 	* element information item [children]."
26767 	*/
26768 	VERROR(XML_SCHEMAV_CVC_ELT_3_2_1, NULL,
26769 	    "Neither character nor element content is allowed "
26770 	    "because the element is 'nilled'");
26771 	return (vctxt->err);
26772     }
26773     /*
26774     * SPEC (2.1) "If the {content type} is empty, then the
26775     * element information item has no character or element
26776     * information item [children]."
26777     */
26778     if (vctxt->inode->typeDef->contentType ==
26779 	    XML_SCHEMA_CONTENT_EMPTY) {
26780 	VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1, NULL,
26781 	    "Character content is not allowed, "
26782 	    "because the content type is empty");
26783 	return (vctxt->err);
26784     }
26785 
26786     if (vctxt->inode->typeDef->contentType ==
26787 	    XML_SCHEMA_CONTENT_ELEMENTS) {
26788 	if ((nodeType != XML_TEXT_NODE) ||
26789 	    (! xmlSchemaIsBlank((xmlChar *) value, len))) {
26790 	    /*
26791 	    * SPEC cvc-complex-type (2.3)
26792 	    * "If the {content type} is element-only, then the
26793 	    * element information item has no character information
26794 	    * item [children] other than those whose [character
26795 	    * code] is defined as a white space in [XML 1.0 (Second
26796 	    * Edition)]."
26797 	    */
26798 	    VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3, NULL,
26799 		"Character content other than whitespace is not allowed "
26800 		"because the content type is 'element-only'");
26801 	    return (vctxt->err);
26802 	}
26803 	return (0);
26804     }
26805 
26806     if ((value == NULL) || (value[0] == 0))
26807 	return (0);
26808     /*
26809     * Save the value.
26810     * NOTE that even if the content type is *mixed*, we need the
26811     * *initial value* for default/fixed value constraints.
26812     */
26813     if ((vctxt->inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) &&
26814 	((vctxt->inode->decl == NULL) ||
26815 	(vctxt->inode->decl->value == NULL)))
26816 	return (0);
26817 
26818     if (vctxt->inode->value == NULL) {
26819 	/*
26820 	* Set the value.
26821 	*/
26822 	switch (mode) {
26823 	    case XML_SCHEMA_PUSH_TEXT_PERSIST:
26824 		/*
26825 		* When working on a tree.
26826 		*/
26827 		vctxt->inode->value = value;
26828 		break;
26829 	    case XML_SCHEMA_PUSH_TEXT_CREATED:
26830 		/*
26831 		* When working with the reader.
26832 		* The value will be freed by the element info.
26833 		*/
26834 		vctxt->inode->value = value;
26835 		if (consumed != NULL)
26836 		    *consumed = 1;
26837 		vctxt->inode->flags |=
26838 		    XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26839 		break;
26840 	    case XML_SCHEMA_PUSH_TEXT_VOLATILE:
26841 		/*
26842 		* When working with SAX.
26843 		* The value will be freed by the element info.
26844 		*/
26845 		if (len != -1)
26846 		    vctxt->inode->value = BAD_CAST xmlStrndup(value, len);
26847 		else
26848 		    vctxt->inode->value = BAD_CAST xmlStrdup(value);
26849 		vctxt->inode->flags |=
26850 		    XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26851 		break;
26852 	    default:
26853 		break;
26854 	}
26855     } else {
26856 	if (len < 0)
26857 	    len = xmlStrlen(value);
26858 	/*
26859 	* Concat the value.
26860 	*/
26861 	if (vctxt->inode->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
26862 	    vctxt->inode->value = BAD_CAST xmlStrncat(
26863 		(xmlChar *) vctxt->inode->value, value, len);
26864 	} else {
26865 	    vctxt->inode->value =
26866 		BAD_CAST xmlStrncatNew(vctxt->inode->value, value, len);
26867 	    vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26868 	}
26869     }
26870 
26871     return (0);
26872 }
26873 
26874 static int
xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt)26875 xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt)
26876 {
26877     int ret = 0;
26878 
26879     if ((vctxt->skipDepth != -1) &&
26880 	(vctxt->depth >= vctxt->skipDepth)) {
26881 	VERROR_INT("xmlSchemaValidateElem",
26882 	    "in skip-state");
26883 	goto internal_error;
26884     }
26885     if (vctxt->xsiAssemble) {
26886 	/*
26887 	* We will stop validation if there was an error during
26888 	* dynamic schema construction.
26889 	* Note that we simply set @skipDepth to 0, this could
26890 	* mean that a streaming document via SAX would be
26891 	* still read to the end but it won't be validated any more.
26892 	* TODO: If we are sure how to stop the validation at once
26893 	*   for all input scenarios, then this should be changed to
26894 	*   instantly stop the validation.
26895 	*/
26896 	ret = xmlSchemaAssembleByXSI(vctxt);
26897 	if (ret != 0) {
26898 	    if (ret == -1)
26899 		goto internal_error;
26900 	    vctxt->skipDepth = 0;
26901 	    return(ret);
26902 	}
26903         /*
26904          * Augment the IDC definitions for the main schema and all imported ones
26905          * NOTE: main schema is the first in the imported list
26906          */
26907         xmlHashScan(vctxt->schema->schemasImports, xmlSchemaAugmentImportedIDC,
26908                     vctxt);
26909     }
26910     if (vctxt->depth > 0) {
26911 	/*
26912 	* Validate this element against the content model
26913 	* of the parent.
26914 	*/
26915 	ret = xmlSchemaValidateChildElem(vctxt);
26916 	if (ret != 0) {
26917 	    if (ret < 0) {
26918 		VERROR_INT("xmlSchemaValidateElem",
26919 		    "calling xmlSchemaStreamValidateChildElement()");
26920 		goto internal_error;
26921 	    }
26922 	    goto exit;
26923 	}
26924 	if (vctxt->depth == vctxt->skipDepth)
26925 	    goto exit;
26926 	if ((vctxt->inode->decl == NULL) &&
26927 	    (vctxt->inode->typeDef == NULL)) {
26928 	    VERROR_INT("xmlSchemaValidateElem",
26929 		"the child element was valid but neither the "
26930 		"declaration nor the type was set");
26931 	    goto internal_error;
26932 	}
26933     } else {
26934 	/*
26935 	* Get the declaration of the validation root.
26936 	*/
26937 	vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26938 	    vctxt->inode->localName,
26939 	    vctxt->inode->nsName);
26940 	if (vctxt->inode->decl == NULL) {
26941 	    ret = XML_SCHEMAV_CVC_ELT_1;
26942 	    VERROR(ret, NULL,
26943 		"No matching global declaration available "
26944 		"for the validation root");
26945 	    goto exit;
26946 	}
26947     }
26948 
26949     if (vctxt->inode->decl == NULL)
26950 	goto type_validation;
26951 
26952     if (vctxt->inode->decl->type == XML_SCHEMA_TYPE_ANY) {
26953 	int skip;
26954 	/*
26955 	* Wildcards.
26956 	*/
26957 	ret = xmlSchemaValidateElemWildcard(vctxt, &skip);
26958 	if (ret != 0) {
26959 	    if (ret < 0) {
26960 		VERROR_INT("xmlSchemaValidateElem",
26961 		    "calling xmlSchemaValidateElemWildcard()");
26962 		goto internal_error;
26963 	    }
26964 	    goto exit;
26965 	}
26966 	if (skip) {
26967 	    vctxt->skipDepth = vctxt->depth;
26968 	    goto exit;
26969 	}
26970 	/*
26971 	* The declaration might be set by the wildcard validation,
26972 	* when the processContents is "lax" or "strict".
26973 	*/
26974 	if (vctxt->inode->decl->type != XML_SCHEMA_TYPE_ELEMENT) {
26975 	    /*
26976 	    * Clear the "decl" field to not confuse further processing.
26977 	    */
26978 	    vctxt->inode->decl = NULL;
26979 	    goto type_validation;
26980 	}
26981     }
26982     /*
26983     * Validate against the declaration.
26984     */
26985     ret = xmlSchemaValidateElemDecl(vctxt);
26986     if (ret != 0) {
26987 	if (ret < 0) {
26988 	    VERROR_INT("xmlSchemaValidateElem",
26989 		"calling xmlSchemaValidateElemDecl()");
26990 	    goto internal_error;
26991 	}
26992 	goto exit;
26993     }
26994     /*
26995     * Validate against the type definition.
26996     */
26997 type_validation:
26998 
26999     if (vctxt->inode->typeDef == NULL) {
27000 	vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
27001 	ret = XML_SCHEMAV_CVC_TYPE_1;
27002 	VERROR(ret, NULL,
27003 	    "The type definition is absent");
27004 	goto exit;
27005     }
27006     if (vctxt->inode->typeDef->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
27007 	vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
27008 	ret = XML_SCHEMAV_CVC_TYPE_2;
27009 	    VERROR(ret, NULL,
27010 	    "The type definition is abstract");
27011 	goto exit;
27012     }
27013     /*
27014     * Evaluate IDCs. Do it here, since new IDC matchers are registered
27015     * during validation against the declaration. This must be done
27016     * _before_ attribute validation.
27017     */
27018     if (vctxt->xpathStates != NULL) {
27019 	ret = xmlSchemaXPathEvaluate(vctxt, XML_ELEMENT_NODE);
27020 	vctxt->inode->appliedXPath = 1;
27021 	if (ret == -1) {
27022 	    VERROR_INT("xmlSchemaValidateElem",
27023 		"calling xmlSchemaXPathEvaluate()");
27024 	    goto internal_error;
27025 	}
27026     }
27027     /*
27028     * Validate attributes.
27029     */
27030     if (WXS_IS_COMPLEX(vctxt->inode->typeDef)) {
27031 	if ((vctxt->nbAttrInfos != 0) ||
27032 	    (vctxt->inode->typeDef->attrUses != NULL)) {
27033 
27034 	    ret = xmlSchemaVAttributesComplex(vctxt);
27035 	}
27036     } else if (vctxt->nbAttrInfos != 0) {
27037 
27038 	ret = xmlSchemaVAttributesSimple(vctxt);
27039     }
27040     /*
27041     * Clear registered attributes.
27042     */
27043     if (vctxt->nbAttrInfos != 0)
27044 	xmlSchemaClearAttrInfos(vctxt);
27045     if (ret == -1) {
27046 	VERROR_INT("xmlSchemaValidateElem",
27047 	    "calling attributes validation");
27048 	goto internal_error;
27049     }
27050     /*
27051     * Don't return an error if attributes are invalid on purpose.
27052     */
27053     ret = 0;
27054 
27055 exit:
27056     if (ret != 0)
27057 	vctxt->skipDepth = vctxt->depth;
27058     return (ret);
27059 internal_error:
27060     return (-1);
27061 }
27062 
27063 #ifdef XML_SCHEMA_READER_ENABLED
27064 static int
xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt)27065 xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt)
27066 {
27067     const int WHTSP = 13, SIGN_WHTSP = 14, END_ELEM = 15;
27068     int depth, nodeType, ret = 0, consumed;
27069     xmlSchemaNodeInfoPtr ielem;
27070 
27071     vctxt->depth = -1;
27072     ret = xmlTextReaderRead(vctxt->reader);
27073     /*
27074     * Move to the document element.
27075     */
27076     while (ret == 1) {
27077 	nodeType = xmlTextReaderNodeType(vctxt->reader);
27078 	if (nodeType == XML_ELEMENT_NODE)
27079 	    goto root_found;
27080 	ret = xmlTextReaderRead(vctxt->reader);
27081     }
27082     goto exit;
27083 
27084 root_found:
27085 
27086     do {
27087 	depth = xmlTextReaderDepth(vctxt->reader);
27088 	nodeType = xmlTextReaderNodeType(vctxt->reader);
27089 
27090 	if (nodeType == XML_ELEMENT_NODE) {
27091 
27092 	    vctxt->depth++;
27093 	    if (xmlSchemaValidatorPushElem(vctxt) == -1) {
27094 		VERROR_INT("xmlSchemaVReaderWalk",
27095 		    "calling xmlSchemaValidatorPushElem()");
27096 		goto internal_error;
27097 	    }
27098 	    ielem = vctxt->inode;
27099 	    ielem->localName = xmlTextReaderLocalName(vctxt->reader);
27100 	    ielem->nsName = xmlTextReaderNamespaceUri(vctxt->reader);
27101 	    ielem->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
27102 	    /*
27103 	    * Is the element empty?
27104 	    */
27105 	    ret = xmlTextReaderIsEmptyElement(vctxt->reader);
27106 	    if (ret == -1) {
27107 		VERROR_INT("xmlSchemaVReaderWalk",
27108 		    "calling xmlTextReaderIsEmptyElement()");
27109 		goto internal_error;
27110 	    }
27111 	    if (ret) {
27112 		ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27113 	    }
27114 	    /*
27115 	    * Register attributes.
27116 	    */
27117 	    vctxt->nbAttrInfos = 0;
27118 	    ret = xmlTextReaderMoveToFirstAttribute(vctxt->reader);
27119 	    if (ret == -1) {
27120 		VERROR_INT("xmlSchemaVReaderWalk",
27121 		    "calling xmlTextReaderMoveToFirstAttribute()");
27122 		goto internal_error;
27123 	    }
27124 	    if (ret == 1) {
27125 		do {
27126 		    /*
27127 		    * VAL TODO: How do we know that the reader works on a
27128 		    * node tree, to be able to pass a node here?
27129 		    */
27130 		    if (xmlSchemaValidatorPushAttribute(vctxt, NULL,
27131 			(const xmlChar *) xmlTextReaderLocalName(vctxt->reader),
27132 			xmlTextReaderNamespaceUri(vctxt->reader), 1,
27133 			xmlTextReaderValue(vctxt->reader), 1) == -1) {
27134 
27135 			VERROR_INT("xmlSchemaVReaderWalk",
27136 			    "calling xmlSchemaValidatorPushAttribute()");
27137 			goto internal_error;
27138 		    }
27139 		    ret = xmlTextReaderMoveToNextAttribute(vctxt->reader);
27140 		    if (ret == -1) {
27141 			VERROR_INT("xmlSchemaVReaderWalk",
27142 			    "calling xmlTextReaderMoveToFirstAttribute()");
27143 			goto internal_error;
27144 		    }
27145 		} while (ret == 1);
27146 		/*
27147 		* Back to element position.
27148 		*/
27149 		ret = xmlTextReaderMoveToElement(vctxt->reader);
27150 		if (ret == -1) {
27151 		    VERROR_INT("xmlSchemaVReaderWalk",
27152 			"calling xmlTextReaderMoveToElement()");
27153 		    goto internal_error;
27154 		}
27155 	    }
27156 	    /*
27157 	    * Validate the element.
27158 	    */
27159 	    ret= xmlSchemaValidateElem(vctxt);
27160 	    if (ret != 0) {
27161 		if (ret == -1) {
27162 		    VERROR_INT("xmlSchemaVReaderWalk",
27163 			"calling xmlSchemaValidateElem()");
27164 		    goto internal_error;
27165 		}
27166 		goto exit;
27167 	    }
27168 	    if (vctxt->depth == vctxt->skipDepth) {
27169 		int curDepth;
27170 		/*
27171 		* Skip all content.
27172 		*/
27173 		if ((ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) == 0) {
27174 		    ret = xmlTextReaderRead(vctxt->reader);
27175 		    curDepth = xmlTextReaderDepth(vctxt->reader);
27176 		    while ((ret == 1) && (curDepth != depth)) {
27177 			ret = xmlTextReaderRead(vctxt->reader);
27178 			curDepth = xmlTextReaderDepth(vctxt->reader);
27179 		    }
27180 		    if (ret < 0) {
27181 			/*
27182 			* VAL TODO: A reader error occurred; what to do here?
27183 			*/
27184 			ret = 1;
27185 			goto exit;
27186 		    }
27187 		}
27188 		goto leave_elem;
27189 	    }
27190 	    /*
27191 	    * READER VAL TODO: Is an END_ELEM really never called
27192 	    * if the elem is empty?
27193 	    */
27194 	    if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27195 		goto leave_elem;
27196 	} else if (nodeType == END_ELEM) {
27197 	    /*
27198 	    * Process END of element.
27199 	    */
27200 leave_elem:
27201 	    ret = xmlSchemaValidatorPopElem(vctxt);
27202 	    if (ret != 0) {
27203 		if (ret < 0) {
27204 		    VERROR_INT("xmlSchemaVReaderWalk",
27205 			"calling xmlSchemaValidatorPopElem()");
27206 		    goto internal_error;
27207 		}
27208 		goto exit;
27209 	    }
27210 	    if (vctxt->depth >= 0)
27211 		ielem = vctxt->inode;
27212 	    else
27213 		ielem = NULL;
27214 	} else if ((nodeType == XML_TEXT_NODE) ||
27215 	    (nodeType == XML_CDATA_SECTION_NODE) ||
27216 	    (nodeType == WHTSP) ||
27217 	    (nodeType == SIGN_WHTSP)) {
27218 	    /*
27219 	    * Process character content.
27220 	    */
27221 	    xmlChar *value;
27222 
27223 	    if ((nodeType == WHTSP) || (nodeType == SIGN_WHTSP))
27224 		nodeType = XML_TEXT_NODE;
27225 
27226 	    value = xmlTextReaderValue(vctxt->reader);
27227 	    ret = xmlSchemaVPushText(vctxt, nodeType, BAD_CAST value,
27228 		-1, XML_SCHEMA_PUSH_TEXT_CREATED, &consumed);
27229 	    if (! consumed)
27230 		xmlFree(value);
27231 	    if (ret == -1) {
27232 		VERROR_INT("xmlSchemaVReaderWalk",
27233 		    "calling xmlSchemaVPushText()");
27234 		goto internal_error;
27235 	    }
27236 	} else if ((nodeType == XML_ENTITY_NODE) ||
27237 	    (nodeType == XML_ENTITY_REF_NODE)) {
27238 	    /*
27239 	    * VAL TODO: What to do with entities?
27240 	    */
27241 	    TODO
27242 	}
27243 	/*
27244 	* Read next node.
27245 	*/
27246 	ret = xmlTextReaderRead(vctxt->reader);
27247     } while (ret == 1);
27248 
27249 exit:
27250     return (ret);
27251 internal_error:
27252     return (-1);
27253 }
27254 #endif
27255 
27256 /************************************************************************
27257  *									*
27258  *			SAX validation handlers				*
27259  *									*
27260  ************************************************************************/
27261 
27262 /*
27263 * Process text content.
27264 */
27265 static void
xmlSchemaSAXHandleText(void * ctx,const xmlChar * ch,int len)27266 xmlSchemaSAXHandleText(void *ctx,
27267 		       const xmlChar * ch,
27268 		       int len)
27269 {
27270     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27271 
27272     if (vctxt->depth < 0)
27273 	return;
27274     if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27275 	return;
27276     if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27277 	vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27278     if (xmlSchemaVPushText(vctxt, XML_TEXT_NODE, ch, len,
27279 	XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
27280 	VERROR_INT("xmlSchemaSAXHandleCDataSection",
27281 	    "calling xmlSchemaVPushText()");
27282 	vctxt->err = -1;
27283 	xmlStopParser(vctxt->parserCtxt);
27284     }
27285 }
27286 
27287 /*
27288 * Process CDATA content.
27289 */
27290 static void
xmlSchemaSAXHandleCDataSection(void * ctx,const xmlChar * ch,int len)27291 xmlSchemaSAXHandleCDataSection(void *ctx,
27292 			     const xmlChar * ch,
27293 			     int len)
27294 {
27295     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27296 
27297     if (vctxt->depth < 0)
27298 	return;
27299     if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27300 	return;
27301     if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27302 	vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27303     if (xmlSchemaVPushText(vctxt, XML_CDATA_SECTION_NODE, ch, len,
27304 	XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
27305 	VERROR_INT("xmlSchemaSAXHandleCDataSection",
27306 	    "calling xmlSchemaVPushText()");
27307 	vctxt->err = -1;
27308 	xmlStopParser(vctxt->parserCtxt);
27309     }
27310 }
27311 
27312 static void
xmlSchemaSAXHandleReference(void * ctx ATTRIBUTE_UNUSED,const xmlChar * name ATTRIBUTE_UNUSED)27313 xmlSchemaSAXHandleReference(void *ctx ATTRIBUTE_UNUSED,
27314 			    const xmlChar * name ATTRIBUTE_UNUSED)
27315 {
27316     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27317 
27318     if (vctxt->depth < 0)
27319 	return;
27320     if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27321 	return;
27322     /* SAX VAL TODO: What to do here? */
27323     TODO
27324 }
27325 
27326 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)27327 xmlSchemaSAXHandleStartElementNs(void *ctx,
27328 				 const xmlChar * localname,
27329 				 const xmlChar * prefix ATTRIBUTE_UNUSED,
27330 				 const xmlChar * URI,
27331 				 int nb_namespaces,
27332 				 const xmlChar ** namespaces,
27333 				 int nb_attributes,
27334 				 int nb_defaulted ATTRIBUTE_UNUSED,
27335 				 const xmlChar ** attributes)
27336 {
27337     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27338     int ret;
27339     xmlSchemaNodeInfoPtr ielem;
27340     int i, j;
27341 
27342     /*
27343     * SAX VAL TODO: What to do with nb_defaulted?
27344     */
27345     /*
27346     * Skip elements if inside a "skip" wildcard or invalid.
27347     */
27348     vctxt->depth++;
27349     if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27350 	return;
27351     /*
27352     * Push the element.
27353     */
27354     if (xmlSchemaValidatorPushElem(vctxt) == -1) {
27355 	VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27356 	    "calling xmlSchemaValidatorPushElem()");
27357 	goto internal_error;
27358     }
27359     ielem = vctxt->inode;
27360     /*
27361     * TODO: Is this OK?
27362     */
27363     ielem->nodeLine = xmlSAX2GetLineNumber(vctxt->parserCtxt);
27364     ielem->localName = localname;
27365     ielem->nsName = URI;
27366     ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27367     /*
27368     * Register namespaces on the elem info.
27369     */
27370     if (nb_namespaces != 0) {
27371 	/*
27372 	* Although the parser builds its own namespace list,
27373 	* we have no access to it, so we'll use an own one.
27374 	*/
27375         for (i = 0, j = 0; i < nb_namespaces; i++, j += 2) {
27376 	    /*
27377 	    * Store prefix and namespace name.
27378 	    */
27379 	    if (ielem->nsBindings == NULL) {
27380 		ielem->nsBindings =
27381 		    (const xmlChar **) xmlMalloc(10 *
27382 			sizeof(const xmlChar *));
27383 		if (ielem->nsBindings == NULL) {
27384 		    xmlSchemaVErrMemory(vctxt,
27385 			"allocating namespace bindings for SAX validation",
27386 			NULL);
27387 		    goto internal_error;
27388 		}
27389 		ielem->nbNsBindings = 0;
27390 		ielem->sizeNsBindings = 5;
27391 	    } else if (ielem->sizeNsBindings <= ielem->nbNsBindings) {
27392 		ielem->sizeNsBindings *= 2;
27393 		ielem->nsBindings =
27394 		    (const xmlChar **) xmlRealloc(
27395 			(void *) ielem->nsBindings,
27396 			ielem->sizeNsBindings * 2 * sizeof(const xmlChar *));
27397 		if (ielem->nsBindings == NULL) {
27398 		    xmlSchemaVErrMemory(vctxt,
27399 			"re-allocating namespace bindings for SAX validation",
27400 			NULL);
27401 		    goto internal_error;
27402 		}
27403 	    }
27404 
27405 	    ielem->nsBindings[ielem->nbNsBindings * 2] = namespaces[j];
27406 	    if (namespaces[j+1][0] == 0) {
27407 		/*
27408 		* Handle xmlns="".
27409 		*/
27410 		ielem->nsBindings[ielem->nbNsBindings * 2 + 1] = NULL;
27411 	    } else
27412 		ielem->nsBindings[ielem->nbNsBindings * 2 + 1] =
27413 		    namespaces[j+1];
27414 	    ielem->nbNsBindings++;
27415 	}
27416     }
27417     /*
27418     * Register attributes.
27419     * SAX VAL TODO: We are not adding namespace declaration
27420     * attributes yet.
27421     */
27422     if (nb_attributes != 0) {
27423 	int valueLen, k, l;
27424 	xmlChar *value;
27425 
27426         for (j = 0, i = 0; i < nb_attributes; i++, j += 5) {
27427 	    /*
27428 	    * Duplicate the value, changing any &#38; to a literal ampersand.
27429 	    *
27430 	    * libxml2 differs from normal SAX here in that it escapes all ampersands
27431 	    * as &#38; instead of delivering the raw converted string. Changing the
27432 	    * behavior at this point would break applications that use this API, so
27433 	    * we are forced to work around it.
27434 	    */
27435 	    valueLen = attributes[j+4] - attributes[j+3];
27436 	    value = xmlMallocAtomic(valueLen + 1);
27437 	    if (value == NULL) {
27438 		xmlSchemaVErrMemory(vctxt,
27439 		    "allocating string for decoded attribute",
27440 		    NULL);
27441 		goto internal_error;
27442 	    }
27443 	    for (k = 0, l = 0; k < valueLen; l++) {
27444 		if (k < valueLen - 4 &&
27445 		    attributes[j+3][k+0] == '&' &&
27446 		    attributes[j+3][k+1] == '#' &&
27447 		    attributes[j+3][k+2] == '3' &&
27448 		    attributes[j+3][k+3] == '8' &&
27449 		    attributes[j+3][k+4] == ';') {
27450 		    value[l] = '&';
27451 		    k += 5;
27452 		} else {
27453 		    value[l] = attributes[j+3][k];
27454 		    k++;
27455 		}
27456 	    }
27457 	    value[l] = '\0';
27458 	    /*
27459 	    * TODO: Set the node line.
27460 	    */
27461 	    ret = xmlSchemaValidatorPushAttribute(vctxt,
27462 		NULL, ielem->nodeLine, attributes[j], attributes[j+2], 0,
27463 		value, 1);
27464 	    if (ret == -1) {
27465 		VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27466 		    "calling xmlSchemaValidatorPushAttribute()");
27467 		goto internal_error;
27468 	    }
27469 	}
27470     }
27471     /*
27472     * Validate the element.
27473     */
27474     ret = xmlSchemaValidateElem(vctxt);
27475     if (ret != 0) {
27476 	if (ret == -1) {
27477 	    VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27478 		"calling xmlSchemaValidateElem()");
27479 	    goto internal_error;
27480 	}
27481 	goto exit;
27482     }
27483 
27484 exit:
27485     return;
27486 internal_error:
27487     vctxt->err = -1;
27488     xmlStopParser(vctxt->parserCtxt);
27489     return;
27490 }
27491 
27492 static void
xmlSchemaSAXHandleEndElementNs(void * ctx,const xmlChar * localname ATTRIBUTE_UNUSED,const xmlChar * prefix ATTRIBUTE_UNUSED,const xmlChar * URI ATTRIBUTE_UNUSED)27493 xmlSchemaSAXHandleEndElementNs(void *ctx,
27494 			       const xmlChar * localname ATTRIBUTE_UNUSED,
27495 			       const xmlChar * prefix ATTRIBUTE_UNUSED,
27496 			       const xmlChar * URI ATTRIBUTE_UNUSED)
27497 {
27498     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27499     int res;
27500 
27501     /*
27502     * Skip elements if inside a "skip" wildcard or if invalid.
27503     */
27504     if (vctxt->skipDepth != -1) {
27505 	if (vctxt->depth > vctxt->skipDepth) {
27506 	    vctxt->depth--;
27507 	    return;
27508 	} else
27509 	    vctxt->skipDepth = -1;
27510     }
27511     /*
27512     * SAX VAL TODO: Just a temporary check.
27513     */
27514     if ((!xmlStrEqual(vctxt->inode->localName, localname)) ||
27515 	(!xmlStrEqual(vctxt->inode->nsName, URI))) {
27516 	VERROR_INT("xmlSchemaSAXHandleEndElementNs",
27517 	    "elem pop mismatch");
27518     }
27519     res = xmlSchemaValidatorPopElem(vctxt);
27520     if (res != 0) {
27521 	if (res < 0) {
27522 	    VERROR_INT("xmlSchemaSAXHandleEndElementNs",
27523 		"calling xmlSchemaValidatorPopElem()");
27524 	    goto internal_error;
27525 	}
27526 	goto exit;
27527     }
27528 exit:
27529     return;
27530 internal_error:
27531     vctxt->err = -1;
27532     xmlStopParser(vctxt->parserCtxt);
27533     return;
27534 }
27535 
27536 /************************************************************************
27537  *									*
27538  *			Validation interfaces				*
27539  *									*
27540  ************************************************************************/
27541 
27542 /**
27543  * xmlSchemaNewValidCtxt:
27544  * @schema:  a precompiled XML Schemas
27545  *
27546  * Create an XML Schemas validation context based on the given schema.
27547  *
27548  * Returns the validation context or NULL in case of error
27549  */
27550 xmlSchemaValidCtxtPtr
xmlSchemaNewValidCtxt(xmlSchemaPtr schema)27551 xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
27552 {
27553     xmlSchemaValidCtxtPtr ret;
27554 
27555     ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
27556     if (ret == NULL) {
27557         xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
27558         return (NULL);
27559     }
27560     memset(ret, 0, sizeof(xmlSchemaValidCtxt));
27561     ret->type = XML_SCHEMA_CTXT_VALIDATOR;
27562     ret->dict = xmlDictCreate();
27563     ret->nodeQNames = xmlSchemaItemListCreate();
27564     ret->schema = schema;
27565     return (ret);
27566 }
27567 
27568 /**
27569  * xmlSchemaValidateSetFilename:
27570  * @vctxt: the schema validation context
27571  * @filename: the file name
27572  *
27573  * Workaround to provide file error reporting information when this is
27574  * not provided by current APIs
27575  */
27576 void
xmlSchemaValidateSetFilename(xmlSchemaValidCtxtPtr vctxt,const char * filename)27577 xmlSchemaValidateSetFilename(xmlSchemaValidCtxtPtr vctxt, const char *filename) {
27578     if (vctxt == NULL)
27579         return;
27580     if (vctxt->filename != NULL)
27581         xmlFree(vctxt->filename);
27582     if (filename != NULL)
27583         vctxt->filename = (char *) xmlStrdup((const xmlChar *) filename);
27584     else
27585         vctxt->filename = NULL;
27586 }
27587 
27588 /**
27589  * xmlSchemaClearValidCtxt:
27590  * @vctxt: the schema validation context
27591  *
27592  * Free the resources associated to the schema validation context;
27593  * leaves some fields alive intended for reuse of the context.
27594  */
27595 static void
xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)27596 xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
27597 {
27598     if (vctxt == NULL)
27599         return;
27600 
27601     /*
27602     * TODO: Should we clear the flags?
27603     *   Might be problematic if one reuses the context
27604     *   and assumes that the options remain the same.
27605     */
27606     vctxt->flags = 0;
27607     vctxt->validationRoot = NULL;
27608     vctxt->doc = NULL;
27609 #ifdef LIBXML_READER_ENABLED
27610     vctxt->reader = NULL;
27611 #endif
27612     vctxt->hasKeyrefs = 0;
27613 
27614     if (vctxt->value != NULL) {
27615         xmlSchemaFreeValue(vctxt->value);
27616 	vctxt->value = NULL;
27617     }
27618     /*
27619     * Augmented IDC information.
27620     */
27621     if (vctxt->aidcs != NULL) {
27622 	xmlSchemaIDCAugPtr cur = vctxt->aidcs, next;
27623 	do {
27624 	    next = cur->next;
27625 	    xmlFree(cur);
27626 	    cur = next;
27627 	} while (cur != NULL);
27628 	vctxt->aidcs = NULL;
27629     }
27630     if (vctxt->idcMatcherCache != NULL) {
27631 	xmlSchemaIDCMatcherPtr matcher = vctxt->idcMatcherCache, tmp;
27632 
27633 	while (matcher) {
27634 	    tmp = matcher;
27635 	    matcher = matcher->nextCached;
27636 	    xmlSchemaIDCFreeMatcherList(tmp);
27637 	}
27638 	vctxt->idcMatcherCache = NULL;
27639     }
27640 
27641 
27642     if (vctxt->idcNodes != NULL) {
27643 	int i;
27644 	xmlSchemaPSVIIDCNodePtr item;
27645 
27646 	for (i = 0; i < vctxt->nbIdcNodes; i++) {
27647 	    item = vctxt->idcNodes[i];
27648 	    xmlFree(item->keys);
27649 	    xmlFree(item);
27650 	}
27651 	xmlFree(vctxt->idcNodes);
27652 	vctxt->idcNodes = NULL;
27653 	vctxt->nbIdcNodes = 0;
27654 	vctxt->sizeIdcNodes = 0;
27655     }
27656 
27657     if (vctxt->idcKeys != NULL) {
27658 	int i;
27659 	for (i = 0; i < vctxt->nbIdcKeys; i++)
27660 	    xmlSchemaIDCFreeKey(vctxt->idcKeys[i]);
27661 	xmlFree(vctxt->idcKeys);
27662 	vctxt->idcKeys = NULL;
27663 	vctxt->nbIdcKeys = 0;
27664 	vctxt->sizeIdcKeys = 0;
27665     }
27666 
27667     /*
27668     * Note that we won't delete the XPath state pool here.
27669     */
27670     if (vctxt->xpathStates != NULL) {
27671 	xmlSchemaFreeIDCStateObjList(vctxt->xpathStates);
27672 	vctxt->xpathStates = NULL;
27673     }
27674     /*
27675     * Attribute info.
27676     */
27677     if (vctxt->nbAttrInfos != 0) {
27678 	xmlSchemaClearAttrInfos(vctxt);
27679     }
27680     /*
27681     * Element info.
27682     */
27683     if (vctxt->elemInfos != NULL) {
27684 	int i;
27685 	xmlSchemaNodeInfoPtr ei;
27686 
27687 	for (i = 0; i < vctxt->sizeElemInfos; i++) {
27688 	    ei = vctxt->elemInfos[i];
27689 	    if (ei == NULL)
27690 		break;
27691 	    xmlSchemaClearElemInfo(vctxt, ei);
27692 	}
27693     }
27694     xmlSchemaItemListClear(vctxt->nodeQNames);
27695     /* Recreate the dict. */
27696     xmlDictFree(vctxt->dict);
27697     /*
27698     * TODO: Is is save to recreate it? Do we have a scenario
27699     * where the user provides the dict?
27700     */
27701     vctxt->dict = xmlDictCreate();
27702 
27703     if (vctxt->filename != NULL) {
27704         xmlFree(vctxt->filename);
27705 	vctxt->filename = NULL;
27706     }
27707 }
27708 
27709 /**
27710  * xmlSchemaFreeValidCtxt:
27711  * @ctxt:  the schema validation context
27712  *
27713  * Free the resources associated to the schema validation context
27714  */
27715 void
xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)27716 xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
27717 {
27718     if (ctxt == NULL)
27719         return;
27720     if (ctxt->value != NULL)
27721         xmlSchemaFreeValue(ctxt->value);
27722     if (ctxt->pctxt != NULL)
27723 	xmlSchemaFreeParserCtxt(ctxt->pctxt);
27724     if (ctxt->idcNodes != NULL) {
27725 	int i;
27726 	xmlSchemaPSVIIDCNodePtr item;
27727 
27728 	for (i = 0; i < ctxt->nbIdcNodes; i++) {
27729 	    item = ctxt->idcNodes[i];
27730 	    xmlFree(item->keys);
27731 	    xmlFree(item);
27732 	}
27733 	xmlFree(ctxt->idcNodes);
27734     }
27735     if (ctxt->idcKeys != NULL) {
27736 	int i;
27737 	for (i = 0; i < ctxt->nbIdcKeys; i++)
27738 	    xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
27739 	xmlFree(ctxt->idcKeys);
27740     }
27741 
27742     if (ctxt->xpathStates != NULL) {
27743 	xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
27744 	ctxt->xpathStates = NULL;
27745     }
27746     if (ctxt->xpathStatePool != NULL) {
27747 	xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
27748 	ctxt->xpathStatePool = NULL;
27749     }
27750 
27751     /*
27752     * Augmented IDC information.
27753     */
27754     if (ctxt->aidcs != NULL) {
27755 	xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
27756 	do {
27757 	    next = cur->next;
27758 	    xmlFree(cur);
27759 	    cur = next;
27760 	} while (cur != NULL);
27761     }
27762     if (ctxt->attrInfos != NULL) {
27763 	int i;
27764 	xmlSchemaAttrInfoPtr attr;
27765 
27766 	/* Just a paranoid call to the cleanup. */
27767 	if (ctxt->nbAttrInfos != 0)
27768 	    xmlSchemaClearAttrInfos(ctxt);
27769 	for (i = 0; i < ctxt->sizeAttrInfos; i++) {
27770 	    attr = ctxt->attrInfos[i];
27771 	    xmlFree(attr);
27772 	}
27773 	xmlFree(ctxt->attrInfos);
27774     }
27775     if (ctxt->elemInfos != NULL) {
27776 	int i;
27777 	xmlSchemaNodeInfoPtr ei;
27778 
27779 	for (i = 0; i < ctxt->sizeElemInfos; i++) {
27780 	    ei = ctxt->elemInfos[i];
27781 	    if (ei == NULL)
27782 		break;
27783 	    xmlSchemaClearElemInfo(ctxt, ei);
27784 	    xmlFree(ei);
27785 	}
27786 	xmlFree(ctxt->elemInfos);
27787     }
27788     if (ctxt->nodeQNames != NULL)
27789 	xmlSchemaItemListFree(ctxt->nodeQNames);
27790     if (ctxt->dict != NULL)
27791 	xmlDictFree(ctxt->dict);
27792     if (ctxt->filename != NULL)
27793 	xmlFree(ctxt->filename);
27794     xmlFree(ctxt);
27795 }
27796 
27797 /**
27798  * xmlSchemaIsValid:
27799  * @ctxt: the schema validation context
27800  *
27801  * Check if any error was detected during validation.
27802  *
27803  * Returns 1 if valid so far, 0 if errors were detected, and -1 in case
27804  *         of internal error.
27805  */
27806 int
xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt)27807 xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt)
27808 {
27809     if (ctxt == NULL)
27810         return(-1);
27811     return(ctxt->err == 0);
27812 }
27813 
27814 /**
27815  * xmlSchemaSetValidErrors:
27816  * @ctxt:  a schema validation context
27817  * @err:  the error function
27818  * @warn: the warning function
27819  * @ctx: the functions context
27820  *
27821  * Set the error and warning callback informations
27822  */
27823 void
xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,xmlSchemaValidityErrorFunc err,xmlSchemaValidityWarningFunc warn,void * ctx)27824 xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
27825                         xmlSchemaValidityErrorFunc err,
27826                         xmlSchemaValidityWarningFunc warn, void *ctx)
27827 {
27828     if (ctxt == NULL)
27829         return;
27830     ctxt->error = err;
27831     ctxt->warning = warn;
27832     ctxt->errCtxt = ctx;
27833     if (ctxt->pctxt != NULL)
27834 	xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
27835 }
27836 
27837 /**
27838  * xmlSchemaSetValidStructuredErrors:
27839  * @ctxt:  a schema validation context
27840  * @serror:  the structured error function
27841  * @ctx: the functions context
27842  *
27843  * Set the structured error callback
27844  */
27845 void
xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt,xmlStructuredErrorFunc serror,void * ctx)27846 xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt,
27847 				  xmlStructuredErrorFunc serror, void *ctx)
27848 {
27849     if (ctxt == NULL)
27850         return;
27851     ctxt->serror = serror;
27852     ctxt->error = NULL;
27853     ctxt->warning = NULL;
27854     ctxt->errCtxt = ctx;
27855     if (ctxt->pctxt != NULL)
27856 	xmlSchemaSetParserStructuredErrors(ctxt->pctxt, serror, ctx);
27857 }
27858 
27859 /**
27860  * xmlSchemaGetValidErrors:
27861  * @ctxt: a XML-Schema validation context
27862  * @err: the error function result
27863  * @warn: the warning function result
27864  * @ctx: the functions context result
27865  *
27866  * Get the error and warning callback informations
27867  *
27868  * Returns -1 in case of error and 0 otherwise
27869  */
27870 int
xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,xmlSchemaValidityErrorFunc * err,xmlSchemaValidityWarningFunc * warn,void ** ctx)27871 xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
27872 			xmlSchemaValidityErrorFunc * err,
27873 			xmlSchemaValidityWarningFunc * warn, void **ctx)
27874 {
27875 	if (ctxt == NULL)
27876 		return (-1);
27877 	if (err != NULL)
27878 		*err = ctxt->error;
27879 	if (warn != NULL)
27880 		*warn = ctxt->warning;
27881 	if (ctx != NULL)
27882 		*ctx = ctxt->errCtxt;
27883 	return (0);
27884 }
27885 
27886 
27887 /**
27888  * xmlSchemaSetValidOptions:
27889  * @ctxt:	a schema validation context
27890  * @options: a combination of xmlSchemaValidOption
27891  *
27892  * Sets the options to be used during the validation.
27893  *
27894  * Returns 0 in case of success, -1 in case of an
27895  * API error.
27896  */
27897 int
xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,int options)27898 xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
27899 			 int options)
27900 
27901 {
27902     int i;
27903 
27904     if (ctxt == NULL)
27905 	return (-1);
27906     /*
27907     * WARNING: Change the start value if adding to the
27908     * xmlSchemaValidOption.
27909     * TODO: Is there an other, more easy to maintain,
27910     * way?
27911     */
27912     for (i = 1; i < (int) sizeof(int) * 8; i++) {
27913         if (options & 1<<i)
27914 	    return (-1);
27915     }
27916     ctxt->options = options;
27917     return (0);
27918 }
27919 
27920 /**
27921  * xmlSchemaValidCtxtGetOptions:
27922  * @ctxt: a schema validation context
27923  *
27924  * Get the validation context options.
27925  *
27926  * Returns the option combination or -1 on error.
27927  */
27928 int
xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)27929 xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
27930 
27931 {
27932     if (ctxt == NULL)
27933 	return (-1);
27934     else
27935 	return (ctxt->options);
27936 }
27937 
27938 static int
xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)27939 xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)
27940 {
27941     xmlAttrPtr attr;
27942     int ret = 0;
27943     xmlSchemaNodeInfoPtr ielem = NULL;
27944     xmlNodePtr node, valRoot;
27945     const xmlChar *nsName;
27946 
27947     /* DOC VAL TODO: Move this to the start function. */
27948     if (vctxt->validationRoot != NULL)
27949         valRoot = vctxt->validationRoot;
27950     else
27951 	valRoot = xmlDocGetRootElement(vctxt->doc);
27952     if (valRoot == NULL) {
27953 	/* VAL TODO: Error code? */
27954 	VERROR(1, NULL, "The document has no document element");
27955 	return (1);
27956     }
27957     vctxt->depth = -1;
27958     vctxt->validationRoot = valRoot;
27959     node = valRoot;
27960     while (node != NULL) {
27961 	if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27962 	    goto next_sibling;
27963 	if (node->type == XML_ELEMENT_NODE) {
27964 
27965 	    /*
27966 	    * Init the node-info.
27967 	    */
27968 	    vctxt->depth++;
27969 	    if (xmlSchemaValidatorPushElem(vctxt) == -1)
27970 		goto internal_error;
27971 	    ielem = vctxt->inode;
27972 	    ielem->node = node;
27973 	    ielem->nodeLine = node->line;
27974 	    ielem->localName = node->name;
27975 	    if (node->ns != NULL)
27976 		ielem->nsName = node->ns->href;
27977 	    ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27978 	    /*
27979 	    * Register attributes.
27980 	    * DOC VAL TODO: We do not register namespace declaration
27981 	    * attributes yet.
27982 	    */
27983 	    vctxt->nbAttrInfos = 0;
27984 	    if (node->properties != NULL) {
27985 		attr = node->properties;
27986 		do {
27987 		    if (attr->ns != NULL)
27988 			nsName = attr->ns->href;
27989 		    else
27990 			nsName = NULL;
27991 		    ret = xmlSchemaValidatorPushAttribute(vctxt,
27992 			(xmlNodePtr) attr,
27993 			/*
27994 			* Note that we give it the line number of the
27995 			* parent element.
27996 			*/
27997 			ielem->nodeLine,
27998 			attr->name, nsName, 0,
27999 			xmlNodeListGetString(attr->doc, attr->children, 1), 1);
28000 		    if (ret == -1) {
28001 			VERROR_INT("xmlSchemaDocWalk",
28002 			    "calling xmlSchemaValidatorPushAttribute()");
28003 			goto internal_error;
28004 		    }
28005 		    attr = attr->next;
28006 		} while (attr);
28007 	    }
28008 	    /*
28009 	    * Validate the element.
28010 	    */
28011 	    ret = xmlSchemaValidateElem(vctxt);
28012 	    if (ret != 0) {
28013 		if (ret == -1) {
28014 		    VERROR_INT("xmlSchemaDocWalk",
28015 			"calling xmlSchemaValidateElem()");
28016 		    goto internal_error;
28017 		}
28018 		/*
28019 		* Don't stop validation; just skip the content
28020 		* of this element.
28021 		*/
28022 		goto leave_node;
28023 	    }
28024 	    if ((vctxt->skipDepth != -1) &&
28025 		(vctxt->depth >= vctxt->skipDepth))
28026 		goto leave_node;
28027 	} else if ((node->type == XML_TEXT_NODE) ||
28028 	    (node->type == XML_CDATA_SECTION_NODE)) {
28029 	    /*
28030 	    * Process character content.
28031 	    */
28032 	    if ((ielem != NULL) && (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY))
28033 		ielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
28034 	    ret = xmlSchemaVPushText(vctxt, node->type, node->content,
28035 		-1, XML_SCHEMA_PUSH_TEXT_PERSIST, NULL);
28036 	    if (ret < 0) {
28037 		VERROR_INT("xmlSchemaVDocWalk",
28038 		    "calling xmlSchemaVPushText()");
28039 		goto internal_error;
28040 	    }
28041 	    /*
28042 	    * DOC VAL TODO: Should we skip further validation of the
28043 	    * element content here?
28044 	    */
28045 	} else if ((node->type == XML_ENTITY_NODE) ||
28046 	    (node->type == XML_ENTITY_REF_NODE)) {
28047 	    /*
28048 	    * DOC VAL TODO: What to do with entities?
28049 	    */
28050 	    VERROR_INT("xmlSchemaVDocWalk",
28051 		"there is at least one entity reference in the node-tree "
28052 		"currently being validated. Processing of entities with "
28053 		"this XML Schema processor is not supported (yet). Please "
28054 		"substitute entities before validation.");
28055 	    goto internal_error;
28056 	} else {
28057 	    goto leave_node;
28058 	    /*
28059 	    * DOC VAL TODO: XInclude nodes, etc.
28060 	    */
28061 	}
28062 	/*
28063 	* Walk the doc.
28064 	*/
28065 	if (node->children != NULL) {
28066 	    node = node->children;
28067 	    continue;
28068 	}
28069 leave_node:
28070 	if (node->type == XML_ELEMENT_NODE) {
28071 	    /*
28072 	    * Leaving the scope of an element.
28073 	    */
28074 	    if (node != vctxt->inode->node) {
28075 		VERROR_INT("xmlSchemaVDocWalk",
28076 		    "element position mismatch");
28077 		goto internal_error;
28078 	    }
28079 	    ret = xmlSchemaValidatorPopElem(vctxt);
28080 	    if (ret != 0) {
28081 		if (ret < 0) {
28082 		    VERROR_INT("xmlSchemaVDocWalk",
28083 			"calling xmlSchemaValidatorPopElem()");
28084 		    goto internal_error;
28085 		}
28086 	    }
28087 	    if (node == valRoot)
28088 		goto exit;
28089 	}
28090 next_sibling:
28091 	if (node->next != NULL)
28092 	    node = node->next;
28093 	else {
28094 	    node = node->parent;
28095 	    goto leave_node;
28096 	}
28097     }
28098 
28099 exit:
28100     return (ret);
28101 internal_error:
28102     return (-1);
28103 }
28104 
28105 static int
xmlSchemaPreRun(xmlSchemaValidCtxtPtr vctxt)28106 xmlSchemaPreRun(xmlSchemaValidCtxtPtr vctxt) {
28107     /*
28108     * Some initialization.
28109     */
28110     vctxt->err = 0;
28111     vctxt->nberrors = 0;
28112     vctxt->depth = -1;
28113     vctxt->skipDepth = -1;
28114     vctxt->xsiAssemble = 0;
28115     vctxt->hasKeyrefs = 0;
28116 #ifdef ENABLE_IDC_NODE_TABLES_TEST
28117     vctxt->createIDCNodeTables = 1;
28118 #else
28119     vctxt->createIDCNodeTables = 0;
28120 #endif
28121     /*
28122     * Create a schema + parser if necessary.
28123     */
28124     if (vctxt->schema == NULL) {
28125 	xmlSchemaParserCtxtPtr pctxt;
28126 
28127 	vctxt->xsiAssemble = 1;
28128 	/*
28129 	* If not schema was given then we will create a schema
28130 	* dynamically using XSI schema locations.
28131 	*
28132 	* Create the schema parser context.
28133 	*/
28134 	if ((vctxt->pctxt == NULL) &&
28135 	   (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
28136 	   return (-1);
28137 	pctxt = vctxt->pctxt;
28138 	pctxt->xsiAssemble = 1;
28139 	/*
28140 	* Create the schema.
28141 	*/
28142 	vctxt->schema = xmlSchemaNewSchema(pctxt);
28143 	if (vctxt->schema == NULL)
28144 	    return (-1);
28145 	/*
28146 	* Create the schema construction context.
28147 	*/
28148 	pctxt->constructor = xmlSchemaConstructionCtxtCreate(pctxt->dict);
28149 	if (pctxt->constructor == NULL)
28150 	    return(-1);
28151 	pctxt->constructor->mainSchema = vctxt->schema;
28152 	/*
28153 	* Take ownership of the constructor to be able to free it.
28154 	*/
28155 	pctxt->ownsConstructor = 1;
28156     }
28157     /*
28158     * Augment the IDC definitions for the main schema and all imported ones
28159     * NOTE: main schema if the first in the imported list
28160     */
28161     xmlHashScan(vctxt->schema->schemasImports, xmlSchemaAugmentImportedIDC,
28162                 vctxt);
28163 
28164     return(0);
28165 }
28166 
28167 static void
xmlSchemaPostRun(xmlSchemaValidCtxtPtr vctxt)28168 xmlSchemaPostRun(xmlSchemaValidCtxtPtr vctxt) {
28169     if (vctxt->xsiAssemble) {
28170 	if (vctxt->schema != NULL) {
28171 	    xmlSchemaFree(vctxt->schema);
28172 	    vctxt->schema = NULL;
28173 	}
28174     }
28175     xmlSchemaClearValidCtxt(vctxt);
28176 }
28177 
28178 static int
xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt)28179 xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt)
28180 {
28181     int ret = 0;
28182 
28183     if (xmlSchemaPreRun(vctxt) < 0)
28184         return(-1);
28185 
28186     if (vctxt->doc != NULL) {
28187 	/*
28188 	 * Tree validation.
28189 	 */
28190 	ret = xmlSchemaVDocWalk(vctxt);
28191 #ifdef LIBXML_READER_ENABLED
28192     } else if (vctxt->reader != NULL) {
28193 	/*
28194 	 * XML Reader validation.
28195 	 */
28196 #ifdef XML_SCHEMA_READER_ENABLED
28197 	ret = xmlSchemaVReaderWalk(vctxt);
28198 #endif
28199 #endif
28200     } else if ((vctxt->sax != NULL) && (vctxt->parserCtxt != NULL)) {
28201 	/*
28202 	 * SAX validation.
28203 	 */
28204 	ret = xmlParseDocument(vctxt->parserCtxt);
28205     } else {
28206 	VERROR_INT("xmlSchemaVStart",
28207 	    "no instance to validate");
28208 	ret = -1;
28209     }
28210 
28211     xmlSchemaPostRun(vctxt);
28212     if (ret == 0)
28213 	ret = vctxt->err;
28214     return (ret);
28215 }
28216 
28217 /**
28218  * xmlSchemaValidateOneElement:
28219  * @ctxt:  a schema validation context
28220  * @elem:  an element node
28221  *
28222  * Validate a branch of a tree, starting with the given @elem.
28223  *
28224  * Returns 0 if the element and its subtree is valid, a positive error
28225  * code number otherwise and -1 in case of an internal or API error.
28226  */
28227 int
xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt,xmlNodePtr elem)28228 xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
28229 {
28230     if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
28231 	return (-1);
28232 
28233     if (ctxt->schema == NULL)
28234 	return (-1);
28235 
28236     ctxt->doc = elem->doc;
28237     ctxt->node = elem;
28238     ctxt->validationRoot = elem;
28239     return(xmlSchemaVStart(ctxt));
28240 }
28241 
28242 /**
28243  * xmlSchemaValidateDoc:
28244  * @ctxt:  a schema validation context
28245  * @doc:  a parsed document tree
28246  *
28247  * Validate a document tree in memory.
28248  *
28249  * Returns 0 if the document is schemas valid, a positive error code
28250  *     number otherwise and -1 in case of internal or API error.
28251  */
28252 int
xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt,xmlDocPtr doc)28253 xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
28254 {
28255     if ((ctxt == NULL) || (doc == NULL))
28256         return (-1);
28257 
28258     ctxt->doc = doc;
28259     ctxt->node = xmlDocGetRootElement(doc);
28260     if (ctxt->node == NULL) {
28261         xmlSchemaCustomErr(ACTXT_CAST ctxt,
28262 	    XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
28263 	    (xmlNodePtr) doc, NULL,
28264 	    "The document has no document element", NULL, NULL);
28265         return (ctxt->err);
28266     }
28267     ctxt->validationRoot = ctxt->node;
28268     return (xmlSchemaVStart(ctxt));
28269 }
28270 
28271 
28272 /************************************************************************
28273  *									*
28274  *		Function and data for SAX streaming API			*
28275  *									*
28276  ************************************************************************/
28277 typedef struct _xmlSchemaSplitSAXData xmlSchemaSplitSAXData;
28278 typedef xmlSchemaSplitSAXData *xmlSchemaSplitSAXDataPtr;
28279 
28280 struct _xmlSchemaSplitSAXData {
28281     xmlSAXHandlerPtr      user_sax;
28282     void                 *user_data;
28283     xmlSchemaValidCtxtPtr ctxt;
28284     xmlSAXHandlerPtr      schemas_sax;
28285 };
28286 
28287 #define XML_SAX_PLUG_MAGIC 0xdc43ba21
28288 
28289 struct _xmlSchemaSAXPlug {
28290     unsigned int magic;
28291 
28292     /* the original callbacks informations */
28293     xmlSAXHandlerPtr     *user_sax_ptr;
28294     xmlSAXHandlerPtr      user_sax;
28295     void                **user_data_ptr;
28296     void                 *user_data;
28297 
28298     /* the block plugged back and validation informations */
28299     xmlSAXHandler         schemas_sax;
28300     xmlSchemaValidCtxtPtr ctxt;
28301 };
28302 
28303 /* All those functions just bounces to the user provided SAX handlers */
28304 static void
internalSubsetSplit(void * ctx,const xmlChar * name,const xmlChar * ExternalID,const xmlChar * SystemID)28305 internalSubsetSplit(void *ctx, const xmlChar *name,
28306 	       const xmlChar *ExternalID, const xmlChar *SystemID)
28307 {
28308     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28309     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28310         (ctxt->user_sax->internalSubset != NULL))
28311 	ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
28312 	                               SystemID);
28313 }
28314 
28315 static int
isStandaloneSplit(void * ctx)28316 isStandaloneSplit(void *ctx)
28317 {
28318     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28319     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28320         (ctxt->user_sax->isStandalone != NULL))
28321 	return(ctxt->user_sax->isStandalone(ctxt->user_data));
28322     return(0);
28323 }
28324 
28325 static int
hasInternalSubsetSplit(void * ctx)28326 hasInternalSubsetSplit(void *ctx)
28327 {
28328     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28329     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28330         (ctxt->user_sax->hasInternalSubset != NULL))
28331 	return(ctxt->user_sax->hasInternalSubset(ctxt->user_data));
28332     return(0);
28333 }
28334 
28335 static int
hasExternalSubsetSplit(void * ctx)28336 hasExternalSubsetSplit(void *ctx)
28337 {
28338     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28339     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28340         (ctxt->user_sax->hasExternalSubset != NULL))
28341 	return(ctxt->user_sax->hasExternalSubset(ctxt->user_data));
28342     return(0);
28343 }
28344 
28345 static void
externalSubsetSplit(void * ctx,const xmlChar * name,const xmlChar * ExternalID,const xmlChar * SystemID)28346 externalSubsetSplit(void *ctx, const xmlChar *name,
28347 	       const xmlChar *ExternalID, const xmlChar *SystemID)
28348 {
28349     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28350     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28351         (ctxt->user_sax->externalSubset != NULL))
28352 	ctxt->user_sax->externalSubset(ctxt->user_data, name, ExternalID,
28353 	                               SystemID);
28354 }
28355 
28356 static xmlParserInputPtr
resolveEntitySplit(void * ctx,const xmlChar * publicId,const xmlChar * systemId)28357 resolveEntitySplit(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
28358 {
28359     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28360     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28361         (ctxt->user_sax->resolveEntity != NULL))
28362 	return(ctxt->user_sax->resolveEntity(ctxt->user_data, publicId,
28363 	                                     systemId));
28364     return(NULL);
28365 }
28366 
28367 static xmlEntityPtr
getEntitySplit(void * ctx,const xmlChar * name)28368 getEntitySplit(void *ctx, const xmlChar *name)
28369 {
28370     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28371     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28372         (ctxt->user_sax->getEntity != NULL))
28373 	return(ctxt->user_sax->getEntity(ctxt->user_data, name));
28374     return(NULL);
28375 }
28376 
28377 static xmlEntityPtr
getParameterEntitySplit(void * ctx,const xmlChar * name)28378 getParameterEntitySplit(void *ctx, const xmlChar *name)
28379 {
28380     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28381     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28382         (ctxt->user_sax->getParameterEntity != NULL))
28383 	return(ctxt->user_sax->getParameterEntity(ctxt->user_data, name));
28384     return(NULL);
28385 }
28386 
28387 
28388 static void
entityDeclSplit(void * ctx,const xmlChar * name,int type,const xmlChar * publicId,const xmlChar * systemId,xmlChar * content)28389 entityDeclSplit(void *ctx, const xmlChar *name, int type,
28390           const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
28391 {
28392     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28393     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28394         (ctxt->user_sax->entityDecl != NULL))
28395 	ctxt->user_sax->entityDecl(ctxt->user_data, name, type, publicId,
28396 	                           systemId, content);
28397 }
28398 
28399 static void
attributeDeclSplit(void * ctx,const xmlChar * elem,const xmlChar * name,int type,int def,const xmlChar * defaultValue,xmlEnumerationPtr tree)28400 attributeDeclSplit(void *ctx, const xmlChar * elem,
28401                    const xmlChar * name, int type, int def,
28402                    const xmlChar * defaultValue, xmlEnumerationPtr tree)
28403 {
28404     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28405     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28406         (ctxt->user_sax->attributeDecl != NULL)) {
28407 	ctxt->user_sax->attributeDecl(ctxt->user_data, elem, name, type,
28408 	                              def, defaultValue, tree);
28409     } else {
28410 	xmlFreeEnumeration(tree);
28411     }
28412 }
28413 
28414 static void
elementDeclSplit(void * ctx,const xmlChar * name,int type,xmlElementContentPtr content)28415 elementDeclSplit(void *ctx, const xmlChar *name, int type,
28416 	    xmlElementContentPtr content)
28417 {
28418     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28419     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28420         (ctxt->user_sax->elementDecl != NULL))
28421 	ctxt->user_sax->elementDecl(ctxt->user_data, name, type, content);
28422 }
28423 
28424 static void
notationDeclSplit(void * ctx,const xmlChar * name,const xmlChar * publicId,const xmlChar * systemId)28425 notationDeclSplit(void *ctx, const xmlChar *name,
28426 	     const xmlChar *publicId, const xmlChar *systemId)
28427 {
28428     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28429     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28430         (ctxt->user_sax->notationDecl != NULL))
28431 	ctxt->user_sax->notationDecl(ctxt->user_data, name, publicId,
28432 	                             systemId);
28433 }
28434 
28435 static void
unparsedEntityDeclSplit(void * ctx,const xmlChar * name,const xmlChar * publicId,const xmlChar * systemId,const xmlChar * notationName)28436 unparsedEntityDeclSplit(void *ctx, const xmlChar *name,
28437 		   const xmlChar *publicId, const xmlChar *systemId,
28438 		   const xmlChar *notationName)
28439 {
28440     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28441     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28442         (ctxt->user_sax->unparsedEntityDecl != NULL))
28443 	ctxt->user_sax->unparsedEntityDecl(ctxt->user_data, name, publicId,
28444 	                                   systemId, notationName);
28445 }
28446 
28447 static void
setDocumentLocatorSplit(void * ctx,xmlSAXLocatorPtr loc)28448 setDocumentLocatorSplit(void *ctx, xmlSAXLocatorPtr loc)
28449 {
28450     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28451     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28452         (ctxt->user_sax->setDocumentLocator != NULL))
28453 	ctxt->user_sax->setDocumentLocator(ctxt->user_data, loc);
28454 }
28455 
28456 static void
startDocumentSplit(void * ctx)28457 startDocumentSplit(void *ctx)
28458 {
28459     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28460     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28461         (ctxt->user_sax->startDocument != NULL))
28462 	ctxt->user_sax->startDocument(ctxt->user_data);
28463 }
28464 
28465 static void
endDocumentSplit(void * ctx)28466 endDocumentSplit(void *ctx)
28467 {
28468     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28469     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28470         (ctxt->user_sax->endDocument != NULL))
28471 	ctxt->user_sax->endDocument(ctxt->user_data);
28472 }
28473 
28474 static void
processingInstructionSplit(void * ctx,const xmlChar * target,const xmlChar * data)28475 processingInstructionSplit(void *ctx, const xmlChar *target,
28476                       const xmlChar *data)
28477 {
28478     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28479     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28480         (ctxt->user_sax->processingInstruction != NULL))
28481 	ctxt->user_sax->processingInstruction(ctxt->user_data, target, data);
28482 }
28483 
28484 static void
commentSplit(void * ctx,const xmlChar * value)28485 commentSplit(void *ctx, const xmlChar *value)
28486 {
28487     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28488     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28489         (ctxt->user_sax->comment != NULL))
28490 	ctxt->user_sax->comment(ctxt->user_data, value);
28491 }
28492 
28493 /*
28494  * Varargs error callbacks to the user application, harder ...
28495  */
28496 
28497 static void XMLCDECL
warningSplit(void * ctx,const char * msg ATTRIBUTE_UNUSED,...)28498 warningSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28499     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28500     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28501         (ctxt->user_sax->warning != NULL)) {
28502 	TODO
28503     }
28504 }
28505 static void XMLCDECL
errorSplit(void * ctx,const char * msg ATTRIBUTE_UNUSED,...)28506 errorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28507     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28508     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28509         (ctxt->user_sax->error != NULL)) {
28510 	TODO
28511     }
28512 }
28513 static void XMLCDECL
fatalErrorSplit(void * ctx,const char * msg ATTRIBUTE_UNUSED,...)28514 fatalErrorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28515     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28516     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28517         (ctxt->user_sax->fatalError != NULL)) {
28518 	TODO
28519     }
28520 }
28521 
28522 /*
28523  * Those are function where both the user handler and the schemas handler
28524  * need to be called.
28525  */
28526 static void
charactersSplit(void * ctx,const xmlChar * ch,int len)28527 charactersSplit(void *ctx, const xmlChar *ch, int len)
28528 {
28529     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28530     if (ctxt == NULL)
28531         return;
28532     if ((ctxt->user_sax != NULL) && (ctxt->user_sax->characters != NULL))
28533 	ctxt->user_sax->characters(ctxt->user_data, ch, len);
28534     if (ctxt->ctxt != NULL)
28535 	xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
28536 }
28537 
28538 static void
ignorableWhitespaceSplit(void * ctx,const xmlChar * ch,int len)28539 ignorableWhitespaceSplit(void *ctx, const xmlChar *ch, int len)
28540 {
28541     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28542     if (ctxt == NULL)
28543         return;
28544     if ((ctxt->user_sax != NULL) &&
28545         (ctxt->user_sax->ignorableWhitespace != NULL))
28546 	ctxt->user_sax->ignorableWhitespace(ctxt->user_data, ch, len);
28547     if (ctxt->ctxt != NULL)
28548 	xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
28549 }
28550 
28551 static void
cdataBlockSplit(void * ctx,const xmlChar * value,int len)28552 cdataBlockSplit(void *ctx, const xmlChar *value, int len)
28553 {
28554     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28555     if (ctxt == NULL)
28556         return;
28557     if ((ctxt->user_sax != NULL) &&
28558         (ctxt->user_sax->cdataBlock != NULL))
28559 	ctxt->user_sax->cdataBlock(ctxt->user_data, value, len);
28560     if (ctxt->ctxt != NULL)
28561 	xmlSchemaSAXHandleCDataSection(ctxt->ctxt, value, len);
28562 }
28563 
28564 static void
referenceSplit(void * ctx,const xmlChar * name)28565 referenceSplit(void *ctx, const xmlChar *name)
28566 {
28567     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28568     if (ctxt == NULL)
28569         return;
28570     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28571         (ctxt->user_sax->reference != NULL))
28572 	ctxt->user_sax->reference(ctxt->user_data, name);
28573     if (ctxt->ctxt != NULL)
28574         xmlSchemaSAXHandleReference(ctxt->user_data, name);
28575 }
28576 
28577 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)28578 startElementNsSplit(void *ctx, const xmlChar * localname,
28579 		    const xmlChar * prefix, const xmlChar * URI,
28580 		    int nb_namespaces, const xmlChar ** namespaces,
28581 		    int nb_attributes, int nb_defaulted,
28582 		    const xmlChar ** attributes) {
28583     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28584     if (ctxt == NULL)
28585         return;
28586     if ((ctxt->user_sax != NULL) &&
28587         (ctxt->user_sax->startElementNs != NULL))
28588 	ctxt->user_sax->startElementNs(ctxt->user_data, localname, prefix,
28589 	                               URI, nb_namespaces, namespaces,
28590 				       nb_attributes, nb_defaulted,
28591 				       attributes);
28592     if (ctxt->ctxt != NULL)
28593 	xmlSchemaSAXHandleStartElementNs(ctxt->ctxt, localname, prefix,
28594 	                                 URI, nb_namespaces, namespaces,
28595 					 nb_attributes, nb_defaulted,
28596 					 attributes);
28597 }
28598 
28599 static void
endElementNsSplit(void * ctx,const xmlChar * localname,const xmlChar * prefix,const xmlChar * URI)28600 endElementNsSplit(void *ctx, const xmlChar * localname,
28601 		    const xmlChar * prefix, const xmlChar * URI) {
28602     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28603     if (ctxt == NULL)
28604         return;
28605     if ((ctxt->user_sax != NULL) &&
28606         (ctxt->user_sax->endElementNs != NULL))
28607 	ctxt->user_sax->endElementNs(ctxt->user_data, localname, prefix, URI);
28608     if (ctxt->ctxt != NULL)
28609 	xmlSchemaSAXHandleEndElementNs(ctxt->ctxt, localname, prefix, URI);
28610 }
28611 
28612 /**
28613  * xmlSchemaSAXPlug:
28614  * @ctxt:  a schema validation context
28615  * @sax:  a pointer to the original xmlSAXHandlerPtr
28616  * @user_data:  a pointer to the original SAX user data pointer
28617  *
28618  * Plug a SAX based validation layer in a SAX parsing event flow.
28619  * The original @saxptr and @dataptr data are replaced by new pointers
28620  * but the calls to the original will be maintained.
28621  *
28622  * Returns a pointer to a data structure needed to unplug the validation layer
28623  *         or NULL in case of errors.
28624  */
28625 xmlSchemaSAXPlugPtr
xmlSchemaSAXPlug(xmlSchemaValidCtxtPtr ctxt,xmlSAXHandlerPtr * sax,void ** user_data)28626 xmlSchemaSAXPlug(xmlSchemaValidCtxtPtr ctxt,
28627 		 xmlSAXHandlerPtr *sax, void **user_data)
28628 {
28629     xmlSchemaSAXPlugPtr ret;
28630     xmlSAXHandlerPtr old_sax;
28631 
28632     if ((ctxt == NULL) || (sax == NULL) || (user_data == NULL))
28633         return(NULL);
28634 
28635     /*
28636      * We only allow to plug into SAX2 event streams
28637      */
28638     old_sax = *sax;
28639     if ((old_sax != NULL) && (old_sax->initialized != XML_SAX2_MAGIC))
28640         return(NULL);
28641     if ((old_sax != NULL) &&
28642         (old_sax->startElementNs == NULL) && (old_sax->endElementNs == NULL) &&
28643         ((old_sax->startElement != NULL) || (old_sax->endElement != NULL)))
28644         return(NULL);
28645 
28646     /*
28647      * everything seems right allocate the local data needed for that layer
28648      */
28649     ret = (xmlSchemaSAXPlugPtr) xmlMalloc(sizeof(xmlSchemaSAXPlugStruct));
28650     if (ret == NULL) {
28651         return(NULL);
28652     }
28653     memset(ret, 0, sizeof(xmlSchemaSAXPlugStruct));
28654     ret->magic = XML_SAX_PLUG_MAGIC;
28655     ret->schemas_sax.initialized = XML_SAX2_MAGIC;
28656     ret->ctxt = ctxt;
28657     ret->user_sax_ptr = sax;
28658     ret->user_sax = old_sax;
28659     if (old_sax == NULL) {
28660         /*
28661 	 * go direct, no need for the split block and functions.
28662 	 */
28663 	ret->schemas_sax.startElementNs = xmlSchemaSAXHandleStartElementNs;
28664 	ret->schemas_sax.endElementNs = xmlSchemaSAXHandleEndElementNs;
28665 	/*
28666 	 * Note that we use the same text-function for both, to prevent
28667 	 * the parser from testing for ignorable whitespace.
28668 	 */
28669 	ret->schemas_sax.ignorableWhitespace = xmlSchemaSAXHandleText;
28670 	ret->schemas_sax.characters = xmlSchemaSAXHandleText;
28671 
28672 	ret->schemas_sax.cdataBlock = xmlSchemaSAXHandleCDataSection;
28673 	ret->schemas_sax.reference = xmlSchemaSAXHandleReference;
28674 
28675 	ret->user_data = ctxt;
28676 	*user_data = ctxt;
28677     } else {
28678        /*
28679         * for each callback unused by Schemas initialize it to the Split
28680 	* routine only if non NULL in the user block, this can speed up
28681 	* things at the SAX level.
28682 	*/
28683         if (old_sax->internalSubset != NULL)
28684             ret->schemas_sax.internalSubset = internalSubsetSplit;
28685         if (old_sax->isStandalone != NULL)
28686             ret->schemas_sax.isStandalone = isStandaloneSplit;
28687         if (old_sax->hasInternalSubset != NULL)
28688             ret->schemas_sax.hasInternalSubset = hasInternalSubsetSplit;
28689         if (old_sax->hasExternalSubset != NULL)
28690             ret->schemas_sax.hasExternalSubset = hasExternalSubsetSplit;
28691         if (old_sax->resolveEntity != NULL)
28692             ret->schemas_sax.resolveEntity = resolveEntitySplit;
28693         if (old_sax->getEntity != NULL)
28694             ret->schemas_sax.getEntity = getEntitySplit;
28695         if (old_sax->entityDecl != NULL)
28696             ret->schemas_sax.entityDecl = entityDeclSplit;
28697         if (old_sax->notationDecl != NULL)
28698             ret->schemas_sax.notationDecl = notationDeclSplit;
28699         if (old_sax->attributeDecl != NULL)
28700             ret->schemas_sax.attributeDecl = attributeDeclSplit;
28701         if (old_sax->elementDecl != NULL)
28702             ret->schemas_sax.elementDecl = elementDeclSplit;
28703         if (old_sax->unparsedEntityDecl != NULL)
28704             ret->schemas_sax.unparsedEntityDecl = unparsedEntityDeclSplit;
28705         if (old_sax->setDocumentLocator != NULL)
28706             ret->schemas_sax.setDocumentLocator = setDocumentLocatorSplit;
28707         if (old_sax->startDocument != NULL)
28708             ret->schemas_sax.startDocument = startDocumentSplit;
28709         if (old_sax->endDocument != NULL)
28710             ret->schemas_sax.endDocument = endDocumentSplit;
28711         if (old_sax->processingInstruction != NULL)
28712             ret->schemas_sax.processingInstruction = processingInstructionSplit;
28713         if (old_sax->comment != NULL)
28714             ret->schemas_sax.comment = commentSplit;
28715         if (old_sax->warning != NULL)
28716             ret->schemas_sax.warning = warningSplit;
28717         if (old_sax->error != NULL)
28718             ret->schemas_sax.error = errorSplit;
28719         if (old_sax->fatalError != NULL)
28720             ret->schemas_sax.fatalError = fatalErrorSplit;
28721         if (old_sax->getParameterEntity != NULL)
28722             ret->schemas_sax.getParameterEntity = getParameterEntitySplit;
28723         if (old_sax->externalSubset != NULL)
28724             ret->schemas_sax.externalSubset = externalSubsetSplit;
28725 
28726 	/*
28727 	 * the 6 schemas callback have to go to the splitter functions
28728 	 * Note that we use the same text-function for ignorableWhitespace
28729 	 * if possible, to prevent the parser from testing for ignorable
28730 	 * whitespace.
28731 	 */
28732         ret->schemas_sax.characters = charactersSplit;
28733 	if ((old_sax->ignorableWhitespace != NULL) &&
28734 	    (old_sax->ignorableWhitespace != old_sax->characters))
28735 	    ret->schemas_sax.ignorableWhitespace = ignorableWhitespaceSplit;
28736 	else
28737 	    ret->schemas_sax.ignorableWhitespace = charactersSplit;
28738         ret->schemas_sax.cdataBlock = cdataBlockSplit;
28739         ret->schemas_sax.reference = referenceSplit;
28740         ret->schemas_sax.startElementNs = startElementNsSplit;
28741         ret->schemas_sax.endElementNs = endElementNsSplit;
28742 
28743 	ret->user_data_ptr = user_data;
28744 	ret->user_data = *user_data;
28745 	*user_data = ret;
28746     }
28747 
28748     /*
28749      * plug the pointers back.
28750      */
28751     *sax = &(ret->schemas_sax);
28752     ctxt->sax = *sax;
28753     ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28754     xmlSchemaPreRun(ctxt);
28755     return(ret);
28756 }
28757 
28758 /**
28759  * xmlSchemaSAXUnplug:
28760  * @plug:  a data structure returned by xmlSchemaSAXPlug
28761  *
28762  * Unplug a SAX based validation layer in a SAX parsing event flow.
28763  * The original pointers used in the call are restored.
28764  *
28765  * Returns 0 in case of success and -1 in case of failure.
28766  */
28767 int
xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug)28768 xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug)
28769 {
28770     xmlSAXHandlerPtr *sax;
28771     void **user_data;
28772 
28773     if ((plug == NULL) || (plug->magic != XML_SAX_PLUG_MAGIC))
28774         return(-1);
28775     plug->magic = 0;
28776 
28777     xmlSchemaPostRun(plug->ctxt);
28778     /* restore the data */
28779     sax = plug->user_sax_ptr;
28780     *sax = plug->user_sax;
28781     if (plug->user_sax != NULL) {
28782 	user_data = plug->user_data_ptr;
28783 	*user_data = plug->user_data;
28784     }
28785 
28786     /* free and return */
28787     xmlFree(plug);
28788     return(0);
28789 }
28790 
28791 /**
28792  * xmlSchemaValidateSetLocator:
28793  * @vctxt: a schema validation context
28794  * @f: the locator function pointer
28795  * @ctxt: the locator context
28796  *
28797  * Allows to set a locator function to the validation context,
28798  * which will be used to provide file and line information since
28799  * those are not provided as part of the SAX validation flow
28800  * Setting @f to NULL disable the locator.
28801  */
28802 
28803 void
xmlSchemaValidateSetLocator(xmlSchemaValidCtxtPtr vctxt,xmlSchemaValidityLocatorFunc f,void * ctxt)28804 xmlSchemaValidateSetLocator(xmlSchemaValidCtxtPtr vctxt,
28805                             xmlSchemaValidityLocatorFunc f,
28806 			    void *ctxt)
28807 {
28808     if (vctxt == NULL) return;
28809     vctxt->locFunc = f;
28810     vctxt->locCtxt = ctxt;
28811 }
28812 
28813 /**
28814  * xmlSchemaValidateStreamLocator:
28815  * @ctx: the xmlTextReaderPtr used
28816  * @file: returned file information
28817  * @line: returned line information
28818  *
28819  * Internal locator function for the readers
28820  *
28821  * Returns 0 in case the Schema validation could be (des)activated and
28822  *         -1 in case of error.
28823  */
28824 static int
xmlSchemaValidateStreamLocator(void * ctx,const char ** file,unsigned long * line)28825 xmlSchemaValidateStreamLocator(void *ctx, const char **file,
28826                                unsigned long *line) {
28827     xmlParserCtxtPtr ctxt;
28828 
28829     if ((ctx == NULL) || ((file == NULL) && (line == NULL)))
28830         return(-1);
28831 
28832     if (file != NULL)
28833         *file = NULL;
28834     if (line != NULL)
28835         *line = 0;
28836 
28837     ctxt = (xmlParserCtxtPtr) ctx;
28838     if (ctxt->input != NULL) {
28839        if (file != NULL)
28840            *file = ctxt->input->filename;
28841        if (line != NULL)
28842            *line = ctxt->input->line;
28843        return(0);
28844     }
28845     return(-1);
28846 }
28847 
28848 /**
28849  * xmlSchemaValidateStream:
28850  * @ctxt:  a schema validation context
28851  * @input:  the input to use for reading the data
28852  * @enc:  an optional encoding information
28853  * @sax:  a SAX handler for the resulting events
28854  * @user_data:  the context to provide to the SAX handler.
28855  *
28856  * Validate an input based on a flow of SAX event from the parser
28857  * and forward the events to the @sax handler with the provided @user_data
28858  * the user provided @sax handler must be a SAX2 one.
28859  *
28860  * Returns 0 if the document is schemas valid, a positive error code
28861  *     number otherwise and -1 in case of internal or API error.
28862  */
28863 int
xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,xmlParserInputBufferPtr input,xmlCharEncoding enc,xmlSAXHandlerPtr sax,void * user_data)28864 xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
28865                         xmlParserInputBufferPtr input, xmlCharEncoding enc,
28866                         xmlSAXHandlerPtr sax, void *user_data)
28867 {
28868     xmlSchemaSAXPlugPtr plug = NULL;
28869     xmlSAXHandlerPtr old_sax = NULL;
28870     xmlParserCtxtPtr pctxt = NULL;
28871     xmlParserInputPtr inputStream = NULL;
28872     int ret;
28873 
28874     if ((ctxt == NULL) || (input == NULL))
28875         return (-1);
28876 
28877     /*
28878      * prepare the parser
28879      */
28880     pctxt = xmlNewParserCtxt();
28881     if (pctxt == NULL)
28882         return (-1);
28883     old_sax = pctxt->sax;
28884     pctxt->sax = sax;
28885     pctxt->userData = user_data;
28886 #if 0
28887     if (options)
28888         xmlCtxtUseOptions(pctxt, options);
28889 #endif
28890     pctxt->linenumbers = 1;
28891     xmlSchemaValidateSetLocator(ctxt, xmlSchemaValidateStreamLocator, pctxt);
28892 
28893     inputStream = xmlNewIOInputStream(pctxt, input, enc);;
28894     if (inputStream == NULL) {
28895         ret = -1;
28896 	goto done;
28897     }
28898     inputPush(pctxt, inputStream);
28899     ctxt->parserCtxt = pctxt;
28900     ctxt->input = input;
28901 
28902     /*
28903      * Plug the validation and launch the parsing
28904      */
28905     plug = xmlSchemaSAXPlug(ctxt, &(pctxt->sax), &(pctxt->userData));
28906     if (plug == NULL) {
28907         ret = -1;
28908 	goto done;
28909     }
28910     ctxt->input = input;
28911     ctxt->enc = enc;
28912     ctxt->sax = pctxt->sax;
28913     ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28914     ret = xmlSchemaVStart(ctxt);
28915 
28916     if ((ret == 0) && (! ctxt->parserCtxt->wellFormed)) {
28917 	ret = ctxt->parserCtxt->errNo;
28918 	if (ret == 0)
28919 	    ret = 1;
28920     }
28921 
28922 done:
28923     ctxt->parserCtxt = NULL;
28924     ctxt->sax = NULL;
28925     ctxt->input = NULL;
28926     if (plug != NULL) {
28927         xmlSchemaSAXUnplug(plug);
28928     }
28929     /* cleanup */
28930     if (pctxt != NULL) {
28931 	pctxt->sax = old_sax;
28932 	xmlFreeParserCtxt(pctxt);
28933     }
28934     return (ret);
28935 }
28936 
28937 /**
28938  * xmlSchemaValidateFile:
28939  * @ctxt: a schema validation context
28940  * @filename: the URI of the instance
28941  * @options: a future set of options, currently unused
28942  *
28943  * Do a schemas validation of the given resource, it will use the
28944  * SAX streamable validation internally.
28945  *
28946  * Returns 0 if the document is valid, a positive error code
28947  *     number otherwise and -1 in case of an internal or API error.
28948  */
28949 int
xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt,const char * filename,int options ATTRIBUTE_UNUSED)28950 xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt,
28951                       const char * filename,
28952 		      int options ATTRIBUTE_UNUSED)
28953 {
28954     int ret;
28955     xmlParserInputBufferPtr input;
28956 
28957     if ((ctxt == NULL) || (filename == NULL))
28958         return (-1);
28959 
28960     input = xmlParserInputBufferCreateFilename(filename,
28961 	XML_CHAR_ENCODING_NONE);
28962     if (input == NULL)
28963 	return (-1);
28964     ret = xmlSchemaValidateStream(ctxt, input, XML_CHAR_ENCODING_NONE,
28965 	NULL, NULL);
28966     return (ret);
28967 }
28968 
28969 /**
28970  * xmlSchemaValidCtxtGetParserCtxt:
28971  * @ctxt: a schema validation context
28972  *
28973  * allow access to the parser context of the schema validation context
28974  *
28975  * Returns the parser context of the schema validation context or NULL
28976  *         in case of error.
28977  */
28978 xmlParserCtxtPtr
xmlSchemaValidCtxtGetParserCtxt(xmlSchemaValidCtxtPtr ctxt)28979 xmlSchemaValidCtxtGetParserCtxt(xmlSchemaValidCtxtPtr ctxt)
28980 {
28981     if (ctxt == NULL)
28982         return(NULL);
28983     return (ctxt->parserCtxt);
28984 }
28985 
28986 #define bottom_xmlschemas
28987 #include "elfgcchack.h"
28988 #endif /* LIBXML_SCHEMAS_ENABLED */
28989