xref: /aosp_15_r20/external/libxml2/xmlschemas.c (revision 7c5688314b92172186c154356a6374bf7684c3ca)
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 <[email protected]>
8  */
9 
10 /*
11  * TODO:
12  *   - when types are redefined in includes, check that all
13  *     types in the redef list are equal
14  *     -> need a type equality operation.
15  *   - if we don't intend to use the schema for schemas, we
16  *     need to validate all schema attributes (ref, type, name)
17  *     against their types.
18  *   - Eliminate item creation for: ??
19  *
20  * URGENT TODO:
21  *   - For xsi-driven schema acquisition, augment the IDCs after every
22  *     acquisition episode (xmlSchemaAugmentIDC).
23  *
24  * NOTES:
25  *   - Eliminated item creation for: <restriction>, <extension>,
26  *     <simpleContent>, <complexContent>, <list>, <union>
27  *
28  * PROBLEMS:
29  *   - http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0337.html
30  *     IDC XPath expression and chameleon includes: the targetNamespace is changed, so
31  *     XPath will have trouble to resolve to this namespace, since not known.
32  *
33  *
34  * CONSTRAINTS:
35  *
36  * Schema Component Constraint:
37  *   All Group Limited (cos-all-limited)
38  *   Status: complete
39  *   (1.2)
40  *     In xmlSchemaGroupDefReferenceTermFixup() and
41  *   (2)
42  *     In xmlSchemaParseModelGroup()
43  *     TODO: Actually this should go to component-level checks,
44  *     but is done here due to performance. Move it to an other layer
45  *     is schema construction via an API is implemented.
46  */
47 
48 /* To avoid EBCDIC trouble when parsing on zOS */
49 #if defined(__MVS__)
50 #pragma convert("ISO8859-1")
51 #endif
52 
53 #define IN_LIBXML
54 #include "libxml.h"
55 
56 #ifdef LIBXML_SCHEMAS_ENABLED
57 
58 #include <string.h>
59 #include <libxml/xmlmemory.h>
60 #include <libxml/parser.h>
61 #include <libxml/parserInternals.h>
62 #include <libxml/hash.h>
63 #include <libxml/uri.h>
64 #include <libxml/xmlschemas.h>
65 #include <libxml/schemasInternals.h>
66 #include <libxml/xmlschemastypes.h>
67 #include <libxml/xmlautomata.h>
68 #include <libxml/xmlregexp.h>
69 #include <libxml/dict.h>
70 #include <libxml/encoding.h>
71 #include <libxml/xmlIO.h>
72 #ifdef LIBXML_PATTERN_ENABLED
73 #include <libxml/pattern.h>
74 #endif
75 #ifdef LIBXML_READER_ENABLED
76 #include <libxml/xmlreader.h>
77 #endif
78 
79 #include "private/error.h"
80 #include "private/string.h"
81 
82 /* #define WXS_ELEM_DECL_CONS_ENABLED */
83 
84 /* #define ENABLE_PARTICLE_RESTRICTION 1 */
85 
86 #define ENABLE_REDEFINE
87 
88 /* #define ENABLE_NAMED_LOCALS */
89 
90 /* #define ENABLE_IDC_NODE_TABLES_TEST */
91 
92 #define DUMP_CONTENT_MODEL
93 
94 #ifdef LIBXML_READER_ENABLED
95 /* #define XML_SCHEMA_READER_ENABLED */
96 #endif
97 
98 #define UNBOUNDED (1 << 30)
99 
100 #define XML_SCHEMAS_NO_NAMESPACE (const xmlChar *) "##"
101 
102 /*
103  * The XML Schemas namespaces
104  */
105 static const xmlChar *xmlSchemaNs = (const xmlChar *)
106     "http://www.w3.org/2001/XMLSchema";
107 
108 static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
109     "http://www.w3.org/2001/XMLSchema-instance";
110 
111 static const xmlChar *xmlNamespaceNs = (const xmlChar *)
112     "http://www.w3.org/2000/xmlns/";
113 
114 /*
115 * Come casting macros.
116 */
117 #define ACTXT_CAST (xmlSchemaAbstractCtxtPtr)
118 #define PCTXT_CAST (xmlSchemaParserCtxtPtr)
119 #define VCTXT_CAST (xmlSchemaValidCtxtPtr)
120 #define WXS_BASIC_CAST (xmlSchemaBasicItemPtr)
121 #define WXS_TREE_CAST (xmlSchemaTreeItemPtr)
122 #define WXS_PTC_CAST (xmlSchemaParticlePtr)
123 #define WXS_TYPE_CAST (xmlSchemaTypePtr)
124 #define WXS_ELEM_CAST (xmlSchemaElementPtr)
125 #define WXS_ATTR_GROUP_CAST (xmlSchemaAttributeGroupPtr)
126 #define WXS_ATTR_CAST (xmlSchemaAttributePtr)
127 #define WXS_ATTR_USE_CAST (xmlSchemaAttributeUsePtr)
128 #define WXS_ATTR_PROHIB_CAST (xmlSchemaAttributeUseProhibPtr)
129 #define WXS_MODEL_GROUPDEF_CAST (xmlSchemaModelGroupDefPtr)
130 #define WXS_MODEL_GROUP_CAST (xmlSchemaModelGroupPtr)
131 #define WXS_IDC_CAST (xmlSchemaIDCPtr)
132 #define WXS_QNAME_CAST (xmlSchemaQNameRefPtr)
133 #define WXS_LIST_CAST (xmlSchemaItemListPtr)
134 
135 /*
136 * Macros to query common properties of components.
137 */
138 #define WXS_ITEM_NODE(i) xmlSchemaGetComponentNode(WXS_BASIC_CAST (i))
139 
140 #define WXS_ITEM_TYPE_NAME(i) xmlSchemaGetComponentTypeStr(WXS_BASIC_CAST (i))
141 /*
142 * Macros for element declarations.
143 */
144 #define WXS_ELEM_TYPEDEF(e) (e)->subtypes
145 
146 #define WXS_SUBST_HEAD(item) (item)->refDecl
147 /*
148 * Macros for attribute declarations.
149 */
150 #define WXS_ATTR_TYPEDEF(a) (a)->subtypes
151 /*
152 * Macros for attribute uses.
153 */
154 #define WXS_ATTRUSE_DECL(au) (WXS_ATTR_USE_CAST (au))->attrDecl
155 
156 #define WXS_ATTRUSE_TYPEDEF(au) WXS_ATTR_TYPEDEF(WXS_ATTRUSE_DECL( WXS_ATTR_USE_CAST au))
157 
158 #define WXS_ATTRUSE_DECL_NAME(au) (WXS_ATTRUSE_DECL(au))->name
159 
160 #define WXS_ATTRUSE_DECL_TNS(au) (WXS_ATTRUSE_DECL(au))->targetNamespace
161 /*
162 * Macros for attribute groups.
163 */
164 #define WXS_ATTR_GROUP_HAS_REFS(ag) ((WXS_ATTR_GROUP_CAST (ag))->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS)
165 #define WXS_ATTR_GROUP_EXPANDED(ag) ((WXS_ATTR_GROUP_CAST (ag))->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED)
166 /*
167 * Macros for particles.
168 */
169 #define WXS_PARTICLE(p) WXS_PTC_CAST (p)
170 
171 #define WXS_PARTICLE_TERM(p) (WXS_PARTICLE(p))->children
172 
173 #define WXS_PARTICLE_TERM_AS_ELEM(p) (WXS_ELEM_CAST WXS_PARTICLE_TERM(p))
174 
175 #define WXS_PARTICLE_MODEL(p) WXS_MODEL_GROUP_CAST WXS_PARTICLE(p)->children
176 /*
177 * Macros for model groups definitions.
178 */
179 #define WXS_MODELGROUPDEF_MODEL(mgd) (WXS_MODEL_GROUP_CAST (mgd))->children
180 /*
181 * Macros for model groups.
182 */
183 #define WXS_IS_MODEL_GROUP(i) \
184     (((i)->type == XML_SCHEMA_TYPE_SEQUENCE) || \
185      ((i)->type == XML_SCHEMA_TYPE_CHOICE) || \
186      ((i)->type == XML_SCHEMA_TYPE_ALL))
187 
188 #define WXS_MODELGROUP_PARTICLE(mg) WXS_PTC_CAST (mg)->children
189 /*
190 * Macros for schema buckets.
191 */
192 #define WXS_IS_BUCKET_INCREDEF(t) (((t) == XML_SCHEMA_SCHEMA_INCLUDE) || \
193     ((t) == XML_SCHEMA_SCHEMA_REDEFINE))
194 
195 #define WXS_IS_BUCKET_IMPMAIN(t) (((t) == XML_SCHEMA_SCHEMA_MAIN) || \
196     ((t) == XML_SCHEMA_SCHEMA_IMPORT))
197 
198 #define WXS_IMPBUCKET(b) ((xmlSchemaImportPtr) (b))
199 
200 #define WXS_INCBUCKET(b) ((xmlSchemaIncludePtr) (b))
201 /*
202 * Macros for complex/simple types.
203 */
204 #define WXS_IS_ANYTYPE(i) \
205      (( (i)->type == XML_SCHEMA_TYPE_BASIC) && \
206       ( (WXS_TYPE_CAST (i))->builtInType == XML_SCHEMAS_ANYTYPE))
207 
208 #define WXS_IS_COMPLEX(i) \
209     (((i)->type == XML_SCHEMA_TYPE_COMPLEX) || \
210      ((i)->builtInType == XML_SCHEMAS_ANYTYPE))
211 
212 #define WXS_IS_SIMPLE(item) \
213     ((item->type == XML_SCHEMA_TYPE_SIMPLE) || \
214      ((item->type == XML_SCHEMA_TYPE_BASIC) && \
215       (item->builtInType != XML_SCHEMAS_ANYTYPE)))
216 
217 #define WXS_IS_ANY_SIMPLE_TYPE(i) \
218     (((i)->type == XML_SCHEMA_TYPE_BASIC) && \
219       ((i)->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
220 
221 #define WXS_IS_RESTRICTION(t) \
222     ((t)->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)
223 
224 #define WXS_IS_EXTENSION(t) \
225     ((t)->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)
226 
227 #define WXS_IS_TYPE_NOT_FIXED(i) \
228     (((i)->type != XML_SCHEMA_TYPE_BASIC) && \
229      (((i)->flags & XML_SCHEMAS_TYPE_INTERNAL_RESOLVED) == 0))
230 
231 #define WXS_IS_TYPE_NOT_FIXED_1(item) \
232     (((item)->type != XML_SCHEMA_TYPE_BASIC) && \
233      (((item)->flags & XML_SCHEMAS_TYPE_FIXUP_1) == 0))
234 
235 #define WXS_TYPE_IS_GLOBAL(t) ((t)->flags & XML_SCHEMAS_TYPE_GLOBAL)
236 
237 #define WXS_TYPE_IS_LOCAL(t) (((t)->flags & XML_SCHEMAS_TYPE_GLOBAL) == 0)
238 /*
239 * Macros for exclusively for complex types.
240 */
241 #define WXS_HAS_COMPLEX_CONTENT(item) \
242     ((item->contentType == XML_SCHEMA_CONTENT_MIXED) || \
243      (item->contentType == XML_SCHEMA_CONTENT_EMPTY) || \
244      (item->contentType == XML_SCHEMA_CONTENT_ELEMENTS))
245 
246 #define WXS_HAS_SIMPLE_CONTENT(item) \
247     ((item->contentType == XML_SCHEMA_CONTENT_SIMPLE) || \
248      (item->contentType == XML_SCHEMA_CONTENT_BASIC))
249 
250 #define WXS_HAS_MIXED_CONTENT(item) \
251     (item->contentType == XML_SCHEMA_CONTENT_MIXED)
252 
253 #define WXS_EMPTIABLE(t) \
254     (xmlSchemaIsParticleEmptiable(WXS_PTC_CAST (t)->subtypes))
255 
256 #define WXS_TYPE_CONTENTTYPE(t) (t)->subtypes
257 
258 #define WXS_TYPE_PARTICLE(t) WXS_PTC_CAST (t)->subtypes
259 
260 #define WXS_TYPE_PARTICLE_TERM(t) WXS_PARTICLE_TERM(WXS_TYPE_PARTICLE(t))
261 /*
262 * Macros for exclusively for simple types.
263 */
264 #define WXS_LIST_ITEMTYPE(t) (t)->subtypes
265 
266 #define WXS_IS_ATOMIC(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
267 
268 #define WXS_IS_LIST(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
269 
270 #define WXS_IS_UNION(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)
271 /*
272 * Misc parser context macros.
273 */
274 #define WXS_CONSTRUCTOR(ctx) (ctx)->constructor
275 
276 #define WXS_HAS_BUCKETS(ctx) \
277 ( (WXS_CONSTRUCTOR((ctx))->buckets != NULL) && \
278 (WXS_CONSTRUCTOR((ctx))->buckets->nbItems > 0) )
279 
280 #define WXS_SUBST_GROUPS(ctx) WXS_CONSTRUCTOR((ctx))->substGroups
281 
282 #define WXS_BUCKET(ctx) WXS_CONSTRUCTOR((ctx))->bucket
283 
284 #define WXS_SCHEMA(ctx) (ctx)->schema
285 
286 #define WXS_ADD_LOCAL(ctx, item) \
287     do { \
288         if (xmlSchemaAddItemSize(&(WXS_BUCKET(ctx)->locals), 10, item) < 0) { \
289             xmlFree(item); \
290             item = NULL; \
291         } \
292     } while (0)
293 
294 #define WXS_ADD_GLOBAL(ctx, item) \
295     do { \
296         if (xmlSchemaAddItemSize(&(WXS_BUCKET(ctx)->globals), 5, item) < 0) { \
297             xmlFree(item); \
298             item = NULL; \
299         } \
300     } while (0)
301 
302 #define WXS_ADD_PENDING(ctx, item) \
303     xmlSchemaAddItemSize(&((ctx)->constructor->pending), 10, item)
304 /*
305 * xmlSchemaItemList macros.
306 */
307 #define WXS_ILIST_IS_EMPTY(l) ((l == NULL) || ((l)->nbItems == 0))
308 /*
309 * Misc macros.
310 */
311 #define IS_SCHEMA(node, type) \
312    ((node != NULL) && (node->ns != NULL) && \
313     (xmlStrEqual(node->name, (const xmlChar *) type)) && \
314     (xmlStrEqual(node->ns->href, xmlSchemaNs)))
315 
316 #define FREE_AND_NULL(str) if ((str) != NULL) { xmlFree((xmlChar *) (str)); str = NULL; }
317 
318 /*
319 * Since we put the default/fixed values into the dict, we can
320 * use pointer comparison for those values.
321 * REMOVED: (xmlStrEqual((v1), (v2)))
322 */
323 #define WXS_ARE_DEFAULT_STR_EQUAL(v1, v2) ((v1) == (v2))
324 
325 #define INODE_NILLED(item) (item->flags & XML_SCHEMA_ELEM_INFO_NILLED)
326 
327 #define CAN_PARSE_SCHEMA(b) (((b)->doc != NULL) && ((b)->parsed == 0))
328 
329 #define HFAILURE if (res == -1) goto exit_failure;
330 
331 #define HERROR if (res != 0) goto exit_error;
332 
333 #define HSTOP(ctx) if ((ctx)->stop) goto exit;
334 /*
335 * Some flags used for various schema constraints.
336 */
337 #define SUBSET_RESTRICTION  1<<0
338 #define SUBSET_EXTENSION    1<<1
339 #define SUBSET_SUBSTITUTION 1<<2
340 #define SUBSET_LIST         1<<3
341 #define SUBSET_UNION        1<<4
342 
343 typedef struct _xmlSchemaNodeInfo xmlSchemaNodeInfo;
344 typedef xmlSchemaNodeInfo *xmlSchemaNodeInfoPtr;
345 
346 typedef struct _xmlSchemaItemList xmlSchemaItemList;
347 typedef xmlSchemaItemList *xmlSchemaItemListPtr;
348 struct _xmlSchemaItemList {
349     void **items;  /* used for dynamic addition of schemata */
350     int nbItems; /* used for dynamic addition of schemata */
351     int sizeItems; /* used for dynamic addition of schemata */
352 };
353 
354 #define XML_SCHEMA_CTXT_PARSER 1
355 #define XML_SCHEMA_CTXT_VALIDATOR 2
356 
357 typedef struct _xmlSchemaAbstractCtxt xmlSchemaAbstractCtxt;
358 typedef xmlSchemaAbstractCtxt *xmlSchemaAbstractCtxtPtr;
359 struct _xmlSchemaAbstractCtxt {
360     int type; /* E.g. XML_SCHEMA_CTXT_VALIDATOR */
361     void *dummy; /* Fix alignment issues */
362 };
363 
364 typedef struct _xmlSchemaBucket xmlSchemaBucket;
365 typedef xmlSchemaBucket *xmlSchemaBucketPtr;
366 
367 #define XML_SCHEMA_SCHEMA_MAIN 0
368 #define XML_SCHEMA_SCHEMA_IMPORT 1
369 #define XML_SCHEMA_SCHEMA_INCLUDE 2
370 #define XML_SCHEMA_SCHEMA_REDEFINE 3
371 
372 /**
373  * xmlSchemaSchemaRelation:
374  *
375  * Used to create a graph of schema relationships.
376  */
377 typedef struct _xmlSchemaSchemaRelation xmlSchemaSchemaRelation;
378 typedef xmlSchemaSchemaRelation *xmlSchemaSchemaRelationPtr;
379 struct _xmlSchemaSchemaRelation {
380     xmlSchemaSchemaRelationPtr next;
381     int type; /* E.g. XML_SCHEMA_SCHEMA_IMPORT */
382     const xmlChar *importNamespace;
383     xmlSchemaBucketPtr bucket;
384 };
385 
386 #define XML_SCHEMA_BUCKET_MARKED 1<<0
387 #define XML_SCHEMA_BUCKET_COMPS_ADDED 1<<1
388 
389 struct _xmlSchemaBucket {
390     int type;
391     int flags;
392     const xmlChar *schemaLocation;
393     const xmlChar *origTargetNamespace;
394     const xmlChar *targetNamespace;
395     xmlDocPtr doc;
396     xmlSchemaSchemaRelationPtr relations;
397     int located;
398     int parsed;
399     int imported;
400     int preserveDoc;
401     xmlSchemaItemListPtr globals; /* Global components. */
402     xmlSchemaItemListPtr locals; /* Local components. */
403 };
404 
405 /**
406  * xmlSchemaImport:
407  * (extends xmlSchemaBucket)
408  *
409  * Reflects a schema. Holds some information
410  * about the schema and its toplevel components. Duplicate
411  * toplevel components are not checked at this level.
412  */
413 typedef struct _xmlSchemaImport xmlSchemaImport;
414 typedef xmlSchemaImport *xmlSchemaImportPtr;
415 struct _xmlSchemaImport {
416     int type; /* Main OR import OR include. */
417     int flags;
418     const xmlChar *schemaLocation; /* The URI of the schema document. */
419     /* For chameleon includes, @origTargetNamespace will be NULL */
420     const xmlChar *origTargetNamespace;
421     /*
422     * For chameleon includes, @targetNamespace will be the
423     * targetNamespace of the including schema.
424     */
425     const xmlChar *targetNamespace;
426     xmlDocPtr doc; /* The schema node-tree. */
427     /* @relations will hold any included/imported/redefined schemas. */
428     xmlSchemaSchemaRelationPtr relations;
429     int located;
430     int parsed;
431     int imported;
432     int preserveDoc;
433     xmlSchemaItemListPtr globals;
434     xmlSchemaItemListPtr locals;
435     /* The imported schema. */
436     xmlSchemaPtr schema;
437 };
438 
439 /*
440 * (extends xmlSchemaBucket)
441 */
442 typedef struct _xmlSchemaInclude xmlSchemaInclude;
443 typedef xmlSchemaInclude *xmlSchemaIncludePtr;
444 struct _xmlSchemaInclude {
445     int type;
446     int flags;
447     const xmlChar *schemaLocation;
448     const xmlChar *origTargetNamespace;
449     const xmlChar *targetNamespace;
450     xmlDocPtr doc;
451     xmlSchemaSchemaRelationPtr relations;
452     int located;
453     int parsed;
454     int imported;
455     int preserveDoc;
456     xmlSchemaItemListPtr globals; /* Global components. */
457     xmlSchemaItemListPtr locals; /* Local components. */
458 
459     /* The owning main or import schema bucket. */
460     xmlSchemaImportPtr ownerImport;
461 };
462 
463 /**
464  * xmlSchemaBasicItem:
465  *
466  * The abstract base type for schema components.
467  */
468 typedef struct _xmlSchemaBasicItem xmlSchemaBasicItem;
469 typedef xmlSchemaBasicItem *xmlSchemaBasicItemPtr;
470 struct _xmlSchemaBasicItem {
471     xmlSchemaTypeType type;
472     void *dummy; /* Fix alignment issues */
473 };
474 
475 /**
476  * xmlSchemaAnnotItem:
477  *
478  * The abstract base type for annotated schema components.
479  * (Extends xmlSchemaBasicItem)
480  */
481 typedef struct _xmlSchemaAnnotItem xmlSchemaAnnotItem;
482 typedef xmlSchemaAnnotItem *xmlSchemaAnnotItemPtr;
483 struct _xmlSchemaAnnotItem {
484     xmlSchemaTypeType type;
485     xmlSchemaAnnotPtr annot;
486 };
487 
488 /**
489  * xmlSchemaTreeItem:
490  *
491  * The abstract base type for tree-like structured schema components.
492  * (Extends xmlSchemaAnnotItem)
493  */
494 typedef struct _xmlSchemaTreeItem xmlSchemaTreeItem;
495 typedef xmlSchemaTreeItem *xmlSchemaTreeItemPtr;
496 struct _xmlSchemaTreeItem {
497     xmlSchemaTypeType type;
498     xmlSchemaAnnotPtr annot;
499     xmlSchemaTreeItemPtr next;
500     xmlSchemaTreeItemPtr children;
501 };
502 
503 
504 #define XML_SCHEMA_ATTR_USE_FIXED 1<<0
505 /**
506  * xmlSchemaAttributeUsePtr:
507  *
508  * The abstract base type for tree-like structured schema components.
509  * (Extends xmlSchemaTreeItem)
510  */
511 typedef struct _xmlSchemaAttributeUse xmlSchemaAttributeUse;
512 typedef xmlSchemaAttributeUse *xmlSchemaAttributeUsePtr;
513 struct _xmlSchemaAttributeUse {
514     xmlSchemaTypeType type;
515     xmlSchemaAnnotPtr annot;
516     xmlSchemaAttributeUsePtr next; /* The next attr. use. */
517     /*
518     * The attr. decl. OR a QName-ref. to an attr. decl. OR
519     * a QName-ref. to an attribute group definition.
520     */
521     xmlSchemaAttributePtr attrDecl;
522 
523     int flags;
524     xmlNodePtr node;
525     int occurs; /* required, optional */
526     const xmlChar * defValue;
527     xmlSchemaValPtr defVal;
528 };
529 
530 /**
531  * xmlSchemaAttributeUseProhibPtr:
532  *
533  * A helper component to reflect attribute prohibitions.
534  * (Extends xmlSchemaBasicItem)
535  */
536 typedef struct _xmlSchemaAttributeUseProhib xmlSchemaAttributeUseProhib;
537 typedef xmlSchemaAttributeUseProhib *xmlSchemaAttributeUseProhibPtr;
538 struct _xmlSchemaAttributeUseProhib {
539     xmlSchemaTypeType type; /* == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB */
540     xmlNodePtr node;
541     const xmlChar *name;
542     const xmlChar *targetNamespace;
543     int isRef;
544 };
545 
546 /**
547  * xmlSchemaRedef:
548  */
549 typedef struct _xmlSchemaRedef xmlSchemaRedef;
550 typedef xmlSchemaRedef *xmlSchemaRedefPtr;
551 struct _xmlSchemaRedef {
552     xmlSchemaRedefPtr next;
553     xmlSchemaBasicItemPtr item; /* The redefining component. */
554     xmlSchemaBasicItemPtr reference; /* The referencing component. */
555     xmlSchemaBasicItemPtr target; /* The to-be-redefined component. */
556     const xmlChar *refName; /* The name of the to-be-redefined component. */
557     const xmlChar *refTargetNs; /* The target namespace of the
558                                    to-be-redefined comp. */
559     xmlSchemaBucketPtr targetBucket; /* The redefined schema. */
560 };
561 
562 /**
563  * xmlSchemaConstructionCtxt:
564  */
565 typedef struct _xmlSchemaConstructionCtxt xmlSchemaConstructionCtxt;
566 typedef xmlSchemaConstructionCtxt *xmlSchemaConstructionCtxtPtr;
567 struct _xmlSchemaConstructionCtxt {
568     xmlSchemaPtr mainSchema; /* The main schema. */
569     xmlSchemaBucketPtr mainBucket; /* The main schema bucket */
570     xmlDictPtr dict;
571     xmlSchemaItemListPtr buckets; /* List of schema buckets. */
572     /* xmlSchemaItemListPtr relations; */ /* List of schema relations. */
573     xmlSchemaBucketPtr bucket; /* The current schema bucket */
574     xmlSchemaItemListPtr pending; /* All Components of all schemas that
575                                      need to be fixed. */
576     xmlHashTablePtr substGroups;
577     xmlSchemaRedefPtr redefs;
578     xmlSchemaRedefPtr lastRedef;
579 };
580 
581 #define XML_SCHEMAS_PARSE_ERROR		1
582 #define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
583 
584 struct _xmlSchemaParserCtxt {
585     int type;
586     void *errCtxt;             /* user specific error context */
587     xmlSchemaValidityErrorFunc error;   /* the callback in case of errors */
588     xmlSchemaValidityWarningFunc warning;       /* the callback in case of warning */
589     int err;
590     int nberrors;
591     xmlStructuredErrorFunc serror;
592 
593     xmlSchemaConstructionCtxtPtr constructor;
594     int ownsConstructor; /* TODO: Move this to parser *flags*. */
595 
596     /* xmlSchemaPtr topschema;	*/
597     /* xmlHashTablePtr namespaces;  */
598 
599     xmlSchemaPtr schema;        /* The main schema in use */
600     int counter;
601 
602     const xmlChar *URL;
603     xmlDocPtr doc;
604     int preserve;		/* Whether the doc should be freed  */
605 
606     const char *buffer;
607     int size;
608 
609     /*
610      * Used to build complex element content models
611      */
612     xmlAutomataPtr am;
613     xmlAutomataStatePtr start;
614     xmlAutomataStatePtr end;
615     xmlAutomataStatePtr state;
616 
617     xmlDictPtr dict;		/* dictionary for interned string names */
618     xmlSchemaTypePtr ctxtType; /* The current context simple/complex type */
619     int options;
620     xmlSchemaValidCtxtPtr vctxt;
621     int isS4S;
622     int isRedefine;
623     int xsiAssemble;
624     int stop; /* If the parser should stop; i.e. a critical error. */
625     const xmlChar *targetNamespace;
626     xmlSchemaBucketPtr redefined; /* The schema to be redefined. */
627 
628     xmlSchemaRedefPtr redef; /* Used for redefinitions. */
629     int redefCounter; /* Used for redefinitions. */
630     xmlSchemaItemListPtr attrProhibs;
631 
632     xmlResourceLoader resourceLoader;
633     void *resourceCtxt;
634 };
635 
636 /**
637  * xmlSchemaQNameRef:
638  *
639  * A component reference item (not a schema component)
640  * (Extends xmlSchemaBasicItem)
641  */
642 typedef struct _xmlSchemaQNameRef xmlSchemaQNameRef;
643 typedef xmlSchemaQNameRef *xmlSchemaQNameRefPtr;
644 struct _xmlSchemaQNameRef {
645     xmlSchemaTypeType type;
646     xmlSchemaBasicItemPtr item; /* The resolved referenced item. */
647     xmlSchemaTypeType itemType;
648     const xmlChar *name;
649     const xmlChar *targetNamespace;
650     xmlNodePtr node;
651 };
652 
653 /**
654  * xmlSchemaParticle:
655  *
656  * A particle component.
657  * (Extends xmlSchemaTreeItem)
658  */
659 typedef struct _xmlSchemaParticle xmlSchemaParticle;
660 typedef xmlSchemaParticle *xmlSchemaParticlePtr;
661 struct _xmlSchemaParticle {
662     xmlSchemaTypeType type;
663     xmlSchemaAnnotPtr annot;
664     xmlSchemaTreeItemPtr next; /* next particle */
665     xmlSchemaTreeItemPtr children; /* the "term" (e.g. a model group,
666 	a group definition, a XML_SCHEMA_EXTRA_QNAMEREF (if a reference),
667         etc.) */
668     int minOccurs;
669     int maxOccurs;
670     xmlNodePtr node;
671 };
672 
673 /**
674  * xmlSchemaModelGroup:
675  *
676  * A model group component.
677  * (Extends xmlSchemaTreeItem)
678  */
679 typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
680 typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
681 struct _xmlSchemaModelGroup {
682     xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_SEQUENCE, XML_SCHEMA_TYPE_CHOICE, XML_SCHEMA_TYPE_ALL */
683     xmlSchemaAnnotPtr annot;
684     xmlSchemaTreeItemPtr next; /* not used */
685     xmlSchemaTreeItemPtr children; /* first particle (OR "element decl" OR "wildcard") */
686     xmlNodePtr node;
687 };
688 
689 #define XML_SCHEMA_MODEL_GROUP_DEF_MARKED 1<<0
690 #define XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED 1<<1
691 /**
692  * xmlSchemaModelGroupDef:
693  *
694  * A model group definition component.
695  * (Extends xmlSchemaTreeItem)
696  */
697 typedef struct _xmlSchemaModelGroupDef xmlSchemaModelGroupDef;
698 typedef xmlSchemaModelGroupDef *xmlSchemaModelGroupDefPtr;
699 struct _xmlSchemaModelGroupDef {
700     xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_GROUP */
701     xmlSchemaAnnotPtr annot;
702     xmlSchemaTreeItemPtr next; /* not used */
703     xmlSchemaTreeItemPtr children; /* the "model group" */
704     const xmlChar *name;
705     const xmlChar *targetNamespace;
706     xmlNodePtr node;
707     int flags;
708 };
709 
710 typedef struct _xmlSchemaIDC xmlSchemaIDC;
711 typedef xmlSchemaIDC *xmlSchemaIDCPtr;
712 
713 /**
714  * xmlSchemaIDCSelect:
715  *
716  * The identity-constraint "field" and "selector" item, holding the
717  * XPath expression.
718  */
719 typedef struct _xmlSchemaIDCSelect xmlSchemaIDCSelect;
720 typedef xmlSchemaIDCSelect *xmlSchemaIDCSelectPtr;
721 struct _xmlSchemaIDCSelect {
722     xmlSchemaIDCSelectPtr next;
723     xmlSchemaIDCPtr idc;
724     int index; /* an index position if significant for IDC key-sequences */
725     const xmlChar *xpath; /* the XPath expression */
726     void *xpathComp; /* the compiled XPath expression */
727 };
728 
729 /**
730  * xmlSchemaIDC:
731  *
732  * The identity-constraint definition component.
733  * (Extends xmlSchemaAnnotItem)
734  */
735 
736 struct _xmlSchemaIDC {
737     xmlSchemaTypeType type;
738     xmlSchemaAnnotPtr annot;
739     xmlSchemaIDCPtr next;
740     xmlNodePtr node;
741     const xmlChar *name;
742     const xmlChar *targetNamespace;
743     xmlSchemaIDCSelectPtr selector;
744     xmlSchemaIDCSelectPtr fields;
745     int nbFields;
746     xmlSchemaQNameRefPtr ref;
747 };
748 
749 /**
750  * xmlSchemaIDCAug:
751  *
752  * The augmented IDC information used for validation.
753  */
754 typedef struct _xmlSchemaIDCAug xmlSchemaIDCAug;
755 typedef xmlSchemaIDCAug *xmlSchemaIDCAugPtr;
756 struct _xmlSchemaIDCAug {
757     xmlSchemaIDCAugPtr next; /* next in a list */
758     xmlSchemaIDCPtr def; /* the IDC definition */
759     int keyrefDepth; /* the lowest tree level to which IDC
760                         tables need to be bubbled upwards */
761 };
762 
763 /**
764  * xmlSchemaPSVIIDCKeySequence:
765  *
766  * The key sequence of a node table item.
767  */
768 typedef struct _xmlSchemaPSVIIDCKey xmlSchemaPSVIIDCKey;
769 typedef xmlSchemaPSVIIDCKey *xmlSchemaPSVIIDCKeyPtr;
770 struct _xmlSchemaPSVIIDCKey {
771     xmlSchemaTypePtr type;
772     xmlSchemaValPtr val;
773 };
774 
775 /**
776  * xmlSchemaPSVIIDCNode:
777  *
778  * The node table item of a node table.
779  */
780 typedef struct _xmlSchemaPSVIIDCNode xmlSchemaPSVIIDCNode;
781 typedef xmlSchemaPSVIIDCNode *xmlSchemaPSVIIDCNodePtr;
782 struct _xmlSchemaPSVIIDCNode {
783     xmlNodePtr node;
784     xmlSchemaPSVIIDCKeyPtr *keys;
785     int nodeLine;
786     int nodeQNameID;
787 
788 };
789 
790 /**
791  * xmlSchemaPSVIIDCBinding:
792  *
793  * The identity-constraint binding item of the [identity-constraint table].
794  */
795 typedef struct _xmlSchemaPSVIIDCBinding xmlSchemaPSVIIDCBinding;
796 typedef xmlSchemaPSVIIDCBinding *xmlSchemaPSVIIDCBindingPtr;
797 struct _xmlSchemaPSVIIDCBinding {
798     xmlSchemaPSVIIDCBindingPtr next; /* next binding of a specific node */
799     xmlSchemaIDCPtr definition; /* the IDC definition */
800     xmlSchemaPSVIIDCNodePtr *nodeTable; /* array of key-sequences */
801     int nbNodes; /* number of entries in the node table */
802     int sizeNodes; /* size of the node table */
803     xmlSchemaItemListPtr dupls;
804 };
805 
806 
807 #define XPATH_STATE_OBJ_TYPE_IDC_SELECTOR 1
808 #define XPATH_STATE_OBJ_TYPE_IDC_FIELD 2
809 
810 #define XPATH_STATE_OBJ_MATCHES -2
811 #define XPATH_STATE_OBJ_BLOCKED -3
812 
813 typedef struct _xmlSchemaIDCMatcher xmlSchemaIDCMatcher;
814 typedef xmlSchemaIDCMatcher *xmlSchemaIDCMatcherPtr;
815 
816 /**
817  * xmlSchemaIDCStateObj:
818  *
819  * The state object used to evaluate XPath expressions.
820  */
821 typedef struct _xmlSchemaIDCStateObj xmlSchemaIDCStateObj;
822 typedef xmlSchemaIDCStateObj *xmlSchemaIDCStateObjPtr;
823 struct _xmlSchemaIDCStateObj {
824     int type;
825     xmlSchemaIDCStateObjPtr next; /* next if in a list */
826     int depth; /* depth of creation */
827     int *history; /* list of (depth, state-id) tuples */
828     int nbHistory;
829     int sizeHistory;
830     xmlSchemaIDCMatcherPtr matcher; /* the correspondent field/selector
831                                        matcher */
832     xmlSchemaIDCSelectPtr sel;
833     void *xpathCtxt;
834 };
835 
836 #define IDC_MATCHER 0
837 
838 /**
839  * xmlSchemaIDCMatcher:
840  *
841  * Used to evaluate IDC selectors (and fields).
842  */
843 struct _xmlSchemaIDCMatcher {
844     int type;
845     int depth; /* the tree depth at creation time */
846     xmlSchemaIDCMatcherPtr next; /* next in the list */
847     xmlSchemaIDCMatcherPtr nextCached; /* next in the cache list */
848     xmlSchemaIDCAugPtr aidc; /* the augmented IDC item */
849     int idcType;
850     xmlSchemaPSVIIDCKeyPtr **keySeqs; /* the key-sequences of the target
851                                          elements */
852     int sizeKeySeqs;
853     xmlSchemaItemListPtr targets; /* list of target-node
854                                      (xmlSchemaPSVIIDCNodePtr) entries */
855     xmlHashTablePtr htab;
856 };
857 
858 /*
859 * Element info flags.
860 */
861 #define XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES  1<<0
862 #define XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES 1<<1
863 #define XML_SCHEMA_ELEM_INFO_NILLED	       1<<2
864 #define XML_SCHEMA_ELEM_INFO_LOCAL_TYPE	       1<<3
865 
866 #define XML_SCHEMA_NODE_INFO_VALUE_NEEDED      1<<4
867 #define XML_SCHEMA_ELEM_INFO_EMPTY             1<<5
868 #define XML_SCHEMA_ELEM_INFO_HAS_CONTENT       1<<6
869 
870 #define XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT  1<<7
871 #define XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT  1<<8
872 #define XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED  1<<9
873 #define XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE  1<<10
874 
875 /**
876  * xmlSchemaNodeInfo:
877  *
878  * Holds information of an element node.
879  */
880 struct _xmlSchemaNodeInfo {
881     int nodeType;
882     xmlNodePtr node;
883     int nodeLine;
884     const xmlChar *localName;
885     const xmlChar *nsName;
886     const xmlChar *value;
887     xmlSchemaValPtr val; /* the pre-computed value if any */
888     xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
889 
890     int flags; /* combination of node info flags */
891 
892     int valNeeded;
893     int normVal;
894 
895     xmlSchemaElementPtr decl; /* the element/attribute declaration */
896     int depth;
897     xmlSchemaPSVIIDCBindingPtr idcTable; /* the table of PSVI IDC bindings
898                                             for the scope element*/
899     xmlSchemaIDCMatcherPtr idcMatchers; /* the IDC matchers for the scope
900                                            element */
901     xmlRegExecCtxtPtr regexCtxt;
902 
903     const xmlChar **nsBindings; /* Namespace bindings on this element */
904     int nbNsBindings;
905     int sizeNsBindings;
906 
907     int hasKeyrefs;
908     int appliedXPath; /* Indicates that an XPath has been applied. */
909 };
910 
911 #define XML_SCHEMAS_ATTR_UNKNOWN 1
912 #define XML_SCHEMAS_ATTR_ASSESSED 2
913 #define XML_SCHEMAS_ATTR_PROHIBITED 3
914 #define XML_SCHEMAS_ATTR_ERR_MISSING 4
915 #define XML_SCHEMAS_ATTR_INVALID_VALUE 5
916 #define XML_SCHEMAS_ATTR_ERR_NO_TYPE 6
917 #define XML_SCHEMAS_ATTR_ERR_FIXED_VALUE 7
918 #define XML_SCHEMAS_ATTR_DEFAULT 8
919 #define XML_SCHEMAS_ATTR_VALIDATE_VALUE 9
920 #define XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL 10
921 #define XML_SCHEMAS_ATTR_HAS_ATTR_USE 11
922 #define XML_SCHEMAS_ATTR_HAS_ATTR_DECL 12
923 #define XML_SCHEMAS_ATTR_WILD_SKIP 13
924 #define XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL 14
925 #define XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID 15
926 #define XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID 16
927 #define XML_SCHEMAS_ATTR_META 17
928 /*
929 * @metaType values of xmlSchemaAttrInfo.
930 */
931 #define XML_SCHEMA_ATTR_INFO_META_XSI_TYPE 1
932 #define XML_SCHEMA_ATTR_INFO_META_XSI_NIL 2
933 #define XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC 3
934 #define XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC 4
935 #define XML_SCHEMA_ATTR_INFO_META_XMLNS 5
936 
937 typedef struct _xmlSchemaAttrInfo xmlSchemaAttrInfo;
938 typedef xmlSchemaAttrInfo *xmlSchemaAttrInfoPtr;
939 struct _xmlSchemaAttrInfo {
940     int nodeType;
941     xmlNodePtr node;
942     int nodeLine;
943     const xmlChar *localName;
944     const xmlChar *nsName;
945     const xmlChar *value;
946     xmlSchemaValPtr val; /* the pre-computed value if any */
947     xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
948     int flags; /* combination of node info flags */
949 
950     xmlSchemaAttributePtr decl; /* the attribute declaration */
951     xmlSchemaAttributeUsePtr use;  /* the attribute use */
952     int state;
953     int metaType;
954     const xmlChar *vcValue; /* the value constraint value */
955     xmlSchemaNodeInfoPtr parent;
956 };
957 
958 
959 #define XML_SCHEMA_VALID_CTXT_FLAG_STREAM 1
960 /**
961  * xmlSchemaValidCtxt:
962  *
963  * A Schemas validation context
964  */
965 struct _xmlSchemaValidCtxt {
966     int type;
967     void *errCtxt;             /* user specific data block */
968     xmlSchemaValidityErrorFunc error;   /* the callback in case of errors */
969     xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
970     xmlStructuredErrorFunc serror;
971 
972     xmlSchemaPtr schema;        /* The schema in use */
973     xmlDocPtr doc;
974     xmlParserInputBufferPtr input;
975     xmlCharEncoding enc;
976     xmlSAXHandlerPtr sax;
977     xmlParserCtxtPtr parserCtxt;
978     void *user_data; /* TODO: What is this for? */
979     char *filename;
980 
981     int err;
982     int nberrors;
983 
984     xmlNodePtr node;
985     xmlNodePtr cur;
986     /* xmlSchemaTypePtr type; */
987 
988     xmlRegExecCtxtPtr regexp;
989     xmlSchemaValPtr value;
990 
991     int valueWS;
992     int options;
993     xmlNodePtr validationRoot;
994     xmlSchemaParserCtxtPtr pctxt;
995     int xsiAssemble;
996 
997     int depth;
998     xmlSchemaNodeInfoPtr *elemInfos; /* array of element information */
999     int sizeElemInfos;
1000     xmlSchemaNodeInfoPtr inode; /* the current element information */
1001 
1002     xmlSchemaIDCAugPtr aidcs; /* a list of augmented IDC information */
1003 
1004     xmlSchemaIDCStateObjPtr xpathStates; /* first active state object. */
1005     xmlSchemaIDCStateObjPtr xpathStatePool; /* first stored state object. */
1006     xmlSchemaIDCMatcherPtr idcMatcherCache; /* Cache for IDC matcher objects. */
1007 
1008     xmlSchemaPSVIIDCNodePtr *idcNodes; /* list of all IDC node-table entries*/
1009     int nbIdcNodes;
1010     int sizeIdcNodes;
1011 
1012     xmlSchemaPSVIIDCKeyPtr *idcKeys; /* list of all IDC node-table entries */
1013     int nbIdcKeys;
1014     int sizeIdcKeys;
1015 
1016     int flags;
1017 
1018     xmlDictPtr dict;
1019 
1020 #ifdef LIBXML_READER_ENABLED
1021     xmlTextReaderPtr reader;
1022 #endif
1023 
1024     xmlSchemaAttrInfoPtr *attrInfos;
1025     int nbAttrInfos;
1026     int sizeAttrInfos;
1027 
1028     int skipDepth;
1029     xmlSchemaItemListPtr nodeQNames;
1030     int hasKeyrefs;
1031     int createIDCNodeTables;
1032     int psviExposeIDCNodeTables;
1033 
1034     /* Locator for error reporting in streaming mode */
1035     xmlSchemaValidityLocatorFunc locFunc;
1036     void *locCtxt;
1037 };
1038 
1039 /**
1040  * xmlSchemaSubstGroup:
1041  *
1042  *
1043  */
1044 typedef struct _xmlSchemaSubstGroup xmlSchemaSubstGroup;
1045 typedef xmlSchemaSubstGroup *xmlSchemaSubstGroupPtr;
1046 struct _xmlSchemaSubstGroup {
1047     xmlSchemaElementPtr head;
1048     xmlSchemaItemListPtr members;
1049 };
1050 
1051 /**
1052  * xmlIDCHashEntry:
1053  *
1054  * an entry in hash tables to quickly look up keys/uniques
1055  */
1056 typedef struct _xmlIDCHashEntry xmlIDCHashEntry;
1057 typedef xmlIDCHashEntry *xmlIDCHashEntryPtr;
1058 struct _xmlIDCHashEntry {
1059     xmlIDCHashEntryPtr next; /* next item with same hash */
1060     int index;               /* index into associated item list */
1061 };
1062 
1063 /************************************************************************
1064  *									*
1065  *			Some predeclarations				*
1066  *									*
1067  ************************************************************************/
1068 
1069 static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
1070                                  xmlSchemaPtr schema,
1071                                  xmlNodePtr node);
1072 static int xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr ctxt,
1073                                  xmlSchemaPtr schema,
1074                                  xmlNodePtr node);
1075 static int
1076 xmlSchemaTypeFixup(xmlSchemaTypePtr type,
1077                    xmlSchemaAbstractCtxtPtr ctxt);
1078 static const xmlChar *
1079 xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
1080 static int
1081 xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1082                      xmlNodePtr node);
1083 static int
1084 xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
1085                        xmlSchemaParserCtxtPtr ctxt);
1086 static void
1087 xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt);
1088 static xmlSchemaWhitespaceValueType
1089 xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type);
1090 static xmlSchemaTreeItemPtr
1091 xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1092 			 xmlNodePtr node, xmlSchemaTypeType type,
1093 			 int withParticle);
1094 static const xmlChar *
1095 xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item);
1096 static xmlSchemaTypeLinkPtr
1097 xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type);
1098 static void
1099 xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
1100 		     const char *funcName,
1101 		     const char *message) LIBXML_ATTR_FORMAT(3,0);
1102 static int
1103 xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr ctxt,
1104 			     xmlSchemaTypePtr type,
1105 			     xmlSchemaTypePtr baseType,
1106 			     int subset);
1107 static void
1108 xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
1109 				   xmlSchemaParserCtxtPtr ctxt);
1110 static void
1111 xmlSchemaComponentListFree(xmlSchemaItemListPtr list);
1112 static xmlSchemaQNameRefPtr
1113 xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,
1114 				xmlSchemaPtr schema,
1115 				xmlNodePtr node);
1116 
1117 /************************************************************************
1118  *									*
1119  *			Helper functions			        *
1120  *									*
1121  ************************************************************************/
1122 
1123 /**
1124  * xmlSchemaItemTypeToStr:
1125  * @type: the type of the schema item
1126  *
1127  * Returns the component name of a schema item.
1128  */
1129 static const xmlChar *
xmlSchemaItemTypeToStr(xmlSchemaTypeType type)1130 xmlSchemaItemTypeToStr(xmlSchemaTypeType type)
1131 {
1132     switch (type) {
1133 	case XML_SCHEMA_TYPE_BASIC:
1134 	    return(BAD_CAST "simple type definition");
1135 	case XML_SCHEMA_TYPE_SIMPLE:
1136 	    return(BAD_CAST "simple type definition");
1137 	case XML_SCHEMA_TYPE_COMPLEX:
1138 	    return(BAD_CAST "complex type definition");
1139 	case XML_SCHEMA_TYPE_ELEMENT:
1140 	    return(BAD_CAST "element declaration");
1141 	case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1142 	    return(BAD_CAST "attribute use");
1143 	case XML_SCHEMA_TYPE_ATTRIBUTE:
1144 	    return(BAD_CAST "attribute declaration");
1145 	case XML_SCHEMA_TYPE_GROUP:
1146 	    return(BAD_CAST "model group definition");
1147 	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1148 	    return(BAD_CAST "attribute group definition");
1149 	case XML_SCHEMA_TYPE_NOTATION:
1150 	    return(BAD_CAST "notation declaration");
1151 	case XML_SCHEMA_TYPE_SEQUENCE:
1152 	    return(BAD_CAST "model group (sequence)");
1153 	case XML_SCHEMA_TYPE_CHOICE:
1154 	    return(BAD_CAST "model group (choice)");
1155 	case XML_SCHEMA_TYPE_ALL:
1156 	    return(BAD_CAST "model group (all)");
1157 	case XML_SCHEMA_TYPE_PARTICLE:
1158 	    return(BAD_CAST "particle");
1159 	case XML_SCHEMA_TYPE_IDC_UNIQUE:
1160 	    return(BAD_CAST "unique identity-constraint");
1161 	    /* return(BAD_CAST "IDC (unique)"); */
1162 	case XML_SCHEMA_TYPE_IDC_KEY:
1163 	    return(BAD_CAST "key identity-constraint");
1164 	    /* return(BAD_CAST "IDC (key)"); */
1165 	case XML_SCHEMA_TYPE_IDC_KEYREF:
1166 	    return(BAD_CAST "keyref identity-constraint");
1167 	    /* return(BAD_CAST "IDC (keyref)"); */
1168 	case XML_SCHEMA_TYPE_ANY:
1169 	    return(BAD_CAST "wildcard (any)");
1170 	case XML_SCHEMA_EXTRA_QNAMEREF:
1171 	    return(BAD_CAST "[helper component] QName reference");
1172 	case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
1173 	    return(BAD_CAST "[helper component] attribute use prohibition");
1174 	default:
1175 	    return(BAD_CAST "Not a schema component");
1176     }
1177 }
1178 
1179 /**
1180  * xmlSchemaGetComponentTypeStr:
1181  * @type: the type of the schema item
1182  *
1183  * Returns the component name of a schema item.
1184  */
1185 static const xmlChar *
xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item)1186 xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item)
1187 {
1188     switch (item->type) {
1189 	case XML_SCHEMA_TYPE_BASIC:
1190 	    if (WXS_IS_COMPLEX(WXS_TYPE_CAST item))
1191 		return(BAD_CAST "complex type definition");
1192 	    else
1193 		return(BAD_CAST "simple type definition");
1194 	default:
1195 	    return(xmlSchemaItemTypeToStr(item->type));
1196     }
1197 }
1198 
1199 /**
1200  * xmlSchemaGetComponentNode:
1201  * @item: a schema component
1202  *
1203  * Returns node associated with the schema component.
1204  * NOTE that such a node need not be available; plus, a component's
1205  * node need not to reflect the component directly, since there is no
1206  * one-to-one relationship between the XML Schema representation and
1207  * the component representation.
1208  */
1209 static xmlNodePtr
xmlSchemaGetComponentNode(xmlSchemaBasicItemPtr item)1210 xmlSchemaGetComponentNode(xmlSchemaBasicItemPtr item)
1211 {
1212     switch (item->type) {
1213 	case XML_SCHEMA_TYPE_ELEMENT:
1214 	    return (((xmlSchemaElementPtr) item)->node);
1215 	case XML_SCHEMA_TYPE_ATTRIBUTE:
1216 	    return (((xmlSchemaAttributePtr) item)->node);
1217 	case XML_SCHEMA_TYPE_COMPLEX:
1218 	case XML_SCHEMA_TYPE_SIMPLE:
1219 	    return (((xmlSchemaTypePtr) item)->node);
1220 	case XML_SCHEMA_TYPE_ANY:
1221 	case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1222 	    return (((xmlSchemaWildcardPtr) item)->node);
1223 	case XML_SCHEMA_TYPE_PARTICLE:
1224 	    return (((xmlSchemaParticlePtr) item)->node);
1225 	case XML_SCHEMA_TYPE_SEQUENCE:
1226 	case XML_SCHEMA_TYPE_CHOICE:
1227 	case XML_SCHEMA_TYPE_ALL:
1228 	    return (((xmlSchemaModelGroupPtr) item)->node);
1229 	case XML_SCHEMA_TYPE_GROUP:
1230 	    return (((xmlSchemaModelGroupDefPtr) item)->node);
1231 	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1232 	    return (((xmlSchemaAttributeGroupPtr) item)->node);
1233 	case XML_SCHEMA_TYPE_IDC_UNIQUE:
1234 	case XML_SCHEMA_TYPE_IDC_KEY:
1235 	case XML_SCHEMA_TYPE_IDC_KEYREF:
1236 	    return (((xmlSchemaIDCPtr) item)->node);
1237 	case XML_SCHEMA_EXTRA_QNAMEREF:
1238 	    return(((xmlSchemaQNameRefPtr) item)->node);
1239 	/* TODO: What to do with NOTATIONs?
1240 	case XML_SCHEMA_TYPE_NOTATION:
1241 	    return (((xmlSchemaNotationPtr) item)->node);
1242 	*/
1243 	case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1244 	    return (((xmlSchemaAttributeUsePtr) item)->node);
1245 	default:
1246 	    return (NULL);
1247     }
1248 }
1249 
1250 #if 0
1251 /**
1252  * xmlSchemaGetNextComponent:
1253  * @item: a schema component
1254  *
1255  * Returns the next sibling of the schema component.
1256  */
1257 static xmlSchemaBasicItemPtr
1258 xmlSchemaGetNextComponent(xmlSchemaBasicItemPtr item)
1259 {
1260     switch (item->type) {
1261 	case XML_SCHEMA_TYPE_ELEMENT:
1262 	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaElementPtr) item)->next);
1263 	case XML_SCHEMA_TYPE_ATTRIBUTE:
1264 	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributePtr) item)->next);
1265 	case XML_SCHEMA_TYPE_COMPLEX:
1266 	case XML_SCHEMA_TYPE_SIMPLE:
1267 	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaTypePtr) item)->next);
1268 	case XML_SCHEMA_TYPE_ANY:
1269 	case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1270 	    return (NULL);
1271 	case XML_SCHEMA_TYPE_PARTICLE:
1272 	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaParticlePtr) item)->next);
1273 	case XML_SCHEMA_TYPE_SEQUENCE:
1274 	case XML_SCHEMA_TYPE_CHOICE:
1275 	case XML_SCHEMA_TYPE_ALL:
1276 	    return (NULL);
1277 	case XML_SCHEMA_TYPE_GROUP:
1278 	    return (NULL);
1279 	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1280 	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributeGroupPtr) item)->next);
1281 	case XML_SCHEMA_TYPE_IDC_UNIQUE:
1282 	case XML_SCHEMA_TYPE_IDC_KEY:
1283 	case XML_SCHEMA_TYPE_IDC_KEYREF:
1284 	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaIDCPtr) item)->next);
1285 	default:
1286 	    return (NULL);
1287     }
1288 }
1289 #endif
1290 
1291 
1292 /**
1293  * xmlSchemaFormatQName:
1294  * @buf: the string buffer
1295  * @namespaceName:  the namespace name
1296  * @localName: the local name
1297  *
1298  * Returns the given QName in the format "{namespaceName}localName" or
1299  * just "localName" if @namespaceName is NULL.
1300  *
1301  * Returns the localName if @namespaceName is NULL, a formatted
1302  * string otherwise.
1303  */
1304 static const xmlChar*
xmlSchemaFormatQName(xmlChar ** buf,const xmlChar * namespaceName,const xmlChar * localName)1305 xmlSchemaFormatQName(xmlChar **buf,
1306 		     const xmlChar *namespaceName,
1307 		     const xmlChar *localName)
1308 {
1309     FREE_AND_NULL(*buf)
1310     if (namespaceName != NULL) {
1311 	*buf = xmlStrdup(BAD_CAST "{");
1312 	*buf = xmlStrcat(*buf, namespaceName);
1313 	*buf = xmlStrcat(*buf, BAD_CAST "}");
1314     }
1315     if (localName != NULL) {
1316 	if (namespaceName == NULL)
1317 	    return(localName);
1318 	*buf = xmlStrcat(*buf, localName);
1319     } else {
1320 	*buf = xmlStrcat(*buf, BAD_CAST "(NULL)");
1321     }
1322     return ((const xmlChar *) *buf);
1323 }
1324 
1325 static const xmlChar*
xmlSchemaFormatQNameNs(xmlChar ** buf,xmlNsPtr ns,const xmlChar * localName)1326 xmlSchemaFormatQNameNs(xmlChar **buf, xmlNsPtr ns, const xmlChar *localName)
1327 {
1328     if (ns != NULL)
1329 	return (xmlSchemaFormatQName(buf, ns->href, localName));
1330     else
1331 	return (xmlSchemaFormatQName(buf, NULL, localName));
1332 }
1333 
1334 static const xmlChar *
xmlSchemaGetComponentName(xmlSchemaBasicItemPtr item)1335 xmlSchemaGetComponentName(xmlSchemaBasicItemPtr item)
1336 {
1337     if (item == NULL) {
1338         return (NULL);
1339     }
1340     switch (item->type) {
1341 	case XML_SCHEMA_TYPE_ELEMENT:
1342 	    return (((xmlSchemaElementPtr) item)->name);
1343 	case XML_SCHEMA_TYPE_ATTRIBUTE:
1344 	    return (((xmlSchemaAttributePtr) item)->name);
1345 	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1346 	    return (((xmlSchemaAttributeGroupPtr) item)->name);
1347 	case XML_SCHEMA_TYPE_BASIC:
1348 	case XML_SCHEMA_TYPE_SIMPLE:
1349 	case XML_SCHEMA_TYPE_COMPLEX:
1350 	    return (((xmlSchemaTypePtr) item)->name);
1351 	case XML_SCHEMA_TYPE_GROUP:
1352 	    return (((xmlSchemaModelGroupDefPtr) item)->name);
1353 	case XML_SCHEMA_TYPE_IDC_KEY:
1354 	case XML_SCHEMA_TYPE_IDC_UNIQUE:
1355 	case XML_SCHEMA_TYPE_IDC_KEYREF:
1356 	    return (((xmlSchemaIDCPtr) item)->name);
1357 	case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1358 	    if (WXS_ATTRUSE_DECL(item) != NULL) {
1359 		return(xmlSchemaGetComponentName(
1360 		    WXS_BASIC_CAST WXS_ATTRUSE_DECL(item)));
1361 	    } else
1362 		return(NULL);
1363 	case XML_SCHEMA_EXTRA_QNAMEREF:
1364 	    return (((xmlSchemaQNameRefPtr) item)->name);
1365 	case XML_SCHEMA_TYPE_NOTATION:
1366 	    return (((xmlSchemaNotationPtr) item)->name);
1367 	default:
1368 	    /*
1369 	    * Other components cannot have names.
1370 	    */
1371 	    break;
1372     }
1373     return (NULL);
1374 }
1375 
1376 #define xmlSchemaGetQNameRefName(r) (WXS_QNAME_CAST (r))->name
1377 #define xmlSchemaGetQNameRefTargetNs(r) (WXS_QNAME_CAST (r))->targetNamespace
1378 /*
1379 static const xmlChar *
1380 xmlSchemaGetQNameRefName(void *ref)
1381 {
1382     return(((xmlSchemaQNameRefPtr) ref)->name);
1383 }
1384 
1385 static const xmlChar *
1386 xmlSchemaGetQNameRefTargetNs(void *ref)
1387 {
1388     return(((xmlSchemaQNameRefPtr) ref)->targetNamespace);
1389 }
1390 */
1391 
1392 static const xmlChar *
xmlSchemaGetComponentTargetNs(xmlSchemaBasicItemPtr item)1393 xmlSchemaGetComponentTargetNs(xmlSchemaBasicItemPtr item)
1394 {
1395     if (item == NULL) {
1396         return (NULL);
1397     }
1398     switch (item->type) {
1399 	case XML_SCHEMA_TYPE_ELEMENT:
1400 	    return (((xmlSchemaElementPtr) item)->targetNamespace);
1401 	case XML_SCHEMA_TYPE_ATTRIBUTE:
1402 	    return (((xmlSchemaAttributePtr) item)->targetNamespace);
1403 	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1404 	    return (((xmlSchemaAttributeGroupPtr) item)->targetNamespace);
1405 	case XML_SCHEMA_TYPE_BASIC:
1406 	    return (BAD_CAST "http://www.w3.org/2001/XMLSchema");
1407 	case XML_SCHEMA_TYPE_SIMPLE:
1408 	case XML_SCHEMA_TYPE_COMPLEX:
1409 	    return (((xmlSchemaTypePtr) item)->targetNamespace);
1410 	case XML_SCHEMA_TYPE_GROUP:
1411 	    return (((xmlSchemaModelGroupDefPtr) item)->targetNamespace);
1412 	case XML_SCHEMA_TYPE_IDC_KEY:
1413 	case XML_SCHEMA_TYPE_IDC_UNIQUE:
1414 	case XML_SCHEMA_TYPE_IDC_KEYREF:
1415 	    return (((xmlSchemaIDCPtr) item)->targetNamespace);
1416 	case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1417 	    if (WXS_ATTRUSE_DECL(item) != NULL) {
1418 		return(xmlSchemaGetComponentTargetNs(
1419 		    WXS_BASIC_CAST WXS_ATTRUSE_DECL(item)));
1420 	    }
1421 	    /* TODO: Will returning NULL break something? */
1422 	    break;
1423 	case XML_SCHEMA_EXTRA_QNAMEREF:
1424 	    return (((xmlSchemaQNameRefPtr) item)->targetNamespace);
1425 	case XML_SCHEMA_TYPE_NOTATION:
1426 	    return (((xmlSchemaNotationPtr) item)->targetNamespace);
1427 	default:
1428 	    /*
1429 	    * Other components cannot have names.
1430 	    */
1431 	    break;
1432     }
1433     return (NULL);
1434 }
1435 
1436 static const xmlChar*
xmlSchemaGetComponentQName(xmlChar ** buf,void * item)1437 xmlSchemaGetComponentQName(xmlChar **buf,
1438 			   void *item)
1439 {
1440     return (xmlSchemaFormatQName(buf,
1441 	xmlSchemaGetComponentTargetNs((xmlSchemaBasicItemPtr) item),
1442 	xmlSchemaGetComponentName((xmlSchemaBasicItemPtr) item)));
1443 }
1444 
1445 static const xmlChar*
xmlSchemaGetComponentDesignation(xmlChar ** buf,void * item)1446 xmlSchemaGetComponentDesignation(xmlChar **buf, void *item)
1447 {
1448     xmlChar *str = NULL;
1449 
1450     *buf = xmlStrcat(*buf, WXS_ITEM_TYPE_NAME(item));
1451     *buf = xmlStrcat(*buf, BAD_CAST " '");
1452     *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str,
1453 	(xmlSchemaBasicItemPtr) item));
1454     *buf = xmlStrcat(*buf, BAD_CAST "'");
1455     FREE_AND_NULL(str);
1456     return(*buf);
1457 }
1458 
1459 static const xmlChar*
xmlSchemaGetIDCDesignation(xmlChar ** buf,xmlSchemaIDCPtr idc)1460 xmlSchemaGetIDCDesignation(xmlChar **buf, xmlSchemaIDCPtr idc)
1461 {
1462     return(xmlSchemaGetComponentDesignation(buf, idc));
1463 }
1464 
1465 /**
1466  * xmlSchemaWildcardPCToString:
1467  * @pc: the type of processContents
1468  *
1469  * Returns a string representation of the type of
1470  * processContents.
1471  */
1472 static const xmlChar *
xmlSchemaWildcardPCToString(int pc)1473 xmlSchemaWildcardPCToString(int pc)
1474 {
1475     switch (pc) {
1476 	case XML_SCHEMAS_ANY_SKIP:
1477 	    return (BAD_CAST "skip");
1478 	case XML_SCHEMAS_ANY_LAX:
1479 	    return (BAD_CAST "lax");
1480 	case XML_SCHEMAS_ANY_STRICT:
1481 	    return (BAD_CAST "strict");
1482 	default:
1483 	    return (BAD_CAST "invalid process contents");
1484     }
1485 }
1486 
1487 /**
1488  * xmlSchemaGetCanonValueWhtspExt:
1489  * @val: the precomputed value
1490  * @retValue: the returned value
1491  * @ws: the whitespace type of the value
1492  * @for_hash: non-zero if this is supposed to generate a string for hashing
1493  *
1494  * Get a the canonical representation of the value.
1495  * The caller has to free the returned retValue.
1496  *
1497  * Returns 0 if the value could be built and -1 in case of
1498  *         API errors or if the value type is not supported yet.
1499  */
1500 static int
xmlSchemaGetCanonValueWhtspExt_1(xmlSchemaValPtr val,xmlSchemaWhitespaceValueType ws,xmlChar ** retValue,int for_hash)1501 xmlSchemaGetCanonValueWhtspExt_1(xmlSchemaValPtr val,
1502 			         xmlSchemaWhitespaceValueType ws,
1503 			         xmlChar **retValue,
1504 				 int for_hash)
1505 {
1506     int list;
1507     xmlSchemaValType valType;
1508     const xmlChar *value, *value2 = NULL;
1509 
1510 
1511     if ((retValue == NULL) || (val == NULL))
1512 	return (-1);
1513     list = xmlSchemaValueGetNext(val) ? 1 : 0;
1514     *retValue = NULL;
1515     do {
1516 	value = NULL;
1517 	valType = xmlSchemaGetValType(val);
1518 	switch (valType) {
1519 	    case XML_SCHEMAS_STRING:
1520 	    case XML_SCHEMAS_NORMSTRING:
1521 	    case XML_SCHEMAS_ANYSIMPLETYPE:
1522 		value = xmlSchemaValueGetAsString(val);
1523 		if (value != NULL) {
1524 		    if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
1525 			value2 = xmlSchemaCollapseString(value);
1526 		    else if (ws == XML_SCHEMA_WHITESPACE_REPLACE)
1527 			value2 = xmlSchemaWhiteSpaceReplace(value);
1528 		    if (value2 != NULL)
1529 			value = value2;
1530 		}
1531 		break;
1532 	    default:
1533 		if (xmlSchemaGetCanonValue(val, &value2) == -1) {
1534 		    if (value2 != NULL)
1535 			xmlFree((xmlChar *) value2);
1536 		    goto internal_error;
1537 		}
1538 		if (for_hash && valType == XML_SCHEMAS_DECIMAL) {
1539 		    /* We can mostly use the canonical value for hashing,
1540 		       except in the case of decimal.  There the canonical
1541 		       representation requires a trailing '.0' even for
1542 		       non-fractional numbers, but for the derived integer
1543 		       types it forbids any decimal point.  Nevertheless they
1544 		       compare equal if the value is equal.  We need to generate
1545 		       the same hash value for this to work, and it's easiest
1546 		       to just cut off the useless '.0' suffix for the
1547 		       decimal type.  */
1548 		    int len = xmlStrlen(value2);
1549 		    if (len > 2 && value2[len-1] == '0' && value2[len-2] == '.')
1550 		      ((xmlChar*)value2)[len-2] = 0;
1551 		}
1552 		value = value2;
1553 	}
1554 	if (*retValue == NULL)
1555 	    if (value == NULL) {
1556 		if (! list)
1557 		    *retValue = xmlStrdup(BAD_CAST "");
1558 	    } else
1559 		*retValue = xmlStrdup(value);
1560 	else if (value != NULL) {
1561 	    /* List. */
1562 	    *retValue = xmlStrcat((xmlChar *) *retValue, BAD_CAST " ");
1563 	    *retValue = xmlStrcat((xmlChar *) *retValue, value);
1564 	}
1565 	FREE_AND_NULL(value2)
1566 	val = xmlSchemaValueGetNext(val);
1567     } while (val != NULL);
1568 
1569     return (0);
1570 internal_error:
1571     if (*retValue != NULL)
1572 	xmlFree((xmlChar *) (*retValue));
1573     if (value2 != NULL)
1574 	xmlFree((xmlChar *) value2);
1575     return (-1);
1576 }
1577 
1578 static int
xmlSchemaGetCanonValueWhtspExt(xmlSchemaValPtr val,xmlSchemaWhitespaceValueType ws,xmlChar ** retValue)1579 xmlSchemaGetCanonValueWhtspExt(xmlSchemaValPtr val,
1580 			       xmlSchemaWhitespaceValueType ws,
1581 			       xmlChar **retValue)
1582 {
1583     return xmlSchemaGetCanonValueWhtspExt_1(val, ws, retValue, 0);
1584 }
1585 
1586 static int
xmlSchemaGetCanonValueHash(xmlSchemaValPtr val,xmlChar ** retValue)1587 xmlSchemaGetCanonValueHash(xmlSchemaValPtr val,
1588 			   xmlChar **retValue)
1589 {
1590     return xmlSchemaGetCanonValueWhtspExt_1(val, XML_SCHEMA_WHITESPACE_COLLAPSE,
1591 					    retValue, 1);
1592 }
1593 
1594 /**
1595  * xmlSchemaFormatItemForReport:
1596  * @buf: the string buffer
1597  * @itemDes: the designation of the item
1598  * @itemName: the name of the item
1599  * @item: the item as an object
1600  * @itemNode: the node of the item
1601  * @local: the local name
1602  * @parsing: if the function is used during the parse
1603  *
1604  * Returns a representation of the given item used
1605  * for error reports.
1606  *
1607  * The following order is used to build the resulting
1608  * designation if the arguments are not NULL:
1609  * 1a. If itemDes not NULL -> itemDes
1610  * 1b. If (itemDes not NULL) and (itemName not NULL)
1611  *     -> itemDes + itemName
1612  * 2. If the preceding was NULL and (item not NULL) -> item
1613  * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
1614  *
1615  * If the itemNode is an attribute node, the name of the attribute
1616  * will be appended to the result.
1617  *
1618  * Returns the formatted string and sets @buf to the resulting value.
1619  */
1620 static xmlChar*
xmlSchemaFormatItemForReport(xmlChar ** buf,const xmlChar * itemDes,xmlSchemaBasicItemPtr item,xmlNodePtr itemNode)1621 xmlSchemaFormatItemForReport(xmlChar **buf,
1622 		     const xmlChar *itemDes,
1623 		     xmlSchemaBasicItemPtr item,
1624 		     xmlNodePtr itemNode)
1625 {
1626     xmlChar *str = NULL;
1627     int named = 1;
1628 
1629     if (*buf != NULL) {
1630 	xmlFree(*buf);
1631 	*buf = NULL;
1632     }
1633 
1634     if (itemDes != NULL) {
1635 	*buf = xmlStrdup(itemDes);
1636     } else if (item != NULL) {
1637 	switch (item->type) {
1638 	case XML_SCHEMA_TYPE_BASIC: {
1639 	    xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1640 
1641 	    if (WXS_IS_ATOMIC(type))
1642 		*buf = xmlStrdup(BAD_CAST "atomic type 'xs:");
1643 	    else if (WXS_IS_LIST(type))
1644 		*buf = xmlStrdup(BAD_CAST "list type 'xs:");
1645 	    else if (WXS_IS_UNION(type))
1646 		*buf = xmlStrdup(BAD_CAST "union type 'xs:");
1647 	    else
1648 		*buf = xmlStrdup(BAD_CAST "simple type 'xs:");
1649 	    *buf = xmlStrcat(*buf, type->name);
1650 	    *buf = xmlStrcat(*buf, BAD_CAST "'");
1651 	    }
1652 	    break;
1653 	case XML_SCHEMA_TYPE_SIMPLE: {
1654 	    xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1655 
1656 	    if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1657 		*buf = xmlStrdup(BAD_CAST"");
1658 	    } else {
1659 		*buf = xmlStrdup(BAD_CAST "local ");
1660 	    }
1661 	    if (WXS_IS_ATOMIC(type))
1662 		*buf = xmlStrcat(*buf, BAD_CAST "atomic type");
1663 	    else if (WXS_IS_LIST(type))
1664 		*buf = xmlStrcat(*buf, BAD_CAST "list type");
1665 	    else if (WXS_IS_UNION(type))
1666 		*buf = xmlStrcat(*buf, BAD_CAST "union type");
1667 	    else
1668 		*buf = xmlStrcat(*buf, BAD_CAST "simple type");
1669 	    if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1670 		*buf = xmlStrcat(*buf, BAD_CAST " '");
1671 		*buf = xmlStrcat(*buf, type->name);
1672 		*buf = xmlStrcat(*buf, BAD_CAST "'");
1673 	    }
1674 	    }
1675 	    break;
1676 	case XML_SCHEMA_TYPE_COMPLEX: {
1677 	    xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1678 
1679 	    if (type->flags & XML_SCHEMAS_TYPE_GLOBAL)
1680 		*buf = xmlStrdup(BAD_CAST "");
1681 	    else
1682 		*buf = xmlStrdup(BAD_CAST "local ");
1683 	    *buf = xmlStrcat(*buf, BAD_CAST "complex type");
1684 	    if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1685 		*buf = xmlStrcat(*buf, BAD_CAST " '");
1686 		*buf = xmlStrcat(*buf, type->name);
1687 		*buf = xmlStrcat(*buf, BAD_CAST "'");
1688 	    }
1689 	    }
1690 	    break;
1691 	case XML_SCHEMA_TYPE_ATTRIBUTE_USE: {
1692 		xmlSchemaAttributeUsePtr ause;
1693 
1694 		ause = WXS_ATTR_USE_CAST item;
1695 		*buf = xmlStrdup(BAD_CAST "attribute use ");
1696 		if (WXS_ATTRUSE_DECL(ause) != NULL) {
1697 		    *buf = xmlStrcat(*buf, BAD_CAST "'");
1698 		    *buf = xmlStrcat(*buf,
1699 			xmlSchemaGetComponentQName(&str, WXS_ATTRUSE_DECL(ause)));
1700 		    FREE_AND_NULL(str)
1701 			*buf = xmlStrcat(*buf, BAD_CAST "'");
1702 		} else {
1703 		    *buf = xmlStrcat(*buf, BAD_CAST "(unknown)");
1704 		}
1705 	    }
1706 	    break;
1707 	case XML_SCHEMA_TYPE_ATTRIBUTE: {
1708 		xmlSchemaAttributePtr attr;
1709 
1710 		attr = (xmlSchemaAttributePtr) item;
1711 		*buf = xmlStrdup(BAD_CAST "attribute decl.");
1712 		*buf = xmlStrcat(*buf, BAD_CAST " '");
1713 		*buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1714 		    attr->targetNamespace, attr->name));
1715 		FREE_AND_NULL(str)
1716 		    *buf = xmlStrcat(*buf, BAD_CAST "'");
1717 	    }
1718 	    break;
1719 	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1720 	    xmlSchemaGetComponentDesignation(buf, item);
1721 	    break;
1722 	case XML_SCHEMA_TYPE_ELEMENT: {
1723 		xmlSchemaElementPtr elem;
1724 
1725 		elem = (xmlSchemaElementPtr) item;
1726 		*buf = xmlStrdup(BAD_CAST "element decl.");
1727 		*buf = xmlStrcat(*buf, BAD_CAST " '");
1728 		*buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1729 		    elem->targetNamespace, elem->name));
1730 		*buf = xmlStrcat(*buf, BAD_CAST "'");
1731 	    }
1732 	    break;
1733 	case XML_SCHEMA_TYPE_IDC_UNIQUE:
1734 	case XML_SCHEMA_TYPE_IDC_KEY:
1735 	case XML_SCHEMA_TYPE_IDC_KEYREF:
1736 	    if (item->type == XML_SCHEMA_TYPE_IDC_UNIQUE)
1737 		*buf = xmlStrdup(BAD_CAST "unique '");
1738 	    else if (item->type == XML_SCHEMA_TYPE_IDC_KEY)
1739 		*buf = xmlStrdup(BAD_CAST "key '");
1740 	    else
1741 		*buf = xmlStrdup(BAD_CAST "keyRef '");
1742 	    *buf = xmlStrcat(*buf, ((xmlSchemaIDCPtr) item)->name);
1743 	    *buf = xmlStrcat(*buf, BAD_CAST "'");
1744 	    break;
1745 	case XML_SCHEMA_TYPE_ANY:
1746 	case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1747 	    *buf = xmlStrdup(xmlSchemaWildcardPCToString(
1748 		    ((xmlSchemaWildcardPtr) item)->processContents));
1749 	    *buf = xmlStrcat(*buf, BAD_CAST " wildcard");
1750 	    break;
1751 	case XML_SCHEMA_FACET_MININCLUSIVE:
1752 	case XML_SCHEMA_FACET_MINEXCLUSIVE:
1753 	case XML_SCHEMA_FACET_MAXINCLUSIVE:
1754 	case XML_SCHEMA_FACET_MAXEXCLUSIVE:
1755 	case XML_SCHEMA_FACET_TOTALDIGITS:
1756 	case XML_SCHEMA_FACET_FRACTIONDIGITS:
1757 	case XML_SCHEMA_FACET_PATTERN:
1758 	case XML_SCHEMA_FACET_ENUMERATION:
1759 	case XML_SCHEMA_FACET_WHITESPACE:
1760 	case XML_SCHEMA_FACET_LENGTH:
1761 	case XML_SCHEMA_FACET_MAXLENGTH:
1762 	case XML_SCHEMA_FACET_MINLENGTH:
1763 	    *buf = xmlStrdup(BAD_CAST "facet '");
1764 	    *buf = xmlStrcat(*buf, xmlSchemaFacetTypeToString(item->type));
1765 	    *buf = xmlStrcat(*buf, BAD_CAST "'");
1766 	    break;
1767 	case XML_SCHEMA_TYPE_GROUP: {
1768 		*buf = xmlStrdup(BAD_CAST "model group def.");
1769 		*buf = xmlStrcat(*buf, BAD_CAST " '");
1770 		*buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, item));
1771 		*buf = xmlStrcat(*buf, BAD_CAST "'");
1772 		FREE_AND_NULL(str)
1773 	    }
1774 	    break;
1775 	case XML_SCHEMA_TYPE_SEQUENCE:
1776 	case XML_SCHEMA_TYPE_CHOICE:
1777 	case XML_SCHEMA_TYPE_ALL:
1778 	case XML_SCHEMA_TYPE_PARTICLE:
1779 	    *buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item));
1780 	    break;
1781 	case XML_SCHEMA_TYPE_NOTATION: {
1782 		*buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item));
1783 		*buf = xmlStrcat(*buf, BAD_CAST " '");
1784 		*buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, item));
1785 		*buf = xmlStrcat(*buf, BAD_CAST "'");
1786 		FREE_AND_NULL(str);
1787 	    }
1788             /* Falls through. */
1789 	default:
1790 	    named = 0;
1791 	}
1792     } else
1793 	named = 0;
1794 
1795     if ((named == 0) && (itemNode != NULL)) {
1796 	xmlNodePtr elem;
1797 
1798 	if (itemNode->type == XML_ATTRIBUTE_NODE)
1799 	    elem = itemNode->parent;
1800 	else
1801 	    elem = itemNode;
1802 	*buf = xmlStrdup(BAD_CAST "Element '");
1803 	if (elem->ns != NULL) {
1804 	    *buf = xmlStrcat(*buf,
1805 		xmlSchemaFormatQName(&str, elem->ns->href, elem->name));
1806 	    FREE_AND_NULL(str)
1807 	} else
1808 	    *buf = xmlStrcat(*buf, elem->name);
1809 	*buf = xmlStrcat(*buf, BAD_CAST "'");
1810 
1811     }
1812     if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
1813 	*buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
1814 	if (itemNode->ns != NULL) {
1815 	    *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1816 		itemNode->ns->href, itemNode->name));
1817 	    FREE_AND_NULL(str)
1818 	} else
1819 	    *buf = xmlStrcat(*buf, itemNode->name);
1820 	*buf = xmlStrcat(*buf, BAD_CAST "'");
1821     }
1822     FREE_AND_NULL(str)
1823 
1824     return (xmlEscapeFormatString(buf));
1825 }
1826 
1827 /**
1828  * xmlSchemaFormatFacetEnumSet:
1829  * @buf: the string buffer
1830  * @type: the type holding the enumeration facets
1831  *
1832  * Builds a string consisting of all enumeration elements.
1833  *
1834  * Returns a string of all enumeration elements.
1835  */
1836 static const xmlChar *
xmlSchemaFormatFacetEnumSet(xmlSchemaAbstractCtxtPtr actxt,xmlChar ** buf,xmlSchemaTypePtr type)1837 xmlSchemaFormatFacetEnumSet(xmlSchemaAbstractCtxtPtr actxt,
1838 			    xmlChar **buf, xmlSchemaTypePtr type)
1839 {
1840     xmlSchemaFacetPtr facet;
1841     xmlSchemaWhitespaceValueType ws;
1842     xmlChar *value = NULL;
1843     int res, found = 0;
1844 
1845     if (*buf != NULL)
1846 	xmlFree(*buf);
1847     *buf = NULL;
1848 
1849     do {
1850 	/*
1851 	* Use the whitespace type of the base type.
1852 	*/
1853 	ws = xmlSchemaGetWhiteSpaceFacetValue(type->baseType);
1854 	for (facet = type->facets; facet != NULL; facet = facet->next) {
1855 	    if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
1856 		continue;
1857 	    found = 1;
1858 	    res = xmlSchemaGetCanonValueWhtspExt(facet->val,
1859 		ws, &value);
1860 	    if (res == -1) {
1861 		xmlSchemaInternalErr(actxt,
1862 		    "xmlSchemaFormatFacetEnumSet",
1863 		    "compute the canonical lexical representation");
1864 		if (*buf != NULL)
1865 		    xmlFree(*buf);
1866 		*buf = NULL;
1867 		return (NULL);
1868 	    }
1869 	    if (*buf == NULL)
1870 		*buf = xmlStrdup(BAD_CAST "'");
1871 	    else
1872 		*buf = xmlStrcat(*buf, BAD_CAST ", '");
1873 	    *buf = xmlStrcat(*buf, BAD_CAST value);
1874 	    *buf = xmlStrcat(*buf, BAD_CAST "'");
1875 	    if (value != NULL) {
1876 		xmlFree((xmlChar *)value);
1877 		value = NULL;
1878 	    }
1879 	}
1880 	/*
1881 	* The enumeration facet of a type restricts the enumeration
1882 	* facet of the ancestor type; i.e., such restricted enumerations
1883 	* do not belong to the set of the given type. Thus we break
1884 	* on the first found enumeration.
1885 	*/
1886 	if (found)
1887 	    break;
1888 	type = type->baseType;
1889     } while ((type != NULL) && (type->type != XML_SCHEMA_TYPE_BASIC));
1890 
1891     return ((const xmlChar *) *buf);
1892 }
1893 
1894 /************************************************************************
1895  *									*
1896  *			Error functions				        *
1897  *									*
1898  ************************************************************************/
1899 
1900 /**
1901  * xmlSchemaPErrMemory:
1902  * @node: a context node
1903  * @extra:  extra information
1904  *
1905  * Handle an out of memory condition
1906  */
1907 static void
xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt)1908 xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt)
1909 {
1910     xmlGenericErrorFunc channel = NULL;
1911     xmlStructuredErrorFunc schannel = NULL;
1912     void *data = NULL;
1913 
1914     if (ctxt != NULL) {
1915         ctxt->nberrors++;
1916         ctxt->err = XML_ERR_NO_MEMORY;
1917         channel = ctxt->error;
1918         schannel = ctxt->serror;
1919         data = ctxt->errCtxt;
1920     }
1921 
1922     xmlRaiseMemoryError(schannel, channel, data, XML_FROM_SCHEMASP, NULL);
1923 }
1924 
1925 static void LIBXML_ATTR_FORMAT(11,12)
xmlSchemaPErrFull(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,int code,xmlErrorLevel level,const char * file,int line,const xmlChar * str1,const xmlChar * str2,const xmlChar * str3,int col,const char * msg,...)1926 xmlSchemaPErrFull(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int code,
1927                   xmlErrorLevel level, const char *file, int line,
1928                   const xmlChar *str1, const xmlChar *str2, const xmlChar *str3,
1929                   int col, const char *msg, ...) {
1930     xmlGenericErrorFunc channel = NULL;
1931     xmlStructuredErrorFunc schannel = NULL;
1932     void *data = NULL;
1933     int res;
1934     va_list ap;
1935 
1936     if (ctxt != NULL) {
1937         /* Don't overwrite memory errors */
1938         if (ctxt->err == XML_ERR_NO_MEMORY)
1939             return;
1940 
1941         if (level == XML_ERR_WARNING) {
1942             channel = ctxt->warning;
1943         } else {
1944             ctxt->nberrors++;
1945             ctxt->err = code;
1946             channel = ctxt->error;
1947         }
1948         data = ctxt->errCtxt;
1949         schannel = ctxt->serror;
1950     }
1951 
1952     if ((channel == NULL) && (schannel == NULL)) {
1953         channel = xmlGenericError;
1954         data = xmlGenericErrorContext;
1955     }
1956 
1957     va_start(ap, msg);
1958     res = xmlVRaiseError(schannel, channel, data, ctxt, node,
1959                          XML_FROM_SCHEMASP, code, level, file, line,
1960                          (const char *) str1,
1961                          (const char *) str2,
1962                          (const char *) str3,
1963                          0, col, msg, ap);
1964     va_end(ap);
1965 
1966     if (res < 0)
1967         xmlSchemaPErrMemory(ctxt);
1968 }
1969 
1970 /**
1971  * xmlSchemaPErr:
1972  * @ctxt: the parsing context
1973  * @node: the context node
1974  * @error: the error code
1975  * @msg: the error message
1976  * @str1: extra data
1977  * @str2: extra data
1978  *
1979  * Handle a parser error
1980  */
1981 static void LIBXML_ATTR_FORMAT(4,0)
xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,int code,const char * msg,const xmlChar * str1,const xmlChar * str2)1982 xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int code,
1983               const char *msg, const xmlChar * str1, const xmlChar * str2)
1984 {
1985     xmlSchemaPErrFull(ctxt, node, code, XML_ERR_ERROR, NULL, 0,
1986                       str1, str2, NULL, 0, msg, str1, str2);
1987 }
1988 
1989 /**
1990  * xmlSchemaPErr2:
1991  * @ctxt: the parsing context
1992  * @node: the context node
1993  * @node: the current child
1994  * @error: the error code
1995  * @msg: the error message
1996  * @str1: extra data
1997  * @str2: extra data
1998  *
1999  * Handle a parser error
2000  */
2001 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)2002 xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
2003                xmlNodePtr child, int error,
2004                const char *msg, const xmlChar * str1, const xmlChar * str2)
2005 {
2006     if (child != NULL)
2007         xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
2008     else
2009         xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
2010 }
2011 
2012 
2013 /**
2014  * xmlSchemaPErrExt:
2015  * @ctxt: the parsing context
2016  * @node: the context node
2017  * @error: the error code
2018  * @strData1: extra data
2019  * @strData2: extra data
2020  * @strData3: extra data
2021  * @msg: the message
2022  * @str1:  extra parameter for the message display
2023  * @str2:  extra parameter for the message display
2024  * @str3:  extra parameter for the message display
2025  * @str4:  extra parameter for the message display
2026  * @str5:  extra parameter for the message display
2027  *
2028  * Handle a parser error
2029  */
2030 static void LIBXML_ATTR_FORMAT(7,0)
xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,int code,const xmlChar * strData1,const xmlChar * strData2,const xmlChar * strData3,const char * msg,const xmlChar * str1,const xmlChar * str2,const xmlChar * str3,const xmlChar * str4,const xmlChar * str5)2031 xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int code,
2032 		const xmlChar * strData1, const xmlChar * strData2,
2033 		const xmlChar * strData3, const char *msg, const xmlChar * str1,
2034 		const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
2035 		const xmlChar * str5)
2036 {
2037     xmlSchemaPErrFull(ctxt, node, code, XML_ERR_ERROR, NULL, 0,
2038                       strData1, strData2, strData3, 0,
2039                       msg, str1, str2, str3, str4, str5);
2040 }
2041 
2042 /************************************************************************
2043  *									*
2044  *			Allround error functions			*
2045  *									*
2046  ************************************************************************/
2047 
2048 /**
2049  * xmlSchemaVTypeErrMemory:
2050  * @node: a context node
2051  * @extra:  extra information
2052  *
2053  * Handle an out of memory condition
2054  */
2055 static void
xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt)2056 xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt)
2057 {
2058     xmlGenericErrorFunc channel = NULL;
2059     xmlStructuredErrorFunc schannel = NULL;
2060     void *data = NULL;
2061 
2062     if (ctxt != NULL) {
2063         ctxt->nberrors++;
2064         ctxt->err = XML_ERR_NO_MEMORY;
2065         channel = ctxt->error;
2066         schannel = ctxt->serror;
2067         data = ctxt->errCtxt;
2068     }
2069 
2070     xmlRaiseMemoryError(schannel, channel, data, XML_FROM_SCHEMASV, NULL);
2071 }
2072 
2073 static void LIBXML_ATTR_FORMAT(11,12)
xmlSchemaVErrFull(xmlSchemaValidCtxtPtr ctxt,xmlNodePtr node,int code,xmlErrorLevel level,const char * file,int line,const xmlChar * str1,const xmlChar * str2,const xmlChar * str3,int col,const char * msg,...)2074 xmlSchemaVErrFull(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int code,
2075                   xmlErrorLevel level, const char *file, int line,
2076                   const xmlChar *str1, const xmlChar *str2, const xmlChar *str3,
2077                   int col, const char *msg, ...) {
2078     xmlGenericErrorFunc channel = NULL;
2079     xmlStructuredErrorFunc schannel = NULL;
2080     void *data = NULL;
2081     int res;
2082     va_list ap;
2083 
2084     if (ctxt != NULL) {
2085         /* Don't overwrite memory errors */
2086         if (ctxt->err == XML_ERR_NO_MEMORY)
2087             return;
2088 
2089         if (level == XML_ERR_WARNING) {
2090             channel = ctxt->warning;
2091         } else {
2092             ctxt->nberrors++;
2093             ctxt->err = code;
2094             channel = ctxt->error;
2095         }
2096         data = ctxt->errCtxt;
2097         schannel = ctxt->serror;
2098     }
2099 
2100     if ((channel == NULL) && (schannel == NULL)) {
2101         channel = xmlGenericError;
2102         data = xmlGenericErrorContext;
2103     }
2104 
2105     va_start(ap, msg);
2106     res = xmlVRaiseError(schannel, channel, data, ctxt, node,
2107                          XML_FROM_SCHEMASV, code, level, file, line,
2108                          (const char *) str1,
2109                          (const char *) str2,
2110                          (const char *) str3,
2111                          0, col, msg, ap);
2112     va_end(ap);
2113 
2114     if (res < 0)
2115         xmlSchemaVErrMemory(ctxt);
2116 }
2117 
2118 #define WXS_ERROR_TYPE_ERROR 1
2119 #define WXS_ERROR_TYPE_WARNING 2
2120 /**
2121  * xmlSchemaErr4Line:
2122  * @ctxt: the validation context
2123  * @errorLevel: the error level
2124  * @error: the error code
2125  * @node: the context node
2126  * @line: the line number
2127  * @msg: the error message
2128  * @str1: extra data
2129  * @str2: extra data
2130  * @str3: extra data
2131  * @str4: extra data
2132  *
2133  * Handle a validation error
2134  */
2135 static void LIBXML_ATTR_FORMAT(6,0)
xmlSchemaErr4Line(xmlSchemaAbstractCtxtPtr ctxt,xmlErrorLevel errorLevel,int code,xmlNodePtr node,int line,const char * msg,const xmlChar * str1,const xmlChar * str2,const xmlChar * str3,const xmlChar * str4)2136 xmlSchemaErr4Line(xmlSchemaAbstractCtxtPtr ctxt,
2137 		  xmlErrorLevel errorLevel,
2138 		  int code, xmlNodePtr node, int line, const char *msg,
2139 		  const xmlChar *str1, const xmlChar *str2,
2140 		  const xmlChar *str3, const xmlChar *str4)
2141 {
2142     if (ctxt != NULL) {
2143 	if (ctxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
2144 	    xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctxt;
2145 	    const char *file = NULL;
2146 	    int col = 0;
2147 
2148 	    /*
2149 	    * Error node. If we specify a line number, then
2150 	    * do not channel any node to the error function.
2151 	    */
2152 	    if (line == 0) {
2153 		if ((node == NULL) &&
2154 		    (vctxt->depth >= 0) &&
2155 		    (vctxt->inode != NULL)) {
2156 		    node = vctxt->inode->node;
2157 		}
2158 		/*
2159 		* Get filename and line if no node-tree.
2160 		*/
2161 		if ((node == NULL) &&
2162 		    (vctxt->parserCtxt != NULL) &&
2163 		    (vctxt->parserCtxt->input != NULL)) {
2164 		    file = vctxt->parserCtxt->input->filename;
2165                     if (vctxt->inode != NULL) {
2166 		        line = vctxt->inode->nodeLine;
2167                         col = 0;
2168                     } else {
2169                         /* This is inaccurate. */
2170 		        line = vctxt->parserCtxt->input->line;
2171 		        col = vctxt->parserCtxt->input->col;
2172                     }
2173 		}
2174 	    } else {
2175 		/*
2176 		* Override the given node's (if any) position
2177 		* and channel only the given line number.
2178 		*/
2179 		node = NULL;
2180 		/*
2181 		* Get filename.
2182 		*/
2183 		if (vctxt->doc != NULL)
2184 		    file = (const char *) vctxt->doc->URL;
2185 		else if ((vctxt->parserCtxt != NULL) &&
2186 		    (vctxt->parserCtxt->input != NULL))
2187 		    file = vctxt->parserCtxt->input->filename;
2188 	    }
2189 	    if (vctxt->locFunc != NULL) {
2190 	        if ((file == NULL) || (line == 0)) {
2191 		    unsigned long l;
2192 		    const char *f;
2193 		    vctxt->locFunc(vctxt->locCtxt, &f, &l);
2194 		    if (file == NULL)
2195 		        file = f;
2196 		    if (line == 0)
2197 		        line = (int) l;
2198 		}
2199 	    }
2200 	    if ((file == NULL) && (vctxt->filename != NULL))
2201 	        file = vctxt->filename;
2202 
2203             xmlSchemaVErrFull(vctxt, node, code, errorLevel,
2204                               file, line, str1, str2, str3, col,
2205                               msg, str1, str2, str3, str4);
2206 	} else if (ctxt->type == XML_SCHEMA_CTXT_PARSER) {
2207 	    xmlSchemaParserCtxtPtr pctxt = (xmlSchemaParserCtxtPtr) ctxt;
2208 
2209             xmlSchemaPErrFull(pctxt, node, code, errorLevel,
2210                               NULL, 0, str1, str2, str3, 0,
2211                               msg, str1, str2, str3, str4);
2212 	}
2213     }
2214 }
2215 
2216 /**
2217  * xmlSchemaErr3:
2218  * @ctxt: the validation context
2219  * @node: the context node
2220  * @error: the error code
2221  * @msg: the error message
2222  * @str1: extra data
2223  * @str2: extra data
2224  * @str3: extra data
2225  *
2226  * Handle a validation error
2227  */
2228 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)2229 xmlSchemaErr3(xmlSchemaAbstractCtxtPtr actxt,
2230 	      int error, xmlNodePtr node, const char *msg,
2231 	      const xmlChar *str1, const xmlChar *str2, const xmlChar *str3)
2232 {
2233     xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0,
2234 	msg, str1, str2, str3, NULL);
2235 }
2236 
2237 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)2238 xmlSchemaErr4(xmlSchemaAbstractCtxtPtr actxt,
2239 	      int error, xmlNodePtr node, const char *msg,
2240 	      const xmlChar *str1, const xmlChar *str2,
2241 	      const xmlChar *str3, const xmlChar *str4)
2242 {
2243     xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0,
2244 	msg, str1, str2, str3, str4);
2245 }
2246 
2247 static void LIBXML_ATTR_FORMAT(4,0)
xmlSchemaErr(xmlSchemaAbstractCtxtPtr actxt,int error,xmlNodePtr node,const char * msg,const xmlChar * str1,const xmlChar * str2)2248 xmlSchemaErr(xmlSchemaAbstractCtxtPtr actxt,
2249 	     int error, xmlNodePtr node, const char *msg,
2250 	     const xmlChar *str1, const xmlChar *str2)
2251 {
2252     xmlSchemaErr4(actxt, error, node, msg, str1, str2, NULL, NULL);
2253 }
2254 
2255 static xmlChar *
xmlSchemaFormatNodeForError(xmlChar ** msg,xmlSchemaAbstractCtxtPtr actxt,xmlNodePtr node)2256 xmlSchemaFormatNodeForError(xmlChar ** msg,
2257 			    xmlSchemaAbstractCtxtPtr actxt,
2258 			    xmlNodePtr node)
2259 {
2260     xmlChar *str = NULL;
2261 
2262     *msg = NULL;
2263     if ((node != NULL) &&
2264 	(node->type != XML_ELEMENT_NODE) &&
2265 	(node->type != XML_ATTRIBUTE_NODE))
2266     {
2267 	/*
2268 	* Don't try to format other nodes than element and
2269 	* attribute nodes.
2270 	* Play safe and return an empty string.
2271 	*/
2272 	*msg = xmlStrdup(BAD_CAST "");
2273 	return(*msg);
2274     }
2275     if (node != NULL) {
2276 	/*
2277 	* Work on tree nodes.
2278 	*/
2279 	if (node->type == XML_ATTRIBUTE_NODE) {
2280 	    xmlNodePtr elem = node->parent;
2281 
2282 	    *msg = xmlStrdup(BAD_CAST "Element '");
2283 	    if (elem->ns != NULL)
2284 		*msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2285 		    elem->ns->href, elem->name));
2286 	    else
2287 		*msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2288 		    NULL, elem->name));
2289 	    FREE_AND_NULL(str);
2290 	    *msg = xmlStrcat(*msg, BAD_CAST "', ");
2291 	    *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
2292 	} else {
2293 	    *msg = xmlStrdup(BAD_CAST "Element '");
2294 	}
2295 	if (node->ns != NULL)
2296 	    *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2297 	    node->ns->href, node->name));
2298 	else
2299 	    *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2300 	    NULL, node->name));
2301 	FREE_AND_NULL(str);
2302 	*msg = xmlStrcat(*msg, BAD_CAST "': ");
2303     } else if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
2304 	xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) actxt;
2305 	/*
2306 	* Work on node infos.
2307 	*/
2308 	if (vctxt->inode->nodeType == XML_ATTRIBUTE_NODE) {
2309 	    xmlSchemaNodeInfoPtr ielem =
2310 		vctxt->elemInfos[vctxt->depth];
2311 
2312 	    *msg = xmlStrdup(BAD_CAST "Element '");
2313 	    *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2314 		ielem->nsName, ielem->localName));
2315 	    FREE_AND_NULL(str);
2316 	    *msg = xmlStrcat(*msg, BAD_CAST "', ");
2317 	    *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
2318 	} else {
2319 	    *msg = xmlStrdup(BAD_CAST "Element '");
2320 	}
2321 	*msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2322 	    vctxt->inode->nsName, vctxt->inode->localName));
2323 	FREE_AND_NULL(str);
2324 	*msg = xmlStrcat(*msg, BAD_CAST "': ");
2325     } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
2326 	/*
2327 	* Hmm, no node while parsing?
2328 	* Return an empty string, in case NULL will break something.
2329 	*/
2330 	*msg = xmlStrdup(BAD_CAST "");
2331     } else {
2332 	/* TODO */
2333 	return (NULL);
2334     }
2335 
2336     /*
2337      * xmlSchemaFormatItemForReport() also returns an escaped format
2338      * string, so do this before calling it below (in the future).
2339      */
2340     xmlEscapeFormatString(msg);
2341 
2342     /*
2343     * VAL TODO: The output of the given schema component is currently
2344     * disabled.
2345     */
2346 #if 0
2347     if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
2348 	*msg = xmlStrcat(*msg, BAD_CAST " [");
2349 	*msg = xmlStrcat(*msg, xmlSchemaFormatItemForReport(&str,
2350 	    NULL, type, NULL, 0));
2351 	FREE_AND_NULL(str)
2352 	*msg = xmlStrcat(*msg, BAD_CAST "]");
2353     }
2354 #endif
2355     return (*msg);
2356 }
2357 
2358 static void LIBXML_ATTR_FORMAT(3,0)
xmlSchemaInternalErr2(xmlSchemaAbstractCtxtPtr actxt,const char * funcName,const char * message,const xmlChar * str1,const xmlChar * str2)2359 xmlSchemaInternalErr2(xmlSchemaAbstractCtxtPtr actxt,
2360 		     const char *funcName,
2361 		     const char *message,
2362 		     const xmlChar *str1,
2363 		     const xmlChar *str2)
2364 {
2365     xmlChar *msg = NULL;
2366 
2367     if (actxt == NULL)
2368         return;
2369     msg = xmlStrdup(BAD_CAST "Internal error: %s, ");
2370     msg = xmlStrcat(msg, BAD_CAST message);
2371     msg = xmlStrcat(msg, BAD_CAST ".\n");
2372 
2373     if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR)
2374 	xmlSchemaErr3(actxt, XML_SCHEMAV_INTERNAL, NULL,
2375 	    (const char *) msg, (const xmlChar *) funcName, str1, str2);
2376     else if (actxt->type == XML_SCHEMA_CTXT_PARSER)
2377 	xmlSchemaErr3(actxt, XML_SCHEMAP_INTERNAL, NULL,
2378 	    (const char *) msg, (const xmlChar *) funcName, str1, str2);
2379 
2380     FREE_AND_NULL(msg)
2381 }
2382 
2383 static void LIBXML_ATTR_FORMAT(3,0)
xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,const char * funcName,const char * message)2384 xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
2385 		     const char *funcName,
2386 		     const char *message)
2387 {
2388     xmlSchemaInternalErr2(actxt, funcName, message, NULL, NULL);
2389 }
2390 
2391 #if 0
2392 static void LIBXML_ATTR_FORMAT(3,0)
2393 xmlSchemaPInternalErr(xmlSchemaParserCtxtPtr pctxt,
2394 		     const char *funcName,
2395 		     const char *message,
2396 		     const xmlChar *str1,
2397 		     const xmlChar *str2)
2398 {
2399     xmlSchemaInternalErr2(ACTXT_CAST pctxt, funcName, message,
2400 	str1, str2);
2401 }
2402 #endif
2403 
2404 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)2405 xmlSchemaCustomErr4(xmlSchemaAbstractCtxtPtr actxt,
2406 		   xmlParserErrors error,
2407 		   xmlNodePtr node,
2408 		   xmlSchemaBasicItemPtr item,
2409 		   const char *message,
2410 		   const xmlChar *str1, const xmlChar *str2,
2411 		   const xmlChar *str3, const xmlChar *str4)
2412 {
2413     xmlChar *msg = NULL;
2414 
2415     if ((node == NULL) && (item != NULL) &&
2416 	(actxt->type == XML_SCHEMA_CTXT_PARSER)) {
2417 	node = WXS_ITEM_NODE(item);
2418 	xmlSchemaFormatItemForReport(&msg, NULL, item, NULL);
2419 	msg = xmlStrcat(msg, BAD_CAST ": ");
2420     } else
2421 	xmlSchemaFormatNodeForError(&msg, actxt, node);
2422     msg = xmlStrcat(msg, (const xmlChar *) message);
2423     msg = xmlStrcat(msg, BAD_CAST ".\n");
2424     xmlSchemaErr4(actxt, error, node,
2425 	(const char *) msg, str1, str2, str3, str4);
2426     FREE_AND_NULL(msg)
2427 }
2428 
2429 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)2430 xmlSchemaCustomErr(xmlSchemaAbstractCtxtPtr actxt,
2431 		   xmlParserErrors error,
2432 		   xmlNodePtr node,
2433 		   xmlSchemaBasicItemPtr item,
2434 		   const char *message,
2435 		   const xmlChar *str1,
2436 		   const xmlChar *str2)
2437 {
2438     xmlSchemaCustomErr4(actxt, error, node, item,
2439 	message, str1, str2, NULL, NULL);
2440 }
2441 
2442 
2443 
2444 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)2445 xmlSchemaCustomWarning(xmlSchemaAbstractCtxtPtr actxt,
2446 		   xmlParserErrors error,
2447 		   xmlNodePtr node,
2448 		   xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2449 		   const char *message,
2450 		   const xmlChar *str1,
2451 		   const xmlChar *str2,
2452 		   const xmlChar *str3)
2453 {
2454     xmlChar *msg = NULL;
2455 
2456     xmlSchemaFormatNodeForError(&msg, actxt, node);
2457     msg = xmlStrcat(msg, (const xmlChar *) message);
2458     msg = xmlStrcat(msg, BAD_CAST ".\n");
2459 
2460     /* URGENT TODO: Set the error code to something sane. */
2461     xmlSchemaErr4Line(actxt, XML_ERR_WARNING, error, node, 0,
2462 	(const char *) msg, str1, str2, str3, NULL);
2463 
2464     FREE_AND_NULL(msg)
2465 }
2466 
2467 
2468 
2469 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)2470 xmlSchemaKeyrefErr(xmlSchemaValidCtxtPtr vctxt,
2471 		   xmlParserErrors error,
2472 		   xmlSchemaPSVIIDCNodePtr idcNode,
2473 		   xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2474 		   const char *message,
2475 		   const xmlChar *str1,
2476 		   const xmlChar *str2)
2477 {
2478     xmlChar *msg = NULL, *qname = NULL;
2479 
2480     msg = xmlStrdup(BAD_CAST "Element '%s': ");
2481     msg = xmlStrcat(msg, (const xmlChar *) message);
2482     msg = xmlStrcat(msg, BAD_CAST ".\n");
2483     xmlSchemaErr4Line(ACTXT_CAST vctxt, XML_ERR_ERROR,
2484 	error, NULL, idcNode->nodeLine, (const char *) msg,
2485 	xmlSchemaFormatQName(&qname,
2486 	    vctxt->nodeQNames->items[idcNode->nodeQNameID +1],
2487 	    vctxt->nodeQNames->items[idcNode->nodeQNameID]),
2488 	str1, str2, NULL);
2489     FREE_AND_NULL(qname);
2490     FREE_AND_NULL(msg);
2491 }
2492 
2493 static int
xmlSchemaEvalErrorNodeType(xmlSchemaAbstractCtxtPtr actxt,xmlNodePtr node)2494 xmlSchemaEvalErrorNodeType(xmlSchemaAbstractCtxtPtr actxt,
2495 			   xmlNodePtr node)
2496 {
2497     if (node != NULL)
2498 	return (node->type);
2499     if ((actxt->type == XML_SCHEMA_CTXT_VALIDATOR) &&
2500 	(((xmlSchemaValidCtxtPtr) actxt)->inode != NULL))
2501 	return ( ((xmlSchemaValidCtxtPtr) actxt)->inode->nodeType);
2502     return (-1);
2503 }
2504 
2505 static int
xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)2506 xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
2507 {
2508     switch (item->type) {
2509 	case XML_SCHEMA_TYPE_COMPLEX:
2510 	case XML_SCHEMA_TYPE_SIMPLE:
2511 	    if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
2512 		return(1);
2513 	    break;
2514 	case XML_SCHEMA_TYPE_GROUP:
2515 	    return (1);
2516 	case XML_SCHEMA_TYPE_ELEMENT:
2517 	    if ( ((xmlSchemaElementPtr) item)->flags &
2518 		XML_SCHEMAS_ELEM_GLOBAL)
2519 		return(1);
2520 	    break;
2521 	case XML_SCHEMA_TYPE_ATTRIBUTE:
2522 	    if ( ((xmlSchemaAttributePtr) item)->flags &
2523 		XML_SCHEMAS_ATTR_GLOBAL)
2524 		return(1);
2525 	    break;
2526 	/* Note that attribute groups are always global. */
2527 	default:
2528 	    return(1);
2529     }
2530     return (0);
2531 }
2532 
2533 static void
xmlSchemaSimpleTypeErr(xmlSchemaAbstractCtxtPtr actxt,xmlParserErrors error,xmlNodePtr node,const xmlChar * value,xmlSchemaTypePtr type,int displayValue)2534 xmlSchemaSimpleTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2535 		       xmlParserErrors error,
2536 		       xmlNodePtr node,
2537 		       const xmlChar *value,
2538 		       xmlSchemaTypePtr type,
2539 		       int displayValue)
2540 {
2541     xmlChar *msg = NULL;
2542 
2543     xmlSchemaFormatNodeForError(&msg, actxt, node);
2544 
2545     if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2546 	    XML_ATTRIBUTE_NODE))
2547 	msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
2548     else
2549 	msg = xmlStrcat(msg, BAD_CAST "The character content is not a valid "
2550 	    "value of ");
2551 
2552     if (! xmlSchemaIsGlobalItem(type))
2553 	msg = xmlStrcat(msg, BAD_CAST "the local ");
2554     else
2555 	msg = xmlStrcat(msg, BAD_CAST "the ");
2556 
2557     if (WXS_IS_ATOMIC(type))
2558 	msg = xmlStrcat(msg, BAD_CAST "atomic type");
2559     else if (WXS_IS_LIST(type))
2560 	msg = xmlStrcat(msg, BAD_CAST "list type");
2561     else if (WXS_IS_UNION(type))
2562 	msg = xmlStrcat(msg, BAD_CAST "union type");
2563 
2564     if (xmlSchemaIsGlobalItem(type)) {
2565 	xmlChar *str = NULL;
2566 	msg = xmlStrcat(msg, BAD_CAST " '");
2567 	if (type->builtInType != 0) {
2568 	    msg = xmlStrcat(msg, BAD_CAST "xs:");
2569 	    str = xmlStrdup(type->name);
2570 	} else {
2571 	    const xmlChar *qName = xmlSchemaFormatQName(&str, type->targetNamespace, type->name);
2572 	    if (!str)
2573 		str = xmlStrdup(qName);
2574 	}
2575 	msg = xmlStrcat(msg, xmlEscapeFormatString(&str));
2576 	msg = xmlStrcat(msg, BAD_CAST "'");
2577 	FREE_AND_NULL(str);
2578     }
2579     msg = xmlStrcat(msg, BAD_CAST ".\n");
2580     if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2581 	    XML_ATTRIBUTE_NODE))
2582 	xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2583     else
2584 	xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2585     FREE_AND_NULL(msg)
2586 }
2587 
2588 static const xmlChar *
xmlSchemaFormatErrorNodeQName(xmlChar ** str,xmlSchemaNodeInfoPtr ni,xmlNodePtr node)2589 xmlSchemaFormatErrorNodeQName(xmlChar ** str,
2590 			      xmlSchemaNodeInfoPtr ni,
2591 			      xmlNodePtr node)
2592 {
2593     if (node != NULL) {
2594 	if (node->ns != NULL)
2595 	    return (xmlSchemaFormatQName(str, node->ns->href, node->name));
2596 	else
2597 	    return (xmlSchemaFormatQName(str, NULL, node->name));
2598     } else if (ni != NULL)
2599 	return (xmlSchemaFormatQName(str, ni->nsName, ni->localName));
2600     return (NULL);
2601 }
2602 
2603 static void
xmlSchemaIllegalAttrErr(xmlSchemaAbstractCtxtPtr actxt,xmlParserErrors error,xmlSchemaAttrInfoPtr ni,xmlNodePtr node)2604 xmlSchemaIllegalAttrErr(xmlSchemaAbstractCtxtPtr actxt,
2605 			xmlParserErrors error,
2606 			xmlSchemaAttrInfoPtr ni,
2607 			xmlNodePtr node)
2608 {
2609     xmlChar *msg = NULL, *str = NULL;
2610 
2611     xmlSchemaFormatNodeForError(&msg, actxt, node);
2612     msg = xmlStrcat(msg, BAD_CAST "The attribute '%s' is not allowed.\n");
2613     xmlSchemaErr(actxt, error, node, (const char *) msg,
2614 	xmlSchemaFormatErrorNodeQName(&str, (xmlSchemaNodeInfoPtr) ni, node),
2615 	NULL);
2616     FREE_AND_NULL(str)
2617     FREE_AND_NULL(msg)
2618 }
2619 
2620 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)2621 xmlSchemaComplexTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2622 		        xmlParserErrors error,
2623 		        xmlNodePtr node,
2624 			xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2625 			const char *message,
2626 			int nbval,
2627 			int nbneg,
2628 			xmlChar **values)
2629 {
2630     xmlChar *str = NULL, *msg = NULL;
2631     xmlChar *localName, *nsName;
2632     const xmlChar *cur, *end;
2633     int i;
2634 
2635     xmlSchemaFormatNodeForError(&msg, actxt, node);
2636     msg = xmlStrcat(msg, (const xmlChar *) message);
2637     msg = xmlStrcat(msg, BAD_CAST ".");
2638     /*
2639     * Note that is does not make sense to report that we have a
2640     * wildcard here, since the wildcard might be unfolded into
2641     * multiple transitions.
2642     */
2643     if (nbval + nbneg > 0) {
2644 	if (nbval + nbneg > 1) {
2645 	    str = xmlStrdup(BAD_CAST " Expected is one of ( ");
2646 	} else
2647 	    str = xmlStrdup(BAD_CAST " Expected is ( ");
2648 	nsName = NULL;
2649 
2650 	for (i = 0; i < nbval + nbneg; i++) {
2651 	    cur = values[i];
2652 	    if (cur == NULL)
2653 	        continue;
2654 	    if ((cur[0] == 'n') && (cur[1] == 'o') && (cur[2] == 't') &&
2655 	        (cur[3] == ' ')) {
2656 		cur += 4;
2657 		str = xmlStrcat(str, BAD_CAST "##other");
2658 	    }
2659 	    /*
2660 	    * Get the local name.
2661 	    */
2662 	    localName = NULL;
2663 
2664 	    end = cur;
2665 	    if (*end == '*') {
2666 		localName = xmlStrdup(BAD_CAST "*");
2667 		end++;
2668 	    } else {
2669 		while ((*end != 0) && (*end != '|'))
2670 		    end++;
2671 		localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
2672 	    }
2673 	    if (*end != 0) {
2674 		end++;
2675 		/*
2676 		* Skip "*|*" if they come with negated expressions, since
2677 		* they represent the same negated wildcard.
2678 		*/
2679 		if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
2680 		    /*
2681 		    * Get the namespace name.
2682 		    */
2683 		    cur = end;
2684 		    if (*end == '*') {
2685 			nsName = xmlStrdup(BAD_CAST "{*}");
2686 		    } else {
2687 			while (*end != 0)
2688 			    end++;
2689 
2690 			if (i >= nbval)
2691 			    nsName = xmlStrdup(BAD_CAST "{##other:");
2692 			else
2693 			    nsName = xmlStrdup(BAD_CAST "{");
2694 
2695 			nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
2696 			nsName = xmlStrcat(nsName, BAD_CAST "}");
2697 		    }
2698 		    str = xmlStrcat(str, BAD_CAST nsName);
2699 		    FREE_AND_NULL(nsName)
2700 		} else {
2701 		    FREE_AND_NULL(localName);
2702 		    continue;
2703 		}
2704 	    }
2705 	    str = xmlStrcat(str, BAD_CAST localName);
2706 	    FREE_AND_NULL(localName);
2707 
2708 	    if (i < nbval + nbneg -1)
2709 		str = xmlStrcat(str, BAD_CAST ", ");
2710 	}
2711 	str = xmlStrcat(str, BAD_CAST " ).\n");
2712 	msg = xmlStrcat(msg, xmlEscapeFormatString(&str));
2713 	FREE_AND_NULL(str)
2714     } else
2715       msg = xmlStrcat(msg, BAD_CAST "\n");
2716     xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2717     xmlFree(msg);
2718 }
2719 
2720 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)2721 xmlSchemaFacetErr(xmlSchemaAbstractCtxtPtr actxt,
2722 		  xmlParserErrors error,
2723 		  xmlNodePtr node,
2724 		  const xmlChar *value,
2725 		  unsigned long length,
2726 		  xmlSchemaTypePtr type,
2727 		  xmlSchemaFacetPtr facet,
2728 		  const char *message,
2729 		  const xmlChar *str1,
2730 		  const xmlChar *str2)
2731 {
2732     xmlChar *str = NULL, *msg = NULL;
2733     xmlSchemaTypeType facetType;
2734     int nodeType = xmlSchemaEvalErrorNodeType(actxt, node);
2735 
2736     xmlSchemaFormatNodeForError(&msg, actxt, node);
2737     if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
2738 	facetType = XML_SCHEMA_FACET_ENUMERATION;
2739 	/*
2740 	* If enumerations are validated, one must not expect the
2741 	* facet to be given.
2742 	*/
2743     } else
2744 	facetType = facet->type;
2745     msg = xmlStrcat(msg, BAD_CAST "[");
2746     msg = xmlStrcat(msg, BAD_CAST "facet '");
2747     msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facetType));
2748     msg = xmlStrcat(msg, BAD_CAST "'] ");
2749     if (message == NULL) {
2750 	/*
2751 	* Use a default message.
2752 	*/
2753 	if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
2754 	    (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
2755 	    (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
2756 
2757 	    char len[25], actLen[25];
2758 
2759 	    /* FIXME, TODO: What is the max expected string length of the
2760 	    * this value?
2761 	    */
2762 	    if (nodeType == XML_ATTRIBUTE_NODE)
2763 		msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
2764 	    else
2765 		msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
2766 
2767 	    snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
2768 	    snprintf(actLen, 24, "%lu", length);
2769 
2770 	    if (facetType == XML_SCHEMA_FACET_LENGTH)
2771 		msg = xmlStrcat(msg,
2772 		BAD_CAST "this differs from the allowed length of '%s'.\n");
2773 	    else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
2774 		msg = xmlStrcat(msg,
2775 		BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
2776 	    else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
2777 		msg = xmlStrcat(msg,
2778 		BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
2779 
2780 	    if (nodeType == XML_ATTRIBUTE_NODE)
2781 		xmlSchemaErr3(actxt, error, node, (const char *) msg,
2782 		    value, (const xmlChar *) actLen, (const xmlChar *) len);
2783 	    else
2784 		xmlSchemaErr(actxt, error, node, (const char *) msg,
2785 		    (const xmlChar *) actLen, (const xmlChar *) len);
2786 
2787 	} else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
2788 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
2789 		"of the set {%s}.\n");
2790 	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2791 		xmlSchemaFormatFacetEnumSet(actxt, &str, type));
2792 	} else if (facetType == XML_SCHEMA_FACET_PATTERN) {
2793 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
2794 		"by the pattern '%s'.\n");
2795 	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2796 		facet->value);
2797 	} else if (facetType == XML_SCHEMA_FACET_MININCLUSIVE) {
2798 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' is less than the "
2799 		"minimum value allowed ('%s').\n");
2800 	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2801 		facet->value);
2802 	} else if (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) {
2803 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' is greater than the "
2804 		"maximum value allowed ('%s').\n");
2805 	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2806 		facet->value);
2807 	} else if (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE) {
2808 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be greater than "
2809 		"'%s'.\n");
2810 	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2811 		facet->value);
2812 	} else if (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) {
2813 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be less than "
2814 		"'%s'.\n");
2815 	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2816 		facet->value);
2817 	} else if (facetType == XML_SCHEMA_FACET_TOTALDIGITS) {
2818 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more "
2819 		"digits than are allowed ('%s').\n");
2820 	    xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2821 		facet->value);
2822 	} else if (facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) {
2823 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more fractional "
2824 		"digits than are allowed ('%s').\n");
2825 	    xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2826 		facet->value);
2827 	} else if (nodeType == XML_ATTRIBUTE_NODE) {
2828 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
2829 	    xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2830 	} else {
2831 	    msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
2832 	    xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2833 	}
2834     } else {
2835 	msg = xmlStrcat(msg, (const xmlChar *) message);
2836 	msg = xmlStrcat(msg, BAD_CAST ".\n");
2837 	xmlSchemaErr(actxt, error, node, (const char *) msg, str1, str2);
2838     }
2839     FREE_AND_NULL(str)
2840     xmlFree(msg);
2841 }
2842 
2843 #define VERROR(err, type, msg) \
2844     xmlSchemaCustomErr(ACTXT_CAST vctxt, err, NULL, type, msg, NULL, NULL);
2845 
2846 #define VERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST vctxt, func, msg);
2847 
2848 #define PERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST pctxt, func, msg);
2849 #define PERROR_INT2(func, msg) xmlSchemaInternalErr(ACTXT_CAST ctxt, func, msg);
2850 
2851 #define AERROR_INT(func, msg) xmlSchemaInternalErr(actxt, func, msg);
2852 
2853 
2854 /**
2855  * xmlSchemaPMissingAttrErr:
2856  * @ctxt: the schema validation context
2857  * @ownerItem: the owner as a schema object
2858  * @ownerElem: the owner as an element node
2859  * @node: the parent element node of the missing attribute node
2860  * @type: the corresponding type of the attribute node
2861  *
2862  * Reports an illegal attribute.
2863  */
2864 static void
xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaBasicItemPtr ownerItem,xmlNodePtr ownerElem,const char * name,const char * message)2865 xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
2866 			 xmlParserErrors error,
2867 			 xmlSchemaBasicItemPtr ownerItem,
2868 			 xmlNodePtr ownerElem,
2869 			 const char *name,
2870 			 const char *message)
2871 {
2872     xmlChar *des = NULL;
2873 
2874     xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2875 
2876     if (message != NULL)
2877 	xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
2878     else
2879 	xmlSchemaPErr(ctxt, ownerElem, error,
2880 	    "%s: The attribute '%s' is required but missing.\n",
2881 	    BAD_CAST des, BAD_CAST name);
2882     FREE_AND_NULL(des);
2883 }
2884 
2885 
2886 /**
2887  * xmlSchemaPResCompAttrErr:
2888  * @ctxt: the schema validation context
2889  * @error: the error code
2890  * @ownerItem: the owner as a schema object
2891  * @ownerElem: the owner as an element node
2892  * @name: the name of the attribute holding the QName
2893  * @refName: the referenced local name
2894  * @refURI: the referenced namespace URI
2895  * @message: optional message
2896  *
2897  * Used to report QName attribute values that failed to resolve
2898  * to schema components.
2899  */
2900 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)2901 xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
2902 			 xmlParserErrors error,
2903 			 xmlSchemaBasicItemPtr ownerItem,
2904 			 xmlNodePtr ownerElem,
2905 			 const char *name,
2906 			 const xmlChar *refName,
2907 			 const xmlChar *refURI,
2908 			 xmlSchemaTypeType refType,
2909 			 const char *refTypeStr)
2910 {
2911     xmlChar *des = NULL, *strA = NULL;
2912 
2913     xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2914     if (refTypeStr == NULL)
2915 	refTypeStr = (const char *) xmlSchemaItemTypeToStr(refType);
2916     xmlSchemaPErrExt(ctxt, ownerElem, error,
2917 	    NULL, NULL, NULL,
2918 	    "%s, attribute '%s': The QName value '%s' does not resolve to a(n) "
2919 	    "%s.\n", BAD_CAST des, BAD_CAST name,
2920 	    xmlSchemaFormatQName(&strA, refURI, refName),
2921 	    BAD_CAST refTypeStr, NULL);
2922     FREE_AND_NULL(des)
2923     FREE_AND_NULL(strA)
2924 }
2925 
2926 /**
2927  * xmlSchemaPCustomAttrErr:
2928  * @ctxt: the schema parser context
2929  * @error: the error code
2930  * @ownerDes: the designation of the owner
2931  * @ownerItem: the owner as a schema object
2932  * @attr: the illegal attribute node
2933  *
2934  * Reports an illegal attribute during the parse.
2935  */
2936 static void
xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlChar ** ownerDes,xmlSchemaBasicItemPtr ownerItem,xmlAttrPtr attr,const char * msg)2937 xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
2938 			xmlParserErrors error,
2939 			xmlChar **ownerDes,
2940 			xmlSchemaBasicItemPtr ownerItem,
2941 			xmlAttrPtr attr,
2942 			const char *msg)
2943 {
2944     xmlChar *des = NULL;
2945 
2946     if (ownerDes == NULL)
2947 	xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
2948     else if (*ownerDes == NULL) {
2949 	xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
2950 	des = *ownerDes;
2951     } else
2952 	des = *ownerDes;
2953     if (attr == NULL) {
2954 	xmlSchemaPErrExt(ctxt, NULL, error, NULL, NULL, NULL,
2955 	    "%s, attribute '%s': %s.\n",
2956 	    BAD_CAST des, (const xmlChar *) "Unknown",
2957 	    (const xmlChar *) msg, NULL, NULL);
2958     } else {
2959 	xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
2960 	    "%s, attribute '%s': %s.\n",
2961 	    BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
2962     }
2963     if (ownerDes == NULL)
2964 	FREE_AND_NULL(des);
2965 }
2966 
2967 /**
2968  * xmlSchemaPIllegalAttrErr:
2969  * @ctxt: the schema parser context
2970  * @error: the error code
2971  * @ownerItem: the attribute's owner item
2972  * @attr: the illegal attribute node
2973  *
2974  * Reports an illegal attribute during the parse.
2975  */
2976 static void
xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaBasicItemPtr ownerComp ATTRIBUTE_UNUSED,xmlAttrPtr attr)2977 xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
2978 			 xmlParserErrors error,
2979 			 xmlSchemaBasicItemPtr ownerComp ATTRIBUTE_UNUSED,
2980 			 xmlAttrPtr attr)
2981 {
2982     xmlChar *strA = NULL, *strB = NULL;
2983 
2984     xmlSchemaFormatNodeForError(&strA, ACTXT_CAST ctxt, attr->parent);
2985     xmlSchemaErr4(ACTXT_CAST ctxt, error, (xmlNodePtr) attr,
2986 	"%sThe attribute '%s' is not allowed.\n", BAD_CAST strA,
2987 	xmlSchemaFormatQNameNs(&strB, attr->ns, attr->name),
2988 	NULL, NULL);
2989     FREE_AND_NULL(strA);
2990     FREE_AND_NULL(strB);
2991 }
2992 
2993 /**
2994  * xmlSchemaPCustomErr:
2995  * @ctxt: the schema parser context
2996  * @error: the error code
2997  * @itemDes: the designation of the schema item
2998  * @item: the schema item
2999  * @itemElem: the node of the schema item
3000  * @message: the error message
3001  * @str1: an optional param for the error message
3002  * @str2: an optional param for the error message
3003  * @str3: an optional param for the error message
3004  *
3005  * Reports an error during parsing.
3006  */
3007 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)3008 xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
3009 		    xmlParserErrors error,
3010 		    xmlSchemaBasicItemPtr item,
3011 		    xmlNodePtr itemElem,
3012 		    const char *message,
3013 		    const xmlChar *str1,
3014 		    const xmlChar *str2,
3015 		    const xmlChar *str3)
3016 {
3017     xmlChar *des = NULL, *msg = NULL;
3018 
3019     xmlSchemaFormatItemForReport(&des, NULL, item, itemElem);
3020     msg = xmlStrdup(BAD_CAST "%s: ");
3021     msg = xmlStrcat(msg, (const xmlChar *) message);
3022     msg = xmlStrcat(msg, BAD_CAST ".\n");
3023     if ((itemElem == NULL) && (item != NULL))
3024 	itemElem = WXS_ITEM_NODE(item);
3025     xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
3026 	(const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
3027     FREE_AND_NULL(des);
3028     FREE_AND_NULL(msg);
3029 }
3030 
3031 /**
3032  * xmlSchemaPCustomErr:
3033  * @ctxt: the schema parser context
3034  * @error: the error code
3035  * @itemDes: the designation of the schema item
3036  * @item: the schema item
3037  * @itemElem: the node of the schema item
3038  * @message: the error message
3039  * @str1: the optional param for the error message
3040  *
3041  * Reports an error during parsing.
3042  */
3043 static void LIBXML_ATTR_FORMAT(5,0)
xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaBasicItemPtr item,xmlNodePtr itemElem,const char * message,const xmlChar * str1)3044 xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
3045 		    xmlParserErrors error,
3046 		    xmlSchemaBasicItemPtr item,
3047 		    xmlNodePtr itemElem,
3048 		    const char *message,
3049 		    const xmlChar *str1)
3050 {
3051     xmlSchemaPCustomErrExt(ctxt, error, item, itemElem, message,
3052 	str1, NULL, NULL);
3053 }
3054 
3055 /**
3056  * xmlSchemaPAttrUseErr:
3057  * @ctxt: the schema parser context
3058  * @error: the error code
3059  * @itemDes: the designation of the schema type
3060  * @item: the schema type
3061  * @itemElem: the node of the schema type
3062  * @attr: the invalid schema attribute
3063  * @message: the error message
3064  * @str1: the optional param for the error message
3065  *
3066  * Reports an attribute use error during parsing.
3067  */
3068 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)3069 xmlSchemaPAttrUseErr4(xmlSchemaParserCtxtPtr ctxt,
3070 		    xmlParserErrors error,
3071 		    xmlNodePtr node,
3072 		    xmlSchemaBasicItemPtr ownerItem,
3073 		    const xmlSchemaAttributeUsePtr attruse,
3074 		    const char *message,
3075 		    const xmlChar *str1, const xmlChar *str2,
3076 		    const xmlChar *str3,const xmlChar *str4)
3077 {
3078     xmlChar *str = NULL, *msg = NULL;
3079 
3080     xmlSchemaFormatItemForReport(&msg, NULL, ownerItem, NULL);
3081     msg = xmlStrcat(msg, BAD_CAST ", ");
3082     msg = xmlStrcat(msg,
3083 	BAD_CAST xmlSchemaFormatItemForReport(&str, NULL,
3084 	WXS_BASIC_CAST attruse, NULL));
3085     FREE_AND_NULL(str);
3086     msg = xmlStrcat(msg, BAD_CAST ": ");
3087     msg = xmlStrcat(msg, (const xmlChar *) message);
3088     msg = xmlStrcat(msg, BAD_CAST ".\n");
3089     xmlSchemaErr4(ACTXT_CAST ctxt, error, node,
3090 	(const char *) msg, str1, str2, str3, str4);
3091     xmlFree(msg);
3092 }
3093 
3094 /**
3095  * xmlSchemaPIllegalFacetAtomicErr:
3096  * @ctxt: the schema parser context
3097  * @error: the error code
3098  * @type: the schema type
3099  * @baseType: the base type of type
3100  * @facet: the illegal facet
3101  *
3102  * Reports an illegal facet for atomic simple types.
3103  */
3104 static void
xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaTypePtr type,xmlSchemaTypePtr baseType,xmlSchemaFacetPtr facet)3105 xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
3106 			  xmlParserErrors error,
3107 			  xmlSchemaTypePtr type,
3108 			  xmlSchemaTypePtr baseType,
3109 			  xmlSchemaFacetPtr facet)
3110 {
3111     xmlChar *des = NULL, *strT = NULL;
3112 
3113     xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type, type->node);
3114     xmlSchemaPErrExt(ctxt, type->node, error, NULL, NULL, NULL,
3115 	"%s: The facet '%s' is not allowed on types derived from the "
3116 	"type %s.\n",
3117 	BAD_CAST des, xmlSchemaFacetTypeToString(facet->type),
3118 	xmlSchemaFormatItemForReport(&strT, NULL, WXS_BASIC_CAST baseType, NULL),
3119 	NULL, NULL);
3120     FREE_AND_NULL(des);
3121     FREE_AND_NULL(strT);
3122 }
3123 
3124 /**
3125  * xmlSchemaPIllegalFacetListUnionErr:
3126  * @ctxt: the schema parser context
3127  * @error: the error code
3128  * @itemDes: the designation of the schema item involved
3129  * @item: the schema item involved
3130  * @facet: the illegal facet
3131  *
3132  * Reports an illegal facet for <list> and <union>.
3133  */
3134 static void
xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaTypePtr type,xmlSchemaFacetPtr facet)3135 xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
3136 			  xmlParserErrors error,
3137 			  xmlSchemaTypePtr type,
3138 			  xmlSchemaFacetPtr facet)
3139 {
3140     xmlChar *des = NULL;
3141 
3142     xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type,
3143 	type->node);
3144     xmlSchemaPErr(ctxt, type->node, error,
3145 	"%s: The facet '%s' is not allowed.\n",
3146 	BAD_CAST des, xmlSchemaFacetTypeToString(facet->type));
3147     FREE_AND_NULL(des);
3148 }
3149 
3150 /**
3151  * xmlSchemaPMutualExclAttrErr:
3152  * @ctxt: the schema validation context
3153  * @error: the error code
3154  * @elemDes: the designation of the parent element node
3155  * @attr: the bad attribute node
3156  * @type: the corresponding type of the attribute node
3157  *
3158  * Reports an illegal attribute.
3159  */
3160 static void
xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaBasicItemPtr ownerItem,xmlAttrPtr attr,const char * name1,const char * name2)3161 xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
3162 			 xmlParserErrors error,
3163 			 xmlSchemaBasicItemPtr ownerItem,
3164 			 xmlAttrPtr attr,
3165 			 const char *name1,
3166 			 const char *name2)
3167 {
3168     xmlChar *des = NULL;
3169 
3170     xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST ownerItem, attr->parent);
3171     xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
3172 	"%s: The attributes '%s' and '%s' are mutually exclusive.\n",
3173 	BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
3174     FREE_AND_NULL(des);
3175 }
3176 
3177 /**
3178  * xmlSchemaPSimpleTypeErr:
3179  * @ctxt:  the schema validation context
3180  * @error: the error code
3181  * @type: the type specifier
3182  * @ownerItem: the schema object if existent
3183  * @node: the validated node
3184  * @value: the validated value
3185  *
3186  * Reports a simple type validation error.
3187  * TODO: Should this report the value of an element as well?
3188  */
3189 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)3190 xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
3191 			xmlParserErrors error,
3192 			xmlSchemaBasicItemPtr ownerItem ATTRIBUTE_UNUSED,
3193 			xmlNodePtr node,
3194 			xmlSchemaTypePtr type,
3195 			const char *expected,
3196 			const xmlChar *value,
3197 			const char *message,
3198 			const xmlChar *str1,
3199 			const xmlChar *str2)
3200 {
3201     xmlChar *msg = NULL;
3202 
3203     xmlSchemaFormatNodeForError(&msg, ACTXT_CAST ctxt, node);
3204     if (message == NULL) {
3205 	/*
3206 	* Use default messages.
3207 	*/
3208 	if (type != NULL) {
3209 	    if (node->type == XML_ATTRIBUTE_NODE)
3210 		msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
3211 	    else
3212 		msg = xmlStrcat(msg, BAD_CAST "The character content is not a "
3213 		"valid value of ");
3214 	    if (! xmlSchemaIsGlobalItem(type))
3215 		msg = xmlStrcat(msg, BAD_CAST "the local ");
3216 	    else
3217 		msg = xmlStrcat(msg, BAD_CAST "the ");
3218 
3219 	    if (WXS_IS_ATOMIC(type))
3220 		msg = xmlStrcat(msg, BAD_CAST "atomic type");
3221 	    else if (WXS_IS_LIST(type))
3222 		msg = xmlStrcat(msg, BAD_CAST "list type");
3223 	    else if (WXS_IS_UNION(type))
3224 		msg = xmlStrcat(msg, BAD_CAST "union type");
3225 
3226 	    if (xmlSchemaIsGlobalItem(type)) {
3227 		xmlChar *str = NULL;
3228 		msg = xmlStrcat(msg, BAD_CAST " '");
3229 		if (type->builtInType != 0) {
3230 		    msg = xmlStrcat(msg, BAD_CAST "xs:");
3231 		    str = xmlStrdup(type->name);
3232 		} else {
3233 		    const xmlChar *qName = xmlSchemaFormatQName(&str, type->targetNamespace, type->name);
3234 		    if (!str)
3235 			str = xmlStrdup(qName);
3236 		}
3237 		msg = xmlStrcat(msg, xmlEscapeFormatString(&str));
3238 		msg = xmlStrcat(msg, BAD_CAST "'.");
3239 		FREE_AND_NULL(str);
3240 	    }
3241 	} else {
3242 	    if (node->type == XML_ATTRIBUTE_NODE)
3243 		msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not valid.");
3244 	    else
3245 		msg = xmlStrcat(msg, BAD_CAST "The character content is not "
3246 		"valid.");
3247 	}
3248 	if (expected) {
3249 	    xmlChar *expectedEscaped = xmlCharStrdup(expected);
3250 	    msg = xmlStrcat(msg, BAD_CAST " Expected is '");
3251 	    msg = xmlStrcat(msg, xmlEscapeFormatString(&expectedEscaped));
3252 	    FREE_AND_NULL(expectedEscaped);
3253 	    msg = xmlStrcat(msg, BAD_CAST "'.\n");
3254 	} else
3255 	    msg = xmlStrcat(msg, BAD_CAST "\n");
3256 	if (node->type == XML_ATTRIBUTE_NODE)
3257 	    xmlSchemaPErr(ctxt, node, error, (const char *) msg, value, NULL);
3258 	else
3259 	    xmlSchemaPErr(ctxt, node, error, (const char *) msg, NULL, NULL);
3260     } else {
3261 	msg = xmlStrcat(msg, BAD_CAST message);
3262 	msg = xmlStrcat(msg, BAD_CAST ".\n");
3263 	xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
3264 	     (const char*) msg, str1, str2, NULL, NULL, NULL);
3265     }
3266     /* Cleanup. */
3267     FREE_AND_NULL(msg)
3268 }
3269 
3270 /**
3271  * xmlSchemaPContentErr:
3272  * @ctxt: the schema parser context
3273  * @error: the error code
3274  * @ownerItem: the owner item of the holder of the content
3275  * @ownerElem: the node of the holder of the content
3276  * @child: the invalid child node
3277  * @message: the optional error message
3278  * @content: the optional string describing the correct content
3279  *
3280  * Reports an error concerning the content of a schema element.
3281  */
3282 static void
xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaBasicItemPtr ownerItem,xmlNodePtr ownerElem,xmlNodePtr child,const char * message,const char * content)3283 xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
3284 		     xmlParserErrors error,
3285 		     xmlSchemaBasicItemPtr ownerItem,
3286 		     xmlNodePtr ownerElem,
3287 		     xmlNodePtr child,
3288 		     const char *message,
3289 		     const char *content)
3290 {
3291     xmlChar *des = NULL;
3292 
3293     xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
3294     if (message != NULL)
3295 	xmlSchemaPErr2(ctxt, ownerElem, child, error,
3296 	    "%s: %s.\n",
3297 	    BAD_CAST des, BAD_CAST message);
3298     else {
3299 	if (content != NULL) {
3300 	    xmlSchemaPErr2(ctxt, ownerElem, child, error,
3301 		"%s: The content is not valid. Expected is %s.\n",
3302 		BAD_CAST des, BAD_CAST content);
3303 	} else {
3304 	    xmlSchemaPErr2(ctxt, ownerElem, child, error,
3305 		"%s: The content is not valid.\n",
3306 		BAD_CAST des, NULL);
3307 	}
3308     }
3309     FREE_AND_NULL(des)
3310 }
3311 
3312 /************************************************************************
3313  *									*
3314  *			Streamable error functions                      *
3315  *									*
3316  ************************************************************************/
3317 
3318 
3319 
3320 
3321 /************************************************************************
3322  *									*
3323  *			Validation helper functions			*
3324  *									*
3325  ************************************************************************/
3326 
3327 
3328 /************************************************************************
3329  *									*
3330  *			Allocation functions				*
3331  *									*
3332  ************************************************************************/
3333 
3334 /**
3335  * xmlSchemaNewSchemaForParserCtxt:
3336  * @ctxt:  a schema validation context
3337  *
3338  * Allocate a new Schema structure.
3339  *
3340  * Returns the newly allocated structure or NULL in case or error
3341  */
3342 static xmlSchemaPtr
xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)3343 xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
3344 {
3345     xmlSchemaPtr ret;
3346 
3347     ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
3348     if (ret == NULL) {
3349         xmlSchemaPErrMemory(ctxt);
3350         return (NULL);
3351     }
3352     memset(ret, 0, sizeof(xmlSchema));
3353     ret->dict = ctxt->dict;
3354     xmlDictReference(ret->dict);
3355 
3356     return (ret);
3357 }
3358 
3359 /**
3360  * xmlSchemaNewFacet:
3361  *
3362  * Allocate a new Facet structure.
3363  *
3364  * Returns the newly allocated structure or NULL in case or error
3365  */
3366 xmlSchemaFacetPtr
xmlSchemaNewFacet(void)3367 xmlSchemaNewFacet(void)
3368 {
3369     xmlSchemaFacetPtr ret;
3370 
3371     ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
3372     if (ret == NULL) {
3373         return (NULL);
3374     }
3375     memset(ret, 0, sizeof(xmlSchemaFacet));
3376 
3377     return (ret);
3378 }
3379 
3380 /**
3381  * xmlSchemaNewAnnot:
3382  * @ctxt:  a schema validation context
3383  * @node:  a node
3384  *
3385  * Allocate a new annotation structure.
3386  *
3387  * Returns the newly allocated structure or NULL in case or error
3388  */
3389 static xmlSchemaAnnotPtr
xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node)3390 xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3391 {
3392     xmlSchemaAnnotPtr ret;
3393 
3394     ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
3395     if (ret == NULL) {
3396         xmlSchemaPErrMemory(ctxt);
3397         return (NULL);
3398     }
3399     memset(ret, 0, sizeof(xmlSchemaAnnot));
3400     ret->content = node;
3401     return (ret);
3402 }
3403 
3404 static xmlSchemaItemListPtr
xmlSchemaItemListCreate(void)3405 xmlSchemaItemListCreate(void)
3406 {
3407     xmlSchemaItemListPtr ret;
3408 
3409     ret = xmlMalloc(sizeof(xmlSchemaItemList));
3410     if (ret == NULL) {
3411 	xmlSchemaPErrMemory(NULL);
3412 	return (NULL);
3413     }
3414     memset(ret, 0, sizeof(xmlSchemaItemList));
3415     return (ret);
3416 }
3417 
3418 static void
xmlSchemaItemListClear(xmlSchemaItemListPtr list)3419 xmlSchemaItemListClear(xmlSchemaItemListPtr list)
3420 {
3421     if (list->items != NULL) {
3422 	xmlFree(list->items);
3423 	list->items = NULL;
3424     }
3425     list->nbItems = 0;
3426     list->sizeItems = 0;
3427 }
3428 
3429 static int
xmlSchemaItemListAdd(xmlSchemaItemListPtr list,void * item)3430 xmlSchemaItemListAdd(xmlSchemaItemListPtr list, void *item)
3431 {
3432     if (list->sizeItems <= list->nbItems) {
3433         void **tmp;
3434         size_t newSize = list->sizeItems == 0 ? 20 : list->sizeItems * 2;
3435 
3436 	tmp = (void **) xmlRealloc(list->items, newSize * sizeof(void *));
3437 	if (tmp == NULL) {
3438 	    xmlSchemaPErrMemory(NULL);
3439 	    return(-1);
3440 	}
3441         list->items = tmp;
3442 	list->sizeItems = newSize;
3443     }
3444     list->items[list->nbItems++] = item;
3445     return(0);
3446 }
3447 
3448 static int
xmlSchemaItemListAddSize(xmlSchemaItemListPtr list,int initialSize,void * item)3449 xmlSchemaItemListAddSize(xmlSchemaItemListPtr list,
3450 			 int initialSize,
3451 			 void *item)
3452 {
3453     if (list->items == NULL) {
3454 	if (initialSize <= 0)
3455 	    initialSize = 1;
3456 	list->items = (void **) xmlMalloc(
3457 	    initialSize * sizeof(void *));
3458 	if (list->items == NULL) {
3459 	    xmlSchemaPErrMemory(NULL);
3460 	    return(-1);
3461 	}
3462 	list->sizeItems = initialSize;
3463     } else if (list->sizeItems <= list->nbItems) {
3464         void **tmp;
3465 
3466 	list->sizeItems *= 2;
3467 	tmp = (void **) xmlRealloc(list->items,
3468 	    list->sizeItems * sizeof(void *));
3469 	if (tmp == NULL) {
3470 	    xmlSchemaPErrMemory(NULL);
3471 	    list->sizeItems /= 2;
3472 	    return(-1);
3473 	}
3474         list->items = tmp;
3475     }
3476     list->items[list->nbItems++] = item;
3477     return(0);
3478 }
3479 
3480 static int
xmlSchemaItemListInsert(xmlSchemaItemListPtr list,void * item,int idx)3481 xmlSchemaItemListInsert(xmlSchemaItemListPtr list, void *item, int idx)
3482 {
3483     if (list->sizeItems <= list->nbItems) {
3484         void **tmp;
3485         size_t newSize = list->sizeItems == 0 ? 20 : list->sizeItems * 2;
3486 
3487 	tmp = (void **) xmlRealloc(list->items, newSize * sizeof(void *));
3488 	if (tmp == NULL) {
3489 	    xmlSchemaPErrMemory(NULL);
3490 	    return(-1);
3491 	}
3492         list->items = tmp;
3493 	list->sizeItems = newSize;
3494     }
3495     /*
3496     * Just append if the index is greater/equal than the item count.
3497     */
3498     if (idx >= list->nbItems) {
3499 	list->items[list->nbItems++] = item;
3500     } else {
3501 	int i;
3502 	for (i = list->nbItems; i > idx; i--)
3503 	    list->items[i] = list->items[i-1];
3504 	list->items[idx] = item;
3505 	list->nbItems++;
3506     }
3507     return(0);
3508 }
3509 
3510 #if 0 /* enable if ever needed */
3511 static int
3512 xmlSchemaItemListInsertSize(xmlSchemaItemListPtr list,
3513 			    int initialSize,
3514 			    void *item,
3515 			    int idx)
3516 {
3517     if (list->items == NULL) {
3518 	if (initialSize <= 0)
3519 	    initialSize = 1;
3520 	list->items = (void **) xmlMalloc(
3521 	    initialSize * sizeof(void *));
3522 	if (list->items == NULL) {
3523 	    xmlSchemaPErrMemory(NULL);
3524 	    return(-1);
3525 	}
3526 	list->sizeItems = initialSize;
3527     } else if (list->sizeItems <= list->nbItems) {
3528 	list->sizeItems *= 2;
3529 	list->items = (void **) xmlRealloc(list->items,
3530 	    list->sizeItems * sizeof(void *));
3531 	if (list->items == NULL) {
3532 	    xmlSchemaPErrMemory(NULL);
3533 	    list->sizeItems = 0;
3534 	    return(-1);
3535 	}
3536     }
3537     /*
3538     * Just append if the index is greater/equal than the item count.
3539     */
3540     if (idx >= list->nbItems) {
3541 	list->items[list->nbItems++] = item;
3542     } else {
3543 	int i;
3544 	for (i = list->nbItems; i > idx; i--)
3545 	    list->items[i] = list->items[i-1];
3546 	list->items[idx] = item;
3547 	list->nbItems++;
3548     }
3549     return(0);
3550 }
3551 #endif
3552 
3553 static int
xmlSchemaItemListRemove(xmlSchemaItemListPtr list,int idx)3554 xmlSchemaItemListRemove(xmlSchemaItemListPtr list, int idx)
3555 {
3556     int i;
3557     if ((list->items == NULL) || (idx >= list->nbItems))
3558 	return(-1);
3559 
3560     if (list->nbItems == 1) {
3561 	/* TODO: Really free the list? */
3562 	xmlFree(list->items);
3563 	list->items = NULL;
3564 	list->nbItems = 0;
3565 	list->sizeItems = 0;
3566     } else if (list->nbItems -1 == idx) {
3567 	list->nbItems--;
3568     } else {
3569 	for (i = idx; i < list->nbItems -1; i++)
3570 	    list->items[i] = list->items[i+1];
3571 	list->nbItems--;
3572     }
3573     return(0);
3574 }
3575 
3576 /**
3577  * xmlSchemaItemListFree:
3578  * @annot:  a schema type structure
3579  *
3580  * Deallocate a annotation structure
3581  */
3582 static void
xmlSchemaItemListFree(xmlSchemaItemListPtr list)3583 xmlSchemaItemListFree(xmlSchemaItemListPtr list)
3584 {
3585     if (list == NULL)
3586 	return;
3587     if (list->items != NULL)
3588 	xmlFree(list->items);
3589     xmlFree(list);
3590 }
3591 
3592 static void
xmlSchemaBucketFree(xmlSchemaBucketPtr bucket)3593 xmlSchemaBucketFree(xmlSchemaBucketPtr bucket)
3594 {
3595     if (bucket == NULL)
3596 	return;
3597     if (bucket->globals != NULL) {
3598 	xmlSchemaComponentListFree(bucket->globals);
3599 	xmlSchemaItemListFree(bucket->globals);
3600     }
3601     if (bucket->locals != NULL) {
3602 	xmlSchemaComponentListFree(bucket->locals);
3603 	xmlSchemaItemListFree(bucket->locals);
3604     }
3605     if (bucket->relations != NULL) {
3606 	xmlSchemaSchemaRelationPtr prev, cur = bucket->relations;
3607 	do {
3608 	    prev = cur;
3609 	    cur = cur->next;
3610 	    xmlFree(prev);
3611 	} while (cur != NULL);
3612     }
3613     if ((! bucket->preserveDoc) && (bucket->doc != NULL)) {
3614 	xmlFreeDoc(bucket->doc);
3615     }
3616     if (bucket->type == XML_SCHEMA_SCHEMA_IMPORT) {
3617 	if (WXS_IMPBUCKET(bucket)->schema != NULL)
3618 	    xmlSchemaFree(WXS_IMPBUCKET(bucket)->schema);
3619     }
3620     xmlFree(bucket);
3621 }
3622 
3623 static void
xmlSchemaBucketFreeEntry(void * bucket,const xmlChar * name ATTRIBUTE_UNUSED)3624 xmlSchemaBucketFreeEntry(void *bucket, const xmlChar *name ATTRIBUTE_UNUSED)
3625 {
3626     xmlSchemaBucketFree((xmlSchemaBucketPtr) bucket);
3627 }
3628 
3629 static xmlSchemaBucketPtr
xmlSchemaBucketCreate(xmlSchemaParserCtxtPtr pctxt,int type,const xmlChar * targetNamespace)3630 xmlSchemaBucketCreate(xmlSchemaParserCtxtPtr pctxt,
3631 			 int type, const xmlChar *targetNamespace)
3632 {
3633     xmlSchemaBucketPtr ret;
3634     int size;
3635     xmlSchemaPtr mainSchema;
3636 
3637     if (WXS_CONSTRUCTOR(pctxt)->mainSchema == NULL) {
3638 	PERROR_INT("xmlSchemaBucketCreate",
3639 	    "no main schema on constructor");
3640 	return(NULL);
3641     }
3642     mainSchema = WXS_CONSTRUCTOR(pctxt)->mainSchema;
3643     /* Create the schema bucket. */
3644     if (WXS_IS_BUCKET_INCREDEF(type))
3645 	size = sizeof(xmlSchemaInclude);
3646     else
3647 	size = sizeof(xmlSchemaImport);
3648     ret = (xmlSchemaBucketPtr) xmlMalloc(size);
3649     if (ret == NULL) {
3650 	xmlSchemaPErrMemory(NULL);
3651 	return(NULL);
3652     }
3653     memset(ret, 0, size);
3654     ret->targetNamespace = targetNamespace;
3655     ret->type = type;
3656     ret->globals = xmlSchemaItemListCreate();
3657     if (ret->globals == NULL) {
3658 	xmlSchemaBucketFree(ret);
3659 	return(NULL);
3660     }
3661     ret->locals = xmlSchemaItemListCreate();
3662     if (ret->locals == NULL) {
3663 	xmlSchemaBucketFree(ret);
3664 	return(NULL);
3665     }
3666     /*
3667     * The following will assure that only the first bucket is marked as
3668     * XML_SCHEMA_SCHEMA_MAIN and it points to the *main* schema.
3669     * For each following import buckets an xmlSchema will be created.
3670     * An xmlSchema will be created for every distinct targetNamespace.
3671     * We assign the targetNamespace to the schemata here.
3672     */
3673     if (! WXS_HAS_BUCKETS(pctxt)) {
3674 	if (WXS_IS_BUCKET_INCREDEF(type)) {
3675 	    PERROR_INT("xmlSchemaBucketCreate",
3676 		"first bucket but it's an include or redefine");
3677 	    xmlSchemaBucketFree(ret);
3678 	    return(NULL);
3679 	}
3680 	/* Force the type to be XML_SCHEMA_SCHEMA_MAIN. */
3681 	ret->type = XML_SCHEMA_SCHEMA_MAIN;
3682 	/* Point to the *main* schema. */
3683 	WXS_CONSTRUCTOR(pctxt)->mainBucket = ret;
3684 	WXS_IMPBUCKET(ret)->schema = mainSchema;
3685 	/*
3686 	* Ensure that the main schema gets a targetNamespace.
3687 	*/
3688 	mainSchema->targetNamespace = targetNamespace;
3689     } else {
3690 	if (type == XML_SCHEMA_SCHEMA_MAIN) {
3691 	    PERROR_INT("xmlSchemaBucketCreate",
3692 		"main bucket but it's not the first one");
3693 	    xmlSchemaBucketFree(ret);
3694 	    return(NULL);
3695 	} else if (type == XML_SCHEMA_SCHEMA_IMPORT) {
3696 	    /*
3697 	    * Create a schema for imports and assign the
3698 	    * targetNamespace.
3699 	    */
3700 	    WXS_IMPBUCKET(ret)->schema = xmlSchemaNewSchema(pctxt);
3701 	    if (WXS_IMPBUCKET(ret)->schema == NULL) {
3702 		xmlSchemaBucketFree(ret);
3703 		return(NULL);
3704 	    }
3705 	    WXS_IMPBUCKET(ret)->schema->targetNamespace = targetNamespace;
3706 	}
3707     }
3708     if (WXS_IS_BUCKET_IMPMAIN(type)) {
3709 	int res;
3710 	/*
3711 	* Imports go into the "schemasImports" slot of the main *schema*.
3712 	* Note that we create an import entry for the main schema as well; i.e.,
3713 	* even if there's only one schema, we'll get an import.
3714 	*/
3715 	if (mainSchema->schemasImports == NULL) {
3716 	    mainSchema->schemasImports = xmlHashCreateDict(5,
3717 		WXS_CONSTRUCTOR(pctxt)->dict);
3718 	    if (mainSchema->schemasImports == NULL) {
3719 		xmlSchemaBucketFree(ret);
3720 		return(NULL);
3721 	    }
3722 	}
3723 	if (targetNamespace == NULL)
3724 	    res = xmlHashAddEntry(mainSchema->schemasImports,
3725 		XML_SCHEMAS_NO_NAMESPACE, ret);
3726 	else
3727 	    res = xmlHashAddEntry(mainSchema->schemasImports,
3728 		targetNamespace, ret);
3729 	if (res != 0) {
3730 	    PERROR_INT("xmlSchemaBucketCreate",
3731 		"failed to add the schema bucket to the hash");
3732 	    xmlSchemaBucketFree(ret);
3733 	    return(NULL);
3734 	}
3735     } else {
3736 	/* Set the @ownerImport of an include bucket. */
3737 	if (WXS_IS_BUCKET_IMPMAIN(WXS_CONSTRUCTOR(pctxt)->bucket->type))
3738 	    WXS_INCBUCKET(ret)->ownerImport =
3739 		WXS_IMPBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket);
3740 	else
3741 	    WXS_INCBUCKET(ret)->ownerImport =
3742 		WXS_INCBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket)->ownerImport;
3743 
3744 	/* Includes got into the "includes" slot of the *main* schema. */
3745 	if (mainSchema->includes == NULL) {
3746 	    mainSchema->includes = xmlSchemaItemListCreate();
3747 	    if (mainSchema->includes == NULL) {
3748 		xmlSchemaBucketFree(ret);
3749 		return(NULL);
3750 	    }
3751 	}
3752 	if (xmlSchemaItemListAdd(mainSchema->includes, ret) < 0) {
3753 	    xmlSchemaBucketFree(ret);
3754 	    return(NULL);
3755         }
3756     }
3757     /*
3758     * Add to list of all buckets; this is used for lookup
3759     * during schema construction time only.
3760     */
3761     if (xmlSchemaItemListAdd(WXS_CONSTRUCTOR(pctxt)->buckets, ret) == -1)
3762 	return(NULL);
3763     return(ret);
3764 }
3765 
3766 static int
xmlSchemaAddItemSize(xmlSchemaItemListPtr * list,int initialSize,void * item)3767 xmlSchemaAddItemSize(xmlSchemaItemListPtr *list, int initialSize, void *item)
3768 {
3769     if (*list == NULL) {
3770 	*list = xmlSchemaItemListCreate();
3771 	if (*list == NULL)
3772 	    return(-1);
3773     }
3774     return(xmlSchemaItemListAddSize(*list, initialSize, item));
3775 }
3776 
3777 /**
3778  * xmlSchemaFreeAnnot:
3779  * @annot:  a schema type structure
3780  *
3781  * Deallocate a annotation structure
3782  */
3783 static void
xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)3784 xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
3785 {
3786     if (annot == NULL)
3787         return;
3788     if (annot->next == NULL) {
3789 	xmlFree(annot);
3790     } else {
3791 	xmlSchemaAnnotPtr prev;
3792 
3793 	do {
3794 	    prev = annot;
3795 	    annot = annot->next;
3796 	    xmlFree(prev);
3797 	} while (annot != NULL);
3798     }
3799 }
3800 
3801 /**
3802  * xmlSchemaFreeNotation:
3803  * @schema:  a schema notation structure
3804  *
3805  * Deallocate a Schema Notation structure.
3806  */
3807 static void
xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)3808 xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
3809 {
3810     if (nota == NULL)
3811         return;
3812     if (nota->annot != NULL)
3813 	xmlSchemaFreeAnnot(nota->annot);
3814     xmlFree(nota);
3815 }
3816 
3817 /**
3818  * xmlSchemaFreeAttribute:
3819  * @attr:  an attribute declaration
3820  *
3821  * Deallocates an attribute declaration structure.
3822  */
3823 static void
xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)3824 xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
3825 {
3826     if (attr == NULL)
3827         return;
3828     if (attr->annot != NULL)
3829 	xmlSchemaFreeAnnot(attr->annot);
3830     if (attr->defVal != NULL)
3831 	xmlSchemaFreeValue(attr->defVal);
3832     xmlFree(attr);
3833 }
3834 
3835 /**
3836  * xmlSchemaFreeAttributeUse:
3837  * @use:  an attribute use
3838  *
3839  * Deallocates an attribute use structure.
3840  */
3841 static void
xmlSchemaFreeAttributeUse(xmlSchemaAttributeUsePtr use)3842 xmlSchemaFreeAttributeUse(xmlSchemaAttributeUsePtr use)
3843 {
3844     if (use == NULL)
3845         return;
3846     if (use->annot != NULL)
3847 	xmlSchemaFreeAnnot(use->annot);
3848     if (use->defVal != NULL)
3849 	xmlSchemaFreeValue(use->defVal);
3850     xmlFree(use);
3851 }
3852 
3853 /**
3854  * xmlSchemaFreeAttributeUseProhib:
3855  * @prohib:  an attribute use prohibition
3856  *
3857  * Deallocates an attribute use structure.
3858  */
3859 static void
xmlSchemaFreeAttributeUseProhib(xmlSchemaAttributeUseProhibPtr prohib)3860 xmlSchemaFreeAttributeUseProhib(xmlSchemaAttributeUseProhibPtr prohib)
3861 {
3862     if (prohib == NULL)
3863         return;
3864     xmlFree(prohib);
3865 }
3866 
3867 /**
3868  * xmlSchemaFreeWildcardNsSet:
3869  * set:  a schema wildcard namespace
3870  *
3871  * Deallocates a list of wildcard constraint structures.
3872  */
3873 static void
xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)3874 xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
3875 {
3876     xmlSchemaWildcardNsPtr next;
3877 
3878     while (set != NULL) {
3879 	next = set->next;
3880 	xmlFree(set);
3881 	set = next;
3882     }
3883 }
3884 
3885 /**
3886  * xmlSchemaFreeWildcard:
3887  * @wildcard:  a wildcard structure
3888  *
3889  * Deallocates a wildcard structure.
3890  */
3891 void
xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)3892 xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
3893 {
3894     if (wildcard == NULL)
3895         return;
3896     if (wildcard->annot != NULL)
3897         xmlSchemaFreeAnnot(wildcard->annot);
3898     if (wildcard->nsSet != NULL)
3899 	xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
3900     if (wildcard->negNsSet != NULL)
3901 	xmlFree(wildcard->negNsSet);
3902     xmlFree(wildcard);
3903 }
3904 
3905 /**
3906  * xmlSchemaFreeAttributeGroup:
3907  * @schema:  a schema attribute group structure
3908  *
3909  * Deallocate a Schema Attribute Group structure.
3910  */
3911 static void
xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attrGr)3912 xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attrGr)
3913 {
3914     if (attrGr == NULL)
3915         return;
3916     if (attrGr->annot != NULL)
3917         xmlSchemaFreeAnnot(attrGr->annot);
3918     if (attrGr->attrUses != NULL)
3919 	xmlSchemaItemListFree(WXS_LIST_CAST attrGr->attrUses);
3920     xmlFree(attrGr);
3921 }
3922 
3923 /**
3924  * xmlSchemaFreeQNameRef:
3925  * @item: a QName reference structure
3926  *
3927  * Deallocatea a QName reference structure.
3928  */
3929 static void
xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item)3930 xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item)
3931 {
3932     xmlFree(item);
3933 }
3934 
3935 /**
3936  * xmlSchemaFreeTypeLinkList:
3937  * @alink: a type link
3938  *
3939  * Deallocate a list of types.
3940  */
3941 static void
xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)3942 xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
3943 {
3944     xmlSchemaTypeLinkPtr next;
3945 
3946     while (link != NULL) {
3947 	next = link->next;
3948 	xmlFree(link);
3949 	link = next;
3950     }
3951 }
3952 
3953 static void
xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)3954 xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
3955 {
3956     xmlSchemaIDCStateObjPtr next;
3957     while (sto != NULL) {
3958 	next = sto->next;
3959 	if (sto->history != NULL)
3960 	    xmlFree(sto->history);
3961 	if (sto->xpathCtxt != NULL)
3962 	    xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
3963 	xmlFree(sto);
3964 	sto = next;
3965     }
3966 }
3967 
3968 /**
3969  * xmlSchemaFreeIDC:
3970  * @idc: a identity-constraint definition
3971  *
3972  * Deallocates an identity-constraint definition.
3973  */
3974 static void
xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)3975 xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)
3976 {
3977     xmlSchemaIDCSelectPtr cur, prev;
3978 
3979     if (idcDef == NULL)
3980 	return;
3981     if (idcDef->annot != NULL)
3982         xmlSchemaFreeAnnot(idcDef->annot);
3983     /* Selector */
3984     if (idcDef->selector != NULL) {
3985 	if (idcDef->selector->xpathComp != NULL)
3986 	    xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp);
3987 	xmlFree(idcDef->selector);
3988     }
3989     /* Fields */
3990     if (idcDef->fields != NULL) {
3991 	cur = idcDef->fields;
3992 	do {
3993 	    prev = cur;
3994 	    cur = cur->next;
3995 	    if (prev->xpathComp != NULL)
3996 		xmlFreePattern((xmlPatternPtr) prev->xpathComp);
3997 	    xmlFree(prev);
3998 	} while (cur != NULL);
3999     }
4000     xmlFree(idcDef);
4001 }
4002 
4003 /**
4004  * xmlSchemaFreeElement:
4005  * @schema:  a schema element structure
4006  *
4007  * Deallocate a Schema Element structure.
4008  */
4009 static void
xmlSchemaFreeElement(xmlSchemaElementPtr elem)4010 xmlSchemaFreeElement(xmlSchemaElementPtr elem)
4011 {
4012     if (elem == NULL)
4013         return;
4014     if (elem->annot != NULL)
4015         xmlSchemaFreeAnnot(elem->annot);
4016     if (elem->contModel != NULL)
4017         xmlRegFreeRegexp(elem->contModel);
4018     if (elem->defVal != NULL)
4019 	xmlSchemaFreeValue(elem->defVal);
4020     xmlFree(elem);
4021 }
4022 
4023 /**
4024  * xmlSchemaFreeFacet:
4025  * @facet:  a schema facet structure
4026  *
4027  * Deallocate a Schema Facet structure.
4028  */
4029 void
xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)4030 xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
4031 {
4032     if (facet == NULL)
4033         return;
4034     if (facet->val != NULL)
4035         xmlSchemaFreeValue(facet->val);
4036     if (facet->regexp != NULL)
4037         xmlRegFreeRegexp(facet->regexp);
4038     if (facet->annot != NULL)
4039         xmlSchemaFreeAnnot(facet->annot);
4040     xmlFree(facet);
4041 }
4042 
4043 /**
4044  * xmlSchemaFreeType:
4045  * @type:  a schema type structure
4046  *
4047  * Deallocate a Schema Type structure.
4048  */
4049 void
xmlSchemaFreeType(xmlSchemaTypePtr type)4050 xmlSchemaFreeType(xmlSchemaTypePtr type)
4051 {
4052     if (type == NULL)
4053         return;
4054     if (type->annot != NULL)
4055         xmlSchemaFreeAnnot(type->annot);
4056     if (type->facets != NULL) {
4057         xmlSchemaFacetPtr facet, next;
4058 
4059         facet = type->facets;
4060         while (facet != NULL) {
4061             next = facet->next;
4062             xmlSchemaFreeFacet(facet);
4063             facet = next;
4064         }
4065     }
4066     if (type->attrUses != NULL)
4067 	xmlSchemaItemListFree((xmlSchemaItemListPtr) type->attrUses);
4068     if (type->memberTypes != NULL)
4069 	xmlSchemaFreeTypeLinkList(type->memberTypes);
4070     if (type->facetSet != NULL) {
4071 	xmlSchemaFacetLinkPtr next, link;
4072 
4073 	link = type->facetSet;
4074 	do {
4075 	    next = link->next;
4076 	    xmlFree(link);
4077 	    link = next;
4078 	} while (link != NULL);
4079     }
4080     if (type->contModel != NULL)
4081         xmlRegFreeRegexp(type->contModel);
4082     xmlFree(type);
4083 }
4084 
4085 /**
4086  * xmlSchemaFreeModelGroupDef:
4087  * @item:  a schema model group definition
4088  *
4089  * Deallocates a schema model group definition.
4090  */
4091 static void
xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item)4092 xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item)
4093 {
4094     if (item->annot != NULL)
4095 	xmlSchemaFreeAnnot(item->annot);
4096     xmlFree(item);
4097 }
4098 
4099 /**
4100  * xmlSchemaFreeModelGroup:
4101  * @item:  a schema model group
4102  *
4103  * Deallocates a schema model group structure.
4104  */
4105 static void
xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item)4106 xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item)
4107 {
4108     if (item->annot != NULL)
4109 	xmlSchemaFreeAnnot(item->annot);
4110     xmlFree(item);
4111 }
4112 
4113 static void
xmlSchemaComponentListFree(xmlSchemaItemListPtr list)4114 xmlSchemaComponentListFree(xmlSchemaItemListPtr list)
4115 {
4116     if ((list == NULL) || (list->nbItems == 0))
4117 	return;
4118     {
4119 	xmlSchemaTreeItemPtr item;
4120 	xmlSchemaTreeItemPtr *items = (xmlSchemaTreeItemPtr *) list->items;
4121 	int i;
4122 
4123 	for (i = 0; i < list->nbItems; i++) {
4124 	    item = items[i];
4125 	    if (item == NULL)
4126 		continue;
4127 	    switch (item->type) {
4128 		case XML_SCHEMA_TYPE_SIMPLE:
4129 		case XML_SCHEMA_TYPE_COMPLEX:
4130 		    xmlSchemaFreeType((xmlSchemaTypePtr) item);
4131 		    break;
4132 		case XML_SCHEMA_TYPE_ATTRIBUTE:
4133 		    xmlSchemaFreeAttribute((xmlSchemaAttributePtr) item);
4134 		    break;
4135 		case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
4136 		    xmlSchemaFreeAttributeUse((xmlSchemaAttributeUsePtr) item);
4137 		    break;
4138 		case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
4139 		    xmlSchemaFreeAttributeUseProhib(
4140 			(xmlSchemaAttributeUseProhibPtr) item);
4141 		    break;
4142 		case XML_SCHEMA_TYPE_ELEMENT:
4143 		    xmlSchemaFreeElement((xmlSchemaElementPtr) item);
4144 		    break;
4145 		case XML_SCHEMA_TYPE_PARTICLE:
4146 		    if (item->annot != NULL)
4147 			xmlSchemaFreeAnnot(item->annot);
4148 		    xmlFree(item);
4149 		    break;
4150 		case XML_SCHEMA_TYPE_SEQUENCE:
4151 		case XML_SCHEMA_TYPE_CHOICE:
4152 		case XML_SCHEMA_TYPE_ALL:
4153 		    xmlSchemaFreeModelGroup((xmlSchemaModelGroupPtr) item);
4154 		    break;
4155 		case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
4156 		    xmlSchemaFreeAttributeGroup(
4157 			(xmlSchemaAttributeGroupPtr) item);
4158 		    break;
4159 		case XML_SCHEMA_TYPE_GROUP:
4160 		    xmlSchemaFreeModelGroupDef(
4161 			(xmlSchemaModelGroupDefPtr) item);
4162 		    break;
4163 		case XML_SCHEMA_TYPE_ANY:
4164 		case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
4165 		    xmlSchemaFreeWildcard((xmlSchemaWildcardPtr) item);
4166 		    break;
4167 		case XML_SCHEMA_TYPE_IDC_KEY:
4168 		case XML_SCHEMA_TYPE_IDC_UNIQUE:
4169 		case XML_SCHEMA_TYPE_IDC_KEYREF:
4170 		    xmlSchemaFreeIDC((xmlSchemaIDCPtr) item);
4171 		    break;
4172 		case XML_SCHEMA_TYPE_NOTATION:
4173 		    xmlSchemaFreeNotation((xmlSchemaNotationPtr) item);
4174 		    break;
4175 		case XML_SCHEMA_EXTRA_QNAMEREF:
4176 		    xmlSchemaFreeQNameRef((xmlSchemaQNameRefPtr) item);
4177 		    break;
4178 		default:
4179 		    /* TODO: This should never be hit. */
4180 		    break;
4181 	    }
4182 	}
4183 	list->nbItems = 0;
4184     }
4185 }
4186 
4187 /**
4188  * xmlSchemaFree:
4189  * @schema:  a schema structure
4190  *
4191  * Deallocate a Schema structure.
4192  */
4193 void
xmlSchemaFree(xmlSchemaPtr schema)4194 xmlSchemaFree(xmlSchemaPtr schema)
4195 {
4196     if (schema == NULL)
4197         return;
4198     /*
4199     * Note that those slots are not responsible for freeing
4200     * schema components anymore; this will now be done by
4201     * the schema buckets.
4202     */
4203     if (schema->notaDecl != NULL)
4204         xmlHashFree(schema->notaDecl, NULL);
4205     if (schema->attrDecl != NULL)
4206         xmlHashFree(schema->attrDecl, NULL);
4207     if (schema->attrgrpDecl != NULL)
4208         xmlHashFree(schema->attrgrpDecl, NULL);
4209     if (schema->elemDecl != NULL)
4210         xmlHashFree(schema->elemDecl, NULL);
4211     if (schema->typeDecl != NULL)
4212         xmlHashFree(schema->typeDecl, NULL);
4213     if (schema->groupDecl != NULL)
4214         xmlHashFree(schema->groupDecl, NULL);
4215     if (schema->idcDef != NULL)
4216         xmlHashFree(schema->idcDef, NULL);
4217 
4218     if (schema->schemasImports != NULL)
4219 	xmlHashFree(schema->schemasImports, xmlSchemaBucketFreeEntry);
4220     if (schema->includes != NULL) {
4221 	xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) schema->includes;
4222 	int i;
4223 	for (i = 0; i < list->nbItems; i++) {
4224 	    xmlSchemaBucketFree((xmlSchemaBucketPtr) list->items[i]);
4225 	}
4226 	xmlSchemaItemListFree(list);
4227     }
4228     if (schema->annot != NULL)
4229         xmlSchemaFreeAnnot(schema->annot);
4230     /* Never free the doc here, since this will be done by the buckets. */
4231 
4232     xmlDictFree(schema->dict);
4233     xmlFree(schema);
4234 }
4235 
4236 /************************************************************************
4237  *									*
4238  *			Debug functions					*
4239  *									*
4240  ************************************************************************/
4241 
4242 #ifdef LIBXML_OUTPUT_ENABLED
4243 
4244 static void
4245 xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output); /* forward */
4246 
4247 /**
4248  * xmlSchemaElementDump:
4249  * @elem:  an element
4250  * @output:  the file output
4251  *
4252  * Dump the element
4253  */
4254 static void
xmlSchemaElementDump(void * payload,void * data,const xmlChar * name ATTRIBUTE_UNUSED,const xmlChar * namespace ATTRIBUTE_UNUSED,const xmlChar * context ATTRIBUTE_UNUSED)4255 xmlSchemaElementDump(void *payload, void *data,
4256                      const xmlChar * name ATTRIBUTE_UNUSED,
4257 		     const xmlChar * namespace ATTRIBUTE_UNUSED,
4258                      const xmlChar * context ATTRIBUTE_UNUSED)
4259 {
4260     xmlSchemaElementPtr elem = (xmlSchemaElementPtr) payload;
4261     FILE *output = (FILE *) data;
4262     if (elem == NULL)
4263         return;
4264 
4265 
4266     fprintf(output, "Element");
4267     if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
4268 	fprintf(output, " (global)");
4269     fprintf(output, ": '%s' ", elem->name);
4270     if (namespace != NULL)
4271 	fprintf(output, "ns '%s'", namespace);
4272     fprintf(output, "\n");
4273 #if 0
4274     if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
4275 	fprintf(output, "  min %d ", elem->minOccurs);
4276         if (elem->maxOccurs >= UNBOUNDED)
4277             fprintf(output, "max: unbounded\n");
4278         else if (elem->maxOccurs != 1)
4279             fprintf(output, "max: %d\n", elem->maxOccurs);
4280         else
4281             fprintf(output, "\n");
4282     }
4283 #endif
4284     /*
4285     * Misc other properties.
4286     */
4287     if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
4288 	(elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
4289 	(elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
4290 	(elem->flags & XML_SCHEMAS_ELEM_DEFAULT)) {
4291 	fprintf(output, "  props: ");
4292 	if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
4293 	    fprintf(output, "[fixed] ");
4294 	if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
4295 	    fprintf(output, "[default] ");
4296 	if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
4297 	    fprintf(output, "[abstract] ");
4298 	if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
4299 	    fprintf(output, "[nillable] ");
4300 	fprintf(output, "\n");
4301     }
4302     /*
4303     * Default/fixed value.
4304     */
4305     if (elem->value != NULL)
4306 	fprintf(output, "  value: '%s'\n", elem->value);
4307     /*
4308     * Type.
4309     */
4310     if (elem->namedType != NULL) {
4311 	fprintf(output, "  type: '%s' ", elem->namedType);
4312 	if (elem->namedTypeNs != NULL)
4313 	    fprintf(output, "ns '%s'\n", elem->namedTypeNs);
4314 	else
4315 	    fprintf(output, "\n");
4316     } else if (elem->subtypes != NULL) {
4317 	/*
4318 	* Dump local types.
4319 	*/
4320 	xmlSchemaTypeDump(elem->subtypes, output);
4321     }
4322     /*
4323     * Substitution group.
4324     */
4325     if (elem->substGroup != NULL) {
4326 	fprintf(output, "  substitutionGroup: '%s' ", elem->substGroup);
4327 	if (elem->substGroupNs != NULL)
4328 	    fprintf(output, "ns '%s'\n", elem->substGroupNs);
4329 	else
4330 	    fprintf(output, "\n");
4331     }
4332 }
4333 
4334 /**
4335  * xmlSchemaAnnotDump:
4336  * @output:  the file output
4337  * @annot:  a annotation
4338  *
4339  * Dump the annotation
4340  */
4341 static void
xmlSchemaAnnotDump(FILE * output,xmlSchemaAnnotPtr annot)4342 xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
4343 {
4344     xmlChar *content;
4345 
4346     if (annot == NULL)
4347         return;
4348 
4349     content = xmlNodeGetContent(annot->content);
4350     if (content != NULL) {
4351         fprintf(output, "  Annot: %s\n", content);
4352         xmlFree(content);
4353     } else
4354         fprintf(output, "  Annot: empty\n");
4355 }
4356 
4357 /**
4358  * xmlSchemaContentModelDump:
4359  * @particle: the schema particle
4360  * @output: the file output
4361  * @depth: the depth used for indentation
4362  *
4363  * Dump a SchemaType structure
4364  */
4365 static void
xmlSchemaContentModelDump(xmlSchemaParticlePtr particle,FILE * output,int depth)4366 xmlSchemaContentModelDump(xmlSchemaParticlePtr particle, FILE * output, int depth)
4367 {
4368     xmlChar *str = NULL;
4369     xmlSchemaTreeItemPtr term;
4370     char shift[100];
4371     int i;
4372 
4373     if (particle == NULL)
4374 	return;
4375     for (i = 0;((i < depth) && (i < 25));i++)
4376         shift[2 * i] = shift[2 * i + 1] = ' ';
4377     shift[2 * i] = shift[2 * i + 1] = 0;
4378     fprintf(output, "%s", shift);
4379     if (particle->children == NULL) {
4380 	fprintf(output, "MISSING particle term\n");
4381 	return;
4382     }
4383     term = particle->children;
4384     if (term == NULL) {
4385 	fprintf(output, "(NULL)");
4386     } else {
4387 	switch (term->type) {
4388 	    case XML_SCHEMA_TYPE_ELEMENT:
4389 		fprintf(output, "ELEM '%s'", xmlSchemaFormatQName(&str,
4390 		    ((xmlSchemaElementPtr)term)->targetNamespace,
4391 		    ((xmlSchemaElementPtr)term)->name));
4392 		FREE_AND_NULL(str);
4393 		break;
4394 	    case XML_SCHEMA_TYPE_SEQUENCE:
4395 		fprintf(output, "SEQUENCE");
4396 		break;
4397 	    case XML_SCHEMA_TYPE_CHOICE:
4398 		fprintf(output, "CHOICE");
4399 		break;
4400 	    case XML_SCHEMA_TYPE_ALL:
4401 		fprintf(output, "ALL");
4402 		break;
4403 	    case XML_SCHEMA_TYPE_ANY:
4404 		fprintf(output, "ANY");
4405 		break;
4406 	    default:
4407 		fprintf(output, "UNKNOWN\n");
4408 		return;
4409 	}
4410     }
4411     if (particle->minOccurs != 1)
4412 	fprintf(output, " min: %d", particle->minOccurs);
4413     if (particle->maxOccurs >= UNBOUNDED)
4414 	fprintf(output, " max: unbounded");
4415     else if (particle->maxOccurs != 1)
4416 	fprintf(output, " max: %d", particle->maxOccurs);
4417     fprintf(output, "\n");
4418     if (term &&
4419 	((term->type == XML_SCHEMA_TYPE_SEQUENCE) ||
4420 	 (term->type == XML_SCHEMA_TYPE_CHOICE) ||
4421 	 (term->type == XML_SCHEMA_TYPE_ALL)) &&
4422 	 (term->children != NULL)) {
4423 	xmlSchemaContentModelDump((xmlSchemaParticlePtr) term->children,
4424 	    output, depth +1);
4425     }
4426     if (particle->next != NULL)
4427 	xmlSchemaContentModelDump((xmlSchemaParticlePtr) particle->next,
4428 		output, depth);
4429 }
4430 
4431 /**
4432  * xmlSchemaAttrUsesDump:
4433  * @uses:  attribute uses list
4434  * @output:  the file output
4435  *
4436  * Dumps a list of attribute use components.
4437  */
4438 static void
xmlSchemaAttrUsesDump(xmlSchemaItemListPtr uses,FILE * output)4439 xmlSchemaAttrUsesDump(xmlSchemaItemListPtr uses, FILE * output)
4440 {
4441     xmlSchemaAttributeUsePtr use;
4442     xmlSchemaAttributeUseProhibPtr prohib;
4443     xmlSchemaQNameRefPtr ref;
4444     const xmlChar *name, *tns;
4445     xmlChar *str = NULL;
4446     int i;
4447 
4448     if ((uses == NULL) || (uses->nbItems == 0))
4449         return;
4450 
4451     fprintf(output, "  attributes:\n");
4452     for (i = 0; i < uses->nbItems; i++) {
4453 	use = uses->items[i];
4454 	if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
4455 	    fprintf(output, "  [prohibition] ");
4456 	    prohib = (xmlSchemaAttributeUseProhibPtr) use;
4457 	    name = prohib->name;
4458 	    tns = prohib->targetNamespace;
4459 	} else if (use->type == XML_SCHEMA_EXTRA_QNAMEREF) {
4460 	    fprintf(output, "  [reference] ");
4461 	    ref = (xmlSchemaQNameRefPtr) use;
4462 	    name = ref->name;
4463 	    tns = ref->targetNamespace;
4464 	} else {
4465 	    fprintf(output, "  [use] ");
4466 	    name = WXS_ATTRUSE_DECL_NAME(use);
4467 	    tns = WXS_ATTRUSE_DECL_TNS(use);
4468 	}
4469 	fprintf(output, "'%s'\n",
4470 	    (const char *) xmlSchemaFormatQName(&str, tns, name));
4471 	FREE_AND_NULL(str);
4472     }
4473 }
4474 
4475 /**
4476  * xmlSchemaTypeDump:
4477  * @output:  the file output
4478  * @type:  a type structure
4479  *
4480  * Dump a SchemaType structure
4481  */
4482 static void
xmlSchemaTypeDump(xmlSchemaTypePtr type,FILE * output)4483 xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
4484 {
4485     if (type == NULL) {
4486         fprintf(output, "Type: NULL\n");
4487         return;
4488     }
4489     fprintf(output, "Type: ");
4490     if (type->name != NULL)
4491         fprintf(output, "'%s' ", type->name);
4492     else
4493         fprintf(output, "(no name) ");
4494     if (type->targetNamespace != NULL)
4495 	fprintf(output, "ns '%s' ", type->targetNamespace);
4496     switch (type->type) {
4497         case XML_SCHEMA_TYPE_BASIC:
4498             fprintf(output, "[basic] ");
4499             break;
4500         case XML_SCHEMA_TYPE_SIMPLE:
4501             fprintf(output, "[simple] ");
4502             break;
4503         case XML_SCHEMA_TYPE_COMPLEX:
4504             fprintf(output, "[complex] ");
4505             break;
4506         case XML_SCHEMA_TYPE_SEQUENCE:
4507             fprintf(output, "[sequence] ");
4508             break;
4509         case XML_SCHEMA_TYPE_CHOICE:
4510             fprintf(output, "[choice] ");
4511             break;
4512         case XML_SCHEMA_TYPE_ALL:
4513             fprintf(output, "[all] ");
4514             break;
4515         case XML_SCHEMA_TYPE_UR:
4516             fprintf(output, "[ur] ");
4517             break;
4518         case XML_SCHEMA_TYPE_RESTRICTION:
4519             fprintf(output, "[restriction] ");
4520             break;
4521         case XML_SCHEMA_TYPE_EXTENSION:
4522             fprintf(output, "[extension] ");
4523             break;
4524         default:
4525             fprintf(output, "[unknown type %d] ", type->type);
4526             break;
4527     }
4528     fprintf(output, "content: ");
4529     switch (type->contentType) {
4530         case XML_SCHEMA_CONTENT_UNKNOWN:
4531             fprintf(output, "[unknown] ");
4532             break;
4533         case XML_SCHEMA_CONTENT_EMPTY:
4534             fprintf(output, "[empty] ");
4535             break;
4536         case XML_SCHEMA_CONTENT_ELEMENTS:
4537             fprintf(output, "[element] ");
4538             break;
4539         case XML_SCHEMA_CONTENT_MIXED:
4540             fprintf(output, "[mixed] ");
4541             break;
4542         case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
4543 	/* not used. */
4544             break;
4545         case XML_SCHEMA_CONTENT_BASIC:
4546             fprintf(output, "[basic] ");
4547             break;
4548         case XML_SCHEMA_CONTENT_SIMPLE:
4549             fprintf(output, "[simple] ");
4550             break;
4551         case XML_SCHEMA_CONTENT_ANY:
4552             fprintf(output, "[any] ");
4553             break;
4554     }
4555     fprintf(output, "\n");
4556     if (type->base != NULL) {
4557         fprintf(output, "  base type: '%s'", type->base);
4558 	if (type->baseNs != NULL)
4559 	    fprintf(output, " ns '%s'\n", type->baseNs);
4560 	else
4561 	    fprintf(output, "\n");
4562     }
4563     if (type->attrUses != NULL)
4564 	xmlSchemaAttrUsesDump(type->attrUses, output);
4565     if (type->annot != NULL)
4566         xmlSchemaAnnotDump(output, type->annot);
4567 #ifdef DUMP_CONTENT_MODEL
4568     if ((type->type == XML_SCHEMA_TYPE_COMPLEX) &&
4569 	(type->subtypes != NULL)) {
4570 	xmlSchemaContentModelDump((xmlSchemaParticlePtr) type->subtypes,
4571 	    output, 1);
4572     }
4573 #endif
4574 }
4575 
4576 static void
xmlSchemaTypeDumpEntry(void * type,void * output,const xmlChar * name ATTRIBUTE_UNUSED)4577 xmlSchemaTypeDumpEntry(void *type, void *output,
4578                        const xmlChar *name ATTRIBUTE_UNUSED)
4579 {
4580     xmlSchemaTypeDump((xmlSchemaTypePtr) type, (FILE *) output);
4581 }
4582 
4583 /**
4584  * xmlSchemaDump:
4585  * @output:  the file output
4586  * @schema:  a schema structure
4587  *
4588  * Dump a Schema structure.
4589  */
4590 void
xmlSchemaDump(FILE * output,xmlSchemaPtr schema)4591 xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
4592 {
4593     if (output == NULL)
4594         return;
4595     if (schema == NULL) {
4596         fprintf(output, "Schemas: NULL\n");
4597         return;
4598     }
4599     fprintf(output, "Schemas: ");
4600     if (schema->name != NULL)
4601         fprintf(output, "%s, ", schema->name);
4602     else
4603         fprintf(output, "no name, ");
4604     if (schema->targetNamespace != NULL)
4605         fprintf(output, "%s", (const char *) schema->targetNamespace);
4606     else
4607         fprintf(output, "no target namespace");
4608     fprintf(output, "\n");
4609     if (schema->annot != NULL)
4610         xmlSchemaAnnotDump(output, schema->annot);
4611     xmlHashScan(schema->typeDecl, xmlSchemaTypeDumpEntry, output);
4612     xmlHashScanFull(schema->elemDecl, xmlSchemaElementDump, output);
4613 }
4614 
4615 #endif /* LIBXML_OUTPUT_ENABLED */
4616 
4617 /************************************************************************
4618  *									*
4619  *			Utilities					*
4620  *									*
4621  ************************************************************************/
4622 
4623 /**
4624  * xmlSchemaGetPropNode:
4625  * @node: the element node
4626  * @name: the name of the attribute
4627  *
4628  * Seeks an attribute with a name of @name in
4629  * no namespace.
4630  *
4631  * Returns the attribute or NULL if not present.
4632  */
4633 static xmlAttrPtr
xmlSchemaGetPropNode(xmlNodePtr node,const char * name)4634 xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
4635 {
4636     xmlAttrPtr prop;
4637 
4638     if ((node == NULL) || (name == NULL))
4639 	return(NULL);
4640     prop = node->properties;
4641     while (prop != NULL) {
4642         if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
4643 	    return(prop);
4644 	prop = prop->next;
4645     }
4646     return (NULL);
4647 }
4648 
4649 /**
4650  * xmlSchemaGetPropNodeNs:
4651  * @node: the element node
4652  * @uri: the uri
4653  * @name: the name of the attribute
4654  *
4655  * Seeks an attribute with a local name of @name and
4656  * a namespace URI of @uri.
4657  *
4658  * Returns the attribute or NULL if not present.
4659  */
4660 static xmlAttrPtr
xmlSchemaGetPropNodeNs(xmlNodePtr node,const char * uri,const char * name)4661 xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
4662 {
4663     xmlAttrPtr prop;
4664 
4665     if ((node == NULL) || (name == NULL))
4666 	return(NULL);
4667     prop = node->properties;
4668     while (prop != NULL) {
4669 	if ((prop->ns != NULL) &&
4670 	    xmlStrEqual(prop->name, BAD_CAST name) &&
4671 	    xmlStrEqual(prop->ns->href, BAD_CAST uri))
4672 	    return(prop);
4673 	prop = prop->next;
4674     }
4675     return (NULL);
4676 }
4677 
4678 static const xmlChar *
xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node)4679 xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
4680 {
4681     xmlChar *val;
4682     const xmlChar *ret;
4683 
4684     val = xmlNodeGetContent(node);
4685     if (val == NULL)
4686 	val = xmlStrdup((xmlChar *)"");
4687     ret = xmlDictLookup(ctxt->dict, val, -1);
4688     xmlFree(val);
4689     if (ret == NULL)
4690         xmlSchemaPErrMemory(ctxt);
4691     return(ret);
4692 }
4693 
4694 static const xmlChar *
xmlSchemaGetNodeContentNoDict(xmlNodePtr node)4695 xmlSchemaGetNodeContentNoDict(xmlNodePtr node)
4696 {
4697     return((const xmlChar*) xmlNodeGetContent(node));
4698 }
4699 
4700 /**
4701  * xmlSchemaGetProp:
4702  * @ctxt: the parser context
4703  * @node: the node
4704  * @name: the property name
4705  *
4706  * Read a attribute value and internalize the string
4707  *
4708  * Returns the string or NULL if not present.
4709  */
4710 static const xmlChar *
xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,const char * name)4711 xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
4712                  const char *name)
4713 {
4714     xmlChar *val;
4715     const xmlChar *ret;
4716 
4717     val = xmlGetNoNsProp(node, BAD_CAST name);
4718     if (val == NULL)
4719         return(NULL);
4720     ret = xmlDictLookup(ctxt->dict, val, -1);
4721     xmlFree(val);
4722     return(ret);
4723 }
4724 
4725 /************************************************************************
4726  *									*
4727  *			Parsing functions				*
4728  *									*
4729  ************************************************************************/
4730 
4731 #define WXS_FIND_GLOBAL_ITEM(slot)			\
4732     if (xmlStrEqual(nsName, schema->targetNamespace)) { \
4733 	ret = xmlHashLookup(schema->slot, name); \
4734 	if (ret != NULL) goto exit; \
4735     } \
4736     if (xmlHashSize(schema->schemasImports) > 1) { \
4737 	xmlSchemaImportPtr import; \
4738 	if (nsName == NULL) \
4739 	    import = xmlHashLookup(schema->schemasImports, \
4740 		XML_SCHEMAS_NO_NAMESPACE); \
4741 	else \
4742 	    import = xmlHashLookup(schema->schemasImports, nsName); \
4743 	if (import == NULL) \
4744 	    goto exit; \
4745 	ret = xmlHashLookup(import->schema->slot, name); \
4746     }
4747 
4748 /**
4749  * xmlSchemaGetElem:
4750  * @schema:  the schema context
4751  * @name:  the element name
4752  * @ns:  the element namespace
4753  *
4754  * Lookup a global element declaration in the schema.
4755  *
4756  * Returns the element declaration or NULL if not found.
4757  */
4758 static xmlSchemaElementPtr
xmlSchemaGetElem(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName)4759 xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
4760                  const xmlChar * nsName)
4761 {
4762     xmlSchemaElementPtr ret = NULL;
4763 
4764     if ((name == NULL) || (schema == NULL))
4765         return(NULL);
4766     if (schema != NULL) {
4767 	WXS_FIND_GLOBAL_ITEM(elemDecl)
4768     }
4769 exit:
4770     return (ret);
4771 }
4772 
4773 /**
4774  * xmlSchemaGetType:
4775  * @schema:  the main schema
4776  * @name:  the type's name
4777  * nsName:  the type's namespace
4778  *
4779  * Lookup a type in the schemas or the predefined types
4780  *
4781  * Returns the group definition or NULL if not found.
4782  */
4783 static xmlSchemaTypePtr
xmlSchemaGetType(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName)4784 xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
4785                  const xmlChar * nsName)
4786 {
4787     xmlSchemaTypePtr ret = NULL;
4788 
4789     if (name == NULL)
4790         return (NULL);
4791     /* First try the built-in types. */
4792     if ((nsName != NULL) && xmlStrEqual(nsName, xmlSchemaNs)) {
4793 	ret = xmlSchemaGetPredefinedType(name, nsName);
4794 	if (ret != NULL)
4795 	    goto exit;
4796 	/*
4797 	* Note that we try the parsed schemas as well here
4798 	* since one might have parsed the S4S, which contain more
4799 	* than the built-in types.
4800 	* TODO: Can we optimize this?
4801 	*/
4802     }
4803     if (schema != NULL) {
4804 	WXS_FIND_GLOBAL_ITEM(typeDecl)
4805     }
4806 exit:
4807 
4808     return (ret);
4809 }
4810 
4811 /**
4812  * xmlSchemaGetAttributeDecl:
4813  * @schema:  the context of the schema
4814  * @name:  the name of the attribute
4815  * @ns:  the target namespace of the attribute
4816  *
4817  * Lookup a an attribute in the schema or imported schemas
4818  *
4819  * Returns the attribute declaration or NULL if not found.
4820  */
4821 static xmlSchemaAttributePtr
xmlSchemaGetAttributeDecl(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName)4822 xmlSchemaGetAttributeDecl(xmlSchemaPtr schema, const xmlChar * name,
4823                  const xmlChar * nsName)
4824 {
4825     xmlSchemaAttributePtr ret = NULL;
4826 
4827     if ((name == NULL) || (schema == NULL))
4828         return (NULL);
4829     if (schema != NULL) {
4830 	WXS_FIND_GLOBAL_ITEM(attrDecl)
4831     }
4832 exit:
4833     return (ret);
4834 }
4835 
4836 /**
4837  * xmlSchemaGetAttributeGroup:
4838  * @schema:  the context of the schema
4839  * @name:  the name of the attribute group
4840  * @ns:  the target namespace of the attribute group
4841  *
4842  * Lookup a an attribute group in the schema or imported schemas
4843  *
4844  * Returns the attribute group definition or NULL if not found.
4845  */
4846 static xmlSchemaAttributeGroupPtr
xmlSchemaGetAttributeGroup(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName)4847 xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
4848                  const xmlChar * nsName)
4849 {
4850     xmlSchemaAttributeGroupPtr ret = NULL;
4851 
4852     if ((name == NULL) || (schema == NULL))
4853         return (NULL);
4854     if (schema != NULL) {
4855 	WXS_FIND_GLOBAL_ITEM(attrgrpDecl)
4856     }
4857 exit:
4858     /* TODO:
4859     if ((ret != NULL) && (ret->redef != NULL)) {
4860 	* Return the last redefinition. *
4861 	ret = ret->redef;
4862     }
4863     */
4864     return (ret);
4865 }
4866 
4867 /**
4868  * xmlSchemaGetGroup:
4869  * @schema:  the context of the schema
4870  * @name:  the name of the group
4871  * @ns:  the target namespace of the group
4872  *
4873  * Lookup a group in the schema or imported schemas
4874  *
4875  * Returns the group definition or NULL if not found.
4876  */
4877 static xmlSchemaModelGroupDefPtr
xmlSchemaGetGroup(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName)4878 xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
4879                  const xmlChar * nsName)
4880 {
4881     xmlSchemaModelGroupDefPtr ret = NULL;
4882 
4883     if ((name == NULL) || (schema == NULL))
4884         return (NULL);
4885     if (schema != NULL) {
4886 	WXS_FIND_GLOBAL_ITEM(groupDecl)
4887     }
4888 exit:
4889 
4890     return (ret);
4891 }
4892 
4893 static xmlSchemaNotationPtr
xmlSchemaGetNotation(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName)4894 xmlSchemaGetNotation(xmlSchemaPtr schema,
4895 		     const xmlChar *name,
4896 		     const xmlChar *nsName)
4897 {
4898     xmlSchemaNotationPtr ret = NULL;
4899 
4900     if ((name == NULL) || (schema == NULL))
4901         return (NULL);
4902     if (schema != NULL) {
4903 	WXS_FIND_GLOBAL_ITEM(notaDecl)
4904     }
4905 exit:
4906     return (ret);
4907 }
4908 
4909 static xmlSchemaIDCPtr
xmlSchemaGetIDC(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName)4910 xmlSchemaGetIDC(xmlSchemaPtr schema,
4911 		const xmlChar *name,
4912 		const xmlChar *nsName)
4913 {
4914     xmlSchemaIDCPtr ret = NULL;
4915 
4916     if ((name == NULL) || (schema == NULL))
4917         return (NULL);
4918     if (schema != NULL) {
4919 	WXS_FIND_GLOBAL_ITEM(idcDef)
4920     }
4921 exit:
4922     return (ret);
4923 }
4924 
4925 /**
4926  * xmlSchemaGetNamedComponent:
4927  * @schema:  the schema
4928  * @name:  the name of the group
4929  * @ns:  the target namespace of the group
4930  *
4931  * Lookup a group in the schema or imported schemas
4932  *
4933  * Returns the group definition or NULL if not found.
4934  */
4935 static xmlSchemaBasicItemPtr
xmlSchemaGetNamedComponent(xmlSchemaPtr schema,xmlSchemaTypeType itemType,const xmlChar * name,const xmlChar * targetNs)4936 xmlSchemaGetNamedComponent(xmlSchemaPtr schema,
4937 			   xmlSchemaTypeType itemType,
4938 			   const xmlChar *name,
4939 			   const xmlChar *targetNs)
4940 {
4941     switch (itemType) {
4942 	case XML_SCHEMA_TYPE_GROUP:
4943 	    return ((xmlSchemaBasicItemPtr) xmlSchemaGetGroup(schema,
4944 		name, targetNs));
4945 	case XML_SCHEMA_TYPE_ELEMENT:
4946 	    return ((xmlSchemaBasicItemPtr) xmlSchemaGetElem(schema,
4947 		name, targetNs));
4948 	default:
4949 	    /* TODO */
4950 	    return (NULL);
4951     }
4952 }
4953 
4954 /************************************************************************
4955  *									*
4956  *			Parsing functions				*
4957  *									*
4958  ************************************************************************/
4959 
4960 #define IS_BLANK_NODE(n)						\
4961     (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content, -1)))
4962 
4963 /**
4964  * xmlSchemaIsBlank:
4965  * @str:  a string
4966  * @len: the length of the string or -1
4967  *
4968  * Check if a string is ignorable
4969  *
4970  * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
4971  */
4972 static int
xmlSchemaIsBlank(xmlChar * str,int len)4973 xmlSchemaIsBlank(xmlChar * str, int len)
4974 {
4975     if (str == NULL)
4976         return (1);
4977     if (len < 0) {
4978 	while (*str != 0) {
4979 	    if (!(IS_BLANK_CH(*str)))
4980 		return (0);
4981 	    str++;
4982 	}
4983     } else while ((*str != 0) && (len != 0)) {
4984 	if (!(IS_BLANK_CH(*str)))
4985 	    return (0);
4986 	str++;
4987 	len--;
4988     }
4989 
4990     return (1);
4991 }
4992 
4993 #define WXS_COMP_NAME(c, t) ((t) (c))->name
4994 #define WXS_COMP_TNS(c, t) ((t) (c))->targetNamespace
4995 /*
4996 * xmlSchemaFindRedefCompInGraph:
4997 * ATTENTION TODO: This uses pointer comp. for strings.
4998 */
4999 static xmlSchemaBasicItemPtr
xmlSchemaFindRedefCompInGraph(xmlSchemaBucketPtr bucket,xmlSchemaTypeType type,const xmlChar * name,const xmlChar * nsName)5000 xmlSchemaFindRedefCompInGraph(xmlSchemaBucketPtr bucket,
5001 			      xmlSchemaTypeType type,
5002 			      const xmlChar *name,
5003 			      const xmlChar *nsName)
5004 {
5005     xmlSchemaBasicItemPtr ret;
5006     int i;
5007 
5008     if ((bucket == NULL) || (name == NULL))
5009 	return(NULL);
5010     if ((bucket->globals == NULL) ||
5011 	(bucket->globals->nbItems == 0))
5012 	goto subschemas;
5013     /*
5014     * Search in global components.
5015     */
5016     for (i = 0; i < bucket->globals->nbItems; i++) {
5017 	ret = bucket->globals->items[i];
5018 	if (ret->type == type) {
5019 	    switch (type) {
5020 		case XML_SCHEMA_TYPE_COMPLEX:
5021 		case XML_SCHEMA_TYPE_SIMPLE:
5022 		    if ((WXS_COMP_NAME(ret, xmlSchemaTypePtr) == name) &&
5023 			(WXS_COMP_TNS(ret, xmlSchemaTypePtr) ==
5024 			nsName))
5025 		    {
5026 			return(ret);
5027 		    }
5028 		    break;
5029 		case XML_SCHEMA_TYPE_GROUP:
5030 		    if ((WXS_COMP_NAME(ret,
5031 			    xmlSchemaModelGroupDefPtr) == name) &&
5032 			(WXS_COMP_TNS(ret,
5033 			    xmlSchemaModelGroupDefPtr) == nsName))
5034 		    {
5035 			return(ret);
5036 		    }
5037 		    break;
5038 		case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
5039 		    if ((WXS_COMP_NAME(ret,
5040 			    xmlSchemaAttributeGroupPtr) == name) &&
5041 			(WXS_COMP_TNS(ret,
5042 			    xmlSchemaAttributeGroupPtr) == nsName))
5043 		    {
5044 			return(ret);
5045 		    }
5046 		    break;
5047 		default:
5048 		    /* Should not be hit. */
5049 		    return(NULL);
5050 	    }
5051 	}
5052     }
5053 subschemas:
5054     /*
5055     * Process imported/included schemas.
5056     */
5057     if (bucket->relations != NULL) {
5058 	xmlSchemaSchemaRelationPtr rel = bucket->relations;
5059 
5060 	/*
5061 	* TODO: Marking the bucket will not avoid multiple searches
5062 	* in the same schema, but avoids at least circularity.
5063 	*/
5064 	bucket->flags |= XML_SCHEMA_BUCKET_MARKED;
5065 	do {
5066 	    if ((rel->bucket != NULL) &&
5067 		((rel->bucket->flags & XML_SCHEMA_BUCKET_MARKED) == 0)) {
5068 		ret = xmlSchemaFindRedefCompInGraph(rel->bucket,
5069 		    type, name, nsName);
5070 		if (ret != NULL)
5071 		    return(ret);
5072 	    }
5073 	    rel = rel->next;
5074 	} while (rel != NULL);
5075 	 bucket->flags ^= XML_SCHEMA_BUCKET_MARKED;
5076     }
5077     return(NULL);
5078 }
5079 
5080 /**
5081  * xmlSchemaAddNotation:
5082  * @ctxt:  a schema parser context
5083  * @schema:  the schema being built
5084  * @name:  the item name
5085  *
5086  * Add an XML schema annotation declaration
5087  * *WARNING* this interface is highly subject to change
5088  *
5089  * Returns the new structure or NULL in case of error
5090  */
5091 static xmlSchemaNotationPtr
xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName,xmlNodePtr node ATTRIBUTE_UNUSED)5092 xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5093                      const xmlChar *name, const xmlChar *nsName,
5094 		     xmlNodePtr node ATTRIBUTE_UNUSED)
5095 {
5096     xmlSchemaNotationPtr ret = NULL;
5097 
5098     if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5099         return (NULL);
5100 
5101     ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
5102     if (ret == NULL) {
5103         xmlSchemaPErrMemory(ctxt);
5104         return (NULL);
5105     }
5106     memset(ret, 0, sizeof(xmlSchemaNotation));
5107     ret->type = XML_SCHEMA_TYPE_NOTATION;
5108     ret->name = name;
5109     ret->targetNamespace = nsName;
5110     /* TODO: do we need the node to be set?
5111     * ret->node = node;*/
5112     WXS_ADD_GLOBAL(ctxt, ret);
5113     return (ret);
5114 }
5115 
5116 /**
5117  * xmlSchemaAddAttribute:
5118  * @ctxt:  a schema parser context
5119  * @schema:  the schema being built
5120  * @name:  the item name
5121  * @namespace:  the namespace
5122  *
5123  * Add an XML schema Attribute declaration
5124  * *WARNING* this interface is highly subject to change
5125  *
5126  * Returns the new structure or NULL in case of error
5127  */
5128 static xmlSchemaAttributePtr
xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName,xmlNodePtr node,int topLevel)5129 xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5130                       const xmlChar * name, const xmlChar * nsName,
5131 		      xmlNodePtr node, int topLevel)
5132 {
5133     xmlSchemaAttributePtr ret = NULL;
5134 
5135     if ((ctxt == NULL) || (schema == NULL))
5136         return (NULL);
5137 
5138     ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
5139     if (ret == NULL) {
5140         xmlSchemaPErrMemory(ctxt);
5141         return (NULL);
5142     }
5143     memset(ret, 0, sizeof(xmlSchemaAttribute));
5144     ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
5145     ret->node = node;
5146     ret->name = name;
5147     ret->targetNamespace = nsName;
5148 
5149     if (topLevel)
5150 	WXS_ADD_GLOBAL(ctxt, ret);
5151     else
5152 	WXS_ADD_LOCAL(ctxt, ret);
5153     WXS_ADD_PENDING(ctxt, ret);
5154     return (ret);
5155 }
5156 
5157 /**
5158  * xmlSchemaAddAttributeUse:
5159  * @ctxt:  a schema parser context
5160  * @schema:  the schema being built
5161  * @name:  the item name
5162  * @namespace:  the namespace
5163  *
5164  * Add an XML schema Attribute declaration
5165  * *WARNING* this interface is highly subject to change
5166  *
5167  * Returns the new structure or NULL in case of error
5168  */
5169 static xmlSchemaAttributeUsePtr
xmlSchemaAddAttributeUse(xmlSchemaParserCtxtPtr pctxt,xmlNodePtr node)5170 xmlSchemaAddAttributeUse(xmlSchemaParserCtxtPtr pctxt,
5171 			 xmlNodePtr node)
5172 {
5173     xmlSchemaAttributeUsePtr ret = NULL;
5174 
5175     if (pctxt == NULL)
5176         return (NULL);
5177 
5178     ret = (xmlSchemaAttributeUsePtr) xmlMalloc(sizeof(xmlSchemaAttributeUse));
5179     if (ret == NULL) {
5180         xmlSchemaPErrMemory(pctxt);
5181         return (NULL);
5182     }
5183     memset(ret, 0, sizeof(xmlSchemaAttributeUse));
5184     ret->type = XML_SCHEMA_TYPE_ATTRIBUTE_USE;
5185     ret->node = node;
5186 
5187     WXS_ADD_LOCAL(pctxt, ret);
5188     return (ret);
5189 }
5190 
5191 /*
5192 * xmlSchemaAddRedef:
5193 *
5194 * Adds a redefinition information. This is used at a later stage to:
5195 * resolve references to the redefined components and to check constraints.
5196 */
5197 static xmlSchemaRedefPtr
xmlSchemaAddRedef(xmlSchemaParserCtxtPtr pctxt,xmlSchemaBucketPtr targetBucket,void * item,const xmlChar * refName,const xmlChar * refTargetNs)5198 xmlSchemaAddRedef(xmlSchemaParserCtxtPtr pctxt,
5199 		  xmlSchemaBucketPtr targetBucket,
5200 		  void *item,
5201 		  const xmlChar *refName,
5202 		  const xmlChar *refTargetNs)
5203 {
5204     xmlSchemaRedefPtr ret;
5205 
5206     ret = (xmlSchemaRedefPtr)
5207 	xmlMalloc(sizeof(xmlSchemaRedef));
5208     if (ret == NULL) {
5209 	xmlSchemaPErrMemory(pctxt);
5210 	return (NULL);
5211     }
5212     memset(ret, 0, sizeof(xmlSchemaRedef));
5213     ret->item = item;
5214     ret->targetBucket = targetBucket;
5215     ret->refName = refName;
5216     ret->refTargetNs = refTargetNs;
5217     if (WXS_CONSTRUCTOR(pctxt)->redefs == NULL)
5218 	WXS_CONSTRUCTOR(pctxt)->redefs = ret;
5219     else
5220 	WXS_CONSTRUCTOR(pctxt)->lastRedef->next = ret;
5221     WXS_CONSTRUCTOR(pctxt)->lastRedef = ret;
5222 
5223     return (ret);
5224 }
5225 
5226 /**
5227  * xmlSchemaAddAttributeGroupDefinition:
5228  * @ctxt:  a schema parser context
5229  * @schema:  the schema being built
5230  * @name:  the item name
5231  * @nsName:  the target namespace
5232  * @node: the corresponding node
5233  *
5234  * Add an XML schema Attribute Group definition.
5235  *
5236  * Returns the new structure or NULL in case of error
5237  */
5238 static xmlSchemaAttributeGroupPtr
xmlSchemaAddAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema ATTRIBUTE_UNUSED,const xmlChar * name,const xmlChar * nsName,xmlNodePtr node)5239 xmlSchemaAddAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
5240                            xmlSchemaPtr schema ATTRIBUTE_UNUSED,
5241 			   const xmlChar *name,
5242 			   const xmlChar *nsName,
5243 			   xmlNodePtr node)
5244 {
5245     xmlSchemaAttributeGroupPtr ret = NULL;
5246 
5247     if ((pctxt == NULL) || (name == NULL))
5248         return (NULL);
5249 
5250     ret = (xmlSchemaAttributeGroupPtr)
5251         xmlMalloc(sizeof(xmlSchemaAttributeGroup));
5252     if (ret == NULL) {
5253 	xmlSchemaPErrMemory(pctxt);
5254 	return (NULL);
5255     }
5256     memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
5257     ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5258     ret->name = name;
5259     ret->targetNamespace = nsName;
5260     ret->node = node;
5261 
5262     /* TODO: Remove the flag. */
5263     ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
5264     if (pctxt->isRedefine) {
5265 	pctxt->redef = xmlSchemaAddRedef(pctxt, pctxt->redefined,
5266 	    ret, name, nsName);
5267 	if (pctxt->redef == NULL) {
5268 	    xmlFree(ret);
5269 	    return(NULL);
5270 	}
5271 	pctxt->redefCounter = 0;
5272     }
5273     WXS_ADD_GLOBAL(pctxt, ret);
5274     WXS_ADD_PENDING(pctxt, ret);
5275     return (ret);
5276 }
5277 
5278 /**
5279  * xmlSchemaAddElement:
5280  * @ctxt:  a schema parser context
5281  * @schema:  the schema being built
5282  * @name:  the type name
5283  * @namespace:  the type namespace
5284  *
5285  * Add an XML schema Element declaration
5286  * *WARNING* this interface is highly subject to change
5287  *
5288  * Returns the new structure or NULL in case of error
5289  */
5290 static xmlSchemaElementPtr
xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt,const xmlChar * name,const xmlChar * nsName,xmlNodePtr node,int topLevel)5291 xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt,
5292                     const xmlChar * name, const xmlChar * nsName,
5293 		    xmlNodePtr node, int topLevel)
5294 {
5295     xmlSchemaElementPtr ret = NULL;
5296 
5297     if ((ctxt == NULL) || (name == NULL))
5298         return (NULL);
5299 
5300     ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
5301     if (ret == NULL) {
5302         xmlSchemaPErrMemory(ctxt);
5303         return (NULL);
5304     }
5305     memset(ret, 0, sizeof(xmlSchemaElement));
5306     ret->type = XML_SCHEMA_TYPE_ELEMENT;
5307     ret->name = name;
5308     ret->targetNamespace = nsName;
5309     ret->node = node;
5310 
5311     if (topLevel)
5312 	WXS_ADD_GLOBAL(ctxt, ret);
5313     else
5314 	WXS_ADD_LOCAL(ctxt, ret);
5315     WXS_ADD_PENDING(ctxt, ret);
5316     return (ret);
5317 }
5318 
5319 /**
5320  * xmlSchemaAddType:
5321  * @ctxt:  a schema parser context
5322  * @schema:  the schema being built
5323  * @name:  the item name
5324  * @namespace:  the namespace
5325  *
5326  * Add an XML schema item
5327  * *WARNING* this interface is highly subject to change
5328  *
5329  * Returns the new structure or NULL in case of error
5330  */
5331 static xmlSchemaTypePtr
xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlSchemaTypeType type,const xmlChar * name,const xmlChar * nsName,xmlNodePtr node,int topLevel)5332 xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5333 		 xmlSchemaTypeType type,
5334                  const xmlChar * name, const xmlChar * nsName,
5335 		 xmlNodePtr node, int topLevel)
5336 {
5337     xmlSchemaTypePtr ret = NULL;
5338 
5339     if ((ctxt == NULL) || (schema == NULL))
5340         return (NULL);
5341 
5342     ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
5343     if (ret == NULL) {
5344         xmlSchemaPErrMemory(ctxt);
5345         return (NULL);
5346     }
5347     memset(ret, 0, sizeof(xmlSchemaType));
5348     ret->type = type;
5349     ret->name = name;
5350     ret->targetNamespace = nsName;
5351     ret->node = node;
5352     if (topLevel) {
5353 	if (ctxt->isRedefine) {
5354 	    ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5355 		ret, name, nsName);
5356 	    if (ctxt->redef == NULL) {
5357 		xmlFree(ret);
5358 		return(NULL);
5359 	    }
5360 	    ctxt->redefCounter = 0;
5361 	}
5362 	WXS_ADD_GLOBAL(ctxt, ret);
5363     } else
5364 	WXS_ADD_LOCAL(ctxt, ret);
5365     WXS_ADD_PENDING(ctxt, ret);
5366     return (ret);
5367 }
5368 
5369 static xmlSchemaQNameRefPtr
xmlSchemaNewQNameRef(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypeType refType,const xmlChar * refName,const xmlChar * refNs)5370 xmlSchemaNewQNameRef(xmlSchemaParserCtxtPtr pctxt,
5371 		     xmlSchemaTypeType refType,
5372 		     const xmlChar *refName,
5373 		     const xmlChar *refNs)
5374 {
5375     xmlSchemaQNameRefPtr ret;
5376 
5377     ret = (xmlSchemaQNameRefPtr)
5378 	xmlMalloc(sizeof(xmlSchemaQNameRef));
5379     if (ret == NULL) {
5380 	xmlSchemaPErrMemory(pctxt);
5381 	return (NULL);
5382     }
5383     ret->node = NULL;
5384     ret->type = XML_SCHEMA_EXTRA_QNAMEREF;
5385     ret->name = refName;
5386     ret->targetNamespace = refNs;
5387     ret->item = NULL;
5388     ret->itemType = refType;
5389     /*
5390     * Store the reference item in the schema.
5391     */
5392     WXS_ADD_LOCAL(pctxt, ret);
5393     return (ret);
5394 }
5395 
5396 static xmlSchemaAttributeUseProhibPtr
xmlSchemaAddAttributeUseProhib(xmlSchemaParserCtxtPtr pctxt)5397 xmlSchemaAddAttributeUseProhib(xmlSchemaParserCtxtPtr pctxt)
5398 {
5399     xmlSchemaAttributeUseProhibPtr ret;
5400 
5401     ret = (xmlSchemaAttributeUseProhibPtr)
5402 	xmlMalloc(sizeof(xmlSchemaAttributeUseProhib));
5403     if (ret == NULL) {
5404 	xmlSchemaPErrMemory(pctxt);
5405 	return (NULL);
5406     }
5407     memset(ret, 0, sizeof(xmlSchemaAttributeUseProhib));
5408     ret->type = XML_SCHEMA_EXTRA_ATTR_USE_PROHIB;
5409     WXS_ADD_LOCAL(pctxt, ret);
5410     return (ret);
5411 }
5412 
5413 
5414 /**
5415  * xmlSchemaAddModelGroup:
5416  * @ctxt:  a schema parser context
5417  * @schema:  the schema being built
5418  * @type: the "compositor" type of the model group
5419  * @node: the node in the schema doc
5420  *
5421  * Adds a schema model group
5422  * *WARNING* this interface is highly subject to change
5423  *
5424  * Returns the new structure or NULL in case of error
5425  */
5426 static xmlSchemaModelGroupPtr
xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlSchemaTypeType type,xmlNodePtr node)5427 xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt,
5428 		       xmlSchemaPtr schema,
5429 		       xmlSchemaTypeType type,
5430 		       xmlNodePtr node)
5431 {
5432     xmlSchemaModelGroupPtr ret = NULL;
5433 
5434     if ((ctxt == NULL) || (schema == NULL))
5435         return (NULL);
5436 
5437     ret = (xmlSchemaModelGroupPtr)
5438 	xmlMalloc(sizeof(xmlSchemaModelGroup));
5439     if (ret == NULL) {
5440 	xmlSchemaPErrMemory(ctxt);
5441 	return (NULL);
5442     }
5443     memset(ret, 0, sizeof(xmlSchemaModelGroup));
5444     ret->type = type;
5445     ret->node = node;
5446     WXS_ADD_LOCAL(ctxt, ret);
5447     if ((type == XML_SCHEMA_TYPE_SEQUENCE) ||
5448 	(type == XML_SCHEMA_TYPE_CHOICE))
5449 	WXS_ADD_PENDING(ctxt, ret);
5450     return (ret);
5451 }
5452 
5453 
5454 /**
5455  * xmlSchemaAddParticle:
5456  * @ctxt:  a schema parser context
5457  * @schema:  the schema being built
5458  * @node: the corresponding node in the schema doc
5459  * @min: the minOccurs
5460  * @max: the maxOccurs
5461  *
5462  * Adds an XML schema particle component.
5463  * *WARNING* this interface is highly subject to change
5464  *
5465  * Returns the new structure or NULL in case of error
5466  */
5467 static xmlSchemaParticlePtr
xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,int min,int max)5468 xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt,
5469 		     xmlNodePtr node, int min, int max)
5470 {
5471     xmlSchemaParticlePtr ret = NULL;
5472     if (ctxt == NULL)
5473         return (NULL);
5474 
5475     ret = (xmlSchemaParticlePtr)
5476 	xmlMalloc(sizeof(xmlSchemaParticle));
5477     if (ret == NULL) {
5478 	xmlSchemaPErrMemory(ctxt);
5479 	return (NULL);
5480     }
5481     ret->type = XML_SCHEMA_TYPE_PARTICLE;
5482     ret->annot = NULL;
5483     ret->node = node;
5484     ret->minOccurs = min;
5485     ret->maxOccurs = max;
5486     ret->next = NULL;
5487     ret->children = NULL;
5488 
5489     WXS_ADD_LOCAL(ctxt, ret);
5490     /*
5491     * Note that addition to pending components will be done locally
5492     * to the specific parsing function, since the most particles
5493     * need not to be fixed up (i.e. the reference to be resolved).
5494     * REMOVED: WXS_ADD_PENDING(ctxt, ret);
5495     */
5496     return (ret);
5497 }
5498 
5499 /**
5500  * xmlSchemaAddModelGroupDefinition:
5501  * @ctxt:  a schema validation context
5502  * @schema:  the schema being built
5503  * @name:  the group name
5504  *
5505  * Add an XML schema Group definition
5506  *
5507  * Returns the new structure or NULL in case of error
5508  */
5509 static xmlSchemaModelGroupDefPtr
xmlSchemaAddModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName,xmlNodePtr node)5510 xmlSchemaAddModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
5511 				 xmlSchemaPtr schema,
5512 				 const xmlChar *name,
5513 				 const xmlChar *nsName,
5514 				 xmlNodePtr node)
5515 {
5516     xmlSchemaModelGroupDefPtr ret = NULL;
5517 
5518     if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5519         return (NULL);
5520 
5521     ret = (xmlSchemaModelGroupDefPtr)
5522 	xmlMalloc(sizeof(xmlSchemaModelGroupDef));
5523     if (ret == NULL) {
5524         xmlSchemaPErrMemory(ctxt);
5525         return (NULL);
5526     }
5527     memset(ret, 0, sizeof(xmlSchemaModelGroupDef));
5528     ret->name = name;
5529     ret->type = XML_SCHEMA_TYPE_GROUP;
5530     ret->node = node;
5531     ret->targetNamespace = nsName;
5532 
5533     if (ctxt->isRedefine) {
5534 	ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5535 	    ret, name, nsName);
5536 	if (ctxt->redef == NULL) {
5537 	    xmlFree(ret);
5538 	    return(NULL);
5539 	}
5540 	ctxt->redefCounter = 0;
5541     }
5542     WXS_ADD_GLOBAL(ctxt, ret);
5543     WXS_ADD_PENDING(ctxt, ret);
5544     return (ret);
5545 }
5546 
5547 /**
5548  * xmlSchemaNewWildcardNs:
5549  * @ctxt:  a schema validation context
5550  *
5551  * Creates a new wildcard namespace constraint.
5552  *
5553  * Returns the new structure or NULL in case of error
5554  */
5555 static xmlSchemaWildcardNsPtr
xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)5556 xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
5557 {
5558     xmlSchemaWildcardNsPtr ret;
5559 
5560     ret = (xmlSchemaWildcardNsPtr)
5561 	xmlMalloc(sizeof(xmlSchemaWildcardNs));
5562     if (ret == NULL) {
5563 	xmlSchemaPErrMemory(ctxt);
5564 	return (NULL);
5565     }
5566     ret->value = NULL;
5567     ret->next = NULL;
5568     return (ret);
5569 }
5570 
5571 static xmlSchemaIDCPtr
xmlSchemaAddIDC(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName,int category,xmlNodePtr node)5572 xmlSchemaAddIDC(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5573                   const xmlChar *name, const xmlChar *nsName,
5574 		  int category, xmlNodePtr node)
5575 {
5576     xmlSchemaIDCPtr ret = NULL;
5577 
5578     if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5579         return (NULL);
5580 
5581     ret = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
5582     if (ret == NULL) {
5583         xmlSchemaPErrMemory(ctxt);
5584         return (NULL);
5585     }
5586     memset(ret, 0, sizeof(xmlSchemaIDC));
5587     /* The target namespace of the parent element declaration. */
5588     ret->targetNamespace = nsName;
5589     ret->name = name;
5590     ret->type = category;
5591     ret->node = node;
5592 
5593     WXS_ADD_GLOBAL(ctxt, ret);
5594     /*
5595     * Only keyrefs need to be fixup up.
5596     */
5597     if (category == XML_SCHEMA_TYPE_IDC_KEYREF)
5598 	WXS_ADD_PENDING(ctxt, ret);
5599     return (ret);
5600 }
5601 
5602 /**
5603  * xmlSchemaAddWildcard:
5604  * @ctxt:  a schema validation context
5605  * @schema: a schema
5606  *
5607  * Adds a wildcard.
5608  * It corresponds to a xsd:anyAttribute and xsd:any.
5609  *
5610  * Returns the new structure or NULL in case of error
5611  */
5612 static xmlSchemaWildcardPtr
xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlSchemaTypeType type,xmlNodePtr node)5613 xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5614 		     xmlSchemaTypeType type, xmlNodePtr node)
5615 {
5616     xmlSchemaWildcardPtr ret = NULL;
5617 
5618     if ((ctxt == NULL) || (schema == NULL))
5619         return (NULL);
5620 
5621     ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
5622     if (ret == NULL) {
5623         xmlSchemaPErrMemory(ctxt);
5624         return (NULL);
5625     }
5626     memset(ret, 0, sizeof(xmlSchemaWildcard));
5627     ret->type = type;
5628     ret->node = node;
5629     WXS_ADD_LOCAL(ctxt, ret);
5630     return (ret);
5631 }
5632 
5633 static void
xmlSchemaSubstGroupFree(xmlSchemaSubstGroupPtr group)5634 xmlSchemaSubstGroupFree(xmlSchemaSubstGroupPtr group)
5635 {
5636     if (group == NULL)
5637 	return;
5638     if (group->members != NULL)
5639 	xmlSchemaItemListFree(group->members);
5640     xmlFree(group);
5641 }
5642 
5643 static void
xmlSchemaSubstGroupFreeEntry(void * group,const xmlChar * name ATTRIBUTE_UNUSED)5644 xmlSchemaSubstGroupFreeEntry(void *group, const xmlChar *name ATTRIBUTE_UNUSED)
5645 {
5646     xmlSchemaSubstGroupFree((xmlSchemaSubstGroupPtr) group);
5647 }
5648 
5649 static xmlSchemaSubstGroupPtr
xmlSchemaSubstGroupAdd(xmlSchemaParserCtxtPtr pctxt,xmlSchemaElementPtr head)5650 xmlSchemaSubstGroupAdd(xmlSchemaParserCtxtPtr pctxt,
5651 		       xmlSchemaElementPtr head)
5652 {
5653     xmlSchemaSubstGroupPtr ret;
5654 
5655     /* Init subst group hash. */
5656     if (WXS_SUBST_GROUPS(pctxt) == NULL) {
5657 	WXS_SUBST_GROUPS(pctxt) = xmlHashCreateDict(10, pctxt->dict);
5658 	if (WXS_SUBST_GROUPS(pctxt) == NULL)
5659 	    return(NULL);
5660     }
5661     /* Create a new substitution group. */
5662     ret = (xmlSchemaSubstGroupPtr) xmlMalloc(sizeof(xmlSchemaSubstGroup));
5663     if (ret == NULL) {
5664 	xmlSchemaPErrMemory(NULL);
5665 	return(NULL);
5666     }
5667     memset(ret, 0, sizeof(xmlSchemaSubstGroup));
5668     ret->head = head;
5669     /* Create list of members. */
5670     ret->members = xmlSchemaItemListCreate();
5671     if (ret->members == NULL) {
5672 	xmlSchemaSubstGroupFree(ret);
5673 	return(NULL);
5674     }
5675     /* Add subst group to hash. */
5676     if (xmlHashAddEntry2(WXS_SUBST_GROUPS(pctxt),
5677 	head->name, head->targetNamespace, ret) != 0) {
5678 	PERROR_INT("xmlSchemaSubstGroupAdd",
5679 	    "failed to add a new substitution container");
5680 	xmlSchemaSubstGroupFree(ret);
5681 	return(NULL);
5682     }
5683     return(ret);
5684 }
5685 
5686 static xmlSchemaSubstGroupPtr
xmlSchemaSubstGroupGet(xmlSchemaParserCtxtPtr pctxt,xmlSchemaElementPtr head)5687 xmlSchemaSubstGroupGet(xmlSchemaParserCtxtPtr pctxt,
5688 		       xmlSchemaElementPtr head)
5689 {
5690     if (WXS_SUBST_GROUPS(pctxt) == NULL)
5691 	return(NULL);
5692     return(xmlHashLookup2(WXS_SUBST_GROUPS(pctxt),
5693 	head->name, head->targetNamespace));
5694 
5695 }
5696 
5697 /**
5698  * xmlSchemaAddElementSubstitutionMember:
5699  * @pctxt:  a schema parser context
5700  * @head:  the head of the substitution group
5701  * @member: the new member of the substitution group
5702  *
5703  * Allocate a new annotation structure.
5704  *
5705  * Returns the newly allocated structure or NULL in case or error
5706  */
5707 static int
xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt,xmlSchemaElementPtr head,xmlSchemaElementPtr member)5708 xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt,
5709 				      xmlSchemaElementPtr head,
5710 				      xmlSchemaElementPtr member)
5711 {
5712     xmlSchemaSubstGroupPtr substGroup = NULL;
5713 
5714     if ((pctxt == NULL) || (head == NULL) || (member == NULL))
5715 	return (-1);
5716 
5717     substGroup = xmlSchemaSubstGroupGet(pctxt, head);
5718     if (substGroup == NULL)
5719 	substGroup = xmlSchemaSubstGroupAdd(pctxt, head);
5720     if (substGroup == NULL)
5721 	return(-1);
5722     if (xmlSchemaItemListAdd(substGroup->members, member) == -1)
5723 	return(-1);
5724     return(0);
5725 }
5726 
5727 /************************************************************************
5728  *									*
5729  *		Utilities for parsing					*
5730  *									*
5731  ************************************************************************/
5732 
5733 /**
5734  * xmlSchemaPValAttrNodeQNameValue:
5735  * @ctxt:  a schema parser context
5736  * @schema: the schema context
5737  * @ownerItem: the parent as a schema object
5738  * @value:  the QName value
5739  * @uri:  the resulting namespace URI if found
5740  * @local: the resulting local part if found, the attribute value otherwise
5741  *
5742  * Extracts the local name and the URI of a QName value and validates it.
5743  * This one is intended to be used on attribute values that
5744  * should resolve to schema components.
5745  *
5746  * Returns 0, in case the QName is valid, a positive error code
5747  * if not valid and -1 if an internal error occurs.
5748  */
5749 static int
xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlSchemaBasicItemPtr ownerItem,xmlAttrPtr attr,const xmlChar * value,const xmlChar ** uri,const xmlChar ** local)5750 xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
5751 				       xmlSchemaPtr schema,
5752 				       xmlSchemaBasicItemPtr ownerItem,
5753 				       xmlAttrPtr attr,
5754 				       const xmlChar *value,
5755 				       const xmlChar **uri,
5756 				       const xmlChar **local)
5757 {
5758     const xmlChar *pref;
5759     xmlNsPtr ns;
5760     int len, ret;
5761 
5762     *uri = NULL;
5763     *local = NULL;
5764     ret = xmlValidateQName(value, 1);
5765     if (ret > 0) {
5766 	xmlSchemaPSimpleTypeErr(ctxt,
5767 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5768 	    ownerItem, (xmlNodePtr) attr,
5769 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
5770 	    NULL, value, NULL, NULL, NULL);
5771 	*local = value;
5772 	return (ctxt->err);
5773     } else if (ret < 0)
5774 	return (-1);
5775 
5776     if (!strchr((char *) value, ':')) {
5777 	ns = xmlSearchNs(attr->doc, attr->parent, NULL);
5778 	if (ns && ns->href && ns->href[0])
5779 	    *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5780 	else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
5781 	    /* TODO: move XML_SCHEMAS_INCLUDING_CONVERT_NS to the
5782 	    * parser context. */
5783 	    /*
5784 	    * This one takes care of included schemas with no
5785 	    * target namespace.
5786 	    */
5787 	    *uri = ctxt->targetNamespace;
5788 	}
5789 	*local = xmlDictLookup(ctxt->dict, value, -1);
5790 	return (0);
5791     }
5792     /*
5793     * At this point xmlSplitQName3 has to return a local name.
5794     */
5795     *local = xmlSplitQName3(value, &len);
5796     *local = xmlDictLookup(ctxt->dict, *local, -1);
5797     pref = xmlDictLookup(ctxt->dict, value, len);
5798     ns = xmlSearchNs(attr->doc, attr->parent, pref);
5799     if (ns == NULL) {
5800 	xmlSchemaPSimpleTypeErr(ctxt,
5801 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5802 	    ownerItem, (xmlNodePtr) attr,
5803 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, value,
5804 	    "The value '%s' of simple type 'xs:QName' has no "
5805 	    "corresponding namespace declaration in scope", value, NULL);
5806 	return (ctxt->err);
5807     } else {
5808         *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5809     }
5810     return (0);
5811 }
5812 
5813 /**
5814  * xmlSchemaPValAttrNodeQName:
5815  * @ctxt:  a schema parser context
5816  * @schema: the schema context
5817  * @ownerItem: the owner as a schema object
5818  * @attr:  the attribute node
5819  * @uri:  the resulting namespace URI if found
5820  * @local: the resulting local part if found, the attribute value otherwise
5821  *
5822  * Extracts and validates the QName of an attribute value.
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
xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlSchemaBasicItemPtr ownerItem,xmlAttrPtr attr,const xmlChar ** uri,const xmlChar ** local)5830 xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
5831 				       xmlSchemaPtr schema,
5832 				       xmlSchemaBasicItemPtr ownerItem,
5833 				       xmlAttrPtr attr,
5834 				       const xmlChar **uri,
5835 				       const xmlChar **local)
5836 {
5837     const xmlChar *value;
5838 
5839     value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5840     return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
5841 	ownerItem, attr, value, uri, local));
5842 }
5843 
5844 /**
5845  * xmlSchemaPValAttrQName:
5846  * @ctxt:  a schema parser context
5847  * @schema: the schema context
5848  * @ownerItem: the owner as a schema object
5849  * @ownerElem:  the parent node of the attribute
5850  * @name:  the name of the attribute
5851  * @uri:  the resulting namespace URI if found
5852  * @local: the resulting local part if found, the attribute value otherwise
5853  *
5854  * Extracts and validates the QName of an attribute value.
5855  *
5856  * Returns 0, in case the QName is valid, a positive error code
5857  * if not valid and -1 if an internal error occurs.
5858  */
5859 static int
xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlSchemaBasicItemPtr ownerItem,xmlNodePtr ownerElem,const char * name,const xmlChar ** uri,const xmlChar ** local)5860 xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
5861 				   xmlSchemaPtr schema,
5862 				   xmlSchemaBasicItemPtr ownerItem,
5863 				   xmlNodePtr ownerElem,
5864 				   const char *name,
5865 				   const xmlChar **uri,
5866 				   const xmlChar **local)
5867 {
5868     xmlAttrPtr attr;
5869 
5870     attr = xmlSchemaGetPropNode(ownerElem, name);
5871     if (attr == NULL) {
5872 	*local = NULL;
5873 	*uri = NULL;
5874 	return (0);
5875     }
5876     return (xmlSchemaPValAttrNodeQName(ctxt, schema,
5877 	ownerItem, attr, uri, local));
5878 }
5879 
5880 /**
5881  * xmlSchemaPValAttrID:
5882  * @ctxt:  a schema parser context
5883  *
5884  * Extracts and validates the ID of an attribute value.
5885  *
5886  * Returns 0, in case the ID is valid, a positive error code
5887  * if not valid and -1 if an internal error occurs.
5888  */
5889 static int
xmlSchemaPValAttrNodeID(xmlSchemaParserCtxtPtr ctxt,xmlAttrPtr attr)5890 xmlSchemaPValAttrNodeID(xmlSchemaParserCtxtPtr ctxt, xmlAttrPtr attr)
5891 {
5892     int ret;
5893     const xmlChar *value;
5894 
5895     if (attr == NULL)
5896 	return(0);
5897     value = xmlSchemaGetNodeContentNoDict((xmlNodePtr) attr);
5898     ret = xmlValidateNCName(value, 1);
5899     if (ret == 0) {
5900 	/*
5901 	* NOTE: the IDness might have already be declared in the DTD
5902 	*/
5903 	if (attr->atype != XML_ATTRIBUTE_ID) {
5904 	    xmlChar *strip;
5905             int res;
5906 
5907 	    /*
5908 	    * TODO: Use xmlSchemaStrip here; it's not exported at this
5909 	    * moment.
5910 	    */
5911 	    strip = xmlSchemaCollapseString(value);
5912 	    if (strip != NULL) {
5913 		xmlFree((xmlChar *) value);
5914 		value = strip;
5915 	    }
5916 	    res = xmlAddIDSafe(attr, value);
5917             if (res < 0) {
5918                 xmlSchemaPErrMemory(ctxt);
5919 	    } else if (res == 0) {
5920 		ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
5921 		xmlSchemaPSimpleTypeErr(ctxt,
5922 		    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5923 		    NULL, (xmlNodePtr) attr,
5924 		    xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5925 		    NULL, NULL, "Duplicate value '%s' of simple "
5926 		    "type 'xs:ID'", value, NULL);
5927 	    }
5928 	}
5929     } else if (ret > 0) {
5930 	ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
5931 	xmlSchemaPSimpleTypeErr(ctxt,
5932 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5933 	    NULL, (xmlNodePtr) attr,
5934 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5935 	    NULL, NULL, "The value '%s' of simple type 'xs:ID' is "
5936 	    "not a valid 'xs:NCName'",
5937 	    value, NULL);
5938     }
5939     if (value != NULL)
5940 	xmlFree((xmlChar *)value);
5941 
5942     return (ret);
5943 }
5944 
5945 static int
xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr ownerElem,const xmlChar * name)5946 xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,
5947 		    xmlNodePtr ownerElem,
5948 		    const xmlChar *name)
5949 {
5950     xmlAttrPtr attr;
5951 
5952     attr = xmlSchemaGetPropNode(ownerElem, (const char *) name);
5953     if (attr == NULL)
5954 	return(0);
5955     return(xmlSchemaPValAttrNodeID(ctxt, attr));
5956 
5957 }
5958 
5959 /**
5960  * xmlGetMaxOccurs:
5961  * @ctxt:  a schema validation context
5962  * @node:  a subtree containing XML Schema information
5963  *
5964  * Get the maxOccurs property
5965  *
5966  * Returns the default if not found, or the value
5967  */
5968 static int
xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,int min,int max,int def,const char * expected)5969 xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
5970 		int min, int max, int def, const char *expected)
5971 {
5972     const xmlChar *val, *cur;
5973     int ret = 0;
5974     xmlAttrPtr attr;
5975 
5976     attr = xmlSchemaGetPropNode(node, "maxOccurs");
5977     if (attr == NULL)
5978 	return (def);
5979     val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5980     if (val == NULL)
5981         return (def);
5982 
5983     if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
5984 	if (max != UNBOUNDED) {
5985 	    xmlSchemaPSimpleTypeErr(ctxt,
5986 		XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5987 		/* XML_SCHEMAP_INVALID_MINOCCURS, */
5988 		NULL, (xmlNodePtr) attr, NULL, expected,
5989 		val, NULL, NULL, NULL);
5990 	    return (def);
5991 	} else
5992 	    return (UNBOUNDED);  /* encoding it with -1 might be another option */
5993     }
5994 
5995     cur = val;
5996     while (IS_BLANK_CH(*cur))
5997         cur++;
5998     if (*cur == 0) {
5999         xmlSchemaPSimpleTypeErr(ctxt,
6000 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6001 	    /* XML_SCHEMAP_INVALID_MINOCCURS, */
6002 	    NULL, (xmlNodePtr) attr, NULL, expected,
6003 	    val, NULL, NULL, NULL);
6004 	return (def);
6005     }
6006     while ((*cur >= '0') && (*cur <= '9')) {
6007         if (ret > INT_MAX / 10) {
6008             ret = INT_MAX;
6009         } else {
6010             int digit = *cur - '0';
6011             ret *= 10;
6012             if (ret > INT_MAX - digit)
6013                 ret = INT_MAX;
6014             else
6015                 ret += digit;
6016         }
6017         cur++;
6018     }
6019     while (IS_BLANK_CH(*cur))
6020         cur++;
6021     /*
6022     * TODO: Restrict the maximal value to Integer.
6023     */
6024     if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
6025 	xmlSchemaPSimpleTypeErr(ctxt,
6026 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6027 	    /* XML_SCHEMAP_INVALID_MINOCCURS, */
6028 	    NULL, (xmlNodePtr) attr, NULL, expected,
6029 	    val, NULL, NULL, NULL);
6030         return (def);
6031     }
6032     return (ret);
6033 }
6034 
6035 /**
6036  * xmlGetMinOccurs:
6037  * @ctxt:  a schema validation context
6038  * @node:  a subtree containing XML Schema information
6039  *
6040  * Get the minOccurs property
6041  *
6042  * Returns the default if not found, or the value
6043  */
6044 static int
xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,int min,int max,int def,const char * expected)6045 xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
6046 		int min, int max, int def, const char *expected)
6047 {
6048     const xmlChar *val, *cur;
6049     int ret = 0;
6050     xmlAttrPtr attr;
6051 
6052     attr = xmlSchemaGetPropNode(node, "minOccurs");
6053     if (attr == NULL)
6054 	return (def);
6055     val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6056     if (val == NULL)
6057 	return (def);
6058     cur = val;
6059     while (IS_BLANK_CH(*cur))
6060         cur++;
6061     if (*cur == 0) {
6062         xmlSchemaPSimpleTypeErr(ctxt,
6063 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6064 	    /* XML_SCHEMAP_INVALID_MINOCCURS, */
6065 	    NULL, (xmlNodePtr) attr, NULL, expected,
6066 	    val, NULL, NULL, NULL);
6067         return (def);
6068     }
6069     while ((*cur >= '0') && (*cur <= '9')) {
6070         if (ret > INT_MAX / 10) {
6071             ret = INT_MAX;
6072         } else {
6073             int digit = *cur - '0';
6074             ret *= 10;
6075             if (ret > INT_MAX - digit)
6076                 ret = INT_MAX;
6077             else
6078                 ret += digit;
6079         }
6080         cur++;
6081     }
6082     while (IS_BLANK_CH(*cur))
6083         cur++;
6084     /*
6085     * TODO: Restrict the maximal value to Integer.
6086     */
6087     if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
6088 	xmlSchemaPSimpleTypeErr(ctxt,
6089 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6090 	    /* XML_SCHEMAP_INVALID_MINOCCURS, */
6091 	    NULL, (xmlNodePtr) attr, NULL, expected,
6092 	    val, NULL, NULL, NULL);
6093         return (def);
6094     }
6095     return (ret);
6096 }
6097 
6098 /**
6099  * xmlSchemaPGetBoolNodeValue:
6100  * @ctxt:  a schema validation context
6101  * @ownerItem:  the owner as a schema item
6102  * @node: the node holding the value
6103  *
6104  * Converts a boolean string value into 1 or 0.
6105  *
6106  * Returns 0 or 1.
6107  */
6108 static int
xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,xmlSchemaBasicItemPtr ownerItem,xmlNodePtr node)6109 xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
6110 			   xmlSchemaBasicItemPtr ownerItem,
6111 			   xmlNodePtr node)
6112 {
6113     xmlChar *value = NULL;
6114     int res = 0;
6115 
6116     value = xmlNodeGetContent(node);
6117     /*
6118     * 3.2.2.1 Lexical representation
6119     * An instance of a datatype that is defined as `boolean`
6120     * can have the following legal literals {true, false, 1, 0}.
6121     */
6122     if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
6123         res = 1;
6124     else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
6125         res = 0;
6126     else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
6127 	res = 1;
6128     else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
6129         res = 0;
6130     else {
6131         xmlSchemaPSimpleTypeErr(ctxt,
6132 	    XML_SCHEMAP_INVALID_BOOLEAN,
6133 	    ownerItem, node,
6134 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6135 	    NULL, BAD_CAST value,
6136 	    NULL, NULL, NULL);
6137     }
6138     if (value != NULL)
6139 	xmlFree(value);
6140     return (res);
6141 }
6142 
6143 /**
6144  * xmlGetBooleanProp:
6145  * @ctxt:  a schema validation context
6146  * @node:  a subtree containing XML Schema information
6147  * @name:  the attribute name
6148  * @def:  the default value
6149  *
6150  * Evaluate if a boolean property is set
6151  *
6152  * Returns the default if not found, 0 if found to be false,
6153  * 1 if found to be true
6154  */
6155 static int
xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,const char * name,int def)6156 xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
6157 		  xmlNodePtr node,
6158                   const char *name, int def)
6159 {
6160     const xmlChar *val;
6161 
6162     val = xmlSchemaGetProp(ctxt, node, name);
6163     if (val == NULL)
6164         return (def);
6165     /*
6166     * 3.2.2.1 Lexical representation
6167     * An instance of a datatype that is defined as `boolean`
6168     * can have the following legal literals {true, false, 1, 0}.
6169     */
6170     if (xmlStrEqual(val, BAD_CAST "true"))
6171         def = 1;
6172     else if (xmlStrEqual(val, BAD_CAST "false"))
6173         def = 0;
6174     else if (xmlStrEqual(val, BAD_CAST "1"))
6175 	def = 1;
6176     else if (xmlStrEqual(val, BAD_CAST "0"))
6177         def = 0;
6178     else {
6179         xmlSchemaPSimpleTypeErr(ctxt,
6180 	    XML_SCHEMAP_INVALID_BOOLEAN,
6181 	    NULL,
6182 	    (xmlNodePtr) xmlSchemaGetPropNode(node, name),
6183 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6184 	    NULL, val, NULL, NULL, NULL);
6185     }
6186     return (def);
6187 }
6188 
6189 /************************************************************************
6190  *									*
6191  *		Schema extraction from an Infoset			*
6192  *									*
6193  ************************************************************************/
6194 static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
6195                                                  ctxt, xmlSchemaPtr schema,
6196                                                  xmlNodePtr node,
6197 						 int topLevel);
6198 static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
6199                                                   ctxt,
6200                                                   xmlSchemaPtr schema,
6201                                                   xmlNodePtr node,
6202 						  int topLevel);
6203 static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
6204                                                   ctxt,
6205                                                   xmlSchemaPtr schema,
6206                                                   xmlNodePtr node,
6207 						  xmlSchemaTypeType parentType);
6208 static xmlSchemaBasicItemPtr
6209 xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
6210 			     xmlSchemaPtr schema,
6211 			     xmlNodePtr node,
6212 			     xmlSchemaItemListPtr uses,
6213 			     int parentType);
6214 static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
6215                                            xmlSchemaPtr schema,
6216                                            xmlNodePtr node);
6217 static xmlSchemaWildcardPtr
6218 xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
6219                            xmlSchemaPtr schema, xmlNodePtr node);
6220 
6221 /**
6222  * xmlSchemaPValAttrNodeValue:
6223  *
6224  * @pctxt:  a schema parser context
6225  * @ownerItem: the schema object owner if existent
6226  * @attr:  the schema attribute node being validated
6227  * @value: the value
6228  * @type: the built-in type to be validated against
6229  *
6230  * Validates a value against the given built-in type.
6231  * This one is intended to be used internally for validation
6232  * of schema attribute values during parsing of the schema.
6233  *
6234  * Returns 0 if the value is valid, a positive error code
6235  * number otherwise and -1 in case of an internal or API error.
6236  */
6237 static int
xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr pctxt,xmlSchemaBasicItemPtr ownerItem,xmlAttrPtr attr,const xmlChar * value,xmlSchemaTypePtr type)6238 xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr pctxt,
6239 			   xmlSchemaBasicItemPtr ownerItem,
6240 			   xmlAttrPtr attr,
6241 			   const xmlChar *value,
6242 			   xmlSchemaTypePtr type)
6243 {
6244 
6245     int ret = 0;
6246 
6247     /*
6248     * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
6249     * one is really meant to be used internally, so better not.
6250     */
6251     if ((pctxt == NULL) || (type == NULL) || (attr == NULL))
6252 	return (-1);
6253     if (type->type != XML_SCHEMA_TYPE_BASIC) {
6254 	PERROR_INT("xmlSchemaPValAttrNodeValue",
6255 	    "the given type is not a built-in type");
6256 	return (-1);
6257     }
6258     switch (type->builtInType) {
6259 	case XML_SCHEMAS_NCNAME:
6260 	case XML_SCHEMAS_QNAME:
6261 	case XML_SCHEMAS_ANYURI:
6262 	case XML_SCHEMAS_TOKEN:
6263 	case XML_SCHEMAS_LANGUAGE:
6264 	    ret = xmlSchemaValPredefTypeNode(type, value, NULL,
6265 		(xmlNodePtr) attr);
6266 	    break;
6267 	default: {
6268 	    PERROR_INT("xmlSchemaPValAttrNodeValue",
6269 		"validation using the given type is not supported while "
6270 		"parsing a schema");
6271 	    return (-1);
6272 	}
6273     }
6274     /*
6275     * TODO: Should we use the S4S error codes instead?
6276     */
6277     if (ret < 0) {
6278 	PERROR_INT("xmlSchemaPValAttrNodeValue",
6279 	    "failed to validate a schema attribute value");
6280 	return (-1);
6281     } else if (ret > 0) {
6282 	if (WXS_IS_LIST(type))
6283 	    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
6284 	else
6285 	    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
6286 	xmlSchemaPSimpleTypeErr(pctxt,
6287 	    ret, ownerItem, (xmlNodePtr) attr,
6288 	    type, NULL, value, NULL, NULL, NULL);
6289     }
6290     return (ret);
6291 }
6292 
6293 /**
6294  * xmlSchemaPValAttrNode:
6295  *
6296  * @ctxt:  a schema parser context
6297  * @ownerItem: the schema object owner if existent
6298  * @attr:  the schema attribute node being validated
6299  * @type: the built-in type to be validated against
6300  * @value: the resulting value if any
6301  *
6302  * Extracts and validates a value against the given built-in type.
6303  * This one is intended to be used internally for validation
6304  * of schema attribute values during parsing of the schema.
6305  *
6306  * Returns 0 if the value is valid, a positive error code
6307  * number otherwise and -1 in case of an internal or API error.
6308  */
6309 static int
xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,xmlSchemaBasicItemPtr ownerItem,xmlAttrPtr attr,xmlSchemaTypePtr type,const xmlChar ** value)6310 xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
6311 			   xmlSchemaBasicItemPtr ownerItem,
6312 			   xmlAttrPtr attr,
6313 			   xmlSchemaTypePtr type,
6314 			   const xmlChar **value)
6315 {
6316     const xmlChar *val;
6317 
6318     if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
6319 	return (-1);
6320 
6321     val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6322     if (value != NULL)
6323 	*value = val;
6324 
6325     return (xmlSchemaPValAttrNodeValue(ctxt, ownerItem, attr,
6326 	val, type));
6327 }
6328 
6329 /**
6330  * xmlSchemaPValAttr:
6331  *
6332  * @ctxt:  a schema parser context
6333  * @node: the element node of the attribute
6334  * @ownerItem: the schema object owner if existent
6335  * @ownerElem: the owner element node
6336  * @name:  the name of the schema attribute node
6337  * @type: the built-in type to be validated against
6338  * @value: the resulting value if any
6339  *
6340  * Extracts and validates a value against the given built-in type.
6341  * This one is intended to be used internally for validation
6342  * of schema attribute values during parsing of the schema.
6343  *
6344  * Returns 0 if the value is valid, a positive error code
6345  * number otherwise and -1 in case of an internal or API error.
6346  */
6347 static int
xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,xmlSchemaBasicItemPtr ownerItem,xmlNodePtr ownerElem,const char * name,xmlSchemaTypePtr type,const xmlChar ** value)6348 xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
6349 		       xmlSchemaBasicItemPtr ownerItem,
6350 		       xmlNodePtr ownerElem,
6351 		       const char *name,
6352 		       xmlSchemaTypePtr type,
6353 		       const xmlChar **value)
6354 {
6355     xmlAttrPtr attr;
6356 
6357     if ((ctxt == NULL) || (type == NULL)) {
6358 	if (value != NULL)
6359 	    *value = NULL;
6360 	return (-1);
6361     }
6362     if (type->type != XML_SCHEMA_TYPE_BASIC) {
6363 	if (value != NULL)
6364 	    *value = NULL;
6365 	xmlSchemaPErr(ctxt, ownerElem,
6366 	    XML_SCHEMAP_INTERNAL,
6367 	    "Internal error: xmlSchemaPValAttr, the given "
6368 	    "type '%s' is not a built-in type.\n",
6369 	    type->name, NULL);
6370 	return (-1);
6371     }
6372     attr = xmlSchemaGetPropNode(ownerElem, name);
6373     if (attr == NULL) {
6374 	if (value != NULL)
6375 	    *value = NULL;
6376 	return (0);
6377     }
6378     return (xmlSchemaPValAttrNode(ctxt, ownerItem, attr,
6379 	type, value));
6380 }
6381 
6382 static int
xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema ATTRIBUTE_UNUSED,xmlNodePtr node,xmlAttrPtr attr,const xmlChar * namespaceName)6383 xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,
6384 		  xmlSchemaPtr schema ATTRIBUTE_UNUSED,
6385 		  xmlNodePtr node,
6386 		  xmlAttrPtr attr,
6387 		  const xmlChar *namespaceName)
6388 {
6389     /* TODO: Pointer comparison instead? */
6390     if (xmlStrEqual(pctxt->targetNamespace, namespaceName))
6391 	return (0);
6392     if (xmlStrEqual(xmlSchemaNs, namespaceName))
6393 	return (0);
6394     /*
6395     * Check if the referenced namespace was <import>ed.
6396     */
6397     if (WXS_BUCKET(pctxt)->relations != NULL) {
6398 	xmlSchemaSchemaRelationPtr rel;
6399 
6400 	rel = WXS_BUCKET(pctxt)->relations;
6401 	do {
6402 	    if (WXS_IS_BUCKET_IMPMAIN(rel->type) &&
6403 		xmlStrEqual(namespaceName, rel->importNamespace))
6404 		return (0);
6405 	    rel = rel->next;
6406 	} while (rel != NULL);
6407     }
6408     /*
6409     * No matching <import>ed namespace found.
6410     */
6411     {
6412 	xmlNodePtr n = (attr != NULL) ? (xmlNodePtr) attr : node;
6413 
6414 	if (namespaceName == NULL)
6415 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
6416 		XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6417 		"References from this schema to components in no "
6418 		"namespace are not allowed, since not indicated by an "
6419 		"import statement", NULL, NULL);
6420 	else
6421 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
6422 		XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6423 		"References from this schema to components in the "
6424 		"namespace '%s' are not allowed, since not indicated by an "
6425 		"import statement", namespaceName, NULL);
6426     }
6427     return (XML_SCHEMAP_SRC_RESOLVE);
6428 }
6429 
6430 /**
6431  * xmlSchemaParseLocalAttributes:
6432  * @ctxt:  a schema validation context
6433  * @schema:  the schema being built
6434  * @node:  a subtree containing XML Schema information
6435  * @type:  the hosting type where the attributes will be anchored
6436  *
6437  * Parses attribute uses and attribute declarations and
6438  * attribute group references.
6439  */
6440 static int
xmlSchemaParseLocalAttributes(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr * child,xmlSchemaItemListPtr * list,int parentType,int * hasRefs)6441 xmlSchemaParseLocalAttributes(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6442                         xmlNodePtr *child, xmlSchemaItemListPtr *list,
6443 			int parentType, int *hasRefs)
6444 {
6445     void *item;
6446 
6447     while ((IS_SCHEMA((*child), "attribute")) ||
6448            (IS_SCHEMA((*child), "attributeGroup"))) {
6449         if (IS_SCHEMA((*child), "attribute")) {
6450 	    item = xmlSchemaParseLocalAttribute(ctxt, schema, *child,
6451 		*list, parentType);
6452         } else {
6453             item = xmlSchemaParseAttributeGroupRef(ctxt, schema, *child);
6454 	    if ((item != NULL) && (hasRefs != NULL))
6455 		*hasRefs = 1;
6456         }
6457 	if (item != NULL) {
6458 	    if (*list == NULL) {
6459 		/* TODO: Customize grow factor. */
6460 		*list = xmlSchemaItemListCreate();
6461 		if (*list == NULL)
6462 		    return(-1);
6463 	    }
6464 	    if (xmlSchemaItemListAddSize(*list, 2, item) == -1)
6465 		return(-1);
6466 	}
6467         *child = (*child)->next;
6468     }
6469     return (0);
6470 }
6471 
6472 /**
6473  * xmlSchemaParseAnnotation:
6474  * @ctxt:  a schema validation context
6475  * @schema:  the schema being built
6476  * @node:  a subtree containing XML Schema information
6477  *
6478  * parse a XML schema Attribute declaration
6479  * *WARNING* this interface is highly subject to change
6480  *
6481  * Returns -1 in case of error, 0 if the declaration is improper and
6482  *         1 in case of success.
6483  */
6484 static xmlSchemaAnnotPtr
xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,int needed)6485 xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int needed)
6486 {
6487     xmlSchemaAnnotPtr ret;
6488     xmlNodePtr child = NULL;
6489     xmlAttrPtr attr;
6490     int barked = 0;
6491 
6492     /*
6493     * INFO: S4S completed.
6494     */
6495     /*
6496     * id = ID
6497     * {any attributes with non-schema namespace . . .}>
6498     * Content: (appinfo | documentation)*
6499     */
6500     if ((ctxt == NULL) || (node == NULL))
6501         return (NULL);
6502     if (needed)
6503 	ret = xmlSchemaNewAnnot(ctxt, node);
6504     else
6505 	ret = NULL;
6506     attr = node->properties;
6507     while (attr != NULL) {
6508 	if (((attr->ns == NULL) &&
6509 	    (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
6510 	    ((attr->ns != NULL) &&
6511 	    xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
6512 
6513 	    xmlSchemaPIllegalAttrErr(ctxt,
6514 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6515 	}
6516 	attr = attr->next;
6517     }
6518     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6519     /*
6520     * And now for the children...
6521     */
6522     child = node->children;
6523     while (child != NULL) {
6524 	if (IS_SCHEMA(child, "appinfo")) {
6525 	    /* TODO: make available the content of "appinfo". */
6526 	    /*
6527 	    * source = anyURI
6528 	    * {any attributes with non-schema namespace . . .}>
6529 	    * Content: ({any})*
6530 	    */
6531 	    attr = child->properties;
6532 	    while (attr != NULL) {
6533 		if (((attr->ns == NULL) &&
6534 		     (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
6535 		     ((attr->ns != NULL) &&
6536 		      xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
6537 
6538 		    xmlSchemaPIllegalAttrErr(ctxt,
6539 			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6540 		}
6541 		attr = attr->next;
6542 	    }
6543 	    xmlSchemaPValAttr(ctxt, NULL, child, "source",
6544 		xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
6545 	    child = child->next;
6546 	} else if (IS_SCHEMA(child, "documentation")) {
6547 	    /* TODO: make available the content of "documentation". */
6548 	    /*
6549 	    * source = anyURI
6550 	    * {any attributes with non-schema namespace . . .}>
6551 	    * Content: ({any})*
6552 	    */
6553 	    attr = child->properties;
6554 	    while (attr != NULL) {
6555 		if (attr->ns == NULL) {
6556 		    if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
6557 			xmlSchemaPIllegalAttrErr(ctxt,
6558 			    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6559 		    }
6560 		} else {
6561 		    if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
6562 			(xmlStrEqual(attr->name, BAD_CAST "lang") &&
6563 			(!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
6564 
6565 			xmlSchemaPIllegalAttrErr(ctxt,
6566 			    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6567 		    }
6568 		}
6569 		attr = attr->next;
6570 	    }
6571 	    /*
6572 	    * Attribute "xml:lang".
6573 	    */
6574 	    attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
6575 	    if (attr != NULL)
6576 		xmlSchemaPValAttrNode(ctxt, NULL, attr,
6577 		xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
6578 	    child = child->next;
6579 	} else {
6580 	    if (!barked)
6581 		xmlSchemaPContentErr(ctxt,
6582 		    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6583 		    NULL, node, child, NULL, "(appinfo | documentation)*");
6584 	    barked = 1;
6585 	    child = child->next;
6586 	}
6587     }
6588 
6589     return (ret);
6590 }
6591 
6592 /**
6593  * xmlSchemaParseFacet:
6594  * @ctxt:  a schema validation context
6595  * @schema:  the schema being built
6596  * @node:  a subtree containing XML Schema information
6597  *
6598  * parse a XML schema Facet declaration
6599  * *WARNING* this interface is highly subject to change
6600  *
6601  * Returns the new type structure or NULL in case of error
6602  */
6603 static xmlSchemaFacetPtr
xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)6604 xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6605                     xmlNodePtr node)
6606 {
6607     xmlSchemaFacetPtr facet;
6608     xmlNodePtr child = NULL;
6609     const xmlChar *value;
6610 
6611     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6612         return (NULL);
6613 
6614     facet = xmlSchemaNewFacet();
6615     if (facet == NULL) {
6616         xmlSchemaPErrMemory(ctxt);
6617         return (NULL);
6618     }
6619     facet->node = node;
6620     value = xmlSchemaGetProp(ctxt, node, "value");
6621     if (value == NULL) {
6622         xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
6623                        "Facet %s has no value\n", node->name, NULL);
6624         xmlSchemaFreeFacet(facet);
6625         return (NULL);
6626     }
6627     if (IS_SCHEMA(node, "minInclusive")) {
6628         facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
6629     } else if (IS_SCHEMA(node, "minExclusive")) {
6630         facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
6631     } else if (IS_SCHEMA(node, "maxInclusive")) {
6632         facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
6633     } else if (IS_SCHEMA(node, "maxExclusive")) {
6634         facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
6635     } else if (IS_SCHEMA(node, "totalDigits")) {
6636         facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
6637     } else if (IS_SCHEMA(node, "fractionDigits")) {
6638         facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
6639     } else if (IS_SCHEMA(node, "pattern")) {
6640         facet->type = XML_SCHEMA_FACET_PATTERN;
6641     } else if (IS_SCHEMA(node, "enumeration")) {
6642         facet->type = XML_SCHEMA_FACET_ENUMERATION;
6643     } else if (IS_SCHEMA(node, "whiteSpace")) {
6644         facet->type = XML_SCHEMA_FACET_WHITESPACE;
6645     } else if (IS_SCHEMA(node, "length")) {
6646         facet->type = XML_SCHEMA_FACET_LENGTH;
6647     } else if (IS_SCHEMA(node, "maxLength")) {
6648         facet->type = XML_SCHEMA_FACET_MAXLENGTH;
6649     } else if (IS_SCHEMA(node, "minLength")) {
6650         facet->type = XML_SCHEMA_FACET_MINLENGTH;
6651     } else {
6652         xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
6653                        "Unknown facet type %s\n", node->name, NULL);
6654         xmlSchemaFreeFacet(facet);
6655         return (NULL);
6656     }
6657     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6658     facet->value = value;
6659     if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
6660 	(facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
6661 	const xmlChar *fixed;
6662 
6663 	fixed = xmlSchemaGetProp(ctxt, node, "fixed");
6664 	if (fixed != NULL) {
6665 	    if (xmlStrEqual(fixed, BAD_CAST "true"))
6666 		facet->fixed = 1;
6667 	}
6668     }
6669     child = node->children;
6670 
6671     if (IS_SCHEMA(child, "annotation")) {
6672         facet->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
6673         child = child->next;
6674     }
6675     if (child != NULL) {
6676         xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
6677                        "Facet %s has unexpected child content\n",
6678                        node->name, NULL);
6679     }
6680     return (facet);
6681 }
6682 
6683 /**
6684  * xmlSchemaParseWildcardNs:
6685  * @ctxt:  a schema parser context
6686  * @wildc:  the wildcard, already created
6687  * @node:  a subtree containing XML Schema information
6688  *
6689  * Parses the attribute "processContents" and "namespace"
6690  * of a xsd:anyAttribute and xsd:any.
6691  * *WARNING* this interface is highly subject to change
6692  *
6693  * Returns 0 if everything goes fine, a positive error code
6694  * if something is not valid and -1 if an internal error occurs.
6695  */
6696 static int
xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema ATTRIBUTE_UNUSED,xmlSchemaWildcardPtr wildc,xmlNodePtr node)6697 xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
6698 			 xmlSchemaPtr schema ATTRIBUTE_UNUSED,
6699 			 xmlSchemaWildcardPtr wildc,
6700 			 xmlNodePtr node)
6701 {
6702     const xmlChar *pc, *ns, *dictnsItem;
6703     int ret = 0;
6704     xmlChar *nsItem;
6705     xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
6706     xmlAttrPtr attr;
6707 
6708     pc = xmlSchemaGetProp(ctxt, node, "processContents");
6709     if ((pc == NULL)
6710         || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
6711         wildc->processContents = XML_SCHEMAS_ANY_STRICT;
6712     } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
6713         wildc->processContents = XML_SCHEMAS_ANY_SKIP;
6714     } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
6715         wildc->processContents = XML_SCHEMAS_ANY_LAX;
6716     } else {
6717         xmlSchemaPSimpleTypeErr(ctxt,
6718 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6719 	    NULL, node,
6720 	    NULL, "(strict | skip | lax)", pc,
6721 	    NULL, NULL, NULL);
6722         wildc->processContents = XML_SCHEMAS_ANY_STRICT;
6723 	ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
6724     }
6725     /*
6726      * Build the namespace constraints.
6727      */
6728     attr = xmlSchemaGetPropNode(node, "namespace");
6729     ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6730     if (ns == NULL)
6731         return (-1);
6732     if ((attr == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
6733 	wildc->any = 1;
6734     else if (xmlStrEqual(ns, BAD_CAST "##other")) {
6735 	wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
6736 	if (wildc->negNsSet == NULL) {
6737 	    return (-1);
6738 	}
6739 	wildc->negNsSet->value = ctxt->targetNamespace;
6740     } else {
6741 	const xmlChar *end, *cur;
6742 
6743 	cur = ns;
6744 	do {
6745 	    while (IS_BLANK_CH(*cur))
6746 		cur++;
6747 	    end = cur;
6748 	    while ((*end != 0) && (!(IS_BLANK_CH(*end))))
6749 		end++;
6750 	    if (end == cur)
6751 		break;
6752 	    nsItem = xmlStrndup(cur, end - cur);
6753 	    if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
6754 		    (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
6755 		xmlSchemaPSimpleTypeErr(ctxt,
6756 		    XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
6757 		    NULL, (xmlNodePtr) attr,
6758 		    NULL,
6759 		    "((##any | ##other) | List of (xs:anyURI | "
6760 		    "(##targetNamespace | ##local)))",
6761 		    nsItem, NULL, NULL, NULL);
6762 		ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
6763 	    } else {
6764 		if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
6765 		    dictnsItem = ctxt->targetNamespace;
6766 		} else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
6767 		    dictnsItem = NULL;
6768 		} else {
6769 		    /*
6770 		    * Validate the item (anyURI).
6771 		    */
6772 		    xmlSchemaPValAttrNodeValue(ctxt, NULL, attr,
6773 			nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
6774 		    dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
6775 		}
6776 		/*
6777 		* Avoid duplicate namespaces.
6778 		*/
6779 		tmp = wildc->nsSet;
6780 		while (tmp != NULL) {
6781 		    if (dictnsItem == tmp->value)
6782 			break;
6783 		    tmp = tmp->next;
6784 		}
6785 		if (tmp == NULL) {
6786 		    tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
6787 		    if (tmp == NULL) {
6788 			xmlFree(nsItem);
6789 			return (-1);
6790 		    }
6791 		    tmp->value = dictnsItem;
6792 		    tmp->next = NULL;
6793 		    if (wildc->nsSet == NULL)
6794 			wildc->nsSet = tmp;
6795 		    else if (lastNs != NULL)
6796 			lastNs->next = tmp;
6797 		    lastNs = tmp;
6798 		}
6799 
6800 	    }
6801 	    xmlFree(nsItem);
6802 	    cur = end;
6803 	} while (*cur != 0);
6804     }
6805     return (ret);
6806 }
6807 
6808 static int
xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr item ATTRIBUTE_UNUSED,xmlNodePtr node,int minOccurs,int maxOccurs)6809 xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
6810 				 xmlSchemaParticlePtr item ATTRIBUTE_UNUSED,
6811 				 xmlNodePtr node,
6812 				 int minOccurs,
6813 				 int maxOccurs) {
6814 
6815     if ((maxOccurs == 0) && ( minOccurs == 0))
6816 	return (0);
6817     if (maxOccurs != UNBOUNDED) {
6818 	/*
6819 	* TODO: Maybe we should better not create the particle,
6820 	* if min/max is invalid, since it could confuse the build of the
6821 	* content model.
6822 	*/
6823 	/*
6824 	* 3.9.6 Schema Component Constraint: Particle Correct
6825 	*
6826 	*/
6827 	if (maxOccurs < 1) {
6828 	    /*
6829 	    * 2.2 {max occurs} must be greater than or equal to 1.
6830 	    */
6831 	    xmlSchemaPCustomAttrErr(ctxt,
6832 		XML_SCHEMAP_P_PROPS_CORRECT_2_2,
6833 		NULL, NULL,
6834 		xmlSchemaGetPropNode(node, "maxOccurs"),
6835 		"The value must be greater than or equal to 1");
6836 	    return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
6837 	} else if (minOccurs > maxOccurs) {
6838 	    /*
6839 	    * 2.1 {min occurs} must not be greater than {max occurs}.
6840 	    */
6841 	    xmlSchemaPCustomAttrErr(ctxt,
6842 		XML_SCHEMAP_P_PROPS_CORRECT_2_1,
6843 		NULL, NULL,
6844 		xmlSchemaGetPropNode(node, "minOccurs"),
6845 		"The value must not be greater than the value of 'maxOccurs'");
6846 	    return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
6847 	}
6848     }
6849     return (0);
6850 }
6851 
6852 /**
6853  * xmlSchemaParseAny:
6854  * @ctxt:  a schema validation context
6855  * @schema:  the schema being built
6856  * @node:  a subtree containing XML Schema information
6857  *
6858  * Parsea a XML schema <any> element. A particle and wildcard
6859  * will be created (except if minOccurs==maxOccurs==0, in this case
6860  * nothing will be created).
6861  * *WARNING* this interface is highly subject to change
6862  *
6863  * Returns the particle or NULL in case of error or if minOccurs==maxOccurs==0
6864  */
6865 static xmlSchemaParticlePtr
xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)6866 xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6867                   xmlNodePtr node)
6868 {
6869     xmlSchemaParticlePtr particle;
6870     xmlNodePtr child = NULL;
6871     xmlSchemaWildcardPtr wild;
6872     int min, max;
6873     xmlAttrPtr attr;
6874     xmlSchemaAnnotPtr annot = NULL;
6875 
6876     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6877         return (NULL);
6878     /*
6879     * Check for illegal attributes.
6880     */
6881     attr = node->properties;
6882     while (attr != NULL) {
6883 	if (attr->ns == NULL) {
6884 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6885 		(!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
6886 		(!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
6887 	        (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6888 		(!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
6889 		xmlSchemaPIllegalAttrErr(ctxt,
6890 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6891 	    }
6892 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6893 	    xmlSchemaPIllegalAttrErr(ctxt,
6894 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6895 	}
6896 	attr = attr->next;
6897     }
6898     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6899     /*
6900     * minOccurs/maxOccurs.
6901     */
6902     max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
6903 	"(xs:nonNegativeInteger | unbounded)");
6904     min = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
6905 	"xs:nonNegativeInteger");
6906     xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
6907     /*
6908     * Create & parse the wildcard.
6909     */
6910     wild = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY, node);
6911     if (wild == NULL)
6912 	return (NULL);
6913     xmlSchemaParseWildcardNs(ctxt, schema, wild, node);
6914     /*
6915     * And now for the children...
6916     */
6917     child = node->children;
6918     if (IS_SCHEMA(child, "annotation")) {
6919         annot = xmlSchemaParseAnnotation(ctxt, child, 1);
6920         child = child->next;
6921     }
6922     if (child != NULL) {
6923 	xmlSchemaPContentErr(ctxt,
6924 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6925 	    NULL, node, child,
6926 	    NULL, "(annotation?)");
6927     }
6928     /*
6929     * No component if minOccurs==maxOccurs==0.
6930     */
6931     if ((min == 0) && (max == 0)) {
6932 	/* Don't free the wildcard, since it's already on the list. */
6933 	return (NULL);
6934     }
6935     /*
6936     * Create the particle.
6937     */
6938     particle = xmlSchemaAddParticle(ctxt, node, min, max);
6939     if (particle == NULL)
6940         return (NULL);
6941     particle->annot = annot;
6942     particle->children = (xmlSchemaTreeItemPtr) wild;
6943 
6944     return (particle);
6945 }
6946 
6947 /**
6948  * xmlSchemaParseNotation:
6949  * @ctxt:  a schema validation context
6950  * @schema:  the schema being built
6951  * @node:  a subtree containing XML Schema information
6952  *
6953  * parse a XML schema Notation declaration
6954  *
6955  * Returns the new structure or NULL in case of error
6956  */
6957 static xmlSchemaNotationPtr
xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)6958 xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6959                        xmlNodePtr node)
6960 {
6961     const xmlChar *name;
6962     xmlSchemaNotationPtr ret;
6963     xmlNodePtr child = NULL;
6964 
6965     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6966         return (NULL);
6967     name = xmlSchemaGetProp(ctxt, node, "name");
6968     if (name == NULL) {
6969         xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
6970                        "Notation has no name\n", NULL, NULL);
6971         return (NULL);
6972     }
6973     ret = xmlSchemaAddNotation(ctxt, schema, name,
6974 	ctxt->targetNamespace, node);
6975     if (ret == NULL)
6976         return (NULL);
6977     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6978 
6979     child = node->children;
6980     if (IS_SCHEMA(child, "annotation")) {
6981         ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
6982         child = child->next;
6983     }
6984     if (child != NULL) {
6985 	xmlSchemaPContentErr(ctxt,
6986 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6987 	    NULL, node, child,
6988 	    NULL, "(annotation?)");
6989     }
6990 
6991     return (ret);
6992 }
6993 
6994 /**
6995  * xmlSchemaParseAnyAttribute:
6996  * @ctxt:  a schema validation context
6997  * @schema:  the schema being built
6998  * @node:  a subtree containing XML Schema information
6999  *
7000  * parse a XML schema AnyAttribute declaration
7001  * *WARNING* this interface is highly subject to change
7002  *
7003  * Returns a wildcard or NULL.
7004  */
7005 static xmlSchemaWildcardPtr
xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)7006 xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
7007                            xmlSchemaPtr schema, xmlNodePtr node)
7008 {
7009     xmlSchemaWildcardPtr ret;
7010     xmlNodePtr child = NULL;
7011     xmlAttrPtr attr;
7012 
7013     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7014         return (NULL);
7015 
7016     ret = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
7017 	node);
7018     if (ret == NULL) {
7019         return (NULL);
7020     }
7021     /*
7022     * Check for illegal attributes.
7023     */
7024     attr = node->properties;
7025     while (attr != NULL) {
7026 	if (attr->ns == NULL) {
7027 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7028 	        (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
7029 		(!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
7030 		xmlSchemaPIllegalAttrErr(ctxt,
7031 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7032 	    }
7033 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7034 	    xmlSchemaPIllegalAttrErr(ctxt,
7035 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7036 	}
7037 	attr = attr->next;
7038     }
7039     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
7040     /*
7041     * Parse the namespace list.
7042     */
7043     if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0)
7044 	return (NULL);
7045     /*
7046     * And now for the children...
7047     */
7048     child = node->children;
7049     if (IS_SCHEMA(child, "annotation")) {
7050         ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
7051         child = child->next;
7052     }
7053     if (child != NULL) {
7054 	xmlSchemaPContentErr(ctxt,
7055 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7056 	    NULL, node, child,
7057 	    NULL, "(annotation?)");
7058     }
7059 
7060     return (ret);
7061 }
7062 
7063 
7064 /**
7065  * xmlSchemaParseAttribute:
7066  * @ctxt:  a schema validation context
7067  * @schema:  the schema being built
7068  * @node:  a subtree containing XML Schema information
7069  *
7070  * parse a XML schema Attribute declaration
7071  * *WARNING* this interface is highly subject to change
7072  *
7073  * Returns the attribute declaration.
7074  */
7075 static xmlSchemaBasicItemPtr
xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node,xmlSchemaItemListPtr uses,int parentType)7076 xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
7077 			     xmlSchemaPtr schema,
7078 			     xmlNodePtr node,
7079 			     xmlSchemaItemListPtr uses,
7080 			     int parentType)
7081 {
7082     const xmlChar *attrValue, *name = NULL, *ns = NULL;
7083     xmlSchemaAttributeUsePtr use = NULL;
7084     xmlNodePtr child = NULL;
7085     xmlAttrPtr attr;
7086     const xmlChar *tmpNs = NULL, *tmpName = NULL, *defValue = NULL;
7087     int isRef = 0, occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7088     int	nberrors, hasForm = 0, defValueType = 0;
7089 
7090 #define WXS_ATTR_DEF_VAL_DEFAULT 1
7091 #define WXS_ATTR_DEF_VAL_FIXED 2
7092 
7093     /*
7094      * 3.2.3 Constraints on XML Representations of Attribute Declarations
7095      */
7096 
7097     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7098         return (NULL);
7099     attr = xmlSchemaGetPropNode(node, "ref");
7100     if (attr != NULL) {
7101 	if (xmlSchemaPValAttrNodeQName(pctxt, schema,
7102 	    NULL, attr, &tmpNs, &tmpName) != 0) {
7103 	    return (NULL);
7104 	}
7105 	if (xmlSchemaCheckReference(pctxt, schema, node, attr, tmpNs) != 0)
7106 	    return(NULL);
7107 	isRef = 1;
7108     }
7109     nberrors = pctxt->nberrors;
7110     /*
7111     * Check for illegal attributes.
7112     */
7113     attr = node->properties;
7114     while (attr != NULL) {
7115 	if (attr->ns == NULL) {
7116 	    if (isRef) {
7117 		if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7118 		    xmlSchemaPValAttrNodeID(pctxt, attr);
7119 		    goto attr_next;
7120 		} else if (xmlStrEqual(attr->name, BAD_CAST "ref")) {
7121 		    goto attr_next;
7122 		}
7123 	    } else {
7124 		if (xmlStrEqual(attr->name, BAD_CAST "name")) {
7125 		    goto attr_next;
7126 		} else if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7127 		    xmlSchemaPValAttrNodeID(pctxt, attr);
7128 		    goto attr_next;
7129 		} else if (xmlStrEqual(attr->name, BAD_CAST "type")) {
7130 		    xmlSchemaPValAttrNodeQName(pctxt, schema, NULL,
7131 			attr, &tmpNs, &tmpName);
7132 		    goto attr_next;
7133 		} else if (xmlStrEqual(attr->name, BAD_CAST "form")) {
7134 		    /*
7135 		    * Evaluate the target namespace
7136 		    */
7137 		    hasForm = 1;
7138 		    attrValue = xmlSchemaGetNodeContent(pctxt,
7139 			(xmlNodePtr) attr);
7140 		    if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
7141 			ns = pctxt->targetNamespace;
7142 		    } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified"))
7143 		    {
7144 			xmlSchemaPSimpleTypeErr(pctxt,
7145 			    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7146 			    NULL, (xmlNodePtr) attr,
7147 			    NULL, "(qualified | unqualified)",
7148 			    attrValue, NULL, NULL, NULL);
7149 		    }
7150 		    goto attr_next;
7151 		}
7152 	    }
7153 	    if (xmlStrEqual(attr->name, BAD_CAST "use")) {
7154 
7155 		attrValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7156 		/* TODO: Maybe we need to normalize the value beforehand. */
7157 		if (xmlStrEqual(attrValue, BAD_CAST "optional"))
7158 		    occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7159 		else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
7160 		    occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
7161 		else if (xmlStrEqual(attrValue, BAD_CAST "required"))
7162 		    occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
7163 		else {
7164 		    xmlSchemaPSimpleTypeErr(pctxt,
7165 			XML_SCHEMAP_INVALID_ATTR_USE,
7166 			NULL, (xmlNodePtr) attr,
7167 			NULL, "(optional | prohibited | required)",
7168 			attrValue, NULL, NULL, NULL);
7169 		}
7170 		goto attr_next;
7171 	    } else if (xmlStrEqual(attr->name, BAD_CAST "default")) {
7172 		/*
7173 		* 3.2.3 : 1
7174 		* default and fixed must not both be present.
7175 		*/
7176 		if (defValue) {
7177 		    xmlSchemaPMutualExclAttrErr(pctxt,
7178 			XML_SCHEMAP_SRC_ATTRIBUTE_1,
7179 			NULL, attr, "default", "fixed");
7180 		} else {
7181 		    defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7182 		    defValueType = WXS_ATTR_DEF_VAL_DEFAULT;
7183 		}
7184 		goto attr_next;
7185 	    } else if (xmlStrEqual(attr->name, BAD_CAST "fixed")) {
7186 		/*
7187 		* 3.2.3 : 1
7188 		* default and fixed must not both be present.
7189 		*/
7190 		if (defValue) {
7191 		    xmlSchemaPMutualExclAttrErr(pctxt,
7192 			XML_SCHEMAP_SRC_ATTRIBUTE_1,
7193 			NULL, attr, "default", "fixed");
7194 		} else {
7195 		    defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7196 		    defValueType = WXS_ATTR_DEF_VAL_FIXED;
7197 		}
7198 		goto attr_next;
7199 	    }
7200 	} else if (! xmlStrEqual(attr->ns->href, xmlSchemaNs))
7201 	    goto attr_next;
7202 
7203 	xmlSchemaPIllegalAttrErr(pctxt,
7204 	    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7205 
7206 attr_next:
7207 	attr = attr->next;
7208     }
7209     /*
7210     * 3.2.3 : 2
7211     * If default and use are both present, use must have
7212     * the actual value optional.
7213     */
7214     if ((defValueType == WXS_ATTR_DEF_VAL_DEFAULT) &&
7215 	(occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL)) {
7216 	xmlSchemaPSimpleTypeErr(pctxt,
7217 	    XML_SCHEMAP_SRC_ATTRIBUTE_2,
7218 	    NULL, node, NULL,
7219 	    "(optional | prohibited | required)", NULL,
7220 	    "The value of the attribute 'use' must be 'optional' "
7221 	    "if the attribute 'default' is present",
7222 	    NULL, NULL);
7223     }
7224     /*
7225     * We want correct attributes.
7226     */
7227     if (nberrors != pctxt->nberrors)
7228 	return(NULL);
7229     if (! isRef) {
7230 	xmlSchemaAttributePtr attrDecl;
7231 
7232 	/* TODO: move XML_SCHEMAS_QUALIF_ATTR to the parser. */
7233 	if ((! hasForm) && (schema->flags & XML_SCHEMAS_QUALIF_ATTR))
7234 	    ns = pctxt->targetNamespace;
7235 	/*
7236 	* 3.2.6 Schema Component Constraint: xsi: Not Allowed
7237 	* TODO: Move this to the component layer.
7238 	*/
7239 	if (xmlStrEqual(ns, xmlSchemaInstanceNs)) {
7240 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
7241 		XML_SCHEMAP_NO_XSI,
7242 		node, NULL,
7243 		"The target namespace must not match '%s'",
7244 		xmlSchemaInstanceNs, NULL);
7245 	}
7246 	attr = xmlSchemaGetPropNode(node, "name");
7247 	if (attr == NULL) {
7248 	    xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7249 		NULL, node, "name", NULL);
7250 	    return (NULL);
7251 	}
7252 	if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7253 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7254 	    return (NULL);
7255 	}
7256 	/*
7257 	* 3.2.6 Schema Component Constraint: xmlns Not Allowed
7258 	* TODO: Move this to the component layer.
7259 	*/
7260 	if (xmlStrEqual(name, BAD_CAST "xmlns")) {
7261 	    xmlSchemaPSimpleTypeErr(pctxt,
7262 		XML_SCHEMAP_NO_XMLNS,
7263 		NULL, (xmlNodePtr) attr,
7264 		xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7265 		"The value of the attribute must not match 'xmlns'",
7266 		NULL, NULL);
7267 	    return (NULL);
7268 	}
7269 	if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED)
7270 	    goto check_children;
7271 	/*
7272 	* Create the attribute use component.
7273 	*/
7274 	use = xmlSchemaAddAttributeUse(pctxt, node);
7275 	if (use == NULL)
7276 	    return(NULL);
7277 	use->occurs = occurs;
7278 	/*
7279 	* Create the attribute declaration.
7280 	*/
7281 	attrDecl = xmlSchemaAddAttribute(pctxt, schema, name, ns, node, 0);
7282 	if (attrDecl == NULL)
7283 	    return (NULL);
7284 	if (tmpName != NULL) {
7285 	    attrDecl->typeName = tmpName;
7286 	    attrDecl->typeNs = tmpNs;
7287 	}
7288 	use->attrDecl = attrDecl;
7289 	/*
7290 	* Value constraint.
7291 	*/
7292 	if (defValue != NULL) {
7293 	    attrDecl->defValue = defValue;
7294 	    if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7295 		attrDecl->flags |= XML_SCHEMAS_ATTR_FIXED;
7296 	}
7297     } else if (occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7298 	xmlSchemaQNameRefPtr ref;
7299 
7300 	/*
7301 	* Create the attribute use component.
7302 	*/
7303 	use = xmlSchemaAddAttributeUse(pctxt, node);
7304 	if (use == NULL)
7305 	    return(NULL);
7306 	/*
7307 	* We need to resolve the reference at later stage.
7308 	*/
7309 	WXS_ADD_PENDING(pctxt, use);
7310 	use->occurs = occurs;
7311 	/*
7312 	* Create a QName reference to the attribute declaration.
7313 	*/
7314 	ref = xmlSchemaNewQNameRef(pctxt, XML_SCHEMA_TYPE_ATTRIBUTE,
7315 	    tmpName, tmpNs);
7316 	if (ref == NULL)
7317 	    return(NULL);
7318 	/*
7319 	* Assign the reference. This will be substituted for the
7320 	* referenced attribute declaration when the QName is resolved.
7321 	*/
7322 	use->attrDecl = WXS_ATTR_CAST ref;
7323 	/*
7324 	* Value constraint.
7325 	*/
7326 	if (defValue != NULL)
7327 	    use->defValue = defValue;
7328 	if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7329 	    use->flags |= XML_SCHEMA_ATTR_USE_FIXED;
7330     }
7331 
7332 check_children:
7333     /*
7334     * And now for the children...
7335     */
7336     child = node->children;
7337     if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7338 	xmlSchemaAttributeUseProhibPtr prohib;
7339 
7340 	if (IS_SCHEMA(child, "annotation")) {
7341 	    xmlSchemaParseAnnotation(pctxt, child, 0);
7342 	    child = child->next;
7343 	}
7344 	if (child != NULL) {
7345 	    xmlSchemaPContentErr(pctxt,
7346 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7347 		NULL, node, child, NULL,
7348 		"(annotation?)");
7349 	}
7350 	/*
7351 	* Check for pointlessness of attribute prohibitions.
7352 	*/
7353 	if (parentType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
7354 	    xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7355 		XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7356 		node, NULL,
7357 		"Skipping attribute use prohibition, since it is "
7358 		"pointless inside an <attributeGroup>",
7359 		NULL, NULL, NULL);
7360 	    return(NULL);
7361 	} else if (parentType == XML_SCHEMA_TYPE_EXTENSION) {
7362 	    xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7363 		XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7364 		node, NULL,
7365 		"Skipping attribute use prohibition, since it is "
7366 		"pointless when extending a type",
7367 		NULL, NULL, NULL);
7368 	    return(NULL);
7369 	}
7370 	if (! isRef) {
7371 	    tmpName = name;
7372 	    tmpNs = ns;
7373 	}
7374 	/*
7375 	* Check for duplicate attribute prohibitions.
7376 	*/
7377 	if (uses) {
7378 	    int i;
7379 
7380 	    for (i = 0; i < uses->nbItems; i++) {
7381 		use = uses->items[i];
7382 		if ((use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) &&
7383 		    (tmpName == (WXS_ATTR_PROHIB_CAST use)->name) &&
7384 		    (tmpNs == (WXS_ATTR_PROHIB_CAST use)->targetNamespace))
7385 		{
7386 		    xmlChar *str = NULL;
7387 
7388 		    xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7389 			XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7390 			node, NULL,
7391 			"Skipping duplicate attribute use prohibition '%s'",
7392 			xmlSchemaFormatQName(&str, tmpNs, tmpName),
7393 			NULL, NULL);
7394 		    FREE_AND_NULL(str)
7395 		    return(NULL);
7396 		}
7397 	    }
7398 	}
7399 	/*
7400 	* Create the attribute prohibition helper component.
7401 	*/
7402 	prohib = xmlSchemaAddAttributeUseProhib(pctxt);
7403 	if (prohib == NULL)
7404 	    return(NULL);
7405 	prohib->node = node;
7406 	prohib->name = tmpName;
7407 	prohib->targetNamespace = tmpNs;
7408 	if (isRef) {
7409 	    /*
7410 	    * We need at least to resolve to the attribute declaration.
7411 	    */
7412 	    WXS_ADD_PENDING(pctxt, prohib);
7413 	}
7414 	return(WXS_BASIC_CAST prohib);
7415     } else {
7416 	if (IS_SCHEMA(child, "annotation")) {
7417 	    /*
7418 	    * TODO: Should this go into the attr decl?
7419 	    */
7420 	    use->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7421 	    child = child->next;
7422 	}
7423 	if (isRef) {
7424 	    if (child != NULL) {
7425 		if (IS_SCHEMA(child, "simpleType"))
7426 		    /*
7427 		    * 3.2.3 : 3.2
7428 		    * If ref is present, then all of <simpleType>,
7429 		    * form and type must be absent.
7430 		    */
7431 		    xmlSchemaPContentErr(pctxt,
7432 			XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
7433 			NULL, node, child, NULL,
7434 			"(annotation?)");
7435 		else
7436 		    xmlSchemaPContentErr(pctxt,
7437 			XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7438 			NULL, node, child, NULL,
7439 			"(annotation?)");
7440 	    }
7441 	} else {
7442 	    if (IS_SCHEMA(child, "simpleType")) {
7443 		if (WXS_ATTRUSE_DECL(use)->typeName != NULL) {
7444 		    /*
7445 		    * 3.2.3 : 4
7446 		    * type and <simpleType> must not both be present.
7447 		    */
7448 		    xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7449 			NULL, node, child,
7450 			"The attribute 'type' and the <simpleType> child "
7451 			"are mutually exclusive", NULL);
7452 		} else
7453 		    WXS_ATTRUSE_TYPEDEF(use) =
7454 			xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7455 		child = child->next;
7456 	    }
7457 	    if (child != NULL)
7458 		xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7459 		NULL, node, child, NULL,
7460 		"(annotation?, simpleType?)");
7461 	}
7462     }
7463     return (WXS_BASIC_CAST use);
7464 }
7465 
7466 
7467 static xmlSchemaAttributePtr
xmlSchemaParseGlobalAttribute(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node)7468 xmlSchemaParseGlobalAttribute(xmlSchemaParserCtxtPtr pctxt,
7469 			      xmlSchemaPtr schema,
7470 			      xmlNodePtr node)
7471 {
7472     const xmlChar *attrValue;
7473     xmlSchemaAttributePtr ret;
7474     xmlNodePtr child = NULL;
7475     xmlAttrPtr attr;
7476 
7477     /*
7478      * Note that the w3c spec assumes the schema to be validated with schema
7479      * for schemas beforehand.
7480      *
7481      * 3.2.3 Constraints on XML Representations of Attribute Declarations
7482      */
7483     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7484         return (NULL);
7485     /*
7486     * 3.2.3 : 3.1
7487     * One of ref or name must be present, but not both
7488     */
7489     attr = xmlSchemaGetPropNode(node, "name");
7490     if (attr == NULL) {
7491 	xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7492 	    NULL, node, "name", NULL);
7493 	return (NULL);
7494     }
7495     if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7496 	xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
7497 	return (NULL);
7498     }
7499     /*
7500     * 3.2.6 Schema Component Constraint: xmlns Not Allowed
7501     * TODO: Move this to the component layer.
7502     */
7503     if (xmlStrEqual(attrValue, BAD_CAST "xmlns")) {
7504 	xmlSchemaPSimpleTypeErr(pctxt,
7505 	    XML_SCHEMAP_NO_XMLNS,
7506 	    NULL, (xmlNodePtr) attr,
7507 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7508 	    "The value of the attribute must not match 'xmlns'",
7509 	    NULL, NULL);
7510 	return (NULL);
7511     }
7512     /*
7513     * 3.2.6 Schema Component Constraint: xsi: Not Allowed
7514     * TODO: Move this to the component layer.
7515     *       Or better leave it here and add it to the component layer
7516     *       if we have a schema construction API.
7517     */
7518     if (xmlStrEqual(pctxt->targetNamespace, xmlSchemaInstanceNs)) {
7519 	xmlSchemaCustomErr(ACTXT_CAST pctxt,
7520 	    XML_SCHEMAP_NO_XSI, node, NULL,
7521 	    "The target namespace must not match '%s'",
7522 	    xmlSchemaInstanceNs, NULL);
7523     }
7524 
7525     ret = xmlSchemaAddAttribute(pctxt, schema, attrValue,
7526 	pctxt->targetNamespace, node, 1);
7527     if (ret == NULL)
7528 	return (NULL);
7529     ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
7530 
7531     /*
7532     * Check for illegal attributes.
7533     */
7534     attr = node->properties;
7535     while (attr != NULL) {
7536 	if (attr->ns == NULL) {
7537 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7538 		(!xmlStrEqual(attr->name, BAD_CAST "default")) &&
7539 		(!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
7540 		(!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7541 		(!xmlStrEqual(attr->name, BAD_CAST "type")))
7542 	    {
7543 		xmlSchemaPIllegalAttrErr(pctxt,
7544 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7545 	    }
7546 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7547 	    xmlSchemaPIllegalAttrErr(pctxt,
7548 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7549 	}
7550 	attr = attr->next;
7551     }
7552     xmlSchemaPValAttrQName(pctxt, schema, NULL,
7553 	node, "type", &ret->typeNs, &ret->typeName);
7554 
7555     xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7556     /*
7557     * Attribute "fixed".
7558     */
7559     ret->defValue = xmlSchemaGetProp(pctxt, node, "fixed");
7560     if (ret->defValue != NULL)
7561 	ret->flags |= XML_SCHEMAS_ATTR_FIXED;
7562     /*
7563     * Attribute "default".
7564     */
7565     attr = xmlSchemaGetPropNode(node, "default");
7566     if (attr != NULL) {
7567 	/*
7568 	* 3.2.3 : 1
7569 	* default and fixed must not both be present.
7570 	*/
7571 	if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
7572 	    xmlSchemaPMutualExclAttrErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
7573 		WXS_BASIC_CAST ret, attr, "default", "fixed");
7574 	} else
7575 	    ret->defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7576     }
7577     /*
7578     * And now for the children...
7579     */
7580     child = node->children;
7581     if (IS_SCHEMA(child, "annotation")) {
7582         ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7583         child = child->next;
7584     }
7585     if (IS_SCHEMA(child, "simpleType")) {
7586 	if (ret->typeName != NULL) {
7587 	    /*
7588 	    * 3.2.3 : 4
7589 	    * type and <simpleType> must not both be present.
7590 	    */
7591 	    xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7592 		NULL, node, child,
7593 		"The attribute 'type' and the <simpleType> child "
7594 		"are mutually exclusive", NULL);
7595 	} else
7596 	    ret->subtypes = xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7597 	child = child->next;
7598     }
7599     if (child != NULL)
7600 	xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7601 	    NULL, node, child, NULL,
7602 	    "(annotation?, simpleType?)");
7603 
7604     return (ret);
7605 }
7606 
7607 /**
7608  * xmlSchemaParseAttributeGroupRef:
7609  * @ctxt:  a schema validation context
7610  * @schema:  the schema being built
7611  * @node:  a subtree containing XML Schema information
7612  *
7613  * Parse an attribute group definition reference.
7614  * Note that a reference to an attribute group does not
7615  * correspond to any component at all.
7616  * *WARNING* this interface is highly subject to change
7617  *
7618  * Returns the attribute group or NULL in case of error.
7619  */
7620 static xmlSchemaQNameRefPtr
xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node)7621 xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,
7622 				xmlSchemaPtr schema,
7623 				xmlNodePtr node)
7624 {
7625     xmlSchemaQNameRefPtr ret;
7626     xmlNodePtr child = NULL;
7627     xmlAttrPtr attr;
7628     const xmlChar *refNs = NULL, *ref = NULL;
7629 
7630     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7631         return (NULL);
7632 
7633     attr = xmlSchemaGetPropNode(node, "ref");
7634     if (attr == NULL) {
7635 	xmlSchemaPMissingAttrErr(pctxt,
7636 	    XML_SCHEMAP_S4S_ATTR_MISSING,
7637 	    NULL, node, "ref", NULL);
7638 	return (NULL);
7639     }
7640     xmlSchemaPValAttrNodeQName(pctxt, schema,
7641 	NULL, attr, &refNs, &ref);
7642     if (xmlSchemaCheckReference(pctxt, schema, node, attr, refNs) != 0)
7643 	return(NULL);
7644 
7645     /*
7646     * Check for illegal attributes.
7647     */
7648     attr = node->properties;
7649     while (attr != NULL) {
7650 	if (attr->ns == NULL) {
7651 	    if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
7652 		(!xmlStrEqual(attr->name, BAD_CAST "id")))
7653 	    {
7654 		xmlSchemaPIllegalAttrErr(pctxt,
7655 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7656 	    }
7657 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7658 	    xmlSchemaPIllegalAttrErr(pctxt,
7659 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7660 	}
7661 	attr = attr->next;
7662     }
7663     /* Attribute ID */
7664     xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7665 
7666     /*
7667     * And now for the children...
7668     */
7669     child = node->children;
7670     if (IS_SCHEMA(child, "annotation")) {
7671 	/*
7672 	* TODO: We do not have a place to store the annotation, do we?
7673 	*/
7674         xmlSchemaParseAnnotation(pctxt, child, 0);
7675         child = child->next;
7676     }
7677     if (child != NULL) {
7678 	xmlSchemaPContentErr(pctxt,
7679 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7680 	    NULL, node, child, NULL,
7681 	    "(annotation?)");
7682     }
7683 
7684     /*
7685     * Handle attribute group redefinitions.
7686     */
7687     if (pctxt->isRedefine && pctxt->redef &&
7688 	(pctxt->redef->item->type ==
7689 	    XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
7690 	(ref == pctxt->redef->refName) &&
7691 	(refNs == pctxt->redef->refTargetNs))
7692     {
7693 	/*
7694 	* SPEC src-redefine:
7695 	* (7.1) "If it has an <attributeGroup> among its contents
7696 	* the `actual value` of whose ref [attribute] is the same
7697 	* as the `actual value` of its own name attribute plus
7698 	* target namespace, then it must have exactly one such group."
7699 	*/
7700 	if (pctxt->redefCounter != 0) {
7701 	    xmlChar *str = NULL;
7702 
7703 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
7704 		XML_SCHEMAP_SRC_REDEFINE, node, NULL,
7705 		"The redefining attribute group definition "
7706 		"'%s' must not contain more than one "
7707 		"reference to the redefined definition",
7708 		xmlSchemaFormatQName(&str, refNs, ref), NULL);
7709 	    FREE_AND_NULL(str);
7710 	    return(NULL);
7711 	}
7712 	pctxt->redefCounter++;
7713 	/*
7714 	* URGENT TODO: How to ensure that the reference will not be
7715 	* handled by the normal component resolution mechanism?
7716 	*/
7717 	ret = xmlSchemaNewQNameRef(pctxt,
7718 	    XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7719 	if (ret == NULL)
7720 	    return(NULL);
7721 	ret->node = node;
7722 	pctxt->redef->reference = WXS_BASIC_CAST ret;
7723     } else {
7724 	/*
7725 	* Create a QName-reference helper component. We will substitute this
7726 	* component for the attribute uses of the referenced attribute group
7727 	* definition.
7728 	*/
7729 	ret = xmlSchemaNewQNameRef(pctxt,
7730 	    XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7731 	if (ret == NULL)
7732 	    return(NULL);
7733 	ret->node = node;
7734 	/* Add to pending items, to be able to resolve the reference. */
7735 	WXS_ADD_PENDING(pctxt, ret);
7736     }
7737     return (ret);
7738 }
7739 
7740 /**
7741  * xmlSchemaParseAttributeGroupDefinition:
7742  * @pctxt:  a schema validation context
7743  * @schema:  the schema being built
7744  * @node:  a subtree containing XML Schema information
7745  *
7746  * parse a XML schema Attribute Group declaration
7747  * *WARNING* this interface is highly subject to change
7748  *
7749  * Returns the attribute group definition or NULL in case of error.
7750  */
7751 static xmlSchemaAttributeGroupPtr
xmlSchemaParseAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node)7752 xmlSchemaParseAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
7753 				       xmlSchemaPtr schema,
7754 				       xmlNodePtr node)
7755 {
7756     const xmlChar *name;
7757     xmlSchemaAttributeGroupPtr ret;
7758     xmlNodePtr child = NULL;
7759     xmlAttrPtr attr;
7760     int hasRefs = 0;
7761 
7762     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7763         return (NULL);
7764 
7765     attr = xmlSchemaGetPropNode(node, "name");
7766     if (attr == NULL) {
7767 	xmlSchemaPMissingAttrErr(pctxt,
7768 	    XML_SCHEMAP_S4S_ATTR_MISSING,
7769 	    NULL, node, "name", NULL);
7770 	return (NULL);
7771     }
7772     /*
7773     * The name is crucial, exit if invalid.
7774     */
7775     if (xmlSchemaPValAttrNode(pctxt,
7776 	NULL, attr,
7777 	xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7778 	return (NULL);
7779     }
7780     ret = xmlSchemaAddAttributeGroupDefinition(pctxt, schema,
7781 	name, pctxt->targetNamespace, node);
7782     if (ret == NULL)
7783 	return (NULL);
7784     /*
7785     * Check for illegal attributes.
7786     */
7787     attr = node->properties;
7788     while (attr != NULL) {
7789 	if (attr->ns == NULL) {
7790 	    if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7791 		(!xmlStrEqual(attr->name, BAD_CAST "id")))
7792 	    {
7793 		xmlSchemaPIllegalAttrErr(pctxt,
7794 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7795 	    }
7796 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7797 	    xmlSchemaPIllegalAttrErr(pctxt,
7798 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7799 	}
7800 	attr = attr->next;
7801     }
7802     /* Attribute ID */
7803     xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7804     /*
7805     * And now for the children...
7806     */
7807     child = node->children;
7808     if (IS_SCHEMA(child, "annotation")) {
7809         ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7810         child = child->next;
7811     }
7812     /*
7813     * Parse contained attribute decls/refs.
7814     */
7815     if (xmlSchemaParseLocalAttributes(pctxt, schema, &child,
7816 	(xmlSchemaItemListPtr *) &(ret->attrUses),
7817 	XML_SCHEMA_TYPE_ATTRIBUTEGROUP, &hasRefs) == -1)
7818 	return(NULL);
7819     if (hasRefs)
7820 	ret->flags |= XML_SCHEMAS_ATTRGROUP_HAS_REFS;
7821     /*
7822     * Parse the attribute wildcard.
7823     */
7824     if (IS_SCHEMA(child, "anyAttribute")) {
7825 	ret->attributeWildcard = xmlSchemaParseAnyAttribute(pctxt,
7826 	    schema, child);
7827 	child = child->next;
7828     }
7829     if (child != NULL) {
7830 	xmlSchemaPContentErr(pctxt,
7831 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7832 	    NULL, node, child, NULL,
7833 	    "(annotation?, ((attribute | attributeGroup)*, anyAttribute?))");
7834     }
7835     return (ret);
7836 }
7837 
7838 /**
7839  * xmlSchemaPValAttrFormDefault:
7840  * @value:  the value
7841  * @flags: the flags to be modified
7842  * @flagQualified: the specific flag for "qualified"
7843  *
7844  * Returns 0 if the value is valid, 1 otherwise.
7845  */
7846 static int
xmlSchemaPValAttrFormDefault(const xmlChar * value,int * flags,int flagQualified)7847 xmlSchemaPValAttrFormDefault(const xmlChar *value,
7848 			     int *flags,
7849 			     int flagQualified)
7850 {
7851     if (xmlStrEqual(value, BAD_CAST "qualified")) {
7852 	if  ((*flags & flagQualified) == 0)
7853 	    *flags |= flagQualified;
7854     } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
7855 	return (1);
7856 
7857     return (0);
7858 }
7859 
7860 /**
7861  * xmlSchemaPValAttrBlockFinal:
7862  * @value:  the value
7863  * @flags: the flags to be modified
7864  * @flagAll: the specific flag for "#all"
7865  * @flagExtension: the specific flag for "extension"
7866  * @flagRestriction: the specific flag for "restriction"
7867  * @flagSubstitution: the specific flag for "substitution"
7868  * @flagList: the specific flag for "list"
7869  * @flagUnion: the specific flag for "union"
7870  *
7871  * Validates the value of the attribute "final" and "block". The value
7872  * is converted into the specified flag values and returned in @flags.
7873  *
7874  * Returns 0 if the value is valid, 1 otherwise.
7875  */
7876 
7877 static int
xmlSchemaPValAttrBlockFinal(const xmlChar * value,int * flags,int flagAll,int flagExtension,int flagRestriction,int flagSubstitution,int flagList,int flagUnion)7878 xmlSchemaPValAttrBlockFinal(const xmlChar *value,
7879 			    int *flags,
7880 			    int flagAll,
7881 			    int flagExtension,
7882 			    int flagRestriction,
7883 			    int flagSubstitution,
7884 			    int flagList,
7885 			    int flagUnion)
7886 {
7887     int ret = 0;
7888 
7889     /*
7890     * TODO: This does not check for duplicate entries.
7891     */
7892     if ((flags == NULL) || (value == NULL))
7893 	return (-1);
7894     if (value[0] == 0)
7895 	return (0);
7896     if (xmlStrEqual(value, BAD_CAST "#all")) {
7897 	if (flagAll != -1)
7898 	    *flags |= flagAll;
7899 	else {
7900 	    if (flagExtension != -1)
7901 		*flags |= flagExtension;
7902 	    if (flagRestriction != -1)
7903 		*flags |= flagRestriction;
7904 	    if (flagSubstitution != -1)
7905 		*flags |= flagSubstitution;
7906 	    if (flagList != -1)
7907 		*flags |= flagList;
7908 	    if (flagUnion != -1)
7909 		*flags |= flagUnion;
7910 	}
7911     } else {
7912 	const xmlChar *end, *cur = value;
7913 	xmlChar *item;
7914 
7915 	do {
7916 	    while (IS_BLANK_CH(*cur))
7917 		cur++;
7918 	    end = cur;
7919 	    while ((*end != 0) && (!(IS_BLANK_CH(*end))))
7920 		end++;
7921 	    if (end == cur)
7922 		break;
7923 	    item = xmlStrndup(cur, end - cur);
7924 	    if (xmlStrEqual(item, BAD_CAST "extension")) {
7925 		if (flagExtension != -1) {
7926 		    if ((*flags & flagExtension) == 0)
7927 			*flags |= flagExtension;
7928 		} else
7929 		    ret = 1;
7930 	    } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
7931 		if (flagRestriction != -1) {
7932 		    if ((*flags & flagRestriction) == 0)
7933 			*flags |= flagRestriction;
7934 		} else
7935 		    ret = 1;
7936 	    } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
7937 		if (flagSubstitution != -1) {
7938 		    if ((*flags & flagSubstitution) == 0)
7939 			*flags |= flagSubstitution;
7940 		} else
7941 		    ret = 1;
7942 	    } else if (xmlStrEqual(item, BAD_CAST "list")) {
7943 		if (flagList != -1) {
7944 		    if ((*flags & flagList) == 0)
7945 			*flags |= flagList;
7946 		} else
7947 		    ret = 1;
7948 	    } else if (xmlStrEqual(item, BAD_CAST "union")) {
7949 		if (flagUnion != -1) {
7950 		    if ((*flags & flagUnion) == 0)
7951 			*flags |= flagUnion;
7952 		} else
7953 		    ret = 1;
7954 	    } else
7955 		ret = 1;
7956 	    if (item != NULL)
7957 		xmlFree(item);
7958 	    cur = end;
7959 	} while ((ret == 0) && (*cur != 0));
7960     }
7961 
7962     return (ret);
7963 }
7964 
7965 static int
xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,xmlSchemaIDCPtr idc,xmlSchemaIDCSelectPtr selector,xmlAttrPtr attr,int isField)7966 xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
7967 			     xmlSchemaIDCPtr idc,
7968 			     xmlSchemaIDCSelectPtr selector,
7969 			     xmlAttrPtr attr,
7970 			     int isField)
7971 {
7972     xmlNodePtr node;
7973 
7974     /*
7975     * c-selector-xpath:
7976     * Schema Component Constraint: Selector Value OK
7977     *
7978     * TODO: 1 The {selector} must be a valid XPath expression, as defined
7979     * in [XPath].
7980     */
7981     if (selector == NULL) {
7982 	xmlSchemaPErr(ctxt, idc->node,
7983 	    XML_SCHEMAP_INTERNAL,
7984 	    "Internal error: xmlSchemaCheckCSelectorXPath, "
7985 	    "the selector is not specified.\n", NULL, NULL);
7986 	return (-1);
7987     }
7988     if (attr == NULL)
7989 	node = idc->node;
7990     else
7991 	node = (xmlNodePtr) attr;
7992     if (selector->xpath == NULL) {
7993 	xmlSchemaPCustomErr(ctxt,
7994 	    /* TODO: Adjust error code. */
7995 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7996 	    NULL, node,
7997 	    "The XPath expression of the selector is not valid", NULL);
7998 	return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
7999     } else {
8000 	const xmlChar **nsArray = NULL;
8001 	xmlNsPtr *nsList = NULL;
8002 	/*
8003 	* Compile the XPath expression.
8004 	*/
8005 	/*
8006 	* TODO: We need the array of in-scope namespaces for compilation.
8007 	* TODO: Call xmlPatterncompile with different options for selector/
8008 	* field.
8009 	*/
8010 	if (attr == NULL)
8011 	    nsList = NULL;
8012 	else
8013 	    nsList = xmlGetNsList(attr->doc, attr->parent);
8014 	/*
8015 	* Build an array of prefixes and namespaces.
8016 	*/
8017 	if (nsList != NULL) {
8018 	    int i, count = 0;
8019 
8020 	    for (i = 0; nsList[i] != NULL; i++)
8021 		count++;
8022 
8023 	    nsArray = (const xmlChar **) xmlMalloc(
8024 		(count * 2 + 1) * sizeof(const xmlChar *));
8025 	    if (nsArray == NULL) {
8026 		xmlSchemaPErrMemory(ctxt);
8027 		xmlFree(nsList);
8028 		return (-1);
8029 	    }
8030 	    for (i = 0; i < count; i++) {
8031 		nsArray[2 * i] = nsList[i]->href;
8032 		nsArray[2 * i + 1] = nsList[i]->prefix;
8033 	    }
8034 	    nsArray[count * 2] = NULL;
8035 	    xmlFree(nsList);
8036 	}
8037 	/*
8038 	* TODO: Differentiate between "selector" and "field".
8039 	*/
8040 	if (isField)
8041 	    selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
8042 		NULL, XML_PATTERN_XSFIELD, nsArray);
8043 	else
8044 	    selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
8045 		NULL, XML_PATTERN_XSSEL, nsArray);
8046 	if (nsArray != NULL)
8047 	    xmlFree((xmlChar **) nsArray);
8048 
8049 	if (selector->xpathComp == NULL) {
8050 	    xmlSchemaPCustomErr(ctxt,
8051 		/* TODO: Adjust error code? */
8052 		XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8053 		NULL, node,
8054 		"The XPath expression '%s' could not be "
8055 		"compiled", selector->xpath);
8056 	    return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
8057 	}
8058     }
8059     return (0);
8060 }
8061 
8062 #define ADD_ANNOTATION(annot)   \
8063     xmlSchemaAnnotPtr cur = item->annot; \
8064     if (item->annot == NULL) {  \
8065 	item->annot = annot;    \
8066 	return (annot);         \
8067     }                           \
8068     cur = item->annot;          \
8069     while (cur->next != NULL) { \
8070 	cur = cur->next;	\
8071     }                           \
8072     cur->next = annot;
8073 
8074 /**
8075  * xmlSchemaAssignAnnotation:
8076  * @item: the schema component
8077  * @annot: the annotation
8078  *
8079  * Adds the annotation to the given schema component.
8080  *
8081  * Returns the given annotation.
8082  */
8083 static xmlSchemaAnnotPtr
xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem,xmlSchemaAnnotPtr annot)8084 xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem,
8085 		       xmlSchemaAnnotPtr annot)
8086 {
8087     if ((annItem == NULL) || (annot == NULL))
8088 	return (NULL);
8089     switch (annItem->type) {
8090 	case XML_SCHEMA_TYPE_ELEMENT: {
8091 		xmlSchemaElementPtr item = (xmlSchemaElementPtr) annItem;
8092 		ADD_ANNOTATION(annot)
8093 	    }
8094 	    break;
8095 	case XML_SCHEMA_TYPE_ATTRIBUTE: {
8096 		xmlSchemaAttributePtr item = (xmlSchemaAttributePtr) annItem;
8097 		ADD_ANNOTATION(annot)
8098 	    }
8099 	    break;
8100 	case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
8101 	case XML_SCHEMA_TYPE_ANY: {
8102 		xmlSchemaWildcardPtr item = (xmlSchemaWildcardPtr) annItem;
8103 		ADD_ANNOTATION(annot)
8104 	    }
8105 	    break;
8106 	case XML_SCHEMA_TYPE_PARTICLE:
8107 	case XML_SCHEMA_TYPE_IDC_KEY:
8108 	case XML_SCHEMA_TYPE_IDC_KEYREF:
8109 	case XML_SCHEMA_TYPE_IDC_UNIQUE: {
8110 		xmlSchemaAnnotItemPtr item = (xmlSchemaAnnotItemPtr) annItem;
8111 		ADD_ANNOTATION(annot)
8112 	    }
8113 	    break;
8114 	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: {
8115 		xmlSchemaAttributeGroupPtr item =
8116 		    (xmlSchemaAttributeGroupPtr) annItem;
8117 		ADD_ANNOTATION(annot)
8118 	    }
8119 	    break;
8120 	case XML_SCHEMA_TYPE_NOTATION: {
8121 		xmlSchemaNotationPtr item = (xmlSchemaNotationPtr) annItem;
8122 		ADD_ANNOTATION(annot)
8123 	    }
8124 	    break;
8125 	case XML_SCHEMA_FACET_MININCLUSIVE:
8126 	case XML_SCHEMA_FACET_MINEXCLUSIVE:
8127 	case XML_SCHEMA_FACET_MAXINCLUSIVE:
8128 	case XML_SCHEMA_FACET_MAXEXCLUSIVE:
8129 	case XML_SCHEMA_FACET_TOTALDIGITS:
8130 	case XML_SCHEMA_FACET_FRACTIONDIGITS:
8131 	case XML_SCHEMA_FACET_PATTERN:
8132 	case XML_SCHEMA_FACET_ENUMERATION:
8133 	case XML_SCHEMA_FACET_WHITESPACE:
8134 	case XML_SCHEMA_FACET_LENGTH:
8135 	case XML_SCHEMA_FACET_MAXLENGTH:
8136 	case XML_SCHEMA_FACET_MINLENGTH: {
8137 		xmlSchemaFacetPtr item = (xmlSchemaFacetPtr) annItem;
8138 		ADD_ANNOTATION(annot)
8139 	    }
8140 	    break;
8141 	case XML_SCHEMA_TYPE_SIMPLE:
8142 	case XML_SCHEMA_TYPE_COMPLEX: {
8143 		xmlSchemaTypePtr item = (xmlSchemaTypePtr) annItem;
8144 		ADD_ANNOTATION(annot)
8145 	    }
8146 	    break;
8147 	case XML_SCHEMA_TYPE_GROUP: {
8148 		xmlSchemaModelGroupDefPtr item = (xmlSchemaModelGroupDefPtr) annItem;
8149 		ADD_ANNOTATION(annot)
8150 	    }
8151 	    break;
8152 	case XML_SCHEMA_TYPE_SEQUENCE:
8153 	case XML_SCHEMA_TYPE_CHOICE:
8154 	case XML_SCHEMA_TYPE_ALL: {
8155 		xmlSchemaModelGroupPtr item = (xmlSchemaModelGroupPtr) annItem;
8156 		ADD_ANNOTATION(annot)
8157 	    }
8158 	    break;
8159 	default:
8160 	     xmlSchemaPCustomErr(NULL,
8161 		XML_SCHEMAP_INTERNAL,
8162 		NULL, NULL,
8163 		"Internal error: xmlSchemaAddAnnotation, "
8164 		"The item is not a annotated schema component", NULL);
8165 	     break;
8166     }
8167     return (annot);
8168 }
8169 
8170 /**
8171  * xmlSchemaParseIDCSelectorAndField:
8172  * @ctxt:  a schema validation context
8173  * @schema:  the schema being built
8174  * @node:  a subtree containing XML Schema information
8175  *
8176  * Parses a XML Schema identity-constraint definition's
8177  * <selector> and <field> elements.
8178  *
8179  * Returns the parsed identity-constraint definition.
8180  */
8181 static xmlSchemaIDCSelectPtr
xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,xmlSchemaIDCPtr idc,xmlNodePtr node,int isField)8182 xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
8183 			  xmlSchemaIDCPtr idc,
8184 			  xmlNodePtr node,
8185 			  int isField)
8186 {
8187     xmlSchemaIDCSelectPtr item;
8188     xmlNodePtr child = NULL;
8189     xmlAttrPtr attr;
8190 
8191     /*
8192     * Check for illegal attributes.
8193     */
8194     attr = node->properties;
8195     while (attr != NULL) {
8196 	if (attr->ns == NULL) {
8197 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8198 		(!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
8199 		xmlSchemaPIllegalAttrErr(ctxt,
8200 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8201 	    }
8202 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8203 	    xmlSchemaPIllegalAttrErr(ctxt,
8204 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8205 	}
8206 	attr = attr->next;
8207     }
8208     /*
8209     * Create the item.
8210     */
8211     item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
8212     if (item == NULL) {
8213         xmlSchemaPErrMemory(ctxt);
8214         return (NULL);
8215     }
8216     memset(item, 0, sizeof(xmlSchemaIDCSelect));
8217     /*
8218     * Attribute "xpath" (mandatory).
8219     */
8220     attr = xmlSchemaGetPropNode(node, "xpath");
8221     if (attr == NULL) {
8222 	xmlSchemaPMissingAttrErr(ctxt,
8223 	    XML_SCHEMAP_S4S_ATTR_MISSING,
8224 	    NULL, node,
8225 	    "name", NULL);
8226     } else {
8227 	item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8228 	/*
8229 	* URGENT TODO: "field"s have an other syntax than "selector"s.
8230 	*/
8231 
8232 	if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr,
8233 	    isField) == -1) {
8234 	    xmlSchemaPErr(ctxt,
8235 		(xmlNodePtr) attr,
8236 		XML_SCHEMAP_INTERNAL,
8237 		"Internal error: xmlSchemaParseIDCSelectorAndField, "
8238 		"validating the XPath expression of a IDC selector.\n",
8239 		NULL, NULL);
8240 	}
8241 
8242     }
8243     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8244     /*
8245     * And now for the children...
8246     */
8247     child = node->children;
8248     if (IS_SCHEMA(child, "annotation")) {
8249 	/*
8250 	* Add the annotation to the parent IDC.
8251 	*/
8252 	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) idc,
8253 	    xmlSchemaParseAnnotation(ctxt, child, 1));
8254 	child = child->next;
8255     }
8256     if (child != NULL) {
8257 	xmlSchemaPContentErr(ctxt,
8258 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8259 	    NULL, node, child,
8260 	    NULL, "(annotation?)");
8261     }
8262 
8263     return (item);
8264 }
8265 
8266 /**
8267  * xmlSchemaParseIDC:
8268  * @ctxt:  a schema validation context
8269  * @schema:  the schema being built
8270  * @node:  a subtree containing XML Schema information
8271  *
8272  * Parses a XML Schema identity-constraint definition.
8273  *
8274  * Returns the parsed identity-constraint definition.
8275  */
8276 static xmlSchemaIDCPtr
xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,xmlSchemaTypeType idcCategory,const xmlChar * targetNamespace)8277 xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
8278 		  xmlSchemaPtr schema,
8279 		  xmlNodePtr node,
8280 		  xmlSchemaTypeType idcCategory,
8281 		  const xmlChar *targetNamespace)
8282 {
8283     xmlSchemaIDCPtr item = NULL;
8284     xmlNodePtr child = NULL;
8285     xmlAttrPtr attr;
8286     const xmlChar *name = NULL;
8287     xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
8288 
8289     /*
8290     * Check for illegal attributes.
8291     */
8292     attr = node->properties;
8293     while (attr != NULL) {
8294 	if (attr->ns == NULL) {
8295 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8296 		(!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8297 		((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
8298 		 (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
8299 		xmlSchemaPIllegalAttrErr(ctxt,
8300 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8301 	    }
8302 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8303 	    xmlSchemaPIllegalAttrErr(ctxt,
8304 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8305 	}
8306 	attr = attr->next;
8307     }
8308     /*
8309     * Attribute "name" (mandatory).
8310     */
8311     attr = xmlSchemaGetPropNode(node, "name");
8312     if (attr == NULL) {
8313 	xmlSchemaPMissingAttrErr(ctxt,
8314 	    XML_SCHEMAP_S4S_ATTR_MISSING,
8315 	    NULL, node,
8316 	    "name", NULL);
8317 	return (NULL);
8318     } else if (xmlSchemaPValAttrNode(ctxt,
8319 	NULL, attr,
8320 	xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
8321 	return (NULL);
8322     }
8323     /* Create the component. */
8324     item = xmlSchemaAddIDC(ctxt, schema, name, targetNamespace,
8325 	idcCategory, node);
8326     if (item == NULL)
8327 	return(NULL);
8328 
8329     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8330     if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
8331 	/*
8332 	* Attribute "refer" (mandatory).
8333 	*/
8334 	attr = xmlSchemaGetPropNode(node, "refer");
8335 	if (attr == NULL) {
8336 	    xmlSchemaPMissingAttrErr(ctxt,
8337 		XML_SCHEMAP_S4S_ATTR_MISSING,
8338 		NULL, node,
8339 		"refer", NULL);
8340 	} else {
8341 	    /*
8342 	    * Create a reference item.
8343 	    */
8344 	    item->ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_IDC_KEY,
8345 		NULL, NULL);
8346 	    if (item->ref == NULL)
8347 		return (NULL);
8348 	    xmlSchemaPValAttrNodeQName(ctxt, schema,
8349 		NULL, attr,
8350 		&(item->ref->targetNamespace),
8351 		&(item->ref->name));
8352 	    xmlSchemaCheckReference(ctxt, schema, node, attr,
8353 		item->ref->targetNamespace);
8354 	}
8355     }
8356     /*
8357     * And now for the children...
8358     */
8359     child = node->children;
8360     if (IS_SCHEMA(child, "annotation")) {
8361 	item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
8362 	child = child->next;
8363     }
8364     if (child == NULL) {
8365 	xmlSchemaPContentErr(ctxt,
8366 		XML_SCHEMAP_S4S_ELEM_MISSING,
8367 		NULL, node, child,
8368 		"A child element is missing",
8369 		"(annotation?, (selector, field+))");
8370     }
8371     /*
8372     * Child element <selector>.
8373     */
8374     if (IS_SCHEMA(child, "selector")) {
8375 	item->selector = xmlSchemaParseIDCSelectorAndField(ctxt,
8376 	    item, child, 0);
8377 	child = child->next;
8378 	/*
8379 	* Child elements <field>.
8380 	*/
8381 	if (IS_SCHEMA(child, "field")) {
8382 	    do {
8383 		field = xmlSchemaParseIDCSelectorAndField(ctxt,
8384 		    item, child, 1);
8385 		if (field != NULL) {
8386 		    field->index = item->nbFields;
8387 		    item->nbFields++;
8388 		    if (lastField != NULL)
8389 			lastField->next = field;
8390 		    else
8391 			item->fields = field;
8392 		    lastField = field;
8393 		}
8394 		child = child->next;
8395 	    } while (IS_SCHEMA(child, "field"));
8396 	} else {
8397 	    xmlSchemaPContentErr(ctxt,
8398 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8399 		NULL, node, child,
8400 		NULL, "(annotation?, (selector, field+))");
8401 	}
8402     }
8403     if (child != NULL) {
8404 	xmlSchemaPContentErr(ctxt,
8405 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8406 	    NULL, node, child,
8407 	    NULL, "(annotation?, (selector, field+))");
8408     }
8409 
8410     return (item);
8411 }
8412 
8413 /**
8414  * xmlSchemaParseElement:
8415  * @ctxt:  a schema validation context
8416  * @schema:  the schema being built
8417  * @node:  a subtree containing XML Schema information
8418  * @topLevel: indicates if this is global declaration
8419  *
8420  * Parses a XML schema element declaration.
8421  * *WARNING* this interface is highly subject to change
8422  *
8423  * Returns the element declaration or a particle; NULL in case
8424  * of an error or if the particle has minOccurs==maxOccurs==0.
8425  */
8426 static xmlSchemaBasicItemPtr
xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,int * isElemRef,int topLevel)8427 xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
8428                       xmlNodePtr node, int *isElemRef, int topLevel)
8429 {
8430     xmlSchemaElementPtr decl = NULL;
8431     xmlSchemaParticlePtr particle = NULL;
8432     xmlSchemaAnnotPtr annot = NULL;
8433     xmlNodePtr child = NULL;
8434     xmlAttrPtr attr, nameAttr;
8435     int min, max, isRef = 0;
8436     xmlChar *des = NULL;
8437 
8438     /* 3.3.3 Constraints on XML Representations of Element Declarations */
8439     /* TODO: Complete implementation of 3.3.6 */
8440 
8441     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8442         return (NULL);
8443 
8444     if (isElemRef != NULL)
8445 	*isElemRef = 0;
8446     /*
8447     * If we get a "ref" attribute on a local <element> we will assume it's
8448     * a reference - even if there's a "name" attribute; this seems to be more
8449     * robust.
8450     */
8451     nameAttr = xmlSchemaGetPropNode(node, "name");
8452     attr = xmlSchemaGetPropNode(node, "ref");
8453     if ((topLevel) || (attr == NULL)) {
8454 	if (nameAttr == NULL) {
8455 	    xmlSchemaPMissingAttrErr(ctxt,
8456 		XML_SCHEMAP_S4S_ATTR_MISSING,
8457 		NULL, node, "name", NULL);
8458 	    return (NULL);
8459 	}
8460     } else
8461 	isRef = 1;
8462 
8463     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8464     child = node->children;
8465     if (IS_SCHEMA(child, "annotation")) {
8466 	annot = xmlSchemaParseAnnotation(ctxt, child, 1);
8467 	child = child->next;
8468     }
8469     /*
8470     * Skip particle part if a global declaration.
8471     */
8472     if (topLevel)
8473 	goto declaration_part;
8474     /*
8475     * The particle part ==================================================
8476     */
8477     min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
8478     max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(xs:nonNegativeInteger | unbounded)");
8479     xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
8480     particle = xmlSchemaAddParticle(ctxt, node, min, max);
8481     if (particle == NULL)
8482 	goto return_null;
8483 
8484     /* ret->flags |= XML_SCHEMAS_ELEM_REF; */
8485 
8486     if (isRef) {
8487 	const xmlChar *refNs = NULL, *ref = NULL;
8488 	xmlSchemaQNameRefPtr refer = NULL;
8489 	/*
8490 	* The reference part =============================================
8491 	*/
8492 	if (isElemRef != NULL)
8493 	    *isElemRef = 1;
8494 
8495 	xmlSchemaPValAttrNodeQName(ctxt, schema,
8496 	    NULL, attr, &refNs, &ref);
8497 	xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
8498 	/*
8499 	* SPEC (3.3.3 : 2.1) "One of ref or name must be present, but not both"
8500 	*/
8501 	if (nameAttr != NULL) {
8502 	    xmlSchemaPMutualExclAttrErr(ctxt,
8503 		XML_SCHEMAP_SRC_ELEMENT_2_1, NULL, nameAttr, "ref", "name");
8504 	}
8505 	/*
8506 	* Check for illegal attributes.
8507 	*/
8508 	attr = node->properties;
8509 	while (attr != NULL) {
8510 	    if (attr->ns == NULL) {
8511 		if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
8512 		    xmlStrEqual(attr->name, BAD_CAST "name") ||
8513 		    xmlStrEqual(attr->name, BAD_CAST "id") ||
8514 		    xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
8515 		    xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
8516 		{
8517 		    attr = attr->next;
8518 		    continue;
8519 		} else {
8520 		    /* SPEC (3.3.3 : 2.2) */
8521 		    xmlSchemaPCustomAttrErr(ctxt,
8522 			XML_SCHEMAP_SRC_ELEMENT_2_2,
8523 			NULL, NULL, attr,
8524 			"Only the attributes 'minOccurs', 'maxOccurs' and "
8525 			"'id' are allowed in addition to 'ref'");
8526 		    break;
8527 		}
8528 	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8529 		xmlSchemaPIllegalAttrErr(ctxt,
8530 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8531 	    }
8532 	    attr = attr->next;
8533 	}
8534 	/*
8535 	* No children except <annotation> expected.
8536 	*/
8537 	if (child != NULL) {
8538 	    xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8539 		NULL, node, child, NULL, "(annotation?)");
8540 	}
8541 	if ((min == 0) && (max == 0))
8542 	    goto return_null;
8543 	/*
8544 	* Create the reference item and attach it to the particle.
8545 	*/
8546 	refer = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_ELEMENT,
8547 	    ref, refNs);
8548 	if (refer == NULL)
8549 	    goto return_null;
8550 	particle->children = (xmlSchemaTreeItemPtr) refer;
8551 	particle->annot = annot;
8552 	/*
8553 	* Add the particle to pending components, since the reference
8554 	* need to be resolved.
8555 	*/
8556 	WXS_ADD_PENDING(ctxt, particle);
8557 	return ((xmlSchemaBasicItemPtr) particle);
8558     }
8559     /*
8560     * The declaration part ===============================================
8561     */
8562 declaration_part:
8563     {
8564 	const xmlChar *ns = NULL, *fixed, *name, *attrValue;
8565 	xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;
8566 
8567 	if (xmlSchemaPValAttrNode(ctxt, NULL, nameAttr,
8568 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
8569 	    goto return_null;
8570 	/*
8571 	* Evaluate the target namespace.
8572 	*/
8573 	if (topLevel) {
8574 	    ns = ctxt->targetNamespace;
8575 	} else {
8576 	    attr = xmlSchemaGetPropNode(node, "form");
8577 	    if (attr != NULL) {
8578 		attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8579 		if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
8580 		    ns = ctxt->targetNamespace;
8581 		} else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
8582 		    xmlSchemaPSimpleTypeErr(ctxt,
8583 			XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8584 			NULL, (xmlNodePtr) attr,
8585 			NULL, "(qualified | unqualified)",
8586 			attrValue, NULL, NULL, NULL);
8587 		}
8588 	    } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
8589 		ns = ctxt->targetNamespace;
8590 	}
8591 	decl = xmlSchemaAddElement(ctxt, name, ns, node, topLevel);
8592 	if (decl == NULL) {
8593 	    goto return_null;
8594 	}
8595 	/*
8596 	* Check for illegal attributes.
8597 	*/
8598 	attr = node->properties;
8599 	while (attr != NULL) {
8600 	    if (attr->ns == NULL) {
8601 		if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8602 		    (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
8603 		    (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8604 		    (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
8605 		    (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
8606 		    (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
8607 		    (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
8608 		{
8609 		    if (topLevel == 0) {
8610 			if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
8611 			    (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
8612 			    (!xmlStrEqual(attr->name, BAD_CAST "form")))
8613 			{
8614 			    xmlSchemaPIllegalAttrErr(ctxt,
8615 				XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8616 			}
8617 		    } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
8618 			(!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
8619 			(!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
8620 
8621 			xmlSchemaPIllegalAttrErr(ctxt,
8622 			    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8623 		    }
8624 		}
8625 	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8626 
8627 		xmlSchemaPIllegalAttrErr(ctxt,
8628 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8629 	    }
8630 	    attr = attr->next;
8631 	}
8632 	/*
8633 	* Extract/validate attributes.
8634 	*/
8635 	if (topLevel) {
8636 	    /*
8637 	    * Process top attributes of global element declarations here.
8638 	    */
8639 	    decl->flags |= XML_SCHEMAS_ELEM_GLOBAL;
8640 	    decl->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
8641 	    xmlSchemaPValAttrQName(ctxt, schema,
8642 		NULL, node, "substitutionGroup",
8643 		&(decl->substGroupNs), &(decl->substGroup));
8644 	    if (xmlGetBooleanProp(ctxt, node, "abstract", 0))
8645 		decl->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
8646 	    /*
8647 	    * Attribute "final".
8648 	    */
8649 	    attr = xmlSchemaGetPropNode(node, "final");
8650 	    if (attr == NULL) {
8651 		if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
8652 		    decl->flags |= XML_SCHEMAS_ELEM_FINAL_EXTENSION;
8653 		if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8654 		    decl->flags |= XML_SCHEMAS_ELEM_FINAL_RESTRICTION;
8655 	    } else {
8656 		attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8657 		if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
8658 		    -1,
8659 		    XML_SCHEMAS_ELEM_FINAL_EXTENSION,
8660 		    XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
8661 		    xmlSchemaPSimpleTypeErr(ctxt,
8662 			XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8663 			NULL, (xmlNodePtr) attr,
8664 			NULL, "(#all | List of (extension | restriction))",
8665 			attrValue, NULL, NULL, NULL);
8666 		}
8667 	    }
8668 	}
8669 	/*
8670 	* Attribute "block".
8671 	*/
8672 	attr = xmlSchemaGetPropNode(node, "block");
8673 	if (attr == NULL) {
8674 	    /*
8675 	    * Apply default "block" values.
8676 	    */
8677 	    if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
8678 		decl->flags |= XML_SCHEMAS_ELEM_BLOCK_RESTRICTION;
8679 	    if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
8680 		decl->flags |= XML_SCHEMAS_ELEM_BLOCK_EXTENSION;
8681 	    if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
8682 		decl->flags |= XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION;
8683 	} else {
8684 	    attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8685 	    if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
8686 		-1,
8687 		XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
8688 		XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
8689 		XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
8690 		xmlSchemaPSimpleTypeErr(ctxt,
8691 		    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8692 		    NULL, (xmlNodePtr) attr,
8693 		    NULL, "(#all | List of (extension | "
8694 		    "restriction | substitution))", attrValue,
8695 		    NULL, NULL, NULL);
8696 	    }
8697 	}
8698 	if (xmlGetBooleanProp(ctxt, node, "nillable", 0))
8699 	    decl->flags |= XML_SCHEMAS_ELEM_NILLABLE;
8700 
8701 	attr = xmlSchemaGetPropNode(node, "type");
8702 	if (attr != NULL) {
8703 	    xmlSchemaPValAttrNodeQName(ctxt, schema,
8704 		NULL, attr,
8705 		&(decl->namedTypeNs), &(decl->namedType));
8706 	    xmlSchemaCheckReference(ctxt, schema, node,
8707 		attr, decl->namedTypeNs);
8708 	}
8709 	decl->value = xmlSchemaGetProp(ctxt, node, "default");
8710 	attr = xmlSchemaGetPropNode(node, "fixed");
8711 	if (attr != NULL) {
8712 	    fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8713 	    if (decl->value != NULL) {
8714 		/*
8715 		* 3.3.3 : 1
8716 		* default and fixed must not both be present.
8717 		*/
8718 		xmlSchemaPMutualExclAttrErr(ctxt,
8719 		    XML_SCHEMAP_SRC_ELEMENT_1,
8720 		    NULL, attr, "default", "fixed");
8721 	    } else {
8722 		decl->flags |= XML_SCHEMAS_ELEM_FIXED;
8723 		decl->value = fixed;
8724 	    }
8725 	}
8726 	/*
8727 	* And now for the children...
8728 	*/
8729 	if (IS_SCHEMA(child, "complexType")) {
8730 	    /*
8731 	    * 3.3.3 : 3
8732 	    * "type" and either <simpleType> or <complexType> are mutually
8733 	    * exclusive
8734 	    */
8735 	    if (decl->namedType != NULL) {
8736 		xmlSchemaPContentErr(ctxt,
8737 		    XML_SCHEMAP_SRC_ELEMENT_3,
8738 		    NULL, node, child,
8739 		    "The attribute 'type' and the <complexType> child are "
8740 		    "mutually exclusive", NULL);
8741 	    } else
8742 		WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseComplexType(ctxt, schema, child, 0);
8743 	    child = child->next;
8744 	} else if (IS_SCHEMA(child, "simpleType")) {
8745 	    /*
8746 	    * 3.3.3 : 3
8747 	    * "type" and either <simpleType> or <complexType> are
8748 	    * mutually exclusive
8749 	    */
8750 	    if (decl->namedType != NULL) {
8751 		xmlSchemaPContentErr(ctxt,
8752 		    XML_SCHEMAP_SRC_ELEMENT_3,
8753 		    NULL, node, child,
8754 		    "The attribute 'type' and the <simpleType> child are "
8755 		    "mutually exclusive", NULL);
8756 	    } else
8757 		WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8758 	    child = child->next;
8759 	}
8760 	while ((IS_SCHEMA(child, "unique")) ||
8761 	    (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
8762 	    if (IS_SCHEMA(child, "unique")) {
8763 		curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8764 		    XML_SCHEMA_TYPE_IDC_UNIQUE, decl->targetNamespace);
8765 	    } else if (IS_SCHEMA(child, "key")) {
8766 		curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8767 		    XML_SCHEMA_TYPE_IDC_KEY, decl->targetNamespace);
8768 	    } else if (IS_SCHEMA(child, "keyref")) {
8769 		curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8770 		    XML_SCHEMA_TYPE_IDC_KEYREF, decl->targetNamespace);
8771 	    }
8772 	    if (lastIDC != NULL)
8773 		lastIDC->next = curIDC;
8774 	    else
8775 		decl->idcs = (void *) curIDC;
8776 	    lastIDC = curIDC;
8777 	    child = child->next;
8778 	}
8779 	if (child != NULL) {
8780 	    xmlSchemaPContentErr(ctxt,
8781 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8782 		NULL, node, child,
8783 		NULL, "(annotation?, ((simpleType | complexType)?, "
8784 		"(unique | key | keyref)*))");
8785 	}
8786 	decl->annot = annot;
8787     }
8788     /*
8789     * NOTE: Element Declaration Representation OK 4. will be checked at a
8790     * different layer.
8791     */
8792     FREE_AND_NULL(des)
8793     if (topLevel)
8794 	return ((xmlSchemaBasicItemPtr) decl);
8795     else {
8796 	particle->children = (xmlSchemaTreeItemPtr) decl;
8797 	return ((xmlSchemaBasicItemPtr) particle);
8798     }
8799 
8800 return_null:
8801     FREE_AND_NULL(des);
8802     if (annot != NULL) {
8803 	if (particle != NULL)
8804 	    particle->annot = NULL;
8805 	if (decl != NULL)
8806 	    decl->annot = NULL;
8807 	xmlSchemaFreeAnnot(annot);
8808     }
8809     return (NULL);
8810 }
8811 
8812 /**
8813  * xmlSchemaParseUnion:
8814  * @ctxt:  a schema validation context
8815  * @schema:  the schema being built
8816  * @node:  a subtree containing XML Schema information
8817  *
8818  * parse a XML schema Union definition
8819  * *WARNING* this interface is highly subject to change
8820  *
8821  * Returns -1 in case of internal error, 0 in case of success and a positive
8822  * error code otherwise.
8823  */
8824 static int
xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)8825 xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
8826                     xmlNodePtr node)
8827 {
8828     xmlSchemaTypePtr type;
8829     xmlNodePtr child = NULL;
8830     xmlAttrPtr attr;
8831     const xmlChar *cur = NULL;
8832 
8833     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8834         return (-1);
8835     /* Not a component, don't create it. */
8836     type = ctxt->ctxtType;
8837     /*
8838     * Mark the simple type as being of variety "union".
8839     */
8840     type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
8841     /*
8842     * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
8843     * then the `simple ur-type definition`."
8844     */
8845     type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
8846     /*
8847     * Check for illegal attributes.
8848     */
8849     attr = node->properties;
8850     while (attr != NULL) {
8851 	if (attr->ns == NULL) {
8852 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8853 		(!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
8854 		xmlSchemaPIllegalAttrErr(ctxt,
8855 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8856 	    }
8857 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8858 	    xmlSchemaPIllegalAttrErr(ctxt,
8859 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8860 	}
8861 	attr = attr->next;
8862     }
8863     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8864     /*
8865     * Attribute "memberTypes". This is a list of QNames.
8866     * TODO: Check the value to contain anything.
8867     */
8868     attr = xmlSchemaGetPropNode(node, "memberTypes");
8869     if (attr != NULL) {
8870 	const xmlChar *end;
8871 	xmlChar *tmp;
8872 	const xmlChar *localName, *nsName;
8873 	xmlSchemaTypeLinkPtr link, lastLink = NULL;
8874 	xmlSchemaQNameRefPtr ref;
8875 
8876 	cur = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8877         if (cur == NULL)
8878             return (-1);
8879 	type->base = cur;
8880 	do {
8881 	    while (IS_BLANK_CH(*cur))
8882 		cur++;
8883 	    end = cur;
8884 	    while ((*end != 0) && (!(IS_BLANK_CH(*end))))
8885 		end++;
8886 	    if (end == cur)
8887 		break;
8888 	    tmp = xmlStrndup(cur, end - cur);
8889             if (tmp == NULL) {
8890                 xmlSchemaPErrMemory(ctxt);
8891                 return (-1);
8892             }
8893 	    if (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
8894 		NULL, attr, BAD_CAST tmp, &nsName, &localName) == 0) {
8895 		/*
8896 		* Create the member type link.
8897 		*/
8898 		link = (xmlSchemaTypeLinkPtr)
8899 		    xmlMalloc(sizeof(xmlSchemaTypeLink));
8900 		if (link == NULL) {
8901 		    xmlSchemaPErrMemory(ctxt);
8902 	            FREE_AND_NULL(tmp)
8903 		    return (-1);
8904 		}
8905 		link->type = NULL;
8906 		link->next = NULL;
8907 		if (lastLink == NULL)
8908 		    type->memberTypes = link;
8909 		else
8910 		    lastLink->next = link;
8911 		lastLink = link;
8912 		/*
8913 		* Create a reference item.
8914 		*/
8915 		ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_SIMPLE,
8916 		    localName, nsName);
8917 		if (ref == NULL) {
8918 		    FREE_AND_NULL(tmp)
8919 		    return (-1);
8920 		}
8921 		/*
8922 		* Assign the reference to the link, it will be resolved
8923 		* later during fixup of the union simple type.
8924 		*/
8925 		link->type = (xmlSchemaTypePtr) ref;
8926 	    }
8927 	    FREE_AND_NULL(tmp)
8928 	    cur = end;
8929 	} while (*cur != 0);
8930 
8931     }
8932     /*
8933     * And now for the children...
8934     */
8935     child = node->children;
8936     if (IS_SCHEMA(child, "annotation")) {
8937 	/*
8938 	* Add the annotation to the simple type ancestor.
8939 	*/
8940 	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
8941 	    xmlSchemaParseAnnotation(ctxt, child, 1));
8942         child = child->next;
8943     }
8944     if (IS_SCHEMA(child, "simpleType")) {
8945 	xmlSchemaTypePtr subtype, last = NULL;
8946 
8947 	/*
8948 	* Anchor the member types in the "subtypes" field of the
8949 	* simple type.
8950 	*/
8951 	while (IS_SCHEMA(child, "simpleType")) {
8952 	    subtype = (xmlSchemaTypePtr)
8953 		xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8954 	    if (subtype != NULL) {
8955 		if (last == NULL) {
8956 		    type->subtypes = subtype;
8957 		    last = subtype;
8958 		} else {
8959 		    last->next = subtype;
8960 		    last = subtype;
8961 		}
8962 		last->next = NULL;
8963 	    }
8964 	    child = child->next;
8965 	}
8966     }
8967     if (child != NULL) {
8968 	xmlSchemaPContentErr(ctxt,
8969 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8970 	    NULL, node, child, NULL, "(annotation?, simpleType*)");
8971     }
8972     if ((attr == NULL) && (type->subtypes == NULL)) {
8973 	 /*
8974 	* src-union-memberTypes-or-simpleTypes
8975 	* Either the memberTypes [attribute] of the <union> element must
8976 	* be non-empty or there must be at least one simpleType [child].
8977 	*/
8978 	xmlSchemaPCustomErr(ctxt,
8979 	    XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
8980 	    NULL, node,
8981 	    "Either the attribute 'memberTypes' or "
8982 	    "at least one <simpleType> child must be present", NULL);
8983     }
8984     return (0);
8985 }
8986 
8987 /**
8988  * xmlSchemaParseList:
8989  * @ctxt:  a schema validation context
8990  * @schema:  the schema being built
8991  * @node:  a subtree containing XML Schema information
8992  *
8993  * parse a XML schema List definition
8994  * *WARNING* this interface is highly subject to change
8995  *
8996  * Returns -1 in case of error, 0 if the declaration is improper and
8997  *         1 in case of success.
8998  */
8999 static xmlSchemaTypePtr
xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)9000 xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9001                    xmlNodePtr node)
9002 {
9003     xmlSchemaTypePtr type;
9004     xmlNodePtr child = NULL;
9005     xmlAttrPtr attr;
9006 
9007     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9008         return (NULL);
9009     /* Not a component, don't create it. */
9010     type = ctxt->ctxtType;
9011     /*
9012     * Mark the type as being of variety "list".
9013     */
9014     type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
9015     /*
9016     * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
9017     * then the `simple ur-type definition`."
9018     */
9019     type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
9020     /*
9021     * Check for illegal attributes.
9022     */
9023     attr = node->properties;
9024     while (attr != NULL) {
9025 	if (attr->ns == NULL) {
9026 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9027 		(!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
9028 		xmlSchemaPIllegalAttrErr(ctxt,
9029 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9030 	    }
9031 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9032 	    xmlSchemaPIllegalAttrErr(ctxt,
9033 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9034 	}
9035 	attr = attr->next;
9036     }
9037 
9038     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9039 
9040     /*
9041     * Attribute "itemType". NOTE that we will use the "ref" and "refNs"
9042     * fields for holding the reference to the itemType.
9043     *
9044     * REVAMP TODO: Use the "base" and "baseNs" fields, since we will remove
9045     * the "ref" fields.
9046     */
9047     xmlSchemaPValAttrQName(ctxt, schema, NULL,
9048 	node, "itemType", &(type->baseNs), &(type->base));
9049     /*
9050     * And now for the children...
9051     */
9052     child = node->children;
9053     if (IS_SCHEMA(child, "annotation")) {
9054 	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
9055 	    xmlSchemaParseAnnotation(ctxt, child, 1));
9056         child = child->next;
9057     }
9058     if (IS_SCHEMA(child, "simpleType")) {
9059 	/*
9060 	* src-list-itemType-or-simpleType
9061 	* Either the itemType [attribute] or the <simpleType> [child] of
9062 	* the <list> element must be present, but not both.
9063 	*/
9064 	if (type->base != NULL) {
9065 	    xmlSchemaPCustomErr(ctxt,
9066 		XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9067 		NULL, node,
9068 		"The attribute 'itemType' and the <simpleType> child "
9069 		"are mutually exclusive", NULL);
9070 	} else {
9071 	    type->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
9072 	}
9073         child = child->next;
9074     } else if (type->base == NULL) {
9075 	xmlSchemaPCustomErr(ctxt,
9076 	    XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9077 	    NULL, node,
9078 	    "Either the attribute 'itemType' or the <simpleType> child "
9079 	    "must be present", NULL);
9080     }
9081     if (child != NULL) {
9082 	xmlSchemaPContentErr(ctxt,
9083 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9084 	    NULL, node, child, NULL, "(annotation?, simpleType?)");
9085     }
9086     if ((type->base == NULL) &&
9087 	(type->subtypes == NULL) &&
9088 	(xmlSchemaGetPropNode(node, "itemType") == NULL)) {
9089 	xmlSchemaPCustomErr(ctxt,
9090 	    XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9091 	    NULL, node,
9092 	    "Either the attribute 'itemType' or the <simpleType> child "
9093 	    "must be present", NULL);
9094     }
9095     return (NULL);
9096 }
9097 
9098 /**
9099  * xmlSchemaParseSimpleType:
9100  * @ctxt:  a schema validation context
9101  * @schema:  the schema being built
9102  * @node:  a subtree containing XML Schema information
9103  *
9104  * parse a XML schema Simple Type definition
9105  * *WARNING* this interface is highly subject to change
9106  *
9107  * Returns -1 in case of error, 0 if the declaration is improper and
9108  * 1 in case of success.
9109  */
9110 static xmlSchemaTypePtr
xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,int topLevel)9111 xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9112                          xmlNodePtr node, int topLevel)
9113 {
9114     xmlSchemaTypePtr type, oldCtxtType;
9115     xmlNodePtr child = NULL;
9116     const xmlChar *attrValue = NULL;
9117     xmlAttrPtr attr;
9118     int hasRestriction = 0;
9119 
9120     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9121         return (NULL);
9122 
9123     if (topLevel) {
9124 	attr = xmlSchemaGetPropNode(node, "name");
9125 	if (attr == NULL) {
9126 	    xmlSchemaPMissingAttrErr(ctxt,
9127 		XML_SCHEMAP_S4S_ATTR_MISSING,
9128 		NULL, node,
9129 		"name", NULL);
9130 	    return (NULL);
9131 	} else {
9132 	    if (xmlSchemaPValAttrNode(ctxt,
9133 		NULL, attr,
9134 		xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0)
9135 		return (NULL);
9136 	    /*
9137 	    * Skip built-in types.
9138 	    */
9139 	    if (ctxt->isS4S) {
9140 		xmlSchemaTypePtr biType;
9141 
9142 		if (ctxt->isRedefine) {
9143 		    /*
9144 		    * REDEFINE: Disallow redefinition of built-in-types.
9145 		    * TODO: It seems that the spec does not say anything
9146 		    * about this case.
9147 		    */
9148 		    xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
9149 			NULL, node,
9150 			"Redefinition of built-in simple types is not "
9151 			"supported", NULL);
9152 		    return(NULL);
9153 		}
9154 		biType = xmlSchemaGetPredefinedType(attrValue, xmlSchemaNs);
9155 		if (biType != NULL)
9156 		    return (biType);
9157 	    }
9158 	}
9159     }
9160     /*
9161     * TargetNamespace:
9162     * SPEC "The `actual value` of the targetNamespace [attribute]
9163     * of the <schema> ancestor element information item if present,
9164     * otherwise `absent`.
9165     */
9166     if (topLevel == 0) {
9167 #ifdef ENABLE_NAMED_LOCALS
9168         char buf[40];
9169 #endif
9170 	/*
9171 	* Parse as local simple type definition.
9172 	*/
9173 #ifdef ENABLE_NAMED_LOCALS
9174         snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
9175 	type = xmlSchemaAddType(ctxt, schema,
9176 	    XML_SCHEMA_TYPE_SIMPLE,
9177 	    xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
9178 	    ctxt->targetNamespace, node, 0);
9179 #else
9180 	type = xmlSchemaAddType(ctxt, schema,
9181 	    XML_SCHEMA_TYPE_SIMPLE,
9182 	    NULL, ctxt->targetNamespace, node, 0);
9183 #endif
9184 	if (type == NULL)
9185 	    return (NULL);
9186 	type->type = XML_SCHEMA_TYPE_SIMPLE;
9187 	type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
9188 	/*
9189 	* Check for illegal attributes.
9190 	*/
9191 	attr = node->properties;
9192 	while (attr != NULL) {
9193 	    if (attr->ns == NULL) {
9194 		if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
9195 		    xmlSchemaPIllegalAttrErr(ctxt,
9196 			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9197 		}
9198 	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9199 		    xmlSchemaPIllegalAttrErr(ctxt,
9200 			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9201 	    }
9202 	    attr = attr->next;
9203 	}
9204     } else {
9205 	/*
9206 	* Parse as global simple type definition.
9207 	*
9208 	* Note that attrValue is the value of the attribute "name" here.
9209 	*/
9210 	type = xmlSchemaAddType(ctxt, schema, XML_SCHEMA_TYPE_SIMPLE,
9211 	    attrValue, ctxt->targetNamespace, node, 1);
9212 	if (type == NULL)
9213 	    return (NULL);
9214 	type->type = XML_SCHEMA_TYPE_SIMPLE;
9215 	type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
9216 	type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
9217 	/*
9218 	* Check for illegal attributes.
9219 	*/
9220 	attr = node->properties;
9221 	while (attr != NULL) {
9222 	    if (attr->ns == NULL) {
9223 		if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9224 		    (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
9225 		    (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
9226 		    xmlSchemaPIllegalAttrErr(ctxt,
9227 			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9228 		}
9229 	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9230 		xmlSchemaPIllegalAttrErr(ctxt,
9231 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9232 	    }
9233 	    attr = attr->next;
9234 	}
9235 	/*
9236 	* Attribute "final".
9237 	*/
9238 	attr = xmlSchemaGetPropNode(node, "final");
9239 	if (attr == NULL) {
9240 	    if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9241 		type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
9242 	    if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9243 		type->flags |= XML_SCHEMAS_TYPE_FINAL_LIST;
9244 	    if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9245 		type->flags |= XML_SCHEMAS_TYPE_FINAL_UNION;
9246 	} else {
9247 	    attrValue = xmlSchemaGetProp(ctxt, node, "final");
9248 	    if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
9249 		-1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
9250 		XML_SCHEMAS_TYPE_FINAL_LIST,
9251 		XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
9252 
9253 		xmlSchemaPSimpleTypeErr(ctxt,
9254 		    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9255 		    WXS_BASIC_CAST type, (xmlNodePtr) attr,
9256 		    NULL, "(#all | List of (list | union | restriction)",
9257 		    attrValue, NULL, NULL, NULL);
9258 	    }
9259 	}
9260     }
9261     type->targetNamespace = ctxt->targetNamespace;
9262     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9263     /*
9264     * And now for the children...
9265     */
9266     oldCtxtType = ctxt->ctxtType;
9267 
9268     ctxt->ctxtType = type;
9269 
9270     child = node->children;
9271     if (IS_SCHEMA(child, "annotation")) {
9272         type->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9273         child = child->next;
9274     }
9275     if (child == NULL) {
9276 	xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_MISSING,
9277 	    NULL, node, child, NULL,
9278 	    "(annotation?, (restriction | list | union))");
9279     } else if (IS_SCHEMA(child, "restriction")) {
9280         xmlSchemaParseRestriction(ctxt, schema, child,
9281 	    XML_SCHEMA_TYPE_SIMPLE);
9282 	hasRestriction = 1;
9283         child = child->next;
9284     } else if (IS_SCHEMA(child, "list")) {
9285         xmlSchemaParseList(ctxt, schema, child);
9286         child = child->next;
9287     } else if (IS_SCHEMA(child, "union")) {
9288         xmlSchemaParseUnion(ctxt, schema, child);
9289         child = child->next;
9290     }
9291     if (child != NULL) {
9292 	xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9293 	    NULL, node, child, NULL,
9294 	    "(annotation?, (restriction | list | union))");
9295     }
9296     /*
9297     * REDEFINE: SPEC src-redefine (5)
9298     * "Within the [children], each <simpleType> must have a
9299     * <restriction> among its [children] ... the `actual value` of whose
9300     * base [attribute] must be the same as the `actual value` of its own
9301     * name attribute plus target namespace;"
9302     */
9303     if (topLevel && ctxt->isRedefine && (! hasRestriction)) {
9304 	xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
9305 	    NULL, node, "This is a redefinition, thus the "
9306 	    "<simpleType> must have a <restriction> child", NULL);
9307     }
9308 
9309     ctxt->ctxtType = oldCtxtType;
9310     return (type);
9311 }
9312 
9313 /**
9314  * xmlSchemaParseModelGroupDefRef:
9315  * @ctxt:  the parser context
9316  * @schema: the schema being built
9317  * @node:  the node
9318  *
9319  * Parses a reference to a model group definition.
9320  *
9321  * We will return a particle component with a qname-component or
9322  * NULL in case of an error.
9323  */
9324 static xmlSchemaTreeItemPtr
xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)9325 xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt,
9326 			       xmlSchemaPtr schema,
9327 			       xmlNodePtr node)
9328 {
9329     xmlSchemaParticlePtr item;
9330     xmlNodePtr child = NULL;
9331     xmlAttrPtr attr;
9332     const xmlChar *ref = NULL, *refNs = NULL;
9333     int min, max;
9334 
9335     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9336         return (NULL);
9337 
9338     attr = xmlSchemaGetPropNode(node, "ref");
9339     if (attr == NULL) {
9340 	xmlSchemaPMissingAttrErr(ctxt,
9341 	    XML_SCHEMAP_S4S_ATTR_MISSING,
9342 	    NULL, node, "ref", NULL);
9343 	return (NULL);
9344     } else if (xmlSchemaPValAttrNodeQName(ctxt, schema, NULL,
9345 	attr, &refNs, &ref) != 0) {
9346 	return (NULL);
9347     }
9348     xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
9349     min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
9350     max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
9351 	"(xs:nonNegativeInteger | unbounded)");
9352     /*
9353     * Check for illegal attributes.
9354     */
9355     attr = node->properties;
9356     while (attr != NULL) {
9357 	if (attr->ns == NULL) {
9358 	    if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
9359 		(!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9360 		(!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
9361 		(!xmlStrEqual(attr->name, BAD_CAST "maxOccurs"))) {
9362 		xmlSchemaPIllegalAttrErr(ctxt,
9363 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9364 	    }
9365 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9366 	    xmlSchemaPIllegalAttrErr(ctxt,
9367 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9368 	}
9369 	attr = attr->next;
9370     }
9371     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9372     item = xmlSchemaAddParticle(ctxt, node, min, max);
9373     if (item == NULL)
9374 	return (NULL);
9375     /*
9376     * Create a qname-reference and set as the term; it will be substituted
9377     * for the model group after the reference has been resolved.
9378     */
9379     item->children = (xmlSchemaTreeItemPtr)
9380 	xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_GROUP, ref, refNs);
9381     xmlSchemaPCheckParticleCorrect_2(ctxt, item, node, min, max);
9382     /*
9383     * And now for the children...
9384     */
9385     child = node->children;
9386     /* TODO: Is annotation even allowed for a model group reference? */
9387     if (IS_SCHEMA(child, "annotation")) {
9388 	/*
9389 	* TODO: What to do exactly with the annotation?
9390 	*/
9391 	item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9392 	child = child->next;
9393     }
9394     if (child != NULL) {
9395 	xmlSchemaPContentErr(ctxt,
9396 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9397 	    NULL, node, child, NULL,
9398 	    "(annotation?)");
9399     }
9400     /*
9401     * Corresponds to no component at all if minOccurs==maxOccurs==0.
9402     */
9403     if ((min == 0) && (max == 0))
9404 	return (NULL);
9405 
9406     return ((xmlSchemaTreeItemPtr) item);
9407 }
9408 
9409 /**
9410  * xmlSchemaParseModelGroupDefinition:
9411  * @ctxt:  a schema validation context
9412  * @schema:  the schema being built
9413  * @node:  a subtree containing XML Schema information
9414  *
9415  * Parses a XML schema model group definition.
9416  *
9417  * Note that the constraint src-redefine (6.2) can't be applied until
9418  * references have been resolved. So we will do this at the
9419  * component fixup level.
9420  *
9421  * *WARNING* this interface is highly subject to change
9422  *
9423  * Returns -1 in case of error, 0 if the declaration is improper and
9424  *         1 in case of success.
9425  */
9426 static xmlSchemaModelGroupDefPtr
xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)9427 xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
9428 				   xmlSchemaPtr schema,
9429 				   xmlNodePtr node)
9430 {
9431     xmlSchemaModelGroupDefPtr item;
9432     xmlNodePtr child = NULL;
9433     xmlAttrPtr attr;
9434     const xmlChar *name;
9435 
9436     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9437         return (NULL);
9438 
9439     attr = xmlSchemaGetPropNode(node, "name");
9440     if (attr == NULL) {
9441 	xmlSchemaPMissingAttrErr(ctxt,
9442 	    XML_SCHEMAP_S4S_ATTR_MISSING,
9443 	    NULL, node,
9444 	    "name", NULL);
9445 	return (NULL);
9446     } else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
9447 	xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
9448 	return (NULL);
9449     }
9450     item = xmlSchemaAddModelGroupDefinition(ctxt, schema, name,
9451 	ctxt->targetNamespace, node);
9452     if (item == NULL)
9453 	return (NULL);
9454     /*
9455     * Check for illegal attributes.
9456     */
9457     attr = node->properties;
9458     while (attr != NULL) {
9459 	if (attr->ns == NULL) {
9460 	    if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
9461 		(!xmlStrEqual(attr->name, BAD_CAST "id"))) {
9462 		xmlSchemaPIllegalAttrErr(ctxt,
9463 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9464 	    }
9465 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9466 	    xmlSchemaPIllegalAttrErr(ctxt,
9467 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9468 	}
9469 	attr = attr->next;
9470     }
9471     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9472     /*
9473     * And now for the children...
9474     */
9475     child = node->children;
9476     if (IS_SCHEMA(child, "annotation")) {
9477 	item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9478 	child = child->next;
9479     }
9480     if (IS_SCHEMA(child, "all")) {
9481 	item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9482 	    XML_SCHEMA_TYPE_ALL, 0);
9483 	child = child->next;
9484     } else if (IS_SCHEMA(child, "choice")) {
9485 	item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9486 	    XML_SCHEMA_TYPE_CHOICE, 0);
9487 	child = child->next;
9488     } else if (IS_SCHEMA(child, "sequence")) {
9489 	item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9490 	    XML_SCHEMA_TYPE_SEQUENCE, 0);
9491 	child = child->next;
9492     }
9493 
9494 
9495 
9496     if (child != NULL) {
9497 	xmlSchemaPContentErr(ctxt,
9498 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9499 	    NULL, node, child, NULL,
9500 	    "(annotation?, (all | choice | sequence)?)");
9501     }
9502     return (item);
9503 }
9504 
9505 /**
9506  * xmlSchemaCleanupDoc:
9507  * @ctxt:  a schema validation context
9508  * @node:  the root of the document.
9509  *
9510  * removes unwanted nodes in a schemas document tree
9511  */
9512 static void
xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr root)9513 xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
9514 {
9515     xmlNodePtr delete, cur;
9516 
9517     if ((ctxt == NULL) || (root == NULL)) return;
9518 
9519     /*
9520      * Remove all the blank text nodes
9521      */
9522     delete = NULL;
9523     cur = root;
9524     while (cur != NULL) {
9525         if (delete != NULL) {
9526             xmlUnlinkNode(delete);
9527             xmlFreeNode(delete);
9528             delete = NULL;
9529         }
9530         if (cur->type == XML_TEXT_NODE) {
9531             if (IS_BLANK_NODE(cur)) {
9532                 if (xmlNodeGetSpacePreserve(cur) != 1) {
9533                     delete = cur;
9534                 }
9535             }
9536         } else if ((cur->type != XML_ELEMENT_NODE) &&
9537                    (cur->type != XML_CDATA_SECTION_NODE)) {
9538             delete = cur;
9539             goto skip_children;
9540         }
9541 
9542         /*
9543          * Skip to next node
9544          */
9545         if (cur->children != NULL) {
9546             if ((cur->children->type != XML_ENTITY_DECL) &&
9547                 (cur->children->type != XML_ENTITY_REF_NODE) &&
9548                 (cur->children->type != XML_ENTITY_NODE)) {
9549                 cur = cur->children;
9550                 continue;
9551             }
9552         }
9553       skip_children:
9554         if (cur->next != NULL) {
9555             cur = cur->next;
9556             continue;
9557         }
9558 
9559         do {
9560             cur = cur->parent;
9561             if (cur == NULL)
9562                 break;
9563             if (cur == root) {
9564                 cur = NULL;
9565                 break;
9566             }
9567             if (cur->next != NULL) {
9568                 cur = cur->next;
9569                 break;
9570             }
9571         } while (cur != NULL);
9572     }
9573     if (delete != NULL) {
9574         xmlUnlinkNode(delete);
9575         xmlFreeNode(delete);
9576         delete = NULL;
9577     }
9578 }
9579 
9580 
9581 static void
xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)9582 xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
9583 {
9584     if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
9585 	schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
9586 
9587     if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
9588 	schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
9589 
9590     if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
9591 	schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
9592     if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9593 	schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
9594     if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9595 	schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
9596     if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9597 	schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
9598 
9599     if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
9600 	schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
9601     if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
9602 	schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
9603     if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
9604 	schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
9605 }
9606 
9607 static int
xmlSchemaParseSchemaElement(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)9608 xmlSchemaParseSchemaElement(xmlSchemaParserCtxtPtr ctxt,
9609 			     xmlSchemaPtr schema,
9610 			     xmlNodePtr node)
9611 {
9612     xmlAttrPtr attr;
9613     const xmlChar *val;
9614     int res = 0, oldErrs = ctxt->nberrors;
9615 
9616     /*
9617     * Those flags should be moved to the parser context flags,
9618     * since they are not visible at the component level. I.e.
9619     * they are used if processing schema *documents* only.
9620     */
9621     res = xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9622     HFAILURE;
9623 
9624     /*
9625     * Since the version is of type xs:token, we won't bother to
9626     * check it.
9627     */
9628     /* REMOVED:
9629     attr = xmlSchemaGetPropNode(node, "version");
9630     if (attr != NULL) {
9631 	res = xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
9632 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &val);
9633 	HFAILURE;
9634     }
9635     */
9636     attr = xmlSchemaGetPropNode(node, "targetNamespace");
9637     if (attr != NULL) {
9638 	res = xmlSchemaPValAttrNode(ctxt, NULL, attr,
9639 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
9640 	HFAILURE;
9641 	if (res != 0) {
9642 	    ctxt->stop = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
9643 	    goto exit;
9644 	}
9645     }
9646     attr = xmlSchemaGetPropNode(node, "elementFormDefault");
9647     if (attr != NULL) {
9648 	val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9649 	res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9650 	    XML_SCHEMAS_QUALIF_ELEM);
9651 	HFAILURE;
9652 	if (res != 0) {
9653 	    xmlSchemaPSimpleTypeErr(ctxt,
9654 		XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
9655 		NULL, (xmlNodePtr) attr, NULL,
9656 		"(qualified | unqualified)", val, NULL, NULL, NULL);
9657 	}
9658     }
9659     attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
9660     if (attr != NULL) {
9661 	val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9662 	res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9663 	    XML_SCHEMAS_QUALIF_ATTR);
9664 	HFAILURE;
9665 	if (res != 0) {
9666 	    xmlSchemaPSimpleTypeErr(ctxt,
9667 		XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
9668 		NULL, (xmlNodePtr) attr, NULL,
9669 		"(qualified | unqualified)", val, NULL, NULL, NULL);
9670 	}
9671     }
9672     attr = xmlSchemaGetPropNode(node, "finalDefault");
9673     if (attr != NULL) {
9674 	val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9675 	res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
9676 	    XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
9677 	    XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
9678 	    -1,
9679 	    XML_SCHEMAS_FINAL_DEFAULT_LIST,
9680 	    XML_SCHEMAS_FINAL_DEFAULT_UNION);
9681 	HFAILURE;
9682 	if (res != 0) {
9683 	    xmlSchemaPSimpleTypeErr(ctxt,
9684 		XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9685 		NULL, (xmlNodePtr) attr, NULL,
9686 		"(#all | List of (extension | restriction | list | union))",
9687 		val, NULL, NULL, NULL);
9688 	}
9689     }
9690     attr = xmlSchemaGetPropNode(node, "blockDefault");
9691     if (attr != NULL) {
9692 	val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9693 	res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
9694 	    XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
9695 	    XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
9696 	    XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1);
9697 	HFAILURE;
9698 	if (res != 0) {
9699 	    xmlSchemaPSimpleTypeErr(ctxt,
9700 		XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9701 		NULL, (xmlNodePtr) attr, NULL,
9702 		"(#all | List of (extension | restriction | substitution))",
9703 		val, NULL, NULL, NULL);
9704 	}
9705     }
9706 
9707 exit:
9708     if (oldErrs != ctxt->nberrors)
9709 	res = ctxt->err;
9710     return(res);
9711 exit_failure:
9712     return(-1);
9713 }
9714 
9715 /**
9716  * xmlSchemaParseSchemaTopLevel:
9717  * @ctxt:  a schema validation context
9718  * @schema:  the schemas
9719  * @nodes:  the list of top level nodes
9720  *
9721  * Returns the internal XML Schema structure built from the resource or
9722  *         NULL in case of error
9723  */
9724 static int
xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr nodes)9725 xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
9726                              xmlSchemaPtr schema, xmlNodePtr nodes)
9727 {
9728     xmlNodePtr child;
9729     xmlSchemaAnnotPtr annot;
9730     int res = 0, oldErrs, tmpOldErrs;
9731 
9732     if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
9733         return(-1);
9734 
9735     oldErrs = ctxt->nberrors;
9736     child = nodes;
9737     while ((IS_SCHEMA(child, "include")) ||
9738 	   (IS_SCHEMA(child, "import")) ||
9739 	   (IS_SCHEMA(child, "redefine")) ||
9740 	   (IS_SCHEMA(child, "annotation"))) {
9741 	if (IS_SCHEMA(child, "annotation")) {
9742 	    annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9743 	    if (schema->annot == NULL)
9744 		schema->annot = annot;
9745 	    else
9746 		xmlSchemaFreeAnnot(annot);
9747 	} else if (IS_SCHEMA(child, "import")) {
9748 	    tmpOldErrs = ctxt->nberrors;
9749 	    res = xmlSchemaParseImport(ctxt, schema, child);
9750 	    HFAILURE;
9751 	    HSTOP(ctxt);
9752 	    if (tmpOldErrs != ctxt->nberrors)
9753 		goto exit;
9754 	} else if (IS_SCHEMA(child, "include")) {
9755 	    tmpOldErrs = ctxt->nberrors;
9756 	    res = xmlSchemaParseInclude(ctxt, schema, child);
9757 	    HFAILURE;
9758 	    HSTOP(ctxt);
9759 	    if (tmpOldErrs != ctxt->nberrors)
9760 		goto exit;
9761 	} else if (IS_SCHEMA(child, "redefine")) {
9762 	    tmpOldErrs = ctxt->nberrors;
9763 	    res = xmlSchemaParseRedefine(ctxt, schema, child);
9764 	    HFAILURE;
9765 	    HSTOP(ctxt);
9766 	    if (tmpOldErrs != ctxt->nberrors)
9767 		goto exit;
9768 	}
9769 	child = child->next;
9770     }
9771     /*
9772     * URGENT TODO: Change the functions to return int results.
9773     * We need especially to catch internal errors.
9774     */
9775     while (child != NULL) {
9776 	if (IS_SCHEMA(child, "complexType")) {
9777 	    xmlSchemaParseComplexType(ctxt, schema, child, 1);
9778 	    child = child->next;
9779 	} else if (IS_SCHEMA(child, "simpleType")) {
9780 	    xmlSchemaParseSimpleType(ctxt, schema, child, 1);
9781 	    child = child->next;
9782 	} else if (IS_SCHEMA(child, "element")) {
9783 	    xmlSchemaParseElement(ctxt, schema, child, NULL, 1);
9784 	    child = child->next;
9785 	} else if (IS_SCHEMA(child, "attribute")) {
9786 	    xmlSchemaParseGlobalAttribute(ctxt, schema, child);
9787 	    child = child->next;
9788 	} else if (IS_SCHEMA(child, "attributeGroup")) {
9789 	    xmlSchemaParseAttributeGroupDefinition(ctxt, schema, child);
9790 	    child = child->next;
9791 	} else if (IS_SCHEMA(child, "group")) {
9792 	    xmlSchemaParseModelGroupDefinition(ctxt, schema, child);
9793 	    child = child->next;
9794 	} else if (IS_SCHEMA(child, "notation")) {
9795 	    xmlSchemaParseNotation(ctxt, schema, child);
9796 	    child = child->next;
9797 	} else {
9798 	    xmlSchemaPContentErr(ctxt,
9799 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9800 		NULL, child->parent, child,
9801 		NULL, "((include | import | redefine | annotation)*, "
9802 		"(((simpleType | complexType | group | attributeGroup) "
9803 		"| element | attribute | notation), annotation*)*)");
9804 	    child = child->next;
9805 	}
9806 	while (IS_SCHEMA(child, "annotation")) {
9807 	    /*
9808 	    * TODO: We should add all annotations.
9809 	    */
9810 	    annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9811 	    if (schema->annot == NULL)
9812 		schema->annot = annot;
9813 	    else
9814 		xmlSchemaFreeAnnot(annot);
9815 	    child = child->next;
9816 	}
9817     }
9818 exit:
9819     ctxt->ctxtType = NULL;
9820     if (oldErrs != ctxt->nberrors)
9821 	res = ctxt->err;
9822     return(res);
9823 exit_failure:
9824     return(-1);
9825 }
9826 
9827 static xmlSchemaSchemaRelationPtr
xmlSchemaSchemaRelationCreate(void)9828 xmlSchemaSchemaRelationCreate(void)
9829 {
9830     xmlSchemaSchemaRelationPtr ret;
9831 
9832     ret = (xmlSchemaSchemaRelationPtr)
9833 	xmlMalloc(sizeof(xmlSchemaSchemaRelation));
9834     if (ret == NULL) {
9835 	xmlSchemaPErrMemory(NULL);
9836 	return(NULL);
9837     }
9838     memset(ret, 0, sizeof(xmlSchemaSchemaRelation));
9839     return(ret);
9840 }
9841 
9842 #if 0
9843 static void
9844 xmlSchemaSchemaRelationFree(xmlSchemaSchemaRelationPtr rel)
9845 {
9846     xmlFree(rel);
9847 }
9848 #endif
9849 
9850 static void
xmlSchemaRedefListFree(xmlSchemaRedefPtr redef)9851 xmlSchemaRedefListFree(xmlSchemaRedefPtr redef)
9852 {
9853     xmlSchemaRedefPtr prev;
9854 
9855     while (redef != NULL) {
9856 	prev = redef;
9857 	redef = redef->next;
9858 	xmlFree(prev);
9859     }
9860 }
9861 
9862 static void
xmlSchemaConstructionCtxtFree(xmlSchemaConstructionCtxtPtr con)9863 xmlSchemaConstructionCtxtFree(xmlSchemaConstructionCtxtPtr con)
9864 {
9865     /*
9866     * After the construction context has been freed, there will be
9867     * no schema graph available any more. Only the schema buckets
9868     * will stay alive, which are put into the "schemasImports" and
9869     * "includes" slots of the xmlSchema.
9870     */
9871     if (con->buckets != NULL)
9872 	xmlSchemaItemListFree(con->buckets);
9873     if (con->pending != NULL)
9874 	xmlSchemaItemListFree(con->pending);
9875     if (con->substGroups != NULL)
9876 	xmlHashFree(con->substGroups, xmlSchemaSubstGroupFreeEntry);
9877     if (con->redefs != NULL)
9878 	xmlSchemaRedefListFree(con->redefs);
9879     if (con->dict != NULL)
9880 	xmlDictFree(con->dict);
9881     xmlFree(con);
9882 }
9883 
9884 static xmlSchemaConstructionCtxtPtr
xmlSchemaConstructionCtxtCreate(xmlDictPtr dict)9885 xmlSchemaConstructionCtxtCreate(xmlDictPtr dict)
9886 {
9887     xmlSchemaConstructionCtxtPtr ret;
9888 
9889     ret = (xmlSchemaConstructionCtxtPtr)
9890 	xmlMalloc(sizeof(xmlSchemaConstructionCtxt));
9891     if (ret == NULL) {
9892         xmlSchemaPErrMemory(NULL);
9893         return (NULL);
9894     }
9895     memset(ret, 0, sizeof(xmlSchemaConstructionCtxt));
9896 
9897     ret->buckets = xmlSchemaItemListCreate();
9898     if (ret->buckets == NULL) {
9899 	xmlSchemaPErrMemory(NULL);
9900 	xmlFree(ret);
9901         return (NULL);
9902     }
9903     ret->pending = xmlSchemaItemListCreate();
9904     if (ret->pending == NULL) {
9905 	xmlSchemaPErrMemory(NULL);
9906 	xmlSchemaConstructionCtxtFree(ret);
9907         return (NULL);
9908     }
9909     ret->dict = dict;
9910     xmlDictReference(dict);
9911     return(ret);
9912 }
9913 
9914 static xmlSchemaParserCtxtPtr
xmlSchemaParserCtxtCreate(void)9915 xmlSchemaParserCtxtCreate(void)
9916 {
9917     xmlSchemaParserCtxtPtr ret;
9918 
9919     ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9920     if (ret == NULL) {
9921         xmlSchemaPErrMemory(NULL);
9922         return (NULL);
9923     }
9924     memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9925     ret->type = XML_SCHEMA_CTXT_PARSER;
9926     ret->attrProhibs = xmlSchemaItemListCreate();
9927     if (ret->attrProhibs == NULL) {
9928 	xmlFree(ret);
9929 	return(NULL);
9930     }
9931     return(ret);
9932 }
9933 
9934 /**
9935  * xmlSchemaNewParserCtxtUseDict:
9936  * @URL:  the location of the schema
9937  * @dict: the dictionary to be used
9938  *
9939  * Create an XML Schemas parse context for that file/resource expected
9940  * to contain an XML Schemas file.
9941  *
9942  * Returns the parser context or NULL in case of error
9943  */
9944 static xmlSchemaParserCtxtPtr
xmlSchemaNewParserCtxtUseDict(const char * URL,xmlDictPtr dict)9945 xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
9946 {
9947     xmlSchemaParserCtxtPtr ret;
9948 
9949     ret = xmlSchemaParserCtxtCreate();
9950     if (ret == NULL)
9951         return (NULL);
9952     ret->dict = dict;
9953     xmlDictReference(dict);
9954     if (URL != NULL)
9955 	ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
9956     return (ret);
9957 }
9958 
9959 static int
xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)9960 xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
9961 {
9962     if (vctxt->pctxt == NULL) {
9963         if (vctxt->schema != NULL)
9964 	    vctxt->pctxt =
9965 		xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
9966 	else
9967 	    vctxt->pctxt = xmlSchemaNewParserCtxt("*");
9968 	if (vctxt->pctxt == NULL) {
9969 	    VERROR_INT("xmlSchemaCreatePCtxtOnVCtxt",
9970 		"failed to create a temp. parser context");
9971 	    return (-1);
9972 	}
9973 	/* TODO: Pass user data. */
9974 	xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error,
9975 	    vctxt->warning, vctxt->errCtxt);
9976 	xmlSchemaSetParserStructuredErrors(vctxt->pctxt, vctxt->serror,
9977 	    vctxt->errCtxt);
9978     }
9979     return (0);
9980 }
9981 
9982 /**
9983  * xmlSchemaGetSchemaBucket:
9984  * @pctxt: the schema parser context
9985  * @schemaLocation: the URI of the schema document
9986  *
9987  * Returns a schema bucket if it was already parsed.
9988  *
9989  * Returns a schema bucket if it was already parsed from
9990  *         @schemaLocation, NULL otherwise.
9991  */
9992 static xmlSchemaBucketPtr
xmlSchemaGetSchemaBucket(xmlSchemaParserCtxtPtr pctxt,const xmlChar * schemaLocation)9993 xmlSchemaGetSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
9994 			    const xmlChar *schemaLocation)
9995 {
9996     xmlSchemaBucketPtr cur;
9997     xmlSchemaItemListPtr list;
9998 
9999     list = pctxt->constructor->buckets;
10000     if (list->nbItems == 0)
10001 	return(NULL);
10002     else {
10003 	int i;
10004 	for (i = 0; i < list->nbItems; i++) {
10005 	    cur = (xmlSchemaBucketPtr) list->items[i];
10006 	    /* Pointer comparison! */
10007 	    if (cur->schemaLocation == schemaLocation)
10008 		return(cur);
10009 	}
10010     }
10011     return(NULL);
10012 }
10013 
10014 static xmlSchemaBucketPtr
xmlSchemaGetChameleonSchemaBucket(xmlSchemaParserCtxtPtr pctxt,const xmlChar * schemaLocation,const xmlChar * targetNamespace)10015 xmlSchemaGetChameleonSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
10016 				     const xmlChar *schemaLocation,
10017 				     const xmlChar *targetNamespace)
10018 {
10019     xmlSchemaBucketPtr cur;
10020     xmlSchemaItemListPtr list;
10021 
10022     list = pctxt->constructor->buckets;
10023     if (list->nbItems == 0)
10024 	return(NULL);
10025     else {
10026 	int i;
10027 	for (i = 0; i < list->nbItems; i++) {
10028 	    cur = (xmlSchemaBucketPtr) list->items[i];
10029 	    /* Pointer comparison! */
10030 	    if ((cur->origTargetNamespace == NULL) &&
10031 		(cur->schemaLocation == schemaLocation) &&
10032 		(cur->targetNamespace == targetNamespace))
10033 		return(cur);
10034 	}
10035     }
10036     return(NULL);
10037 }
10038 
10039 
10040 #define IS_BAD_SCHEMA_DOC(b) \
10041     (((b)->doc == NULL) && ((b)->schemaLocation != NULL))
10042 
10043 static xmlSchemaBucketPtr
xmlSchemaGetSchemaBucketByTNS(xmlSchemaParserCtxtPtr pctxt,const xmlChar * targetNamespace,int imported)10044 xmlSchemaGetSchemaBucketByTNS(xmlSchemaParserCtxtPtr pctxt,
10045 				 const xmlChar *targetNamespace,
10046 				 int imported)
10047 {
10048     xmlSchemaBucketPtr cur;
10049     xmlSchemaItemListPtr list;
10050 
10051     list = pctxt->constructor->buckets;
10052     if (list->nbItems == 0)
10053 	return(NULL);
10054     else {
10055 	int i;
10056 	for (i = 0; i < list->nbItems; i++) {
10057 	    cur = (xmlSchemaBucketPtr) list->items[i];
10058 	    if ((! IS_BAD_SCHEMA_DOC(cur)) &&
10059 		(cur->origTargetNamespace == targetNamespace) &&
10060 		((imported && cur->imported) ||
10061 		 ((!imported) && (!cur->imported))))
10062 		return(cur);
10063 	}
10064     }
10065     return(NULL);
10066 }
10067 
10068 static int
xmlSchemaParseNewDocWithContext(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlSchemaBucketPtr bucket)10069 xmlSchemaParseNewDocWithContext(xmlSchemaParserCtxtPtr pctxt,
10070 		     xmlSchemaPtr schema,
10071 		     xmlSchemaBucketPtr bucket)
10072 {
10073     int oldFlags;
10074     xmlDocPtr oldDoc;
10075     xmlNodePtr node;
10076     int ret, oldErrs;
10077     xmlSchemaBucketPtr oldbucket = pctxt->constructor->bucket;
10078 
10079     /*
10080     * Save old values; reset the *main* schema.
10081     * URGENT TODO: This is not good; move the per-document information
10082     * to the parser. Get rid of passing the main schema to the
10083     * parsing functions.
10084     */
10085     oldFlags = schema->flags;
10086     oldDoc = schema->doc;
10087     if (schema->flags != 0)
10088 	xmlSchemaClearSchemaDefaults(schema);
10089     schema->doc = bucket->doc;
10090     pctxt->schema = schema;
10091     /*
10092     * Keep the current target namespace on the parser *not* on the
10093     * main schema.
10094     */
10095     pctxt->targetNamespace = bucket->targetNamespace;
10096     WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
10097 
10098     if ((bucket->targetNamespace != NULL) &&
10099 	xmlStrEqual(bucket->targetNamespace, xmlSchemaNs)) {
10100 	/*
10101 	* We are parsing the schema for schemas!
10102 	*/
10103 	pctxt->isS4S = 1;
10104     }
10105     /* Mark it as parsed, even if parsing fails. */
10106     bucket->parsed++;
10107     /* Compile the schema doc. */
10108     node = xmlDocGetRootElement(bucket->doc);
10109     ret = xmlSchemaParseSchemaElement(pctxt, schema, node);
10110     if (ret != 0)
10111 	goto exit;
10112     /* An empty schema; just get out. */
10113     if (node->children == NULL)
10114 	goto exit;
10115     oldErrs = pctxt->nberrors;
10116     ret = xmlSchemaParseSchemaTopLevel(pctxt, schema, node->children);
10117     if (ret != 0)
10118 	goto exit;
10119     /*
10120     * TODO: Not nice, but I'm not 100% sure we will get always an error
10121     * as a result of the above functions; so better rely on pctxt->err
10122     * as well.
10123     */
10124     if ((ret == 0) && (oldErrs != pctxt->nberrors)) {
10125 	ret = pctxt->err;
10126 	goto exit;
10127     }
10128 
10129 exit:
10130     WXS_CONSTRUCTOR(pctxt)->bucket = oldbucket;
10131     /* Restore schema values. */
10132     schema->doc = oldDoc;
10133     schema->flags = oldFlags;
10134     return(ret);
10135 }
10136 
10137 static int
xmlSchemaParseNewDoc(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlSchemaBucketPtr bucket)10138 xmlSchemaParseNewDoc(xmlSchemaParserCtxtPtr pctxt,
10139 		     xmlSchemaPtr schema,
10140 		     xmlSchemaBucketPtr bucket)
10141 {
10142     xmlSchemaParserCtxtPtr newpctxt;
10143     int res = 0;
10144 
10145     if (bucket == NULL)
10146 	return(0);
10147     if (bucket->parsed) {
10148 	PERROR_INT("xmlSchemaParseNewDoc",
10149 	    "reparsing a schema doc");
10150 	return(-1);
10151     }
10152     if (bucket->doc == NULL) {
10153 	PERROR_INT("xmlSchemaParseNewDoc",
10154 	    "parsing a schema doc, but there's no doc");
10155 	return(-1);
10156     }
10157     if (pctxt->constructor == NULL) {
10158 	PERROR_INT("xmlSchemaParseNewDoc",
10159 	    "no constructor");
10160 	return(-1);
10161     }
10162     /* Create and init the temporary parser context. */
10163     newpctxt = xmlSchemaNewParserCtxtUseDict(
10164 	(const char *) bucket->schemaLocation, pctxt->dict);
10165     if (newpctxt == NULL)
10166 	return(-1);
10167     newpctxt->constructor = pctxt->constructor;
10168     /*
10169     * TODO: Can we avoid that the parser knows about the main schema?
10170     * It would be better if he knows about the current schema bucket
10171     * only.
10172     */
10173     newpctxt->schema = schema;
10174     xmlSchemaSetParserErrors(newpctxt, pctxt->error, pctxt->warning,
10175 	pctxt->errCtxt);
10176     xmlSchemaSetParserStructuredErrors(newpctxt, pctxt->serror,
10177 	pctxt->errCtxt);
10178     newpctxt->counter = pctxt->counter;
10179 
10180 
10181     res = xmlSchemaParseNewDocWithContext(newpctxt, schema, bucket);
10182 
10183     /* Channel back errors and cleanup the temporary parser context. */
10184     if (res != 0)
10185 	pctxt->err = res;
10186     pctxt->nberrors += newpctxt->nberrors;
10187     pctxt->counter = newpctxt->counter;
10188     newpctxt->constructor = NULL;
10189     /* Free the parser context. */
10190     xmlSchemaFreeParserCtxt(newpctxt);
10191     return(res);
10192 }
10193 
10194 static void
xmlSchemaSchemaRelationAddChild(xmlSchemaBucketPtr bucket,xmlSchemaSchemaRelationPtr rel)10195 xmlSchemaSchemaRelationAddChild(xmlSchemaBucketPtr bucket,
10196 				xmlSchemaSchemaRelationPtr rel)
10197 {
10198     xmlSchemaSchemaRelationPtr cur = bucket->relations;
10199 
10200     if (cur == NULL) {
10201 	bucket->relations = rel;
10202 	return;
10203     }
10204     while (cur->next != NULL)
10205 	cur = cur->next;
10206     cur->next = rel;
10207 }
10208 
10209 
10210 static const xmlChar *
xmlSchemaBuildAbsoluteURI(xmlDictPtr dict,const xmlChar * location,xmlNodePtr ctxtNode)10211 xmlSchemaBuildAbsoluteURI(xmlDictPtr dict, const xmlChar* location,
10212 			  xmlNodePtr ctxtNode)
10213 {
10214     /*
10215     * Build an absolute location URI.
10216     */
10217     if (location != NULL) {
10218 	if (ctxtNode == NULL)
10219 	    return(location);
10220 	else {
10221 	    xmlChar *base, *URI;
10222 	    const xmlChar *ret = NULL;
10223 
10224 	    base = xmlNodeGetBase(ctxtNode->doc, ctxtNode);
10225 	    if (base == NULL) {
10226 		URI = xmlBuildURI(location, ctxtNode->doc->URL);
10227 	    } else {
10228 		URI = xmlBuildURI(location, base);
10229 		xmlFree(base);
10230 	    }
10231 	    if (URI != NULL) {
10232 		ret = xmlDictLookup(dict, URI, -1);
10233 		xmlFree(URI);
10234 		return(ret);
10235 	    }
10236 	}
10237     }
10238     return(NULL);
10239 }
10240 
10241 
10242 
10243 /**
10244  * xmlSchemaAddSchemaDoc:
10245  * @pctxt:  a schema validation context
10246  * @schema:  the schema being built
10247  * @node:  a subtree containing XML Schema information
10248  *
10249  * Parse an included (and to-be-redefined) XML schema document.
10250  *
10251  * Returns 0 on success, a positive error code on errors and
10252  *         -1 in case of an internal or API error.
10253  */
10254 
10255 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)10256 xmlSchemaAddSchemaDoc(xmlSchemaParserCtxtPtr pctxt,
10257 		int type, /* import or include or redefine */
10258 		const xmlChar *schemaLocation,
10259 		xmlDocPtr schemaDoc,
10260 		const char *schemaBuffer,
10261 		int schemaBufferLen,
10262 		xmlNodePtr invokingNode,
10263 		const xmlChar *sourceTargetNamespace,
10264 		const xmlChar *importNamespace,
10265 		xmlSchemaBucketPtr *bucket)
10266 {
10267     const xmlChar *targetNamespace = NULL;
10268     xmlSchemaSchemaRelationPtr relation = NULL;
10269     xmlDocPtr doc = NULL;
10270     int res = 0, err = 0, located = 0, preserveDoc = 0;
10271     xmlSchemaBucketPtr bkt = NULL;
10272 
10273     if (bucket != NULL)
10274 	*bucket = NULL;
10275 
10276     switch (type) {
10277 	case XML_SCHEMA_SCHEMA_IMPORT:
10278 	case XML_SCHEMA_SCHEMA_MAIN:
10279 	    err = XML_SCHEMAP_SRC_IMPORT;
10280 	    break;
10281 	case XML_SCHEMA_SCHEMA_INCLUDE:
10282 	    err = XML_SCHEMAP_SRC_INCLUDE;
10283 	    break;
10284 	case XML_SCHEMA_SCHEMA_REDEFINE:
10285 	    err = XML_SCHEMAP_SRC_REDEFINE;
10286 	    break;
10287     }
10288 
10289 
10290     /* Special handling for the main schema:
10291     * skip the location and relation logic and just parse the doc.
10292     * We need just a bucket to be returned in this case.
10293     */
10294     if ((type == XML_SCHEMA_SCHEMA_MAIN) || (! WXS_HAS_BUCKETS(pctxt)))
10295 	goto doc_load;
10296 
10297     /* Note that we expect the location to be an absolute URI. */
10298     if (schemaLocation != NULL) {
10299 	bkt = xmlSchemaGetSchemaBucket(pctxt, schemaLocation);
10300 	if ((bkt != NULL) &&
10301 	    (pctxt->constructor->bucket == bkt)) {
10302 	    /* Report self-imports/inclusions/redefinitions. */
10303 
10304 	    xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10305 		invokingNode, NULL,
10306 		"The schema must not import/include/redefine itself",
10307 		NULL, NULL);
10308 	    goto exit;
10309 	}
10310     }
10311     /*
10312     * Create a relation for the graph of schemas.
10313     */
10314     relation = xmlSchemaSchemaRelationCreate();
10315     if (relation == NULL)
10316 	return(-1);
10317     xmlSchemaSchemaRelationAddChild(pctxt->constructor->bucket,
10318 	relation);
10319     relation->type = type;
10320 
10321     /*
10322     * Save the namespace import information.
10323     */
10324     if (WXS_IS_BUCKET_IMPMAIN(type)) {
10325 	relation->importNamespace = importNamespace;
10326 	if (schemaLocation == NULL) {
10327 	    /*
10328 	    * No location; this is just an import of the namespace.
10329 	    * Note that we don't assign a bucket to the relation
10330 	    * in this case.
10331 	    */
10332 	    goto exit;
10333 	}
10334 	targetNamespace = importNamespace;
10335     }
10336 
10337     /* Did we already fetch the doc? */
10338     if (bkt != NULL) {
10339 	if ((WXS_IS_BUCKET_IMPMAIN(type)) && (! bkt->imported)) {
10340 	    /*
10341 	    * We included/redefined and then try to import a schema,
10342 	    * but the new location provided for import was different.
10343 	    */
10344 	    if (schemaLocation == NULL)
10345 		schemaLocation = BAD_CAST "in_memory_buffer";
10346 	    if (!xmlStrEqual(schemaLocation,
10347 		bkt->schemaLocation)) {
10348 		xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10349 		    invokingNode, NULL,
10350 		    "The schema document '%s' cannot be imported, since "
10351 		    "it was already included or redefined",
10352 		    schemaLocation, NULL);
10353 		goto exit;
10354 	    }
10355 	} else if ((! WXS_IS_BUCKET_IMPMAIN(type)) && (bkt->imported)) {
10356 	    /*
10357 	    * We imported and then try to include/redefine a schema,
10358 	    * but the new location provided for the include/redefine
10359 	    * was different.
10360 	    */
10361 	    if (schemaLocation == NULL)
10362 		schemaLocation = BAD_CAST "in_memory_buffer";
10363 	    if (!xmlStrEqual(schemaLocation,
10364 		bkt->schemaLocation)) {
10365 		xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10366 		    invokingNode, NULL,
10367 		    "The schema document '%s' cannot be included or "
10368 		    "redefined, since it was already imported",
10369 		    schemaLocation, NULL);
10370 		goto exit;
10371 	    }
10372 	}
10373     }
10374 
10375     if (WXS_IS_BUCKET_IMPMAIN(type)) {
10376 	/*
10377 	* Given that the schemaLocation [attribute] is only a hint, it is open
10378 	* to applications to ignore all but the first <import> for a given
10379 	* namespace, regardless of the `actual value` of schemaLocation, but
10380 	* such a strategy risks missing useful information when new
10381 	* schemaLocations are offered.
10382 	*
10383 	* We will use the first <import> that comes with a location.
10384 	* Further <import>s *with* a location, will result in an error.
10385 	* TODO: Better would be to just report a warning here, but
10386 	* we'll try it this way until someone complains.
10387 	*
10388 	* Schema Document Location Strategy:
10389 	* 3 Based on the namespace name, identify an existing schema document,
10390 	* either as a resource which is an XML document or a <schema> element
10391 	* information item, in some local schema repository;
10392 	* 5 Attempt to resolve the namespace name to locate such a resource.
10393 	*
10394 	* NOTE: (3) and (5) are not supported.
10395 	*/
10396 	if (bkt != NULL) {
10397 	    relation->bucket = bkt;
10398 	    goto exit;
10399 	}
10400 	bkt = xmlSchemaGetSchemaBucketByTNS(pctxt,
10401 	    importNamespace, 1);
10402 
10403 	if (bkt != NULL) {
10404 	    relation->bucket = bkt;
10405 	    if (bkt->schemaLocation == NULL) {
10406 		/* First given location of the schema; load the doc. */
10407 		bkt->schemaLocation = schemaLocation;
10408 	    } else {
10409 		if (!xmlStrEqual(schemaLocation,
10410 		    bkt->schemaLocation)) {
10411 		    /*
10412 		    * Additional location given; just skip it.
10413 		    * URGENT TODO: We should report a warning here.
10414 		    * res = XML_SCHEMAP_SRC_IMPORT;
10415 		    */
10416 		    if (schemaLocation == NULL)
10417 			schemaLocation = BAD_CAST "in_memory_buffer";
10418 
10419 		    xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10420 			XML_SCHEMAP_WARN_SKIP_SCHEMA,
10421 			invokingNode, NULL,
10422 			"Skipping import of schema located at '%s' for the "
10423 			"namespace '%s', since this namespace was already "
10424 			"imported with the schema located at '%s'",
10425 			schemaLocation, importNamespace, bkt->schemaLocation);
10426 		}
10427 		goto exit;
10428 	    }
10429 	}
10430 	/*
10431 	* No bucket + first location: load the doc and create a
10432 	* bucket.
10433 	*/
10434     } else {
10435 	/* <include> and <redefine> */
10436 	if (bkt != NULL) {
10437 
10438 	    if ((bkt->origTargetNamespace == NULL) &&
10439 		(bkt->targetNamespace != sourceTargetNamespace)) {
10440 		xmlSchemaBucketPtr chamel;
10441 
10442 		/*
10443 		* Chameleon include/redefine: skip loading only if it was
10444 		* already build for the targetNamespace of the including
10445 		* schema.
10446 		*/
10447 		/*
10448 		* URGENT TODO: If the schema is a chameleon-include then copy
10449 		* the components into the including schema and modify the
10450 		* targetNamespace of those components, do nothing otherwise.
10451 		* NOTE: This is currently worked-around by compiling the
10452 		* chameleon for every distinct including targetNamespace; thus
10453 		* not performant at the moment.
10454 		* TODO: Check when the namespace in wildcards for chameleons
10455 		* needs to be converted: before we built wildcard intersections
10456 		* or after.
10457 		*   Answer: after!
10458 		*/
10459 		chamel = xmlSchemaGetChameleonSchemaBucket(pctxt,
10460 		    schemaLocation, sourceTargetNamespace);
10461 		if (chamel != NULL) {
10462 		    /* A fitting chameleon was already parsed; NOP. */
10463 		    relation->bucket = chamel;
10464 		    goto exit;
10465 		}
10466 		/*
10467 		* We need to parse the chameleon again for a different
10468 		* targetNamespace.
10469 		* CHAMELEON TODO: Optimize this by only parsing the
10470 		* chameleon once, and then copying the components to
10471 		* the new targetNamespace.
10472 		*/
10473 		bkt = NULL;
10474 	    } else {
10475 		relation->bucket = bkt;
10476 		goto exit;
10477 	    }
10478 	}
10479     }
10480     if ((bkt != NULL) && (bkt->doc != NULL)) {
10481 	PERROR_INT("xmlSchemaAddSchemaDoc",
10482 	    "trying to load a schema doc, but a doc is already "
10483 	    "assigned to the schema bucket");
10484 	goto exit_failure;
10485     }
10486 
10487 doc_load:
10488     /*
10489     * Load the document.
10490     */
10491     if (schemaDoc != NULL) {
10492 	doc = schemaDoc;
10493 	/* Don' free this one, since it was provided by the caller. */
10494 	preserveDoc = 1;
10495 	/* TODO: Does the context or the doc hold the location? */
10496 	if (schemaDoc->URL != NULL)
10497 	    schemaLocation = xmlDictLookup(pctxt->dict,
10498 		schemaDoc->URL, -1);
10499         else
10500 	    schemaLocation = BAD_CAST "in_memory_buffer";
10501     } else if ((schemaLocation != NULL) || (schemaBuffer != NULL)) {
10502 	xmlParserCtxtPtr parserCtxt;
10503 
10504 	parserCtxt = xmlNewParserCtxt();
10505 	if (parserCtxt == NULL) {
10506 	    xmlSchemaPErrMemory(NULL);
10507 	    goto exit_failure;
10508 	}
10509 
10510         if (pctxt->serror != NULL)
10511             xmlCtxtSetErrorHandler(parserCtxt, pctxt->serror, pctxt->errCtxt);
10512         if (pctxt->resourceLoader != NULL)
10513             xmlCtxtSetResourceLoader(parserCtxt, pctxt->resourceLoader,
10514                                      pctxt->resourceCtxt);
10515 
10516 	if ((pctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
10517 	    /*
10518 	    * TODO: Do we have to burden the schema parser dict with all
10519 	    * the content of the schema doc?
10520 	    */
10521 	    xmlDictFree(parserCtxt->dict);
10522 	    parserCtxt->dict = pctxt->dict;
10523 	    xmlDictReference(parserCtxt->dict);
10524 	}
10525 	if (schemaLocation != NULL) {
10526 	    /* Parse from file. */
10527 	    doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
10528 		NULL, SCHEMAS_PARSE_OPTIONS);
10529 	} else if (schemaBuffer != NULL) {
10530 	    /* Parse from memory buffer. */
10531 	    doc = xmlCtxtReadMemory(parserCtxt, schemaBuffer, schemaBufferLen,
10532 		NULL, NULL, SCHEMAS_PARSE_OPTIONS);
10533 	    schemaLocation = BAD_CAST "in_memory_buffer";
10534 	    if (doc != NULL)
10535 		doc->URL = xmlStrdup(schemaLocation);
10536 	}
10537 	/*
10538 	* For <import>:
10539 	* 2.1 The referent is (a fragment of) a resource which is an
10540 	* XML document (see clause 1.1), which in turn corresponds to
10541 	* a <schema> element information item in a well-formed information
10542 	* set, which in turn corresponds to a valid schema.
10543 	* TODO: (2.1) fragments of XML documents are not supported.
10544 	*
10545 	* 2.2 The referent is a <schema> element information item in
10546 	* a well-formed information set, which in turn corresponds
10547 	* to a valid schema.
10548 	* TODO: (2.2) is not supported.
10549 	*/
10550 	if (doc == NULL) {
10551 	    const xmlError *lerr;
10552 	    lerr = xmlGetLastError();
10553 	    /*
10554 	    * Check if this a parser error, or if the document could
10555 	    * just not be located.
10556 	    * TODO: Try to find specific error codes to react only on
10557 	    * localisation failures.
10558 	    */
10559 	    if ((lerr == NULL) || (lerr->domain != XML_FROM_IO)) {
10560 		/*
10561 		* We assume a parser error here.
10562 		*/
10563 		located = 1;
10564 		/* TODO: Error code ?? */
10565 		res = XML_SCHEMAP_SRC_IMPORT_2_1;
10566 		xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10567 		    invokingNode, NULL,
10568 		    "Failed to parse the XML resource '%s'",
10569 		    schemaLocation, NULL);
10570 	    }
10571 	}
10572 	xmlFreeParserCtxt(parserCtxt);
10573 	if ((doc == NULL) && located)
10574 	    goto exit_error;
10575     } else {
10576 	xmlSchemaPErr(pctxt, NULL,
10577 	    XML_SCHEMAP_NOTHING_TO_PARSE,
10578 	    "No information for parsing was provided with the "
10579 	    "given schema parser context.\n",
10580 	    NULL, NULL);
10581 	goto exit_failure;
10582     }
10583     /*
10584     * Preprocess the document.
10585     */
10586     if (doc != NULL) {
10587 	xmlNodePtr docElem = NULL;
10588 
10589 	located = 1;
10590 	docElem = xmlDocGetRootElement(doc);
10591 	if (docElem == NULL) {
10592 	    xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOROOT,
10593 		invokingNode, NULL,
10594 		"The document '%s' has no document element",
10595 		schemaLocation, NULL);
10596 	    goto exit_error;
10597 	}
10598 	/*
10599 	* Remove all the blank text nodes.
10600 	*/
10601 	xmlSchemaCleanupDoc(pctxt, docElem);
10602 	/*
10603 	* Check the schema's top level element.
10604 	*/
10605 	if (!IS_SCHEMA(docElem, "schema")) {
10606 	    xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOT_SCHEMA,
10607 		invokingNode, NULL,
10608 		"The XML document '%s' is not a schema document",
10609 		schemaLocation, NULL);
10610 	    goto exit_error;
10611 	}
10612 	/*
10613 	* Note that we don't apply a type check for the
10614 	* targetNamespace value here.
10615 	*/
10616 	targetNamespace = xmlSchemaGetProp(pctxt, docElem,
10617 	    "targetNamespace");
10618     }
10619 
10620 /* after_doc_loading: */
10621     if ((bkt == NULL) && located) {
10622 	/* Only create a bucket if the schema was located. */
10623         bkt = xmlSchemaBucketCreate(pctxt, type,
10624 	    targetNamespace);
10625 	if (bkt == NULL)
10626 	    goto exit_failure;
10627     }
10628     if (bkt != NULL) {
10629 	bkt->schemaLocation = schemaLocation;
10630 	bkt->located = located;
10631 	if (doc != NULL) {
10632 	    bkt->doc = doc;
10633 	    bkt->targetNamespace = targetNamespace;
10634 	    bkt->origTargetNamespace = targetNamespace;
10635 	    if (preserveDoc)
10636 		bkt->preserveDoc = 1;
10637 	}
10638 	if (WXS_IS_BUCKET_IMPMAIN(type))
10639 	    bkt->imported++;
10640 	    /*
10641 	    * Add it to the graph of schemas.
10642 	    */
10643 	if (relation != NULL)
10644 	    relation->bucket = bkt;
10645     }
10646 
10647 exit:
10648     /*
10649     * Return the bucket explicitly; this is needed for the
10650     * main schema.
10651     */
10652     if (bucket != NULL)
10653 	*bucket = bkt;
10654     return (0);
10655 
10656 exit_error:
10657     if ((doc != NULL) && (! preserveDoc)) {
10658 	xmlFreeDoc(doc);
10659 	if (bkt != NULL)
10660 	    bkt->doc = NULL;
10661     }
10662     return(pctxt->err);
10663 
10664 exit_failure:
10665     if ((doc != NULL) && (! preserveDoc)) {
10666 	xmlFreeDoc(doc);
10667 	if (bkt != NULL)
10668 	    bkt->doc = NULL;
10669     }
10670     return (-1);
10671 }
10672 
10673 /**
10674  * xmlSchemaParseImport:
10675  * @ctxt:  a schema validation context
10676  * @schema:  the schema being built
10677  * @node:  a subtree containing XML Schema information
10678  *
10679  * parse a XML schema Import definition
10680  * *WARNING* this interface is highly subject to change
10681  *
10682  * Returns 0 in case of success, a positive error code if
10683  * not valid and -1 in case of an internal error.
10684  */
10685 static int
xmlSchemaParseImport(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node)10686 xmlSchemaParseImport(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
10687                      xmlNodePtr node)
10688 {
10689     xmlNodePtr child;
10690     const xmlChar *namespaceName = NULL, *schemaLocation = NULL;
10691     const xmlChar *thisTargetNamespace;
10692     xmlAttrPtr attr;
10693     int ret = 0;
10694     xmlSchemaBucketPtr bucket = NULL;
10695 
10696     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
10697         return (-1);
10698 
10699     /*
10700     * Check for illegal attributes.
10701     */
10702     attr = node->properties;
10703     while (attr != NULL) {
10704 	if (attr->ns == NULL) {
10705 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10706 		(!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
10707 		(!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
10708 		xmlSchemaPIllegalAttrErr(pctxt,
10709 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10710 	    }
10711 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10712 	    xmlSchemaPIllegalAttrErr(pctxt,
10713 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10714 	}
10715 	attr = attr->next;
10716     }
10717     /*
10718     * Extract and validate attributes.
10719     */
10720     if (xmlSchemaPValAttr(pctxt, NULL, node,
10721 	"namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10722 	&namespaceName) != 0) {
10723 	xmlSchemaPSimpleTypeErr(pctxt,
10724 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
10725 	    NULL, node,
10726 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10727 	    NULL, namespaceName, NULL, NULL, NULL);
10728 	return (pctxt->err);
10729     }
10730 
10731     if (xmlSchemaPValAttr(pctxt, NULL, node,
10732 	"schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10733 	&schemaLocation) != 0) {
10734 	xmlSchemaPSimpleTypeErr(pctxt,
10735 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
10736 	    NULL, node,
10737 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10738 	    NULL, schemaLocation, NULL, NULL, NULL);
10739 	return (pctxt->err);
10740     }
10741     /*
10742     * And now for the children...
10743     */
10744     child = node->children;
10745     if (IS_SCHEMA(child, "annotation")) {
10746         /*
10747          * the annotation here is simply discarded ...
10748 	 * TODO: really?
10749          */
10750         child = child->next;
10751     }
10752     if (child != NULL) {
10753 	xmlSchemaPContentErr(pctxt,
10754 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10755 	    NULL, node, child, NULL,
10756 	    "(annotation?)");
10757     }
10758     /*
10759     * Apply additional constraints.
10760     *
10761     * Note that it is important to use the original @targetNamespace
10762     * (or none at all), to rule out imports of schemas _with_ a
10763     * @targetNamespace if the importing schema is a chameleon schema
10764     * (with no @targetNamespace).
10765     */
10766     thisTargetNamespace = WXS_BUCKET(pctxt)->origTargetNamespace;
10767     if (namespaceName != NULL) {
10768 	/*
10769 	* 1.1 If the namespace [attribute] is present, then its `actual value`
10770 	* must not match the `actual value` of the enclosing <schema>'s
10771 	* targetNamespace [attribute].
10772 	*/
10773 	if (xmlStrEqual(thisTargetNamespace, namespaceName)) {
10774 	    xmlSchemaPCustomErr(pctxt,
10775 		XML_SCHEMAP_SRC_IMPORT_1_1,
10776 		NULL, node,
10777 		"The value of the attribute 'namespace' must not match "
10778 		"the target namespace '%s' of the importing schema",
10779 		thisTargetNamespace);
10780 	    return (pctxt->err);
10781 	}
10782     } else {
10783 	/*
10784 	* 1.2 If the namespace [attribute] is not present, then the enclosing
10785 	* <schema> must have a targetNamespace [attribute].
10786 	*/
10787 	if (thisTargetNamespace == NULL) {
10788 	    xmlSchemaPCustomErr(pctxt,
10789 		XML_SCHEMAP_SRC_IMPORT_1_2,
10790 		NULL, node,
10791 		"The attribute 'namespace' must be existent if "
10792 		"the importing schema has no target namespace",
10793 		NULL);
10794 	    return (pctxt->err);
10795 	}
10796     }
10797     /*
10798     * Locate and acquire the schema document.
10799     */
10800     if (schemaLocation != NULL)
10801 	schemaLocation = xmlSchemaBuildAbsoluteURI(pctxt->dict,
10802 	    schemaLocation, node);
10803     ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
10804 	schemaLocation, NULL, NULL, 0, node, thisTargetNamespace,
10805 	namespaceName, &bucket);
10806 
10807     if (ret != 0)
10808 	return(ret);
10809 
10810     /*
10811     * For <import>: "It is *not* an error for the application
10812     * schema reference strategy to fail."
10813     * So just don't parse if no schema document was found.
10814     * Note that we will get no bucket if the schema could not be
10815     * located or if there was no schemaLocation.
10816     */
10817     if ((bucket == NULL) && (schemaLocation != NULL)) {
10818 	xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10819 	    XML_SCHEMAP_WARN_UNLOCATED_SCHEMA,
10820 	    node, NULL,
10821 	    "Failed to locate a schema at location '%s'. "
10822 	    "Skipping the import", schemaLocation, NULL, NULL);
10823     }
10824 
10825     if ((bucket != NULL) && CAN_PARSE_SCHEMA(bucket)) {
10826 	ret = xmlSchemaParseNewDoc(pctxt, schema, bucket);
10827     }
10828 
10829     return (ret);
10830 }
10831 
10832 static int
xmlSchemaParseIncludeOrRedefineAttrs(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node,xmlChar ** schemaLocation,int type)10833 xmlSchemaParseIncludeOrRedefineAttrs(xmlSchemaParserCtxtPtr pctxt,
10834 				     xmlSchemaPtr schema,
10835 				     xmlNodePtr node,
10836 				     xmlChar **schemaLocation,
10837 				     int type)
10838 {
10839     xmlAttrPtr attr;
10840 
10841     if ((pctxt == NULL) || (schema == NULL) || (node == NULL) ||
10842 	(schemaLocation == NULL))
10843         return (-1);
10844 
10845     *schemaLocation = NULL;
10846     /*
10847     * Check for illegal attributes.
10848     * Applies for both <include> and <redefine>.
10849     */
10850     attr = node->properties;
10851     while (attr != NULL) {
10852 	if (attr->ns == NULL) {
10853 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10854 		(!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
10855 		xmlSchemaPIllegalAttrErr(pctxt,
10856 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10857 	    }
10858 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10859 	    xmlSchemaPIllegalAttrErr(pctxt,
10860 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10861 	}
10862 	attr = attr->next;
10863     }
10864     xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
10865     /*
10866     * Preliminary step, extract the URI-Reference and make an URI
10867     * from the base.
10868     */
10869     /*
10870     * Attribute "schemaLocation" is mandatory.
10871     */
10872     attr = xmlSchemaGetPropNode(node, "schemaLocation");
10873     if (attr != NULL) {
10874         xmlChar *base = NULL;
10875         xmlChar *uri = NULL;
10876 
10877 	if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
10878 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10879 	    (const xmlChar **) schemaLocation) != 0)
10880 	    goto exit_error;
10881 	base = xmlNodeGetBase(node->doc, node);
10882 	if (base == NULL) {
10883 	    uri = xmlBuildURI(*schemaLocation, node->doc->URL);
10884 	} else {
10885 	    uri = xmlBuildURI(*schemaLocation, base);
10886 	    xmlFree(base);
10887 	}
10888 	if (uri == NULL) {
10889 	    PERROR_INT("xmlSchemaParseIncludeOrRedefine",
10890 		"could not build an URI from the schemaLocation")
10891 	    goto exit_failure;
10892 	}
10893 	(*schemaLocation) = (xmlChar *) xmlDictLookup(pctxt->dict, uri, -1);
10894 	xmlFree(uri);
10895     } else {
10896 	xmlSchemaPMissingAttrErr(pctxt,
10897 	    XML_SCHEMAP_S4S_ATTR_MISSING,
10898 	    NULL, node, "schemaLocation", NULL);
10899 	goto exit_error;
10900     }
10901     /*
10902     * Report self-inclusion and self-redefinition.
10903     */
10904     if (xmlStrEqual(*schemaLocation, pctxt->URL)) {
10905 	if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
10906 	    xmlSchemaPCustomErr(pctxt,
10907 		XML_SCHEMAP_SRC_REDEFINE,
10908 		NULL, node,
10909 		"The schema document '%s' cannot redefine itself.",
10910 		*schemaLocation);
10911 	} else {
10912 	    xmlSchemaPCustomErr(pctxt,
10913 		XML_SCHEMAP_SRC_INCLUDE,
10914 		NULL, node,
10915 		"The schema document '%s' cannot include itself.",
10916 		*schemaLocation);
10917 	}
10918 	goto exit_error;
10919     }
10920 
10921     return(0);
10922 exit_error:
10923     return(pctxt->err);
10924 exit_failure:
10925     return(-1);
10926 }
10927 
10928 static int
xmlSchemaParseIncludeOrRedefine(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node,int type)10929 xmlSchemaParseIncludeOrRedefine(xmlSchemaParserCtxtPtr pctxt,
10930 				xmlSchemaPtr schema,
10931 				xmlNodePtr node,
10932 				int type)
10933 {
10934     xmlNodePtr child = NULL;
10935     const xmlChar *schemaLocation = NULL;
10936     int res = 0; /* hasRedefinitions = 0 */
10937     int isChameleon = 0, wasChameleon = 0;
10938     xmlSchemaBucketPtr bucket = NULL;
10939 
10940     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
10941         return (-1);
10942 
10943     /*
10944     * Parse attributes. Note that the returned schemaLocation will
10945     * be already converted to an absolute URI.
10946     */
10947     res = xmlSchemaParseIncludeOrRedefineAttrs(pctxt, schema,
10948 	node, (xmlChar **) (&schemaLocation), type);
10949     if (res != 0)
10950 	return(res);
10951     /*
10952     * Load and add the schema document.
10953     */
10954     res = xmlSchemaAddSchemaDoc(pctxt, type, schemaLocation, NULL,
10955 	NULL, 0, node, pctxt->targetNamespace, NULL, &bucket);
10956     if (res != 0)
10957 	return(res);
10958     /*
10959     * If we get no schema bucket back, then this means that the schema
10960     * document could not be located or was broken XML or was not
10961     * a schema document.
10962     */
10963     if ((bucket == NULL) || (bucket->doc == NULL)) {
10964 	if (type == XML_SCHEMA_SCHEMA_INCLUDE) {
10965 	    /*
10966 	    * WARNING for <include>:
10967 	    * We will raise an error if the schema cannot be located
10968 	    * for inclusions, since the that was the feedback from the
10969 	    * schema people. I.e. the following spec piece will *not* be
10970 	    * satisfied:
10971 	    * SPEC src-include: "It is not an error for the `actual value` of the
10972 	    * schemaLocation [attribute] to fail to resolve it all, in which
10973 	    * case no corresponding inclusion is performed.
10974 	    * So do we need a warning report here?"
10975 	    */
10976 	    res = XML_SCHEMAP_SRC_INCLUDE;
10977 	    xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10978 		node, NULL,
10979 		"Failed to load the document '%s' for inclusion",
10980 		schemaLocation, NULL);
10981 	} else {
10982 	    /*
10983 	    * NOTE: This was changed to raise an error even if no redefinitions
10984 	    * are specified.
10985 	    *
10986 	    * SPEC src-redefine (1)
10987 	    * "If there are any element information items among the [children]
10988 	    * other than <annotation> then the `actual value` of the
10989 	    * schemaLocation [attribute] must successfully resolve."
10990 	    * TODO: Ask the WG if a the location has always to resolve
10991 	    * here as well!
10992 	    */
10993 	    res = XML_SCHEMAP_SRC_REDEFINE;
10994 	    xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10995 		node, NULL,
10996 		"Failed to load the document '%s' for redefinition",
10997 		schemaLocation, NULL);
10998 	}
10999     } else {
11000 	/*
11001 	* Check targetNamespace sanity before parsing the new schema.
11002 	* TODO: Note that we won't check further content if the
11003 	* targetNamespace was bad.
11004 	*/
11005 	if (bucket->origTargetNamespace != NULL) {
11006 	    /*
11007 	    * SPEC src-include (2.1)
11008 	    * "SII has a targetNamespace [attribute], and its `actual
11009 	    * value` is identical to the `actual value` of the targetNamespace
11010 	    * [attribute] of SII' (which must have such an [attribute])."
11011 	    */
11012 	    if (pctxt->targetNamespace == NULL) {
11013 		xmlSchemaCustomErr(ACTXT_CAST pctxt,
11014 		    XML_SCHEMAP_SRC_INCLUDE,
11015 		    node, NULL,
11016 		    "The target namespace of the included/redefined schema "
11017 		    "'%s' has to be absent, since the including/redefining "
11018 		    "schema has no target namespace",
11019 		    schemaLocation, NULL);
11020 		goto exit_error;
11021 	    } else if (!xmlStrEqual(bucket->origTargetNamespace,
11022 		pctxt->targetNamespace)) {
11023 		/* TODO: Change error function. */
11024 		xmlSchemaPCustomErrExt(pctxt,
11025 		    XML_SCHEMAP_SRC_INCLUDE,
11026 		    NULL, node,
11027 		    "The target namespace '%s' of the included/redefined "
11028 		    "schema '%s' differs from '%s' of the "
11029 		    "including/redefining schema",
11030 		    bucket->origTargetNamespace, schemaLocation,
11031 		    pctxt->targetNamespace);
11032 		goto exit_error;
11033 	    }
11034 	} else if (pctxt->targetNamespace != NULL) {
11035 	    /*
11036 	    * Chameleons: the original target namespace will
11037 	    * differ from the resulting namespace.
11038 	    */
11039 	    isChameleon = 1;
11040 	    bucket->targetNamespace = pctxt->targetNamespace;
11041 	}
11042     }
11043     /*
11044     * Parse the schema.
11045     */
11046     if (bucket && (!bucket->parsed) && (bucket->doc != NULL)) {
11047 	if (isChameleon) {
11048 	    /* TODO: Get rid of this flag on the schema itself. */
11049 	    if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
11050 		schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11051 	    } else
11052 		wasChameleon = 1;
11053 	}
11054 	xmlSchemaParseNewDoc(pctxt, schema, bucket);
11055 	/* Restore chameleon flag. */
11056 	if (isChameleon && (!wasChameleon))
11057 	    schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11058     }
11059     /*
11060     * And now for the children...
11061     */
11062     child = node->children;
11063     if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
11064 	/*
11065 	* Parse (simpleType | complexType | group | attributeGroup))*
11066 	*/
11067 	pctxt->redefined = bucket;
11068 	/*
11069 	* How to proceed if the redefined schema was not located?
11070 	*/
11071 	pctxt->isRedefine = 1;
11072 	while (IS_SCHEMA(child, "annotation") ||
11073 	    IS_SCHEMA(child, "simpleType") ||
11074 	    IS_SCHEMA(child, "complexType") ||
11075 	    IS_SCHEMA(child, "group") ||
11076 	    IS_SCHEMA(child, "attributeGroup")) {
11077 	    if (IS_SCHEMA(child, "annotation")) {
11078 		/*
11079 		* TODO: discard or not?
11080 		*/
11081 	    } else if (IS_SCHEMA(child, "simpleType")) {
11082 		xmlSchemaParseSimpleType(pctxt, schema, child, 1);
11083 	    } else if (IS_SCHEMA(child, "complexType")) {
11084 		xmlSchemaParseComplexType(pctxt, schema, child, 1);
11085 		/* hasRedefinitions = 1; */
11086 	    } else if (IS_SCHEMA(child, "group")) {
11087 		/* hasRedefinitions = 1; */
11088 		xmlSchemaParseModelGroupDefinition(pctxt,
11089 		    schema, child);
11090 	    } else if (IS_SCHEMA(child, "attributeGroup")) {
11091 		/* hasRedefinitions = 1; */
11092 		xmlSchemaParseAttributeGroupDefinition(pctxt, schema,
11093 		    child);
11094 	    }
11095 	    child = child->next;
11096 	}
11097 	pctxt->redefined = NULL;
11098 	pctxt->isRedefine = 0;
11099     } else {
11100 	if (IS_SCHEMA(child, "annotation")) {
11101 	    /*
11102 	    * TODO: discard or not?
11103 	    */
11104 	    child = child->next;
11105 	}
11106     }
11107     if (child != NULL) {
11108 	res = XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED;
11109 	if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
11110 	    xmlSchemaPContentErr(pctxt, res,
11111 		NULL, node, child, NULL,
11112 		"(annotation | (simpleType | complexType | group | attributeGroup))*");
11113 	} else {
11114 	     xmlSchemaPContentErr(pctxt, res,
11115 		NULL, node, child, NULL,
11116 		"(annotation?)");
11117 	}
11118     }
11119     return(res);
11120 
11121 exit_error:
11122     return(pctxt->err);
11123 }
11124 
11125 static int
xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node)11126 xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11127                        xmlNodePtr node)
11128 {
11129     int res;
11130 #ifndef ENABLE_REDEFINE
11131     TODO
11132     return(0);
11133 #endif
11134     res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11135 	XML_SCHEMA_SCHEMA_REDEFINE);
11136     if (res != 0)
11137 	return(res);
11138     return(0);
11139 }
11140 
11141 static int
xmlSchemaParseInclude(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node)11142 xmlSchemaParseInclude(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11143                        xmlNodePtr node)
11144 {
11145     int res;
11146 
11147     res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11148 	XML_SCHEMA_SCHEMA_INCLUDE);
11149     if (res != 0)
11150 	return(res);
11151     return(0);
11152 }
11153 
11154 /**
11155  * xmlSchemaParseModelGroup:
11156  * @ctxt:  a schema validation context
11157  * @schema:  the schema being built
11158  * @node:  a subtree containing XML Schema information
11159  * @type: the "compositor" type
11160  * @particleNeeded: if a a model group with a particle
11161  *
11162  * parse a XML schema Sequence definition.
11163  * Applies parts of:
11164  *   Schema Representation Constraint:
11165  *     Redefinition Constraints and Semantics (src-redefine)
11166  *     (6.1), (6.1.1), (6.1.2)
11167  *
11168  *   Schema Component Constraint:
11169  *     All Group Limited (cos-all-limited) (2)
11170  *     TODO: Actually this should go to component-level checks,
11171  *     but is done here due to performance. Move it to an other layer
11172  *     is schema construction via an API is implemented.
11173  *
11174  * *WARNING* this interface is highly subject to change
11175  *
11176  * Returns -1 in case of error, 0 if the declaration is improper and
11177  *         1 in case of success.
11178  */
11179 static xmlSchemaTreeItemPtr
xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,xmlSchemaTypeType type,int withParticle)11180 xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11181 			 xmlNodePtr node, xmlSchemaTypeType type,
11182 			 int withParticle)
11183 {
11184     xmlSchemaModelGroupPtr item;
11185     xmlSchemaParticlePtr particle = NULL;
11186     xmlNodePtr child = NULL;
11187     xmlAttrPtr attr;
11188     int min = 1, max = 1, isElemRef, hasRefs = 0;
11189 
11190     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11191         return (NULL);
11192     /*
11193     * Create a model group with the given compositor.
11194     */
11195     item = xmlSchemaAddModelGroup(ctxt, schema, type, node);
11196     if (item == NULL)
11197 	return (NULL);
11198 
11199     if (withParticle) {
11200 	if (type == XML_SCHEMA_TYPE_ALL) {
11201 	    min = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
11202 	    max = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
11203 	} else {
11204 	    /* choice + sequence */
11205 	    min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
11206 	    max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
11207 		"(xs:nonNegativeInteger | unbounded)");
11208 	}
11209 	xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
11210 	/*
11211 	* Create a particle
11212 	*/
11213 	particle = xmlSchemaAddParticle(ctxt, node, min, max);
11214 	if (particle == NULL)
11215 	    return (NULL);
11216 	particle->children = (xmlSchemaTreeItemPtr) item;
11217 	/*
11218 	* Check for illegal attributes.
11219 	*/
11220 	attr = node->properties;
11221 	while (attr != NULL) {
11222 	    if (attr->ns == NULL) {
11223 		if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11224 		    (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
11225 		    (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
11226 		    xmlSchemaPIllegalAttrErr(ctxt,
11227 			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11228 		}
11229 	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11230 		xmlSchemaPIllegalAttrErr(ctxt,
11231 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11232 	    }
11233 	    attr = attr->next;
11234 	}
11235     } else {
11236 	/*
11237 	* Check for illegal attributes.
11238 	*/
11239 	attr = node->properties;
11240 	while (attr != NULL) {
11241 	    if (attr->ns == NULL) {
11242 		if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
11243 		    xmlSchemaPIllegalAttrErr(ctxt,
11244 			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11245 		}
11246 	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11247 		xmlSchemaPIllegalAttrErr(ctxt,
11248 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11249 	    }
11250 	    attr = attr->next;
11251 	}
11252     }
11253 
11254     /*
11255     * Extract and validate attributes.
11256     */
11257     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11258     /*
11259     * And now for the children...
11260     */
11261     child = node->children;
11262     if (IS_SCHEMA(child, "annotation")) {
11263         item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
11264         child = child->next;
11265     }
11266     if (type == XML_SCHEMA_TYPE_ALL) {
11267 	xmlSchemaParticlePtr part, last = NULL;
11268 
11269 	while (IS_SCHEMA(child, "element")) {
11270 	    part = (xmlSchemaParticlePtr) xmlSchemaParseElement(ctxt,
11271 		schema, child, &isElemRef, 0);
11272 	    /*
11273 	    * SPEC cos-all-limited (2)
11274 	    * "The {max occurs} of all the particles in the {particles}
11275 	    * of the ('all') group must be 0 or 1.
11276 	    */
11277 	    if (part != NULL) {
11278 		if (isElemRef)
11279 		    hasRefs++;
11280 		if (part->minOccurs > 1) {
11281 		    xmlSchemaPCustomErr(ctxt,
11282 			XML_SCHEMAP_COS_ALL_LIMITED,
11283 			NULL, child,
11284 			"Invalid value for minOccurs (must be 0 or 1)",
11285 			NULL);
11286 		    /* Reset to 1. */
11287 		    part->minOccurs = 1;
11288 		}
11289 		if (part->maxOccurs > 1) {
11290 		    xmlSchemaPCustomErr(ctxt,
11291 			XML_SCHEMAP_COS_ALL_LIMITED,
11292 			NULL, child,
11293 			"Invalid value for maxOccurs (must be 0 or 1)",
11294 			NULL);
11295 		    /* Reset to 1. */
11296 		    part->maxOccurs = 1;
11297 		}
11298 		if (last == NULL)
11299 		    item->children = (xmlSchemaTreeItemPtr) part;
11300 		else
11301 		    last->next = (xmlSchemaTreeItemPtr) part;
11302 		last = part;
11303 	    }
11304 	    child = child->next;
11305 	}
11306 	if (child != NULL) {
11307 	    xmlSchemaPContentErr(ctxt,
11308 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11309 		NULL, node, child, NULL,
11310 		"(annotation?, (annotation?, element*)");
11311 	}
11312     } else {
11313 	/* choice + sequence */
11314 	xmlSchemaTreeItemPtr part = NULL, last = NULL;
11315 
11316 	while ((IS_SCHEMA(child, "element")) ||
11317 	    (IS_SCHEMA(child, "group")) ||
11318 	    (IS_SCHEMA(child, "any")) ||
11319 	    (IS_SCHEMA(child, "choice")) ||
11320 	    (IS_SCHEMA(child, "sequence"))) {
11321 
11322 	    if (IS_SCHEMA(child, "element")) {
11323 		part = (xmlSchemaTreeItemPtr)
11324 		    xmlSchemaParseElement(ctxt, schema, child, &isElemRef, 0);
11325 		if (part && isElemRef)
11326 		    hasRefs++;
11327 	    } else if (IS_SCHEMA(child, "group")) {
11328 		part =
11329 		    xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11330 		if (part != NULL)
11331 		    hasRefs++;
11332 		/*
11333 		* Handle redefinitions.
11334 		*/
11335 		if (ctxt->isRedefine && ctxt->redef &&
11336 		    (ctxt->redef->item->type == XML_SCHEMA_TYPE_GROUP) &&
11337 		    part && part->children)
11338 		{
11339 		    if ((xmlSchemaGetQNameRefName(part->children) ==
11340 			    ctxt->redef->refName) &&
11341 			(xmlSchemaGetQNameRefTargetNs(part->children) ==
11342 			    ctxt->redef->refTargetNs))
11343 		    {
11344 			/*
11345 			* SPEC src-redefine:
11346 			* (6.1) "If it has a <group> among its contents at
11347 			* some level the `actual value` of whose ref
11348 			* [attribute] is the same as the `actual value` of
11349 			* its own name attribute plus target namespace, then
11350 			* all of the following must be true:"
11351 			* (6.1.1) "It must have exactly one such group."
11352 			*/
11353 			if (ctxt->redefCounter != 0) {
11354 			    xmlChar *str = NULL;
11355 
11356 			    xmlSchemaCustomErr(ACTXT_CAST ctxt,
11357 				XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11358 				"The redefining model group definition "
11359 				"'%s' must not contain more than one "
11360 				"reference to the redefined definition",
11361 				xmlSchemaFormatQName(&str,
11362 				    ctxt->redef->refTargetNs,
11363 				    ctxt->redef->refName),
11364 				NULL);
11365 			    FREE_AND_NULL(str)
11366 			    part = NULL;
11367 			} else if (((WXS_PARTICLE(part))->minOccurs != 1) ||
11368 			    ((WXS_PARTICLE(part))->maxOccurs != 1))
11369 			{
11370 			    xmlChar *str = NULL;
11371 			    /*
11372 			    * SPEC src-redefine:
11373 			    * (6.1.2) "The `actual value` of both that
11374 			    * group's minOccurs and maxOccurs [attribute]
11375 			    * must be 1 (or `absent`).
11376 			    */
11377 			    xmlSchemaCustomErr(ACTXT_CAST ctxt,
11378 				XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11379 				"The redefining model group definition "
11380 				"'%s' must not contain a reference to the "
11381 				"redefined definition with a "
11382 				"maxOccurs/minOccurs other than 1",
11383 				xmlSchemaFormatQName(&str,
11384 				    ctxt->redef->refTargetNs,
11385 				    ctxt->redef->refName),
11386 				NULL);
11387 			    FREE_AND_NULL(str)
11388 			    part = NULL;
11389 			}
11390 			ctxt->redef->reference = WXS_BASIC_CAST part;
11391 			ctxt->redefCounter++;
11392 		    }
11393 		}
11394 	    } else if (IS_SCHEMA(child, "any")) {
11395 		part = (xmlSchemaTreeItemPtr)
11396 		    xmlSchemaParseAny(ctxt, schema, child);
11397 	    } else if (IS_SCHEMA(child, "choice")) {
11398 		part = xmlSchemaParseModelGroup(ctxt, schema, child,
11399 		    XML_SCHEMA_TYPE_CHOICE, 1);
11400 	    } else if (IS_SCHEMA(child, "sequence")) {
11401 		part = xmlSchemaParseModelGroup(ctxt, schema, child,
11402 		    XML_SCHEMA_TYPE_SEQUENCE, 1);
11403 	    }
11404 	    if (part != NULL) {
11405 		if (last == NULL)
11406 		    item->children = part;
11407 		else
11408 		    last->next = part;
11409 		last = part;
11410 	    }
11411 	    child = child->next;
11412 	}
11413 	if (child != NULL) {
11414 	    xmlSchemaPContentErr(ctxt,
11415 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11416 		NULL, node, child, NULL,
11417 		"(annotation?, (element | group | choice | sequence | any)*)");
11418 	}
11419     }
11420     if ((max == 0) && (min == 0))
11421 	return (NULL);
11422     if (hasRefs) {
11423 	/*
11424 	* We need to resolve references.
11425 	*/
11426 	WXS_ADD_PENDING(ctxt, item);
11427     }
11428     if (withParticle)
11429 	return ((xmlSchemaTreeItemPtr) particle);
11430     else
11431 	return ((xmlSchemaTreeItemPtr) item);
11432 }
11433 
11434 /**
11435  * xmlSchemaParseRestriction:
11436  * @ctxt:  a schema validation context
11437  * @schema:  the schema being built
11438  * @node:  a subtree containing XML Schema information
11439  *
11440  * parse a XML schema Restriction definition
11441  * *WARNING* this interface is highly subject to change
11442  *
11443  * Returns the type definition or NULL in case of error
11444  */
11445 static xmlSchemaTypePtr
xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,xmlSchemaTypeType parentType)11446 xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11447                           xmlNodePtr node, xmlSchemaTypeType parentType)
11448 {
11449     xmlSchemaTypePtr type;
11450     xmlNodePtr child = NULL;
11451     xmlAttrPtr attr;
11452 
11453     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11454         return (NULL);
11455     /* Not a component, don't create it. */
11456     type = ctxt->ctxtType;
11457     type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
11458 
11459     /*
11460     * Check for illegal attributes.
11461     */
11462     attr = node->properties;
11463     while (attr != NULL) {
11464 	if (attr->ns == NULL) {
11465 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11466 		(!xmlStrEqual(attr->name, BAD_CAST "base"))) {
11467 		xmlSchemaPIllegalAttrErr(ctxt,
11468 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11469 	    }
11470 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11471 	    xmlSchemaPIllegalAttrErr(ctxt,
11472 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11473 	}
11474 	attr = attr->next;
11475     }
11476     /*
11477     * Extract and validate attributes.
11478     */
11479     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11480     /*
11481     * Attribute
11482     */
11483     /*
11484     * Extract the base type. The "base" attribute is mandatory if inside
11485     * a complex type or if redefining.
11486     *
11487     * SPEC (1.2) "...otherwise (<restriction> has no <simpleType> "
11488     * among its [children]), the simple type definition which is
11489     * the {content type} of the type definition `resolved` to by
11490     * the `actual value` of the base [attribute]"
11491     */
11492     if (xmlSchemaPValAttrQName(ctxt, schema, NULL, node, "base",
11493 	&(type->baseNs), &(type->base)) == 0)
11494     {
11495 	if ((type->base == NULL) && (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
11496 	    xmlSchemaPMissingAttrErr(ctxt,
11497 		XML_SCHEMAP_S4S_ATTR_MISSING,
11498 		NULL, node, "base", NULL);
11499 	} else if ((ctxt->isRedefine) &&
11500 	    (type->flags & XML_SCHEMAS_TYPE_GLOBAL))
11501 	{
11502 	    if (type->base == NULL) {
11503 		xmlSchemaPMissingAttrErr(ctxt,
11504 		    XML_SCHEMAP_S4S_ATTR_MISSING,
11505 		    NULL, node, "base", NULL);
11506 	    } else if ((! xmlStrEqual(type->base, type->name)) ||
11507 		(! xmlStrEqual(type->baseNs, type->targetNamespace)))
11508 	    {
11509 		xmlChar *str1 = NULL, *str2 = NULL;
11510 		/*
11511 		* REDEFINE: SPEC src-redefine (5)
11512 		* "Within the [children], each <simpleType> must have a
11513 		* <restriction> among its [children] ... the `actual value` of
11514 		* whose base [attribute] must be the same as the `actual value`
11515 		* of its own name attribute plus target namespace;"
11516 		*/
11517 		xmlSchemaPCustomErrExt(ctxt, XML_SCHEMAP_SRC_REDEFINE,
11518 		    NULL, node, "This is a redefinition, but the QName "
11519 		    "value '%s' of the 'base' attribute does not match the "
11520 		    "type's designation '%s'",
11521 		    xmlSchemaFormatQName(&str1, type->baseNs, type->base),
11522 		    xmlSchemaFormatQName(&str2, type->targetNamespace,
11523 			type->name), NULL);
11524 		FREE_AND_NULL(str1);
11525 		FREE_AND_NULL(str2);
11526 		/* Avoid confusion and erase the values. */
11527 		type->base = NULL;
11528 		type->baseNs = NULL;
11529 	    }
11530 	}
11531     }
11532     /*
11533     * And now for the children...
11534     */
11535     child = node->children;
11536     if (IS_SCHEMA(child, "annotation")) {
11537 	/*
11538 	* Add the annotation to the simple type ancestor.
11539 	*/
11540 	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11541 	    xmlSchemaParseAnnotation(ctxt, child, 1));
11542         child = child->next;
11543     }
11544     if (parentType == XML_SCHEMA_TYPE_SIMPLE) {
11545 	/*
11546 	* Corresponds to <simpleType><restriction><simpleType>.
11547 	*/
11548 	if (IS_SCHEMA(child, "simpleType")) {
11549 	    if (type->base != NULL) {
11550 		/*
11551 		* src-restriction-base-or-simpleType
11552 		* Either the base [attribute] or the simpleType [child] of the
11553 		* <restriction> element must be present, but not both.
11554 		*/
11555 		xmlSchemaPContentErr(ctxt,
11556 		    XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
11557 		    NULL, node, child,
11558 		    "The attribute 'base' and the <simpleType> child are "
11559 		    "mutually exclusive", NULL);
11560 	    } else {
11561 		type->baseType = (xmlSchemaTypePtr)
11562 		    xmlSchemaParseSimpleType(ctxt, schema, child, 0);
11563 	    }
11564 	    child = child->next;
11565 	} else if (type->base == NULL) {
11566 	    xmlSchemaPContentErr(ctxt,
11567 		XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
11568 		NULL, node, child,
11569 		"Either the attribute 'base' or a <simpleType> child "
11570 		"must be present", NULL);
11571 	}
11572     } else if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11573 	/*
11574 	* Corresponds to <complexType><complexContent><restriction>...
11575 	* followed by:
11576 	*
11577 	* Model groups <all>, <choice> and <sequence>.
11578 	*/
11579 	if (IS_SCHEMA(child, "all")) {
11580 	    type->subtypes = (xmlSchemaTypePtr)
11581 		xmlSchemaParseModelGroup(ctxt, schema, child,
11582 		    XML_SCHEMA_TYPE_ALL, 1);
11583 	    child = child->next;
11584 	} else if (IS_SCHEMA(child, "choice")) {
11585 	    type->subtypes = (xmlSchemaTypePtr)
11586 		xmlSchemaParseModelGroup(ctxt,
11587 		    schema, child, XML_SCHEMA_TYPE_CHOICE, 1);
11588 	    child = child->next;
11589 	} else if (IS_SCHEMA(child, "sequence")) {
11590 	    type->subtypes = (xmlSchemaTypePtr)
11591 		xmlSchemaParseModelGroup(ctxt, schema, child,
11592 		    XML_SCHEMA_TYPE_SEQUENCE, 1);
11593 	    child = child->next;
11594 	/*
11595 	* Model group reference <group>.
11596 	*/
11597 	} else if (IS_SCHEMA(child, "group")) {
11598 	    type->subtypes = (xmlSchemaTypePtr)
11599 		xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11600 	    /*
11601 	    * Note that the reference will be resolved in
11602 	    * xmlSchemaResolveTypeReferences();
11603 	    */
11604 	    child = child->next;
11605 	}
11606     } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
11607 	/*
11608 	* Corresponds to <complexType><simpleContent><restriction>...
11609 	*
11610 	* "1.1 the simple type definition corresponding to the <simpleType>
11611 	* among the [children] of <restriction> if there is one;"
11612 	*/
11613 	if (IS_SCHEMA(child, "simpleType")) {
11614 	    /*
11615 	    * We will store the to-be-restricted simple type in
11616 	    * type->contentTypeDef *temporarily*.
11617 	    */
11618 	    type->contentTypeDef = (xmlSchemaTypePtr)
11619 		xmlSchemaParseSimpleType(ctxt, schema, child, 0);
11620 	    if ( type->contentTypeDef == NULL)
11621 		return (NULL);
11622 	    child = child->next;
11623 	}
11624     }
11625 
11626     if ((parentType == XML_SCHEMA_TYPE_SIMPLE) ||
11627 	(parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
11628 	xmlSchemaFacetPtr facet, lastfacet = NULL;
11629 	/*
11630 	* Corresponds to <complexType><simpleContent><restriction>...
11631 	* <simpleType><restriction>...
11632 	*/
11633 
11634 	/*
11635 	* Add the facets to the simple type ancestor.
11636 	*/
11637 	/*
11638 	* TODO: Datatypes: 4.1.3 Constraints on XML Representation of
11639 	* Simple Type Definition Schema Representation Constraint:
11640 	* *Single Facet Value*
11641 	*/
11642 	while ((IS_SCHEMA(child, "minInclusive")) ||
11643 	    (IS_SCHEMA(child, "minExclusive")) ||
11644 	    (IS_SCHEMA(child, "maxInclusive")) ||
11645 	    (IS_SCHEMA(child, "maxExclusive")) ||
11646 	    (IS_SCHEMA(child, "totalDigits")) ||
11647 	    (IS_SCHEMA(child, "fractionDigits")) ||
11648 	    (IS_SCHEMA(child, "pattern")) ||
11649 	    (IS_SCHEMA(child, "enumeration")) ||
11650 	    (IS_SCHEMA(child, "whiteSpace")) ||
11651 	    (IS_SCHEMA(child, "length")) ||
11652 	    (IS_SCHEMA(child, "maxLength")) ||
11653 	    (IS_SCHEMA(child, "minLength"))) {
11654 	    facet = xmlSchemaParseFacet(ctxt, schema, child);
11655 	    if (facet != NULL) {
11656 		if (lastfacet == NULL)
11657 		    type->facets = facet;
11658 		else
11659 		    lastfacet->next = facet;
11660 		lastfacet = facet;
11661 		lastfacet->next = NULL;
11662 	    }
11663 	    child = child->next;
11664 	}
11665 	/*
11666 	* Create links for derivation and validation.
11667 	*/
11668 	if (type->facets != NULL) {
11669 	    xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
11670 
11671 	    facet = type->facets;
11672 	    do {
11673 		facetLink = (xmlSchemaFacetLinkPtr)
11674 		    xmlMalloc(sizeof(xmlSchemaFacetLink));
11675 		if (facetLink == NULL) {
11676 		    xmlSchemaPErrMemory(ctxt);
11677 		    xmlFree(facetLink);
11678 		    return (NULL);
11679 		}
11680 		facetLink->facet = facet;
11681 		facetLink->next = NULL;
11682 		if (lastFacetLink == NULL)
11683 		    type->facetSet = facetLink;
11684 		else
11685 		    lastFacetLink->next = facetLink;
11686 		lastFacetLink = facetLink;
11687 		facet = facet->next;
11688 	    } while (facet != NULL);
11689 	}
11690     }
11691     if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
11692 	/*
11693 	* Attribute uses/declarations.
11694 	*/
11695 	if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11696 	    (xmlSchemaItemListPtr *) &(type->attrUses),
11697 	    XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
11698 	    return(NULL);
11699 	/*
11700 	* Attribute wildcard.
11701 	*/
11702 	if (IS_SCHEMA(child, "anyAttribute")) {
11703 	    type->attributeWildcard =
11704 		xmlSchemaParseAnyAttribute(ctxt, schema, child);
11705 	    child = child->next;
11706 	}
11707     }
11708     if (child != NULL) {
11709 	if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11710 	    xmlSchemaPContentErr(ctxt,
11711 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11712 		NULL, node, child, NULL,
11713 		"annotation?, (group | all | choice | sequence)?, "
11714 		"((attribute | attributeGroup)*, anyAttribute?))");
11715 	} else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
11716 	     xmlSchemaPContentErr(ctxt,
11717 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11718 		NULL, node, child, NULL,
11719 		"(annotation?, (simpleType?, (minExclusive | minInclusive | "
11720 		"maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11721 		"length | minLength | maxLength | enumeration | whiteSpace | "
11722 		"pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
11723 	} else {
11724 	    /* Simple type */
11725 	    xmlSchemaPContentErr(ctxt,
11726 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11727 		NULL, node, child, NULL,
11728 		"(annotation?, (simpleType?, (minExclusive | minInclusive | "
11729 		"maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11730 		"length | minLength | maxLength | enumeration | whiteSpace | "
11731 		"pattern)*))");
11732 	}
11733     }
11734     return (NULL);
11735 }
11736 
11737 /**
11738  * xmlSchemaParseExtension:
11739  * @ctxt:  a schema validation context
11740  * @schema:  the schema being built
11741  * @node:  a subtree containing XML Schema information
11742  *
11743  * Parses an <extension>, which is found inside a
11744  * <simpleContent> or <complexContent>.
11745  * *WARNING* this interface is highly subject to change.
11746  *
11747  * TODO: Returns the type definition or NULL in case of error
11748  */
11749 static xmlSchemaTypePtr
xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,xmlSchemaTypeType parentType)11750 xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11751                         xmlNodePtr node, xmlSchemaTypeType parentType)
11752 {
11753     xmlSchemaTypePtr type;
11754     xmlNodePtr child = NULL;
11755     xmlAttrPtr attr;
11756 
11757     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11758         return (NULL);
11759     /* Not a component, don't create it. */
11760     type = ctxt->ctxtType;
11761     type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
11762 
11763     /*
11764     * Check for illegal attributes.
11765     */
11766     attr = node->properties;
11767     while (attr != NULL) {
11768 	if (attr->ns == NULL) {
11769 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11770 		(!xmlStrEqual(attr->name, BAD_CAST "base"))) {
11771 		xmlSchemaPIllegalAttrErr(ctxt,
11772 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11773 	    }
11774 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11775 	    xmlSchemaPIllegalAttrErr(ctxt,
11776 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11777 	}
11778 	attr = attr->next;
11779     }
11780 
11781     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11782 
11783     /*
11784     * Attribute "base" - mandatory.
11785     */
11786     if ((xmlSchemaPValAttrQName(ctxt, schema, NULL, node,
11787 	"base", &(type->baseNs), &(type->base)) == 0) &&
11788 	(type->base == NULL)) {
11789 	xmlSchemaPMissingAttrErr(ctxt,
11790 	    XML_SCHEMAP_S4S_ATTR_MISSING,
11791 	    NULL, node, "base", NULL);
11792     }
11793     /*
11794     * And now for the children...
11795     */
11796     child = node->children;
11797     if (IS_SCHEMA(child, "annotation")) {
11798 	/*
11799 	* Add the annotation to the type ancestor.
11800 	*/
11801 	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11802 	    xmlSchemaParseAnnotation(ctxt, child, 1));
11803         child = child->next;
11804     }
11805     if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11806 	/*
11807 	* Corresponds to <complexType><complexContent><extension>... and:
11808 	*
11809 	* Model groups <all>, <choice>, <sequence> and <group>.
11810 	*/
11811 	if (IS_SCHEMA(child, "all")) {
11812 	    type->subtypes = (xmlSchemaTypePtr)
11813 		xmlSchemaParseModelGroup(ctxt, schema,
11814 		    child, XML_SCHEMA_TYPE_ALL, 1);
11815 	    child = child->next;
11816 	} else if (IS_SCHEMA(child, "choice")) {
11817 	    type->subtypes = (xmlSchemaTypePtr)
11818 		xmlSchemaParseModelGroup(ctxt, schema,
11819 		    child, XML_SCHEMA_TYPE_CHOICE, 1);
11820 	    child = child->next;
11821 	} else if (IS_SCHEMA(child, "sequence")) {
11822 	    type->subtypes = (xmlSchemaTypePtr)
11823 		xmlSchemaParseModelGroup(ctxt, schema,
11824 		child, XML_SCHEMA_TYPE_SEQUENCE, 1);
11825 	    child = child->next;
11826 	} else if (IS_SCHEMA(child, "group")) {
11827 	    type->subtypes = (xmlSchemaTypePtr)
11828 		xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11829 	    /*
11830 	    * Note that the reference will be resolved in
11831 	    * xmlSchemaResolveTypeReferences();
11832 	    */
11833 	    child = child->next;
11834 	}
11835     }
11836     if (child != NULL) {
11837 	/*
11838 	* Attribute uses/declarations.
11839 	*/
11840 	if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11841 	    (xmlSchemaItemListPtr *) &(type->attrUses),
11842 	    XML_SCHEMA_TYPE_EXTENSION, NULL) == -1)
11843 	    return(NULL);
11844 	/*
11845 	* Attribute wildcard.
11846 	*/
11847 	if (IS_SCHEMA(child, "anyAttribute")) {
11848 	    ctxt->ctxtType->attributeWildcard =
11849 		xmlSchemaParseAnyAttribute(ctxt, schema, child);
11850 	    child = child->next;
11851 	}
11852     }
11853     if (child != NULL) {
11854 	if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11855 	    /* Complex content extension. */
11856 	    xmlSchemaPContentErr(ctxt,
11857 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11858 		NULL, node, child, NULL,
11859 		"(annotation?, ((group | all | choice | sequence)?, "
11860 		"((attribute | attributeGroup)*, anyAttribute?)))");
11861 	} else {
11862 	    /* Simple content extension. */
11863 	    xmlSchemaPContentErr(ctxt,
11864 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11865 		NULL, node, child, NULL,
11866 		"(annotation?, ((attribute | attributeGroup)*, "
11867 		"anyAttribute?))");
11868 	}
11869     }
11870     return (NULL);
11871 }
11872 
11873 /**
11874  * xmlSchemaParseSimpleContent:
11875  * @ctxt:  a schema validation context
11876  * @schema:  the schema being built
11877  * @node:  a subtree containing XML Schema information
11878  *
11879  * parse a XML schema SimpleContent definition
11880  * *WARNING* this interface is highly subject to change
11881  *
11882  * Returns the type definition or NULL in case of error
11883  */
11884 static int
xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,int * hasRestrictionOrExtension)11885 xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
11886                             xmlSchemaPtr schema, xmlNodePtr node,
11887 			    int *hasRestrictionOrExtension)
11888 {
11889     xmlSchemaTypePtr type;
11890     xmlNodePtr child = NULL;
11891     xmlAttrPtr attr;
11892 
11893     if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
11894 	(hasRestrictionOrExtension == NULL))
11895         return (-1);
11896     *hasRestrictionOrExtension = 0;
11897     /* Not a component, don't create it. */
11898     type = ctxt->ctxtType;
11899     type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
11900     /*
11901     * Check for illegal attributes.
11902     */
11903     attr = node->properties;
11904     while (attr != NULL) {
11905 	if (attr->ns == NULL) {
11906 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id"))) {
11907 		xmlSchemaPIllegalAttrErr(ctxt,
11908 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11909 	    }
11910 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11911 	    xmlSchemaPIllegalAttrErr(ctxt,
11912 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11913 	}
11914 	attr = attr->next;
11915     }
11916 
11917     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11918 
11919     /*
11920     * And now for the children...
11921     */
11922     child = node->children;
11923     if (IS_SCHEMA(child, "annotation")) {
11924 	/*
11925 	* Add the annotation to the complex type ancestor.
11926 	*/
11927 	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11928 	    xmlSchemaParseAnnotation(ctxt, child, 1));
11929         child = child->next;
11930     }
11931     if (child == NULL) {
11932 	xmlSchemaPContentErr(ctxt,
11933 	    XML_SCHEMAP_S4S_ELEM_MISSING,
11934 	    NULL, node, NULL, NULL,
11935 	    "(annotation?, (restriction | extension))");
11936     }
11937     if (child == NULL) {
11938 	xmlSchemaPContentErr(ctxt,
11939 	    XML_SCHEMAP_S4S_ELEM_MISSING,
11940 	    NULL, node, NULL, NULL,
11941 	    "(annotation?, (restriction | extension))");
11942     }
11943     if (IS_SCHEMA(child, "restriction")) {
11944         xmlSchemaParseRestriction(ctxt, schema, child,
11945 	    XML_SCHEMA_TYPE_SIMPLE_CONTENT);
11946 	(*hasRestrictionOrExtension) = 1;
11947         child = child->next;
11948     } else if (IS_SCHEMA(child, "extension")) {
11949         xmlSchemaParseExtension(ctxt, schema, child,
11950 	    XML_SCHEMA_TYPE_SIMPLE_CONTENT);
11951 	(*hasRestrictionOrExtension) = 1;
11952         child = child->next;
11953     }
11954     if (child != NULL) {
11955 	xmlSchemaPContentErr(ctxt,
11956 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11957 	    NULL, node, child, NULL,
11958 	    "(annotation?, (restriction | extension))");
11959     }
11960     return (0);
11961 }
11962 
11963 /**
11964  * xmlSchemaParseComplexContent:
11965  * @ctxt:  a schema validation context
11966  * @schema:  the schema being built
11967  * @node:  a subtree containing XML Schema information
11968  *
11969  * parse a XML schema ComplexContent definition
11970  * *WARNING* this interface is highly subject to change
11971  *
11972  * Returns the type definition or NULL in case of error
11973  */
11974 static int
xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,int * hasRestrictionOrExtension)11975 xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
11976                              xmlSchemaPtr schema, xmlNodePtr node,
11977 			     int *hasRestrictionOrExtension)
11978 {
11979     xmlSchemaTypePtr type;
11980     xmlNodePtr child = NULL;
11981     xmlAttrPtr attr;
11982 
11983     if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
11984 	(hasRestrictionOrExtension == NULL))
11985         return (-1);
11986     *hasRestrictionOrExtension = 0;
11987     /* Not a component, don't create it. */
11988     type = ctxt->ctxtType;
11989     /*
11990     * Check for illegal attributes.
11991     */
11992     attr = node->properties;
11993     while (attr != NULL) {
11994 	if (attr->ns == NULL) {
11995 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11996 		(!xmlStrEqual(attr->name, BAD_CAST "mixed")))
11997 	    {
11998 		xmlSchemaPIllegalAttrErr(ctxt,
11999 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12000 	    }
12001 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
12002 	    xmlSchemaPIllegalAttrErr(ctxt,
12003 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12004 	}
12005 	attr = attr->next;
12006     }
12007 
12008     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
12009 
12010     /*
12011     * Set the 'mixed' on the complex type ancestor.
12012     */
12013     if (xmlGetBooleanProp(ctxt, node, "mixed", 0))  {
12014 	if ((type->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
12015 	    type->flags |= XML_SCHEMAS_TYPE_MIXED;
12016     }
12017     child = node->children;
12018     if (IS_SCHEMA(child, "annotation")) {
12019 	/*
12020 	* Add the annotation to the complex type ancestor.
12021 	*/
12022 	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
12023 	    xmlSchemaParseAnnotation(ctxt, child, 1));
12024         child = child->next;
12025     }
12026     if (child == NULL) {
12027 	xmlSchemaPContentErr(ctxt,
12028 	    XML_SCHEMAP_S4S_ELEM_MISSING,
12029 	    NULL, node, NULL,
12030 	    NULL, "(annotation?, (restriction | extension))");
12031     }
12032     if (child == NULL) {
12033 	xmlSchemaPContentErr(ctxt,
12034 	    XML_SCHEMAP_S4S_ELEM_MISSING,
12035 	    NULL, node, NULL,
12036 	    NULL, "(annotation?, (restriction | extension))");
12037     }
12038     if (IS_SCHEMA(child, "restriction")) {
12039         xmlSchemaParseRestriction(ctxt, schema, child,
12040 	    XML_SCHEMA_TYPE_COMPLEX_CONTENT);
12041 	(*hasRestrictionOrExtension) = 1;
12042         child = child->next;
12043     } else if (IS_SCHEMA(child, "extension")) {
12044         xmlSchemaParseExtension(ctxt, schema, child,
12045 	    XML_SCHEMA_TYPE_COMPLEX_CONTENT);
12046 	(*hasRestrictionOrExtension) = 1;
12047         child = child->next;
12048     }
12049     if (child != NULL) {
12050 	xmlSchemaPContentErr(ctxt,
12051 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
12052 	    NULL, node, child,
12053 	    NULL, "(annotation?, (restriction | extension))");
12054     }
12055     return (0);
12056 }
12057 
12058 /**
12059  * xmlSchemaParseComplexType:
12060  * @ctxt:  a schema validation context
12061  * @schema:  the schema being built
12062  * @node:  a subtree containing XML Schema information
12063  *
12064  * parse a XML schema Complex Type definition
12065  * *WARNING* this interface is highly subject to change
12066  *
12067  * Returns the type definition or NULL in case of error
12068  */
12069 static xmlSchemaTypePtr
xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,int topLevel)12070 xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
12071                           xmlNodePtr node, int topLevel)
12072 {
12073     xmlSchemaTypePtr type, ctxtType;
12074     xmlNodePtr child = NULL;
12075     const xmlChar *name = NULL;
12076     xmlAttrPtr attr;
12077     const xmlChar *attrValue;
12078 #ifdef ENABLE_NAMED_LOCALS
12079     char buf[40];
12080 #endif
12081     int final = 0, block = 0, hasRestrictionOrExtension = 0;
12082 
12083 
12084     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
12085         return (NULL);
12086 
12087     ctxtType = ctxt->ctxtType;
12088 
12089     if (topLevel) {
12090 	attr = xmlSchemaGetPropNode(node, "name");
12091 	if (attr == NULL) {
12092 	    xmlSchemaPMissingAttrErr(ctxt,
12093 		XML_SCHEMAP_S4S_ATTR_MISSING, NULL, node, "name", NULL);
12094 	    return (NULL);
12095 	} else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
12096 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
12097 	    return (NULL);
12098 	}
12099     }
12100 
12101     if (topLevel == 0) {
12102 	/*
12103 	* Parse as local complex type definition.
12104 	*/
12105 #ifdef ENABLE_NAMED_LOCALS
12106         snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
12107 	type = xmlSchemaAddType(ctxt, schema,
12108 	    XML_SCHEMA_TYPE_COMPLEX,
12109 	    xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
12110 	    ctxt->targetNamespace, node, 0);
12111 #else
12112 	type = xmlSchemaAddType(ctxt, schema,
12113 	    XML_SCHEMA_TYPE_COMPLEX,
12114 	    NULL, ctxt->targetNamespace, node, 0);
12115 #endif
12116 	if (type == NULL)
12117 	    return (NULL);
12118 	name = type->name;
12119 	type->node = node;
12120 	type->type = XML_SCHEMA_TYPE_COMPLEX;
12121 	/*
12122 	* TODO: We need the target namespace.
12123 	*/
12124     } else {
12125 	/*
12126 	* Parse as global complex type definition.
12127 	*/
12128 	type = xmlSchemaAddType(ctxt, schema,
12129 	    XML_SCHEMA_TYPE_COMPLEX,
12130 	    name, ctxt->targetNamespace, node, 1);
12131 	if (type == NULL)
12132 	    return (NULL);
12133 	type->node = node;
12134 	type->type = XML_SCHEMA_TYPE_COMPLEX;
12135 	type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
12136     }
12137     type->targetNamespace = ctxt->targetNamespace;
12138     /*
12139     * Handle attributes.
12140     */
12141     attr = node->properties;
12142     while (attr != NULL) {
12143 	if (attr->ns == NULL) {
12144 	    if (xmlStrEqual(attr->name, BAD_CAST "id")) {
12145 		/*
12146 		* Attribute "id".
12147 		*/
12148 		xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
12149 	    } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
12150 		/*
12151 		* Attribute "mixed".
12152 		*/
12153 		if (xmlSchemaPGetBoolNodeValue(ctxt,
12154 			NULL, (xmlNodePtr) attr))
12155 		    type->flags |= XML_SCHEMAS_TYPE_MIXED;
12156 	    } else if (topLevel) {
12157 		/*
12158 		* Attributes of global complex type definitions.
12159 		*/
12160 		if (xmlStrEqual(attr->name, BAD_CAST "name")) {
12161 		    /* Pass. */
12162 		} else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
12163 		    /*
12164 		    * Attribute "abstract".
12165 		    */
12166 		    if (xmlSchemaPGetBoolNodeValue(ctxt,
12167 			    NULL, (xmlNodePtr) attr))
12168 			type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
12169 		} else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
12170 		    /*
12171 		    * Attribute "final".
12172 		    */
12173 		    attrValue = xmlSchemaGetNodeContent(ctxt,
12174 			(xmlNodePtr) attr);
12175 		    if (xmlSchemaPValAttrBlockFinal(attrValue,
12176 			&(type->flags),
12177 			-1,
12178 			XML_SCHEMAS_TYPE_FINAL_EXTENSION,
12179 			XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
12180 			-1, -1, -1) != 0)
12181 		    {
12182 			xmlSchemaPSimpleTypeErr(ctxt,
12183 			    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
12184 			    NULL, (xmlNodePtr) attr, NULL,
12185 			    "(#all | List of (extension | restriction))",
12186 			    attrValue, NULL, NULL, NULL);
12187 		    } else
12188 			final = 1;
12189 		} else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
12190 		    /*
12191 		    * Attribute "block".
12192 		    */
12193 		    attrValue = xmlSchemaGetNodeContent(ctxt,
12194 			(xmlNodePtr) attr);
12195 		    if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
12196 			-1,
12197 			XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
12198 			XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
12199 			-1, -1, -1) != 0) {
12200 			xmlSchemaPSimpleTypeErr(ctxt,
12201 			    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
12202 			    NULL, (xmlNodePtr) attr, NULL,
12203 			    "(#all | List of (extension | restriction)) ",
12204 			    attrValue, NULL, NULL, NULL);
12205 		    } else
12206 			block = 1;
12207 		} else {
12208 			xmlSchemaPIllegalAttrErr(ctxt,
12209 			    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12210 		}
12211 	    } else {
12212 		xmlSchemaPIllegalAttrErr(ctxt,
12213 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12214 	    }
12215 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
12216 	    xmlSchemaPIllegalAttrErr(ctxt,
12217 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12218 	}
12219 	attr = attr->next;
12220     }
12221     if (! block) {
12222 	/*
12223 	* Apply default "block" values.
12224 	*/
12225 	if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
12226 	    type->flags |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
12227 	if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
12228 	    type->flags |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
12229     }
12230     if (! final) {
12231 	/*
12232 	* Apply default "block" values.
12233 	*/
12234 	if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
12235 	    type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
12236 	if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
12237 	    type->flags |= XML_SCHEMAS_TYPE_FINAL_EXTENSION;
12238     }
12239     /*
12240     * And now for the children...
12241     */
12242     child = node->children;
12243     if (IS_SCHEMA(child, "annotation")) {
12244         type->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
12245         child = child->next;
12246     }
12247     ctxt->ctxtType = type;
12248     if (IS_SCHEMA(child, "simpleContent")) {
12249 	/*
12250 	* <complexType><simpleContent>...
12251 	* 3.4.3 : 2.2
12252 	* Specifying mixed='true' when the <simpleContent>
12253 	* alternative is chosen has no effect
12254 	*/
12255 	if (type->flags & XML_SCHEMAS_TYPE_MIXED)
12256 	    type->flags ^= XML_SCHEMAS_TYPE_MIXED;
12257         xmlSchemaParseSimpleContent(ctxt, schema, child,
12258 	    &hasRestrictionOrExtension);
12259         child = child->next;
12260     } else if (IS_SCHEMA(child, "complexContent")) {
12261 	/*
12262 	* <complexType><complexContent>...
12263 	*/
12264 	type->contentType = XML_SCHEMA_CONTENT_EMPTY;
12265         xmlSchemaParseComplexContent(ctxt, schema, child,
12266 	    &hasRestrictionOrExtension);
12267         child = child->next;
12268     } else {
12269 	/*
12270 	* E.g <complexType><sequence>... or <complexType><attribute>... etc.
12271 	*
12272 	* SPEC
12273 	* "...the third alternative (neither <simpleContent> nor
12274 	* <complexContent>) is chosen. This case is understood as shorthand
12275 	* for complex content restricting the `ur-type definition`, and the
12276 	* details of the mappings should be modified as necessary.
12277 	*/
12278 	type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
12279 	type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
12280 	/*
12281 	* Parse model groups.
12282 	*/
12283         if (IS_SCHEMA(child, "all")) {
12284             type->subtypes = (xmlSchemaTypePtr)
12285 		xmlSchemaParseModelGroup(ctxt, schema, child,
12286 		    XML_SCHEMA_TYPE_ALL, 1);
12287             child = child->next;
12288         } else if (IS_SCHEMA(child, "choice")) {
12289             type->subtypes = (xmlSchemaTypePtr)
12290 		xmlSchemaParseModelGroup(ctxt, schema, child,
12291 		    XML_SCHEMA_TYPE_CHOICE, 1);
12292             child = child->next;
12293         } else if (IS_SCHEMA(child, "sequence")) {
12294             type->subtypes = (xmlSchemaTypePtr)
12295 		xmlSchemaParseModelGroup(ctxt, schema, child,
12296 		    XML_SCHEMA_TYPE_SEQUENCE, 1);
12297             child = child->next;
12298         } else if (IS_SCHEMA(child, "group")) {
12299             type->subtypes = (xmlSchemaTypePtr)
12300 		xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
12301 	    /*
12302 	    * Note that the reference will be resolved in
12303 	    * xmlSchemaResolveTypeReferences();
12304 	    */
12305             child = child->next;
12306         }
12307 	/*
12308 	* Parse attribute decls/refs.
12309 	*/
12310         if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
12311 	    (xmlSchemaItemListPtr *) &(type->attrUses),
12312 	    XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
12313 	    return(NULL);
12314 	/*
12315 	* Parse attribute wildcard.
12316 	*/
12317 	if (IS_SCHEMA(child, "anyAttribute")) {
12318 	    type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
12319 	    child = child->next;
12320 	}
12321     }
12322     if (child != NULL) {
12323 	xmlSchemaPContentErr(ctxt,
12324 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
12325 	    NULL, node, child,
12326 	    NULL, "(annotation?, (simpleContent | complexContent | "
12327 	    "((group | all | choice | sequence)?, ((attribute | "
12328 	    "attributeGroup)*, anyAttribute?))))");
12329     }
12330     /*
12331     * REDEFINE: SPEC src-redefine (5)
12332     */
12333     if (topLevel && ctxt->isRedefine && (! hasRestrictionOrExtension)) {
12334 	xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
12335 	    NULL, node, "This is a redefinition, thus the "
12336 	    "<complexType> must have a <restriction> or <extension> "
12337 	    "grand-child", NULL);
12338     }
12339     ctxt->ctxtType = ctxtType;
12340     return (type);
12341 }
12342 
12343 /************************************************************************
12344  *									*
12345  *			Validating using Schemas			*
12346  *									*
12347  ************************************************************************/
12348 
12349 /************************************************************************
12350  *									*
12351  *			Reading/Writing Schemas				*
12352  *									*
12353  ************************************************************************/
12354 
12355 #if 0 /* Will be enabled if it is clear what options are needed. */
12356 /**
12357  * xmlSchemaParserCtxtSetOptions:
12358  * @ctxt:	a schema parser context
12359  * @options: a combination of xmlSchemaParserOption
12360  *
12361  * Sets the options to be used during the parse.
12362  *
12363  * Returns 0 in case of success, -1 in case of an
12364  * API error.
12365  */
12366 static int
12367 xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
12368 			      int options)
12369 
12370 {
12371     int i;
12372 
12373     if (ctxt == NULL)
12374 	return (-1);
12375     /*
12376     * WARNING: Change the start value if adding to the
12377     * xmlSchemaParseOption.
12378     */
12379     for (i = 1; i < (int) sizeof(int) * 8; i++) {
12380         if (options & 1<<i) {
12381 	    return (-1);
12382         }
12383     }
12384     ctxt->options = options;
12385     return (0);
12386 }
12387 
12388 /**
12389  * xmlSchemaValidCtxtGetOptions:
12390  * @ctxt: a schema parser context
12391  *
12392  * Returns the option combination of the parser context.
12393  */
12394 static int
12395 xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
12396 
12397 {
12398     if (ctxt == NULL)
12399 	return (-1);
12400     else
12401 	return (ctxt->options);
12402 }
12403 #endif
12404 
12405 /**
12406  * xmlSchemaNewParserCtxt:
12407  * @URL:  the location of the schema
12408  *
12409  * Create an XML Schemas parse context for that file/resource expected
12410  * to contain an XML Schemas file.
12411  *
12412  * Returns the parser context or NULL in case of error
12413  */
12414 xmlSchemaParserCtxtPtr
xmlSchemaNewParserCtxt(const char * URL)12415 xmlSchemaNewParserCtxt(const char *URL)
12416 {
12417     xmlSchemaParserCtxtPtr ret;
12418 
12419     if (URL == NULL)
12420         return (NULL);
12421 
12422     ret = xmlSchemaParserCtxtCreate();
12423     if (ret == NULL)
12424 	return(NULL);
12425     ret->dict = xmlDictCreate();
12426     ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
12427     return (ret);
12428 }
12429 
12430 /**
12431  * xmlSchemaNewMemParserCtxt:
12432  * @buffer:  a pointer to a char array containing the schemas
12433  * @size:  the size of the array
12434  *
12435  * Create an XML Schemas parse context for that memory buffer expected
12436  * to contain an XML Schemas file.
12437  *
12438  * Returns the parser context or NULL in case of error
12439  */
12440 xmlSchemaParserCtxtPtr
xmlSchemaNewMemParserCtxt(const char * buffer,int size)12441 xmlSchemaNewMemParserCtxt(const char *buffer, int size)
12442 {
12443     xmlSchemaParserCtxtPtr ret;
12444 
12445     if ((buffer == NULL) || (size <= 0))
12446         return (NULL);
12447     ret = xmlSchemaParserCtxtCreate();
12448     if (ret == NULL)
12449 	return(NULL);
12450     ret->buffer = buffer;
12451     ret->size = size;
12452     ret->dict = xmlDictCreate();
12453     return (ret);
12454 }
12455 
12456 /**
12457  * xmlSchemaNewDocParserCtxt:
12458  * @doc:  a preparsed document tree
12459  *
12460  * Create an XML Schemas parse context for that document.
12461  * NB. The document may be modified during the parsing process.
12462  *
12463  * Returns the parser context or NULL in case of error
12464  */
12465 xmlSchemaParserCtxtPtr
xmlSchemaNewDocParserCtxt(xmlDocPtr doc)12466 xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
12467 {
12468     xmlSchemaParserCtxtPtr ret;
12469 
12470     if (doc == NULL)
12471       return (NULL);
12472     ret = xmlSchemaParserCtxtCreate();
12473     if (ret == NULL)
12474 	return(NULL);
12475     ret->doc = doc;
12476     ret->dict = xmlDictCreate();
12477     /* The application has responsibility for the document */
12478     ret->preserve = 1;
12479 
12480     return (ret);
12481 }
12482 
12483 /**
12484  * xmlSchemaFreeParserCtxt:
12485  * @ctxt:  the schema parser context
12486  *
12487  * Free the resources associated to the schema parser context
12488  */
12489 void
xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)12490 xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
12491 {
12492     if (ctxt == NULL)
12493         return;
12494     if (ctxt->doc != NULL && !ctxt->preserve)
12495         xmlFreeDoc(ctxt->doc);
12496     if (ctxt->vctxt != NULL) {
12497 	xmlSchemaFreeValidCtxt(ctxt->vctxt);
12498     }
12499     if (ctxt->ownsConstructor && (ctxt->constructor != NULL)) {
12500 	xmlSchemaConstructionCtxtFree(ctxt->constructor);
12501 	ctxt->constructor = NULL;
12502 	ctxt->ownsConstructor = 0;
12503     }
12504     if (ctxt->attrProhibs != NULL)
12505 	xmlSchemaItemListFree(ctxt->attrProhibs);
12506     xmlDictFree(ctxt->dict);
12507     xmlFree(ctxt);
12508 }
12509 
12510 /************************************************************************
12511  *									*
12512  *			Building the content models			*
12513  *									*
12514  ************************************************************************/
12515 
12516 /**
12517  * xmlSchemaBuildContentModelForSubstGroup:
12518  *
12519  * Returns 1 if nillable, 0 otherwise
12520  */
12521 static int
xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,xmlSchemaParticlePtr particle,int counter,xmlAutomataStatePtr end)12522 xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,
12523 	xmlSchemaParticlePtr particle, int counter, xmlAutomataStatePtr end)
12524 {
12525     xmlAutomataStatePtr start, tmp;
12526     xmlSchemaElementPtr elemDecl, member;
12527     xmlSchemaSubstGroupPtr substGroup;
12528     int i;
12529     int ret = 0;
12530 
12531     elemDecl = (xmlSchemaElementPtr) particle->children;
12532     /*
12533     * Wrap the substitution group with a CHOICE.
12534     */
12535     start = pctxt->state;
12536     if (end == NULL)
12537 	end = xmlAutomataNewState(pctxt->am);
12538     substGroup = xmlSchemaSubstGroupGet(pctxt, elemDecl);
12539     if (substGroup == NULL) {
12540 	xmlSchemaPErr(pctxt, WXS_ITEM_NODE(particle),
12541 	    XML_SCHEMAP_INTERNAL,
12542 	    "Internal error: xmlSchemaBuildContentModelForSubstGroup, "
12543 	    "declaration is marked having a subst. group but none "
12544 	    "available.\n", elemDecl->name, NULL);
12545 	return(0);
12546     }
12547     if (counter >= 0) {
12548 	/*
12549 	* NOTE that we put the declaration in, even if it's abstract.
12550 	* However, an error will be raised during *validation* if an element
12551 	* information item shall be validated against an abstract element
12552 	* declaration.
12553 	*/
12554 	tmp = xmlAutomataNewCountedTrans(pctxt->am, start, NULL, counter);
12555         xmlAutomataNewTransition2(pctxt->am, tmp, end,
12556 	            elemDecl->name, elemDecl->targetNamespace, elemDecl);
12557 	/*
12558 	* Add subst. group members.
12559 	*/
12560 	for (i = 0; i < substGroup->members->nbItems; i++) {
12561 	    member = (xmlSchemaElementPtr) substGroup->members->items[i];
12562             xmlAutomataNewTransition2(pctxt->am, tmp, end,
12563 		               member->name, member->targetNamespace, member);
12564 	}
12565     } else if (particle->maxOccurs == 1) {
12566 	/*
12567 	* NOTE that we put the declaration in, even if it's abstract,
12568 	*/
12569 	xmlAutomataNewEpsilon(pctxt->am,
12570 	    xmlAutomataNewTransition2(pctxt->am,
12571 	    start, NULL,
12572 	    elemDecl->name, elemDecl->targetNamespace, elemDecl), end);
12573 	/*
12574 	* Add subst. group members.
12575 	*/
12576 	for (i = 0; i < substGroup->members->nbItems; i++) {
12577 	    member = (xmlSchemaElementPtr) substGroup->members->items[i];
12578 	    /*
12579 	    * NOTE: This fixes bug #341150. xmlAutomataNewOnceTrans2()
12580 	    *  was incorrectly used instead of xmlAutomataNewTransition2()
12581 	    *  (seems like a copy&paste bug from the XML_SCHEMA_TYPE_ALL
12582 	    *  section in xmlSchemaBuildAContentModel() ).
12583 	    * TODO: Check if xmlAutomataNewOnceTrans2() was instead
12584 	    *  intended for the above "counter" section originally. I.e.,
12585 	    *  check xs:all with subst-groups.
12586 	    *
12587 	    * tmp = xmlAutomataNewOnceTrans2(pctxt->am, start, NULL,
12588 	    *	               member->name, member->targetNamespace,
12589 	    *		       1, 1, member);
12590 	    */
12591 	    tmp = xmlAutomataNewTransition2(pctxt->am, start, NULL,
12592 		member->name, member->targetNamespace, member);
12593 	    xmlAutomataNewEpsilon(pctxt->am, tmp, end);
12594 	}
12595     } else {
12596 	xmlAutomataStatePtr hop;
12597 	int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12598 	    UNBOUNDED : particle->maxOccurs - 1;
12599 	int minOccurs = particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12600 
12601 	counter =
12602 	    xmlAutomataNewCounter(pctxt->am, minOccurs,
12603 	    maxOccurs);
12604 	hop = xmlAutomataNewState(pctxt->am);
12605 
12606 	xmlAutomataNewEpsilon(pctxt->am,
12607 	    xmlAutomataNewTransition2(pctxt->am,
12608 	    start, NULL,
12609 	    elemDecl->name, elemDecl->targetNamespace, elemDecl),
12610 	    hop);
12611 	/*
12612 	 * Add subst. group members.
12613 	 */
12614 	for (i = 0; i < substGroup->members->nbItems; i++) {
12615 	    member = (xmlSchemaElementPtr) substGroup->members->items[i];
12616 	    xmlAutomataNewEpsilon(pctxt->am,
12617 		xmlAutomataNewTransition2(pctxt->am,
12618 		start, NULL,
12619 		member->name, member->targetNamespace, member),
12620 		hop);
12621 	}
12622 	xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12623 	xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12624     }
12625     if (particle->minOccurs == 0) {
12626 	xmlAutomataNewEpsilon(pctxt->am, start, end);
12627         ret = 1;
12628     }
12629     pctxt->state = end;
12630     return(ret);
12631 }
12632 
12633 /**
12634  * xmlSchemaBuildContentModelForElement:
12635  *
12636  * Returns 1 if nillable, 0 otherwise
12637  */
12638 static int
xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr particle)12639 xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,
12640 				     xmlSchemaParticlePtr particle)
12641 {
12642     int ret = 0;
12643 
12644     if (((xmlSchemaElementPtr) particle->children)->flags &
12645 	XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
12646 	/*
12647 	* Substitution groups.
12648 	*/
12649 	ret = xmlSchemaBuildContentModelForSubstGroup(ctxt, particle, -1, NULL);
12650     } else {
12651 	xmlSchemaElementPtr elemDecl;
12652 	xmlAutomataStatePtr start;
12653 
12654 	elemDecl = (xmlSchemaElementPtr) particle->children;
12655 
12656 	if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT)
12657 	    return(0);
12658 	if (particle->maxOccurs == 1) {
12659 	    start = ctxt->state;
12660 	    ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12661 		    elemDecl->name, elemDecl->targetNamespace, elemDecl);
12662 	} else if ((particle->maxOccurs >= UNBOUNDED) &&
12663 	           (particle->minOccurs < 2)) {
12664 	    /* Special case. */
12665 	    start = ctxt->state;
12666 	    ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12667 		elemDecl->name, elemDecl->targetNamespace, elemDecl);
12668 	    ctxt->state = xmlAutomataNewTransition2(ctxt->am, ctxt->state, ctxt->state,
12669 		elemDecl->name, elemDecl->targetNamespace, elemDecl);
12670 	} else {
12671 	    int counter;
12672 	    int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12673 			    UNBOUNDED : particle->maxOccurs - 1;
12674 	    int minOccurs = particle->minOccurs < 1 ?
12675 			    0 : particle->minOccurs - 1;
12676 
12677 	    start = xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
12678 	    counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
12679 	    ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12680 		elemDecl->name, elemDecl->targetNamespace, elemDecl);
12681 	    xmlAutomataNewCountedTrans(ctxt->am, ctxt->state, start, counter);
12682 	    ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, ctxt->state,
12683 		NULL, counter);
12684 	}
12685 	if (particle->minOccurs == 0) {
12686 	    xmlAutomataNewEpsilon(ctxt->am, start, ctxt->state);
12687             ret = 1;
12688         }
12689     }
12690     return(ret);
12691 }
12692 
12693 /**
12694  * xmlSchemaBuildAContentModel:
12695  * @ctxt:  the schema parser context
12696  * @particle:  the particle component
12697  * @name:  the complex type's name whose content is being built
12698  *
12699  * Create the automaton for the {content type} of a complex type.
12700  *
12701  * Returns 1 if the content is nillable, 0 otherwise
12702  */
12703 static int
xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,xmlSchemaParticlePtr particle)12704 xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,
12705 			    xmlSchemaParticlePtr particle)
12706 {
12707     int ret = 0, tmp2;
12708 
12709     if (particle == NULL) {
12710 	PERROR_INT("xmlSchemaBuildAContentModel", "particle is NULL");
12711 	return(1);
12712     }
12713     if (particle->children == NULL) {
12714 	/*
12715 	* Just return in this case. A missing "term" of the particle
12716 	* might arise due to an invalid "term" component.
12717 	*/
12718 	return(1);
12719     }
12720 
12721     switch (particle->children->type) {
12722 	case XML_SCHEMA_TYPE_ANY: {
12723 	    xmlAutomataStatePtr start, end;
12724 	    xmlSchemaWildcardPtr wild;
12725 	    xmlSchemaWildcardNsPtr ns;
12726 
12727 	    wild = (xmlSchemaWildcardPtr) particle->children;
12728 
12729 	    start = pctxt->state;
12730 	    end = xmlAutomataNewState(pctxt->am);
12731 
12732 	    if (particle->maxOccurs == 1) {
12733 		if (wild->any == 1) {
12734 		    /*
12735 		    * We need to add both transitions:
12736 		    *
12737 		    * 1. the {"*", "*"} for elements in a namespace.
12738 		    */
12739 		    pctxt->state =
12740 			xmlAutomataNewTransition2(pctxt->am,
12741 			start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
12742 		    xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12743 		    /*
12744 		    * 2. the {"*"} for elements in no namespace.
12745 		    */
12746 		    pctxt->state =
12747 			xmlAutomataNewTransition2(pctxt->am,
12748 			start, NULL, BAD_CAST "*", NULL, wild);
12749 		    xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12750 
12751 		} else if (wild->nsSet != NULL) {
12752 		    ns = wild->nsSet;
12753 		    do {
12754 			pctxt->state = start;
12755 			pctxt->state = xmlAutomataNewTransition2(pctxt->am,
12756 			    pctxt->state, NULL, BAD_CAST "*", ns->value, wild);
12757 			xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12758 			ns = ns->next;
12759 		    } while (ns != NULL);
12760 
12761 		} else if (wild->negNsSet != NULL) {
12762 		    pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
12763 			start, end, BAD_CAST "*", wild->negNsSet->value,
12764 			wild);
12765 		}
12766 	    } else {
12767 		int counter;
12768 		xmlAutomataStatePtr hop;
12769 		int maxOccurs =
12770 		    particle->maxOccurs == UNBOUNDED ? UNBOUNDED :
12771                                            particle->maxOccurs - 1;
12772 		int minOccurs =
12773 		    particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12774 
12775 		counter = xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
12776 		hop = xmlAutomataNewState(pctxt->am);
12777 		if (wild->any == 1) {
12778 		    pctxt->state =
12779 			xmlAutomataNewTransition2(pctxt->am,
12780 			start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
12781 		    xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12782 		    pctxt->state =
12783 			xmlAutomataNewTransition2(pctxt->am,
12784 			start, NULL, BAD_CAST "*", NULL, wild);
12785 		    xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12786 		} else if (wild->nsSet != NULL) {
12787 		    ns = wild->nsSet;
12788 		    do {
12789 			pctxt->state =
12790 			    xmlAutomataNewTransition2(pctxt->am,
12791 				start, NULL, BAD_CAST "*", ns->value, wild);
12792 			xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12793 			ns = ns->next;
12794 		    } while (ns != NULL);
12795 
12796 		} else if (wild->negNsSet != NULL) {
12797 		    pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
12798 			start, hop, BAD_CAST "*", wild->negNsSet->value,
12799 			wild);
12800 		}
12801 		xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12802 		xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12803 	    }
12804 	    if (particle->minOccurs == 0) {
12805 		xmlAutomataNewEpsilon(pctxt->am, start, end);
12806                 ret = 1;
12807 	    }
12808 	    pctxt->state = end;
12809             break;
12810 	}
12811         case XML_SCHEMA_TYPE_ELEMENT:
12812 	    ret = xmlSchemaBuildContentModelForElement(pctxt, particle);
12813 	    break;
12814         case XML_SCHEMA_TYPE_SEQUENCE:{
12815             xmlSchemaTreeItemPtr sub;
12816 
12817             ret = 1;
12818             /*
12819              * If max and min occurrences are default (1) then
12820              * simply iterate over the particles of the <sequence>.
12821              */
12822             if ((particle->minOccurs == 1) && (particle->maxOccurs == 1)) {
12823                 sub = particle->children->children;
12824 
12825                 while (sub != NULL) {
12826                     tmp2 = xmlSchemaBuildAContentModel(pctxt,
12827                                         (xmlSchemaParticlePtr) sub);
12828                     if (tmp2 != 1) ret = 0;
12829                     sub = sub->next;
12830                 }
12831             } else {
12832                 xmlAutomataStatePtr oldstate = pctxt->state;
12833 
12834                 if (particle->maxOccurs >= UNBOUNDED) {
12835                     if (particle->minOccurs > 1) {
12836                         xmlAutomataStatePtr tmp;
12837                         int counter;
12838 
12839                         pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12840                             oldstate, NULL);
12841                         oldstate = pctxt->state;
12842 
12843                         counter = xmlAutomataNewCounter(pctxt->am,
12844                             particle->minOccurs - 1, UNBOUNDED);
12845 
12846                         sub = particle->children->children;
12847                         while (sub != NULL) {
12848                             tmp2 = xmlSchemaBuildAContentModel(pctxt,
12849                                             (xmlSchemaParticlePtr) sub);
12850                             if (tmp2 != 1) ret = 0;
12851                             sub = sub->next;
12852                         }
12853                         tmp = pctxt->state;
12854                         xmlAutomataNewCountedTrans(pctxt->am, tmp,
12855                                                    oldstate, counter);
12856                         pctxt->state =
12857                             xmlAutomataNewCounterTrans(pctxt->am, tmp,
12858                                                        NULL, counter);
12859                         if (ret == 1)
12860                             xmlAutomataNewEpsilon(pctxt->am,
12861                                                 oldstate, pctxt->state);
12862 
12863                     } else {
12864                         pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12865                             oldstate, NULL);
12866                         oldstate = pctxt->state;
12867 
12868                         sub = particle->children->children;
12869                         while (sub != NULL) {
12870                             tmp2 = xmlSchemaBuildAContentModel(pctxt,
12871                                         (xmlSchemaParticlePtr) sub);
12872                             if (tmp2 != 1) ret = 0;
12873                             sub = sub->next;
12874                         }
12875                         xmlAutomataNewEpsilon(pctxt->am, pctxt->state,
12876                                               oldstate);
12877                         /*
12878                          * epsilon needed to block previous trans from
12879                          * being allowed to enter back from another
12880                          * construct
12881                          */
12882                         pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12883                                             pctxt->state, NULL);
12884                         if (particle->minOccurs == 0) {
12885                             xmlAutomataNewEpsilon(pctxt->am,
12886                                 oldstate, pctxt->state);
12887                             ret = 1;
12888                         }
12889                     }
12890                 } else if ((particle->maxOccurs > 1)
12891                            || (particle->minOccurs > 1)) {
12892                     xmlAutomataStatePtr tmp;
12893                     int counter;
12894 
12895                     pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12896                         oldstate, NULL);
12897                     oldstate = pctxt->state;
12898 
12899                     counter = xmlAutomataNewCounter(pctxt->am,
12900                         particle->minOccurs - 1,
12901                         particle->maxOccurs - 1);
12902 
12903                     sub = particle->children->children;
12904                     while (sub != NULL) {
12905                         tmp2 = xmlSchemaBuildAContentModel(pctxt,
12906                                         (xmlSchemaParticlePtr) sub);
12907                         if (tmp2 != 1) ret = 0;
12908                         sub = sub->next;
12909                     }
12910                     tmp = pctxt->state;
12911                     xmlAutomataNewCountedTrans(pctxt->am,
12912                         tmp, oldstate, counter);
12913                     pctxt->state =
12914                         xmlAutomataNewCounterTrans(pctxt->am, tmp, NULL,
12915                                                    counter);
12916                     if ((particle->minOccurs == 0) || (ret == 1)) {
12917                         xmlAutomataNewEpsilon(pctxt->am,
12918                                             oldstate, pctxt->state);
12919                         ret = 1;
12920                     }
12921                 } else {
12922                     sub = particle->children->children;
12923                     while (sub != NULL) {
12924                         tmp2 = xmlSchemaBuildAContentModel(pctxt,
12925                                         (xmlSchemaParticlePtr) sub);
12926                         if (tmp2 != 1) ret = 0;
12927                         sub = sub->next;
12928                     }
12929 
12930 		    /*
12931 		     * epsilon needed to block previous trans from
12932 		     * being allowed to enter back from another
12933 		     * construct
12934 		     */
12935 		    pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12936 					pctxt->state, NULL);
12937 
12938                     if (particle->minOccurs == 0) {
12939                         xmlAutomataNewEpsilon(pctxt->am, oldstate,
12940                                               pctxt->state);
12941                         ret = 1;
12942                     }
12943                 }
12944             }
12945             break;
12946         }
12947         case XML_SCHEMA_TYPE_CHOICE:{
12948             xmlSchemaTreeItemPtr sub;
12949             xmlAutomataStatePtr start, end;
12950 
12951             ret = 0;
12952             start = pctxt->state;
12953             end = xmlAutomataNewState(pctxt->am);
12954 
12955             /*
12956              * iterate over the subtypes and remerge the end with an
12957              * epsilon transition
12958              */
12959             if (particle->maxOccurs == 1) {
12960                 sub = particle->children->children;
12961                 while (sub != NULL) {
12962                     pctxt->state = start;
12963                     tmp2 = xmlSchemaBuildAContentModel(pctxt,
12964                                         (xmlSchemaParticlePtr) sub);
12965                     if (tmp2 == 1) ret = 1;
12966                     xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12967                     sub = sub->next;
12968                 }
12969             } else {
12970                 int counter;
12971                 xmlAutomataStatePtr hop, base;
12972                 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12973                     UNBOUNDED : particle->maxOccurs - 1;
12974                 int minOccurs =
12975                     particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12976 
12977                 /*
12978                  * use a counter to keep track of the number of transitions
12979                  * which went through the choice.
12980                  */
12981                 counter =
12982                     xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
12983                 hop = xmlAutomataNewState(pctxt->am);
12984                 base = xmlAutomataNewState(pctxt->am);
12985 
12986                 sub = particle->children->children;
12987                 while (sub != NULL) {
12988                     pctxt->state = base;
12989                     tmp2 = xmlSchemaBuildAContentModel(pctxt,
12990                                         (xmlSchemaParticlePtr) sub);
12991                     if (tmp2 == 1) ret = 1;
12992                     xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12993                     sub = sub->next;
12994                 }
12995                 xmlAutomataNewEpsilon(pctxt->am, start, base);
12996                 xmlAutomataNewCountedTrans(pctxt->am, hop, base, counter);
12997                 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12998                 if (ret == 1)
12999                     xmlAutomataNewEpsilon(pctxt->am, base, end);
13000             }
13001             if (particle->minOccurs == 0) {
13002                 xmlAutomataNewEpsilon(pctxt->am, start, end);
13003                 ret = 1;
13004             }
13005             pctxt->state = end;
13006             break;
13007         }
13008         case XML_SCHEMA_TYPE_ALL:{
13009             xmlAutomataStatePtr start, tmp;
13010             xmlSchemaParticlePtr sub;
13011             xmlSchemaElementPtr elemDecl;
13012 
13013             ret = 1;
13014 
13015             sub = (xmlSchemaParticlePtr) particle->children->children;
13016             if (sub == NULL)
13017                 break;
13018 
13019             ret = 0;
13020 
13021             start = pctxt->state;
13022             tmp = xmlAutomataNewState(pctxt->am);
13023             xmlAutomataNewEpsilon(pctxt->am, pctxt->state, tmp);
13024             pctxt->state = tmp;
13025             while (sub != NULL) {
13026                 pctxt->state = tmp;
13027 
13028                 elemDecl = (xmlSchemaElementPtr) sub->children;
13029                 if (elemDecl == NULL) {
13030                     PERROR_INT("xmlSchemaBuildAContentModel",
13031                         "<element> particle has no term");
13032                     return(ret);
13033                 };
13034                 /*
13035                 * NOTE: The {max occurs} of all the particles in the
13036                 * {particles} of the group must be 0 or 1; this is
13037                 * already ensured during the parse of the content of
13038                 * <all>.
13039                 */
13040                 if (elemDecl->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
13041                     int counter;
13042 
13043                     /*
13044                      * This is an abstract group, we need to share
13045                      * the same counter for all the element transitions
13046                      * derived from the group
13047                      */
13048                     counter = xmlAutomataNewCounter(pctxt->am,
13049                                        sub->minOccurs, sub->maxOccurs);
13050                     xmlSchemaBuildContentModelForSubstGroup(pctxt,
13051                                        sub, counter, pctxt->state);
13052                 } else {
13053                     if ((sub->minOccurs == 1) &&
13054                         (sub->maxOccurs == 1)) {
13055                         xmlAutomataNewOnceTrans2(pctxt->am, pctxt->state,
13056                                                 pctxt->state,
13057                                                 elemDecl->name,
13058                                                 elemDecl->targetNamespace,
13059                                                 1, 1, elemDecl);
13060                     } else if ((sub->minOccurs == 0) &&
13061                         (sub->maxOccurs == 1)) {
13062 
13063                         xmlAutomataNewCountTrans2(pctxt->am, pctxt->state,
13064                                                  pctxt->state,
13065                                                  elemDecl->name,
13066                                                  elemDecl->targetNamespace,
13067                                                  0,
13068                                                  1,
13069                                                  elemDecl);
13070                     }
13071                 }
13072                 sub = (xmlSchemaParticlePtr) sub->next;
13073             }
13074             pctxt->state =
13075                 xmlAutomataNewAllTrans(pctxt->am, pctxt->state, NULL, 0);
13076             if (particle->minOccurs == 0) {
13077                 xmlAutomataNewEpsilon(pctxt->am, start, pctxt->state);
13078                 ret = 1;
13079             }
13080             break;
13081         }
13082 	case XML_SCHEMA_TYPE_GROUP:
13083 	    /*
13084 	    * If we hit a model group definition, then this means that
13085 	    * it was empty, thus was not substituted for the containing
13086 	    * model group. Just do nothing in this case.
13087 	    * TODO: But the group should be substituted and not occur at
13088 	    * all in the content model at this point. Fix this.
13089 	    */
13090             ret = 1;
13091 	    break;
13092         default:
13093 	    xmlSchemaInternalErr2(ACTXT_CAST pctxt,
13094 		"xmlSchemaBuildAContentModel",
13095 		"found unexpected term of type '%s' in content model",
13096 		WXS_ITEM_TYPE_NAME(particle->children), NULL);
13097             return(ret);
13098     }
13099     return(ret);
13100 }
13101 
13102 /**
13103  * xmlSchemaBuildContentModel:
13104  * @ctxt:  the schema parser context
13105  * @type:  the complex type definition
13106  * @name:  the element name
13107  *
13108  * Builds the content model of the complex type.
13109  */
13110 static void
xmlSchemaBuildContentModel(xmlSchemaTypePtr type,xmlSchemaParserCtxtPtr ctxt)13111 xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
13112 			   xmlSchemaParserCtxtPtr ctxt)
13113 {
13114     if ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
13115 	(type->contModel != NULL) ||
13116 	((type->contentType != XML_SCHEMA_CONTENT_ELEMENTS) &&
13117 	(type->contentType != XML_SCHEMA_CONTENT_MIXED)))
13118 	return;
13119 
13120     ctxt->am = NULL;
13121     ctxt->am = xmlNewAutomata();
13122     if (ctxt->am == NULL) {
13123 	xmlSchemaPErrMemory(ctxt);
13124         return;
13125     }
13126     ctxt->state = xmlAutomataGetInitState(ctxt->am);
13127     /*
13128     * Build the automaton.
13129     */
13130     xmlSchemaBuildAContentModel(ctxt, WXS_TYPE_PARTICLE(type));
13131     xmlAutomataSetFinalState(ctxt->am, ctxt->state);
13132     type->contModel = xmlAutomataCompile(ctxt->am);
13133     if (type->contModel == NULL) {
13134         xmlSchemaPCustomErr(ctxt,
13135 	    XML_SCHEMAP_INTERNAL,
13136 	    WXS_BASIC_CAST type, type->node,
13137 	    "Failed to compile the content model", NULL);
13138     } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
13139         xmlSchemaPCustomErr(ctxt,
13140 	    XML_SCHEMAP_NOT_DETERMINISTIC,
13141 	    /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
13142 	    WXS_BASIC_CAST type, type->node,
13143 	    "The content model is not determinist", NULL);
13144     } else {
13145     }
13146     ctxt->state = NULL;
13147     xmlFreeAutomata(ctxt->am);
13148     ctxt->am = NULL;
13149 }
13150 
13151 /**
13152  * xmlSchemaResolveElementReferences:
13153  * @elem:  the schema element context
13154  * @ctxt:  the schema parser context
13155  *
13156  * Resolves the references of an element declaration
13157  * or particle, which has an element declaration as it's
13158  * term.
13159  */
13160 static void
xmlSchemaResolveElementReferences(xmlSchemaElementPtr elemDecl,xmlSchemaParserCtxtPtr ctxt)13161 xmlSchemaResolveElementReferences(xmlSchemaElementPtr elemDecl,
13162 				  xmlSchemaParserCtxtPtr ctxt)
13163 {
13164     if ((ctxt == NULL) || (elemDecl == NULL) ||
13165 	((elemDecl != NULL) &&
13166 	(elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
13167         return;
13168     elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
13169 
13170     if ((elemDecl->subtypes == NULL) && (elemDecl->namedType != NULL)) {
13171 	xmlSchemaTypePtr type;
13172 
13173 	/* (type definition) ... otherwise the type definition `resolved`
13174 	* to by the `actual value` of the type [attribute] ...
13175 	*/
13176 	type = xmlSchemaGetType(ctxt->schema, elemDecl->namedType,
13177 	    elemDecl->namedTypeNs);
13178 	if (type == NULL) {
13179 	    xmlSchemaPResCompAttrErr(ctxt,
13180 		XML_SCHEMAP_SRC_RESOLVE,
13181 		WXS_BASIC_CAST elemDecl, elemDecl->node,
13182 		"type", elemDecl->namedType, elemDecl->namedTypeNs,
13183 		XML_SCHEMA_TYPE_BASIC, "type definition");
13184 	} else
13185 	    elemDecl->subtypes = type;
13186     }
13187     if (elemDecl->substGroup != NULL) {
13188 	xmlSchemaElementPtr substHead;
13189 
13190 	/*
13191 	* FIXME TODO: Do we need a new field in _xmlSchemaElement for
13192 	* substitutionGroup?
13193 	*/
13194 	substHead = xmlSchemaGetElem(ctxt->schema, elemDecl->substGroup,
13195 	    elemDecl->substGroupNs);
13196 	if (substHead == NULL) {
13197 	    xmlSchemaPResCompAttrErr(ctxt,
13198 		XML_SCHEMAP_SRC_RESOLVE,
13199 		WXS_BASIC_CAST elemDecl, NULL,
13200 		"substitutionGroup", elemDecl->substGroup,
13201 		elemDecl->substGroupNs, XML_SCHEMA_TYPE_ELEMENT, NULL);
13202 	} else {
13203 	    xmlSchemaResolveElementReferences(substHead, ctxt);
13204 	    /*
13205 	    * Set the "substitution group affiliation".
13206 	    * NOTE that now we use the "refDecl" field for this.
13207 	    */
13208 	    WXS_SUBST_HEAD(elemDecl) = substHead;
13209 	    /*
13210 	    * The type definitions is set to:
13211 	    * SPEC "...the {type definition} of the element
13212 	    * declaration `resolved` to by the `actual value`
13213 	    * of the substitutionGroup [attribute], if present"
13214 	    */
13215 	    if (elemDecl->subtypes == NULL) {
13216                 if (substHead->subtypes == NULL) {
13217                     /*
13218                      * This can happen with self-referencing substitution
13219                      * groups. The cycle will be detected later, but we have
13220                      * to set subtypes to avoid null-pointer dereferences.
13221                      */
13222 	            elemDecl->subtypes = xmlSchemaGetBuiltInType(
13223                             XML_SCHEMAS_ANYTYPE);
13224                 } else {
13225 		    elemDecl->subtypes = substHead->subtypes;
13226                 }
13227             }
13228 	}
13229     }
13230     /*
13231     * SPEC "The definition of anyType serves as the default type definition
13232     * for element declarations whose XML representation does not specify one."
13233     */
13234     if ((elemDecl->subtypes == NULL) &&
13235 	(elemDecl->namedType == NULL) &&
13236 	(elemDecl->substGroup == NULL))
13237 	elemDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
13238 }
13239 
13240 /**
13241  * xmlSchemaResolveUnionMemberTypes:
13242  * @ctxt:  the schema parser context
13243  * @type:  the schema simple type definition
13244  *
13245  * Checks and builds the "member type definitions" property of the union
13246  * simple type. This handles part (1), part (2) is done in
13247  * xmlSchemaFinishMemberTypeDefinitionsProperty()
13248  *
13249  * Returns -1 in case of an internal error, 0 otherwise.
13250  */
13251 static int
xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,xmlSchemaTypePtr type)13252 xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,
13253 				 xmlSchemaTypePtr type)
13254 {
13255 
13256     xmlSchemaTypeLinkPtr link, lastLink, newLink;
13257     xmlSchemaTypePtr memberType;
13258 
13259     /*
13260     * SPEC (1) "If the <union> alternative is chosen, then [Definition:]
13261     * define the explicit members as the type definitions `resolved`
13262     * to by the items in the `actual value` of the memberTypes [attribute],
13263     * if any, followed by the type definitions corresponding to the
13264     * <simpleType>s among the [children] of <union>, if any."
13265     */
13266     /*
13267     * Resolve references.
13268     */
13269     link = type->memberTypes;
13270     lastLink = NULL;
13271     while (link != NULL) {
13272 	const xmlChar *name, *nsName;
13273 
13274 	name = ((xmlSchemaQNameRefPtr) link->type)->name;
13275 	nsName = ((xmlSchemaQNameRefPtr) link->type)->targetNamespace;
13276 
13277 	memberType = xmlSchemaGetType(ctxt->schema, name, nsName);
13278 	if ((memberType == NULL) || (! WXS_IS_SIMPLE(memberType))) {
13279 	    xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
13280 		WXS_BASIC_CAST type, type->node, "memberTypes",
13281 		name, nsName, XML_SCHEMA_TYPE_SIMPLE, NULL);
13282 	    /*
13283 	    * Remove the member type link.
13284 	    */
13285 	    if (lastLink == NULL)
13286 		type->memberTypes = link->next;
13287 	    else
13288 		lastLink->next = link->next;
13289 	    newLink = link;
13290 	    link = link->next;
13291 	    xmlFree(newLink);
13292 	} else {
13293 	    link->type = memberType;
13294 	    lastLink = link;
13295 	    link = link->next;
13296 	}
13297     }
13298     /*
13299     * Add local simple types,
13300     */
13301     memberType = type->subtypes;
13302     while (memberType != NULL) {
13303 	link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
13304 	if (link == NULL) {
13305 	    xmlSchemaPErrMemory(ctxt);
13306 	    return (-1);
13307 	}
13308 	link->type = memberType;
13309 	link->next = NULL;
13310 	if (lastLink == NULL)
13311 	    type->memberTypes = link;
13312 	else
13313 	    lastLink->next = link;
13314 	lastLink = link;
13315 	memberType = memberType->next;
13316     }
13317     return (0);
13318 }
13319 
13320 /**
13321  * xmlSchemaIsDerivedFromBuiltInType:
13322  * @ctxt:  the schema parser context
13323  * @type:  the type definition
13324  * @valType: the value type
13325  *
13326  *
13327  * Returns 1 if the type has the given value type, or
13328  * is derived from such a type.
13329  */
13330 static int
xmlSchemaIsDerivedFromBuiltInType(xmlSchemaTypePtr type,int valType)13331 xmlSchemaIsDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
13332 {
13333     if (type == NULL)
13334 	return (0);
13335     if (WXS_IS_COMPLEX(type))
13336 	return (0);
13337     if (type->type == XML_SCHEMA_TYPE_BASIC) {
13338 	if (type->builtInType == valType)
13339 	    return(1);
13340 	if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13341 	    (type->builtInType == XML_SCHEMAS_ANYTYPE))
13342 	    return (0);
13343 	return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13344     }
13345     return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13346 }
13347 
13348 #if 0
13349 /**
13350  * xmlSchemaIsDerivedFromBuiltInType:
13351  * @ctxt:  the schema parser context
13352  * @type:  the type definition
13353  * @valType: the value type
13354  *
13355  *
13356  * Returns 1 if the type has the given value type, or
13357  * is derived from such a type.
13358  */
13359 static int
13360 xmlSchemaIsUserDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
13361 {
13362     if (type == NULL)
13363 	return (0);
13364     if (WXS_IS_COMPLEX(type))
13365 	return (0);
13366     if (type->type == XML_SCHEMA_TYPE_BASIC) {
13367 	if (type->builtInType == valType)
13368 	    return(1);
13369 	return (0);
13370     } else
13371 	return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13372 
13373     return (0);
13374 }
13375 
13376 static xmlSchemaTypePtr
13377 xmlSchemaQueryBuiltInType(xmlSchemaTypePtr type)
13378 {
13379     if (type == NULL)
13380 	return (NULL);
13381     if (WXS_IS_COMPLEX(type))
13382 	return (NULL);
13383     if (type->type == XML_SCHEMA_TYPE_BASIC)
13384 	return(type);
13385     return(xmlSchemaQueryBuiltInType(type->subtypes));
13386 }
13387 #endif
13388 
13389 /**
13390  * xmlSchemaGetPrimitiveType:
13391  * @type:  the simpleType definition
13392  *
13393  * Returns the primitive type of the given type or
13394  * NULL in case of error.
13395  */
13396 static xmlSchemaTypePtr
xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)13397 xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
13398 {
13399 
13400     while (type != NULL) {
13401 	/*
13402 	* Note that anySimpleType is actually not a primitive type
13403 	* but we need that here.
13404 	*/
13405 	if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13406 	   (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
13407 	    return (type);
13408 	type = type->baseType;
13409     }
13410 
13411     return (NULL);
13412 }
13413 
13414 #if 0
13415 /**
13416  * xmlSchemaGetBuiltInTypeAncestor:
13417  * @type:  the simpleType definition
13418  *
13419  * Returns the primitive type of the given type or
13420  * NULL in case of error.
13421  */
13422 static xmlSchemaTypePtr
13423 xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
13424 {
13425     if (WXS_IS_LIST(type) || WXS_IS_UNION(type))
13426 	return (0);
13427     while (type != NULL) {
13428 	if (type->type == XML_SCHEMA_TYPE_BASIC)
13429 	    return (type);
13430 	type = type->baseType;
13431     }
13432 
13433     return (NULL);
13434 }
13435 #endif
13436 
13437 /**
13438  * xmlSchemaCloneWildcardNsConstraints:
13439  * @ctxt:  the schema parser context
13440  * @dest:  the destination wildcard
13441  * @source: the source wildcard
13442  *
13443  * Clones the namespace constraints of source
13444  * and assigns them to dest.
13445  * Returns -1 on internal error, 0 otherwise.
13446  */
13447 static int
xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,xmlSchemaWildcardPtr dest,xmlSchemaWildcardPtr source)13448 xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
13449 				    xmlSchemaWildcardPtr dest,
13450 				    xmlSchemaWildcardPtr source)
13451 {
13452     xmlSchemaWildcardNsPtr cur, tmp, last;
13453 
13454     if ((source == NULL) || (dest == NULL))
13455 	return(-1);
13456     dest->any = source->any;
13457     cur = source->nsSet;
13458     last = NULL;
13459     while (cur != NULL) {
13460 	tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
13461 	if (tmp == NULL)
13462 	    return(-1);
13463 	tmp->value = cur->value;
13464 	if (last == NULL)
13465 	    dest->nsSet = tmp;
13466 	else
13467 	    last->next = tmp;
13468 	last = tmp;
13469 	cur = cur->next;
13470     }
13471     if (dest->negNsSet != NULL)
13472 	xmlSchemaFreeWildcardNsSet(dest->negNsSet);
13473     if (source->negNsSet != NULL) {
13474 	dest->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13475 	if (dest->negNsSet == NULL)
13476 	    return(-1);
13477 	dest->negNsSet->value = source->negNsSet->value;
13478     } else
13479 	dest->negNsSet = NULL;
13480     return(0);
13481 }
13482 
13483 /**
13484  * xmlSchemaUnionWildcards:
13485  * @ctxt:  the schema parser context
13486  * @completeWild:  the first wildcard
13487  * @curWild: the second wildcard
13488  *
13489  * Unions the namespace constraints of the given wildcards.
13490  * @completeWild will hold the resulting union.
13491  * Returns a positive error code on failure, -1 in case of an
13492  * internal error, 0 otherwise.
13493  */
13494 static int
xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,xmlSchemaWildcardPtr completeWild,xmlSchemaWildcardPtr curWild)13495 xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
13496 			    xmlSchemaWildcardPtr completeWild,
13497 			    xmlSchemaWildcardPtr curWild)
13498 {
13499     xmlSchemaWildcardNsPtr cur, curB, tmp;
13500 
13501     /*
13502     * 1 If O1 and O2 are the same value, then that value must be the
13503     * value.
13504     */
13505     if ((completeWild->any == curWild->any) &&
13506 	((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13507 	((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
13508 
13509 	if ((completeWild->negNsSet == NULL) ||
13510 	    (completeWild->negNsSet->value == curWild->negNsSet->value)) {
13511 
13512 	    if (completeWild->nsSet != NULL) {
13513 		int found = 0;
13514 
13515 		/*
13516 		* Check equality of sets.
13517 		*/
13518 		cur = completeWild->nsSet;
13519 		while (cur != NULL) {
13520 		    found = 0;
13521 		    curB = curWild->nsSet;
13522 		    while (curB != NULL) {
13523 			if (cur->value == curB->value) {
13524 			    found = 1;
13525 			    break;
13526 			}
13527 			curB = curB->next;
13528 		    }
13529 		    if (!found)
13530 			break;
13531 		    cur = cur->next;
13532 		}
13533 		if (found)
13534 		    return(0);
13535 	    } else
13536 		return(0);
13537 	}
13538     }
13539     /*
13540     * 2 If either O1 or O2 is any, then any must be the value
13541     */
13542     if (completeWild->any != curWild->any) {
13543 	if (completeWild->any == 0) {
13544 	    completeWild->any = 1;
13545 	    if (completeWild->nsSet != NULL) {
13546 		xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13547 		completeWild->nsSet = NULL;
13548 	    }
13549 	    if (completeWild->negNsSet != NULL) {
13550 		xmlFree(completeWild->negNsSet);
13551 		completeWild->negNsSet = NULL;
13552 	    }
13553 	}
13554 	return (0);
13555     }
13556     /*
13557     * 3 If both O1 and O2 are sets of (namespace names or `absent`),
13558     * then the union of those sets must be the value.
13559     */
13560     if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
13561 	int found;
13562 	xmlSchemaWildcardNsPtr start;
13563 
13564 	cur = curWild->nsSet;
13565 	start = completeWild->nsSet;
13566 	while (cur != NULL) {
13567 	    found = 0;
13568 	    curB = start;
13569 	    while (curB != NULL) {
13570 		if (cur->value == curB->value) {
13571 		    found = 1;
13572 		    break;
13573 		}
13574 		curB = curB->next;
13575 	    }
13576 	    if (!found) {
13577 		tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
13578 		if (tmp == NULL)
13579 		    return (-1);
13580 		tmp->value = cur->value;
13581 		tmp->next = completeWild->nsSet;
13582 		completeWild->nsSet = tmp;
13583 	    }
13584 	    cur = cur->next;
13585 	}
13586 
13587 	return(0);
13588     }
13589     /*
13590     * 4 If the two are negations of different values (namespace names
13591     * or `absent`), then a pair of not and `absent` must be the value.
13592     */
13593     if ((completeWild->negNsSet != NULL) &&
13594 	(curWild->negNsSet != NULL) &&
13595 	(completeWild->negNsSet->value != curWild->negNsSet->value)) {
13596 	completeWild->negNsSet->value = NULL;
13597 
13598 	return(0);
13599     }
13600     /*
13601      * 5.
13602      */
13603     if (((completeWild->negNsSet != NULL) &&
13604 	(completeWild->negNsSet->value != NULL) &&
13605 	(curWild->nsSet != NULL)) ||
13606 	((curWild->negNsSet != NULL) &&
13607 	(curWild->negNsSet->value != NULL) &&
13608 	(completeWild->nsSet != NULL))) {
13609 
13610 	int nsFound, absentFound = 0;
13611 
13612 	if (completeWild->nsSet != NULL) {
13613 	    cur = completeWild->nsSet;
13614 	    curB = curWild->negNsSet;
13615 	} else {
13616 	    cur = curWild->nsSet;
13617 	    curB = completeWild->negNsSet;
13618 	}
13619 	nsFound = 0;
13620 	while (cur != NULL) {
13621 	    if (cur->value == NULL)
13622 		absentFound = 1;
13623 	    else if (cur->value == curB->value)
13624 		nsFound = 1;
13625 	    if (nsFound && absentFound)
13626 		break;
13627 	    cur = cur->next;
13628 	}
13629 
13630 	if (nsFound && absentFound) {
13631 	    /*
13632 	    * 5.1 If the set S includes both the negated namespace
13633 	    * name and `absent`, then any must be the value.
13634 	    */
13635 	    completeWild->any = 1;
13636 	    if (completeWild->nsSet != NULL) {
13637 		xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13638 		completeWild->nsSet = NULL;
13639 	    }
13640 	    if (completeWild->negNsSet != NULL) {
13641 		xmlFree(completeWild->negNsSet);
13642 		completeWild->negNsSet = NULL;
13643 	    }
13644 	} else if (nsFound && (!absentFound)) {
13645 	    /*
13646 	    * 5.2 If the set S includes the negated namespace name
13647 	    * but not `absent`, then a pair of not and `absent` must
13648 	    * be the value.
13649 	    */
13650 	    if (completeWild->nsSet != NULL) {
13651 		xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13652 		completeWild->nsSet = NULL;
13653 	    }
13654 	    if (completeWild->negNsSet == NULL) {
13655 		completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13656 		if (completeWild->negNsSet == NULL)
13657 		    return (-1);
13658 	    }
13659 	    completeWild->negNsSet->value = NULL;
13660 	} else if ((!nsFound) && absentFound) {
13661 	    /*
13662 	    * 5.3 If the set S includes `absent` but not the negated
13663 	    * namespace name, then the union is not expressible.
13664 	    */
13665 	    xmlSchemaPErr(ctxt, completeWild->node,
13666 		XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
13667 		"The union of the wildcard is not expressible.\n",
13668 		NULL, NULL);
13669 	    return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
13670 	} else if ((!nsFound) && (!absentFound)) {
13671 	    /*
13672 	    * 5.4 If the set S does not include either the negated namespace
13673 	    * name or `absent`, then whichever of O1 or O2 is a pair of not
13674 	    * and a namespace name must be the value.
13675 	    */
13676 	    if (completeWild->negNsSet == NULL) {
13677 		if (completeWild->nsSet != NULL) {
13678 		    xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13679 		    completeWild->nsSet = NULL;
13680 		}
13681 		completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13682 		if (completeWild->negNsSet == NULL)
13683 		    return (-1);
13684 		completeWild->negNsSet->value = curWild->negNsSet->value;
13685 	    }
13686 	}
13687 	return (0);
13688     }
13689     /*
13690      * 6.
13691      */
13692     if (((completeWild->negNsSet != NULL) &&
13693 	(completeWild->negNsSet->value == NULL) &&
13694 	(curWild->nsSet != NULL)) ||
13695 	((curWild->negNsSet != NULL) &&
13696 	(curWild->negNsSet->value == NULL) &&
13697 	(completeWild->nsSet != NULL))) {
13698 
13699 	if (completeWild->nsSet != NULL) {
13700 	    cur = completeWild->nsSet;
13701 	} else {
13702 	    cur = curWild->nsSet;
13703 	}
13704 	while (cur != NULL) {
13705 	    if (cur->value == NULL) {
13706 		/*
13707 		* 6.1 If the set S includes `absent`, then any must be the
13708 		* value.
13709 		*/
13710 		completeWild->any = 1;
13711 		if (completeWild->nsSet != NULL) {
13712 		    xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13713 		    completeWild->nsSet = NULL;
13714 		}
13715 		if (completeWild->negNsSet != NULL) {
13716 		    xmlFree(completeWild->negNsSet);
13717 		    completeWild->negNsSet = NULL;
13718 		}
13719 		return (0);
13720 	    }
13721 	    cur = cur->next;
13722 	}
13723 	if (completeWild->negNsSet == NULL) {
13724 	    /*
13725 	    * 6.2 If the set S does not include `absent`, then a pair of not
13726 	    * and `absent` must be the value.
13727 	    */
13728 	    if (completeWild->nsSet != NULL) {
13729 		xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13730 		completeWild->nsSet = NULL;
13731 	    }
13732 	    completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13733 	    if (completeWild->negNsSet == NULL)
13734 		return (-1);
13735 	    completeWild->negNsSet->value = NULL;
13736 	}
13737 	return (0);
13738     }
13739     return (0);
13740 
13741 }
13742 
13743 /**
13744  * xmlSchemaIntersectWildcards:
13745  * @ctxt:  the schema parser context
13746  * @completeWild:  the first wildcard
13747  * @curWild: the second wildcard
13748  *
13749  * Intersects the namespace constraints of the given wildcards.
13750  * @completeWild will hold the resulting intersection.
13751  * Returns a positive error code on failure, -1 in case of an
13752  * internal error, 0 otherwise.
13753  */
13754 static int
xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,xmlSchemaWildcardPtr completeWild,xmlSchemaWildcardPtr curWild)13755 xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
13756 			    xmlSchemaWildcardPtr completeWild,
13757 			    xmlSchemaWildcardPtr curWild)
13758 {
13759     xmlSchemaWildcardNsPtr cur, curB, prev,  tmp;
13760 
13761     /*
13762     * 1 If O1 and O2 are the same value, then that value must be the
13763     * value.
13764     */
13765     if ((completeWild->any == curWild->any) &&
13766 	((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13767 	((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
13768 
13769 	if ((completeWild->negNsSet == NULL) ||
13770 	    (completeWild->negNsSet->value == curWild->negNsSet->value)) {
13771 
13772 	    if (completeWild->nsSet != NULL) {
13773 		int found = 0;
13774 
13775 		/*
13776 		* Check equality of sets.
13777 		*/
13778 		cur = completeWild->nsSet;
13779 		while (cur != NULL) {
13780 		    found = 0;
13781 		    curB = curWild->nsSet;
13782 		    while (curB != NULL) {
13783 			if (cur->value == curB->value) {
13784 			    found = 1;
13785 			    break;
13786 			}
13787 			curB = curB->next;
13788 		    }
13789 		    if (!found)
13790 			break;
13791 		    cur = cur->next;
13792 		}
13793 		if (found)
13794 		    return(0);
13795 	    } else
13796 		return(0);
13797 	}
13798     }
13799     /*
13800     * 2 If either O1 or O2 is any, then the other must be the value.
13801     */
13802     if ((completeWild->any != curWild->any) && (completeWild->any)) {
13803 	if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
13804 	    return(-1);
13805 	return(0);
13806     }
13807     /*
13808     * 3 If either O1 or O2 is a pair of not and a value (a namespace
13809     * name or `absent`) and the other is a set of (namespace names or
13810     * `absent`), then that set, minus the negated value if it was in
13811     * the set, minus `absent` if it was in the set, must be the value.
13812     */
13813     if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
13814 	((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
13815 	const xmlChar *neg;
13816 
13817 	if (completeWild->nsSet == NULL) {
13818 	    neg = completeWild->negNsSet->value;
13819 	    if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
13820 		return(-1);
13821 	} else
13822 	    neg = curWild->negNsSet->value;
13823 	/*
13824 	* Remove absent and negated.
13825 	*/
13826 	prev = NULL;
13827 	cur = completeWild->nsSet;
13828 	while (cur != NULL) {
13829 	    if (cur->value == NULL) {
13830 		if (prev == NULL)
13831 		    completeWild->nsSet = cur->next;
13832 		else
13833 		    prev->next = cur->next;
13834 		xmlFree(cur);
13835 		break;
13836 	    }
13837 	    prev = cur;
13838 	    cur = cur->next;
13839 	}
13840 	if (neg != NULL) {
13841 	    prev = NULL;
13842 	    cur = completeWild->nsSet;
13843 	    while (cur != NULL) {
13844 		if (cur->value == neg) {
13845 		    if (prev == NULL)
13846 			completeWild->nsSet = cur->next;
13847 		    else
13848 			prev->next = cur->next;
13849 		    xmlFree(cur);
13850 		    break;
13851 		}
13852 		prev = cur;
13853 		cur = cur->next;
13854 	    }
13855 	}
13856 
13857 	return(0);
13858     }
13859     /*
13860     * 4 If both O1 and O2 are sets of (namespace names or `absent`),
13861     * then the intersection of those sets must be the value.
13862     */
13863     if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
13864 	int found;
13865 
13866 	cur = completeWild->nsSet;
13867 	prev = NULL;
13868 	while (cur != NULL) {
13869 	    found = 0;
13870 	    curB = curWild->nsSet;
13871 	    while (curB != NULL) {
13872 		if (cur->value == curB->value) {
13873 		    found = 1;
13874 		    break;
13875 		}
13876 		curB = curB->next;
13877 	    }
13878 	    if (!found) {
13879 		if (prev == NULL)
13880 		    completeWild->nsSet = cur->next;
13881 		else
13882 		    prev->next = cur->next;
13883 		tmp = cur->next;
13884 		xmlFree(cur);
13885 		cur = tmp;
13886 		continue;
13887 	    }
13888 	    prev = cur;
13889 	    cur = cur->next;
13890 	}
13891 
13892 	return(0);
13893     }
13894     /* 5 If the two are negations of different namespace names,
13895     * then the intersection is not expressible
13896     */
13897     if ((completeWild->negNsSet != NULL) &&
13898 	(curWild->negNsSet != NULL) &&
13899 	(completeWild->negNsSet->value != curWild->negNsSet->value) &&
13900 	(completeWild->negNsSet->value != NULL) &&
13901 	(curWild->negNsSet->value != NULL)) {
13902 
13903 	xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
13904 	    "The intersection of the wildcard is not expressible.\n",
13905 	    NULL, NULL);
13906 	return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
13907     }
13908     /*
13909     * 6 If the one is a negation of a namespace name and the other
13910     * is a negation of `absent`, then the one which is the negation
13911     * of a namespace name must be the value.
13912     */
13913     if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
13914 	(completeWild->negNsSet->value != curWild->negNsSet->value) &&
13915 	(completeWild->negNsSet->value == NULL)) {
13916 	completeWild->negNsSet->value =  curWild->negNsSet->value;
13917     }
13918     return(0);
13919 }
13920 
13921 /**
13922  * xmlSchemaIsWildcardNsConstraintSubset:
13923  * @ctxt:  the schema parser context
13924  * @sub:  the first wildcard
13925  * @super: the second wildcard
13926  *
13927  * Schema Component Constraint: Wildcard Subset (cos-ns-subset)
13928  *
13929  * Returns 0 if the namespace constraint of @sub is an intensional
13930  * subset of @super, 1 otherwise.
13931  */
13932 static int
xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub,xmlSchemaWildcardPtr super)13933 xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub,
13934 			  xmlSchemaWildcardPtr super)
13935 {
13936     /*
13937     * 1 super must be any.
13938     */
13939     if (super->any)
13940 	return (0);
13941     /*
13942     * 2.1 sub must be a pair of not and a namespace name or `absent`.
13943     * 2.2 super must be a pair of not and the same value.
13944     */
13945     if ((sub->negNsSet != NULL) &&
13946 	(super->negNsSet != NULL) &&
13947 	(sub->negNsSet->value == super->negNsSet->value))
13948 	return (0);
13949     /*
13950     * 3.1 sub must be a set whose members are either namespace names or `absent`.
13951     */
13952     if (sub->nsSet != NULL) {
13953 	/*
13954 	* 3.2.1 super must be the same set or a superset thereof.
13955 	*/
13956 	if (super->nsSet != NULL) {
13957 	    xmlSchemaWildcardNsPtr cur, curB;
13958 	    int found = 0;
13959 
13960 	    cur = sub->nsSet;
13961 	    while (cur != NULL) {
13962 		found = 0;
13963 		curB = super->nsSet;
13964 		while (curB != NULL) {
13965 		    if (cur->value == curB->value) {
13966 			found = 1;
13967 			break;
13968 		    }
13969 		    curB = curB->next;
13970 		}
13971 		if (!found)
13972 		    return (1);
13973 		cur = cur->next;
13974 	    }
13975 	    if (found)
13976 		return (0);
13977 	} else if (super->negNsSet != NULL) {
13978 	    xmlSchemaWildcardNsPtr cur;
13979 	    /*
13980 	    * 3.2.2 super must be a pair of not and a namespace name or
13981 	    * `absent` and that value must not be in sub's set.
13982 	    */
13983 	    cur = sub->nsSet;
13984 	    while (cur != NULL) {
13985 		if (cur->value == super->negNsSet->value)
13986 		    return (1);
13987 		cur = cur->next;
13988 	    }
13989 	    return (0);
13990 	}
13991     }
13992     return (1);
13993 }
13994 
13995 static int
xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributeUsePtr attruse,int * fixed,const xmlChar ** value,xmlSchemaValPtr * val)13996 xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributeUsePtr attruse,
13997 				     int *fixed,
13998 				     const xmlChar **value,
13999 				     xmlSchemaValPtr *val)
14000 {
14001     *fixed = 0;
14002     *value = NULL;
14003     if (val != 0)
14004 	*val = NULL;
14005 
14006     if (attruse->defValue != NULL) {
14007 	*value = attruse->defValue;
14008 	if (val != NULL)
14009 	    *val = attruse->defVal;
14010 	if (attruse->flags & XML_SCHEMA_ATTR_USE_FIXED)
14011 	    *fixed = 1;
14012 	return(1);
14013     } else if ((attruse->attrDecl != NULL) &&
14014 	(attruse->attrDecl->defValue != NULL)) {
14015 	*value = attruse->attrDecl->defValue;
14016 	if (val != NULL)
14017 	    *val = attruse->attrDecl->defVal;
14018 	if (attruse->attrDecl->flags & XML_SCHEMAS_ATTR_FIXED)
14019 	    *fixed = 1;
14020 	return(1);
14021     }
14022     return(0);
14023 }
14024 /**
14025  * xmlSchemaCheckCVCWildcardNamespace:
14026  * @wild:  the wildcard
14027  * @ns:  the namespace
14028  *
14029  * Validation Rule: Wildcard allows Namespace Name
14030  * (cvc-wildcard-namespace)
14031  *
14032  * Returns 0 if the given namespace matches the wildcard,
14033  * 1 otherwise and -1 on API errors.
14034  */
14035 static int
xmlSchemaCheckCVCWildcardNamespace(xmlSchemaWildcardPtr wild,const xmlChar * ns)14036 xmlSchemaCheckCVCWildcardNamespace(xmlSchemaWildcardPtr wild,
14037 				   const xmlChar* ns)
14038 {
14039     if (wild == NULL)
14040 	return(-1);
14041 
14042     if (wild->any)
14043 	return(0);
14044     else if (wild->nsSet != NULL) {
14045 	xmlSchemaWildcardNsPtr cur;
14046 
14047 	cur = wild->nsSet;
14048 	while (cur != NULL) {
14049 	    if (xmlStrEqual(cur->value, ns))
14050 		return(0);
14051 	    cur = cur->next;
14052 	}
14053     } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
14054 	(!xmlStrEqual(wild->negNsSet->value, ns)))
14055 	return(0);
14056 
14057     return(1);
14058 }
14059 
14060 #define XML_SCHEMA_ACTION_DERIVE 0
14061 #define XML_SCHEMA_ACTION_REDEFINE 1
14062 
14063 #define WXS_ACTION_STR(a) \
14064 ((a) == XML_SCHEMA_ACTION_DERIVE) ? (const xmlChar *) "base" : (const xmlChar *) "redefined"
14065 
14066 /*
14067 * Schema Component Constraint:
14068 *   Derivation Valid (Restriction, Complex)
14069 *   derivation-ok-restriction (2) - (4)
14070 *
14071 * ATTENTION:
14072 * In XML Schema 1.1 this will be:
14073 * Validation Rule:
14074 *     Checking complex type subsumption (practicalSubsumption) (1, 2 and 3)
14075 *
14076 */
14077 static int
xmlSchemaCheckDerivationOKRestriction2to4(xmlSchemaParserCtxtPtr pctxt,int action,xmlSchemaBasicItemPtr item,xmlSchemaBasicItemPtr baseItem,xmlSchemaItemListPtr uses,xmlSchemaItemListPtr baseUses,xmlSchemaWildcardPtr wild,xmlSchemaWildcardPtr baseWild)14078 xmlSchemaCheckDerivationOKRestriction2to4(xmlSchemaParserCtxtPtr pctxt,
14079 				       int action,
14080 				       xmlSchemaBasicItemPtr item,
14081 				       xmlSchemaBasicItemPtr baseItem,
14082 				       xmlSchemaItemListPtr uses,
14083 				       xmlSchemaItemListPtr baseUses,
14084 				       xmlSchemaWildcardPtr wild,
14085 				       xmlSchemaWildcardPtr baseWild)
14086 {
14087     xmlSchemaAttributeUsePtr cur = NULL, bcur;
14088     int i, j, found; /* err = 0; */
14089     const xmlChar *bEffValue;
14090     int effFixed;
14091 
14092     if (uses != NULL) {
14093 	for (i = 0; i < uses->nbItems; i++) {
14094 	    cur = uses->items[i];
14095 	    found = 0;
14096 	    if (baseUses == NULL)
14097 		goto not_found;
14098 	    for (j = 0; j < baseUses->nbItems; j++) {
14099 		bcur = baseUses->items[j];
14100 		if ((WXS_ATTRUSE_DECL_NAME(cur) ==
14101 			WXS_ATTRUSE_DECL_NAME(bcur)) &&
14102 		    (WXS_ATTRUSE_DECL_TNS(cur) ==
14103 			WXS_ATTRUSE_DECL_TNS(bcur)))
14104 		{
14105 		    /*
14106 		    * (2.1) "If there is an attribute use in the {attribute
14107 		    * uses} of the {base type definition} (call this B) whose
14108 		    * {attribute declaration} has the same {name} and {target
14109 		    * namespace}, then  all of the following must be true:"
14110 		    */
14111 		    found = 1;
14112 
14113 		    if ((cur->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
14114 			(bcur->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED))
14115 		    {
14116 			xmlChar *str = NULL;
14117 			/*
14118 			* (2.1.1) "one of the following must be true:"
14119 			* (2.1.1.1) "B's {required} is false."
14120 			* (2.1.1.2) "R's {required} is true."
14121 			*/
14122 			xmlSchemaPAttrUseErr4(pctxt,
14123 			    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
14124 			    WXS_ITEM_NODE(item), item, cur,
14125 			    "The 'optional' attribute use is inconsistent "
14126 			    "with the corresponding 'required' attribute use of "
14127 			    "the %s %s",
14128 			    WXS_ACTION_STR(action),
14129 			    xmlSchemaGetComponentDesignation(&str, baseItem),
14130 			    NULL, NULL);
14131 			FREE_AND_NULL(str);
14132 			/* err = pctxt->err; */
14133 		    } else if (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
14134 			WXS_ATTRUSE_TYPEDEF(cur),
14135 			WXS_ATTRUSE_TYPEDEF(bcur), 0) != 0)
14136 		    {
14137 			xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
14138 
14139 			/*
14140 			* SPEC (2.1.2) "R's {attribute declaration}'s
14141 			* {type definition} must be validly derived from
14142 			* B's {type definition} given the empty set as
14143 			* defined in Type Derivation OK (Simple) ($3.14.6)."
14144 			*/
14145 			xmlSchemaPAttrUseErr4(pctxt,
14146 			    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_2,
14147 			    WXS_ITEM_NODE(item), item, cur,
14148 			    "The attribute declaration's %s "
14149 			    "is not validly derived from "
14150 			    "the corresponding %s of the "
14151 			    "attribute declaration in the %s %s",
14152 			    xmlSchemaGetComponentDesignation(&strA,
14153 				WXS_ATTRUSE_TYPEDEF(cur)),
14154 			    xmlSchemaGetComponentDesignation(&strB,
14155 				WXS_ATTRUSE_TYPEDEF(bcur)),
14156 			    WXS_ACTION_STR(action),
14157 			    xmlSchemaGetComponentDesignation(&strC, baseItem));
14158 			    /* xmlSchemaGetComponentDesignation(&str, baseItem), */
14159 			FREE_AND_NULL(strA);
14160 			FREE_AND_NULL(strB);
14161 			FREE_AND_NULL(strC);
14162 			/* err = pctxt->err; */
14163 		    } else {
14164 			/*
14165 			* 2.1.3 [Definition:]  Let the effective value
14166 			* constraint of an attribute use be its {value
14167 			* constraint}, if present, otherwise its {attribute
14168 			* declaration}'s {value constraint} .
14169 			*/
14170 			xmlSchemaGetEffectiveValueConstraint(bcur,
14171 			    &effFixed, &bEffValue, NULL);
14172 			/*
14173 			* 2.1.3 ... one of the following must be true
14174 			*
14175 			* 2.1.3.1 B's `effective value constraint` is
14176 			* `absent` or default.
14177 			*/
14178 			if ((bEffValue != NULL) &&
14179 			    (effFixed == 1)) {
14180 			    const xmlChar *rEffValue = NULL;
14181 
14182 			    xmlSchemaGetEffectiveValueConstraint(bcur,
14183 				&effFixed, &rEffValue, NULL);
14184 			    /*
14185 			    * 2.1.3.2 R's `effective value constraint` is
14186 			    * fixed with the same string as B's.
14187 			    * MAYBE TODO: Compare the computed values.
14188 			    *       Hmm, it says "same string" so
14189 			    *       string-equality might really be sufficient.
14190 			    */
14191 			    if ((effFixed == 0) ||
14192 				(! WXS_ARE_DEFAULT_STR_EQUAL(rEffValue, bEffValue)))
14193 			    {
14194 				xmlChar *str = NULL;
14195 
14196 				xmlSchemaPAttrUseErr4(pctxt,
14197 				    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
14198 				    WXS_ITEM_NODE(item), item, cur,
14199 				    "The effective value constraint of the "
14200 				    "attribute use is inconsistent with "
14201 				    "its correspondent in the %s %s",
14202 				    WXS_ACTION_STR(action),
14203 				    xmlSchemaGetComponentDesignation(&str,
14204 					baseItem),
14205 				    NULL, NULL);
14206 				FREE_AND_NULL(str);
14207 				/* err = pctxt->err; */
14208 			    }
14209 			}
14210 		    }
14211 		    break;
14212 		}
14213 	    }
14214 not_found:
14215 	    if (!found) {
14216 		/*
14217 		* (2.2) "otherwise the {base type definition} must have an
14218 		* {attribute wildcard} and the {target namespace} of the
14219 		* R's {attribute declaration} must be `valid` with respect
14220 		* to that wildcard, as defined in Wildcard allows Namespace
14221 		* Name ($3.10.4)."
14222 		*/
14223 		if ((baseWild == NULL) ||
14224 		    (xmlSchemaCheckCVCWildcardNamespace(baseWild,
14225 		    (WXS_ATTRUSE_DECL(cur))->targetNamespace) != 0))
14226 		{
14227 		    xmlChar *str = NULL;
14228 
14229 		    xmlSchemaPAttrUseErr4(pctxt,
14230 			XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
14231 			WXS_ITEM_NODE(item), item, cur,
14232 			"Neither a matching attribute use, "
14233 			"nor a matching wildcard exists in the %s %s",
14234 			WXS_ACTION_STR(action),
14235 			xmlSchemaGetComponentDesignation(&str, baseItem),
14236 			NULL, NULL);
14237 		    FREE_AND_NULL(str);
14238 		    /* err = pctxt->err; */
14239 		}
14240 	    }
14241 	}
14242     }
14243     /*
14244     * SPEC derivation-ok-restriction (3):
14245     * (3) "For each attribute use in the {attribute uses} of the {base type
14246     * definition} whose {required} is true, there must be an attribute
14247     * use with an {attribute declaration} with the same {name} and
14248     * {target namespace} as its {attribute declaration} in the {attribute
14249     * uses} of the complex type definition itself whose {required} is true.
14250     */
14251     if (baseUses != NULL) {
14252 	for (j = 0; j < baseUses->nbItems; j++) {
14253 	    bcur = baseUses->items[j];
14254 	    if (bcur->occurs != XML_SCHEMAS_ATTR_USE_REQUIRED)
14255 		continue;
14256 	    found = 0;
14257 	    if (uses != NULL) {
14258 		for (i = 0; i < uses->nbItems; i++) {
14259 		    cur = uses->items[i];
14260 		    if ((WXS_ATTRUSE_DECL_NAME(cur) ==
14261 			WXS_ATTRUSE_DECL_NAME(bcur)) &&
14262 			(WXS_ATTRUSE_DECL_TNS(cur) ==
14263 			WXS_ATTRUSE_DECL_TNS(bcur))) {
14264 			found = 1;
14265 			break;
14266 		    }
14267 		}
14268 	    }
14269 	    if (!found) {
14270 		xmlChar *strA = NULL, *strB = NULL;
14271 
14272 		xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14273 		    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
14274 		    NULL, item,
14275 		    "A matching attribute use for the "
14276 		    "'required' %s of the %s %s is missing",
14277 		    xmlSchemaGetComponentDesignation(&strA, bcur),
14278 		    WXS_ACTION_STR(action),
14279 		    xmlSchemaGetComponentDesignation(&strB, baseItem),
14280 		    NULL);
14281 		FREE_AND_NULL(strA);
14282 		FREE_AND_NULL(strB);
14283 	    }
14284 	}
14285     }
14286     /*
14287     * derivation-ok-restriction (4)
14288     */
14289     if (wild != NULL) {
14290 	/*
14291 	* (4) "If there is an {attribute wildcard}, all of the
14292 	* following must be true:"
14293 	*/
14294 	if (baseWild == NULL) {
14295 	    xmlChar *str = NULL;
14296 
14297 	    /*
14298 	    * (4.1) "The {base type definition} must also have one."
14299 	    */
14300 	    xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14301 		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
14302 		NULL, item,
14303 		"The %s has an attribute wildcard, "
14304 		"but the %s %s '%s' does not have one",
14305 		WXS_ITEM_TYPE_NAME(item),
14306 		WXS_ACTION_STR(action),
14307 		WXS_ITEM_TYPE_NAME(baseItem),
14308 		xmlSchemaGetComponentQName(&str, baseItem));
14309 	    FREE_AND_NULL(str);
14310 	    return(pctxt->err);
14311 	} else if ((baseWild->any == 0) &&
14312 		xmlSchemaCheckCOSNSSubset(wild, baseWild))
14313 	{
14314 	    xmlChar *str = NULL;
14315 	    /*
14316 	    * (4.2) "The complex type definition's {attribute wildcard}'s
14317 	    * {namespace constraint} must be a subset of the {base type
14318 	    * definition}'s {attribute wildcard}'s {namespace constraint},
14319 	    * as defined by Wildcard Subset ($3.10.6)."
14320 	    */
14321 	    xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14322 		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
14323 		NULL, item,
14324 		"The attribute wildcard is not a valid "
14325 		"subset of the wildcard in the %s %s '%s'",
14326 		WXS_ACTION_STR(action),
14327 		WXS_ITEM_TYPE_NAME(baseItem),
14328 		xmlSchemaGetComponentQName(&str, baseItem),
14329 		NULL);
14330 	    FREE_AND_NULL(str);
14331 	    return(pctxt->err);
14332 	}
14333 	/* 4.3 Unless the {base type definition} is the `ur-type
14334 	* definition`, the complex type definition's {attribute
14335 	* wildcard}'s {process contents} must be identical to or
14336 	* stronger than the {base type definition}'s {attribute
14337 	* wildcard}'s {process contents}, where strict is stronger
14338 	* than lax is stronger than skip.
14339 	*/
14340 	if ((! WXS_IS_ANYTYPE(baseItem)) &&
14341 	    (wild->processContents < baseWild->processContents)) {
14342 	    xmlChar *str = NULL;
14343 	    xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14344 		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
14345 		NULL, baseItem,
14346 		"The {process contents} of the attribute wildcard is "
14347 		"weaker than the one in the %s %s '%s'",
14348 		WXS_ACTION_STR(action),
14349 		WXS_ITEM_TYPE_NAME(baseItem),
14350 		xmlSchemaGetComponentQName(&str, baseItem),
14351 		NULL);
14352 	    FREE_AND_NULL(str)
14353 		return(pctxt->err);
14354 	}
14355     }
14356     return(0);
14357 }
14358 
14359 
14360 static int
14361 xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
14362 				  xmlSchemaBasicItemPtr item,
14363 				  xmlSchemaWildcardPtr *completeWild,
14364 				  xmlSchemaItemListPtr list,
14365 				  xmlSchemaItemListPtr prohibs);
14366 /**
14367  * xmlSchemaFixupTypeAttributeUses:
14368  * @ctxt:  the schema parser context
14369  * @type:  the complex type definition
14370  *
14371  *
14372  * Builds the wildcard and the attribute uses on the given complex type.
14373  * Returns -1 if an internal error occurs, 0 otherwise.
14374  *
14375  * ATTENTION TODO: Experimentally this uses pointer comparisons for
14376  * strings, so recheck this if we start to hardcode some schemata, since
14377  * they might not be in the same dict.
14378  * NOTE: It is allowed to "extend" the xs:anyType type.
14379  */
14380 static int
xmlSchemaFixupTypeAttributeUses(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)14381 xmlSchemaFixupTypeAttributeUses(xmlSchemaParserCtxtPtr pctxt,
14382 				  xmlSchemaTypePtr type)
14383 {
14384     xmlSchemaTypePtr baseType = NULL;
14385     xmlSchemaAttributeUsePtr use;
14386     xmlSchemaItemListPtr uses, baseUses, prohibs = NULL;
14387 
14388     if (type->baseType == NULL) {
14389 	PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14390 	    "no base type");
14391         return (-1);
14392     }
14393     baseType = type->baseType;
14394     if (WXS_IS_TYPE_NOT_FIXED(baseType))
14395 	if (xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt) == -1)
14396 	    return(-1);
14397 
14398     uses = type->attrUses;
14399     baseUses = baseType->attrUses;
14400     /*
14401     * Expand attribute group references. And build the 'complete'
14402     * wildcard, i.e. intersect multiple wildcards.
14403     * Move attribute prohibitions into a separate list.
14404     */
14405     if (uses != NULL) {
14406 	if (WXS_IS_RESTRICTION(type)) {
14407 	    /*
14408 	    * This one will transfer all attr. prohibitions
14409 	    * into pctxt->attrProhibs.
14410 	    */
14411 	    if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14412 		WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14413 		pctxt->attrProhibs) == -1)
14414 	    {
14415 		PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14416 		"failed to expand attributes");
14417                 return(-1);
14418 	    }
14419 	    if (pctxt->attrProhibs->nbItems != 0)
14420 		prohibs = pctxt->attrProhibs;
14421 	} else {
14422 	    if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14423 		WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14424 		NULL) == -1)
14425 	    {
14426 		PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14427 		"failed to expand attributes");
14428                 return(-1);
14429 	    }
14430 	}
14431     }
14432     /*
14433     * Inherit the attribute uses of the base type.
14434     */
14435     if (baseUses != NULL) {
14436 	int i, j;
14437 	xmlSchemaAttributeUseProhibPtr pro;
14438 
14439 	if (WXS_IS_RESTRICTION(type)) {
14440 	    int usesCount;
14441 	    xmlSchemaAttributeUsePtr tmp;
14442 
14443 	    if (uses != NULL)
14444 		usesCount = uses->nbItems;
14445 	    else
14446 		usesCount = 0;
14447 
14448 	    /* Restriction. */
14449 	    for (i = 0; i < baseUses->nbItems; i++) {
14450 		use = baseUses->items[i];
14451 		if (prohibs) {
14452 		    /*
14453 		    * Filter out prohibited uses.
14454 		    */
14455 		    for (j = 0; j < prohibs->nbItems; j++) {
14456 			pro = prohibs->items[j];
14457 			if ((WXS_ATTRUSE_DECL_NAME(use) == pro->name) &&
14458 			    (WXS_ATTRUSE_DECL_TNS(use) ==
14459 				pro->targetNamespace))
14460 			{
14461 			    goto inherit_next;
14462 			}
14463 		    }
14464 		}
14465 		if (usesCount) {
14466 		    /*
14467 		    * Filter out existing uses.
14468 		    */
14469 		    for (j = 0; j < usesCount; j++) {
14470 			tmp = uses->items[j];
14471 			if ((WXS_ATTRUSE_DECL_NAME(use) ==
14472 				WXS_ATTRUSE_DECL_NAME(tmp)) &&
14473 			    (WXS_ATTRUSE_DECL_TNS(use) ==
14474 				WXS_ATTRUSE_DECL_TNS(tmp)))
14475 			{
14476 			    goto inherit_next;
14477 			}
14478 		    }
14479 		}
14480 		if (uses == NULL) {
14481 		    type->attrUses = xmlSchemaItemListCreate();
14482 		    if (type->attrUses == NULL)
14483 			goto exit_failure;
14484 		    uses = type->attrUses;
14485 		}
14486 		xmlSchemaItemListAddSize(uses, 2, use);
14487 inherit_next: {}
14488 	    }
14489 	} else {
14490 	    /* Extension. */
14491 	    for (i = 0; i < baseUses->nbItems; i++) {
14492 		use = baseUses->items[i];
14493 		if (uses == NULL) {
14494 		    type->attrUses = xmlSchemaItemListCreate();
14495 		    if (type->attrUses == NULL)
14496 			goto exit_failure;
14497 		    uses = type->attrUses;
14498 		}
14499 		xmlSchemaItemListAddSize(uses, baseUses->nbItems, use);
14500 	    }
14501 	}
14502     }
14503     /*
14504     * Shrink attr. uses.
14505     */
14506     if (uses) {
14507 	if (uses->nbItems == 0) {
14508 	    xmlSchemaItemListFree(uses);
14509 	    type->attrUses = NULL;
14510 	}
14511 	/*
14512 	* TODO: We could shrink the size of the array
14513 	* to fit the actual number of items.
14514 	*/
14515     }
14516     /*
14517     * Compute the complete wildcard.
14518     */
14519     if (WXS_IS_EXTENSION(type)) {
14520 	if (baseType->attributeWildcard != NULL) {
14521 	    /*
14522 	    * (3.2.2.1) "If the `base wildcard` is non-`absent`, then
14523 	    * the appropriate case among the following:"
14524 	    */
14525 	    if (type->attributeWildcard != NULL) {
14526 		/*
14527 		* Union the complete wildcard with the base wildcard.
14528 		* SPEC {attribute wildcard}
14529 		* (3.2.2.1.2) "otherwise a wildcard whose {process contents}
14530 		* and {annotation} are those of the `complete wildcard`,
14531 		* and whose {namespace constraint} is the intensional union
14532 		* of the {namespace constraint} of the `complete wildcard`
14533 		* and of the `base wildcard`, as defined in Attribute
14534 		* Wildcard Union ($3.10.6)."
14535 		*/
14536 		if (xmlSchemaUnionWildcards(pctxt, type->attributeWildcard,
14537 		    baseType->attributeWildcard) == -1)
14538 		    goto exit_failure;
14539 	    } else {
14540 		/*
14541 		* (3.2.2.1.1) "If the `complete wildcard` is `absent`,
14542 		* then the `base wildcard`."
14543 		*/
14544 		type->attributeWildcard = baseType->attributeWildcard;
14545 	    }
14546 	} else {
14547 	    /*
14548 	    * (3.2.2.2) "otherwise (the `base wildcard` is `absent`) the
14549 	    * `complete wildcard`"
14550 	    * NOOP
14551 	    */
14552 	}
14553     } else {
14554 	/*
14555 	* SPEC {attribute wildcard}
14556 	* (3.1) "If the <restriction> alternative is chosen, then the
14557 	* `complete wildcard`;"
14558 	* NOOP
14559 	*/
14560     }
14561 
14562     return (0);
14563 
14564 exit_failure:
14565     return(-1);
14566 }
14567 
14568 /**
14569  * xmlSchemaTypeFinalContains:
14570  * @schema:  the schema
14571  * @type:  the type definition
14572  * @final: the final
14573  *
14574  * Evaluates if a type definition contains the given "final".
14575  * This does take "finalDefault" into account as well.
14576  *
14577  * Returns 1 if the type does contain the given "final",
14578  * 0 otherwise.
14579  */
14580 static int
xmlSchemaTypeFinalContains(xmlSchemaTypePtr type,int final)14581 xmlSchemaTypeFinalContains(xmlSchemaTypePtr type, int final)
14582 {
14583     if (type == NULL)
14584 	return (0);
14585     if (type->flags & final)
14586 	return (1);
14587     else
14588 	return (0);
14589 }
14590 
14591 /**
14592  * xmlSchemaGetUnionSimpleTypeMemberTypes:
14593  * @type:  the Union Simple Type
14594  *
14595  * Returns a list of member types of @type if existing,
14596  * returns NULL otherwise.
14597  */
14598 static xmlSchemaTypeLinkPtr
xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)14599 xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
14600 {
14601     while ((type != NULL) && (type->type == XML_SCHEMA_TYPE_SIMPLE)) {
14602 	if (type->memberTypes != NULL)
14603 	    return (type->memberTypes);
14604 	else
14605 	    type = type->baseType;
14606     }
14607     return (NULL);
14608 }
14609 
14610 #if 0
14611 /**
14612  * xmlSchemaGetParticleTotalRangeMin:
14613  * @particle: the particle
14614  *
14615  * Schema Component Constraint: Effective Total Range
14616  * (all and sequence) + (choice)
14617  *
14618  * Returns the minimum Effective Total Range.
14619  */
14620 static int
14621 xmlSchemaGetParticleTotalRangeMin(xmlSchemaParticlePtr particle)
14622 {
14623     if ((particle->children == NULL) ||
14624 	(particle->minOccurs == 0))
14625 	return (0);
14626     if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14627 	int min = -1, cur;
14628 	xmlSchemaParticlePtr part =
14629 	    (xmlSchemaParticlePtr) particle->children->children;
14630 
14631 	if (part == NULL)
14632 	    return (0);
14633 	while (part != NULL) {
14634 	    if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14635 		(part->children->type == XML_SCHEMA_TYPE_ANY))
14636 		cur = part->minOccurs;
14637 	    else
14638 		cur = xmlSchemaGetParticleTotalRangeMin(part);
14639 	    if (cur == 0)
14640 		return (0);
14641 	    if ((min > cur) || (min == -1))
14642 		min = cur;
14643 	    part = (xmlSchemaParticlePtr) part->next;
14644 	}
14645 	return (particle->minOccurs * min);
14646     } else {
14647 	/* <all> and <sequence> */
14648 	int sum = 0;
14649 	xmlSchemaParticlePtr part =
14650 	    (xmlSchemaParticlePtr) particle->children->children;
14651 
14652 	if (part == NULL)
14653 	    return (0);
14654 	do {
14655 	    if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14656 		(part->children->type == XML_SCHEMA_TYPE_ANY))
14657 		sum += part->minOccurs;
14658 	    else
14659 		sum += xmlSchemaGetParticleTotalRangeMin(part);
14660 	    part = (xmlSchemaParticlePtr) part->next;
14661 	} while (part != NULL);
14662 	return (particle->minOccurs * sum);
14663     }
14664 }
14665 
14666 /**
14667  * xmlSchemaGetParticleTotalRangeMax:
14668  * @particle: the particle
14669  *
14670  * Schema Component Constraint: Effective Total Range
14671  * (all and sequence) + (choice)
14672  *
14673  * Returns the maximum Effective Total Range.
14674  */
14675 static int
14676 xmlSchemaGetParticleTotalRangeMax(xmlSchemaParticlePtr particle)
14677 {
14678     if ((particle->children == NULL) ||
14679 	(particle->children->children == NULL))
14680 	return (0);
14681     if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14682 	int max = -1, cur;
14683 	xmlSchemaParticlePtr part =
14684 	    (xmlSchemaParticlePtr) particle->children->children;
14685 
14686 	for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14687 	    if (part->children == NULL)
14688 		continue;
14689 	    if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14690 		(part->children->type == XML_SCHEMA_TYPE_ANY))
14691 		cur = part->maxOccurs;
14692 	    else
14693 		cur = xmlSchemaGetParticleTotalRangeMax(part);
14694 	    if (cur == UNBOUNDED)
14695 		return (UNBOUNDED);
14696 	    if ((max < cur) || (max == -1))
14697 		max = cur;
14698 	}
14699 	/* TODO: Handle overflows? */
14700 	return (particle->maxOccurs * max);
14701     } else {
14702 	/* <all> and <sequence> */
14703 	int sum = 0, cur;
14704 	xmlSchemaParticlePtr part =
14705 	    (xmlSchemaParticlePtr) particle->children->children;
14706 
14707 	for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14708 	    if (part->children == NULL)
14709 		continue;
14710 	    if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14711 		(part->children->type == XML_SCHEMA_TYPE_ANY))
14712 		cur = part->maxOccurs;
14713 	    else
14714 		cur = xmlSchemaGetParticleTotalRangeMax(part);
14715 	    if (cur == UNBOUNDED)
14716 		return (UNBOUNDED);
14717 	    if ((cur > 0) && (particle->maxOccurs == UNBOUNDED))
14718 		return (UNBOUNDED);
14719 	    sum += cur;
14720 	}
14721 	/* TODO: Handle overflows? */
14722 	return (particle->maxOccurs * sum);
14723     }
14724 }
14725 #endif
14726 
14727 /**
14728  * xmlSchemaGetParticleEmptiable:
14729  * @particle: the particle
14730  *
14731  * Returns 1 if emptiable, 0 otherwise.
14732  */
14733 static int
xmlSchemaGetParticleEmptiable(xmlSchemaParticlePtr particle)14734 xmlSchemaGetParticleEmptiable(xmlSchemaParticlePtr particle)
14735 {
14736     xmlSchemaParticlePtr part;
14737     int emptiable;
14738 
14739     if ((particle->children == NULL) || (particle->minOccurs == 0))
14740 	return (1);
14741 
14742     part = (xmlSchemaParticlePtr) particle->children->children;
14743     if (part == NULL)
14744         return (1);
14745 
14746     while (part != NULL) {
14747         if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14748             (part->children->type == XML_SCHEMA_TYPE_ANY))
14749             emptiable = (part->minOccurs == 0);
14750         else
14751             emptiable = xmlSchemaGetParticleEmptiable(part);
14752         if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14753             if (emptiable)
14754                 return (1);
14755         } else {
14756 	    /* <all> and <sequence> */
14757             if (!emptiable)
14758                 return (0);
14759         }
14760         part = (xmlSchemaParticlePtr) part->next;
14761     }
14762 
14763     if (particle->children->type == XML_SCHEMA_TYPE_CHOICE)
14764         return (0);
14765     else
14766         return (1);
14767 }
14768 
14769 /**
14770  * xmlSchemaIsParticleEmptiable:
14771  * @particle: the particle
14772  *
14773  * Schema Component Constraint: Particle Emptiable
14774  * Checks whether the given particle is emptiable.
14775  *
14776  * Returns 1 if emptiable, 0 otherwise.
14777  */
14778 static int
xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)14779 xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)
14780 {
14781     /*
14782     * SPEC (1) "Its {min occurs} is 0."
14783     */
14784     if ((particle == NULL) || (particle->minOccurs == 0) ||
14785 	(particle->children == NULL))
14786 	return (1);
14787     /*
14788     * SPEC (2) "Its {term} is a group and the minimum part of the
14789     * effective total range of that group, [...] is 0."
14790     */
14791     if (WXS_IS_MODEL_GROUP(particle->children))
14792 	return (xmlSchemaGetParticleEmptiable(particle));
14793     return (0);
14794 }
14795 
14796 /**
14797  * xmlSchemaCheckCOSSTDerivedOK:
14798  * @actxt: a context
14799  * @type:  the derived simple type definition
14800  * @baseType:  the base type definition
14801  * @subset: the subset of ('restriction', etc.)
14802  *
14803  * Schema Component Constraint:
14804  * Type Derivation OK (Simple) (cos-st-derived-OK)
14805  *
14806  * Checks whether @type can be validly
14807  * derived from @baseType.
14808  *
14809  * Returns 0 on success, an positive error code otherwise.
14810  */
14811 static int
xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,xmlSchemaTypePtr type,xmlSchemaTypePtr baseType,int subset)14812 xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
14813 			     xmlSchemaTypePtr type,
14814 			     xmlSchemaTypePtr baseType,
14815 			     int subset)
14816 {
14817     /*
14818     * 1 They are the same type definition.
14819     * TODO: The identity check might have to be more complex than this.
14820     */
14821     if (type == baseType)
14822 	return (0);
14823     /*
14824     * 2.1 restriction is not in the subset, or in the {final}
14825     * of its own {base type definition};
14826     *
14827     * NOTE that this will be used also via "xsi:type".
14828     *
14829     * TODO: Revise this, it looks strange. How can the "type"
14830     * not be fixed or *in* fixing?
14831     */
14832     if (WXS_IS_TYPE_NOT_FIXED(type))
14833 	if (xmlSchemaTypeFixup(type, actxt) == -1)
14834 	    return(-1);
14835     if (WXS_IS_TYPE_NOT_FIXED(baseType))
14836 	if (xmlSchemaTypeFixup(baseType, actxt) == -1)
14837 	    return(-1);
14838     if ((subset & SUBSET_RESTRICTION) ||
14839 	(xmlSchemaTypeFinalContains(type->baseType,
14840 	    XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
14841 	return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
14842     }
14843     /* 2.2 */
14844     if (type->baseType == baseType) {
14845 	/*
14846 	* 2.2.1 D's `base type definition` is B.
14847 	*/
14848 	return (0);
14849     }
14850     /*
14851     * 2.2.2 D's `base type definition` is not the `ur-type definition`
14852     * and is validly derived from B given the subset, as defined by this
14853     * constraint.
14854     */
14855     if ((! WXS_IS_ANYTYPE(type->baseType)) &&
14856 	(xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
14857 	    baseType, subset) == 0)) {
14858 	return (0);
14859     }
14860     /*
14861     * 2.2.3 D's {variety} is list or union and B is the `simple ur-type
14862     * definition`.
14863     */
14864     if (WXS_IS_ANY_SIMPLE_TYPE(baseType) &&
14865 	(WXS_IS_LIST(type) || WXS_IS_UNION(type))) {
14866 	return (0);
14867     }
14868     /*
14869     * 2.2.4 B's {variety} is union and D is validly derived from a type
14870     * definition in B's {member type definitions} given the subset, as
14871     * defined by this constraint.
14872     *
14873     * NOTE: This seems not to involve built-in types, since there is no
14874     * built-in Union Simple Type.
14875     */
14876     if (WXS_IS_UNION(baseType)) {
14877 	xmlSchemaTypeLinkPtr cur;
14878 
14879 	cur = baseType->memberTypes;
14880 	while (cur != NULL) {
14881 	    if (WXS_IS_TYPE_NOT_FIXED(cur->type))
14882 		if (xmlSchemaTypeFixup(cur->type, actxt) == -1)
14883 		    return(-1);
14884 	    if (xmlSchemaCheckCOSSTDerivedOK(actxt,
14885 		    type, cur->type, subset) == 0)
14886 	    {
14887 		/*
14888 		* It just has to be validly derived from at least one
14889 		* member-type.
14890 		*/
14891 		return (0);
14892 	    }
14893 	    cur = cur->next;
14894 	}
14895     }
14896     return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
14897 }
14898 
14899 /**
14900  * xmlSchemaCheckTypeDefCircularInternal:
14901  * @pctxt:  the schema parser context
14902  * @ctxtType:  the type definition
14903  * @ancestor: an ancestor of @ctxtType
14904  *
14905  * Checks st-props-correct (2) + ct-props-correct (3).
14906  * Circular type definitions are not allowed.
14907  *
14908  * Returns XML_SCHEMAP_ST_PROPS_CORRECT_2 if the given type is
14909  * circular, 0 otherwise.
14910  */
14911 static int
xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr ctxtType,xmlSchemaTypePtr ancestor)14912 xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,
14913 			   xmlSchemaTypePtr ctxtType,
14914 			   xmlSchemaTypePtr ancestor)
14915 {
14916     int ret;
14917 
14918     if ((ancestor == NULL) || (ancestor->type == XML_SCHEMA_TYPE_BASIC))
14919 	return (0);
14920 
14921     if (ctxtType == ancestor) {
14922 	xmlSchemaPCustomErr(pctxt,
14923 	    XML_SCHEMAP_ST_PROPS_CORRECT_2,
14924 	    WXS_BASIC_CAST ctxtType, WXS_ITEM_NODE(ctxtType),
14925 	    "The definition is circular", NULL);
14926 	return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
14927     }
14928     if (ancestor->flags & XML_SCHEMAS_TYPE_MARKED) {
14929 	/*
14930 	* Avoid infinite recursion on circular types not yet checked.
14931 	*/
14932 	return (0);
14933     }
14934     ancestor->flags |= XML_SCHEMAS_TYPE_MARKED;
14935     ret = xmlSchemaCheckTypeDefCircularInternal(pctxt, ctxtType,
14936 	ancestor->baseType);
14937     ancestor->flags ^= XML_SCHEMAS_TYPE_MARKED;
14938     return (ret);
14939 }
14940 
14941 /**
14942  * xmlSchemaCheckTypeDefCircular:
14943  * @item:  the complex/simple type definition
14944  * @ctxt:  the parser context
14945  * @name:  the name
14946  *
14947  * Checks for circular type definitions.
14948  */
14949 static void
xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,xmlSchemaParserCtxtPtr ctxt)14950 xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,
14951 			      xmlSchemaParserCtxtPtr ctxt)
14952 {
14953     if ((item == NULL) ||
14954 	(item->type == XML_SCHEMA_TYPE_BASIC) ||
14955 	(item->baseType == NULL))
14956 	return;
14957     xmlSchemaCheckTypeDefCircularInternal(ctxt, item,
14958 	item->baseType);
14959 }
14960 
14961 /*
14962 * Simple Type Definition Representation OK (src-simple-type) 4
14963 *
14964 * "4 Circular union type definition is disallowed. That is, if the
14965 * <union> alternative is chosen, there must not be any entries in the
14966 * memberTypes [attribute] at any depth which resolve to the component
14967 * corresponding to the <simpleType>."
14968 *
14969 * Note that this should work on the *representation* of a component,
14970 * thus assumes any union types in the member types not being yet
14971 * substituted. At this stage we need the variety of the types
14972 * to be already computed.
14973 */
14974 static int
xmlSchemaCheckUnionTypeDefCircularRecur(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr ctxType,xmlSchemaTypeLinkPtr members)14975 xmlSchemaCheckUnionTypeDefCircularRecur(xmlSchemaParserCtxtPtr pctxt,
14976 					xmlSchemaTypePtr ctxType,
14977 					xmlSchemaTypeLinkPtr members)
14978 {
14979     xmlSchemaTypeLinkPtr member;
14980     xmlSchemaTypePtr memberType;
14981 
14982     member = members;
14983     while (member != NULL) {
14984 	memberType = member->type;
14985 	while ((memberType != NULL) &&
14986 	    (memberType->type != XML_SCHEMA_TYPE_BASIC)) {
14987 	    if (memberType == ctxType) {
14988 		xmlSchemaPCustomErr(pctxt,
14989 		    XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
14990 		    WXS_BASIC_CAST ctxType, NULL,
14991 		    "The union type definition is circular", NULL);
14992 		return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
14993 	    }
14994 	    if ((WXS_IS_UNION(memberType)) &&
14995 		((memberType->flags & XML_SCHEMAS_TYPE_MARKED) == 0))
14996 	    {
14997 		int res;
14998 		memberType->flags |= XML_SCHEMAS_TYPE_MARKED;
14999 		res = xmlSchemaCheckUnionTypeDefCircularRecur(pctxt,
15000 		    ctxType,
15001 		    xmlSchemaGetUnionSimpleTypeMemberTypes(memberType));
15002 		memberType->flags ^= XML_SCHEMAS_TYPE_MARKED;
15003 		if (res != 0)
15004 		    return(res);
15005 	    }
15006 	    memberType = memberType->baseType;
15007 	}
15008 	member = member->next;
15009     }
15010     return(0);
15011 }
15012 
15013 static int
xmlSchemaCheckUnionTypeDefCircular(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)15014 xmlSchemaCheckUnionTypeDefCircular(xmlSchemaParserCtxtPtr pctxt,
15015 				   xmlSchemaTypePtr type)
15016 {
15017     if (! WXS_IS_UNION(type))
15018 	return(0);
15019     return(xmlSchemaCheckUnionTypeDefCircularRecur(pctxt, type,
15020 	type->memberTypes));
15021 }
15022 
15023 /**
15024  * xmlSchemaResolveTypeReferences:
15025  * @item:  the complex/simple type definition
15026  * @ctxt:  the parser context
15027  * @name:  the name
15028  *
15029  * Resolves type definition references
15030  */
15031 static void
xmlSchemaResolveTypeReferences(xmlSchemaTypePtr typeDef,xmlSchemaParserCtxtPtr ctxt)15032 xmlSchemaResolveTypeReferences(xmlSchemaTypePtr typeDef,
15033 			 xmlSchemaParserCtxtPtr ctxt)
15034 {
15035     if (typeDef == NULL)
15036 	return;
15037 
15038     /*
15039     * Resolve the base type.
15040     */
15041     if (typeDef->baseType == NULL) {
15042 	typeDef->baseType = xmlSchemaGetType(ctxt->schema,
15043 	    typeDef->base, typeDef->baseNs);
15044 	if (typeDef->baseType == NULL) {
15045 	    xmlSchemaPResCompAttrErr(ctxt,
15046 		XML_SCHEMAP_SRC_RESOLVE,
15047 		WXS_BASIC_CAST typeDef, typeDef->node,
15048 		"base", typeDef->base, typeDef->baseNs,
15049 		XML_SCHEMA_TYPE_SIMPLE, NULL);
15050 	    return;
15051 	}
15052     }
15053     if (WXS_IS_SIMPLE(typeDef)) {
15054 	if (WXS_IS_UNION(typeDef)) {
15055 	    /*
15056 	    * Resolve the memberTypes.
15057 	    */
15058 	    xmlSchemaResolveUnionMemberTypes(ctxt, typeDef);
15059 	    return;
15060 	} else if (WXS_IS_LIST(typeDef)) {
15061 	    /*
15062 	    * Resolve the itemType.
15063 	    */
15064 	    if ((typeDef->subtypes == NULL) && (typeDef->base != NULL)) {
15065 
15066 		typeDef->subtypes = xmlSchemaGetType(ctxt->schema,
15067 		    typeDef->base, typeDef->baseNs);
15068 
15069 		if ((typeDef->subtypes == NULL) ||
15070 		    (! WXS_IS_SIMPLE(typeDef->subtypes)))
15071 		{
15072 		    typeDef->subtypes = NULL;
15073 		    xmlSchemaPResCompAttrErr(ctxt,
15074 			XML_SCHEMAP_SRC_RESOLVE,
15075 			WXS_BASIC_CAST typeDef, typeDef->node,
15076 			"itemType", typeDef->base, typeDef->baseNs,
15077 			XML_SCHEMA_TYPE_SIMPLE, NULL);
15078 		}
15079 	    }
15080 	    return;
15081 	}
15082     }
15083     /*
15084     * The ball of letters below means, that if we have a particle
15085     * which has a QName-helper component as its {term}, we want
15086     * to resolve it...
15087     */
15088     else if ((WXS_TYPE_CONTENTTYPE(typeDef) != NULL) &&
15089 	((WXS_TYPE_CONTENTTYPE(typeDef))->type ==
15090 	    XML_SCHEMA_TYPE_PARTICLE) &&
15091 	(WXS_TYPE_PARTICLE_TERM(typeDef) != NULL) &&
15092 	((WXS_TYPE_PARTICLE_TERM(typeDef))->type ==
15093 	    XML_SCHEMA_EXTRA_QNAMEREF))
15094     {
15095 	xmlSchemaQNameRefPtr ref =
15096 	    WXS_QNAME_CAST WXS_TYPE_PARTICLE_TERM(typeDef);
15097 	xmlSchemaModelGroupDefPtr groupDef;
15098 
15099 	/*
15100 	* URGENT TODO: Test this.
15101 	*/
15102 	WXS_TYPE_PARTICLE_TERM(typeDef) = NULL;
15103 	/*
15104 	* Resolve the MG definition reference.
15105 	*/
15106 	groupDef =
15107 	    WXS_MODEL_GROUPDEF_CAST xmlSchemaGetNamedComponent(ctxt->schema,
15108 		ref->itemType, ref->name, ref->targetNamespace);
15109 	if (groupDef == NULL) {
15110 	    xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
15111 		NULL, WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)),
15112 		"ref", ref->name, ref->targetNamespace, ref->itemType,
15113 		NULL);
15114 	    /* Remove the particle. */
15115 	    WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
15116 	} else if (WXS_MODELGROUPDEF_MODEL(groupDef) == NULL)
15117 	    /* Remove the particle. */
15118 	    WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
15119 	else {
15120 	    /*
15121 	    * Assign the MG definition's {model group} to the
15122 	    * particle's {term}.
15123 	    */
15124 	    WXS_TYPE_PARTICLE_TERM(typeDef) = WXS_MODELGROUPDEF_MODEL(groupDef);
15125 
15126 	    if (WXS_MODELGROUPDEF_MODEL(groupDef)->type == XML_SCHEMA_TYPE_ALL) {
15127 		/*
15128 		* SPEC cos-all-limited (1.2)
15129 		* "1.2 the {term} property of a particle with
15130 		* {max occurs}=1 which is part of a pair which constitutes
15131 		* the {content type} of a complex type definition."
15132 		*/
15133 		if ((WXS_TYPE_PARTICLE(typeDef))->maxOccurs != 1) {
15134 		    xmlSchemaCustomErr(ACTXT_CAST ctxt,
15135 			/* TODO: error code */
15136 			XML_SCHEMAP_COS_ALL_LIMITED,
15137 			WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)), NULL,
15138 			"The particle's {max occurs} must be 1, since the "
15139 			"reference resolves to an 'all' model group",
15140 			NULL, NULL);
15141 		}
15142 	    }
15143 	}
15144     }
15145 }
15146 
15147 
15148 
15149 /**
15150  * xmlSchemaCheckSTPropsCorrect:
15151  * @ctxt:  the schema parser context
15152  * @type:  the simple type definition
15153  *
15154  * Checks st-props-correct.
15155  *
15156  * Returns 0 if the properties are correct,
15157  * if not, a positive error code and -1 on internal
15158  * errors.
15159  */
15160 static int
xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,xmlSchemaTypePtr type)15161 xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
15162 			     xmlSchemaTypePtr type)
15163 {
15164     xmlSchemaTypePtr baseType = type->baseType;
15165     xmlChar *str = NULL;
15166 
15167     /* STATE: error funcs converted. */
15168     /*
15169     * Schema Component Constraint: Simple Type Definition Properties Correct
15170     *
15171     * NOTE: This is somehow redundant, since we actually built a simple type
15172     * to have all the needed information; this acts as an self test.
15173     */
15174     /* Base type: If the datatype has been `derived` by `restriction`
15175     * then the Simple Type Definition component from which it is `derived`,
15176     * otherwise the Simple Type Definition for anySimpleType ($4.1.6).
15177     */
15178     if (baseType == NULL) {
15179 	/*
15180 	* TODO: Think about: "modulo the impact of Missing
15181 	* Sub-components ($5.3)."
15182 	*/
15183 	xmlSchemaPCustomErr(ctxt,
15184 	    XML_SCHEMAP_ST_PROPS_CORRECT_1,
15185 	    WXS_BASIC_CAST type, NULL,
15186 	    "No base type existent", NULL);
15187 	return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15188 
15189     }
15190     if (! WXS_IS_SIMPLE(baseType)) {
15191 	xmlSchemaPCustomErr(ctxt,
15192 	    XML_SCHEMAP_ST_PROPS_CORRECT_1,
15193 	    WXS_BASIC_CAST type, NULL,
15194 	    "The base type '%s' is not a simple type",
15195 	    xmlSchemaGetComponentQName(&str, baseType));
15196 	FREE_AND_NULL(str)
15197 	return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15198     }
15199     if ((WXS_IS_LIST(type) || WXS_IS_UNION(type)) &&
15200 	(WXS_IS_RESTRICTION(type) == 0) &&
15201 	((! WXS_IS_ANY_SIMPLE_TYPE(baseType)) &&
15202          (baseType->type != XML_SCHEMA_TYPE_SIMPLE))) {
15203 	xmlSchemaPCustomErr(ctxt,
15204 	    XML_SCHEMAP_ST_PROPS_CORRECT_1,
15205 	    WXS_BASIC_CAST type, NULL,
15206 	    "A type, derived by list or union, must have "
15207 	    "the simple ur-type definition as base type, not '%s'",
15208 	    xmlSchemaGetComponentQName(&str, baseType));
15209 	FREE_AND_NULL(str)
15210 	return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15211     }
15212     /*
15213     * Variety: One of {atomic, list, union}.
15214     */
15215     if ((! WXS_IS_ATOMIC(type)) && (! WXS_IS_UNION(type)) &&
15216 	(! WXS_IS_LIST(type))) {
15217 	xmlSchemaPCustomErr(ctxt,
15218 	    XML_SCHEMAP_ST_PROPS_CORRECT_1,
15219 	    WXS_BASIC_CAST type, NULL,
15220 	    "The variety is absent", NULL);
15221 	return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15222     }
15223     /* TODO: Finish this. Hmm, is this finished? */
15224 
15225     /*
15226     * 3 The {final} of the {base type definition} must not contain restriction.
15227     */
15228     if (xmlSchemaTypeFinalContains(baseType,
15229 	XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15230 	xmlSchemaPCustomErr(ctxt,
15231 	    XML_SCHEMAP_ST_PROPS_CORRECT_3,
15232 	    WXS_BASIC_CAST type, NULL,
15233 	    "The 'final' of its base type '%s' must not contain "
15234 	    "'restriction'",
15235 	    xmlSchemaGetComponentQName(&str, baseType));
15236 	FREE_AND_NULL(str)
15237 	return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
15238     }
15239 
15240     /*
15241     * 2 All simple type definitions must be derived ultimately from the `simple
15242     * ur-type definition` (so circular definitions are disallowed). That is, it
15243     * must be possible to reach a built-in primitive datatype or the `simple
15244     * ur-type definition` by repeatedly following the {base type definition}.
15245     *
15246     * NOTE: this is done in xmlSchemaCheckTypeDefCircular().
15247     */
15248     return (0);
15249 }
15250 
15251 /**
15252  * xmlSchemaCheckCOSSTRestricts:
15253  * @ctxt:  the schema parser context
15254  * @type:  the simple type definition
15255  *
15256  * Schema Component Constraint:
15257  * Derivation Valid (Restriction, Simple) (cos-st-restricts)
15258 
15259  * Checks if the given @type (simpleType) is derived validly by restriction.
15260  * STATUS:
15261  *
15262  * Returns -1 on internal errors, 0 if the type is validly derived,
15263  * a positive error code otherwise.
15264  */
15265 static int
xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)15266 xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt,
15267 			     xmlSchemaTypePtr type)
15268 {
15269     xmlChar *str = NULL;
15270 
15271     if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
15272 	PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15273 	    "given type is not a user-derived simpleType");
15274 	return (-1);
15275     }
15276 
15277     if (WXS_IS_ATOMIC(type)) {
15278 	xmlSchemaTypePtr primitive;
15279 	/*
15280 	* 1.1 The {base type definition} must be an atomic simple
15281 	* type definition or a built-in primitive datatype.
15282 	*/
15283 	if (! WXS_IS_ATOMIC(type->baseType)) {
15284 	    xmlSchemaPCustomErr(pctxt,
15285 		XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
15286 		WXS_BASIC_CAST type, NULL,
15287 		"The base type '%s' is not an atomic simple type",
15288 		xmlSchemaGetComponentQName(&str, type->baseType));
15289 	    FREE_AND_NULL(str)
15290 	    return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
15291 	}
15292 	/* 1.2 The {final} of the {base type definition} must not contain
15293 	* restriction.
15294 	*/
15295 	/* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
15296 	if (xmlSchemaTypeFinalContains(type->baseType,
15297 	    XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15298 	    xmlSchemaPCustomErr(pctxt,
15299 		XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
15300 		WXS_BASIC_CAST type, NULL,
15301 		"The final of its base type '%s' must not contain 'restriction'",
15302 		xmlSchemaGetComponentQName(&str, type->baseType));
15303 	    FREE_AND_NULL(str)
15304 	    return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
15305 	}
15306 
15307 	/*
15308 	* 1.3.1 DF must be an allowed constraining facet for the {primitive
15309 	* type definition}, as specified in the appropriate subsection of 3.2
15310 	* Primitive datatypes.
15311 	*/
15312 	if (type->facets != NULL) {
15313 	    xmlSchemaFacetPtr facet;
15314 	    int ok = 1;
15315 
15316 	    primitive = xmlSchemaGetPrimitiveType(type);
15317 	    if (primitive == NULL) {
15318 		PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15319 		    "failed to get primitive type");
15320 		return (-1);
15321 	    }
15322 	    facet = type->facets;
15323 	    do {
15324 		if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
15325 		    ok = 0;
15326 		    xmlSchemaPIllegalFacetAtomicErr(pctxt,
15327 			XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
15328 			type, primitive, facet);
15329 		}
15330 		facet = facet->next;
15331 	    } while (facet != NULL);
15332 	    if (ok == 0)
15333 		return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
15334 	}
15335 	/*
15336 	* SPEC (1.3.2) "If there is a facet of the same kind in the {facets}
15337 	* of the {base type definition} (call this BF),then the DF's {value}
15338 	* must be a valid restriction of BF's {value} as defined in
15339 	* [XML Schemas: Datatypes]."
15340 	*
15341 	* NOTE (1.3.2) Facet derivation constraints are currently handled in
15342 	* xmlSchemaDeriveAndValidateFacets()
15343 	*/
15344     } else if (WXS_IS_LIST(type)) {
15345 	xmlSchemaTypePtr itemType = NULL;
15346 
15347 	itemType = type->subtypes;
15348 	if ((itemType == NULL) || (! WXS_IS_SIMPLE(itemType))) {
15349 	    PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15350 		"failed to evaluate the item type");
15351 	    return (-1);
15352 	}
15353 	if (WXS_IS_TYPE_NOT_FIXED(itemType))
15354 	    xmlSchemaTypeFixup(itemType, ACTXT_CAST pctxt);
15355 	/*
15356 	* 2.1 The {item type definition} must have a {variety} of atomic or
15357 	* union (in which case all the {member type definitions}
15358 	* must be atomic).
15359 	*/
15360 	if ((! WXS_IS_ATOMIC(itemType)) &&
15361 	    (! WXS_IS_UNION(itemType))) {
15362 	    xmlSchemaPCustomErr(pctxt,
15363 		XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
15364 		WXS_BASIC_CAST type, NULL,
15365 		"The item type '%s' does not have a variety of atomic or union",
15366 		xmlSchemaGetComponentQName(&str, itemType));
15367 	    FREE_AND_NULL(str)
15368 	    return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
15369 	} else if (WXS_IS_UNION(itemType)) {
15370 	    xmlSchemaTypeLinkPtr member;
15371 
15372 	    member = itemType->memberTypes;
15373 	    while (member != NULL) {
15374 		if (! WXS_IS_ATOMIC(member->type)) {
15375 		    xmlSchemaPCustomErr(pctxt,
15376 			XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
15377 			WXS_BASIC_CAST type, NULL,
15378 			"The item type is a union type, but the "
15379 			"member type '%s' of this item type is not atomic",
15380 			xmlSchemaGetComponentQName(&str, member->type));
15381 		    FREE_AND_NULL(str)
15382 		    return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
15383 		}
15384 		member = member->next;
15385 	    }
15386 	}
15387 
15388 	if (WXS_IS_ANY_SIMPLE_TYPE(type->baseType)) {
15389 	    xmlSchemaFacetPtr facet;
15390 	    /*
15391 	    * This is the case if we have: <simpleType><list ..
15392 	    */
15393 	    /*
15394 	    * 2.3.1
15395 	    * 2.3.1.1 The {final} of the {item type definition} must not
15396 	    * contain list.
15397 	    */
15398 	    if (xmlSchemaTypeFinalContains(itemType,
15399 		XML_SCHEMAS_TYPE_FINAL_LIST)) {
15400 		xmlSchemaPCustomErr(pctxt,
15401 		    XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
15402 		    WXS_BASIC_CAST type, NULL,
15403 		    "The final of its item type '%s' must not contain 'list'",
15404 		    xmlSchemaGetComponentQName(&str, itemType));
15405 		FREE_AND_NULL(str)
15406 		return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
15407 	    }
15408 	    /*
15409 	    * 2.3.1.2 The {facets} must only contain the whiteSpace
15410 	    * facet component.
15411 	    * OPTIMIZE TODO: the S4S already disallows any facet
15412 	    * to be specified.
15413 	    */
15414 	    if (type->facets != NULL) {
15415 		facet = type->facets;
15416 		do {
15417 		    if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
15418 			xmlSchemaPIllegalFacetListUnionErr(pctxt,
15419 			    XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
15420 			    type, facet);
15421 			return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
15422 		    }
15423 		    facet = facet->next;
15424 		} while (facet != NULL);
15425 	    }
15426 	    /*
15427 	    * MAYBE TODO: (Hmm, not really) Datatypes states:
15428 	    * A `list` datatype can be `derived` from an `atomic` datatype
15429 	    * whose `lexical space` allows space (such as string or anyURI)or
15430 	    * a `union` datatype any of whose {member type definitions}'s
15431 	    * `lexical space` allows space.
15432 	    */
15433 	} else {
15434 	    /*
15435 	    * This is the case if we have: <simpleType><restriction ...
15436 	    * I.e. the variety of "list" is inherited.
15437 	    */
15438 	    /*
15439 	    * 2.3.2
15440 	    * 2.3.2.1 The {base type definition} must have a {variety} of list.
15441 	    */
15442 	    if (! WXS_IS_LIST(type->baseType)) {
15443 		xmlSchemaPCustomErr(pctxt,
15444 		    XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
15445 		    WXS_BASIC_CAST type, NULL,
15446 		    "The base type '%s' must be a list type",
15447 		    xmlSchemaGetComponentQName(&str, type->baseType));
15448 		FREE_AND_NULL(str)
15449 		return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
15450 	    }
15451 	    /*
15452 	    * 2.3.2.2 The {final} of the {base type definition} must not
15453 	    * contain restriction.
15454 	    */
15455 	    if (xmlSchemaTypeFinalContains(type->baseType,
15456 		XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15457 		xmlSchemaPCustomErr(pctxt,
15458 		    XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
15459 		    WXS_BASIC_CAST type, NULL,
15460 		    "The 'final' of the base type '%s' must not contain 'restriction'",
15461 		    xmlSchemaGetComponentQName(&str, type->baseType));
15462 		FREE_AND_NULL(str)
15463 		return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
15464 	    }
15465 	    /*
15466 	    * 2.3.2.3 The {item type definition} must be validly derived
15467 	    * from the {base type definition}'s {item type definition} given
15468 	    * the empty set, as defined in Type Derivation OK (Simple) ($3.14.6).
15469 	    */
15470 	    {
15471 		xmlSchemaTypePtr baseItemType;
15472 
15473 		baseItemType = type->baseType->subtypes;
15474 		if ((baseItemType == NULL) || (! WXS_IS_SIMPLE(baseItemType))) {
15475 		    PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15476 			"failed to eval the item type of a base type");
15477 		    return (-1);
15478 		}
15479 		if ((itemType != baseItemType) &&
15480 		    (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt, itemType,
15481 			baseItemType, 0) != 0)) {
15482 		    xmlChar *strBIT = NULL, *strBT = NULL;
15483 		    xmlSchemaPCustomErrExt(pctxt,
15484 			XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
15485 			WXS_BASIC_CAST type, NULL,
15486 			"The item type '%s' is not validly derived from "
15487 			"the item type '%s' of the base type '%s'",
15488 			xmlSchemaGetComponentQName(&str, itemType),
15489 			xmlSchemaGetComponentQName(&strBIT, baseItemType),
15490 			xmlSchemaGetComponentQName(&strBT, type->baseType));
15491 
15492 		    FREE_AND_NULL(str)
15493 		    FREE_AND_NULL(strBIT)
15494 		    FREE_AND_NULL(strBT)
15495 		    return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
15496 		}
15497 	    }
15498 
15499 	    if (type->facets != NULL) {
15500 		xmlSchemaFacetPtr facet;
15501 		int ok = 1;
15502 		/*
15503 		* 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
15504 		* and enumeration facet components are allowed among the {facets}.
15505 		*/
15506 		facet = type->facets;
15507 		do {
15508 		    switch (facet->type) {
15509 			case XML_SCHEMA_FACET_LENGTH:
15510 			case XML_SCHEMA_FACET_MINLENGTH:
15511 			case XML_SCHEMA_FACET_MAXLENGTH:
15512 			case XML_SCHEMA_FACET_WHITESPACE:
15513 			    /*
15514 			    * TODO: 2.5.1.2 List datatypes
15515 			    * The value of `whiteSpace` is fixed to the value collapse.
15516 			    */
15517 			case XML_SCHEMA_FACET_PATTERN:
15518 			case XML_SCHEMA_FACET_ENUMERATION:
15519 			    break;
15520 			default: {
15521 			    xmlSchemaPIllegalFacetListUnionErr(pctxt,
15522 				XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
15523 				type, facet);
15524 			    /*
15525 			    * We could return, but it's nicer to report all
15526 			    * invalid facets.
15527 			    */
15528 			    ok = 0;
15529 			}
15530 		    }
15531 		    facet = facet->next;
15532 		} while (facet != NULL);
15533 		if (ok == 0)
15534 		    return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
15535 		/*
15536 		* SPEC (2.3.2.5) (same as 1.3.2)
15537 		*
15538 		* NOTE (2.3.2.5) This is currently done in
15539 		* xmlSchemaDeriveAndValidateFacets()
15540 		*/
15541 	    }
15542 	}
15543     } else if (WXS_IS_UNION(type)) {
15544 	/*
15545 	* 3.1 The {member type definitions} must all have {variety} of
15546 	* atomic or list.
15547 	*/
15548 	xmlSchemaTypeLinkPtr member;
15549 
15550 	member = type->memberTypes;
15551 	while (member != NULL) {
15552 	    if (WXS_IS_TYPE_NOT_FIXED(member->type))
15553 		xmlSchemaTypeFixup(member->type, ACTXT_CAST pctxt);
15554 
15555 	    if ((! WXS_IS_ATOMIC(member->type)) &&
15556 		(! WXS_IS_LIST(member->type))) {
15557 		xmlSchemaPCustomErr(pctxt,
15558 		    XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
15559 		    WXS_BASIC_CAST type, NULL,
15560 		    "The member type '%s' is neither an atomic, nor a list type",
15561 		    xmlSchemaGetComponentQName(&str, member->type));
15562 		FREE_AND_NULL(str)
15563 		return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
15564 	    }
15565 	    member = member->next;
15566 	}
15567 	/*
15568 	* 3.3.1 If the {base type definition} is the `simple ur-type
15569 	* definition`
15570 	*/
15571 	if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) {
15572 	    /*
15573 	    * 3.3.1.1 All of the {member type definitions} must have a
15574 	    * {final} which does not contain union.
15575 	    */
15576 	    member = type->memberTypes;
15577 	    while (member != NULL) {
15578 		if (xmlSchemaTypeFinalContains(member->type,
15579 		    XML_SCHEMAS_TYPE_FINAL_UNION)) {
15580 		    xmlSchemaPCustomErr(pctxt,
15581 			XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
15582 			WXS_BASIC_CAST type, NULL,
15583 			"The 'final' of member type '%s' contains 'union'",
15584 			xmlSchemaGetComponentQName(&str, member->type));
15585 		    FREE_AND_NULL(str)
15586 		    return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
15587 		}
15588 		member = member->next;
15589 	    }
15590 	    /*
15591 	    * 3.3.1.2 The {facets} must be empty.
15592 	    */
15593 	    if (type->facetSet != NULL) {
15594 		xmlSchemaPCustomErr(pctxt,
15595 		    XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
15596 		    WXS_BASIC_CAST type, NULL,
15597 		    "No facets allowed", NULL);
15598 		return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
15599 	    }
15600 	} else {
15601 	    /*
15602 	    * 3.3.2.1 The {base type definition} must have a {variety} of union.
15603 	    * I.e. the variety of "list" is inherited.
15604 	    */
15605 	    if (! WXS_IS_UNION(type->baseType)) {
15606 		xmlSchemaPCustomErr(pctxt,
15607 		    XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
15608 		    WXS_BASIC_CAST type, NULL,
15609 		    "The base type '%s' is not a union type",
15610 		    xmlSchemaGetComponentQName(&str, type->baseType));
15611 		FREE_AND_NULL(str)
15612 		return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
15613 	    }
15614 	    /*
15615 	    * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
15616 	    */
15617 	    if (xmlSchemaTypeFinalContains(type->baseType,
15618 		XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15619 		xmlSchemaPCustomErr(pctxt,
15620 		    XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
15621 		    WXS_BASIC_CAST type, NULL,
15622 		    "The 'final' of its base type '%s' must not contain 'restriction'",
15623 		    xmlSchemaGetComponentQName(&str, type->baseType));
15624 		FREE_AND_NULL(str)
15625 		return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
15626 	    }
15627 	    /*
15628 	    * 3.3.2.3 The {member type definitions}, in order, must be validly
15629 	    * derived from the corresponding type definitions in the {base
15630 	    * type definition}'s {member type definitions} given the empty set,
15631 	    * as defined in Type Derivation OK (Simple) ($3.14.6).
15632 	    */
15633 	    {
15634 		xmlSchemaTypeLinkPtr baseMember;
15635 
15636 		/*
15637 		* OPTIMIZE: if the type is restricting, it has no local defined
15638 		* member types and inherits the member types of the base type;
15639 		* thus a check for equality can be skipped.
15640 		*/
15641 		/*
15642 		* Even worse: I cannot see a scenario where a restricting
15643 		* union simple type can have other member types as the member
15644 		* types of it's base type. This check seems not necessary with
15645 		* respect to the derivation process in libxml2.
15646 		* But necessary if constructing types with an API.
15647 		*/
15648 		if (type->memberTypes != NULL) {
15649 		    member = type->memberTypes;
15650 		    baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
15651 		    if ((member == NULL) && (baseMember != NULL)) {
15652 			PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15653 			    "different number of member types in base");
15654 		    }
15655 		    while (member != NULL) {
15656 			if (baseMember == NULL) {
15657 			    PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15658 			    "different number of member types in base");
15659 			} else if ((member->type != baseMember->type) &&
15660 			    (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
15661 				member->type, baseMember->type, 0) != 0)) {
15662 			    xmlChar *strBMT = NULL, *strBT = NULL;
15663 
15664 			    xmlSchemaPCustomErrExt(pctxt,
15665 				XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
15666 				WXS_BASIC_CAST type, NULL,
15667 				"The member type %s is not validly "
15668 				"derived from its corresponding member "
15669 				"type %s of the base type %s",
15670 				xmlSchemaGetComponentQName(&str, member->type),
15671 				xmlSchemaGetComponentQName(&strBMT, baseMember->type),
15672 				xmlSchemaGetComponentQName(&strBT, type->baseType));
15673 			    FREE_AND_NULL(str)
15674 			    FREE_AND_NULL(strBMT)
15675 			    FREE_AND_NULL(strBT)
15676 			    return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
15677 			}
15678 			member = member->next;
15679                         if (baseMember != NULL)
15680                             baseMember = baseMember->next;
15681 		    }
15682 		}
15683 	    }
15684 	    /*
15685 	    * 3.3.2.4 Only pattern and enumeration facet components are
15686 	    * allowed among the {facets}.
15687 	    */
15688 	    if (type->facets != NULL) {
15689 		xmlSchemaFacetPtr facet;
15690 		int ok = 1;
15691 
15692 		facet = type->facets;
15693 		do {
15694 		    if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
15695 			(facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
15696 			xmlSchemaPIllegalFacetListUnionErr(pctxt,
15697 				XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
15698 				type, facet);
15699 			ok = 0;
15700 		    }
15701 		    facet = facet->next;
15702 		} while (facet != NULL);
15703 		if (ok == 0)
15704 		    return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
15705 
15706 	    }
15707 	    /*
15708 	    * SPEC (3.3.2.5) (same as 1.3.2)
15709 	    *
15710 	    * NOTE (3.3.2.5) This is currently done in
15711 	    * xmlSchemaDeriveAndValidateFacets()
15712 	    */
15713 	}
15714     }
15715 
15716     return (0);
15717 }
15718 
15719 /**
15720  * xmlSchemaCheckSRCSimpleType:
15721  * @ctxt:  the schema parser context
15722  * @type:  the simple type definition
15723  *
15724  * Checks crc-simple-type constraints.
15725  *
15726  * Returns 0 if the constraints are satisfied,
15727  * if not a positive error code and -1 on internal
15728  * errors.
15729  */
15730 #if 0
15731 static int
15732 xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
15733 			    xmlSchemaTypePtr type)
15734 {
15735     /*
15736     * src-simple-type.1 The corresponding simple type definition, if any,
15737     * must satisfy the conditions set out in Constraints on Simple Type
15738     * Definition Schema Components ($3.14.6).
15739     */
15740     if (WXS_IS_RESTRICTION(type)) {
15741 	/*
15742 	* src-simple-type.2 "If the <restriction> alternative is chosen,
15743 	* either it must have a base [attribute] or a <simpleType> among its
15744 	* [children], but not both."
15745 	* NOTE: This is checked in the parse function of <restriction>.
15746 	*/
15747 	/*
15748 	*
15749 	*/
15750     } else if (WXS_IS_LIST(type)) {
15751 	/* src-simple-type.3 "If the <list> alternative is chosen, either it must have
15752 	* an itemType [attribute] or a <simpleType> among its [children],
15753 	* but not both."
15754 	*
15755 	* NOTE: This is checked in the parse function of <list>.
15756 	*/
15757     } else if (WXS_IS_UNION(type)) {
15758 	/*
15759 	* src-simple-type.4 is checked in xmlSchemaCheckUnionTypeDefCircular().
15760 	*/
15761     }
15762     return (0);
15763 }
15764 #endif
15765 
15766 static int
xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)15767 xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
15768 {
15769    if (ctxt->vctxt == NULL) {
15770 	ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
15771 	if (ctxt->vctxt == NULL) {
15772 	    xmlSchemaPErr(ctxt, NULL,
15773 		XML_SCHEMAP_INTERNAL,
15774 		"Internal error: xmlSchemaCreateVCtxtOnPCtxt, "
15775 		"failed to create a temp. validation context.\n",
15776 		NULL, NULL);
15777 	    return (-1);
15778 	}
15779 	/* TODO: Pass user data. */
15780 	xmlSchemaSetValidErrors(ctxt->vctxt,
15781 	    ctxt->error, ctxt->warning, ctxt->errCtxt);
15782 	xmlSchemaSetValidStructuredErrors(ctxt->vctxt,
15783 	    ctxt->serror, ctxt->errCtxt);
15784     }
15785     return (0);
15786 }
15787 
15788 static int
15789 xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
15790 			     xmlNodePtr node,
15791 			     xmlSchemaTypePtr type,
15792 			     const xmlChar *value,
15793 			     xmlSchemaValPtr *retVal,
15794 			     int fireErrors,
15795 			     int normalize,
15796 			     int isNormalized);
15797 
15798 /**
15799  * xmlSchemaParseCheckCOSValidDefault:
15800  * @pctxt:  the schema parser context
15801  * @type:  the simple type definition
15802  * @value: the default value
15803  * @node: an optional node (the holder of the value)
15804  *
15805  * Schema Component Constraint: Element Default Valid (Immediate)
15806  * (cos-valid-default)
15807  * This will be used by the parser only. For the validator there's
15808  * an other version.
15809  *
15810  * Returns 0 if the constraints are satisfied,
15811  * if not, a positive error code and -1 on internal
15812  * errors.
15813  */
15814 static int
xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,xmlNodePtr node,xmlSchemaTypePtr type,const xmlChar * value,xmlSchemaValPtr * val)15815 xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
15816 				   xmlNodePtr node,
15817 				   xmlSchemaTypePtr type,
15818 				   const xmlChar *value,
15819 				   xmlSchemaValPtr *val)
15820 {
15821     int ret = 0;
15822 
15823     /*
15824     * cos-valid-default:
15825     * Schema Component Constraint: Element Default Valid (Immediate)
15826     * For a string to be a valid default with respect to a type
15827     * definition the appropriate case among the following must be true:
15828     */
15829     if WXS_IS_COMPLEX(type) {
15830 	/*
15831 	* Complex type.
15832 	*
15833 	* SPEC (2.1) "its {content type} must be a simple type definition
15834 	* or mixed."
15835 	* SPEC (2.2.2) "If the {content type} is mixed, then the {content
15836 	* type}'s particle must be `emptiable` as defined by
15837 	* Particle Emptiable ($3.9.6)."
15838 	*/
15839 	if ((! WXS_HAS_SIMPLE_CONTENT(type)) &&
15840 	    ((! WXS_HAS_MIXED_CONTENT(type)) || (! WXS_EMPTIABLE(type)))) {
15841 	    /* NOTE that this covers (2.2.2) as well. */
15842 	    xmlSchemaPCustomErr(pctxt,
15843 		XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
15844 		WXS_BASIC_CAST type, type->node,
15845 		"For a string to be a valid default, the type definition "
15846 		"must be a simple type or a complex type with mixed content "
15847 		"and a particle emptiable", NULL);
15848 	    return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
15849 	}
15850     }
15851     /*
15852     * 1 If the type definition is a simple type definition, then the string
15853     * must be `valid` with respect to that definition as defined by String
15854     * Valid ($3.14.4).
15855     *
15856     * AND
15857     *
15858     * 2.2.1 If the {content type} is a simple type definition, then the
15859     * string must be `valid` with respect to that simple type definition
15860     * as defined by String Valid ($3.14.4).
15861     */
15862     if (WXS_IS_SIMPLE(type))
15863 	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
15864 	    type, value, val, 1, 1, 0);
15865     else if (WXS_HAS_SIMPLE_CONTENT(type))
15866 	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
15867 	    type->contentTypeDef, value, val, 1, 1, 0);
15868     else
15869 	return (ret);
15870 
15871     if (ret < 0) {
15872 	PERROR_INT("xmlSchemaParseCheckCOSValidDefault",
15873 	    "calling xmlSchemaVCheckCVCSimpleType()");
15874     }
15875 
15876     return (ret);
15877 }
15878 
15879 /**
15880  * xmlSchemaCheckCTPropsCorrect:
15881  * @ctxt:  the schema parser context
15882  * @type:  the complex type definition
15883  *
15884  *.(4.6) Constraints on Complex Type Definition Schema Components
15885  * Schema Component Constraint:
15886  * Complex Type Definition Properties Correct (ct-props-correct)
15887  * STATUS: (seems) complete
15888  *
15889  * Returns 0 if the constraints are satisfied, a positive
15890  * error code if not and -1 if an internal error occurred.
15891  */
15892 static int
xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)15893 xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
15894 			     xmlSchemaTypePtr type)
15895 {
15896     /*
15897     * TODO: Correct the error code; XML_SCHEMAP_SRC_CT_1 is used temporarily.
15898     *
15899     * SPEC (1) "The values of the properties of a complex type definition must
15900     * be as described in the property tableau in The Complex Type Definition
15901     * Schema Component ($3.4.1), modulo the impact of Missing
15902     * Sub-components ($5.3)."
15903     */
15904     if ((type->baseType != NULL) &&
15905 	(WXS_IS_SIMPLE(type->baseType)) &&
15906 	(WXS_IS_EXTENSION(type) == 0)) {
15907 	/*
15908 	* SPEC (2) "If the {base type definition} is a simple type definition,
15909 	* the {derivation method} must be extension."
15910 	*/
15911 	xmlSchemaCustomErr(ACTXT_CAST pctxt,
15912 	    XML_SCHEMAP_SRC_CT_1,
15913 	    NULL, WXS_BASIC_CAST type,
15914 	    "If the base type is a simple type, the derivation method must be "
15915 	    "'extension'", NULL, NULL);
15916 	return (XML_SCHEMAP_SRC_CT_1);
15917     }
15918     /*
15919     * SPEC (3) "Circular definitions are disallowed, except for the `ur-type
15920     * definition`. That is, it must be possible to reach the `ur-type
15921     * definition` by repeatedly following the {base type definition}."
15922     *
15923     * NOTE (3) is done in xmlSchemaCheckTypeDefCircular().
15924     */
15925     /*
15926     * NOTE that (4) and (5) need the following:
15927     *   - attribute uses need to be already inherited (apply attr. prohibitions)
15928     *   - attribute group references need to be expanded already
15929     *   - simple types need to be typefixed already
15930     */
15931     if (type->attrUses &&
15932 	(((xmlSchemaItemListPtr) type->attrUses)->nbItems > 1))
15933     {
15934 	xmlSchemaItemListPtr uses = (xmlSchemaItemListPtr) type->attrUses;
15935 	xmlSchemaAttributeUsePtr use, tmp;
15936 	int i, j, hasId = 0;
15937 
15938 	for (i = uses->nbItems -1; i >= 0; i--) {
15939 	    use = uses->items[i];
15940 
15941 	    /*
15942 	    * SPEC ct-props-correct
15943 	    * (4) "Two distinct attribute declarations in the
15944 	    * {attribute uses} must not have identical {name}s and
15945 	    * {target namespace}s."
15946 	    */
15947 	    if (i > 0) {
15948 		for (j = i -1; j >= 0; j--) {
15949 		    tmp = uses->items[j];
15950 		    if ((WXS_ATTRUSE_DECL_NAME(use) ==
15951 			WXS_ATTRUSE_DECL_NAME(tmp)) &&
15952 			(WXS_ATTRUSE_DECL_TNS(use) ==
15953 			WXS_ATTRUSE_DECL_TNS(tmp)))
15954 		    {
15955 			xmlChar *str = NULL;
15956 
15957 			xmlSchemaCustomErr(ACTXT_CAST pctxt,
15958 			    XML_SCHEMAP_AG_PROPS_CORRECT,
15959 			    NULL, WXS_BASIC_CAST type,
15960 			    "Duplicate %s",
15961 			    xmlSchemaGetComponentDesignation(&str, use),
15962 			    NULL);
15963 			FREE_AND_NULL(str);
15964 			/*
15965 			* Remove the duplicate.
15966 			*/
15967 			if (xmlSchemaItemListRemove(uses, i) == -1)
15968 			    goto exit_failure;
15969 			goto next_use;
15970 		    }
15971 		}
15972 	    }
15973 	    /*
15974 	    * SPEC ct-props-correct
15975 	    * (5) "Two distinct attribute declarations in the
15976 	    * {attribute uses} must not have {type definition}s which
15977 	    * are or are derived from ID."
15978 	    */
15979 	    if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
15980 		if (xmlSchemaIsDerivedFromBuiltInType(
15981 		    WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
15982 		{
15983 		    if (hasId) {
15984 			xmlChar *str = NULL;
15985 
15986 			xmlSchemaCustomErr(ACTXT_CAST pctxt,
15987 			    XML_SCHEMAP_AG_PROPS_CORRECT,
15988 			    NULL, WXS_BASIC_CAST type,
15989 			    "There must not exist more than one attribute "
15990 			    "declaration of type 'xs:ID' "
15991 			    "(or derived from 'xs:ID'). The %s violates this "
15992 			    "constraint",
15993 			    xmlSchemaGetComponentDesignation(&str, use),
15994 			    NULL);
15995 			FREE_AND_NULL(str);
15996 			if (xmlSchemaItemListRemove(uses, i) == -1)
15997 			    goto exit_failure;
15998 		    }
15999 
16000 		    hasId = 1;
16001 		}
16002 	    }
16003 next_use: {}
16004 	}
16005     }
16006     return (0);
16007 exit_failure:
16008     return(-1);
16009 }
16010 
16011 static int
xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,xmlSchemaTypePtr typeB)16012 xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,
16013 		       xmlSchemaTypePtr typeB)
16014 {
16015     /*
16016     * TODO: This should implement component-identity
16017     * in the future.
16018     */
16019     if ((typeA == NULL) || (typeB == NULL))
16020 	return (0);
16021     return (typeA == typeB);
16022 }
16023 
16024 /**
16025  * xmlSchemaCheckCOSCTDerivedOK:
16026  * @ctxt:  the schema parser context
16027  * @type:  the to-be derived complex type definition
16028  * @baseType:  the base complex type definition
16029  * @set: the given set
16030  *
16031  * Schema Component Constraint:
16032  * Type Derivation OK (Complex) (cos-ct-derived-ok)
16033  *
16034  * STATUS: completed
16035  *
16036  * Returns 0 if the constraints are satisfied, or 1
16037  * if not.
16038  */
16039 static int
xmlSchemaCheckCOSCTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,xmlSchemaTypePtr type,xmlSchemaTypePtr baseType,int set)16040 xmlSchemaCheckCOSCTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
16041 			     xmlSchemaTypePtr type,
16042 			     xmlSchemaTypePtr baseType,
16043 			     int set)
16044 {
16045     int equal = xmlSchemaAreEqualTypes(type, baseType);
16046     /* TODO: Error codes. */
16047     /*
16048     * SPEC "For a complex type definition (call it D, for derived)
16049     * to be validly derived from a type definition (call this
16050     * B, for base) given a subset of {extension, restriction}
16051     * all of the following must be true:"
16052     */
16053     if (! equal) {
16054 	/*
16055 	* SPEC (1) "If B and D are not the same type definition, then the
16056 	* {derivation method} of D must not be in the subset."
16057 	*/
16058 	if (((set & SUBSET_EXTENSION) && (WXS_IS_EXTENSION(type))) ||
16059 	    ((set & SUBSET_RESTRICTION) && (WXS_IS_RESTRICTION(type))))
16060 	    return (1);
16061     } else {
16062 	/*
16063 	* SPEC (2.1) "B and D must be the same type definition."
16064 	*/
16065 	return (0);
16066     }
16067     /*
16068     * SPEC (2.2) "B must be D's {base type definition}."
16069     */
16070     if (type->baseType == baseType)
16071 	return (0);
16072     /*
16073     * SPEC (2.3.1) "D's {base type definition} must not be the `ur-type
16074     * definition`."
16075     */
16076     if (WXS_IS_ANYTYPE(type->baseType))
16077 	return (1);
16078 
16079     if (WXS_IS_COMPLEX(type->baseType)) {
16080 	/*
16081 	* SPEC (2.3.2.1) "If D's {base type definition} is complex, then it
16082 	* must be validly derived from B given the subset as defined by this
16083 	* constraint."
16084 	*/
16085 	return (xmlSchemaCheckCOSCTDerivedOK(actxt, type->baseType,
16086 	    baseType, set));
16087     } else {
16088 	/*
16089 	* SPEC (2.3.2.2) "If D's {base type definition} is simple, then it
16090 	* must be validly derived from B given the subset as defined in Type
16091 	* Derivation OK (Simple) ($3.14.6).
16092 	*/
16093 	return (xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
16094 	    baseType, set));
16095     }
16096 }
16097 
16098 /**
16099  * xmlSchemaCheckCOSDerivedOK:
16100  * @type:  the derived simple type definition
16101  * @baseType:  the base type definition
16102  *
16103  * Calls:
16104  * Type Derivation OK (Simple) AND Type Derivation OK (Complex)
16105  *
16106  * Checks whether @type can be validly derived from @baseType.
16107  *
16108  * Returns 0 on success, an positive error code otherwise.
16109  */
16110 static int
xmlSchemaCheckCOSDerivedOK(xmlSchemaAbstractCtxtPtr actxt,xmlSchemaTypePtr type,xmlSchemaTypePtr baseType,int set)16111 xmlSchemaCheckCOSDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
16112 			   xmlSchemaTypePtr type,
16113 			   xmlSchemaTypePtr baseType,
16114 			   int set)
16115 {
16116     if (WXS_IS_SIMPLE(type))
16117 	return (xmlSchemaCheckCOSSTDerivedOK(actxt, type, baseType, set));
16118     else
16119 	return (xmlSchemaCheckCOSCTDerivedOK(actxt, type, baseType, set));
16120 }
16121 
16122 /**
16123  * xmlSchemaCheckCOSCTExtends:
16124  * @ctxt:  the schema parser context
16125  * @type:  the complex type definition
16126  *
16127  * (3.4.6) Constraints on Complex Type Definition Schema Components
16128  * Schema Component Constraint:
16129  * Derivation Valid (Extension) (cos-ct-extends)
16130  *
16131  * STATUS:
16132  *   missing:
16133  *     (1.5)
16134  *     (1.4.3.2.2.2) "Particle Valid (Extension)"
16135  *
16136  * Returns 0 if the constraints are satisfied, a positive
16137  * error code if not and -1 if an internal error occurred.
16138  */
16139 static int
xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,xmlSchemaTypePtr type)16140 xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
16141 			   xmlSchemaTypePtr type)
16142 {
16143     xmlSchemaTypePtr base = type->baseType;
16144     /*
16145     * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
16146     * temporarily only.
16147     */
16148     /*
16149     * SPEC (1) "If the {base type definition} is a complex type definition,
16150     * then all of the following must be true:"
16151     */
16152     if (WXS_IS_COMPLEX(base)) {
16153 	/*
16154 	* SPEC (1.1) "The {final} of the {base type definition} must not
16155 	* contain extension."
16156 	*/
16157 	if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16158 	    xmlSchemaPCustomErr(ctxt,
16159 		XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16160 		WXS_BASIC_CAST type, NULL,
16161 		"The 'final' of the base type definition "
16162 		"contains 'extension'", NULL);
16163 	    return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16164 	}
16165 
16166 	/*
16167 	* ATTENTION: The constrains (1.2) and (1.3) are not applied,
16168 	* since they are automatically satisfied through the
16169 	* inheriting mechanism.
16170 	* Note that even if redefining components, the inheriting mechanism
16171 	* is used.
16172 	*/
16173 #if 0
16174 	/*
16175 	* SPEC (1.2) "Its {attribute uses} must be a subset of the {attribute
16176 	* uses}
16177 	* of the complex type definition itself, that is, for every attribute
16178 	* use in the {attribute uses} of the {base type definition}, there
16179 	* must be an attribute use in the {attribute uses} of the complex
16180 	* type definition itself whose {attribute declaration} has the same
16181 	* {name}, {target namespace} and {type definition} as its attribute
16182 	* declaration"
16183 	*/
16184 	if (base->attrUses != NULL) {
16185 	    int i, j, found;
16186 	    xmlSchemaAttributeUsePtr use, buse;
16187 
16188 	    for (i = 0; i < (WXS_LIST_CAST base->attrUses)->nbItems; i ++) {
16189 		buse = (WXS_LIST_CAST base->attrUses)->items[i];
16190 		found = 0;
16191 		if (type->attrUses != NULL) {
16192 		    use = (WXS_LIST_CAST type->attrUses)->items[j];
16193 		    for (j = 0; j < (WXS_LIST_CAST type->attrUses)->nbItems; j ++)
16194 		    {
16195 			if ((WXS_ATTRUSE_DECL_NAME(use) ==
16196 				WXS_ATTRUSE_DECL_NAME(buse)) &&
16197 			    (WXS_ATTRUSE_DECL_TNS(use) ==
16198 				WXS_ATTRUSE_DECL_TNS(buse)) &&
16199 			    (WXS_ATTRUSE_TYPEDEF(use) ==
16200 				WXS_ATTRUSE_TYPEDEF(buse))
16201 			{
16202 			    found = 1;
16203 			    break;
16204 			}
16205 		    }
16206 		}
16207 		if (! found) {
16208 		    xmlChar *str = NULL;
16209 
16210 		    xmlSchemaCustomErr(ACTXT_CAST ctxt,
16211 			XML_SCHEMAP_COS_CT_EXTENDS_1_2,
16212 			NULL, WXS_BASIC_CAST type,
16213 			/*
16214 			* TODO: The report does not indicate that also the
16215 			* type needs to be the same.
16216 			*/
16217 			"This type is missing a matching correspondent "
16218 			"for its {base type}'s %s in its {attribute uses}",
16219 			xmlSchemaGetComponentDesignation(&str,
16220 			    buse->children),
16221 			NULL);
16222 		    FREE_AND_NULL(str)
16223 		}
16224 	    }
16225 	}
16226 	/*
16227 	* SPEC (1.3) "If it has an {attribute wildcard}, the complex type
16228 	* definition must also have one, and the base type definition's
16229 	* {attribute  wildcard}'s {namespace constraint} must be a subset
16230 	* of the complex  type definition's {attribute wildcard}'s {namespace
16231 	* constraint}, as defined by Wildcard Subset ($3.10.6)."
16232 	*/
16233 
16234 	/*
16235 	* MAYBE TODO: Enable if ever needed. But this will be needed only
16236 	* if created the type via a schema construction API.
16237 	*/
16238 	if (base->attributeWildcard != NULL) {
16239 	    if (type->attributeWildcard == NULL) {
16240 		xmlChar *str = NULL;
16241 
16242 		xmlSchemaCustomErr(ACTXT_CAST pctxt,
16243 		    XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16244 		    NULL, type,
16245 		    "The base %s has an attribute wildcard, "
16246 		    "but this type is missing an attribute wildcard",
16247 		    xmlSchemaGetComponentDesignation(&str, base));
16248 		FREE_AND_NULL(str)
16249 
16250 	    } else if (xmlSchemaCheckCOSNSSubset(
16251 		base->attributeWildcard, type->attributeWildcard))
16252 	    {
16253 		xmlChar *str = NULL;
16254 
16255 		xmlSchemaCustomErr(ACTXT_CAST pctxt,
16256 		    XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16257 		    NULL, type,
16258 		    "The attribute wildcard is not a valid "
16259 		    "superset of the one in the base %s",
16260 		    xmlSchemaGetComponentDesignation(&str, base));
16261 		FREE_AND_NULL(str)
16262 	    }
16263 	}
16264 #endif
16265 	/*
16266 	* SPEC (1.4) "One of the following must be true:"
16267 	*/
16268 	if ((type->contentTypeDef != NULL) &&
16269 	    (type->contentTypeDef == base->contentTypeDef)) {
16270 	    /*
16271 	    * SPEC (1.4.1) "The {content type} of the {base type definition}
16272 	    * and the {content type} of the complex type definition itself
16273 	    * must be the same simple type definition"
16274 	    * PASS
16275 	    */
16276 	} else if ((type->contentType == XML_SCHEMA_CONTENT_EMPTY) &&
16277 	    (base->contentType == XML_SCHEMA_CONTENT_EMPTY) ) {
16278 	    /*
16279 	    * SPEC (1.4.2) "The {content type} of both the {base type
16280 	    * definition} and the complex type definition itself must
16281 	    * be empty."
16282 	    * PASS
16283 	    */
16284 	} else {
16285 	    /*
16286 	    * SPEC (1.4.3) "All of the following must be true:"
16287 	    */
16288 	    if (type->subtypes == NULL) {
16289 		/*
16290 		* SPEC 1.4.3.1 The {content type} of the complex type
16291 		* definition itself must specify a particle.
16292 		*/
16293 		xmlSchemaPCustomErr(ctxt,
16294 		    XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16295 		    WXS_BASIC_CAST type, NULL,
16296 		    "The content type must specify a particle", NULL);
16297 		return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16298 	    }
16299 	    /*
16300 	    * SPEC (1.4.3.2) "One of the following must be true:"
16301 	    */
16302 	    if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16303 		/*
16304 		* SPEC (1.4.3.2.1) "The {content type} of the {base type
16305 		* definition} must be empty.
16306 		* PASS
16307 		*/
16308 	    } else {
16309 		/*
16310 		* SPEC (1.4.3.2.2) "All of the following must be true:"
16311 		*/
16312 		if ((type->contentType != base->contentType) ||
16313 		    ((type->contentType != XML_SCHEMA_CONTENT_MIXED) &&
16314 		    (type->contentType != XML_SCHEMA_CONTENT_ELEMENTS))) {
16315 		    /*
16316 		    * SPEC (1.4.3.2.2.1) "Both {content type}s must be mixed
16317 		    * or both must be element-only."
16318 		    */
16319 		    xmlSchemaPCustomErr(ctxt,
16320 			XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16321 			WXS_BASIC_CAST type, NULL,
16322 			"The content type of both, the type and its base "
16323 			"type, must either 'mixed' or 'element-only'", NULL);
16324 		    return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16325 		}
16326 		/*
16327 		* URGENT TODO SPEC (1.4.3.2.2.2) "The particle of the
16328 		* complex type definition must be a `valid extension`
16329 		* of the {base type definition}'s particle, as defined
16330 		* in Particle Valid (Extension) ($3.9.6)."
16331 		*
16332 		* NOTE that we won't check "Particle Valid (Extension)",
16333 		* since it is ensured by the derivation process in
16334 		* xmlSchemaTypeFixup(). We need to implement this when heading
16335 		* for a construction API
16336 		* TODO: !! This is needed to be checked if redefining a type !!
16337 		*/
16338 	    }
16339 	    /*
16340 	    * URGENT TODO (1.5)
16341 	    */
16342 	}
16343     } else {
16344 	/*
16345 	* SPEC (2) "If the {base type definition} is a simple type definition,
16346 	* then all of the following must be true:"
16347 	*/
16348 	if (type->contentTypeDef != base) {
16349 	    /*
16350 	    * SPEC (2.1) "The {content type} must be the same simple type
16351 	    * definition."
16352 	    */
16353 	    xmlSchemaPCustomErr(ctxt,
16354 		XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16355 		WXS_BASIC_CAST type, NULL,
16356 		"The content type must be the simple base type", NULL);
16357 	    return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16358 	}
16359 	if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16360 	    /*
16361 	    * SPEC (2.2) "The {final} of the {base type definition} must not
16362 	    * contain extension"
16363 	    * NOTE that this is the same as (1.1).
16364 	    */
16365 	    xmlSchemaPCustomErr(ctxt,
16366 		XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16367 		WXS_BASIC_CAST type, NULL,
16368 		"The 'final' of the base type definition "
16369 		"contains 'extension'", NULL);
16370 	    return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16371 	}
16372     }
16373     return (0);
16374 }
16375 
16376 /**
16377  * xmlSchemaCheckDerivationOKRestriction:
16378  * @ctxt:  the schema parser context
16379  * @type:  the complex type definition
16380  *
16381  * (3.4.6) Constraints on Complex Type Definition Schema Components
16382  * Schema Component Constraint:
16383  * Derivation Valid (Restriction, Complex) (derivation-ok-restriction)
16384  *
16385  * STATUS:
16386  *   missing:
16387  *     (5.4.2) ???
16388  *
16389  * ATTENTION:
16390  * In XML Schema 1.1 this will be:
16391  * Validation Rule: Checking complex type subsumption
16392  *
16393  * Returns 0 if the constraints are satisfied, a positive
16394  * error code if not and -1 if an internal error occurred.
16395  */
16396 static int
xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,xmlSchemaTypePtr type)16397 xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,
16398 				      xmlSchemaTypePtr type)
16399 {
16400     xmlSchemaTypePtr base;
16401 
16402     /*
16403     * TODO: Correct the error code; XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1 is used
16404     * temporarily only.
16405     */
16406     base = type->baseType;
16407     if (! WXS_IS_COMPLEX(base)) {
16408 	xmlSchemaCustomErr(ACTXT_CAST ctxt,
16409 	    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16410 	    type->node, WXS_BASIC_CAST type,
16411 	    "The base type must be a complex type", NULL, NULL);
16412 	return(ctxt->err);
16413     }
16414     if (base->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) {
16415 	/*
16416 	* SPEC (1) "The {base type definition} must be a complex type
16417 	* definition whose {final} does not contain restriction."
16418 	*/
16419 	xmlSchemaCustomErr(ACTXT_CAST ctxt,
16420 	    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16421 	    type->node, WXS_BASIC_CAST type,
16422 	    "The 'final' of the base type definition "
16423 	    "contains 'restriction'", NULL, NULL);
16424 	return (ctxt->err);
16425     }
16426     /*
16427     * SPEC (2), (3) and (4)
16428     * Those are handled in a separate function, since the
16429     * same constraints are needed for redefinition of
16430     * attribute groups as well.
16431     */
16432     if (xmlSchemaCheckDerivationOKRestriction2to4(ctxt,
16433 	XML_SCHEMA_ACTION_DERIVE,
16434 	WXS_BASIC_CAST type, WXS_BASIC_CAST base,
16435 	type->attrUses, base->attrUses,
16436 	type->attributeWildcard,
16437 	base->attributeWildcard) == -1)
16438     {
16439 	return(-1);
16440     }
16441     /*
16442     * SPEC (5) "One of the following must be true:"
16443     */
16444     if (base->builtInType == XML_SCHEMAS_ANYTYPE) {
16445 	/*
16446 	* SPEC (5.1) "The {base type definition} must be the
16447 	* `ur-type definition`."
16448 	* PASS
16449 	*/
16450     } else if ((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16451 	    (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16452 	/*
16453 	* SPEC (5.2.1) "The {content type} of the complex type definition
16454 	* must be a simple type definition"
16455 	*
16456 	* SPEC (5.2.2) "One of the following must be true:"
16457 	*/
16458 	if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16459 	    (base->contentType == XML_SCHEMA_CONTENT_BASIC))
16460 	{
16461 	    int err;
16462 	    /*
16463 	    * SPEC (5.2.2.1) "The {content type} of the {base type
16464 	    * definition} must be a simple type definition from which
16465 	    * the {content type} is validly derived given the empty
16466 	    * set as defined in Type Derivation OK (Simple) ($3.14.6)."
16467 	    *
16468 	    * ATTENTION TODO: This seems not needed if the type implicitly
16469 	    * derived from the base type.
16470 	    *
16471 	    */
16472 	    err = xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST ctxt,
16473 		type->contentTypeDef, base->contentTypeDef, 0);
16474 	    if (err != 0) {
16475 		xmlChar *strA = NULL, *strB = NULL;
16476 
16477 		if (err == -1)
16478 		    return(-1);
16479 		xmlSchemaCustomErr(ACTXT_CAST ctxt,
16480 		    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16481 		    NULL, WXS_BASIC_CAST type,
16482 		    "The {content type} %s is not validly derived from the "
16483 		    "base type's {content type} %s",
16484 		    xmlSchemaGetComponentDesignation(&strA,
16485 			type->contentTypeDef),
16486 		    xmlSchemaGetComponentDesignation(&strB,
16487 			base->contentTypeDef));
16488 		FREE_AND_NULL(strA);
16489 		FREE_AND_NULL(strB);
16490 		return(ctxt->err);
16491 	    }
16492 	} else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16493 	    (xmlSchemaIsParticleEmptiable(
16494 		(xmlSchemaParticlePtr) base->subtypes))) {
16495 	    /*
16496 	    * SPEC (5.2.2.2) "The {base type definition} must be mixed
16497 	    * and have a particle which is `emptiable` as defined in
16498 	    * Particle Emptiable ($3.9.6)."
16499 	    * PASS
16500 	    */
16501 	} else {
16502 	    xmlSchemaPCustomErr(ctxt,
16503 		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16504 		WXS_BASIC_CAST type, NULL,
16505 		"The content type of the base type must be either "
16506 		"a simple type or 'mixed' and an emptiable particle", NULL);
16507 	    return (ctxt->err);
16508 	}
16509     } else if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16510 	/*
16511 	* SPEC (5.3.1) "The {content type} of the complex type itself must
16512 	* be empty"
16513 	*/
16514 	if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16515 	    /*
16516 	    * SPEC (5.3.2.1) "The {content type} of the {base type
16517 	    * definition} must also be empty."
16518 	    * PASS
16519 	    */
16520 	} else if (((base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16521 	    (base->contentType == XML_SCHEMA_CONTENT_MIXED)) &&
16522 	    xmlSchemaIsParticleEmptiable(
16523 		(xmlSchemaParticlePtr) base->subtypes)) {
16524 	    /*
16525 	    * SPEC (5.3.2.2) "The {content type} of the {base type
16526 	    * definition} must be elementOnly or mixed and have a particle
16527 	    * which is `emptiable` as defined in 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 		"empty or 'mixed' (or 'elements-only') and an emptiable "
16536 		"particle", NULL);
16537 	    return (ctxt->err);
16538 	}
16539     } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16540 	WXS_HAS_MIXED_CONTENT(type)) {
16541 	/*
16542 	* SPEC (5.4.1.1) "The {content type} of the complex type definition
16543 	* itself must be element-only"
16544 	*/
16545 	if (WXS_HAS_MIXED_CONTENT(type) && (! WXS_HAS_MIXED_CONTENT(base))) {
16546 	    /*
16547 	    * SPEC (5.4.1.2) "The {content type} of the complex type
16548 	    * definition itself and of the {base type definition} must be
16549 	    * mixed"
16550 	    */
16551 	    xmlSchemaPCustomErr(ctxt,
16552 		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16553 		WXS_BASIC_CAST type, NULL,
16554 		"If the content type is 'mixed', then the content type of the "
16555 		"base type must also be 'mixed'", NULL);
16556 	    return (ctxt->err);
16557 	}
16558 	/*
16559 	* SPEC (5.4.2) "The particle of the complex type definition itself
16560 	* must be a `valid restriction` of the particle of the {content
16561 	* type} of the {base type definition} as defined in Particle Valid
16562 	* (Restriction) ($3.9.6).
16563 	*
16564 	* URGENT TODO: (5.4.2)
16565 	*/
16566     } else {
16567 	xmlSchemaPCustomErr(ctxt,
16568 	    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16569 	    WXS_BASIC_CAST type, NULL,
16570 	    "The type is not a valid restriction of its base type", NULL);
16571 	return (ctxt->err);
16572     }
16573     return (0);
16574 }
16575 
16576 /**
16577  * xmlSchemaCheckCTComponent:
16578  * @ctxt:  the schema parser context
16579  * @type:  the complex type definition
16580  *
16581  * (3.4.6) Constraints on Complex Type Definition Schema Components
16582  *
16583  * Returns 0 if the constraints are satisfied, a positive
16584  * error code if not and -1 if an internal error occurred.
16585  */
16586 static int
xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,xmlSchemaTypePtr type)16587 xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,
16588 			  xmlSchemaTypePtr type)
16589 {
16590     int ret;
16591     /*
16592     * Complex Type Definition Properties Correct
16593     */
16594     ret = xmlSchemaCheckCTPropsCorrect(ctxt, type);
16595     if (ret != 0)
16596 	return (ret);
16597     if (WXS_IS_EXTENSION(type))
16598 	ret = xmlSchemaCheckCOSCTExtends(ctxt, type);
16599     else
16600 	ret = xmlSchemaCheckDerivationOKRestriction(ctxt, type);
16601     return (ret);
16602 }
16603 
16604 /**
16605  * xmlSchemaCheckSRCCT:
16606  * @ctxt:  the schema parser context
16607  * @type:  the complex type definition
16608  *
16609  * (3.4.3) Constraints on XML Representations of Complex Type Definitions:
16610  * Schema Representation Constraint:
16611  * Complex Type Definition Representation OK (src-ct)
16612  *
16613  * Returns 0 if the constraints are satisfied, a positive
16614  * error code if not and -1 if an internal error occurred.
16615  */
16616 static int
xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,xmlSchemaTypePtr type)16617 xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
16618 		    xmlSchemaTypePtr type)
16619 {
16620     xmlSchemaTypePtr base;
16621     int ret = 0;
16622 
16623     /*
16624     * TODO: Adjust the error codes here, as I used
16625     * XML_SCHEMAP_SRC_CT_1 only yet.
16626     */
16627     base = type->baseType;
16628     if (! WXS_HAS_SIMPLE_CONTENT(type)) {
16629 	/*
16630 	* 1 If the <complexContent> alternative is chosen, the type definition
16631 	* `resolved` to by the `actual value` of the base [attribute]
16632 	* must be a complex type definition;
16633 	*/
16634 	if (! WXS_IS_COMPLEX(base)) {
16635 	    xmlChar *str = NULL;
16636 	    xmlSchemaPCustomErr(ctxt,
16637 		XML_SCHEMAP_SRC_CT_1,
16638 		WXS_BASIC_CAST type, type->node,
16639 		"If using <complexContent>, the base type is expected to be "
16640 		"a complex type. The base type '%s' is a simple type",
16641 		xmlSchemaFormatQName(&str, base->targetNamespace,
16642 		base->name));
16643 	    FREE_AND_NULL(str)
16644 	    return (XML_SCHEMAP_SRC_CT_1);
16645 	}
16646     } else {
16647 	/*
16648 	* SPEC
16649 	* 2 If the <simpleContent> alternative is chosen, all of the
16650 	* following must be true:
16651 	* 2.1 The type definition `resolved` to by the `actual value` of the
16652 	* base [attribute] must be one of the following:
16653 	*/
16654 	if (WXS_IS_SIMPLE(base)) {
16655 	    if (WXS_IS_EXTENSION(type) == 0) {
16656 		xmlChar *str = NULL;
16657 		/*
16658 		* 2.1.3 only if the <extension> alternative is also
16659 		* chosen, a simple type definition.
16660 		*/
16661 		/* TODO: Change error code to ..._SRC_CT_2_1_3. */
16662 		xmlSchemaPCustomErr(ctxt,
16663 		    XML_SCHEMAP_SRC_CT_1,
16664 		    WXS_BASIC_CAST type, NULL,
16665 		    "If using <simpleContent> and <restriction>, the base "
16666 		    "type must be a complex type. The base type '%s' is "
16667 		    "a simple type",
16668 		    xmlSchemaFormatQName(&str, base->targetNamespace,
16669 			base->name));
16670 		FREE_AND_NULL(str)
16671 		return (XML_SCHEMAP_SRC_CT_1);
16672 	    }
16673 	} else {
16674 	    /* Base type is a complex type. */
16675 	    if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16676 		(base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16677 		/*
16678 		* 2.1.1 a complex type definition whose {content type} is a
16679 		* simple type definition;
16680 		* PASS
16681 		*/
16682 		if (base->contentTypeDef == NULL) {
16683 		    xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
16684 			WXS_BASIC_CAST type, NULL,
16685 			"Internal error: xmlSchemaCheckSRCCT, "
16686 			"'%s', base type has no content type",
16687 			type->name);
16688 		    return (-1);
16689 		}
16690 	    } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16691 		(WXS_IS_RESTRICTION(type))) {
16692 
16693 		/*
16694 		* 2.1.2 only if the <restriction> alternative is also
16695 		* chosen, a complex type definition whose {content type}
16696 		* is mixed and a particle emptiable.
16697 		*/
16698 		if (! xmlSchemaIsParticleEmptiable(
16699 		    (xmlSchemaParticlePtr) base->subtypes)) {
16700 		    ret = XML_SCHEMAP_SRC_CT_1;
16701 		} else
16702 		    /*
16703 		    * Attention: at this point the <simpleType> child is in
16704 		    * ->contentTypeDef (put there during parsing).
16705 		    */
16706 		    if (type->contentTypeDef == NULL) {
16707 		    xmlChar *str = NULL;
16708 		    /*
16709 		    * 2.2 If clause 2.1.2 above is satisfied, then there
16710 		    * must be a <simpleType> among the [children] of
16711 		    * <restriction>.
16712 		    */
16713 		    /* TODO: Change error code to ..._SRC_CT_2_2. */
16714 		    xmlSchemaPCustomErr(ctxt,
16715 			XML_SCHEMAP_SRC_CT_1,
16716 			WXS_BASIC_CAST type, NULL,
16717 			"A <simpleType> is expected among the children "
16718 			"of <restriction>, if <simpleContent> is used and "
16719 			"the base type '%s' is a complex type",
16720 			xmlSchemaFormatQName(&str, base->targetNamespace,
16721 			base->name));
16722 		    FREE_AND_NULL(str)
16723 		    return (XML_SCHEMAP_SRC_CT_1);
16724 		}
16725 	    } else {
16726 		ret = XML_SCHEMAP_SRC_CT_1;
16727 	    }
16728 	}
16729 	if (ret > 0) {
16730 	    xmlChar *str = NULL;
16731 	    if (WXS_IS_RESTRICTION(type)) {
16732 		xmlSchemaPCustomErr(ctxt,
16733 		    XML_SCHEMAP_SRC_CT_1,
16734 		    WXS_BASIC_CAST type, NULL,
16735 		    "If <simpleContent> and <restriction> is used, the "
16736 		    "base type must be a simple type or a complex type with "
16737 		    "mixed content and particle emptiable. The base type "
16738 		    "'%s' is none of those",
16739 		    xmlSchemaFormatQName(&str, base->targetNamespace,
16740 		    base->name));
16741 	    } else {
16742 		xmlSchemaPCustomErr(ctxt,
16743 		    XML_SCHEMAP_SRC_CT_1,
16744 		    WXS_BASIC_CAST type, NULL,
16745 		    "If <simpleContent> and <extension> is used, the "
16746 		    "base type must be a simple type. The base type '%s' "
16747 		    "is a complex type",
16748 		    xmlSchemaFormatQName(&str, base->targetNamespace,
16749 		    base->name));
16750 	    }
16751 	    FREE_AND_NULL(str)
16752 	}
16753     }
16754     /*
16755     * SPEC (3) "The corresponding complex type definition component must
16756     * satisfy the conditions set out in Constraints on Complex Type
16757     * Definition Schema Components ($3.4.6);"
16758     * NOTE (3) will be done in xmlSchemaTypeFixup().
16759     */
16760     /*
16761     * SPEC (4) If clause 2.2.1 or clause 2.2.2 in the correspondence specification
16762     * above for {attribute wildcard} is satisfied, the intensional
16763     * intersection must be expressible, as defined in Attribute Wildcard
16764     * Intersection ($3.10.6).
16765     * NOTE (4) is done in xmlSchemaFixupTypeAttributeUses().
16766     */
16767     return (ret);
16768 }
16769 
16770 #ifdef ENABLE_PARTICLE_RESTRICTION
16771 /**
16772  * xmlSchemaCheckParticleRangeOK:
16773  * @ctxt:  the schema parser context
16774  * @type:  the complex type definition
16775  *
16776  * (3.9.6) Constraints on Particle Schema Components
16777  * Schema Component Constraint:
16778  * Occurrence Range OK (range-ok)
16779  *
16780  * STATUS: complete
16781  *
16782  * Returns 0 if the constraints are satisfied, a positive
16783  * error code if not and -1 if an internal error occurred.
16784  */
16785 static int
xmlSchemaCheckParticleRangeOK(int rmin,int rmax,int bmin,int bmax)16786 xmlSchemaCheckParticleRangeOK(int rmin, int rmax,
16787 			      int bmin, int bmax)
16788 {
16789     if (rmin < bmin)
16790 	return (1);
16791     if ((bmax != UNBOUNDED) &&
16792 	(rmax > bmax))
16793 	return (1);
16794     return (0);
16795 }
16796 
16797 /**
16798  * xmlSchemaCheckRCaseNameAndTypeOK:
16799  * @ctxt:  the schema parser context
16800  * @r: the restricting element declaration particle
16801  * @b: the base element declaration particle
16802  *
16803  * (3.9.6) Constraints on Particle Schema Components
16804  * Schema Component Constraint:
16805  * Particle Restriction OK (Elt:Elt -- NameAndTypeOK)
16806  * (rcase-NameAndTypeOK)
16807  *
16808  * STATUS:
16809  *   MISSING (3.2.3)
16810  *   CLARIFY: (3.2.2)
16811  *
16812  * Returns 0 if the constraints are satisfied, a positive
16813  * error code if not and -1 if an internal error occurred.
16814  */
16815 static int
xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr r,xmlSchemaParticlePtr b)16816 xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,
16817 				 xmlSchemaParticlePtr r,
16818 				 xmlSchemaParticlePtr b)
16819 {
16820     xmlSchemaElementPtr elemR, elemB;
16821 
16822     /* TODO: Error codes (rcase-NameAndTypeOK). */
16823     elemR = (xmlSchemaElementPtr) r->children;
16824     elemB = (xmlSchemaElementPtr) b->children;
16825     /*
16826     * SPEC (1) "The declarations' {name}s and {target namespace}s are
16827     * the same."
16828     */
16829     if ((elemR != elemB) &&
16830 	((! xmlStrEqual(elemR->name, elemB->name)) ||
16831 	(! xmlStrEqual(elemR->targetNamespace, elemB->targetNamespace))))
16832 	return (1);
16833     /*
16834     * SPEC (2) "R's occurrence range is a valid restriction of B's
16835     * occurrence range as defined by Occurrence Range OK ($3.9.6)."
16836     */
16837     if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16838 	    b->minOccurs, b->maxOccurs) != 0)
16839 	return (1);
16840     /*
16841     * SPEC (3.1) "Both B's declaration's {scope} and R's declaration's
16842     * {scope} are global."
16843     */
16844     if (elemR == elemB)
16845 	return (0);
16846     /*
16847     * SPEC (3.2.1) "Either B's {nillable} is true or R's {nillable} is false."
16848     */
16849     if (((elemB->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) &&
16850 	(elemR->flags & XML_SCHEMAS_ELEM_NILLABLE))
16851 	 return (1);
16852     /*
16853     * SPEC (3.2.2) "either B's declaration's {value constraint} is absent,
16854     * or is not fixed, or R's declaration's {value constraint} is fixed
16855     * with the same value."
16856     */
16857     if ((elemB->value != NULL) && (elemB->flags & XML_SCHEMAS_ELEM_FIXED) &&
16858 	((elemR->value == NULL) ||
16859 	 ((elemR->flags & XML_SCHEMAS_ELEM_FIXED) == 0) ||
16860 	 /* TODO: Equality of the initial value or normalized or canonical? */
16861 	 (! xmlStrEqual(elemR->value, elemB->value))))
16862 	 return (1);
16863     /*
16864     * TODO: SPEC (3.2.3) "R's declaration's {identity-constraint
16865     * definitions} is a subset of B's declaration's {identity-constraint
16866     * definitions}, if any."
16867     */
16868     if (elemB->idcs != NULL) {
16869 	/* TODO */
16870     }
16871     /*
16872     * SPEC (3.2.4) "R's declaration's {disallowed substitutions} is a
16873     * superset of B's declaration's {disallowed substitutions}."
16874     */
16875     if (((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) &&
16876 	 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) == 0)) ||
16877 	((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) &&
16878 	 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) == 0)) ||
16879 	((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) &&
16880 	 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) == 0)))
16881 	 return (1);
16882     /*
16883     * SPEC (3.2.5) "R's {type definition} is validly derived given
16884     * {extension, list, union} from B's {type definition}"
16885     *
16886     * BADSPEC TODO: What's the point of adding "list" and "union" to the
16887     * set, if the corresponding constraints handle "restriction" and
16888     * "extension" only?
16889     *
16890     */
16891     {
16892 	int set = 0;
16893 
16894 	set |= SUBSET_EXTENSION;
16895 	set |= SUBSET_LIST;
16896 	set |= SUBSET_UNION;
16897 	if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST ctxt, elemR->subtypes,
16898 	    elemB->subtypes, set) != 0)
16899 	    return (1);
16900     }
16901     return (0);
16902 }
16903 
16904 /**
16905  * xmlSchemaCheckRCaseNSCompat:
16906  * @ctxt:  the schema parser context
16907  * @r: the restricting element declaration particle
16908  * @b: the base wildcard particle
16909  *
16910  * (3.9.6) Constraints on Particle Schema Components
16911  * Schema Component Constraint:
16912  * Particle Derivation OK (Elt:Any -- NSCompat)
16913  * (rcase-NSCompat)
16914  *
16915  * STATUS: complete
16916  *
16917  * Returns 0 if the constraints are satisfied, a positive
16918  * error code if not and -1 if an internal error occurred.
16919  */
16920 static int
xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr r,xmlSchemaParticlePtr b)16921 xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,
16922 			    xmlSchemaParticlePtr r,
16923 			    xmlSchemaParticlePtr b)
16924 {
16925     /* TODO:Error codes (rcase-NSCompat). */
16926     /*
16927     * SPEC "For an element declaration particle to be a `valid restriction`
16928     * of a wildcard particle all of the following must be true:"
16929     *
16930     * SPEC (1) "The element declaration's {target namespace} is `valid`
16931     * with respect to the wildcard's {namespace constraint} as defined by
16932     * Wildcard allows Namespace Name ($3.10.4)."
16933     */
16934     if (xmlSchemaCheckCVCWildcardNamespace((xmlSchemaWildcardPtr) b->children,
16935 	((xmlSchemaElementPtr) r->children)->targetNamespace) != 0)
16936 	return (1);
16937     /*
16938     * SPEC (2) "R's occurrence range is a valid restriction of B's
16939     * occurrence range as defined by Occurrence Range OK ($3.9.6)."
16940     */
16941     if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16942 	    b->minOccurs, b->maxOccurs) != 0)
16943 	return (1);
16944 
16945     return (0);
16946 }
16947 
16948 /**
16949  * xmlSchemaCheckRCaseRecurseAsIfGroup:
16950  * @ctxt:  the schema parser context
16951  * @r: the restricting element declaration particle
16952  * @b: the base model group particle
16953  *
16954  * (3.9.6) Constraints on Particle Schema Components
16955  * Schema Component Constraint:
16956  * Particle Derivation OK (Elt:All/Choice/Sequence -- RecurseAsIfGroup)
16957  * (rcase-RecurseAsIfGroup)
16958  *
16959  * STATUS: TODO
16960  *
16961  * Returns 0 if the constraints are satisfied, a positive
16962  * error code if not and -1 if an internal error occurred.
16963  */
16964 static int
xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr r,xmlSchemaParticlePtr b)16965 xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,
16966 				    xmlSchemaParticlePtr r,
16967 				    xmlSchemaParticlePtr b)
16968 {
16969     /* TODO: Error codes (rcase-RecurseAsIfGroup). */
16970     TODO
16971     return (0);
16972 }
16973 
16974 /**
16975  * xmlSchemaCheckRCaseNSSubset:
16976  * @ctxt:  the schema parser context
16977  * @r: the restricting wildcard particle
16978  * @b: the base wildcard particle
16979  *
16980  * (3.9.6) Constraints on Particle Schema Components
16981  * Schema Component Constraint:
16982  * Particle Derivation OK (Any:Any -- NSSubset)
16983  * (rcase-NSSubset)
16984  *
16985  * STATUS: complete
16986  *
16987  * Returns 0 if the constraints are satisfied, a positive
16988  * error code if not and -1 if an internal error occurred.
16989  */
16990 static int
xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr r,xmlSchemaParticlePtr b,int isAnyTypeBase)16991 xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,
16992 				    xmlSchemaParticlePtr r,
16993 				    xmlSchemaParticlePtr b,
16994 				    int isAnyTypeBase)
16995 {
16996     /* TODO: Error codes (rcase-NSSubset). */
16997     /*
16998     * SPEC (1) "R's occurrence range is a valid restriction of B's
16999     * occurrence range as defined by Occurrence Range OK ($3.9.6)."
17000     */
17001     if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
17002 	    b->minOccurs, b->maxOccurs))
17003 	return (1);
17004     /*
17005     * SPEC (2) "R's {namespace constraint} must be an intensional subset
17006     * of B's {namespace constraint} as defined by Wildcard Subset ($3.10.6)."
17007     */
17008     if (xmlSchemaCheckCOSNSSubset((xmlSchemaWildcardPtr) r->children,
17009 	(xmlSchemaWildcardPtr) b->children))
17010 	return (1);
17011     /*
17012     * SPEC (3) "Unless B is the content model wildcard of the `ur-type
17013     * definition`, R's {process contents} must be identical to or stronger
17014     * than B's {process contents}, where strict is stronger than lax is
17015     * stronger than skip."
17016     */
17017     if (! isAnyTypeBase) {
17018 	if ( ((xmlSchemaWildcardPtr) r->children)->processContents <
17019 	    ((xmlSchemaWildcardPtr) b->children)->processContents)
17020 	    return (1);
17021     }
17022 
17023     return (0);
17024 }
17025 
17026 /**
17027  * xmlSchemaCheckCOSParticleRestrict:
17028  * @ctxt:  the schema parser context
17029  * @type:  the complex type definition
17030  *
17031  * (3.9.6) Constraints on Particle Schema Components
17032  * Schema Component Constraint:
17033  * Particle Valid (Restriction) (cos-particle-restrict)
17034  *
17035  * STATUS: TODO
17036  *
17037  * Returns 0 if the constraints are satisfied, a positive
17038  * error code if not and -1 if an internal error occurred.
17039  */
17040 static int
xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr r,xmlSchemaParticlePtr b)17041 xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,
17042 				  xmlSchemaParticlePtr r,
17043 				  xmlSchemaParticlePtr b)
17044 {
17045     int ret = 0;
17046 
17047     /*part = WXS_TYPE_PARTICLE(type);
17048     basePart = WXS_TYPE_PARTICLE(base);
17049     */
17050 
17051     TODO
17052 
17053     /*
17054     * SPEC (1) "They are the same particle."
17055     */
17056     if (r == b)
17057 	return (0);
17058 
17059 
17060     return (0);
17061 }
17062 
17063 #if 0
17064 /**
17065  * xmlSchemaCheckRCaseNSRecurseCheckCardinality:
17066  * @ctxt:  the schema parser context
17067  * @r: the model group particle
17068  * @b: the base wildcard particle
17069  *
17070  * (3.9.6) Constraints on Particle Schema Components
17071  * Schema Component Constraint:
17072  * Particle Derivation OK (All/Choice/Sequence:Any --
17073  *                         NSRecurseCheckCardinality)
17074  * (rcase-NSRecurseCheckCardinality)
17075  *
17076  * STATUS: TODO: subst-groups
17077  *
17078  * Returns 0 if the constraints are satisfied, a positive
17079  * error code if not and -1 if an internal error occurred.
17080  */
17081 static int
17082 xmlSchemaCheckRCaseNSRecurseCheckCardinality(xmlSchemaParserCtxtPtr ctxt,
17083 					     xmlSchemaParticlePtr r,
17084 					     xmlSchemaParticlePtr b)
17085 {
17086     xmlSchemaParticlePtr part;
17087     /* TODO: Error codes (rcase-NSRecurseCheckCardinality). */
17088     if ((r->children == NULL) || (r->children->children == NULL))
17089 	return (-1);
17090     /*
17091     * SPEC "For a group particle to be a `valid restriction` of a
17092     * wildcard particle..."
17093     *
17094     * SPEC (1) "Every member of the {particles} of the group is a `valid
17095     * restriction` of the wildcard as defined by
17096     * Particle Valid (Restriction) ($3.9.6)."
17097     */
17098     part = (xmlSchemaParticlePtr) r->children->children;
17099     do {
17100 	if (xmlSchemaCheckCOSParticleRestrict(ctxt, part, b))
17101 	    return (1);
17102 	part = (xmlSchemaParticlePtr) part->next;
17103     } while (part != NULL);
17104     /*
17105     * SPEC (2) "The effective total range of the group [...] is a
17106     * valid restriction of B's occurrence range as defined by
17107     * Occurrence Range OK ($3.9.6)."
17108     */
17109     if (xmlSchemaCheckParticleRangeOK(
17110 	    xmlSchemaGetParticleTotalRangeMin(r),
17111 	    xmlSchemaGetParticleTotalRangeMax(r),
17112 	    b->minOccurs, b->maxOccurs) != 0)
17113 	return (1);
17114     return (0);
17115 }
17116 #endif
17117 
17118 /**
17119  * xmlSchemaCheckRCaseRecurse:
17120  * @ctxt:  the schema parser context
17121  * @r: the <all> or <sequence> model group particle
17122  * @b: the base <all> or <sequence> model group particle
17123  *
17124  * (3.9.6) Constraints on Particle Schema Components
17125  * Schema Component Constraint:
17126  * Particle Derivation OK (All:All,Sequence:Sequence --
17127                            Recurse)
17128  * (rcase-Recurse)
17129  *
17130  * STATUS:  ?
17131  * TODO: subst-groups
17132  *
17133  * Returns 0 if the constraints are satisfied, a positive
17134  * error code if not and -1 if an internal error occurred.
17135  */
17136 static int
xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr r,xmlSchemaParticlePtr b)17137 xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,
17138 			   xmlSchemaParticlePtr r,
17139 			   xmlSchemaParticlePtr b)
17140 {
17141     /* xmlSchemaParticlePtr part; */
17142     /* TODO: Error codes (rcase-Recurse). */
17143     if ((r->children == NULL) || (b->children == NULL) ||
17144 	(r->children->type != b->children->type))
17145 	return (-1);
17146     /*
17147     * SPEC "For an all or sequence group particle to be a `valid
17148     * restriction` of another group particle with the same {compositor}..."
17149     *
17150     * SPEC (1) "R's occurrence range is a valid restriction of B's
17151     * occurrence range as defined by Occurrence Range OK ($3.9.6)."
17152     */
17153     if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
17154 	    b->minOccurs, b->maxOccurs))
17155 	return (1);
17156 
17157 
17158     return (0);
17159 }
17160 
17161 #endif
17162 
17163 #define FACET_RESTR_MUTUAL_ERR(fac1, fac2) \
17164     xmlSchemaPCustomErrExt(pctxt,      \
17165 	XML_SCHEMAP_INVALID_FACET_VALUE, \
17166 	WXS_BASIC_CAST fac1, fac1->node, \
17167 	"It is an error for both '%s' and '%s' to be specified on the "\
17168 	"same type definition", \
17169 	BAD_CAST xmlSchemaFacetTypeToString(fac1->type), \
17170 	BAD_CAST xmlSchemaFacetTypeToString(fac2->type), NULL);
17171 
17172 #define FACET_RESTR_ERR(fac1, msg) \
17173     xmlSchemaPCustomErr(pctxt,      \
17174 	XML_SCHEMAP_INVALID_FACET_VALUE, \
17175 	WXS_BASIC_CAST fac1, fac1->node, \
17176 	msg, NULL);
17177 
17178 #define FACET_RESTR_FIXED_ERR(fac) \
17179     xmlSchemaPCustomErr(pctxt, \
17180 	XML_SCHEMAP_INVALID_FACET_VALUE, \
17181 	WXS_BASIC_CAST fac, fac->node, \
17182 	"The base type's facet is 'fixed', thus the value must not " \
17183 	"differ", NULL);
17184 
17185 static void
xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,xmlSchemaFacetPtr facet1,xmlSchemaFacetPtr facet2,int lessGreater,int orEqual,int ofBase)17186 xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,
17187 			xmlSchemaFacetPtr facet1,
17188 			xmlSchemaFacetPtr facet2,
17189 			int lessGreater,
17190 			int orEqual,
17191 			int ofBase)
17192 {
17193     xmlChar *msg = NULL;
17194 
17195     msg = xmlStrdup(BAD_CAST "'");
17196     msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet1->type));
17197     msg = xmlStrcat(msg, BAD_CAST "' has to be");
17198     if (lessGreater == 0)
17199 	msg = xmlStrcat(msg, BAD_CAST " equal to");
17200     if (lessGreater == 1)
17201 	msg = xmlStrcat(msg, BAD_CAST " greater than");
17202     else
17203 	msg = xmlStrcat(msg, BAD_CAST " less than");
17204 
17205     if (orEqual)
17206 	msg = xmlStrcat(msg, BAD_CAST " or equal to");
17207     msg = xmlStrcat(msg, BAD_CAST " '");
17208     msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet2->type));
17209     if (ofBase)
17210 	msg = xmlStrcat(msg, BAD_CAST "' of the base type");
17211     else
17212 	msg = xmlStrcat(msg, BAD_CAST "'");
17213 
17214     xmlSchemaPCustomErr(pctxt,
17215 	XML_SCHEMAP_INVALID_FACET_VALUE,
17216 	WXS_BASIC_CAST facet1, NULL,
17217 	(const char *) msg, NULL);
17218 
17219     if (msg != NULL)
17220 	xmlFree(msg);
17221 }
17222 
17223 /*
17224 * xmlSchemaDeriveAndValidateFacets:
17225 *
17226 * Schema Component Constraint: Simple Type Restriction (Facets)
17227 * (st-restrict-facets)
17228 */
17229 static int
xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)17230 xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,
17231 				 xmlSchemaTypePtr type)
17232 {
17233     xmlSchemaTypePtr base = type->baseType;
17234     xmlSchemaFacetLinkPtr link, cur, last = NULL;
17235     xmlSchemaFacetPtr facet, bfacet,
17236 	flength = NULL, ftotdig = NULL, ffracdig = NULL,
17237 	fmaxlen = NULL, fminlen = NULL, /* facets of the current type */
17238 	fmininc = NULL, fmaxinc = NULL,
17239 	fminexc = NULL, fmaxexc = NULL,
17240 	bflength = NULL, bftotdig = NULL, bffracdig = NULL,
17241 	bfmaxlen = NULL, bfminlen = NULL, /* facets of the base type */
17242 	bfmininc = NULL, bfmaxinc = NULL,
17243 	bfminexc = NULL, bfmaxexc = NULL;
17244     int res; /* err = 0, fixedErr; */
17245 
17246     /*
17247     * SPEC st-restrict-facets 1:
17248     * "The {variety} of R is the same as that of B."
17249     */
17250     /*
17251     * SPEC st-restrict-facets 2:
17252     * "If {variety} is atomic, the {primitive type definition}
17253     * of R is the same as that of B."
17254     *
17255     * NOTE: we leave 1 & 2 out for now, since this will be
17256     * satisfied by the derivation process.
17257     * CONSTRUCTION TODO: Maybe needed if using a construction API.
17258     */
17259     /*
17260     * SPEC st-restrict-facets 3:
17261     * "The {facets} of R are the union of S and the {facets}
17262     * of B, eliminating duplicates. To eliminate duplicates,
17263     * when a facet of the same kind occurs in both S and the
17264     * {facets} of B, the one in the {facets} of B is not
17265     * included, with the exception of enumeration and pattern
17266     * facets, for which multiple occurrences with distinct values
17267     * are allowed."
17268     */
17269 
17270     if ((type->facetSet == NULL) && (base->facetSet == NULL))
17271 	return (0);
17272 
17273     last = type->facetSet;
17274     if (last != NULL)
17275 	while (last->next != NULL)
17276 	    last = last->next;
17277 
17278     for (cur = type->facetSet; cur != NULL; cur = cur->next) {
17279 	facet = cur->facet;
17280 	switch (facet->type) {
17281 	    case XML_SCHEMA_FACET_LENGTH:
17282 		flength = facet; break;
17283 	    case XML_SCHEMA_FACET_MINLENGTH:
17284 		fminlen = facet; break;
17285 	    case XML_SCHEMA_FACET_MININCLUSIVE:
17286 		fmininc = facet; break;
17287 	    case XML_SCHEMA_FACET_MINEXCLUSIVE:
17288 		fminexc = facet; break;
17289 	    case XML_SCHEMA_FACET_MAXLENGTH:
17290 		fmaxlen = facet; break;
17291 	    case XML_SCHEMA_FACET_MAXINCLUSIVE:
17292 		fmaxinc = facet; break;
17293 	    case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17294 		fmaxexc = facet; break;
17295 	    case XML_SCHEMA_FACET_TOTALDIGITS:
17296 		ftotdig = facet; break;
17297 	    case XML_SCHEMA_FACET_FRACTIONDIGITS:
17298 		ffracdig = facet; break;
17299 	    default:
17300 		break;
17301 	}
17302     }
17303     for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17304 	facet = cur->facet;
17305 	switch (facet->type) {
17306 	    case XML_SCHEMA_FACET_LENGTH:
17307 		bflength = facet; break;
17308 	    case XML_SCHEMA_FACET_MINLENGTH:
17309 		bfminlen = facet; break;
17310 	    case XML_SCHEMA_FACET_MININCLUSIVE:
17311 		bfmininc = facet; break;
17312 	    case XML_SCHEMA_FACET_MINEXCLUSIVE:
17313 		bfminexc = facet; break;
17314 	    case XML_SCHEMA_FACET_MAXLENGTH:
17315 		bfmaxlen = facet; break;
17316 	    case XML_SCHEMA_FACET_MAXINCLUSIVE:
17317 		bfmaxinc = facet; break;
17318 	    case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17319 		bfmaxexc = facet; break;
17320 	    case XML_SCHEMA_FACET_TOTALDIGITS:
17321 		bftotdig = facet; break;
17322 	    case XML_SCHEMA_FACET_FRACTIONDIGITS:
17323 		bffracdig = facet; break;
17324 	    default:
17325 		break;
17326 	}
17327     }
17328     /*
17329     * length and minLength or maxLength (2.2) + (3.2)
17330     */
17331     if (flength && (fminlen || fmaxlen)) {
17332 	FACET_RESTR_ERR(flength, "It is an error for both 'length' and "
17333 	    "either of 'minLength' or 'maxLength' to be specified on "
17334 	    "the same type definition")
17335     }
17336     /*
17337     * Mutual exclusions in the same derivation step.
17338     */
17339     if ((fmaxinc) && (fmaxexc)) {
17340 	/*
17341 	* SCC "maxInclusive and maxExclusive"
17342 	*/
17343 	FACET_RESTR_MUTUAL_ERR(fmaxinc, fmaxexc)
17344     }
17345     if ((fmininc) && (fminexc)) {
17346 	/*
17347 	* SCC "minInclusive and minExclusive"
17348 	*/
17349 	FACET_RESTR_MUTUAL_ERR(fmininc, fminexc)
17350     }
17351 
17352     if (flength && bflength) {
17353 	/*
17354 	* SCC "length valid restriction"
17355 	* The values have to be equal.
17356 	*/
17357 	res = xmlSchemaCompareValues(flength->val, bflength->val);
17358 	if (res == -2)
17359 	    goto internal_error;
17360 	if (res != 0)
17361 	    xmlSchemaDeriveFacetErr(pctxt, flength, bflength, 0, 0, 1);
17362 	if ((res != 0) && (bflength->fixed)) {
17363 	    FACET_RESTR_FIXED_ERR(flength)
17364 	}
17365 
17366     }
17367     if (fminlen && bfminlen) {
17368 	/*
17369 	* SCC "minLength valid restriction"
17370 	* minLength >= BASE minLength
17371 	*/
17372 	res = xmlSchemaCompareValues(fminlen->val, bfminlen->val);
17373 	if (res == -2)
17374 	    goto internal_error;
17375 	if (res == -1)
17376 	    xmlSchemaDeriveFacetErr(pctxt, fminlen, bfminlen, 1, 1, 1);
17377 	if ((res != 0) && (bfminlen->fixed)) {
17378 	    FACET_RESTR_FIXED_ERR(fminlen)
17379 	}
17380     }
17381     if (fmaxlen && bfmaxlen) {
17382 	/*
17383 	* SCC "maxLength valid restriction"
17384 	* maxLength <= BASE minLength
17385 	*/
17386 	res = xmlSchemaCompareValues(fmaxlen->val, bfmaxlen->val);
17387 	if (res == -2)
17388 	    goto internal_error;
17389 	if (res == 1)
17390 	    xmlSchemaDeriveFacetErr(pctxt, fmaxlen, bfmaxlen, -1, 1, 1);
17391 	if ((res != 0) && (bfmaxlen->fixed)) {
17392 	    FACET_RESTR_FIXED_ERR(fmaxlen)
17393 	}
17394     }
17395     /*
17396     * SCC "length and minLength or maxLength"
17397     */
17398     if (! flength)
17399 	flength = bflength;
17400     if (flength) {
17401 	if (! fminlen)
17402 	    fminlen = bfminlen;
17403 	if (fminlen) {
17404 	    /* (1.1) length >= minLength */
17405 	    res = xmlSchemaCompareValues(flength->val, fminlen->val);
17406 	    if (res == -2)
17407 		goto internal_error;
17408 	    if (res == -1)
17409 		xmlSchemaDeriveFacetErr(pctxt, flength, fminlen, 1, 1, 0);
17410 	}
17411 	if (! fmaxlen)
17412 	    fmaxlen = bfmaxlen;
17413 	if (fmaxlen) {
17414 	    /* (2.1) length <= maxLength */
17415 	    res = xmlSchemaCompareValues(flength->val, fmaxlen->val);
17416 	    if (res == -2)
17417 		goto internal_error;
17418 	    if (res == 1)
17419 		xmlSchemaDeriveFacetErr(pctxt, flength, fmaxlen, -1, 1, 0);
17420 	}
17421     }
17422     if (fmaxinc) {
17423 	/*
17424 	* "maxInclusive"
17425 	*/
17426 	if (fmininc) {
17427 	    /* SCC "maxInclusive >= minInclusive" */
17428 	    res = xmlSchemaCompareValues(fmaxinc->val, fmininc->val);
17429 	    if (res == -2)
17430 		goto internal_error;
17431 	    if (res == -1) {
17432 		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, fmininc, 1, 1, 0);
17433 	    }
17434 	}
17435 	/*
17436 	* SCC "maxInclusive valid restriction"
17437 	*/
17438 	if (bfmaxinc) {
17439 	    /* maxInclusive <= BASE maxInclusive */
17440 	    res = xmlSchemaCompareValues(fmaxinc->val, bfmaxinc->val);
17441 	    if (res == -2)
17442 		goto internal_error;
17443 	    if (res == 1)
17444 		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxinc, -1, 1, 1);
17445 	    if ((res != 0) && (bfmaxinc->fixed)) {
17446 		FACET_RESTR_FIXED_ERR(fmaxinc)
17447 	    }
17448 	}
17449 	if (bfmaxexc) {
17450 	    /* maxInclusive < BASE maxExclusive */
17451 	    res = xmlSchemaCompareValues(fmaxinc->val, bfmaxexc->val);
17452 	    if (res == -2)
17453 		goto internal_error;
17454 	    if (res != -1) {
17455 		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxexc, -1, 0, 1);
17456 	    }
17457 	}
17458 	if (bfmininc) {
17459 	    /* maxInclusive >= BASE minInclusive */
17460 	    res = xmlSchemaCompareValues(fmaxinc->val, bfmininc->val);
17461 	    if (res == -2)
17462 		goto internal_error;
17463 	    if (res == -1) {
17464 		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmininc, 1, 1, 1);
17465 	    }
17466 	}
17467 	if (bfminexc) {
17468 	    /* maxInclusive > BASE minExclusive */
17469 	    res = xmlSchemaCompareValues(fmaxinc->val, bfminexc->val);
17470 	    if (res == -2)
17471 		goto internal_error;
17472 	    if (res != 1) {
17473 		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfminexc, 1, 0, 1);
17474 	    }
17475 	}
17476     }
17477     if (fmaxexc) {
17478 	/*
17479 	* "maxExclusive >= minExclusive"
17480 	*/
17481 	if (fminexc) {
17482 	    res = xmlSchemaCompareValues(fmaxexc->val, fminexc->val);
17483 	    if (res == -2)
17484 		goto internal_error;
17485 	    if (res == -1) {
17486 		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, fminexc, 1, 1, 0);
17487 	    }
17488 	}
17489 	/*
17490 	* "maxExclusive valid restriction"
17491 	*/
17492 	if (bfmaxexc) {
17493 	    /* maxExclusive <= BASE maxExclusive */
17494 	    res = xmlSchemaCompareValues(fmaxexc->val, bfmaxexc->val);
17495 	    if (res == -2)
17496 		goto internal_error;
17497 	    if (res == 1) {
17498 		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxexc, -1, 1, 1);
17499 	    }
17500 	    if ((res != 0) && (bfmaxexc->fixed)) {
17501 		FACET_RESTR_FIXED_ERR(fmaxexc)
17502 	    }
17503 	}
17504 	if (bfmaxinc) {
17505 	    /* maxExclusive <= BASE maxInclusive */
17506 	    res = xmlSchemaCompareValues(fmaxexc->val, bfmaxinc->val);
17507 	    if (res == -2)
17508 		goto internal_error;
17509 	    if (res == 1) {
17510 		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxinc, -1, 1, 1);
17511 	    }
17512 	}
17513 	if (bfmininc) {
17514 	    /* maxExclusive > BASE minInclusive */
17515 	    res = xmlSchemaCompareValues(fmaxexc->val, bfmininc->val);
17516 	    if (res == -2)
17517 		goto internal_error;
17518 	    if (res != 1) {
17519 		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmininc, 1, 0, 1);
17520 	    }
17521 	}
17522 	if (bfminexc) {
17523 	    /* maxExclusive > BASE minExclusive */
17524 	    res = xmlSchemaCompareValues(fmaxexc->val, bfminexc->val);
17525 	    if (res == -2)
17526 		goto internal_error;
17527 	    if (res != 1) {
17528 		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfminexc, 1, 0, 1);
17529 	    }
17530 	}
17531     }
17532     if (fminexc) {
17533 	/*
17534 	* "minExclusive < maxInclusive"
17535 	*/
17536 	if (fmaxinc) {
17537 	    res = xmlSchemaCompareValues(fminexc->val, fmaxinc->val);
17538 	    if (res == -2)
17539 		goto internal_error;
17540 	    if (res != -1) {
17541 		xmlSchemaDeriveFacetErr(pctxt, fminexc, fmaxinc, -1, 0, 0);
17542 	    }
17543 	}
17544 	/*
17545 	* "minExclusive valid restriction"
17546 	*/
17547 	if (bfminexc) {
17548 	    /* minExclusive >= BASE minExclusive */
17549 	    res = xmlSchemaCompareValues(fminexc->val, bfminexc->val);
17550 	    if (res == -2)
17551 		goto internal_error;
17552 	    if (res == -1) {
17553 		xmlSchemaDeriveFacetErr(pctxt, fminexc, bfminexc, 1, 1, 1);
17554 	    }
17555 	    if ((res != 0) && (bfminexc->fixed)) {
17556 		FACET_RESTR_FIXED_ERR(fminexc)
17557 	    }
17558 	}
17559 	if (bfmaxinc) {
17560 	    /* minExclusive <= BASE maxInclusive */
17561 	    res = xmlSchemaCompareValues(fminexc->val, bfmaxinc->val);
17562 	    if (res == -2)
17563 		goto internal_error;
17564 	    if (res == 1) {
17565 		xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxinc, -1, 1, 1);
17566 	    }
17567 	}
17568 	if (bfmininc) {
17569 	    /* minExclusive >= BASE minInclusive */
17570 	    res = xmlSchemaCompareValues(fminexc->val, bfmininc->val);
17571 	    if (res == -2)
17572 		goto internal_error;
17573 	    if (res == -1) {
17574 		xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmininc, 1, 1, 1);
17575 	    }
17576 	}
17577 	if (bfmaxexc) {
17578 	    /* minExclusive < BASE maxExclusive */
17579 	    res = xmlSchemaCompareValues(fminexc->val, bfmaxexc->val);
17580 	    if (res == -2)
17581 		goto internal_error;
17582 	    if (res != -1) {
17583 		xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxexc, -1, 0, 1);
17584 	    }
17585 	}
17586     }
17587     if (fmininc) {
17588 	/*
17589 	* "minInclusive < maxExclusive"
17590 	*/
17591 	if (fmaxexc) {
17592 	    res = xmlSchemaCompareValues(fmininc->val, fmaxexc->val);
17593 	    if (res == -2)
17594 		goto internal_error;
17595 	    if (res != -1) {
17596 		xmlSchemaDeriveFacetErr(pctxt, fmininc, fmaxexc, -1, 0, 0);
17597 	    }
17598 	}
17599 	/*
17600 	* "minExclusive valid restriction"
17601 	*/
17602 	if (bfmininc) {
17603 	    /* minInclusive >= BASE minInclusive */
17604 	    res = xmlSchemaCompareValues(fmininc->val, bfmininc->val);
17605 	    if (res == -2)
17606 		goto internal_error;
17607 	    if (res == -1) {
17608 		xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmininc, 1, 1, 1);
17609 	    }
17610 	    if ((res != 0) && (bfmininc->fixed)) {
17611 		FACET_RESTR_FIXED_ERR(fmininc)
17612 	    }
17613 	}
17614 	if (bfmaxinc) {
17615 	    /* minInclusive <= BASE maxInclusive */
17616 	    res = xmlSchemaCompareValues(fmininc->val, bfmaxinc->val);
17617 	    if (res == -2)
17618 		goto internal_error;
17619 	    if (res == 1) {
17620 		xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxinc, -1, 1, 1);
17621 	    }
17622 	}
17623 	if (bfminexc) {
17624 	    /* minInclusive > BASE minExclusive */
17625 	    res = xmlSchemaCompareValues(fmininc->val, bfminexc->val);
17626 	    if (res == -2)
17627 		goto internal_error;
17628 	    if (res != 1)
17629 		xmlSchemaDeriveFacetErr(pctxt, fmininc, bfminexc, 1, 0, 1);
17630 	}
17631 	if (bfmaxexc) {
17632 	    /* minInclusive < BASE maxExclusive */
17633 	    res = xmlSchemaCompareValues(fmininc->val, bfmaxexc->val);
17634 	    if (res == -2)
17635 		goto internal_error;
17636 	    if (res != -1)
17637 		xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxexc, -1, 0, 1);
17638 	}
17639     }
17640     if (ftotdig && bftotdig) {
17641 	/*
17642 	* SCC " totalDigits valid restriction"
17643 	* totalDigits <= BASE totalDigits
17644 	*/
17645 	res = xmlSchemaCompareValues(ftotdig->val, bftotdig->val);
17646 	if (res == -2)
17647 	    goto internal_error;
17648 	if (res == 1)
17649 	    xmlSchemaDeriveFacetErr(pctxt, ftotdig, bftotdig,
17650 	    -1, 1, 1);
17651 	if ((res != 0) && (bftotdig->fixed)) {
17652 	    FACET_RESTR_FIXED_ERR(ftotdig)
17653 	}
17654     }
17655     if (ffracdig && bffracdig) {
17656 	/*
17657 	* SCC  "fractionDigits valid restriction"
17658 	* fractionDigits <= BASE fractionDigits
17659 	*/
17660 	res = xmlSchemaCompareValues(ffracdig->val, bffracdig->val);
17661 	if (res == -2)
17662 	    goto internal_error;
17663 	if (res == 1)
17664 	    xmlSchemaDeriveFacetErr(pctxt, ffracdig, bffracdig,
17665 	    -1, 1, 1);
17666 	if ((res != 0) && (bffracdig->fixed)) {
17667 	    FACET_RESTR_FIXED_ERR(ffracdig)
17668 	}
17669     }
17670     /*
17671     * SCC "fractionDigits less than or equal to totalDigits"
17672     */
17673     if (! ftotdig)
17674 	ftotdig = bftotdig;
17675     if (! ffracdig)
17676 	ffracdig = bffracdig;
17677     if (ftotdig && ffracdig) {
17678 	res = xmlSchemaCompareValues(ffracdig->val, ftotdig->val);
17679 	if (res == -2)
17680 	    goto internal_error;
17681 	if (res == 1)
17682 	    xmlSchemaDeriveFacetErr(pctxt, ffracdig, ftotdig,
17683 		-1, 1, 0);
17684     }
17685     /*
17686     * *Enumerations* won' be added here, since only the first set
17687     * of enumerations in the ancestor-or-self axis is used
17688     * for validation, plus we need to use the base type of those
17689     * enumerations for whitespace.
17690     *
17691     * *Patterns*: won't be add here, since they are ORed at
17692     * type level and ANDed at ancestor level. This will
17693     * happen during validation by walking the base axis
17694     * of the type.
17695     */
17696     for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17697 	bfacet = cur->facet;
17698 	/*
17699 	* Special handling of enumerations and patterns.
17700 	* TODO: hmm, they should not appear in the set, so remove this.
17701 	*/
17702 	if ((bfacet->type == XML_SCHEMA_FACET_PATTERN) ||
17703 	    (bfacet->type == XML_SCHEMA_FACET_ENUMERATION))
17704 	    continue;
17705 	/*
17706 	* Search for a duplicate facet in the current type.
17707 	*/
17708 	link = type->facetSet;
17709 	/* err = 0; */
17710 	/* fixedErr = 0; */
17711 	while (link != NULL) {
17712 	    facet = link->facet;
17713 	    if (facet->type == bfacet->type) {
17714 		switch (facet->type) {
17715 		    case XML_SCHEMA_FACET_WHITESPACE:
17716 			/*
17717 			* The whitespace must be stronger.
17718 			*/
17719 			if (facet->whitespace < bfacet->whitespace) {
17720 			    FACET_RESTR_ERR(facet,
17721 				"The 'whitespace' value has to be equal to "
17722 				"or stronger than the 'whitespace' value of "
17723 				"the base type")
17724 			}
17725 			if ((bfacet->fixed) &&
17726 			    (facet->whitespace != bfacet->whitespace)) {
17727 			    FACET_RESTR_FIXED_ERR(facet)
17728 			}
17729 			break;
17730 		    default:
17731 			break;
17732 		}
17733 		/* Duplicate found. */
17734 		break;
17735 	    }
17736 	    link = link->next;
17737 	}
17738 	/*
17739 	* If no duplicate was found: add the base types's facet
17740 	* to the set.
17741 	*/
17742 	if (link == NULL) {
17743 	    link = (xmlSchemaFacetLinkPtr)
17744 		xmlMalloc(sizeof(xmlSchemaFacetLink));
17745 	    if (link == NULL) {
17746 		xmlSchemaPErrMemory(pctxt);
17747 		return (-1);
17748 	    }
17749 	    link->facet = cur->facet;
17750 	    link->next = NULL;
17751 	    if (last == NULL)
17752 		type->facetSet = link;
17753 	    else
17754 		last->next = link;
17755 	    last = link;
17756 	}
17757 
17758     }
17759 
17760     return (0);
17761 internal_error:
17762     PERROR_INT("xmlSchemaDeriveAndValidateFacets",
17763 	"an error occurred");
17764     return (-1);
17765 }
17766 
17767 static int
xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)17768 xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,
17769 					     xmlSchemaTypePtr type)
17770 {
17771     xmlSchemaTypeLinkPtr link, lastLink, prevLink, subLink, newLink;
17772     /*
17773     * The actual value is then formed by replacing any union type
17774     * definition in the `explicit members` with the members of their
17775     * {member type definitions}, in order.
17776     *
17777     * TODO: There's a bug entry at
17778     * "http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0287.html"
17779     * which indicates that we'll keep the union types the future.
17780     */
17781     link = type->memberTypes;
17782     while (link != NULL) {
17783 
17784 	if (WXS_IS_TYPE_NOT_FIXED(link->type))
17785 	    xmlSchemaTypeFixup(link->type, ACTXT_CAST pctxt);
17786 
17787 	if (WXS_IS_UNION(link->type)) {
17788 	    subLink = xmlSchemaGetUnionSimpleTypeMemberTypes(link->type);
17789 	    if (subLink != NULL) {
17790 		link->type = subLink->type;
17791 		if (subLink->next != NULL) {
17792 		    lastLink = link->next;
17793 		    subLink = subLink->next;
17794 		    prevLink = link;
17795 		    while (subLink != NULL) {
17796 			newLink = (xmlSchemaTypeLinkPtr)
17797 			    xmlMalloc(sizeof(xmlSchemaTypeLink));
17798 			if (newLink == NULL) {
17799 			    xmlSchemaPErrMemory(pctxt);
17800 			    return (-1);
17801 			}
17802 			newLink->type = subLink->type;
17803 			prevLink->next = newLink;
17804 			prevLink = newLink;
17805 			newLink->next = lastLink;
17806 
17807 			subLink = subLink->next;
17808 		    }
17809 		}
17810 	    }
17811 	}
17812 	link = link->next;
17813     }
17814     return (0);
17815 }
17816 
17817 static void
xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type)17818 xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type)
17819 {
17820     int has = 0, needVal = 0, normVal = 0;
17821 
17822     has	= (type->baseType->flags & XML_SCHEMAS_TYPE_HAS_FACETS) ? 1 : 0;
17823     if (has) {
17824 	needVal = (type->baseType->flags &
17825 	    XML_SCHEMAS_TYPE_FACETSNEEDVALUE) ? 1 : 0;
17826 	normVal = (type->baseType->flags &
17827 	    XML_SCHEMAS_TYPE_NORMVALUENEEDED) ? 1 : 0;
17828     }
17829     if (type->facets != NULL) {
17830 	xmlSchemaFacetPtr fac;
17831 
17832 	for (fac = type->facets; fac != NULL; fac = fac->next) {
17833 	    switch (fac->type) {
17834 		case XML_SCHEMA_FACET_WHITESPACE:
17835 		    break;
17836 		case XML_SCHEMA_FACET_PATTERN:
17837 		    normVal = 1;
17838 		    has = 1;
17839 		    break;
17840 		case XML_SCHEMA_FACET_ENUMERATION:
17841 		    needVal = 1;
17842 		    normVal = 1;
17843 		    has = 1;
17844 		    break;
17845 		default:
17846 		    has = 1;
17847 		    break;
17848 	    }
17849 	}
17850     }
17851     if (normVal)
17852 	type->flags |= XML_SCHEMAS_TYPE_NORMVALUENEEDED;
17853     if (needVal)
17854 	type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17855     if (has)
17856 	type->flags |= XML_SCHEMAS_TYPE_HAS_FACETS;
17857 
17858     if (has && (! needVal) && WXS_IS_ATOMIC(type)) {
17859 	xmlSchemaTypePtr prim = xmlSchemaGetPrimitiveType(type);
17860 	/*
17861 	* OPTIMIZE VAL TODO: Some facets need a computed value.
17862 	*/
17863 	if ((prim->builtInType != XML_SCHEMAS_ANYSIMPLETYPE) &&
17864 	    (prim->builtInType != XML_SCHEMAS_STRING)) {
17865 	    type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17866 	}
17867     }
17868 }
17869 
17870 static int
xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type)17871 xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type)
17872 {
17873 
17874 
17875     /*
17876     * Evaluate the whitespace-facet value.
17877     */
17878     if (WXS_IS_LIST(type)) {
17879 	type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17880 	return (0);
17881     } else if (WXS_IS_UNION(type))
17882 	return (0);
17883 
17884     if (type->facetSet != NULL) {
17885 	xmlSchemaFacetLinkPtr lin;
17886 
17887 	for (lin = type->facetSet; lin != NULL; lin = lin->next) {
17888 	    if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
17889 		switch (lin->facet->whitespace) {
17890 		case XML_SCHEMAS_FACET_PRESERVE:
17891 		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
17892 		    break;
17893 		case XML_SCHEMAS_FACET_REPLACE:
17894 		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
17895 		    break;
17896 		case XML_SCHEMAS_FACET_COLLAPSE:
17897 		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17898 		    break;
17899 		default:
17900 		    return (-1);
17901 		}
17902 		return (0);
17903 	    }
17904 	}
17905     }
17906     /*
17907     * For all `atomic` datatypes other than string (and types `derived`
17908     * by `restriction` from it) the value of whiteSpace is fixed to
17909     * collapse
17910     */
17911     {
17912 	xmlSchemaTypePtr anc;
17913 
17914 	for (anc = type->baseType; anc != NULL &&
17915 		anc->builtInType != XML_SCHEMAS_ANYTYPE;
17916 		anc = anc->baseType) {
17917 
17918 	    if (anc->type == XML_SCHEMA_TYPE_BASIC) {
17919 		if (anc->builtInType == XML_SCHEMAS_NORMSTRING) {
17920 		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
17921 
17922 		} else if ((anc->builtInType == XML_SCHEMAS_STRING) ||
17923 		    (anc->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)) {
17924 		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
17925 
17926 		} else
17927 		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17928 		break;
17929 	    }
17930 	}
17931     }
17932     return (0);
17933 }
17934 
17935 static int
xmlSchemaFixupSimpleTypeStageOne(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)17936 xmlSchemaFixupSimpleTypeStageOne(xmlSchemaParserCtxtPtr pctxt,
17937 			  xmlSchemaTypePtr type)
17938 {
17939     if (type->type != XML_SCHEMA_TYPE_SIMPLE)
17940 	return(0);
17941     if (! WXS_IS_TYPE_NOT_FIXED_1(type))
17942 	return(0);
17943     type->flags |= XML_SCHEMAS_TYPE_FIXUP_1;
17944 
17945     if (WXS_IS_LIST(type)) {
17946 	/*
17947 	* Corresponds to <simpleType><list>...
17948 	*/
17949 	if (type->subtypes == NULL) {
17950 	    /*
17951 	    * This one is really needed, so get out.
17952 	    */
17953 	    PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17954 		"list type has no item-type assigned");
17955 	    return(-1);
17956 	}
17957     } else if (WXS_IS_UNION(type)) {
17958 	/*
17959 	* Corresponds to <simpleType><union>...
17960 	*/
17961 	if (type->memberTypes == NULL) {
17962 	    /*
17963 	    * This one is really needed, so get out.
17964 	    */
17965 	    PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17966 		"union type has no member-types assigned");
17967 	    return(-1);
17968 	}
17969     } else {
17970 	/*
17971 	* Corresponds to <simpleType><restriction>...
17972 	*/
17973 	if (type->baseType == NULL) {
17974 	    PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17975 		"type has no base-type assigned");
17976 	    return(-1);
17977 	}
17978 	if (WXS_IS_TYPE_NOT_FIXED_1(type->baseType))
17979 	    if (xmlSchemaFixupSimpleTypeStageOne(pctxt, type->baseType) == -1)
17980 		return(-1);
17981 	/*
17982 	* Variety
17983 	* If the <restriction> alternative is chosen, then the
17984 	* {variety} of the {base type definition}.
17985 	*/
17986 	if (WXS_IS_ATOMIC(type->baseType))
17987 	    type->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
17988 	else if (WXS_IS_LIST(type->baseType)) {
17989 	    type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
17990 	    /*
17991 	    * Inherit the itemType.
17992 	    */
17993 	    type->subtypes = type->baseType->subtypes;
17994 	} else if (WXS_IS_UNION(type->baseType)) {
17995 	    type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
17996 	    /*
17997 	    * NOTE that we won't assign the memberTypes of the base,
17998 	    * since this will make trouble when freeing them; we will
17999 	    * use a lookup function to access them instead.
18000 	    */
18001 	}
18002     }
18003     return(0);
18004 }
18005 
18006 /*
18007 * 3.14.6 Constraints on Simple Type Definition Schema Components
18008 */
18009 static int
xmlSchemaFixupSimpleTypeStageTwo(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)18010 xmlSchemaFixupSimpleTypeStageTwo(xmlSchemaParserCtxtPtr pctxt,
18011 				 xmlSchemaTypePtr type)
18012 {
18013     int res, olderrs = pctxt->nberrors;
18014 
18015     if (type->type != XML_SCHEMA_TYPE_SIMPLE)
18016 	return(-1);
18017 
18018     if (! WXS_IS_TYPE_NOT_FIXED(type))
18019 	return(0);
18020 
18021     type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
18022     type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
18023 
18024     if (type->baseType == NULL) {
18025 	PERROR_INT("xmlSchemaFixupSimpleTypeStageTwo",
18026 	    "missing baseType");
18027 	goto exit_failure;
18028     }
18029     if (WXS_IS_TYPE_NOT_FIXED(type->baseType))
18030 	xmlSchemaTypeFixup(type->baseType, ACTXT_CAST pctxt);
18031     /*
18032     * If a member type of a union is a union itself, we need to substitute
18033     * that member type for its member types.
18034     * NOTE that this might change in WXS 1.1; i.e. we will keep the union
18035     * types in WXS 1.1.
18036     */
18037     if ((type->memberTypes != NULL) &&
18038 	(xmlSchemaFinishMemberTypeDefinitionsProperty(pctxt, type) == -1))
18039 	return(-1);
18040     /*
18041     * SPEC src-simple-type 1
18042     * "The corresponding simple type definition, if any, must satisfy
18043     * the conditions set out in Constraints on Simple Type Definition
18044     * Schema Components ($3.14.6)."
18045     */
18046     /*
18047     * Schema Component Constraint: Simple Type Definition Properties Correct
18048     * (st-props-correct)
18049     */
18050     res = xmlSchemaCheckSTPropsCorrect(pctxt, type);
18051     HFAILURE HERROR
18052     /*
18053     * Schema Component Constraint: Derivation Valid (Restriction, Simple)
18054     * (cos-st-restricts)
18055     */
18056     res = xmlSchemaCheckCOSSTRestricts(pctxt, type);
18057     HFAILURE HERROR
18058     /*
18059     * TODO: Removed the error report, since it got annoying to get an
18060     * extra error report, if anything failed until now.
18061     * Enable this if needed.
18062     *
18063     * xmlSchemaPErr(ctxt, type->node,
18064     *    XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
18065     *    "Simple type '%s' does not satisfy the constraints "
18066     *    "on simple type definitions.\n",
18067     *    type->name, NULL);
18068     */
18069     /*
18070     * Schema Component Constraint: Simple Type Restriction (Facets)
18071     * (st-restrict-facets)
18072     */
18073     res = xmlSchemaCheckFacetValues(type, pctxt);
18074     HFAILURE HERROR
18075     if ((type->facetSet != NULL) ||
18076 	(type->baseType->facetSet != NULL)) {
18077 	res = xmlSchemaDeriveAndValidateFacets(pctxt, type);
18078 	HFAILURE HERROR
18079     }
18080     /*
18081     * Whitespace value.
18082     */
18083     res = xmlSchemaTypeFixupWhitespace(type);
18084     HFAILURE HERROR
18085     xmlSchemaTypeFixupOptimFacets(type);
18086 
18087 exit_error:
18088     if (olderrs != pctxt->nberrors)
18089 	return(pctxt->err);
18090     return(0);
18091 
18092 exit_failure:
18093     return(-1);
18094 }
18095 
18096 static int
xmlSchemaFixupComplexType(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)18097 xmlSchemaFixupComplexType(xmlSchemaParserCtxtPtr pctxt,
18098 			  xmlSchemaTypePtr type)
18099 {
18100     int res = 0, olderrs = pctxt->nberrors;
18101     xmlSchemaTypePtr baseType = type->baseType;
18102 
18103     if (! WXS_IS_TYPE_NOT_FIXED(type))
18104 	return(0);
18105     type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
18106     if (baseType == NULL) {
18107 	PERROR_INT("xmlSchemaFixupComplexType",
18108 	    "missing baseType");
18109 	goto exit_failure;
18110     }
18111     /*
18112     * Fixup the base type.
18113     */
18114     if (WXS_IS_TYPE_NOT_FIXED(baseType))
18115 	xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt);
18116     if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) {
18117 	/*
18118 	* Skip fixup if the base type is invalid.
18119 	* TODO: Generate a warning!
18120 	*/
18121 	return(0);
18122     }
18123     /*
18124     * This basically checks if the base type can be derived.
18125     */
18126     res = xmlSchemaCheckSRCCT(pctxt, type);
18127     HFAILURE HERROR
18128     /*
18129     * Fixup the content type.
18130     */
18131     if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) {
18132 	/*
18133 	* Corresponds to <complexType><simpleContent>...
18134 	*/
18135 	if ((WXS_IS_COMPLEX(baseType)) &&
18136 	    (baseType->contentTypeDef != NULL) &&
18137 	    (WXS_IS_RESTRICTION(type))) {
18138 	    xmlSchemaTypePtr contentBase, content;
18139 #ifdef ENABLE_NAMED_LOCALS
18140 	    char buf[30];
18141 	    const xmlChar *tmpname;
18142 #endif
18143 	    /*
18144 	    * SPEC (1) If <restriction> + base type is <complexType>,
18145 	    * "whose own {content type} is a simple type..."
18146 	    */
18147 	    if (type->contentTypeDef != NULL) {
18148 		/*
18149 		* SPEC (1.1) "the simple type definition corresponding to the
18150 		* <simpleType> among the [children] of <restriction> if there
18151 		* is one;"
18152 		* Note that this "<simpleType> among the [children]" was put
18153 		* into ->contentTypeDef during parsing.
18154 		*/
18155 		contentBase = type->contentTypeDef;
18156 		type->contentTypeDef = NULL;
18157 	    } else {
18158 		/*
18159 		* (1.2) "...otherwise (<restriction> has no <simpleType>
18160 		* among its [children]), the simple type definition which
18161 		* is the {content type} of the ... base type."
18162 		*/
18163 		contentBase = baseType->contentTypeDef;
18164 	    }
18165 	    /*
18166 	    * SPEC
18167 	    * "... a simple type definition which restricts the simple
18168 	    * type definition identified in clause 1.1 or clause 1.2
18169 	    * with a set of facet components"
18170 	    *
18171 	    * Create the anonymous simple type, which will be the content
18172 	    * type of the complex type.
18173 	    */
18174 #ifdef ENABLE_NAMED_LOCALS
18175 	    snprintf(buf, 29, "#scST%d", ++(pctxt->counter));
18176 	    tmpname = xmlDictLookup(pctxt->dict, BAD_CAST buf, -1);
18177 	    content = xmlSchemaAddType(pctxt, pctxt->schema,
18178 		XML_SCHEMA_TYPE_SIMPLE, tmpname, type->targetNamespace,
18179 		type->node, 0);
18180 #else
18181 	    content = xmlSchemaAddType(pctxt, pctxt->schema,
18182 		XML_SCHEMA_TYPE_SIMPLE, NULL, type->targetNamespace,
18183 		type->node, 0);
18184 #endif
18185 	    if (content == NULL)
18186 		goto exit_failure;
18187 	    /*
18188 	    * We will use the same node as for the <complexType>
18189 	    * to have it somehow anchored in the schema doc.
18190 	    */
18191 	    content->type = XML_SCHEMA_TYPE_SIMPLE;
18192 	    content->baseType = contentBase;
18193 	    /*
18194 	    * Move the facets, previously anchored on the
18195 	    * complexType during parsing.
18196 	    */
18197 	    content->facets = type->facets;
18198 	    type->facets = NULL;
18199 	    content->facetSet = type->facetSet;
18200 	    type->facetSet = NULL;
18201 
18202 	    type->contentTypeDef = content;
18203 	    if (WXS_IS_TYPE_NOT_FIXED(contentBase))
18204 		xmlSchemaTypeFixup(contentBase, ACTXT_CAST pctxt);
18205 	    /*
18206 	    * Fixup the newly created type. We don't need to check
18207 	    * for circularity here.
18208 	    */
18209 	    res = xmlSchemaFixupSimpleTypeStageOne(pctxt, content);
18210 	    HFAILURE HERROR
18211 	    res = xmlSchemaFixupSimpleTypeStageTwo(pctxt, content);
18212 	    HFAILURE HERROR
18213 
18214 	} else if ((WXS_IS_COMPLEX(baseType)) &&
18215 	    (baseType->contentType == XML_SCHEMA_CONTENT_MIXED) &&
18216 	    (WXS_IS_RESTRICTION(type))) {
18217 	    /*
18218 	    * SPEC (2) If <restriction> + base is a mixed <complexType> with
18219 	    * an emptiable particle, then a simple type definition which
18220 	    * restricts the <restriction>'s <simpleType> child.
18221 	    */
18222 	    if ((type->contentTypeDef == NULL) ||
18223 		(type->contentTypeDef->baseType == NULL)) {
18224 		/*
18225 		* TODO: Check if this ever happens.
18226 		*/
18227 		xmlSchemaPCustomErr(pctxt,
18228 		    XML_SCHEMAP_INTERNAL,
18229 		    WXS_BASIC_CAST type, NULL,
18230 		    "Internal error: xmlSchemaTypeFixup, "
18231 		    "complex type '%s': the <simpleContent><restriction> "
18232 		    "is missing a <simpleType> child, but was not caught "
18233 		    "by xmlSchemaCheckSRCCT()", type->name);
18234 		goto exit_failure;
18235 	    }
18236 	} else if ((WXS_IS_COMPLEX(baseType)) && WXS_IS_EXTENSION(type)) {
18237 	    /*
18238 	    * SPEC (3) If <extension> + base is <complexType> with
18239 	    * <simpleType> content, "...then the {content type} of that
18240 	    * complex type definition"
18241 	    */
18242 	    if (baseType->contentTypeDef == NULL) {
18243 		/*
18244 		* TODO: Check if this ever happens. xmlSchemaCheckSRCCT
18245 		* should have caught this already.
18246 		*/
18247 		xmlSchemaPCustomErr(pctxt,
18248 		    XML_SCHEMAP_INTERNAL,
18249 		    WXS_BASIC_CAST type, NULL,
18250 		    "Internal error: xmlSchemaTypeFixup, "
18251 		    "complex type '%s': the <extension>ed base type is "
18252 		    "a complex type with no simple content type",
18253 		    type->name);
18254 		goto exit_failure;
18255 	    }
18256 	    type->contentTypeDef = baseType->contentTypeDef;
18257 	} else if ((WXS_IS_SIMPLE(baseType)) && WXS_IS_EXTENSION(type)) {
18258 	    /*
18259 	    * SPEC (4) <extension> + base is <simpleType>
18260 	    * "... then that simple type definition"
18261 	    */
18262 	    type->contentTypeDef = baseType;
18263 	} else {
18264 	    /*
18265 	    * TODO: Check if this ever happens.
18266 	    */
18267 	    xmlSchemaPCustomErr(pctxt,
18268 		XML_SCHEMAP_INTERNAL,
18269 		WXS_BASIC_CAST type, NULL,
18270 		"Internal error: xmlSchemaTypeFixup, "
18271 		"complex type '%s' with <simpleContent>: unhandled "
18272 		"derivation case", type->name);
18273 	    goto exit_failure;
18274 	}
18275     } else {
18276 	int dummySequence = 0;
18277 	xmlSchemaParticlePtr particle =
18278 	    (xmlSchemaParticlePtr) type->subtypes;
18279 	/*
18280 	* Corresponds to <complexType><complexContent>...
18281 	*
18282 	* NOTE that the effective mixed was already set during parsing of
18283 	* <complexType> and <complexContent>; its flag value is
18284 	* XML_SCHEMAS_TYPE_MIXED.
18285 	*
18286 	* Compute the "effective content":
18287 	* (2.1.1) + (2.1.2) + (2.1.3)
18288 	*/
18289 	if ((particle == NULL) ||
18290 	    ((particle->type == XML_SCHEMA_TYPE_PARTICLE) &&
18291 	    ((particle->children->type == XML_SCHEMA_TYPE_ALL) ||
18292 	    (particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) ||
18293 	    ((particle->children->type == XML_SCHEMA_TYPE_CHOICE) &&
18294 	    (particle->minOccurs == 0))) &&
18295 	    ( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) {
18296 	    if (type->flags & XML_SCHEMAS_TYPE_MIXED) {
18297 		/*
18298 		* SPEC (2.1.4) "If the `effective mixed` is true, then
18299 		* a particle whose properties are as follows:..."
18300 		*
18301 		* Empty sequence model group with
18302 		* minOccurs/maxOccurs = 1 (i.e. a "particle emptiable").
18303 		* NOTE that we sill assign it the <complexType> node to
18304 		* somehow anchor it in the doc.
18305 		*/
18306 		if ((particle == NULL) ||
18307 		    (particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) {
18308 		    /*
18309 		    * Create the particle.
18310 		    */
18311 		    particle = xmlSchemaAddParticle(pctxt,
18312 			type->node, 1, 1);
18313 		    if (particle == NULL)
18314 			goto exit_failure;
18315 		    /*
18316 		    * Create the model group.
18317 		    */ /* URGENT TODO: avoid adding to pending items. */
18318 		    particle->children = (xmlSchemaTreeItemPtr)
18319 			xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18320 			XML_SCHEMA_TYPE_SEQUENCE, type->node);
18321 		    if (particle->children == NULL)
18322 			goto exit_failure;
18323 
18324 		    type->subtypes = (xmlSchemaTypePtr) particle;
18325 		}
18326 		dummySequence = 1;
18327 		type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18328 	    } else {
18329 		/*
18330 		* SPEC (2.1.5) "otherwise empty"
18331 		*/
18332 		type->contentType = XML_SCHEMA_CONTENT_EMPTY;
18333 	    }
18334 	} else {
18335 	    /*
18336 	    * SPEC (2.2) "otherwise the particle corresponding to the
18337 	    * <all>, <choice>, <group> or <sequence> among the
18338 	    * [children]."
18339 	    */
18340 	    type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18341 	}
18342 	/*
18343 	* Compute the "content type".
18344 	*/
18345 	if (WXS_IS_RESTRICTION(type)) {
18346 	    /*
18347 	    * SPEC (3.1) "If <restriction>..."
18348 	    * (3.1.1) + (3.1.2) */
18349 	    if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) {
18350 		if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18351 		    type->contentType = XML_SCHEMA_CONTENT_MIXED;
18352 	    }
18353 	} else {
18354 	    /*
18355 	    * SPEC (3.2) "If <extension>..."
18356 	    */
18357 	    if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18358 		/*
18359 		* SPEC (3.2.1)
18360 		* "If the `effective content` is empty, then the
18361 		*  {content type} of the [...] base ..."
18362 		*/
18363 		type->contentType = baseType->contentType;
18364 		type->subtypes = baseType->subtypes;
18365 		/*
18366 		* Fixes bug #347316:
18367 		* This is the case when the base type has a simple
18368 		* type definition as content.
18369 		*/
18370 		type->contentTypeDef = baseType->contentTypeDef;
18371 		/*
18372 		* NOTE that the effective mixed is ignored here.
18373 		*/
18374 	    } else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18375 		/*
18376 		* SPEC (3.2.2)
18377 		*/
18378 		if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18379 		    type->contentType = XML_SCHEMA_CONTENT_MIXED;
18380 	    } else {
18381 		/*
18382 		* SPEC (3.2.3)
18383 		*/
18384 		if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18385 		    type->contentType = XML_SCHEMA_CONTENT_MIXED;
18386 		    /*
18387 		    * "A model group whose {compositor} is sequence and whose
18388 		    * {particles} are..."
18389 		    */
18390 		if ((WXS_TYPE_PARTICLE(type) != NULL) &&
18391 		    (WXS_TYPE_PARTICLE_TERM(type) != NULL) &&
18392 		    ((WXS_TYPE_PARTICLE_TERM(type))->type ==
18393 			XML_SCHEMA_TYPE_ALL))
18394 		{
18395 		    /*
18396 		    * SPEC cos-all-limited (1)
18397 		    */
18398 		    xmlSchemaCustomErr(ACTXT_CAST pctxt,
18399 			/* TODO: error code */
18400 			XML_SCHEMAP_COS_ALL_LIMITED,
18401 			WXS_ITEM_NODE(type), NULL,
18402 			"The type has an 'all' model group in its "
18403 			"{content type} and thus cannot be derived from "
18404 			"a non-empty type, since this would produce a "
18405 			"'sequence' model group containing the 'all' "
18406 			"model group; 'all' model groups are not "
18407 			"allowed to appear inside other model groups",
18408 			NULL, NULL);
18409 
18410 		} else if ((WXS_TYPE_PARTICLE(baseType) != NULL) &&
18411 		    (WXS_TYPE_PARTICLE_TERM(baseType) != NULL) &&
18412 		    ((WXS_TYPE_PARTICLE_TERM(baseType))->type ==
18413 			XML_SCHEMA_TYPE_ALL))
18414 		{
18415 		    /*
18416 		    * SPEC cos-all-limited (1)
18417 		    */
18418 		    xmlSchemaCustomErr(ACTXT_CAST pctxt,
18419 			/* TODO: error code */
18420 			XML_SCHEMAP_COS_ALL_LIMITED,
18421 			WXS_ITEM_NODE(type), NULL,
18422 			"A type cannot be derived by extension from a type "
18423 			"which has an 'all' model group in its "
18424 			"{content type}, since this would produce a "
18425 			"'sequence' model group containing the 'all' "
18426 			"model group; 'all' model groups are not "
18427 			"allowed to appear inside other model groups",
18428 			NULL, NULL);
18429 
18430 		} else if ((!dummySequence) && (baseType->subtypes != NULL)) {
18431 		    xmlSchemaTreeItemPtr effectiveContent =
18432 			(xmlSchemaTreeItemPtr) type->subtypes;
18433 		    /*
18434 		    * Create the particle.
18435 		    */
18436 		    particle = xmlSchemaAddParticle(pctxt,
18437 			type->node, 1, 1);
18438 		    if (particle == NULL)
18439 			goto exit_failure;
18440 		    /*
18441 		    * Create the "sequence" model group.
18442 		    */
18443 		    particle->children = (xmlSchemaTreeItemPtr)
18444 			xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18445 			XML_SCHEMA_TYPE_SEQUENCE, type->node);
18446 		    if (particle->children == NULL)
18447 			goto exit_failure;
18448 		    WXS_TYPE_CONTENTTYPE(type) = (xmlSchemaTypePtr) particle;
18449 		    /*
18450 		    * SPEC "the particle of the {content type} of
18451 		    * the ... base ..."
18452 		    * Create a duplicate of the base type's particle
18453 		    * and assign its "term" to it.
18454 		    */
18455 		    particle->children->children =
18456 			(xmlSchemaTreeItemPtr) xmlSchemaAddParticle(pctxt,
18457 			type->node,
18458 			((xmlSchemaParticlePtr) baseType->subtypes)->minOccurs,
18459 			((xmlSchemaParticlePtr) baseType->subtypes)->maxOccurs);
18460 		    if (particle->children->children == NULL)
18461 			goto exit_failure;
18462 		    particle = (xmlSchemaParticlePtr)
18463 			particle->children->children;
18464 		    particle->children =
18465 			((xmlSchemaParticlePtr) baseType->subtypes)->children;
18466 		    /*
18467 		    * SPEC "followed by the `effective content`."
18468 		    */
18469 		    particle->next = effectiveContent;
18470 		    /*
18471 		    * This all will result in:
18472 		    * new-particle
18473 		    *   --> new-sequence(
18474 		    *         new-particle
18475 		    *           --> base-model,
18476 		    *         this-particle
18477 		    *	        --> this-model
18478 		    *	    )
18479 		    */
18480 		} else {
18481 		    /*
18482 		    * This is the case when there is already an empty
18483 		    * <sequence> with minOccurs==maxOccurs==1.
18484 		    * Just add the base types's content type.
18485 		    * NOTE that, although we miss to add an intermediate
18486 		    * <sequence>, this should produce no difference to
18487 		    * neither the regex compilation of the content model,
18488 		    * nor to the complex type constraints.
18489 		    */
18490 		    particle->children->children =
18491 			(xmlSchemaTreeItemPtr) baseType->subtypes;
18492 		}
18493 	    }
18494 	}
18495     }
18496     /*
18497     * Now fixup attribute uses:
18498     *   - expand attr. group references
18499     *     - intersect attribute wildcards
18500     *   - inherit attribute uses of the base type
18501     *   - inherit or union attr. wildcards if extending
18502     *   - apply attr. use prohibitions if restricting
18503     */
18504     res = xmlSchemaFixupTypeAttributeUses(pctxt, type);
18505     HFAILURE HERROR
18506     /*
18507     * Apply the complex type component constraints; this will not
18508     * check attributes, since this is done in
18509     * xmlSchemaFixupTypeAttributeUses().
18510     */
18511     res = xmlSchemaCheckCTComponent(pctxt, type);
18512     HFAILURE HERROR
18513 
18514     if (olderrs != pctxt->nberrors)
18515 	return(pctxt->err);
18516     else
18517 	return(0);
18518 
18519 exit_error:
18520     type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18521     return(pctxt->err);
18522 
18523 exit_failure:
18524     type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18525     return(-1);
18526 }
18527 
18528 
18529 /**
18530  * xmlSchemaTypeFixup:
18531  * @typeDecl:  the schema type definition
18532  * @ctxt:  the schema parser context
18533  *
18534  * Fixes the content model of the type.
18535  * URGENT TODO: We need an int result!
18536  */
18537 static int
xmlSchemaTypeFixup(xmlSchemaTypePtr type,xmlSchemaAbstractCtxtPtr actxt)18538 xmlSchemaTypeFixup(xmlSchemaTypePtr type,
18539                    xmlSchemaAbstractCtxtPtr actxt)
18540 {
18541     if (type == NULL)
18542         return(0);
18543     if (actxt->type != XML_SCHEMA_CTXT_PARSER) {
18544 	AERROR_INT("xmlSchemaTypeFixup",
18545 	    "this function needs a parser context");
18546 	return(-1);
18547     }
18548     if (! WXS_IS_TYPE_NOT_FIXED(type))
18549 	return(0);
18550     if (type->type == XML_SCHEMA_TYPE_COMPLEX)
18551 	return(xmlSchemaFixupComplexType(PCTXT_CAST actxt, type));
18552     else if (type->type == XML_SCHEMA_TYPE_SIMPLE)
18553 	return(xmlSchemaFixupSimpleTypeStageTwo(PCTXT_CAST actxt, type));
18554     return(0);
18555 }
18556 
18557 /**
18558  * xmlSchemaCheckFacet:
18559  * @facet:  the facet
18560  * @typeDecl:  the schema type definition
18561  * @pctxt:  the schema parser context or NULL
18562  * @name: the optional name of the type
18563  *
18564  * Checks and computes the values of facets.
18565  *
18566  * Returns 0 if valid, a positive error code if not valid and
18567  *         -1 in case of an internal or API error.
18568  */
18569 int
xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,xmlSchemaTypePtr typeDecl,xmlSchemaParserCtxtPtr pctxt,const xmlChar * name ATTRIBUTE_UNUSED)18570 xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
18571                     xmlSchemaTypePtr typeDecl,
18572                     xmlSchemaParserCtxtPtr pctxt,
18573 		    const xmlChar * name ATTRIBUTE_UNUSED)
18574 {
18575     int ret = 0, ctxtGiven;
18576 
18577     if ((facet == NULL) || (typeDecl == NULL))
18578         return(-1);
18579     /*
18580     * TODO: will the parser context be given if used from
18581     * the relaxNG module?
18582     */
18583     if (pctxt == NULL)
18584 	ctxtGiven = 0;
18585     else
18586 	ctxtGiven = 1;
18587 
18588     switch (facet->type) {
18589         case XML_SCHEMA_FACET_MININCLUSIVE:
18590         case XML_SCHEMA_FACET_MINEXCLUSIVE:
18591         case XML_SCHEMA_FACET_MAXINCLUSIVE:
18592         case XML_SCHEMA_FACET_MAXEXCLUSIVE:
18593 	case XML_SCHEMA_FACET_ENUMERATION: {
18594                 /*
18595                  * Okay we need to validate the value
18596                  * at that point.
18597                  */
18598 		xmlSchemaTypePtr base;
18599 
18600 		/* 4.3.5.5 Constraints on enumeration Schema Components
18601 		* Schema Component Constraint: enumeration valid restriction
18602 		* It is an `error` if any member of {value} is not in the
18603 		* `value space` of {base type definition}.
18604 		*
18605 		* minInclusive, maxInclusive, minExclusive, maxExclusive:
18606 		* The value `must` be in the
18607 		* `value space` of the `base type`.
18608 		*/
18609 		/*
18610 		* This function is intended to deliver a compiled value
18611 		* on the facet. In this implementation of XML Schemata the
18612 		* type holding a facet, won't be a built-in type.
18613 		* Thus to ensure that other API
18614 		* calls (relaxng) do work, if the given type is a built-in
18615 		* type, we will assume that the given built-in type *is
18616 		* already* the base type.
18617 		*/
18618 		if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
18619 		    base = typeDecl->baseType;
18620 		    if (base == NULL) {
18621 			PERROR_INT("xmlSchemaCheckFacet",
18622 			    "a type user derived type has no base type");
18623 			return (-1);
18624 		    }
18625 		} else
18626 		    base = typeDecl;
18627 
18628 		if (! ctxtGiven) {
18629 		    /*
18630 		    * A context is needed if called from RelaxNG.
18631 		    */
18632 		    pctxt = xmlSchemaNewParserCtxt("*");
18633 		    if (pctxt == NULL)
18634 			return (-1);
18635 		}
18636 		/*
18637 		* NOTE: This call does not check the content nodes,
18638 		* since they are not available:
18639 		* facet->node is just the node holding the facet
18640 		* definition, *not* the attribute holding the *value*
18641 		* of the facet.
18642 		*/
18643 		ret = xmlSchemaVCheckCVCSimpleType(
18644 		    ACTXT_CAST pctxt, facet->node, base,
18645 		    facet->value, &(facet->val), 1, 1, 0);
18646                 if (ret != 0) {
18647 		    if (ret < 0) {
18648 			/* No error message for RelaxNG. */
18649 			if (ctxtGiven) {
18650 			    xmlSchemaCustomErr(ACTXT_CAST pctxt,
18651 				XML_SCHEMAP_INTERNAL, facet->node, NULL,
18652 				"Internal error: xmlSchemaCheckFacet, "
18653 				"failed to validate the value '%s' of the "
18654 				"facet '%s' against the base type",
18655 				facet->value, xmlSchemaFacetTypeToString(facet->type));
18656 			}
18657 			goto internal_error;
18658 		    }
18659 		    ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18660 		    /* No error message for RelaxNG. */
18661 		    if (ctxtGiven) {
18662 			xmlChar *str = NULL;
18663 
18664 			xmlSchemaCustomErr(ACTXT_CAST pctxt,
18665 			    ret, facet->node, WXS_BASIC_CAST facet,
18666 			    "The value '%s' of the facet does not validate "
18667 			    "against the base type '%s'",
18668 			    facet->value,
18669 			    xmlSchemaFormatQName(&str,
18670 				base->targetNamespace, base->name));
18671 			FREE_AND_NULL(str);
18672 		    }
18673 		    goto exit;
18674                 } else if (facet->val == NULL) {
18675 		    if (ctxtGiven) {
18676 			PERROR_INT("xmlSchemaCheckFacet",
18677 			    "value was not computed");
18678 		    }
18679 		    /* TODO */
18680 		}
18681                 break;
18682             }
18683         case XML_SCHEMA_FACET_PATTERN:
18684             facet->regexp = xmlRegexpCompile(facet->value);
18685             if (facet->regexp == NULL) {
18686 		ret = XML_SCHEMAP_REGEXP_INVALID;
18687 		/* No error message for RelaxNG. */
18688 		if (ctxtGiven) {
18689 		    xmlSchemaCustomErr(ACTXT_CAST pctxt,
18690 			ret, facet->node, WXS_BASIC_CAST typeDecl,
18691 			"The value '%s' of the facet 'pattern' is not a "
18692 			"valid regular expression",
18693 			facet->value, NULL);
18694 		}
18695             }
18696             break;
18697         case XML_SCHEMA_FACET_TOTALDIGITS:
18698         case XML_SCHEMA_FACET_FRACTIONDIGITS:
18699         case XML_SCHEMA_FACET_LENGTH:
18700         case XML_SCHEMA_FACET_MAXLENGTH:
18701         case XML_SCHEMA_FACET_MINLENGTH:
18702 
18703 	    if (facet->type == XML_SCHEMA_FACET_TOTALDIGITS) {
18704 		ret = xmlSchemaValidatePredefinedType(
18705 		    xmlSchemaGetBuiltInType(XML_SCHEMAS_PINTEGER),
18706 		    facet->value, &(facet->val));
18707 	    } else {
18708 		ret = xmlSchemaValidatePredefinedType(
18709 		    xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER),
18710 		    facet->value, &(facet->val));
18711 	    }
18712 	    if (ret != 0) {
18713 		if (ret < 0) {
18714 		    /* No error message for RelaxNG. */
18715 		    if (ctxtGiven) {
18716 			PERROR_INT("xmlSchemaCheckFacet",
18717 			    "validating facet value");
18718 		    }
18719 		    goto internal_error;
18720 		}
18721 		ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18722 		/* No error message for RelaxNG. */
18723 		if (ctxtGiven) {
18724 		    /* error code */
18725 		    xmlSchemaCustomErr4(ACTXT_CAST pctxt,
18726 			ret, facet->node, WXS_BASIC_CAST typeDecl,
18727 			"The value '%s' of the facet '%s' is not a valid '%s'",
18728 			facet->value,
18729 			xmlSchemaFacetTypeToString(facet->type),
18730 			(facet->type != XML_SCHEMA_FACET_TOTALDIGITS) ?
18731 			    BAD_CAST "nonNegativeInteger" :
18732 			    BAD_CAST "positiveInteger",
18733 			NULL);
18734 		}
18735 	    }
18736 	    break;
18737 
18738         case XML_SCHEMA_FACET_WHITESPACE:{
18739                 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
18740                     facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
18741                 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
18742                     facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
18743                 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
18744                     facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
18745                 } else {
18746 		    ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18747                     /* No error message for RelaxNG. */
18748 		    if (ctxtGiven) {
18749 			/* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */
18750 			xmlSchemaCustomErr(ACTXT_CAST pctxt,
18751 			    ret, facet->node, WXS_BASIC_CAST typeDecl,
18752 			    "The value '%s' of the facet 'whitespace' is not "
18753 			    "valid", facet->value, NULL);
18754                     }
18755                 }
18756             }
18757         default:
18758             break;
18759     }
18760 exit:
18761     if ((! ctxtGiven) && (pctxt != NULL))
18762 	xmlSchemaFreeParserCtxt(pctxt);
18763     return (ret);
18764 internal_error:
18765     if ((! ctxtGiven) && (pctxt != NULL))
18766 	xmlSchemaFreeParserCtxt(pctxt);
18767     return (-1);
18768 }
18769 
18770 /**
18771  * xmlSchemaCheckFacetValues:
18772  * @typeDecl:  the schema type definition
18773  * @ctxt:  the schema parser context
18774  *
18775  * Checks the default values types, especially for facets
18776  */
18777 static int
xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,xmlSchemaParserCtxtPtr pctxt)18778 xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
18779 			  xmlSchemaParserCtxtPtr pctxt)
18780 {
18781     int res, olderrs = pctxt->nberrors;
18782     const xmlChar *name = typeDecl->name;
18783     /*
18784     * NOTE: It is intended to use the facets list, instead
18785     * of facetSet.
18786     */
18787     if (typeDecl->facets != NULL) {
18788 	xmlSchemaFacetPtr facet = typeDecl->facets;
18789 
18790 	/*
18791 	* Temporarily assign the "schema" to the validation context
18792 	* of the parser context. This is needed for NOTATION validation.
18793 	*/
18794 	if (pctxt->vctxt == NULL) {
18795 	    if (xmlSchemaCreateVCtxtOnPCtxt(pctxt) == -1)
18796 		return(-1);
18797 	}
18798 	pctxt->vctxt->schema = pctxt->schema;
18799 	while (facet != NULL) {
18800 	    res = xmlSchemaCheckFacet(facet, typeDecl, pctxt, name);
18801 	    HFAILURE
18802 	    facet = facet->next;
18803 	}
18804 	pctxt->vctxt->schema = NULL;
18805     }
18806     if (olderrs != pctxt->nberrors)
18807 	return(pctxt->err);
18808     return(0);
18809 exit_failure:
18810     return(-1);
18811 }
18812 
18813 /**
18814  * xmlSchemaGetCircModelGrDefRef:
18815  * @ctxtMGroup: the searched model group
18816  * @selfMGroup: the second searched model group
18817  * @particle: the first particle
18818  *
18819  * This one is intended to be used by
18820  * xmlSchemaCheckGroupDefCircular only.
18821  *
18822  * Returns the particle with the circular model group definition reference,
18823  * otherwise NULL.
18824  */
18825 static xmlSchemaTreeItemPtr
xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,xmlSchemaTreeItemPtr particle)18826 xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,
18827 			      xmlSchemaTreeItemPtr particle)
18828 {
18829     xmlSchemaTreeItemPtr circ = NULL;
18830     xmlSchemaTreeItemPtr term;
18831     xmlSchemaModelGroupDefPtr gdef;
18832 
18833     for (; particle != NULL; particle = particle->next) {
18834 	term = particle->children;
18835 	if (term == NULL)
18836 	    continue;
18837 	switch (term->type) {
18838 	    case XML_SCHEMA_TYPE_GROUP:
18839 		gdef = (xmlSchemaModelGroupDefPtr) term;
18840 		if (gdef == groupDef)
18841 		    return (particle);
18842 		/*
18843 		* Mark this model group definition to avoid infinite
18844 		* recursion on circular references not yet examined.
18845 		*/
18846 		if (gdef->flags & XML_SCHEMA_MODEL_GROUP_DEF_MARKED)
18847 		    continue;
18848 		if (gdef->children != NULL) {
18849 		    gdef->flags |= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18850 		    circ = xmlSchemaGetCircModelGrDefRef(groupDef,
18851 			gdef->children->children);
18852 		    gdef->flags ^= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18853 		    if (circ != NULL)
18854 			return (circ);
18855 		}
18856 		break;
18857 	    case XML_SCHEMA_TYPE_SEQUENCE:
18858 	    case XML_SCHEMA_TYPE_CHOICE:
18859 	    case XML_SCHEMA_TYPE_ALL:
18860 		circ = xmlSchemaGetCircModelGrDefRef(groupDef, term->children);
18861 		if (circ != NULL)
18862 		    return (circ);
18863 		break;
18864 	    default:
18865 		break;
18866 	}
18867     }
18868     return (NULL);
18869 }
18870 
18871 /**
18872  * xmlSchemaCheckGroupDefCircular:
18873  * @item:  the model group definition
18874  * @ctxt:  the parser context
18875  * @name:  the name
18876  *
18877  * Checks for circular references to model group definitions.
18878  */
18879 static void
xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,xmlSchemaParserCtxtPtr ctxt)18880 xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,
18881 			       xmlSchemaParserCtxtPtr ctxt)
18882 {
18883     /*
18884     * Schema Component Constraint: Model Group Correct
18885     * 2 Circular groups are disallowed. That is, within the {particles}
18886     * of a group there must not be at any depth a particle whose {term}
18887     * is the group itself.
18888     */
18889     if ((item == NULL) ||
18890 	(item->type != XML_SCHEMA_TYPE_GROUP) ||
18891 	(item->children == NULL))
18892 	return;
18893     {
18894 	xmlSchemaTreeItemPtr circ;
18895 
18896 	circ = xmlSchemaGetCircModelGrDefRef(item, item->children->children);
18897 	if (circ != NULL) {
18898 	    xmlChar *str = NULL;
18899 	    /*
18900 	    * TODO: The error report is not adequate: this constraint
18901 	    * is defined for model groups but not definitions, but since
18902 	    * there cannot be any circular model groups without a model group
18903 	    * definition (if not using a construction API), we check those
18904 	    * definitions only.
18905 	    */
18906 	    xmlSchemaPCustomErr(ctxt,
18907 		XML_SCHEMAP_MG_PROPS_CORRECT_2,
18908 		NULL, WXS_ITEM_NODE(circ),
18909 		"Circular reference to the model group definition '%s' "
18910 		"defined", xmlSchemaFormatQName(&str,
18911 		    item->targetNamespace, item->name));
18912 	    FREE_AND_NULL(str)
18913 	    /*
18914 	    * NOTE: We will cut the reference to avoid further
18915 	    * confusion of the processor. This is a fatal error.
18916 	    */
18917 	    circ->children = NULL;
18918 	}
18919     }
18920 }
18921 
18922 /**
18923  * xmlSchemaModelGroupToModelGroupDefFixup:
18924  * @ctxt:  the parser context
18925  * @mg:  the model group
18926  *
18927  * Assigns the model group of model group definitions to the "term"
18928  * of the referencing particle.
18929  * In xmlSchemaResolveModelGroupParticleReferences the model group
18930  * definitions were assigned to the "term", since needed for the
18931  * circularity check.
18932  *
18933  * Schema Component Constraint:
18934  *     All Group Limited (cos-all-limited) (1.2)
18935  */
18936 static void
xmlSchemaModelGroupToModelGroupDefFixup(xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,xmlSchemaModelGroupPtr mg)18937 xmlSchemaModelGroupToModelGroupDefFixup(
18938     xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
18939     xmlSchemaModelGroupPtr mg)
18940 {
18941     xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
18942 
18943     while (particle != NULL) {
18944 	if ((WXS_PARTICLE_TERM(particle) == NULL) ||
18945 	    ((WXS_PARTICLE_TERM(particle))->type !=
18946 		XML_SCHEMA_TYPE_GROUP))
18947 	{
18948 	    particle = WXS_PTC_CAST particle->next;
18949 	    continue;
18950 	}
18951 	if (WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle)) == NULL) {
18952 	    /*
18953 	    * TODO: Remove the particle.
18954 	    */
18955 	    WXS_PARTICLE_TERM(particle) = NULL;
18956 	    particle = WXS_PTC_CAST particle->next;
18957 	    continue;
18958 	}
18959 	/*
18960 	* Assign the model group to the {term} of the particle.
18961 	*/
18962 	WXS_PARTICLE_TERM(particle) =
18963 	    WXS_TREE_CAST WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle));
18964 
18965 	particle = WXS_PTC_CAST particle->next;
18966     }
18967 }
18968 
18969 /**
18970  * xmlSchemaCheckAttrGroupCircularRecur:
18971  * @ctxtGr: the searched attribute group
18972  * @attr: the current attribute list to be processed
18973  *
18974  * This one is intended to be used by
18975  * xmlSchemaCheckAttrGroupCircular only.
18976  *
18977  * Returns the circular attribute group reference, otherwise NULL.
18978  */
18979 static xmlSchemaQNameRefPtr
xmlSchemaCheckAttrGroupCircularRecur(xmlSchemaAttributeGroupPtr ctxtGr,xmlSchemaItemListPtr list)18980 xmlSchemaCheckAttrGroupCircularRecur(xmlSchemaAttributeGroupPtr ctxtGr,
18981 				     xmlSchemaItemListPtr list)
18982 {
18983     xmlSchemaAttributeGroupPtr gr;
18984     xmlSchemaQNameRefPtr ref, circ;
18985     int i;
18986     /*
18987     * We will search for an attribute group reference which
18988     * references the context attribute group.
18989     */
18990     for (i = 0; i < list->nbItems; i++) {
18991 	ref = list->items[i];
18992 	if ((ref->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
18993 	    (ref->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
18994 	    (ref->item != NULL))
18995 	{
18996 	    gr = WXS_ATTR_GROUP_CAST ref->item;
18997 	    if (gr == ctxtGr)
18998 		return(ref);
18999 	    if (gr->flags & XML_SCHEMAS_ATTRGROUP_MARKED)
19000 		continue;
19001 	    /*
19002 	    * Mark as visited to avoid infinite recursion on
19003 	    * circular references not yet examined.
19004 	    */
19005 	    if ((gr->attrUses) &&
19006 		(gr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS))
19007 	    {
19008 		gr->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
19009 		circ = xmlSchemaCheckAttrGroupCircularRecur(ctxtGr,
19010 		    (xmlSchemaItemListPtr) gr->attrUses);
19011 		gr->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
19012 		if (circ != NULL)
19013 		    return (circ);
19014 	    }
19015 
19016 	}
19017     }
19018     return (NULL);
19019 }
19020 
19021 /**
19022  * xmlSchemaCheckAttrGroupCircular:
19023  * attrGr:  the attribute group definition
19024  * @ctxt:  the parser context
19025  * @name:  the name
19026  *
19027  * Checks for circular references of attribute groups.
19028  */
19029 static int
xmlSchemaCheckAttrGroupCircular(xmlSchemaAttributeGroupPtr attrGr,xmlSchemaParserCtxtPtr ctxt)19030 xmlSchemaCheckAttrGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
19031 				xmlSchemaParserCtxtPtr ctxt)
19032 {
19033     /*
19034     * Schema Representation Constraint:
19035     * Attribute Group Definition Representation OK
19036     * 3 Circular group reference is disallowed outside <redefine>.
19037     * That is, unless this element information item's parent is
19038     * <redefine>, then among the [children], if any, there must
19039     * not be an <attributeGroup> with ref [attribute] which resolves
19040     * to the component corresponding to this <attributeGroup>. Indirect
19041     * circularity is also ruled out. That is, when QName resolution
19042     * (Schema Document) ($3.15.3) is applied to a `QName` arising from
19043     * any <attributeGroup>s with a ref [attribute] among the [children],
19044     * it must not be the case that a `QName` is encountered at any depth
19045     * which resolves to the component corresponding to this <attributeGroup>.
19046     */
19047     if (attrGr->attrUses == NULL)
19048 	return(0);
19049     else if ((attrGr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS) == 0)
19050 	return(0);
19051     else {
19052 	xmlSchemaQNameRefPtr circ;
19053 
19054 	circ = xmlSchemaCheckAttrGroupCircularRecur(attrGr,
19055 	    (xmlSchemaItemListPtr) attrGr->attrUses);
19056 	if (circ != NULL) {
19057 	    xmlChar *str = NULL;
19058 	    /*
19059 	    * TODO: Report the referenced attr group as QName.
19060 	    */
19061 	    xmlSchemaPCustomErr(ctxt,
19062 		XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
19063 		NULL, WXS_ITEM_NODE(WXS_BASIC_CAST circ),
19064 		"Circular reference to the attribute group '%s' "
19065 		"defined", xmlSchemaGetComponentQName(&str, attrGr));
19066 	    FREE_AND_NULL(str);
19067 	    /*
19068 	    * NOTE: We will cut the reference to avoid further
19069 	    * confusion of the processor.
19070 	    * BADSPEC TODO: The spec should define how to process in this case.
19071 	    */
19072 	    circ->item = NULL;
19073 	    return(ctxt->err);
19074 	}
19075     }
19076     return(0);
19077 }
19078 
19079 static int
19080 xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19081 				  xmlSchemaAttributeGroupPtr attrGr);
19082 
19083 /**
19084  * xmlSchemaExpandAttributeGroupRefs:
19085  * @pctxt: the parser context
19086  * @node: the node of the component holding the attribute uses
19087  * @completeWild: the intersected wildcard to be returned
19088  * @list: the attribute uses
19089  *
19090  * Substitutes contained attribute group references
19091  * for their attribute uses. Wildcards are intersected.
19092  * Attribute use prohibitions are removed from the list
19093  * and returned via the @prohibs list.
19094  * Pointlessness of attr. prohibs, if a matching attr. decl
19095  * is existent a well, are checked.
19096  */
19097 static int
xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,xmlSchemaBasicItemPtr item,xmlSchemaWildcardPtr * completeWild,xmlSchemaItemListPtr list,xmlSchemaItemListPtr prohibs)19098 xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
19099 				  xmlSchemaBasicItemPtr item,
19100 				  xmlSchemaWildcardPtr *completeWild,
19101 				  xmlSchemaItemListPtr list,
19102 				  xmlSchemaItemListPtr prohibs)
19103 {
19104     xmlSchemaAttributeGroupPtr gr;
19105     xmlSchemaAttributeUsePtr use;
19106     xmlSchemaItemListPtr sublist;
19107     int i, j;
19108     int created = (*completeWild == NULL) ? 0 : 1;
19109 
19110     if (prohibs)
19111 	prohibs->nbItems = 0;
19112 
19113     for (i = 0; i < list->nbItems; i++) {
19114 	use = list->items[i];
19115 
19116 	if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
19117 	    if (prohibs == NULL) {
19118 		PERROR_INT("xmlSchemaExpandAttributeGroupRefs",
19119 		    "unexpected attr prohibition found");
19120 		return(-1);
19121 	    }
19122 	    /*
19123 	    * Remove from attribute uses.
19124 	    */
19125 	    if (xmlSchemaItemListRemove(list, i) == -1)
19126 		return(-1);
19127 	    i--;
19128 	    /*
19129 	    * Note that duplicate prohibitions were already
19130 	    * handled at parsing time.
19131 	    */
19132 	    /*
19133 	    * Add to list of prohibitions.
19134 	    */
19135 	    xmlSchemaItemListAddSize(prohibs, 2, use);
19136 	    continue;
19137 	}
19138 	if ((use->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
19139 	    ((WXS_QNAME_CAST use)->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP))
19140 	{
19141 	    if ((WXS_QNAME_CAST use)->item == NULL)
19142 		return(-1);
19143 	    gr = WXS_ATTR_GROUP_CAST (WXS_QNAME_CAST use)->item;
19144 	    /*
19145 	    * Expand the referenced attr. group.
19146 	    * TODO: remove this, this is done in a previous step, so
19147 	    * already done here.
19148 	    */
19149 	    if ((gr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
19150 		if (xmlSchemaAttributeGroupExpandRefs(pctxt, gr) == -1)
19151 		    return(-1);
19152 	    }
19153 	    /*
19154 	    * Build the 'complete' wildcard; i.e. intersect multiple
19155 	    * wildcards.
19156 	    */
19157 	    if (gr->attributeWildcard != NULL) {
19158 		if (*completeWild == NULL) {
19159 		    *completeWild = gr->attributeWildcard;
19160 		} else {
19161 		    if (! created) {
19162 			xmlSchemaWildcardPtr tmpWild;
19163 
19164 			 /*
19165 			* Copy the first encountered wildcard as context,
19166 			* except for the annotation.
19167 			*
19168 			* Although the complete wildcard might not correspond
19169 			* to any node in the schema, we will anchor it on
19170 			* the node of the owner component.
19171 			*/
19172 			tmpWild =  xmlSchemaAddWildcard(pctxt, pctxt->schema,
19173 			    XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
19174 			    WXS_ITEM_NODE(item));
19175 			if (tmpWild == NULL)
19176 			    return(-1);
19177 			if (xmlSchemaCloneWildcardNsConstraints(pctxt,
19178 			    tmpWild, *completeWild) == -1)
19179 			    return (-1);
19180 			tmpWild->processContents = (*completeWild)->processContents;
19181 			*completeWild = tmpWild;
19182 			created = 1;
19183 		    }
19184 
19185 		    if (xmlSchemaIntersectWildcards(pctxt, *completeWild,
19186 			gr->attributeWildcard) == -1)
19187 			return(-1);
19188 		}
19189 	    }
19190 	    /*
19191 	    * Just remove the reference if the referenced group does not
19192 	    * contain any attribute uses.
19193 	    */
19194 	    sublist = ((xmlSchemaItemListPtr) gr->attrUses);
19195 	    if ((sublist == NULL) || sublist->nbItems == 0) {
19196 		if (xmlSchemaItemListRemove(list, i) == -1)
19197 		    return(-1);
19198 		i--;
19199 		continue;
19200 	    }
19201 	    /*
19202 	    * Add the attribute uses.
19203 	    */
19204 	    list->items[i] = sublist->items[0];
19205 	    if (sublist->nbItems != 1) {
19206 		for (j = 1; j < sublist->nbItems; j++) {
19207 		    i++;
19208 		    if (xmlSchemaItemListInsert(list,
19209 			    sublist->items[j], i) == -1)
19210 			return(-1);
19211 		}
19212 	    }
19213 	}
19214 
19215     }
19216     /*
19217     * Handle pointless prohibitions of declared attributes.
19218     */
19219     if (prohibs && (prohibs->nbItems != 0) && (list->nbItems != 0)) {
19220 	xmlSchemaAttributeUseProhibPtr prohib;
19221 
19222 	for (i = prohibs->nbItems -1; i >= 0; i--) {
19223 	    prohib = prohibs->items[i];
19224 	    for (j = 0; j < list->nbItems; j++) {
19225 		use = list->items[j];
19226 
19227 		if ((prohib->name == WXS_ATTRUSE_DECL_NAME(use)) &&
19228 		    (prohib->targetNamespace == WXS_ATTRUSE_DECL_TNS(use)))
19229 		{
19230 		    xmlChar *str = NULL;
19231 
19232 		    xmlSchemaCustomWarning(ACTXT_CAST pctxt,
19233 			XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
19234 			prohib->node, NULL,
19235 			"Skipping pointless attribute use prohibition "
19236 			"'%s', since a corresponding attribute use "
19237 			"exists already in the type definition",
19238 			xmlSchemaFormatQName(&str,
19239 			    prohib->targetNamespace, prohib->name),
19240 			NULL, NULL);
19241 		    FREE_AND_NULL(str);
19242 		    /*
19243 		    * Remove the prohibition.
19244 		    */
19245 		    if (xmlSchemaItemListRemove(prohibs, i) == -1)
19246 			return(-1);
19247 		    break;
19248 		}
19249 	    }
19250 	}
19251     }
19252     return(0);
19253 }
19254 
19255 /**
19256  * xmlSchemaAttributeGroupExpandRefs:
19257  * @pctxt:  the parser context
19258  * @attrGr:  the attribute group definition
19259  *
19260  * Computation of:
19261  * {attribute uses} property
19262  * {attribute wildcard} property
19263  *
19264  * Substitutes contained attribute group references
19265  * for their attribute uses. Wildcards are intersected.
19266  */
19267 static int
xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,xmlSchemaAttributeGroupPtr attrGr)19268 xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19269 				  xmlSchemaAttributeGroupPtr attrGr)
19270 {
19271     if ((attrGr->attrUses == NULL) ||
19272 	(attrGr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED))
19273 	return(0);
19274 
19275     attrGr->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
19276     if (xmlSchemaExpandAttributeGroupRefs(pctxt, WXS_BASIC_CAST attrGr,
19277 	&(attrGr->attributeWildcard), attrGr->attrUses, NULL) == -1)
19278 	return(-1);
19279     return(0);
19280 }
19281 
19282 /**
19283  * xmlSchemaAttributeGroupExpandRefs:
19284  * @pctxt:  the parser context
19285  * @attrGr:  the attribute group definition
19286  *
19287  * Substitutes contained attribute group references
19288  * for their attribute uses. Wildcards are intersected.
19289  *
19290  * Schema Component Constraint:
19291  *    Attribute Group Definition Properties Correct (ag-props-correct)
19292  */
19293 static int
xmlSchemaCheckAGPropsCorrect(xmlSchemaParserCtxtPtr pctxt,xmlSchemaAttributeGroupPtr attrGr)19294 xmlSchemaCheckAGPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19295 				  xmlSchemaAttributeGroupPtr attrGr)
19296 {
19297     /*
19298     * SPEC ag-props-correct
19299     * (1) "The values of the properties of an attribute group definition
19300     * must be as described in the property tableau in The Attribute
19301     * Group Definition Schema Component ($3.6.1), modulo the impact of
19302     * Missing Sub-components ($5.3);"
19303     */
19304 
19305     if ((attrGr->attrUses != NULL) &&
19306 	(WXS_LIST_CAST attrGr->attrUses)->nbItems > 1)
19307     {
19308 	xmlSchemaItemListPtr uses = WXS_LIST_CAST attrGr->attrUses;
19309 	xmlSchemaAttributeUsePtr use, tmp;
19310 	int i, j, hasId = 0;
19311 
19312 	for (i = uses->nbItems -1; i >= 0; i--) {
19313 	    use = uses->items[i];
19314 	    /*
19315 	    * SPEC ag-props-correct
19316 	    * (2) "Two distinct members of the {attribute uses} must not have
19317 	    * {attribute declaration}s both of whose {name}s match and whose
19318 	    * {target namespace}s are identical."
19319 	    */
19320 	    if (i > 0) {
19321 		for (j = i -1; j >= 0; j--) {
19322 		    tmp = uses->items[j];
19323 		    if ((WXS_ATTRUSE_DECL_NAME(use) ==
19324 			WXS_ATTRUSE_DECL_NAME(tmp)) &&
19325 			(WXS_ATTRUSE_DECL_TNS(use) ==
19326 			WXS_ATTRUSE_DECL_TNS(tmp)))
19327 		    {
19328 			xmlChar *str = NULL;
19329 
19330 			xmlSchemaCustomErr(ACTXT_CAST pctxt,
19331 			    XML_SCHEMAP_AG_PROPS_CORRECT,
19332 			    attrGr->node, WXS_BASIC_CAST attrGr,
19333 			    "Duplicate %s",
19334 			    xmlSchemaGetComponentDesignation(&str, use),
19335 			    NULL);
19336 			FREE_AND_NULL(str);
19337 			/*
19338 			* Remove the duplicate.
19339 			*/
19340 			if (xmlSchemaItemListRemove(uses, i) == -1)
19341 			    return(-1);
19342 			goto next_use;
19343 		    }
19344 		}
19345 	    }
19346 	    /*
19347 	    * SPEC ag-props-correct
19348 	    * (3) "Two distinct members of the {attribute uses} must not have
19349 	    * {attribute declaration}s both of whose {type definition}s are or
19350 	    * are derived from ID."
19351 	    * TODO: Does 'derived' include member-types of unions?
19352 	    */
19353 	    if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
19354 		if (xmlSchemaIsDerivedFromBuiltInType(
19355 		    WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
19356 		{
19357 		    if (hasId) {
19358 			xmlChar *str = NULL;
19359 
19360 			xmlSchemaCustomErr(ACTXT_CAST pctxt,
19361 			    XML_SCHEMAP_AG_PROPS_CORRECT,
19362 			    attrGr->node, WXS_BASIC_CAST attrGr,
19363 			    "There must not exist more than one attribute "
19364 			    "declaration of type 'xs:ID' "
19365 			    "(or derived from 'xs:ID'). The %s violates this "
19366 			    "constraint",
19367 			    xmlSchemaGetComponentDesignation(&str, use),
19368 			    NULL);
19369 			FREE_AND_NULL(str);
19370 			if (xmlSchemaItemListRemove(uses, i) == -1)
19371 			    return(-1);
19372 		    }
19373 		    hasId = 1;
19374 		}
19375 	    }
19376 next_use: {}
19377 	}
19378     }
19379     return(0);
19380 }
19381 
19382 /**
19383  * xmlSchemaResolveAttrGroupReferences:
19384  * @attrgrpDecl:  the schema attribute definition
19385  * @ctxt:  the schema parser context
19386  * @name:  the attribute name
19387  *
19388  * Resolves references to attribute group definitions.
19389  */
19390 static int
xmlSchemaResolveAttrGroupReferences(xmlSchemaQNameRefPtr ref,xmlSchemaParserCtxtPtr ctxt)19391 xmlSchemaResolveAttrGroupReferences(xmlSchemaQNameRefPtr ref,
19392 				    xmlSchemaParserCtxtPtr ctxt)
19393 {
19394     xmlSchemaAttributeGroupPtr group;
19395 
19396     if (ref->item != NULL)
19397         return(0);
19398     group = xmlSchemaGetAttributeGroup(ctxt->schema,
19399 	ref->name,
19400 	ref->targetNamespace);
19401     if (group == NULL) {
19402 	xmlSchemaPResCompAttrErr(ctxt,
19403 	    XML_SCHEMAP_SRC_RESOLVE,
19404 	    NULL, ref->node,
19405 	    "ref", ref->name, ref->targetNamespace,
19406 	    ref->itemType, NULL);
19407 	return(ctxt->err);
19408     }
19409     ref->item = WXS_BASIC_CAST group;
19410     return(0);
19411 }
19412 
19413 /**
19414  * xmlSchemaCheckAttrPropsCorrect:
19415  * @item:  an schema attribute declaration/use
19416  * @ctxt:  a schema parser context
19417  * @name:  the name of the attribute
19418  *
19419  *
19420  * Schema Component Constraint:
19421  *    Attribute Declaration Properties Correct (a-props-correct)
19422  *
19423  * Validates the value constraints of an attribute declaration/use.
19424  * NOTE that this needs the simple type definitions to be already
19425  *   built and checked.
19426  */
19427 static int
xmlSchemaCheckAttrPropsCorrect(xmlSchemaParserCtxtPtr pctxt,xmlSchemaAttributePtr attr)19428 xmlSchemaCheckAttrPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19429 			       xmlSchemaAttributePtr attr)
19430 {
19431 
19432     /*
19433     * SPEC a-props-correct (1)
19434     * "The values of the properties of an attribute declaration must
19435     * be as described in the property tableau in The Attribute
19436     * Declaration Schema Component ($3.2.1), modulo the impact of
19437     * Missing Sub-components ($5.3)."
19438     */
19439 
19440     if (WXS_ATTR_TYPEDEF(attr) == NULL)
19441 	return(0);
19442 
19443     if (attr->defValue != NULL) {
19444 	int ret;
19445 
19446 	/*
19447 	* SPEC a-props-correct (3)
19448 	* "If the {type definition} is or is derived from ID then there
19449 	* must not be a {value constraint}."
19450 	*/
19451 	if (xmlSchemaIsDerivedFromBuiltInType(
19452 	    WXS_ATTR_TYPEDEF(attr), XML_SCHEMAS_ID))
19453 	{
19454 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
19455 		XML_SCHEMAP_A_PROPS_CORRECT_3,
19456 		NULL, WXS_BASIC_CAST attr,
19457 		"Value constraints are not allowed if the type definition "
19458 		"is or is derived from xs:ID",
19459 		NULL, NULL);
19460 	    return(pctxt->err);
19461 	}
19462 	/*
19463 	* SPEC a-props-correct (2)
19464 	* "if there is a {value constraint}, the canonical lexical
19465 	* representation of its value must be `valid` with respect
19466 	* to the {type definition} as defined in String Valid ($3.14.4)."
19467 	* TODO: Don't care about the *canonical* stuff here, this requirement
19468 	* will be removed in WXS 1.1 anyway.
19469 	*/
19470 	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt,
19471 	    attr->node, WXS_ATTR_TYPEDEF(attr),
19472 	    attr->defValue, &(attr->defVal),
19473 	    1, 1, 0);
19474 	if (ret != 0) {
19475 	    if (ret < 0) {
19476 		PERROR_INT("xmlSchemaCheckAttrPropsCorrect",
19477 		    "calling xmlSchemaVCheckCVCSimpleType()");
19478 		return(-1);
19479 	    }
19480 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
19481 		XML_SCHEMAP_A_PROPS_CORRECT_2,
19482 		NULL, WXS_BASIC_CAST attr,
19483 		"The value of the value constraint is not valid",
19484 		NULL, NULL);
19485 	    return(pctxt->err);
19486 	}
19487     }
19488 
19489     return(0);
19490 }
19491 
19492 static xmlSchemaElementPtr
xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,xmlSchemaElementPtr ancestor)19493 xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,
19494 				 xmlSchemaElementPtr ancestor)
19495 {
19496     xmlSchemaElementPtr ret;
19497 
19498     if (WXS_SUBST_HEAD(ancestor) == NULL)
19499 	return (NULL);
19500     if (WXS_SUBST_HEAD(ancestor) == elemDecl)
19501 	return (ancestor);
19502 
19503     if (WXS_SUBST_HEAD(ancestor)->flags & XML_SCHEMAS_ELEM_CIRCULAR)
19504 	return (NULL);
19505     WXS_SUBST_HEAD(ancestor)->flags |= XML_SCHEMAS_ELEM_CIRCULAR;
19506     ret = xmlSchemaCheckSubstGroupCircular(elemDecl,
19507 	WXS_SUBST_HEAD(ancestor));
19508     WXS_SUBST_HEAD(ancestor)->flags ^= XML_SCHEMAS_ELEM_CIRCULAR;
19509 
19510     return (ret);
19511 }
19512 
19513 /**
19514  * xmlSchemaCheckElemPropsCorrect:
19515  * @ctxt:  a schema parser context
19516  * @decl: the element declaration
19517  * @name:  the name of the attribute
19518  *
19519  * Schema Component Constraint:
19520  * Element Declaration Properties Correct (e-props-correct)
19521  *
19522  * STATUS:
19523  *   missing: (6)
19524  */
19525 static int
xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,xmlSchemaElementPtr elemDecl)19526 xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19527 			       xmlSchemaElementPtr elemDecl)
19528 {
19529     int ret = 0;
19530     xmlSchemaTypePtr typeDef = WXS_ELEM_TYPEDEF(elemDecl);
19531     /*
19532     * SPEC (1) "The values of the properties of an element declaration
19533     * must be as described in the property tableau in The Element
19534     * Declaration Schema Component ($3.3.1), modulo the impact of Missing
19535     * Sub-components ($5.3)."
19536     */
19537     if (WXS_SUBST_HEAD(elemDecl) != NULL) {
19538 	xmlSchemaElementPtr head = WXS_SUBST_HEAD(elemDecl), circ;
19539 
19540 	xmlSchemaCheckElementDeclComponent(head, pctxt);
19541 	/*
19542 	* SPEC (3) "If there is a non-`absent` {substitution group
19543 	* affiliation}, then {scope} must be global."
19544 	*/
19545 	if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
19546 	    xmlSchemaPCustomErr(pctxt,
19547 		XML_SCHEMAP_E_PROPS_CORRECT_3,
19548 		WXS_BASIC_CAST elemDecl, NULL,
19549 		"Only global element declarations can have a "
19550 		"substitution group affiliation", NULL);
19551 	    ret = XML_SCHEMAP_E_PROPS_CORRECT_3;
19552 	}
19553 	/*
19554 	* TODO: SPEC (6) "Circular substitution groups are disallowed.
19555 	* That is, it must not be possible to return to an element declaration
19556 	* by repeatedly following the {substitution group affiliation}
19557 	* property."
19558 	*/
19559 	if (head == elemDecl)
19560 	    circ = head;
19561 	else if (WXS_SUBST_HEAD(head) != NULL)
19562 	    circ = xmlSchemaCheckSubstGroupCircular(head, head);
19563 	else
19564 	    circ = NULL;
19565 	if (circ != NULL) {
19566 	    xmlChar *strA = NULL, *strB = NULL;
19567 
19568 	    xmlSchemaPCustomErrExt(pctxt,
19569 		XML_SCHEMAP_E_PROPS_CORRECT_6,
19570 		WXS_BASIC_CAST circ, NULL,
19571 		"The element declaration '%s' defines a circular "
19572 		"substitution group to element declaration '%s'",
19573 		xmlSchemaGetComponentQName(&strA, circ),
19574 		xmlSchemaGetComponentQName(&strB, head),
19575 		NULL);
19576 	    FREE_AND_NULL(strA)
19577 	    FREE_AND_NULL(strB)
19578 	    ret = XML_SCHEMAP_E_PROPS_CORRECT_6;
19579 	}
19580 	/*
19581 	* SPEC (4) "If there is a {substitution group affiliation},
19582 	* the {type definition}
19583 	* of the element declaration must be validly derived from the {type
19584 	* definition} of the {substitution group affiliation}, given the value
19585 	* of the {substitution group exclusions} of the {substitution group
19586 	* affiliation}, as defined in Type Derivation OK (Complex) ($3.4.6)
19587 	* (if the {type definition} is complex) or as defined in
19588 	* Type Derivation OK (Simple) ($3.14.6) (if the {type definition} is
19589 	* simple)."
19590 	*
19591 	* NOTE: {substitution group exclusions} means the values of the
19592 	* attribute "final".
19593 	*/
19594 
19595 	if (typeDef != WXS_ELEM_TYPEDEF(WXS_SUBST_HEAD(elemDecl))) {
19596 	    int set = 0;
19597 
19598 	    if (head->flags & XML_SCHEMAS_ELEM_FINAL_EXTENSION)
19599 		set |= SUBSET_EXTENSION;
19600 	    if (head->flags & XML_SCHEMAS_ELEM_FINAL_RESTRICTION)
19601 		set |= SUBSET_RESTRICTION;
19602 
19603 	    if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST pctxt, typeDef,
19604 		WXS_ELEM_TYPEDEF(head), set) != 0) {
19605 		xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
19606 
19607 		ret = XML_SCHEMAP_E_PROPS_CORRECT_4;
19608 		xmlSchemaPCustomErrExt(pctxt,
19609 		    XML_SCHEMAP_E_PROPS_CORRECT_4,
19610 		    WXS_BASIC_CAST elemDecl, NULL,
19611 		    "The type definition '%s' was "
19612 		    "either rejected by the substitution group "
19613 		    "affiliation '%s', or not validly derived from its type "
19614 		    "definition '%s'",
19615 		    xmlSchemaGetComponentQName(&strA, typeDef),
19616 		    xmlSchemaGetComponentQName(&strB, head),
19617 		    xmlSchemaGetComponentQName(&strC, WXS_ELEM_TYPEDEF(head)));
19618 		FREE_AND_NULL(strA)
19619 		FREE_AND_NULL(strB)
19620 		FREE_AND_NULL(strC)
19621 	    }
19622 	}
19623     }
19624     /*
19625     * SPEC (5) "If the {type definition} or {type definition}'s
19626     * {content type}
19627     * is or is derived from ID then there must not be a {value constraint}.
19628     * Note: The use of ID as a type definition for elements goes beyond
19629     * XML 1.0, and should be avoided if backwards compatibility is desired"
19630     */
19631     if ((elemDecl->value != NULL) &&
19632 	((WXS_IS_SIMPLE(typeDef) &&
19633 	  xmlSchemaIsDerivedFromBuiltInType(typeDef, XML_SCHEMAS_ID)) ||
19634 	 (WXS_IS_COMPLEX(typeDef) &&
19635 	  WXS_HAS_SIMPLE_CONTENT(typeDef) &&
19636 	  xmlSchemaIsDerivedFromBuiltInType(typeDef->contentTypeDef,
19637 	    XML_SCHEMAS_ID)))) {
19638 
19639 	ret = XML_SCHEMAP_E_PROPS_CORRECT_5;
19640 	xmlSchemaPCustomErr(pctxt,
19641 	    XML_SCHEMAP_E_PROPS_CORRECT_5,
19642 	    WXS_BASIC_CAST elemDecl, NULL,
19643 	    "The type definition (or type definition's content type) is or "
19644 	    "is derived from ID; value constraints are not allowed in "
19645 	    "conjunction with such a type definition", NULL);
19646     } else if (elemDecl->value != NULL) {
19647 	int vcret;
19648 	xmlNodePtr node = NULL;
19649 
19650 	/*
19651 	* SPEC (2) "If there is a {value constraint}, the canonical lexical
19652 	* representation of its value must be `valid` with respect to the
19653 	* {type definition} as defined in Element Default Valid (Immediate)
19654 	* ($3.3.6)."
19655 	*/
19656 	if (typeDef == NULL) {
19657 	    xmlSchemaPErr(pctxt, elemDecl->node,
19658 		XML_SCHEMAP_INTERNAL,
19659 		"Internal error: xmlSchemaCheckElemPropsCorrect, "
19660 		"type is missing... skipping validation of "
19661 		"the value constraint", NULL, NULL);
19662 	    return (-1);
19663 	}
19664 	if (elemDecl->node != NULL) {
19665 	    if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
19666 		node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19667 		    BAD_CAST "fixed");
19668 	    else
19669 		node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19670 		    BAD_CAST "default");
19671 	}
19672 	vcret = xmlSchemaParseCheckCOSValidDefault(pctxt, node,
19673 	    typeDef, elemDecl->value, &(elemDecl->defVal));
19674 	if (vcret != 0) {
19675 	    if (vcret < 0) {
19676 		PERROR_INT("xmlSchemaElemCheckValConstr",
19677 		    "failed to validate the value constraint of an "
19678 		    "element declaration");
19679 		return (-1);
19680 	    }
19681 	    return (vcret);
19682 	}
19683     }
19684 
19685     return (ret);
19686 }
19687 
19688 /**
19689  * xmlSchemaCheckElemSubstGroup:
19690  * @ctxt:  a schema parser context
19691  * @decl: the element declaration
19692  * @name:  the name of the attribute
19693  *
19694  * Schema Component Constraint:
19695  * Substitution Group (cos-equiv-class)
19696  *
19697  * In Libxml2 the subst. groups will be precomputed, in terms of that
19698  * a list will be built for each subst. group head, holding all direct
19699  * referents to this head.
19700  * NOTE that this function needs:
19701  *   1. circular subst. groups to be checked beforehand
19702  *   2. the declaration's type to be derived from the head's type
19703  *
19704  * STATUS:
19705  *
19706  */
19707 static void
xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,xmlSchemaElementPtr elemDecl)19708 xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,
19709 			     xmlSchemaElementPtr elemDecl)
19710 {
19711     if ((WXS_SUBST_HEAD(elemDecl) == NULL) ||
19712 	/* SPEC (1) "Its {abstract} is false." */
19713 	(elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT))
19714 	return;
19715     {
19716 	xmlSchemaElementPtr head;
19717 	xmlSchemaTypePtr headType, type;
19718 	int set, methSet;
19719 	/*
19720 	* SPEC (2) "It is validly substitutable for HEAD subject to HEAD's
19721 	* {disallowed substitutions} as the blocking constraint, as defined in
19722 	* Substitution Group OK (Transitive) ($3.3.6)."
19723 	*/
19724 	for (head = WXS_SUBST_HEAD(elemDecl); head != NULL;
19725 	    head = WXS_SUBST_HEAD(head)) {
19726 	    set = 0;
19727 	    methSet = 0;
19728 	    /*
19729 	    * The blocking constraints.
19730 	    */
19731 	    if (head->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION)
19732 		continue;
19733 	    headType = head->subtypes;
19734 	    type = elemDecl->subtypes;
19735 	    if (headType == type)
19736 		goto add_member;
19737 	    if (head->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION)
19738 		set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19739 	    if (head->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION)
19740 		set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19741 	    /*
19742 	    * SPEC: Substitution Group OK (Transitive) (2.3)
19743 	    * "The set of all {derivation method}s involved in the
19744 	    * derivation of D's {type definition} from C's {type definition}
19745 	    * does not intersect with the union of the blocking constraint,
19746 	    * C's {prohibited substitutions} (if C is complex, otherwise the
19747 	    * empty set) and the {prohibited substitutions} (respectively the
19748 	    * empty set) of any intermediate {type definition}s in the
19749 	    * derivation of D's {type definition} from C's {type definition}."
19750 	    */
19751 	    /*
19752 	    * OPTIMIZE TODO: Optimize this a bit, since, if traversing the
19753 	    * subst.head axis, the methSet does not need to be computed for
19754 	    * the full depth over and over.
19755 	    */
19756 	    /*
19757 	    * The set of all {derivation method}s involved in the derivation
19758 	    */
19759 	    while ((type != NULL) && (type != headType) &&
19760                    (type != type->baseType)) {
19761 		if ((WXS_IS_EXTENSION(type)) &&
19762 		    ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19763 		    methSet |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19764 
19765 		if (WXS_IS_RESTRICTION(type) &&
19766 		    ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19767 		    methSet |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19768 
19769 		type = type->baseType;
19770 	    }
19771 	    /*
19772 	    * The {prohibited substitutions} of all intermediate types +
19773 	    * the head's type.
19774 	    */
19775 	    type = elemDecl->subtypes->baseType;
19776 	    while (type != NULL) {
19777 		if (WXS_IS_COMPLEX(type)) {
19778 		    if ((type->flags &
19779 			    XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19780 			((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) == 0))
19781 		    set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19782 		    if ((type->flags &
19783 			    XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19784 			((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19785 		    set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19786 		} else
19787 		    break;
19788 		if (type == headType)
19789 		    break;
19790 		type = type->baseType;
19791 	    }
19792 	    if ((set != 0) &&
19793 		(((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19794 		(methSet & XML_SCHEMAS_TYPE_BLOCK_EXTENSION)) ||
19795 		((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19796 		(methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION)))) {
19797 		continue;
19798 	    }
19799 add_member:
19800 	    xmlSchemaAddElementSubstitutionMember(ctxt, head, elemDecl);
19801 	    if ((head->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) == 0)
19802 		head->flags |= XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD;
19803 	}
19804     }
19805 }
19806 
19807 #ifdef WXS_ELEM_DECL_CONS_ENABLED /* enable when finished */
19808 /**
19809  * xmlSchemaCheckElementDeclComponent
19810  * @pctxt: the schema parser context
19811  * @ctxtComponent: the context component (an element declaration)
19812  * @ctxtParticle: the first particle of the context component
19813  * @searchParticle: the element declaration particle to be analysed
19814  *
19815  * Schema Component Constraint: Element Declarations Consistent
19816  */
19817 static int
xmlSchemaCheckElementDeclConsistent(xmlSchemaParserCtxtPtr pctxt,xmlSchemaBasicItemPtr ctxtComponent,xmlSchemaParticlePtr ctxtParticle,xmlSchemaParticlePtr searchParticle,xmlSchemaParticlePtr curParticle,int search)19818 xmlSchemaCheckElementDeclConsistent(xmlSchemaParserCtxtPtr pctxt,
19819 				    xmlSchemaBasicItemPtr ctxtComponent,
19820 				    xmlSchemaParticlePtr ctxtParticle,
19821 				    xmlSchemaParticlePtr searchParticle,
19822 				    xmlSchemaParticlePtr curParticle,
19823 				    int search)
19824 {
19825     return(0);
19826 
19827     int ret = 0;
19828     xmlSchemaParticlePtr cur = curParticle;
19829     if (curParticle == NULL) {
19830 	return(0);
19831     }
19832     if (WXS_PARTICLE_TERM(curParticle) == NULL) {
19833 	/*
19834 	* Just return in this case. A missing "term" of the particle
19835 	* might arise due to an invalid "term" component.
19836 	*/
19837 	return(0);
19838     }
19839     while (cur != NULL) {
19840 	switch (WXS_PARTICLE_TERM(cur)->type) {
19841 	    case XML_SCHEMA_TYPE_ANY:
19842 		break;
19843 	    case XML_SCHEMA_TYPE_ELEMENT:
19844 		if (search == 0) {
19845 		    ret = xmlSchemaCheckElementDeclConsistent(pctxt,
19846 			ctxtComponent, ctxtParticle, cur, ctxtParticle, 1);
19847 		    if (ret != 0)
19848 			return(ret);
19849 		} else {
19850 		    xmlSchemaElementPtr elem =
19851 			WXS_ELEM_CAST(WXS_PARTICLE_TERM(cur));
19852 		    /*
19853 		    * SPEC Element Declarations Consistent:
19854 		    * "If the {particles} contains, either directly,
19855 		    * indirectly (that is, within the {particles} of a
19856 		    * contained model group, recursively) or `implicitly`
19857 		    * two or more element declaration particles with
19858 		    * the same {name} and {target namespace}, then
19859 		    * all their type definitions must be the same
19860 		    * top-level definition [...]"
19861 		    */
19862 		    if (xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->name,
19863 			    WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->name) &&
19864 			xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamespace,
19865 			    WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->targetNamespace))
19866 		    {
19867 			xmlChar *strA = NULL, *strB = NULL;
19868 
19869 			xmlSchemaCustomErr(ACTXT_CAST pctxt,
19870 			    /* TODO: error code */
19871 			    XML_SCHEMAP_COS_NONAMBIG,
19872 			    WXS_ITEM_NODE(cur), NULL,
19873 			    "In the content model of %s, there are multiple "
19874 			    "element declarations for '%s' with different "
19875 			    "type definitions",
19876 			    xmlSchemaGetComponentDesignation(&strA,
19877 				ctxtComponent),
19878 			    xmlSchemaFormatQName(&strB,
19879 				WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamespace,
19880 				WXS_PARTICLE_TERM_AS_ELEM(cur)->name));
19881 			FREE_AND_NULL(strA);
19882 			FREE_AND_NULL(strB);
19883 			return(XML_SCHEMAP_COS_NONAMBIG);
19884 		    }
19885 		}
19886 		break;
19887 	    case XML_SCHEMA_TYPE_SEQUENCE: {
19888 		break;
19889 		}
19890 	    case XML_SCHEMA_TYPE_CHOICE:{
19891 		/*
19892 		xmlSchemaTreeItemPtr sub;
19893 
19894 		sub = WXS_PARTICLE_TERM(particle)->children;  (xmlSchemaParticlePtr)
19895 		while (sub != NULL) {
19896 		    ret = xmlSchemaCheckElementDeclConsistent(pctxt, ctxtComponent,
19897 			ctxtParticle, ctxtElem);
19898 		    if (ret != 0)
19899 			return(ret);
19900 		    sub = sub->next;
19901 		}
19902 		*/
19903 		break;
19904 		}
19905 	    case XML_SCHEMA_TYPE_ALL:
19906 		break;
19907 	    case XML_SCHEMA_TYPE_GROUP:
19908 		break;
19909 	    default:
19910 		xmlSchemaInternalErr2(ACTXT_CAST pctxt,
19911 		    "xmlSchemaCheckElementDeclConsistent",
19912 		    "found unexpected term of type '%s' in content model",
19913 		    WXS_ITEM_TYPE_NAME(WXS_PARTICLE_TERM(cur)), NULL);
19914 		return(-1);
19915 	}
19916 	cur = (xmlSchemaParticlePtr) cur->next;
19917     }
19918 
19919 exit:
19920     return(ret);
19921 }
19922 #endif
19923 
19924 /**
19925  * xmlSchemaCheckElementDeclComponent
19926  * @item:  an schema element declaration/particle
19927  * @ctxt:  a schema parser context
19928  * @name:  the name of the attribute
19929  *
19930  * Validates the value constraints of an element declaration.
19931  * Adds substitution group members.
19932  */
19933 static void
xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,xmlSchemaParserCtxtPtr ctxt)19934 xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
19935 				   xmlSchemaParserCtxtPtr ctxt)
19936 {
19937     if (elemDecl == NULL)
19938 	return;
19939     if (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED)
19940 	return;
19941     elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_CHECKED;
19942     if (xmlSchemaCheckElemPropsCorrect(ctxt, elemDecl) == 0) {
19943 	/*
19944 	* Adds substitution group members.
19945 	*/
19946 	xmlSchemaCheckElemSubstGroup(ctxt, elemDecl);
19947     }
19948 }
19949 
19950 /**
19951  * xmlSchemaResolveModelGroupParticleReferences:
19952  * @particle:  a particle component
19953  * @ctxt:  a parser context
19954  *
19955  * Resolves references of a model group's {particles} to
19956  * model group definitions and to element declarations.
19957  */
19958 static void
xmlSchemaResolveModelGroupParticleReferences(xmlSchemaParserCtxtPtr ctxt,xmlSchemaModelGroupPtr mg)19959 xmlSchemaResolveModelGroupParticleReferences(
19960     xmlSchemaParserCtxtPtr ctxt,
19961     xmlSchemaModelGroupPtr mg)
19962 {
19963     xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
19964     xmlSchemaQNameRefPtr ref;
19965     xmlSchemaBasicItemPtr refItem;
19966 
19967     /*
19968     * URGENT TODO: Test this.
19969     */
19970     while (particle != NULL) {
19971 	if ((WXS_PARTICLE_TERM(particle) == NULL) ||
19972 	    ((WXS_PARTICLE_TERM(particle))->type !=
19973 		XML_SCHEMA_EXTRA_QNAMEREF))
19974 	{
19975 	    goto next_particle;
19976 	}
19977 	ref = WXS_QNAME_CAST WXS_PARTICLE_TERM(particle);
19978 	/*
19979 	* Resolve the reference.
19980 	* NULL the {term} by default.
19981 	*/
19982 	particle->children = NULL;
19983 
19984 	refItem = xmlSchemaGetNamedComponent(ctxt->schema,
19985 	    ref->itemType, ref->name, ref->targetNamespace);
19986 	if (refItem == NULL) {
19987 	    xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
19988 		NULL, WXS_ITEM_NODE(particle), "ref", ref->name,
19989 		ref->targetNamespace, ref->itemType, NULL);
19990 	    /* TODO: remove the particle. */
19991 	    goto next_particle;
19992 	}
19993 	if (refItem->type == XML_SCHEMA_TYPE_GROUP) {
19994 	    if (WXS_MODELGROUPDEF_MODEL(refItem) == NULL)
19995 		/* TODO: remove the particle. */
19996 		goto next_particle;
19997 	    /*
19998 	    * NOTE that we will assign the model group definition
19999 	    * itself to the "term" of the particle. This will ease
20000 	    * the check for circular model group definitions. After
20001 	    * that the "term" will be assigned the model group of the
20002 	    * model group definition.
20003 	    */
20004 	    if ((WXS_MODELGROUPDEF_MODEL(refItem))->type ==
20005 		    XML_SCHEMA_TYPE_ALL) {
20006 		/*
20007 		* SPEC cos-all-limited (1)
20008 		* SPEC cos-all-limited (1.2)
20009 		* "It appears only as the value of one or both of the
20010 		* following properties:"
20011 		* (1.1) "the {model group} property of a model group
20012 		*        definition."
20013 		* (1.2) "the {term} property of a particle [... of] the "
20014 		* {content type} of a complex type definition."
20015 		*/
20016 		xmlSchemaCustomErr(ACTXT_CAST ctxt,
20017 		    /* TODO: error code */
20018 		    XML_SCHEMAP_COS_ALL_LIMITED,
20019 		    WXS_ITEM_NODE(particle), NULL,
20020 		    "A model group definition is referenced, but "
20021 		    "it contains an 'all' model group, which "
20022 		    "cannot be contained by model groups",
20023 		    NULL, NULL);
20024 		/* TODO: remove the particle. */
20025 		goto next_particle;
20026 	    }
20027 	    particle->children = (xmlSchemaTreeItemPtr) refItem;
20028 	} else {
20029 	    /*
20030 	    * TODO: Are referenced element declarations the only
20031 	    * other components we expect here?
20032 	    */
20033 	    particle->children = (xmlSchemaTreeItemPtr) refItem;
20034 	}
20035 next_particle:
20036 	particle = WXS_PTC_CAST particle->next;
20037     }
20038 }
20039 
20040 static int
xmlSchemaAreValuesEqual(xmlSchemaValPtr x,xmlSchemaValPtr y)20041 xmlSchemaAreValuesEqual(xmlSchemaValPtr x,
20042 		       xmlSchemaValPtr y)
20043 {
20044     xmlSchemaTypePtr tx, ty, ptx, pty;
20045     int ret;
20046 
20047     while (x != NULL) {
20048 	/* Same types. */
20049 	tx = xmlSchemaGetBuiltInType(xmlSchemaGetValType(x));
20050 	ty = xmlSchemaGetBuiltInType(xmlSchemaGetValType(y));
20051 	ptx = xmlSchemaGetPrimitiveType(tx);
20052 	pty = xmlSchemaGetPrimitiveType(ty);
20053 	/*
20054 	* (1) if a datatype T' is `derived` by `restriction` from an
20055 	* atomic datatype T then the `value space` of T' is a subset of
20056 	* the `value space` of T. */
20057 	/*
20058 	* (2) if datatypes T' and T'' are `derived` by `restriction`
20059 	* from a common atomic ancestor T then the `value space`s of T'
20060 	* and T'' may overlap.
20061 	*/
20062 	if (ptx != pty)
20063 	    return(0);
20064 	/*
20065 	* We assume computed values to be normalized, so do a fast
20066 	* string comparison for string based types.
20067 	*/
20068 	if ((ptx->builtInType == XML_SCHEMAS_STRING) ||
20069 	    WXS_IS_ANY_SIMPLE_TYPE(ptx)) {
20070 	    if (! xmlStrEqual(
20071 		xmlSchemaValueGetAsString(x),
20072 		xmlSchemaValueGetAsString(y)))
20073 		return (0);
20074 	} else {
20075 	    ret = xmlSchemaCompareValuesWhtsp(
20076 		x, XML_SCHEMA_WHITESPACE_PRESERVE,
20077 		y, XML_SCHEMA_WHITESPACE_PRESERVE);
20078 	    if (ret == -2)
20079 		return(-1);
20080 	    if (ret != 0)
20081 		return(0);
20082 	}
20083 	/*
20084 	* Lists.
20085 	*/
20086 	x = xmlSchemaValueGetNext(x);
20087 	if (x != NULL) {
20088 	    y = xmlSchemaValueGetNext(y);
20089 	    if (y == NULL)
20090 		return (0);
20091 	} else if (xmlSchemaValueGetNext(y) != NULL)
20092 	    return (0);
20093 	else
20094 	    return (1);
20095     }
20096     return (0);
20097 }
20098 
20099 /**
20100  * xmlSchemaResolveAttrUseReferences:
20101  * @item:  an attribute use
20102  * @ctxt:  a parser context
20103  *
20104  * Resolves the referenced attribute declaration.
20105  */
20106 static int
xmlSchemaResolveAttrUseReferences(xmlSchemaAttributeUsePtr ause,xmlSchemaParserCtxtPtr ctxt)20107 xmlSchemaResolveAttrUseReferences(xmlSchemaAttributeUsePtr ause,
20108 				  xmlSchemaParserCtxtPtr ctxt)
20109 {
20110     if ((ctxt == NULL) || (ause == NULL))
20111 	return(-1);
20112     if ((ause->attrDecl == NULL) ||
20113 	(ause->attrDecl->type != XML_SCHEMA_EXTRA_QNAMEREF))
20114 	return(0);
20115 
20116     {
20117 	xmlSchemaQNameRefPtr ref = WXS_QNAME_CAST ause->attrDecl;
20118 
20119 	/*
20120 	* TODO: Evaluate, what errors could occur if the declaration is not
20121 	* found.
20122 	*/
20123 	ause->attrDecl = xmlSchemaGetAttributeDecl(ctxt->schema,
20124 	    ref->name, ref->targetNamespace);
20125         if (ause->attrDecl == NULL) {
20126 	    xmlSchemaPResCompAttrErr(ctxt,
20127 		XML_SCHEMAP_SRC_RESOLVE,
20128 		WXS_BASIC_CAST ause, ause->node,
20129 		"ref", ref->name, ref->targetNamespace,
20130 		XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20131             return(ctxt->err);;
20132         }
20133     }
20134     return(0);
20135 }
20136 
20137 /**
20138  * xmlSchemaCheckAttrUsePropsCorrect:
20139  * @ctxt:  a parser context
20140  * @use:  an attribute use
20141  *
20142  * Schema Component Constraint:
20143  * Attribute Use Correct (au-props-correct)
20144  *
20145  */
20146 static int
xmlSchemaCheckAttrUsePropsCorrect(xmlSchemaParserCtxtPtr ctxt,xmlSchemaAttributeUsePtr use)20147 xmlSchemaCheckAttrUsePropsCorrect(xmlSchemaParserCtxtPtr ctxt,
20148 			     xmlSchemaAttributeUsePtr use)
20149 {
20150     if ((ctxt == NULL) || (use == NULL))
20151 	return(-1);
20152     if ((use->defValue == NULL) || (WXS_ATTRUSE_DECL(use) == NULL) ||
20153 	((WXS_ATTRUSE_DECL(use))->type != XML_SCHEMA_TYPE_ATTRIBUTE))
20154 	return(0);
20155 
20156     /*
20157     * SPEC au-props-correct (1)
20158     * "The values of the properties of an attribute use must be as
20159     * described in the property tableau in The Attribute Use Schema
20160     * Component ($3.5.1), modulo the impact of Missing
20161     * Sub-components ($5.3)."
20162     */
20163 
20164     if (((WXS_ATTRUSE_DECL(use))->defValue != NULL) &&
20165 	((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMAS_ATTR_FIXED) &&
20166         ((use->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20167     {
20168 	xmlSchemaPCustomErr(ctxt,
20169 	    XML_SCHEMAP_AU_PROPS_CORRECT_2,
20170 	    WXS_BASIC_CAST use, NULL,
20171 	    "The attribute declaration has a 'fixed' value constraint "
20172 	    ", thus the attribute use must also have a 'fixed' value "
20173 	    "constraint",
20174 	    NULL);
20175 	return(ctxt->err);
20176     }
20177     /*
20178     * Compute and check the value constraint's value.
20179     */
20180     if ((use->defVal != NULL) && (WXS_ATTRUSE_TYPEDEF(use) != NULL)) {
20181 	int ret;
20182 	/*
20183 	* TODO: The spec seems to be missing a check of the
20184 	* value constraint of the attribute use. We will do it here.
20185 	*/
20186 	/*
20187 	* SPEC a-props-correct (3)
20188 	*/
20189 	if (xmlSchemaIsDerivedFromBuiltInType(
20190 	    WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
20191 	{
20192 	    xmlSchemaCustomErr(ACTXT_CAST ctxt,
20193 		XML_SCHEMAP_AU_PROPS_CORRECT,
20194 		NULL, WXS_BASIC_CAST use,
20195 		"Value constraints are not allowed if the type definition "
20196 		"is or is derived from xs:ID",
20197 		NULL, NULL);
20198 	    return(ctxt->err);
20199 	}
20200 
20201 	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST ctxt,
20202 	    use->node, WXS_ATTRUSE_TYPEDEF(use),
20203 	    use->defValue, &(use->defVal),
20204 	    1, 1, 0);
20205 	if (ret != 0) {
20206 	    if (ret < 0) {
20207 		PERROR_INT2("xmlSchemaCheckAttrUsePropsCorrect",
20208 		    "calling xmlSchemaVCheckCVCSimpleType()");
20209 		return(-1);
20210 	    }
20211 	    xmlSchemaCustomErr(ACTXT_CAST ctxt,
20212 		XML_SCHEMAP_AU_PROPS_CORRECT,
20213 		NULL, WXS_BASIC_CAST use,
20214 		"The value of the value constraint is not valid",
20215 		NULL, NULL);
20216 	    return(ctxt->err);
20217 	}
20218     }
20219     /*
20220     * SPEC au-props-correct (2)
20221     * "If the {attribute declaration} has a fixed
20222     * {value constraint}, then if the attribute use itself has a
20223     * {value constraint}, it must also be fixed and its value must match
20224     * that of the {attribute declaration}'s {value constraint}."
20225     */
20226     if (((WXS_ATTRUSE_DECL(use))->defVal != NULL) &&
20227 	(((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20228     {
20229 	if (! xmlSchemaAreValuesEqual(use->defVal,
20230 		(WXS_ATTRUSE_DECL(use))->defVal))
20231 	{
20232 	    xmlSchemaPCustomErr(ctxt,
20233 		XML_SCHEMAP_AU_PROPS_CORRECT_2,
20234 		WXS_BASIC_CAST use, NULL,
20235 		"The 'fixed' value constraint of the attribute use "
20236 		"must match the attribute declaration's value "
20237 		"constraint '%s'",
20238 		(WXS_ATTRUSE_DECL(use))->defValue);
20239 	}
20240 	return(ctxt->err);
20241     }
20242     return(0);
20243 }
20244 
20245 
20246 
20247 
20248 /**
20249  * xmlSchemaResolveAttrTypeReferences:
20250  * @item:  an attribute declaration
20251  * @ctxt:  a parser context
20252  *
20253  * Resolves the referenced type definition component.
20254  */
20255 static int
xmlSchemaResolveAttrTypeReferences(xmlSchemaAttributePtr item,xmlSchemaParserCtxtPtr ctxt)20256 xmlSchemaResolveAttrTypeReferences(xmlSchemaAttributePtr item,
20257 				   xmlSchemaParserCtxtPtr ctxt)
20258 {
20259     /*
20260     * The simple type definition corresponding to the <simpleType> element
20261     * information item in the [children], if present, otherwise the simple
20262     * type definition `resolved` to by the `actual value` of the type
20263     * [attribute], if present, otherwise the `simple ur-type definition`.
20264     */
20265     if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
20266 	return(0);
20267     item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
20268     if (item->subtypes != NULL)
20269         return(0);
20270     if (item->typeName != NULL) {
20271         xmlSchemaTypePtr type;
20272 
20273 	type = xmlSchemaGetType(ctxt->schema, item->typeName,
20274 	    item->typeNs);
20275 	if ((type == NULL) || (! WXS_IS_SIMPLE(type))) {
20276 	    xmlSchemaPResCompAttrErr(ctxt,
20277 		XML_SCHEMAP_SRC_RESOLVE,
20278 		WXS_BASIC_CAST item, item->node,
20279 		"type", item->typeName, item->typeNs,
20280 		XML_SCHEMA_TYPE_SIMPLE, NULL);
20281 	    return(ctxt->err);
20282 	} else
20283 	    item->subtypes = type;
20284 
20285     } else {
20286 	/*
20287 	* The type defaults to the xs:anySimpleType.
20288 	*/
20289 	item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
20290     }
20291     return(0);
20292 }
20293 
20294 /**
20295  * xmlSchemaResolveIDCKeyReferences:
20296  * @idc:  the identity-constraint definition
20297  * @ctxt:  the schema parser context
20298  * @name:  the attribute name
20299  *
20300  * Resolve keyRef references to key/unique IDCs.
20301  * Schema Component Constraint:
20302  *   Identity-constraint Definition Properties Correct (c-props-correct)
20303  */
20304 static int
xmlSchemaResolveIDCKeyReferences(xmlSchemaIDCPtr idc,xmlSchemaParserCtxtPtr pctxt)20305 xmlSchemaResolveIDCKeyReferences(xmlSchemaIDCPtr idc,
20306 			  xmlSchemaParserCtxtPtr pctxt)
20307 {
20308     if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
20309         return(0);
20310     if (idc->ref->name != NULL) {
20311 	idc->ref->item = (xmlSchemaBasicItemPtr)
20312 	    xmlSchemaGetIDC(pctxt->schema, idc->ref->name,
20313 		idc->ref->targetNamespace);
20314         if (idc->ref->item == NULL) {
20315 	    /*
20316 	    * TODO: It is actually not an error to fail to resolve
20317 	    * at this stage. BUT we need to be that strict!
20318 	    */
20319 	    xmlSchemaPResCompAttrErr(pctxt,
20320 		XML_SCHEMAP_SRC_RESOLVE,
20321 		WXS_BASIC_CAST idc, idc->node,
20322 		"refer", idc->ref->name,
20323 		idc->ref->targetNamespace,
20324 		XML_SCHEMA_TYPE_IDC_KEY, NULL);
20325             return(pctxt->err);
20326 	} else if (idc->ref->item->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
20327 	    /*
20328 	    * SPEC c-props-correct (1)
20329 	    */
20330 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
20331 		XML_SCHEMAP_C_PROPS_CORRECT,
20332 		NULL, WXS_BASIC_CAST idc,
20333 		"The keyref references a keyref",
20334 		NULL, NULL);
20335 	    idc->ref->item = NULL;
20336 	    return(pctxt->err);
20337 	} else {
20338 	    if (idc->nbFields !=
20339 		((xmlSchemaIDCPtr) idc->ref->item)->nbFields) {
20340 		xmlChar *str = NULL;
20341 		xmlSchemaIDCPtr refer;
20342 
20343 		refer = (xmlSchemaIDCPtr) idc->ref->item;
20344 		/*
20345 		* SPEC c-props-correct(2)
20346 		* "If the {identity-constraint category} is keyref,
20347 		* the cardinality of the {fields} must equal that of
20348 		* the {fields} of the {referenced key}.
20349 		*/
20350 		xmlSchemaCustomErr(ACTXT_CAST pctxt,
20351 		    XML_SCHEMAP_C_PROPS_CORRECT,
20352 		    NULL, WXS_BASIC_CAST idc,
20353 		    "The cardinality of the keyref differs from the "
20354 		    "cardinality of the referenced key/unique '%s'",
20355 		    xmlSchemaFormatQName(&str, refer->targetNamespace,
20356 			refer->name),
20357 		    NULL);
20358 		FREE_AND_NULL(str)
20359 		return(pctxt->err);
20360 	    }
20361 	}
20362     }
20363     return(0);
20364 }
20365 
20366 static int
xmlSchemaResolveAttrUseProhibReferences(xmlSchemaAttributeUseProhibPtr prohib,xmlSchemaParserCtxtPtr pctxt)20367 xmlSchemaResolveAttrUseProhibReferences(xmlSchemaAttributeUseProhibPtr prohib,
20368 				       xmlSchemaParserCtxtPtr pctxt)
20369 {
20370     if (xmlSchemaGetAttributeDecl(pctxt->schema, prohib->name,
20371 	prohib->targetNamespace) == NULL) {
20372 
20373 	xmlSchemaPResCompAttrErr(pctxt,
20374 	    XML_SCHEMAP_SRC_RESOLVE,
20375 	    NULL, prohib->node,
20376 	    "ref", prohib->name, prohib->targetNamespace,
20377 	    XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20378 	return(XML_SCHEMAP_SRC_RESOLVE);
20379     }
20380     return(0);
20381 }
20382 
20383 #define WXS_REDEFINED_TYPE(c) \
20384 (((xmlSchemaTypePtr) item)->flags & XML_SCHEMAS_TYPE_REDEFINED)
20385 
20386 #define WXS_REDEFINED_MODEL_GROUP_DEF(c) \
20387 (((xmlSchemaModelGroupDefPtr) item)->flags & XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20388 
20389 #define WXS_REDEFINED_ATTR_GROUP(c) \
20390 (((xmlSchemaAttributeGroupPtr) item)->flags & XML_SCHEMAS_ATTRGROUP_REDEFINED)
20391 
20392 static int
xmlSchemaCheckSRCRedefineFirst(xmlSchemaParserCtxtPtr pctxt)20393 xmlSchemaCheckSRCRedefineFirst(xmlSchemaParserCtxtPtr pctxt)
20394 {
20395     int err = 0;
20396     xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20397     xmlSchemaBasicItemPtr prev, item;
20398     int wasRedefined;
20399 
20400     if (redef == NULL)
20401 	return(0);
20402 
20403     do {
20404 	item = redef->item;
20405 	/*
20406 	* First try to locate the redefined component in the
20407 	* schema graph starting with the redefined schema.
20408 	* NOTE: According to this schema bug entry:
20409 	*   http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005OctDec/0019.html
20410 	*   it's not clear if the referenced component needs to originate
20411 	*   from the <redefine>d schema _document_ or the schema; the latter
20412 	*   would include all imported and included sub-schemas of the
20413 	*   <redefine>d schema. Currently the latter approach is used.
20414 	*   SUPPLEMENT: It seems that the WG moves towards the latter
20415 	*   approach, so we are doing it right.
20416 	*
20417 	*/
20418 	prev = xmlSchemaFindRedefCompInGraph(
20419 	    redef->targetBucket, item->type,
20420 	    redef->refName, redef->refTargetNs);
20421 	if (prev == NULL) {
20422 	    xmlChar *str = NULL;
20423 	    xmlNodePtr node;
20424 
20425 	    /*
20426 	    * SPEC src-redefine:
20427 	    * (6.2.1) "The `actual value` of its own name attribute plus
20428 	    * target namespace must successfully `resolve` to a model
20429 	    * group definition in I."
20430 	    * (7.2.1) "The `actual value` of its own name attribute plus
20431 	    * target namespace must successfully `resolve` to an attribute
20432 	    * group definition in I."
20433 
20434 	    *
20435 	    * Note that, if we are redefining with the use of references
20436 	    * to components, the spec assumes the src-resolve to be used;
20437 	    * but this won't assure that we search only *inside* the
20438 	    * redefined schema.
20439 	    */
20440 	    if (redef->reference)
20441 		node = WXS_ITEM_NODE(redef->reference);
20442 	    else
20443 		node = WXS_ITEM_NODE(item);
20444 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
20445 		/*
20446 		* TODO: error code.
20447 		* Probably XML_SCHEMAP_SRC_RESOLVE, if this is using the
20448 		* reference kind.
20449 		*/
20450 		XML_SCHEMAP_SRC_REDEFINE, node, NULL,
20451 		"The %s '%s' to be redefined could not be found in "
20452 		"the redefined schema",
20453 		WXS_ITEM_TYPE_NAME(item),
20454 		xmlSchemaFormatQName(&str, redef->refTargetNs,
20455 		    redef->refName));
20456 	    FREE_AND_NULL(str);
20457 	    err = pctxt->err;
20458 	    redef = redef->next;
20459 	    continue;
20460 	}
20461 	/*
20462 	* TODO: Obtaining and setting the redefinition state is really
20463 	* clumsy.
20464 	*/
20465 	wasRedefined = 0;
20466 	switch (item->type) {
20467 	    case XML_SCHEMA_TYPE_COMPLEX:
20468 	    case XML_SCHEMA_TYPE_SIMPLE:
20469 		if ((WXS_TYPE_CAST prev)->flags &
20470 		    XML_SCHEMAS_TYPE_REDEFINED)
20471 		{
20472 		    wasRedefined = 1;
20473 		    break;
20474 		}
20475 		/* Mark it as redefined. */
20476 		(WXS_TYPE_CAST prev)->flags |= XML_SCHEMAS_TYPE_REDEFINED;
20477 		/*
20478 		* Assign the redefined type to the
20479 		* base type of the redefining type.
20480 		* TODO: How
20481 		*/
20482 		((xmlSchemaTypePtr) item)->baseType =
20483 		    (xmlSchemaTypePtr) prev;
20484 		break;
20485 	    case XML_SCHEMA_TYPE_GROUP:
20486 		if ((WXS_MODEL_GROUPDEF_CAST prev)->flags &
20487 		    XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20488 		{
20489 		    wasRedefined = 1;
20490 		    break;
20491 		}
20492 		/* Mark it as redefined. */
20493 		(WXS_MODEL_GROUPDEF_CAST prev)->flags |=
20494 		    XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED;
20495 		if (redef->reference != NULL) {
20496 		    /*
20497 		    * Overwrite the QName-reference with the
20498 		    * referenced model group def.
20499 		    */
20500 		    (WXS_PTC_CAST redef->reference)->children =
20501 			WXS_TREE_CAST prev;
20502 		}
20503 		redef->target = prev;
20504 		break;
20505 	    case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20506 		if ((WXS_ATTR_GROUP_CAST prev)->flags &
20507 		    XML_SCHEMAS_ATTRGROUP_REDEFINED)
20508 		{
20509 		    wasRedefined = 1;
20510 		    break;
20511 		}
20512 		(WXS_ATTR_GROUP_CAST prev)->flags |=
20513 		    XML_SCHEMAS_ATTRGROUP_REDEFINED;
20514 		if (redef->reference != NULL) {
20515 		    /*
20516 		    * Assign the redefined attribute group to the
20517 		    * QName-reference component.
20518 		    * This is the easy case, since we will just
20519 		    * expand the redefined group.
20520 		    */
20521 		    (WXS_QNAME_CAST redef->reference)->item = prev;
20522 		    redef->target = NULL;
20523 		} else {
20524 		    /*
20525 		    * This is the complicated case: we need
20526 		    * to apply src-redefine (7.2.2) at a later
20527 		    * stage, i.e. when attribute group references
20528 		    * have been expanded and simple types have
20529 		    * been fixed.
20530 		    */
20531 		    redef->target = prev;
20532 		}
20533 		break;
20534 	    default:
20535 		PERROR_INT("xmlSchemaResolveRedefReferences",
20536 		    "Unexpected redefined component type");
20537 		return(-1);
20538 	}
20539 	if (wasRedefined) {
20540 	    xmlChar *str = NULL;
20541 	    xmlNodePtr node;
20542 
20543 	    if (redef->reference)
20544 		node = WXS_ITEM_NODE(redef->reference);
20545 	    else
20546 		node = WXS_ITEM_NODE(redef->item);
20547 
20548 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
20549 		/* TODO: error code. */
20550 		XML_SCHEMAP_SRC_REDEFINE,
20551 		node, NULL,
20552 		"The referenced %s was already redefined. Multiple "
20553 		"redefinition of the same component is not supported",
20554 		xmlSchemaGetComponentDesignation(&str, prev),
20555 		NULL);
20556 	    FREE_AND_NULL(str)
20557 	    err = pctxt->err;
20558 	    redef = redef->next;
20559 	    continue;
20560 	}
20561 	redef = redef->next;
20562     } while (redef != NULL);
20563 
20564     return(err);
20565 }
20566 
20567 static int
xmlSchemaCheckSRCRedefineSecond(xmlSchemaParserCtxtPtr pctxt)20568 xmlSchemaCheckSRCRedefineSecond(xmlSchemaParserCtxtPtr pctxt)
20569 {
20570     int err = 0;
20571     xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20572     xmlSchemaBasicItemPtr item;
20573 
20574     if (redef == NULL)
20575 	return(0);
20576 
20577     do {
20578 	if (redef->target == NULL) {
20579 	    redef = redef->next;
20580 	    continue;
20581 	}
20582 	item = redef->item;
20583 
20584 	switch (item->type) {
20585 	    case XML_SCHEMA_TYPE_SIMPLE:
20586 	    case XML_SCHEMA_TYPE_COMPLEX:
20587 		/*
20588 		* Since the spec wants the {name} of the redefined
20589 		* type to be 'absent', we'll NULL it.
20590 		*/
20591 		(WXS_TYPE_CAST redef->target)->name = NULL;
20592 
20593 		/*
20594 		* TODO: Seems like there's nothing more to do. The normal
20595 		* inheritance mechanism is used. But not 100% sure.
20596 		*/
20597 		break;
20598 	    case XML_SCHEMA_TYPE_GROUP:
20599 		/*
20600 		* URGENT TODO:
20601 		* SPEC src-redefine:
20602 		* (6.2.2) "The {model group} of the model group definition
20603 		* which corresponds to it per XML Representation of Model
20604 		* Group Definition Schema Components ($3.7.2) must be a
20605 		* `valid restriction` of the {model group} of that model
20606 		* group definition in I, as defined in Particle Valid
20607 		* (Restriction) ($3.9.6)."
20608 		*/
20609 		break;
20610 	    case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20611 		/*
20612 		* SPEC src-redefine:
20613 		* (7.2.2) "The {attribute uses} and {attribute wildcard} of
20614 		* the attribute group definition which corresponds to it
20615 		* per XML Representation of Attribute Group Definition Schema
20616 		* Components ($3.6.2) must be `valid restrictions` of the
20617 		* {attribute uses} and {attribute wildcard} of that attribute
20618 		* group definition in I, as defined in clause 2, clause 3 and
20619 		* clause 4 of Derivation Valid (Restriction, Complex)
20620 		* ($3.4.6) (where references to the base type definition are
20621 		* understood as references to the attribute group definition
20622 		* in I)."
20623 		*/
20624 		err = xmlSchemaCheckDerivationOKRestriction2to4(pctxt,
20625 		    XML_SCHEMA_ACTION_REDEFINE,
20626 		    item, redef->target,
20627 		    (WXS_ATTR_GROUP_CAST item)->attrUses,
20628 		    (WXS_ATTR_GROUP_CAST redef->target)->attrUses,
20629 		    (WXS_ATTR_GROUP_CAST item)->attributeWildcard,
20630 		    (WXS_ATTR_GROUP_CAST redef->target)->attributeWildcard);
20631 		if (err == -1)
20632 		    return(-1);
20633 		break;
20634 	    default:
20635 		break;
20636 	}
20637 	redef = redef->next;
20638     } while (redef != NULL);
20639     return(0);
20640 }
20641 
20642 
20643 static int
xmlSchemaAddComponents(xmlSchemaParserCtxtPtr pctxt,xmlSchemaBucketPtr bucket)20644 xmlSchemaAddComponents(xmlSchemaParserCtxtPtr pctxt,
20645 		       xmlSchemaBucketPtr bucket)
20646 {
20647     xmlSchemaBasicItemPtr item;
20648     int err;
20649     xmlHashTablePtr *table;
20650     const xmlChar *name;
20651     int i;
20652 
20653 #define WXS_GET_GLOBAL_HASH(c, slot) { \
20654     if (WXS_IS_BUCKET_IMPMAIN((c)->type)) \
20655 	table = &(WXS_IMPBUCKET((c))->schema->slot); \
20656     else \
20657 	table = &(WXS_INCBUCKET((c))->ownerImport->schema->slot); }
20658 
20659     /*
20660     * Add global components to the schema's hash tables.
20661     * This is the place where duplicate components will be
20662     * detected.
20663     * TODO: I think normally we should support imports of the
20664     *   same namespace from multiple locations. We don't do currently,
20665     *   but if we do then according to:
20666     *   http://www.w3.org/Bugs/Public/show_bug.cgi?id=2224
20667     *   we would need, if imported directly, to import redefined
20668     *   components as well to be able to catch clashing components.
20669     *   (I hope I'll still know what this means after some months :-()
20670     */
20671     if (bucket == NULL)
20672 	return(-1);
20673     if (bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED)
20674 	return(0);
20675     bucket->flags |= XML_SCHEMA_BUCKET_COMPS_ADDED;
20676 
20677     for (i = 0; i < bucket->globals->nbItems; i++) {
20678 	item = bucket->globals->items[i];
20679 	table = NULL;
20680 	switch (item->type) {
20681 	    case XML_SCHEMA_TYPE_COMPLEX:
20682 	    case XML_SCHEMA_TYPE_SIMPLE:
20683 		if (WXS_REDEFINED_TYPE(item))
20684 		    continue;
20685 		name = (WXS_TYPE_CAST item)->name;
20686 		WXS_GET_GLOBAL_HASH(bucket, typeDecl)
20687 		break;
20688 	    case XML_SCHEMA_TYPE_ELEMENT:
20689 		name = (WXS_ELEM_CAST item)->name;
20690 		WXS_GET_GLOBAL_HASH(bucket, elemDecl)
20691 		break;
20692 	    case XML_SCHEMA_TYPE_ATTRIBUTE:
20693 		name = (WXS_ATTR_CAST item)->name;
20694 		WXS_GET_GLOBAL_HASH(bucket, attrDecl)
20695 		break;
20696 	    case XML_SCHEMA_TYPE_GROUP:
20697 		if (WXS_REDEFINED_MODEL_GROUP_DEF(item))
20698 		    continue;
20699 		name = (WXS_MODEL_GROUPDEF_CAST item)->name;
20700 		WXS_GET_GLOBAL_HASH(bucket, groupDecl)
20701 		break;
20702 	    case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20703 		if (WXS_REDEFINED_ATTR_GROUP(item))
20704 		    continue;
20705 		name = (WXS_ATTR_GROUP_CAST item)->name;
20706 		WXS_GET_GLOBAL_HASH(bucket, attrgrpDecl)
20707 		break;
20708 	    case XML_SCHEMA_TYPE_IDC_KEY:
20709 	    case XML_SCHEMA_TYPE_IDC_UNIQUE:
20710 	    case XML_SCHEMA_TYPE_IDC_KEYREF:
20711 		name = (WXS_IDC_CAST item)->name;
20712 		WXS_GET_GLOBAL_HASH(bucket, idcDef)
20713 		break;
20714 	    case XML_SCHEMA_TYPE_NOTATION:
20715 		name = ((xmlSchemaNotationPtr) item)->name;
20716 		WXS_GET_GLOBAL_HASH(bucket, notaDecl)
20717 		break;
20718 	    default:
20719 		PERROR_INT("xmlSchemaAddComponents",
20720 		    "Unexpected global component type");
20721 		continue;
20722 	}
20723 	if (*table == NULL) {
20724 	    *table = xmlHashCreateDict(10, pctxt->dict);
20725 	    if (*table == NULL) {
20726 		PERROR_INT("xmlSchemaAddComponents",
20727 		    "failed to create a component hash table");
20728 		return(-1);
20729 	    }
20730 	}
20731 	err = xmlHashAddEntry(*table, name, item);
20732 	if (err != 0) {
20733 	    xmlChar *str = NULL;
20734 
20735 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
20736 		XML_SCHEMAP_REDEFINED_TYPE,
20737 		WXS_ITEM_NODE(item),
20738 		WXS_BASIC_CAST item,
20739 		"A global %s '%s' does already exist",
20740 		WXS_ITEM_TYPE_NAME(item),
20741 		xmlSchemaGetComponentQName(&str, item));
20742 	    FREE_AND_NULL(str);
20743 	}
20744     }
20745     /*
20746     * Process imported/included schemas.
20747     */
20748     if (bucket->relations != NULL) {
20749 	xmlSchemaSchemaRelationPtr rel = bucket->relations;
20750 	do {
20751 	    if ((rel->bucket != NULL) &&
20752 		((rel->bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED) == 0)) {
20753 		if (xmlSchemaAddComponents(pctxt, rel->bucket) == -1)
20754 		    return(-1);
20755 	    }
20756 	    rel = rel->next;
20757 	} while (rel != NULL);
20758     }
20759     return(0);
20760 }
20761 
20762 static int
xmlSchemaFixupComponents(xmlSchemaParserCtxtPtr pctxt,xmlSchemaBucketPtr rootBucket)20763 xmlSchemaFixupComponents(xmlSchemaParserCtxtPtr pctxt,
20764 			 xmlSchemaBucketPtr rootBucket)
20765 {
20766     xmlSchemaConstructionCtxtPtr con = pctxt->constructor;
20767     xmlSchemaTreeItemPtr item, *items;
20768     int nbItems, i, ret = 0;
20769     xmlSchemaBucketPtr oldbucket = con->bucket;
20770     xmlSchemaElementPtr elemDecl;
20771 
20772 #define FIXHFAILURE if (pctxt->err == XML_SCHEMAP_INTERNAL) goto exit_failure;
20773 
20774     if ((con->pending == NULL) ||
20775 	(con->pending->nbItems == 0))
20776 	return(0);
20777 
20778     /*
20779     * Since xmlSchemaFixupComplexType() will create new particles
20780     * (local components), and those particle components need a bucket
20781     * on the constructor, we'll assure here that the constructor has
20782     * a bucket.
20783     * TODO: Think about storing locals _only_ on the main bucket.
20784     */
20785     if (con->bucket == NULL)
20786 	con->bucket = rootBucket;
20787 
20788     /* TODO:
20789     * SPEC (src-redefine):
20790     * (6.2) "If it has no such self-reference, then all of the
20791     * following must be true:"
20792 
20793     * (6.2.2) The {model group} of the model group definition which
20794     * corresponds to it per XML Representation of Model Group
20795     * Definition Schema Components ($3.7.2) must be a `valid
20796     * restriction` of the {model group} of that model group definition
20797     * in I, as defined in Particle Valid (Restriction) ($3.9.6)."
20798     */
20799     xmlSchemaCheckSRCRedefineFirst(pctxt);
20800 
20801     /*
20802     * Add global components to the schemata's hash tables.
20803     */
20804     xmlSchemaAddComponents(pctxt, rootBucket);
20805 
20806     pctxt->ctxtType = NULL;
20807     items = (xmlSchemaTreeItemPtr *) con->pending->items;
20808     nbItems = con->pending->nbItems;
20809     /*
20810     * Now that we have parsed *all* the schema document(s) and converted
20811     * them to schema components, we can resolve references, apply component
20812     * constraints, create the FSA from the content model, etc.
20813     */
20814     /*
20815     * Resolve references of..
20816     *
20817     * 1. element declarations:
20818     *   - the type definition
20819     *   - the substitution group affiliation
20820     * 2. simple/complex types:
20821     *   - the base type definition
20822     *   - the memberTypes of union types
20823     *   - the itemType of list types
20824     * 3. attributes declarations and attribute uses:
20825     *   - the type definition
20826     *   - if an attribute use, then the attribute declaration
20827     * 4. attribute group references:
20828     *   - the attribute group definition
20829     * 5. particles:
20830     *   - the term of the particle (e.g. a model group)
20831     * 6. IDC key-references:
20832     *   - the referenced IDC 'key' or 'unique' definition
20833     * 7. Attribute prohibitions which had a "ref" attribute.
20834     */
20835     for (i = 0; i < nbItems; i++) {
20836 	item = items[i];
20837 	switch (item->type) {
20838 	    case XML_SCHEMA_TYPE_ELEMENT:
20839 		xmlSchemaResolveElementReferences(
20840 		    (xmlSchemaElementPtr) item, pctxt);
20841 		FIXHFAILURE;
20842 		break;
20843 	    case XML_SCHEMA_TYPE_COMPLEX:
20844 	    case XML_SCHEMA_TYPE_SIMPLE:
20845 		xmlSchemaResolveTypeReferences(
20846 		    (xmlSchemaTypePtr) item, pctxt);
20847 		FIXHFAILURE;
20848 		break;
20849 	    case XML_SCHEMA_TYPE_ATTRIBUTE:
20850 		xmlSchemaResolveAttrTypeReferences(
20851 		    (xmlSchemaAttributePtr) item, pctxt);
20852 		FIXHFAILURE;
20853 		break;
20854 	    case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
20855 		xmlSchemaResolveAttrUseReferences(
20856 		    (xmlSchemaAttributeUsePtr) item, pctxt);
20857 		FIXHFAILURE;
20858 		break;
20859 	    case XML_SCHEMA_EXTRA_QNAMEREF:
20860 		if ((WXS_QNAME_CAST item)->itemType ==
20861 		    XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
20862 		{
20863 		    xmlSchemaResolveAttrGroupReferences(
20864 			WXS_QNAME_CAST item, pctxt);
20865 		}
20866 		FIXHFAILURE;
20867 		break;
20868 	    case XML_SCHEMA_TYPE_SEQUENCE:
20869 	    case XML_SCHEMA_TYPE_CHOICE:
20870 	    case XML_SCHEMA_TYPE_ALL:
20871 		xmlSchemaResolveModelGroupParticleReferences(pctxt,
20872 		    WXS_MODEL_GROUP_CAST item);
20873 		FIXHFAILURE;
20874 		break;
20875 	    case XML_SCHEMA_TYPE_IDC_KEY:
20876 	    case XML_SCHEMA_TYPE_IDC_UNIQUE:
20877 	    case XML_SCHEMA_TYPE_IDC_KEYREF:
20878 		xmlSchemaResolveIDCKeyReferences(
20879 		    (xmlSchemaIDCPtr) item, pctxt);
20880 		FIXHFAILURE;
20881 		break;
20882 	    case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
20883 		/*
20884 		* Handle attribute prohibition which had a
20885 		* "ref" attribute.
20886 		*/
20887 		xmlSchemaResolveAttrUseProhibReferences(
20888 		    WXS_ATTR_PROHIB_CAST item, pctxt);
20889 		FIXHFAILURE;
20890 		break;
20891 	    default:
20892 		break;
20893 	}
20894     }
20895     if (pctxt->nberrors != 0)
20896 	goto exit_error;
20897 
20898     /*
20899     * Now that all references are resolved we
20900     * can check for circularity of...
20901     * 1. the base axis of type definitions
20902     * 2. nested model group definitions
20903     * 3. nested attribute group definitions
20904     * TODO: check for circular substitution groups.
20905     */
20906     for (i = 0; i < nbItems; i++) {
20907 	item = items[i];
20908 	/*
20909 	* Let's better stop on the first error here.
20910 	*/
20911 	switch (item->type) {
20912 	    case XML_SCHEMA_TYPE_COMPLEX:
20913 	    case XML_SCHEMA_TYPE_SIMPLE:
20914 		xmlSchemaCheckTypeDefCircular(
20915 		    (xmlSchemaTypePtr) item, pctxt);
20916 		FIXHFAILURE;
20917 		if (pctxt->nberrors != 0)
20918 		    goto exit_error;
20919 		break;
20920 	    case XML_SCHEMA_TYPE_GROUP:
20921 		xmlSchemaCheckGroupDefCircular(
20922 		    (xmlSchemaModelGroupDefPtr) item, pctxt);
20923 		FIXHFAILURE;
20924 		if (pctxt->nberrors != 0)
20925 		    goto exit_error;
20926 		break;
20927 	    case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20928 		xmlSchemaCheckAttrGroupCircular(
20929 		    (xmlSchemaAttributeGroupPtr) item, pctxt);
20930 		FIXHFAILURE;
20931 		if (pctxt->nberrors != 0)
20932 		    goto exit_error;
20933 		break;
20934 	    default:
20935 		break;
20936 	}
20937     }
20938     if (pctxt->nberrors != 0)
20939 	goto exit_error;
20940     /*
20941     * Model group definition references:
20942     * Such a reference is reflected by a particle at the component
20943     * level. Until now the 'term' of such particles pointed
20944     * to the model group definition; this was done, in order to
20945     * ease circularity checks. Now we need to set the 'term' of
20946     * such particles to the model group of the model group definition.
20947     */
20948     for (i = 0; i < nbItems; i++) {
20949 	item = items[i];
20950 	switch (item->type) {
20951 	    case XML_SCHEMA_TYPE_SEQUENCE:
20952 	    case XML_SCHEMA_TYPE_CHOICE:
20953 		xmlSchemaModelGroupToModelGroupDefFixup(pctxt,
20954 		    WXS_MODEL_GROUP_CAST item);
20955 		break;
20956 	    default:
20957 		break;
20958 	}
20959     }
20960     if (pctxt->nberrors != 0)
20961 	goto exit_error;
20962     /*
20963     * Expand attribute group references of attribute group definitions.
20964     */
20965     for (i = 0; i < nbItems; i++) {
20966 	item = items[i];
20967 	switch (item->type) {
20968             case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20969 		if ((! WXS_ATTR_GROUP_EXPANDED(item)) &&
20970 		    WXS_ATTR_GROUP_HAS_REFS(item))
20971 		{
20972 		    xmlSchemaAttributeGroupExpandRefs(pctxt,
20973 			WXS_ATTR_GROUP_CAST item);
20974 		    FIXHFAILURE;
20975 		}
20976 		break;
20977 	    default:
20978 		break;
20979 	}
20980     }
20981     if (pctxt->nberrors != 0)
20982 	goto exit_error;
20983     /*
20984     * First compute the variety of simple types. This is needed as
20985     * a separate step, since otherwise we won't be able to detect
20986     * circular union types in all cases.
20987     */
20988     for (i = 0; i < nbItems; i++) {
20989 	item = items[i];
20990 	switch (item->type) {
20991             case XML_SCHEMA_TYPE_SIMPLE:
20992 		if (WXS_IS_TYPE_NOT_FIXED_1((xmlSchemaTypePtr) item)) {
20993 		    xmlSchemaFixupSimpleTypeStageOne(pctxt,
20994 			(xmlSchemaTypePtr) item);
20995 		    FIXHFAILURE;
20996 		}
20997 		break;
20998 	    default:
20999 		break;
21000 	}
21001     }
21002     if (pctxt->nberrors != 0)
21003 	goto exit_error;
21004     /*
21005     * Detect circular union types. Note that this needs the variety to
21006     * be already computed.
21007     */
21008     for (i = 0; i < nbItems; i++) {
21009 	item = items[i];
21010 	switch (item->type) {
21011             case XML_SCHEMA_TYPE_SIMPLE:
21012 		if (((xmlSchemaTypePtr) item)->memberTypes != NULL) {
21013 		    xmlSchemaCheckUnionTypeDefCircular(pctxt,
21014 			(xmlSchemaTypePtr) item);
21015 		    FIXHFAILURE;
21016 		}
21017 		break;
21018 	    default:
21019 		break;
21020 	}
21021     }
21022     if (pctxt->nberrors != 0)
21023 	goto exit_error;
21024 
21025     /*
21026     * Do the complete type fixup for simple types.
21027     */
21028     for (i = 0; i < nbItems; i++) {
21029 	item = items[i];
21030 	switch (item->type) {
21031             case XML_SCHEMA_TYPE_SIMPLE:
21032 		if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
21033 		    xmlSchemaFixupSimpleTypeStageTwo(pctxt, WXS_TYPE_CAST item);
21034 		    FIXHFAILURE;
21035 		}
21036 		break;
21037 	    default:
21038 		break;
21039 	}
21040     }
21041     if (pctxt->nberrors != 0)
21042 	goto exit_error;
21043     /*
21044     * At this point we need build and check all simple types.
21045     */
21046     /*
21047     * Apply constraints for attribute declarations.
21048     */
21049     for (i = 0; i < nbItems; i++) {
21050 	item = items[i];
21051 	switch (item->type) {
21052 	    case XML_SCHEMA_TYPE_ATTRIBUTE:
21053 		xmlSchemaCheckAttrPropsCorrect(pctxt, WXS_ATTR_CAST item);
21054 		FIXHFAILURE;
21055 		break;
21056 	    default:
21057 		break;
21058 	}
21059     }
21060     if (pctxt->nberrors != 0)
21061 	goto exit_error;
21062     /*
21063     * Apply constraints for attribute uses.
21064     */
21065     for (i = 0; i < nbItems; i++) {
21066 	item = items[i];
21067 	switch (item->type) {
21068 	    case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
21069 		if (((xmlSchemaAttributeUsePtr)item)->defValue != NULL) {
21070 		    xmlSchemaCheckAttrUsePropsCorrect(pctxt,
21071 			WXS_ATTR_USE_CAST item);
21072 		    FIXHFAILURE;
21073 		}
21074 		break;
21075 	    default:
21076 		break;
21077 	}
21078     }
21079     if (pctxt->nberrors != 0)
21080 	goto exit_error;
21081 
21082     /*
21083     * Apply constraints for attribute group definitions.
21084     */
21085     for (i = 0; i < nbItems; i++) {
21086 	item = items[i];
21087 	switch (item->type) {
21088 	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
21089 	    if (( (WXS_ATTR_GROUP_CAST item)->attrUses != NULL) &&
21090 		( (WXS_LIST_CAST (WXS_ATTR_GROUP_CAST item)->attrUses)->nbItems > 1))
21091 	    {
21092 		xmlSchemaCheckAGPropsCorrect(pctxt, WXS_ATTR_GROUP_CAST item);
21093 		FIXHFAILURE;
21094 	    }
21095 	    break;
21096 	default:
21097 	    break;
21098 	}
21099     }
21100     if (pctxt->nberrors != 0)
21101 	goto exit_error;
21102 
21103     /*
21104     * Apply constraints for redefinitions.
21105     */
21106     if (WXS_CONSTRUCTOR(pctxt)->redefs != NULL)
21107 	xmlSchemaCheckSRCRedefineSecond(pctxt);
21108     if (pctxt->nberrors != 0)
21109 	goto exit_error;
21110 
21111     /*
21112     * Complex types are built and checked.
21113     */
21114     for (i = 0; i < nbItems; i++) {
21115 	item = con->pending->items[i];
21116 	switch (item->type) {
21117 	    case XML_SCHEMA_TYPE_COMPLEX:
21118 		if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
21119 		    xmlSchemaFixupComplexType(pctxt, WXS_TYPE_CAST item);
21120 		    FIXHFAILURE;
21121 		}
21122 		break;
21123 	    default:
21124 		break;
21125 	}
21126     }
21127     if (pctxt->nberrors != 0)
21128 	goto exit_error;
21129 
21130     /*
21131     * The list could have changed, since xmlSchemaFixupComplexType()
21132     * will create particles and model groups in some cases.
21133     */
21134     items = (xmlSchemaTreeItemPtr *) con->pending->items;
21135     nbItems = con->pending->nbItems;
21136 
21137     /*
21138     * Apply some constraints for element declarations.
21139     */
21140     for (i = 0; i < nbItems; i++) {
21141 	item = items[i];
21142 	switch (item->type) {
21143 	    case XML_SCHEMA_TYPE_ELEMENT:
21144 		elemDecl = (xmlSchemaElementPtr) item;
21145 
21146 		if ((elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED) == 0)
21147 		{
21148 		    xmlSchemaCheckElementDeclComponent(
21149 			(xmlSchemaElementPtr) elemDecl, pctxt);
21150 		    FIXHFAILURE;
21151 		}
21152 
21153 #ifdef WXS_ELEM_DECL_CONS_ENABLED
21154 		/*
21155 		* Schema Component Constraint: Element Declarations Consistent
21156 		* Apply this constraint to local types of element declarations.
21157 		*/
21158 		if ((WXS_ELEM_TYPEDEF(elemDecl) != NULL) &&
21159 		    (WXS_IS_COMPLEX(WXS_ELEM_TYPEDEF(elemDecl))) &&
21160 		    (WXS_TYPE_IS_LOCAL(WXS_ELEM_TYPEDEF(elemDecl))))
21161 		{
21162 		    xmlSchemaCheckElementDeclConsistent(pctxt,
21163 			WXS_BASIC_CAST elemDecl,
21164 			WXS_TYPE_PARTICLE(WXS_ELEM_TYPEDEF(elemDecl)),
21165 			NULL, NULL, 0);
21166 		}
21167 #endif
21168 		break;
21169 	    default:
21170 		break;
21171 	}
21172     }
21173     if (pctxt->nberrors != 0)
21174 	goto exit_error;
21175 
21176     /*
21177     * Finally we can build the automaton from the content model of
21178     * complex types.
21179     */
21180 
21181     for (i = 0; i < nbItems; i++) {
21182 	item = items[i];
21183 	switch (item->type) {
21184 	    case XML_SCHEMA_TYPE_COMPLEX:
21185 		xmlSchemaBuildContentModel((xmlSchemaTypePtr) item, pctxt);
21186 		/* FIXHFAILURE; */
21187 		break;
21188 	    default:
21189 		break;
21190 	}
21191     }
21192     if (pctxt->nberrors != 0)
21193 	goto exit_error;
21194     /*
21195     * URGENT TODO: cos-element-consistent
21196     */
21197     goto exit;
21198 
21199 exit_error:
21200     ret = pctxt->err;
21201     goto exit;
21202 
21203 exit_failure:
21204     ret = -1;
21205 
21206 exit:
21207     /*
21208     * Reset the constructor. This is needed for XSI acquisition, since
21209     * those items will be processed over and over again for every XSI
21210     * if not cleared here.
21211     */
21212     con->bucket = oldbucket;
21213     con->pending->nbItems = 0;
21214     if (con->substGroups != NULL) {
21215 	xmlHashFree(con->substGroups, xmlSchemaSubstGroupFreeEntry);
21216 	con->substGroups = NULL;
21217     }
21218     if (con->redefs != NULL) {
21219 	xmlSchemaRedefListFree(con->redefs);
21220 	con->redefs = NULL;
21221     }
21222     return(ret);
21223 }
21224 /**
21225  * xmlSchemaParse:
21226  * @ctxt:  a schema validation context
21227  *
21228  * parse a schema definition resource and build an internal
21229  * XML Schema structure which can be used to validate instances.
21230  *
21231  * Returns the internal XML Schema structure built from the resource or
21232  *         NULL in case of error
21233  */
21234 xmlSchemaPtr
xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)21235 xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
21236 {
21237     xmlSchemaPtr mainSchema = NULL;
21238     xmlSchemaBucketPtr bucket = NULL;
21239     int res;
21240 
21241     /*
21242     * This one is used if the schema to be parsed was specified via
21243     * the API; i.e. not automatically by the validated instance document.
21244     */
21245 
21246     if (xmlSchemaInitTypes() < 0)
21247         return (NULL);
21248 
21249     if (ctxt == NULL)
21250         return (NULL);
21251 
21252     /* TODO: Init the context. Is this all we need?*/
21253     ctxt->nberrors = 0;
21254     ctxt->err = 0;
21255     ctxt->counter = 0;
21256 
21257     /* Create the *main* schema. */
21258     mainSchema = xmlSchemaNewSchema(ctxt);
21259     if (mainSchema == NULL)
21260 	goto exit_failure;
21261     /*
21262     * Create the schema constructor.
21263     */
21264     if (ctxt->constructor == NULL) {
21265 	ctxt->constructor = xmlSchemaConstructionCtxtCreate(ctxt->dict);
21266 	if (ctxt->constructor == NULL)
21267 	    goto exit_failure;
21268 	/* Take ownership of the constructor to be able to free it. */
21269 	ctxt->ownsConstructor = 1;
21270     }
21271     ctxt->constructor->mainSchema = mainSchema;
21272     /*
21273     * Locate and add the schema document.
21274     */
21275     res = xmlSchemaAddSchemaDoc(ctxt, XML_SCHEMA_SCHEMA_MAIN,
21276 	ctxt->URL, ctxt->doc, ctxt->buffer, ctxt->size, NULL,
21277 	NULL, NULL, &bucket);
21278     if (res == -1)
21279 	goto exit_failure;
21280     if (res != 0)
21281 	goto exit;
21282 
21283     if (bucket == NULL) {
21284 	/* TODO: Error code, actually we failed to *locate* the schema. */
21285 	if (ctxt->URL)
21286 	    xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21287 		NULL, NULL,
21288 		"Failed to locate the main schema resource at '%s'",
21289 		ctxt->URL, NULL);
21290 	else
21291 	    xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21292 		NULL, NULL,
21293 		"Failed to locate the main schema resource",
21294 		    NULL, NULL);
21295 	goto exit;
21296     }
21297     /* Then do the parsing for good. */
21298     if (xmlSchemaParseNewDocWithContext(ctxt, mainSchema, bucket) == -1)
21299 	goto exit_failure;
21300     if (ctxt->nberrors != 0)
21301 	goto exit;
21302 
21303     mainSchema->doc = bucket->doc;
21304     mainSchema->preserve = ctxt->preserve;
21305 
21306     ctxt->schema = mainSchema;
21307 
21308     if (xmlSchemaFixupComponents(ctxt, WXS_CONSTRUCTOR(ctxt)->mainBucket) == -1)
21309 	goto exit_failure;
21310 
21311     /*
21312     * TODO: This is not nice, since we cannot distinguish from the
21313     * result if there was an internal error or not.
21314     */
21315 exit:
21316     if (ctxt->nberrors != 0) {
21317 	if (mainSchema) {
21318 	    xmlSchemaFree(mainSchema);
21319 	    mainSchema = NULL;
21320 	}
21321 	if (ctxt->constructor) {
21322 	    xmlSchemaConstructionCtxtFree(ctxt->constructor);
21323 	    ctxt->constructor = NULL;
21324 	    ctxt->ownsConstructor = 0;
21325 	}
21326     }
21327     ctxt->schema = NULL;
21328     return(mainSchema);
21329 exit_failure:
21330     /*
21331     * Quite verbose, but should catch internal errors, which were
21332     * not communicated.
21333     */
21334     if (mainSchema) {
21335         xmlSchemaFree(mainSchema);
21336 	mainSchema = NULL;
21337     }
21338     if (ctxt->constructor) {
21339 	xmlSchemaConstructionCtxtFree(ctxt->constructor);
21340 	ctxt->constructor = NULL;
21341 	ctxt->ownsConstructor = 0;
21342     }
21343     PERROR_INT2("xmlSchemaParse",
21344 	"An internal error occurred");
21345     ctxt->schema = NULL;
21346     return(NULL);
21347 }
21348 
21349 /**
21350  * xmlSchemaSetParserErrors:
21351  * @ctxt:  a schema validation context
21352  * @err:  the error callback
21353  * @warn:  the warning callback
21354  * @ctx:  contextual data for the callbacks
21355  *
21356  * DEPRECATED: Use xmlSchemaSetParserStructuredErrors.
21357  *
21358  * Set the callback functions used to handle errors for a validation context
21359  */
21360 void
xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,xmlSchemaValidityErrorFunc err,xmlSchemaValidityWarningFunc warn,void * ctx)21361 xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
21362                          xmlSchemaValidityErrorFunc err,
21363                          xmlSchemaValidityWarningFunc warn, void *ctx)
21364 {
21365     if (ctxt == NULL)
21366         return;
21367     ctxt->error = err;
21368     ctxt->warning = warn;
21369     ctxt->errCtxt = ctx;
21370     if (ctxt->vctxt != NULL)
21371 	xmlSchemaSetValidErrors(ctxt->vctxt, err, warn, ctx);
21372 }
21373 
21374 /**
21375  * xmlSchemaSetParserStructuredErrors:
21376  * @ctxt:  a schema parser context
21377  * @serror:  the structured error function
21378  * @ctx: the functions context
21379  *
21380  * Set the structured error callback
21381  */
21382 void
xmlSchemaSetParserStructuredErrors(xmlSchemaParserCtxtPtr ctxt,xmlStructuredErrorFunc serror,void * ctx)21383 xmlSchemaSetParserStructuredErrors(xmlSchemaParserCtxtPtr ctxt,
21384 				   xmlStructuredErrorFunc serror,
21385 				   void *ctx)
21386 {
21387     if (ctxt == NULL)
21388 	return;
21389     ctxt->serror = serror;
21390     ctxt->errCtxt = ctx;
21391     if (ctxt->vctxt != NULL)
21392 	xmlSchemaSetValidStructuredErrors(ctxt->vctxt, serror, ctx);
21393 }
21394 
21395 /**
21396  * xmlSchemaGetParserErrors:
21397  * @ctxt:  a XMl-Schema parser context
21398  * @err: the error callback result
21399  * @warn: the warning callback result
21400  * @ctx: contextual data for the callbacks result
21401  *
21402  * Get the callback information used to handle errors for a parser context
21403  *
21404  * Returns -1 in case of failure, 0 otherwise
21405  */
21406 int
xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,xmlSchemaValidityErrorFunc * err,xmlSchemaValidityWarningFunc * warn,void ** ctx)21407 xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
21408 			 xmlSchemaValidityErrorFunc * err,
21409 			 xmlSchemaValidityWarningFunc * warn, void **ctx)
21410 {
21411 	if (ctxt == NULL)
21412 		return(-1);
21413 	if (err != NULL)
21414 		*err = ctxt->error;
21415 	if (warn != NULL)
21416 		*warn = ctxt->warning;
21417 	if (ctx != NULL)
21418 		*ctx = ctxt->errCtxt;
21419 	return(0);
21420 }
21421 
21422 /**
21423  * xmlSchemaSetResourceLoader:
21424  * @ctxt:  schema parser
21425  * @loader:  resource loader
21426  * @data:  user data which will be passed to the loader
21427  *
21428  * Register a callback function that will be called to load documents
21429  * or external entities.
21430  *
21431  * Available since 2.14.0.
21432  */
21433 void
xmlSchemaSetResourceLoader(xmlSchemaParserCtxtPtr ctxt,xmlResourceLoader loader,void * data)21434 xmlSchemaSetResourceLoader(xmlSchemaParserCtxtPtr ctxt,
21435                            xmlResourceLoader loader, void *data) {
21436     if (ctxt == NULL)
21437         return;
21438     ctxt->resourceLoader = loader;
21439     ctxt->resourceCtxt = data;
21440 }
21441 
21442 /**
21443  * xmlSchemaFacetTypeToString:
21444  * @type:  the facet type
21445  *
21446  * Convert the xmlSchemaTypeType to a char string.
21447  *
21448  * Returns the char string representation of the facet type if the
21449  *     type is a facet and an "Internal Error" string otherwise.
21450  */
21451 static const xmlChar *
xmlSchemaFacetTypeToString(xmlSchemaTypeType type)21452 xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
21453 {
21454     switch (type) {
21455         case XML_SCHEMA_FACET_PATTERN:
21456             return (BAD_CAST "pattern");
21457         case XML_SCHEMA_FACET_MAXEXCLUSIVE:
21458             return (BAD_CAST "maxExclusive");
21459         case XML_SCHEMA_FACET_MAXINCLUSIVE:
21460             return (BAD_CAST "maxInclusive");
21461         case XML_SCHEMA_FACET_MINEXCLUSIVE:
21462             return (BAD_CAST "minExclusive");
21463         case XML_SCHEMA_FACET_MININCLUSIVE:
21464             return (BAD_CAST "minInclusive");
21465         case XML_SCHEMA_FACET_WHITESPACE:
21466             return (BAD_CAST "whiteSpace");
21467         case XML_SCHEMA_FACET_ENUMERATION:
21468             return (BAD_CAST "enumeration");
21469         case XML_SCHEMA_FACET_LENGTH:
21470             return (BAD_CAST "length");
21471         case XML_SCHEMA_FACET_MAXLENGTH:
21472             return (BAD_CAST "maxLength");
21473         case XML_SCHEMA_FACET_MINLENGTH:
21474             return (BAD_CAST "minLength");
21475         case XML_SCHEMA_FACET_TOTALDIGITS:
21476             return (BAD_CAST "totalDigits");
21477         case XML_SCHEMA_FACET_FRACTIONDIGITS:
21478             return (BAD_CAST "fractionDigits");
21479         default:
21480             break;
21481     }
21482     return (BAD_CAST "Internal Error");
21483 }
21484 
21485 static xmlSchemaWhitespaceValueType
xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)21486 xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
21487 {
21488     /*
21489     * The normalization type can be changed only for types which are derived
21490     * from xsd:string.
21491     */
21492     if (type->type == XML_SCHEMA_TYPE_BASIC) {
21493 	/*
21494 	* Note that we assume a whitespace of preserve for anySimpleType.
21495 	*/
21496 	if ((type->builtInType == XML_SCHEMAS_STRING) ||
21497 	    (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
21498 	    return(XML_SCHEMA_WHITESPACE_PRESERVE);
21499 	else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
21500 	    return(XML_SCHEMA_WHITESPACE_REPLACE);
21501 	else {
21502 	    /*
21503 	    * For all `atomic` datatypes other than string (and types `derived`
21504 	    * by `restriction` from it) the value of whiteSpace is fixed to
21505 	    * collapse
21506 	    * Note that this includes built-in list datatypes.
21507 	    */
21508 	    return(XML_SCHEMA_WHITESPACE_COLLAPSE);
21509 	}
21510     } else if (WXS_IS_LIST(type)) {
21511 	/*
21512 	* For list types the facet "whiteSpace" is fixed to "collapse".
21513 	*/
21514 	return (XML_SCHEMA_WHITESPACE_COLLAPSE);
21515     } else if (WXS_IS_UNION(type)) {
21516 	return (XML_SCHEMA_WHITESPACE_UNKNOWN);
21517     } else if (WXS_IS_ATOMIC(type)) {
21518 	if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE)
21519 	    return (XML_SCHEMA_WHITESPACE_PRESERVE);
21520 	else if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_REPLACE)
21521 	    return (XML_SCHEMA_WHITESPACE_REPLACE);
21522 	else
21523 	    return (XML_SCHEMA_WHITESPACE_COLLAPSE);
21524     }
21525     return (-1);
21526 }
21527 
21528 /************************************************************************
21529  *									*
21530  *			Simple type validation				*
21531  *									*
21532  ************************************************************************/
21533 
21534 
21535 /************************************************************************
21536  *									*
21537  *			DOM Validation code				*
21538  *									*
21539  ************************************************************************/
21540 
21541 /**
21542  * xmlSchemaAssembleByLocation:
21543  * @pctxt:  a schema parser context
21544  * @vctxt:  a schema validation context
21545  * @schema: the existing schema
21546  * @node: the node that fired the assembling
21547  * @nsName: the namespace name of the new schema
21548  * @location: the location of the schema
21549  *
21550  * Expands an existing schema by an additional schema.
21551  *
21552  * Returns 0 if the new schema is correct, a positive error code
21553  * number otherwise and -1 in case of an internal or API error.
21554  */
21555 static int
xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,xmlSchemaPtr schema,xmlNodePtr node,const xmlChar * nsName,const xmlChar * location)21556 xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
21557 			    xmlSchemaPtr schema,
21558 			    xmlNodePtr node,
21559 			    const xmlChar *nsName,
21560 			    const xmlChar *location)
21561 {
21562     int ret = 0;
21563     xmlSchemaParserCtxtPtr pctxt;
21564     xmlSchemaBucketPtr bucket = NULL;
21565 
21566     if ((vctxt == NULL) || (schema == NULL))
21567 	return (-1);
21568 
21569     if (vctxt->pctxt == NULL) {
21570 	VERROR_INT("xmlSchemaAssembleByLocation",
21571 	    "no parser context available");
21572 	return(-1);
21573     }
21574     pctxt = vctxt->pctxt;
21575     if (pctxt->constructor == NULL) {
21576 	PERROR_INT("xmlSchemaAssembleByLocation",
21577 	    "no constructor");
21578 	return(-1);
21579     }
21580     /*
21581     * Acquire the schema document.
21582     */
21583     location = xmlSchemaBuildAbsoluteURI(pctxt->dict,
21584 	location, node);
21585     /*
21586     * Note that we pass XML_SCHEMA_SCHEMA_IMPORT here;
21587     * the process will automatically change this to
21588     * XML_SCHEMA_SCHEMA_MAIN if it is the first schema document.
21589     */
21590     ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
21591 	location, NULL, NULL, 0, node, NULL, nsName,
21592 	&bucket);
21593     if (ret != 0)
21594 	return(ret);
21595     if (bucket == NULL) {
21596 	/*
21597 	* Generate a warning that the document could not be located.
21598 	*/
21599 	xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC,
21600 	    node, NULL,
21601 	    "The document at location '%s' could not be acquired",
21602 	    location, NULL, NULL);
21603 	return(ret);
21604     }
21605     /*
21606     * The first located schema will be handled as if all other
21607     * schemas imported by XSI were imported by this first schema.
21608     */
21609     if ((bucket != NULL) &&
21610 	(WXS_CONSTRUCTOR(pctxt)->bucket == NULL))
21611 	WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
21612     /*
21613     * TODO: Is this handled like an import? I.e. is it not an error
21614     * if the schema cannot be located?
21615     */
21616     if ((bucket == NULL) || (! CAN_PARSE_SCHEMA(bucket)))
21617 	return(0);
21618     /*
21619     * We will reuse the parser context for every schema imported
21620     * directly via XSI. So reset the context.
21621     */
21622     pctxt->nberrors = 0;
21623     pctxt->err = 0;
21624     pctxt->doc = bucket->doc;
21625 
21626     ret = xmlSchemaParseNewDocWithContext(pctxt, schema, bucket);
21627     if (ret == -1) {
21628 	pctxt->doc = NULL;
21629 	goto exit_failure;
21630     }
21631     /* Paranoid error channelling. */
21632     if ((ret == 0) && (pctxt->nberrors != 0))
21633 	ret = pctxt->err;
21634     if (pctxt->nberrors == 0) {
21635 	/*
21636 	* Only bother to fixup pending components, if there was
21637 	* no error yet.
21638 	* For every XSI acquired schema (and its sub-schemata) we will
21639 	* fixup the components.
21640 	*/
21641 	xmlSchemaFixupComponents(pctxt, bucket);
21642 	ret = pctxt->err;
21643 	/*
21644 	* Not nice, but we need somehow to channel the schema parser
21645 	* error to the validation context.
21646 	*/
21647 	if ((ret != 0) && (vctxt->err == 0))
21648 	    vctxt->err = ret;
21649 	vctxt->nberrors += pctxt->nberrors;
21650     } else {
21651 	/* Add to validation error sum. */
21652 	vctxt->nberrors += pctxt->nberrors;
21653     }
21654     pctxt->doc = NULL;
21655     return(ret);
21656 exit_failure:
21657     pctxt->doc = NULL;
21658     return (-1);
21659 }
21660 
21661 static xmlSchemaAttrInfoPtr
xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,int metaType)21662 xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,
21663 			 int metaType)
21664 {
21665     if (vctxt->nbAttrInfos == 0)
21666 	return (NULL);
21667     {
21668 	int i;
21669 	xmlSchemaAttrInfoPtr iattr;
21670 
21671 	for (i = 0; i < vctxt->nbAttrInfos; i++) {
21672 	    iattr = vctxt->attrInfos[i];
21673 	    if (iattr->metaType == metaType)
21674 		return (iattr);
21675 	}
21676 
21677     }
21678     return (NULL);
21679 }
21680 
21681 /**
21682  * xmlSchemaAssembleByXSI:
21683  * @vctxt:  a schema validation context
21684  *
21685  * Expands an existing schema by an additional schema using
21686  * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
21687  * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
21688  * must be set to 1.
21689  *
21690  * Returns 0 if the new schema is correct, a positive error code
21691  * number otherwise and -1 in case of an internal or API error.
21692  */
21693 static int
xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)21694 xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)
21695 {
21696     const xmlChar *cur, *end;
21697     const xmlChar *nsname = NULL, *location;
21698     int ret = 0;
21699     xmlSchemaAttrInfoPtr iattr;
21700 
21701     /*
21702     * Parse the value; we will assume an even number of values
21703     * to be given (this is how Xerces and XSV work).
21704     *
21705     * URGENT TODO: !! This needs to work for both
21706     * @noNamespaceSchemaLocation AND @schemaLocation on the same
21707     * element !!
21708     */
21709     iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21710 	XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC);
21711     if (iattr == NULL)
21712 	iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21713 	XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC);
21714     if (iattr == NULL)
21715 	return (0);
21716     cur = iattr->value;
21717     do {
21718 	/*
21719 	* TODO: Move the string parsing mechanism away from here.
21720 	*/
21721 	if (iattr->metaType == XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC) {
21722 	    /*
21723 	    * Get the namespace name.
21724 	    */
21725 	    while (IS_BLANK_CH(*cur))
21726 		cur++;
21727 	    end = cur;
21728 	    while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21729 		end++;
21730 	    if (end == cur)
21731 		break;
21732 	    /* TODO: Don't use the schema's dict. */
21733 	    nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
21734 	    cur = end;
21735 	}
21736 	/*
21737 	* Get the URI.
21738 	*/
21739 	while (IS_BLANK_CH(*cur))
21740 	    cur++;
21741 	end = cur;
21742 	while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21743 	    end++;
21744 	if (end == cur) {
21745 	    if (iattr->metaType ==
21746 		XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC)
21747 	    {
21748 		/*
21749 		* If using @schemaLocation then tuples are expected.
21750 		* I.e. the namespace name *and* the document's URI.
21751 		*/
21752 		xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC,
21753 		    iattr->node, NULL,
21754 		    "The value must consist of tuples: the target namespace "
21755 		    "name and the document's URI", NULL, NULL, NULL);
21756 	    }
21757 	    break;
21758 	}
21759 	/* TODO: Don't use the schema's dict. */
21760 	location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
21761 	cur = end;
21762 	ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
21763 	    iattr->node, nsname, location);
21764 	if (ret == -1) {
21765 	    VERROR_INT("xmlSchemaAssembleByXSI",
21766 		"assembling schemata");
21767 	    return (-1);
21768 	}
21769     } while (*cur != 0);
21770     return (ret);
21771 }
21772 
21773 static const xmlChar *
xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,const xmlChar * prefix)21774 xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,
21775 			 const xmlChar *prefix)
21776 {
21777     if (vctxt->sax != NULL) {
21778 	int i, j;
21779 	xmlSchemaNodeInfoPtr inode;
21780 
21781 	for (i = vctxt->depth; i >= 0; i--) {
21782 	    if (vctxt->elemInfos[i]->nbNsBindings != 0) {
21783 		inode = vctxt->elemInfos[i];
21784 		for (j = 0; j < inode->nbNsBindings * 2; j += 2) {
21785 		    if (((prefix == NULL) &&
21786 			    (inode->nsBindings[j] == NULL)) ||
21787 			((prefix != NULL) && xmlStrEqual(prefix,
21788 			    inode->nsBindings[j]))) {
21789 
21790 			/*
21791 			* Note that the namespace bindings are already
21792 			* in a string dict.
21793 			*/
21794 			return (inode->nsBindings[j+1]);
21795 		    }
21796 		}
21797 	    }
21798 	}
21799 	return (NULL);
21800 #ifdef LIBXML_READER_ENABLED
21801     } else if (vctxt->reader != NULL) {
21802 	xmlChar *nsName;
21803 
21804 	nsName = xmlTextReaderLookupNamespace(vctxt->reader, prefix);
21805 	if (nsName != NULL) {
21806 	    const xmlChar *ret;
21807 
21808 	    ret = xmlDictLookup(vctxt->dict, nsName, -1);
21809 	    xmlFree(nsName);
21810 	    return (ret);
21811 	} else
21812 	    return (NULL);
21813 #endif
21814     } else {
21815 	xmlNsPtr ns;
21816 
21817 	if ((vctxt->inode->node == NULL) ||
21818 	    (vctxt->inode->node->doc == NULL)) {
21819 	    VERROR_INT("xmlSchemaLookupNamespace",
21820 		"no node or node's doc available");
21821 	    return (NULL);
21822 	}
21823 	ns = xmlSearchNs(vctxt->inode->node->doc,
21824 	    vctxt->inode->node, prefix);
21825 	if (ns != NULL)
21826 	    return (ns->href);
21827 	return (NULL);
21828     }
21829 }
21830 
21831 /*
21832 * This one works on the schema of the validation context.
21833 */
21834 static int
xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,xmlSchemaPtr schema,xmlNodePtr node,const xmlChar * value,xmlSchemaValPtr * val,int valNeeded)21835 xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
21836 			  xmlSchemaPtr schema,
21837 			  xmlNodePtr node,
21838 			  const xmlChar *value,
21839 			  xmlSchemaValPtr *val,
21840 			  int valNeeded)
21841 {
21842     int ret;
21843 
21844     if (vctxt && (vctxt->schema == NULL)) {
21845 	VERROR_INT("xmlSchemaValidateNotation",
21846 	    "a schema is needed on the validation context");
21847 	return (-1);
21848     }
21849     ret = xmlValidateQName(value, 1);
21850     if (ret != 0)
21851 	return (ret);
21852     {
21853 	xmlChar *localName = NULL;
21854 	xmlChar *prefix = NULL;
21855 
21856 	localName = xmlSplitQName2(value, &prefix);
21857 	if (prefix != NULL) {
21858 	    const xmlChar *nsName = NULL;
21859 
21860 	    if (vctxt != NULL)
21861 		nsName = xmlSchemaLookupNamespace(vctxt, BAD_CAST prefix);
21862 	    else if (node != NULL) {
21863 		xmlNsPtr ns = xmlSearchNs(node->doc, node, prefix);
21864 		if (ns != NULL)
21865 		    nsName = ns->href;
21866 	    } else {
21867 		xmlFree(prefix);
21868 		xmlFree(localName);
21869 		return (1);
21870 	    }
21871 	    if (nsName == NULL) {
21872 		xmlFree(prefix);
21873 		xmlFree(localName);
21874 		return (1);
21875 	    }
21876 	    if (xmlSchemaGetNotation(schema, localName, nsName) != NULL) {
21877 		if ((valNeeded) && (val != NULL)) {
21878 		    (*val) = xmlSchemaNewNOTATIONValue(xmlStrdup(localName),
21879 						       xmlStrdup(nsName));
21880 		    if (*val == NULL)
21881 			ret = -1;
21882 		}
21883 	    } else
21884 		ret = 1;
21885 	    xmlFree(prefix);
21886 	    xmlFree(localName);
21887 	} else {
21888 	    if (xmlSchemaGetNotation(schema, value, NULL) != NULL) {
21889 		if (valNeeded && (val != NULL)) {
21890 		    (*val) = xmlSchemaNewNOTATIONValue(
21891 			BAD_CAST xmlStrdup(value), NULL);
21892 		    if (*val == NULL)
21893 			ret = -1;
21894 		}
21895 	    } else
21896 		return (1);
21897 	}
21898     }
21899     return (ret);
21900 }
21901 
21902 static int
xmlSchemaVAddNodeQName(xmlSchemaValidCtxtPtr vctxt,const xmlChar * lname,const xmlChar * nsname)21903 xmlSchemaVAddNodeQName(xmlSchemaValidCtxtPtr vctxt,
21904 		       const xmlChar* lname,
21905 		       const xmlChar* nsname)
21906 {
21907     int i;
21908 
21909     lname = xmlDictLookup(vctxt->dict, lname, -1);
21910     if (lname == NULL)
21911 	return(-1);
21912     if (nsname != NULL) {
21913 	nsname = xmlDictLookup(vctxt->dict, nsname, -1);
21914 	if (nsname == NULL)
21915 	    return(-1);
21916     }
21917     for (i = 0; i < vctxt->nodeQNames->nbItems; i += 2) {
21918 	if ((vctxt->nodeQNames->items [i] == lname) &&
21919 	    (vctxt->nodeQNames->items[i +1] == nsname))
21920 	    /* Already there */
21921 	    return(i);
21922     }
21923     /* Add new entry. */
21924     i = vctxt->nodeQNames->nbItems;
21925     xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) lname);
21926     xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) nsname);
21927     return(i);
21928 }
21929 
21930 /************************************************************************
21931  *									*
21932  *  Validation of identity-constraints (IDC)                            *
21933  *									*
21934  ************************************************************************/
21935 
21936 /**
21937  * xmlSchemaAugmentIDC:
21938  * @idcDef: the IDC definition
21939  *
21940  * Creates an augmented IDC definition item.
21941  *
21942  * Returns the item, or NULL on internal errors.
21943  */
21944 static void
xmlSchemaAugmentIDC(void * payload,void * data,const xmlChar * name ATTRIBUTE_UNUSED)21945 xmlSchemaAugmentIDC(void *payload, void *data,
21946                     const xmlChar *name ATTRIBUTE_UNUSED)
21947 {
21948     xmlSchemaIDCPtr idcDef = (xmlSchemaIDCPtr) payload;
21949     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) data;
21950     xmlSchemaIDCAugPtr aidc;
21951 
21952     aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
21953     if (aidc == NULL) {
21954 	xmlSchemaVErrMemory(vctxt);
21955 	return;
21956     }
21957     aidc->keyrefDepth = -1;
21958     aidc->def = idcDef;
21959     aidc->next = NULL;
21960     if (vctxt->aidcs == NULL)
21961 	vctxt->aidcs = aidc;
21962     else {
21963 	aidc->next = vctxt->aidcs;
21964 	vctxt->aidcs = aidc;
21965     }
21966     /*
21967     * Save if we have keyrefs at all.
21968     */
21969     if ((vctxt->hasKeyrefs == 0) &&
21970 	(idcDef->type == XML_SCHEMA_TYPE_IDC_KEYREF))
21971 	vctxt->hasKeyrefs = 1;
21972 }
21973 
21974 /**
21975  * xmlSchemaAugmentImportedIDC:
21976  * @imported: the imported schema
21977  *
21978  * Creates an augmented IDC definition for the imported schema.
21979  */
21980 static void
xmlSchemaAugmentImportedIDC(void * payload,void * data,const xmlChar * name ATTRIBUTE_UNUSED)21981 xmlSchemaAugmentImportedIDC(void *payload, void *data,
21982                             const xmlChar *name ATTRIBUTE_UNUSED) {
21983     xmlSchemaImportPtr imported = (xmlSchemaImportPtr) payload;
21984     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) data;
21985     if (imported->schema->idcDef != NULL) {
21986 	    xmlHashScan(imported->schema->idcDef, xmlSchemaAugmentIDC, vctxt);
21987     }
21988 }
21989 
21990 /**
21991  * xmlSchemaIDCNewBinding:
21992  * @idcDef: the IDC definition of this binding
21993  *
21994  * Creates a new IDC binding.
21995  *
21996  * Returns the new IDC binding, NULL on internal errors.
21997  */
21998 static xmlSchemaPSVIIDCBindingPtr
xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)21999 xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
22000 {
22001     xmlSchemaPSVIIDCBindingPtr ret;
22002 
22003     ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
22004 	    sizeof(xmlSchemaPSVIIDCBinding));
22005     if (ret == NULL) {
22006 	xmlSchemaVErrMemory(NULL);
22007 	return (NULL);
22008     }
22009     memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
22010     ret->definition = idcDef;
22011     return (ret);
22012 }
22013 
22014 /**
22015  * xmlSchemaIDCStoreNodeTableItem:
22016  * @vctxt: the WXS validation context
22017  * @item: the IDC node table item
22018  *
22019  * The validation context is used to store IDC node table items.
22020  * They are stored to avoid copying them if IDC node-tables are merged
22021  * with corresponding parent IDC node-tables (bubbling).
22022  *
22023  * Returns 0 if succeeded, -1 on internal errors.
22024  */
22025 static int
xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,xmlSchemaPSVIIDCNodePtr item)22026 xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
22027 			       xmlSchemaPSVIIDCNodePtr item)
22028 {
22029     /*
22030     * Add to global list.
22031     */
22032     if (vctxt->idcNodes == NULL) {
22033 	vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
22034 	    xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
22035 	if (vctxt->idcNodes == NULL) {
22036 	    xmlSchemaVErrMemory(vctxt);
22037 	    return (-1);
22038 	}
22039 	vctxt->sizeIdcNodes = 20;
22040     } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
22041 	vctxt->sizeIdcNodes *= 2;
22042 	vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
22043 	    xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
22044 	    sizeof(xmlSchemaPSVIIDCNodePtr));
22045 	if (vctxt->idcNodes == NULL) {
22046 	    xmlSchemaVErrMemory(vctxt);
22047 	    return (-1);
22048 	}
22049     }
22050     vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
22051 
22052     return (0);
22053 }
22054 
22055 /**
22056  * xmlSchemaIDCStoreKey:
22057  * @vctxt: the WXS validation context
22058  * @item: the IDC key
22059  *
22060  * The validation context is used to store an IDC key.
22061  *
22062  * Returns 0 if succeeded, -1 on internal errors.
22063  */
22064 static int
xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,xmlSchemaPSVIIDCKeyPtr key)22065 xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
22066 		     xmlSchemaPSVIIDCKeyPtr key)
22067 {
22068     /*
22069     * Add to global list.
22070     */
22071     if (vctxt->idcKeys == NULL) {
22072 	vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
22073 	    xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
22074 	if (vctxt->idcKeys == NULL) {
22075 	    xmlSchemaVErrMemory(vctxt);
22076 	    return (-1);
22077 	}
22078 	vctxt->sizeIdcKeys = 40;
22079     } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
22080 	vctxt->sizeIdcKeys *= 2;
22081 	vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
22082 	    xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
22083 	    sizeof(xmlSchemaPSVIIDCKeyPtr));
22084 	if (vctxt->idcKeys == NULL) {
22085 	    xmlSchemaVErrMemory(vctxt);
22086 	    return (-1);
22087 	}
22088     }
22089     vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
22090 
22091     return (0);
22092 }
22093 
22094 /**
22095  * xmlSchemaIDCAppendNodeTableItem:
22096  * @bind: the IDC binding
22097  * @ntItem: the node-table item
22098  *
22099  * Appends the IDC node-table item to the binding.
22100  *
22101  * Returns 0 on success and -1 on internal errors.
22102  */
22103 static int
xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,xmlSchemaPSVIIDCNodePtr ntItem)22104 xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
22105 				xmlSchemaPSVIIDCNodePtr ntItem)
22106 {
22107     if (bind->nodeTable == NULL) {
22108 	bind->sizeNodes = 10;
22109 	bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
22110 	    xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
22111 	if (bind->nodeTable == NULL) {
22112 	    xmlSchemaVErrMemory(NULL);
22113 	    return(-1);
22114 	}
22115     } else if (bind->sizeNodes <= bind->nbNodes) {
22116 	bind->sizeNodes *= 2;
22117 	bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
22118 	    xmlRealloc(bind->nodeTable, bind->sizeNodes *
22119 		sizeof(xmlSchemaPSVIIDCNodePtr));
22120 	if (bind->nodeTable == NULL) {
22121 	    xmlSchemaVErrMemory(NULL);
22122 	    return(-1);
22123 	}
22124     }
22125     bind->nodeTable[bind->nbNodes++] = ntItem;
22126     return(0);
22127 }
22128 
22129 /**
22130  * xmlSchemaIDCAcquireBinding:
22131  * @vctxt: the WXS validation context
22132  * @matcher: the IDC matcher
22133  *
22134  * Looks up an PSVI IDC binding, for the IDC definition and
22135  * of the given matcher. If none found, a new one is created
22136  * and added to the IDC table.
22137  *
22138  * Returns an IDC binding or NULL on internal errors.
22139  */
22140 static xmlSchemaPSVIIDCBindingPtr
xmlSchemaIDCAcquireBinding(xmlSchemaValidCtxtPtr vctxt,xmlSchemaIDCMatcherPtr matcher)22141 xmlSchemaIDCAcquireBinding(xmlSchemaValidCtxtPtr vctxt,
22142 			  xmlSchemaIDCMatcherPtr matcher)
22143 {
22144     xmlSchemaNodeInfoPtr ielem;
22145 
22146     ielem = vctxt->elemInfos[matcher->depth];
22147 
22148     if (ielem->idcTable == NULL) {
22149 	ielem->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
22150 	if (ielem->idcTable == NULL)
22151 	    return (NULL);
22152 	return(ielem->idcTable);
22153     } else {
22154 	xmlSchemaPSVIIDCBindingPtr bind = NULL;
22155 
22156 	bind = ielem->idcTable;
22157 	do {
22158 	    if (bind->definition == matcher->aidc->def)
22159 		return(bind);
22160 	    if (bind->next == NULL) {
22161 		bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
22162 		if (bind->next == NULL)
22163 		    return (NULL);
22164 		return(bind->next);
22165 	    }
22166 	    bind = bind->next;
22167 	} while (bind != NULL);
22168     }
22169     return (NULL);
22170 }
22171 
22172 static xmlSchemaItemListPtr
xmlSchemaIDCAcquireTargetList(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,xmlSchemaIDCMatcherPtr matcher)22173 xmlSchemaIDCAcquireTargetList(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
22174 			     xmlSchemaIDCMatcherPtr matcher)
22175 {
22176     if (matcher->targets == NULL)
22177 	matcher->targets = xmlSchemaItemListCreate();
22178     return(matcher->targets);
22179 }
22180 
22181 /**
22182  * xmlSchemaIDCFreeKey:
22183  * @key: the IDC key
22184  *
22185  * Frees an IDC key together with its compiled value.
22186  */
22187 static void
xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)22188 xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
22189 {
22190     if (key->val != NULL)
22191 	xmlSchemaFreeValue(key->val);
22192     xmlFree(key);
22193 }
22194 
22195 /**
22196  * xmlSchemaIDCFreeBinding:
22197  *
22198  * Frees an IDC binding. Note that the node table-items
22199  * are not freed.
22200  */
22201 static void
xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)22202 xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
22203 {
22204     if (bind->nodeTable != NULL)
22205 	xmlFree(bind->nodeTable);
22206     if (bind->dupls != NULL)
22207 	xmlSchemaItemListFree(bind->dupls);
22208     xmlFree(bind);
22209 }
22210 
22211 /**
22212  * xmlSchemaIDCFreeIDCTable:
22213  * @bind: the first IDC binding in the list
22214  *
22215  * Frees an IDC table, i.e. all the IDC bindings in the list.
22216  */
22217 static void
xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)22218 xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
22219 {
22220     xmlSchemaPSVIIDCBindingPtr prev;
22221 
22222     while (bind != NULL) {
22223 	prev = bind;
22224 	bind = bind->next;
22225 	xmlSchemaIDCFreeBinding(prev);
22226     }
22227 }
22228 
22229 static void
xmlFreeIDCHashEntry(void * payload,const xmlChar * name ATTRIBUTE_UNUSED)22230 xmlFreeIDCHashEntry (void *payload, const xmlChar *name ATTRIBUTE_UNUSED)
22231 {
22232     xmlIDCHashEntryPtr e = payload, n;
22233     while (e) {
22234 	n = e->next;
22235 	xmlFree(e);
22236 	e = n;
22237     }
22238 }
22239 
22240 /**
22241  * xmlSchemaIDCFreeMatcherList:
22242  * @matcher: the first IDC matcher in the list
22243  *
22244  * Frees a list of IDC matchers.
22245  */
22246 static void
xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)22247 xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
22248 {
22249     xmlSchemaIDCMatcherPtr next;
22250 
22251     while (matcher != NULL) {
22252 	next = matcher->next;
22253 	if (matcher->keySeqs != NULL) {
22254 	    int i;
22255 	    for (i = 0; i < matcher->sizeKeySeqs; i++)
22256 		if (matcher->keySeqs[i] != NULL)
22257 		    xmlFree(matcher->keySeqs[i]);
22258 	    xmlFree(matcher->keySeqs);
22259 	}
22260 	if (matcher->targets != NULL) {
22261 	    if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
22262 		int i;
22263 		xmlSchemaPSVIIDCNodePtr idcNode;
22264 		/*
22265 		* Node-table items for keyrefs are not stored globally
22266 		* to the validation context, since they are not bubbled.
22267 		* We need to free them here.
22268 		*/
22269 		for (i = 0; i < matcher->targets->nbItems; i++) {
22270 		    idcNode =
22271 			(xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
22272 		    xmlFree(idcNode->keys);
22273 		    xmlFree(idcNode);
22274 		}
22275 	    }
22276 	    xmlSchemaItemListFree(matcher->targets);
22277 	}
22278 	if (matcher->htab != NULL)
22279 	  xmlHashFree(matcher->htab, xmlFreeIDCHashEntry);
22280 	xmlFree(matcher);
22281 	matcher = next;
22282     }
22283 }
22284 
22285 /**
22286  * xmlSchemaIDCReleaseMatcherList:
22287  * @vctxt: the WXS validation context
22288  * @matcher: the first IDC matcher in the list
22289  *
22290  * Caches a list of IDC matchers for reuse.
22291  */
22292 static void
xmlSchemaIDCReleaseMatcherList(xmlSchemaValidCtxtPtr vctxt,xmlSchemaIDCMatcherPtr matcher)22293 xmlSchemaIDCReleaseMatcherList(xmlSchemaValidCtxtPtr vctxt,
22294 			       xmlSchemaIDCMatcherPtr matcher)
22295 {
22296     xmlSchemaIDCMatcherPtr next;
22297 
22298     while (matcher != NULL) {
22299 	next = matcher->next;
22300 	if (matcher->keySeqs != NULL) {
22301 	    int i;
22302 	    /*
22303 	    * Don't free the array, but only the content.
22304 	    */
22305 	    for (i = 0; i < matcher->sizeKeySeqs; i++)
22306 		if (matcher->keySeqs[i] != NULL) {
22307 		    xmlFree(matcher->keySeqs[i]);
22308 		    matcher->keySeqs[i] = NULL;
22309 		}
22310 	}
22311 	if (matcher->targets) {
22312 	    if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
22313 		int i;
22314 		xmlSchemaPSVIIDCNodePtr idcNode;
22315 		/*
22316 		* Node-table items for keyrefs are not stored globally
22317 		* to the validation context, since they are not bubbled.
22318 		* We need to free them here.
22319 		*/
22320 		for (i = 0; i < matcher->targets->nbItems; i++) {
22321 		    idcNode =
22322 			(xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
22323 		    xmlFree(idcNode->keys);
22324 		    xmlFree(idcNode);
22325 		}
22326 	    }
22327 	    xmlSchemaItemListFree(matcher->targets);
22328 	    matcher->targets = NULL;
22329 	}
22330 	if (matcher->htab != NULL) {
22331 	    xmlHashFree(matcher->htab, xmlFreeIDCHashEntry);
22332 	    matcher->htab = NULL;
22333 	}
22334 	matcher->next = NULL;
22335 	/*
22336 	* Cache the matcher.
22337 	*/
22338 	if (vctxt->idcMatcherCache != NULL)
22339 	    matcher->nextCached = vctxt->idcMatcherCache;
22340 	vctxt->idcMatcherCache = matcher;
22341 
22342 	matcher = next;
22343     }
22344 }
22345 
22346 /**
22347  * xmlSchemaIDCAddStateObject:
22348  * @vctxt: the WXS validation context
22349  * @matcher: the IDC matcher
22350  * @sel: the XPath information
22351  * @parent: the parent "selector" state object if any
22352  * @type: "selector" or "field"
22353  *
22354  * Creates/reuses and activates state objects for the given
22355  * XPath information; if the XPath expression consists of unions,
22356  * multiple state objects are created for every unioned expression.
22357  *
22358  * Returns 0 on success and -1 on internal errors.
22359  */
22360 static int
xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,xmlSchemaIDCMatcherPtr matcher,xmlSchemaIDCSelectPtr sel,int type)22361 xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
22362 			xmlSchemaIDCMatcherPtr matcher,
22363 			xmlSchemaIDCSelectPtr sel,
22364 			int type)
22365 {
22366     xmlSchemaIDCStateObjPtr sto;
22367 
22368     /*
22369     * Reuse the state objects from the pool.
22370     */
22371     if (vctxt->xpathStatePool != NULL) {
22372 	sto = vctxt->xpathStatePool;
22373 	vctxt->xpathStatePool = sto->next;
22374 	sto->next = NULL;
22375     } else {
22376 	/*
22377 	* Create a new state object.
22378 	*/
22379 	sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
22380 	if (sto == NULL) {
22381 	    xmlSchemaVErrMemory(NULL);
22382 	    return (-1);
22383 	}
22384 	memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
22385     }
22386     /*
22387     * Add to global list.
22388     */
22389     if (vctxt->xpathStates != NULL)
22390 	sto->next = vctxt->xpathStates;
22391     vctxt->xpathStates = sto;
22392 
22393     /*
22394     * Free the old xpath validation context.
22395     */
22396     if (sto->xpathCtxt != NULL)
22397 	xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
22398 
22399     /*
22400     * Create a new XPath (pattern) validation context.
22401     */
22402     sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
22403 	(xmlPatternPtr) sel->xpathComp);
22404     if (sto->xpathCtxt == NULL) {
22405 	VERROR_INT("xmlSchemaIDCAddStateObject",
22406 	    "failed to create an XPath validation context");
22407 	return (-1);
22408     }
22409     sto->type = type;
22410     sto->depth = vctxt->depth;
22411     sto->matcher = matcher;
22412     sto->sel = sel;
22413     sto->nbHistory = 0;
22414 
22415     return (0);
22416 }
22417 
22418 /**
22419  * xmlSchemaXPathEvaluate:
22420  * @vctxt: the WXS validation context
22421  * @nodeType: the nodeType of the current node
22422  *
22423  * Evaluates all active XPath state objects.
22424  *
22425  * Returns the number of IC "field" state objects which resolved to
22426  * this node, 0 if none resolved and -1 on internal errors.
22427  */
22428 static int
xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,xmlElementType nodeType)22429 xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
22430 		       xmlElementType nodeType)
22431 {
22432     xmlSchemaIDCStateObjPtr sto, head = NULL, first;
22433     int res, resolved = 0, depth = vctxt->depth;
22434 
22435     if (vctxt->xpathStates == NULL)
22436 	return (0);
22437 
22438     if (nodeType == XML_ATTRIBUTE_NODE)
22439 	depth++;
22440     /*
22441     * Process all active XPath state objects.
22442     */
22443     first = vctxt->xpathStates;
22444     sto = first;
22445     while (sto != head) {
22446 	if (nodeType == XML_ELEMENT_NODE)
22447 	    res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
22448 		vctxt->inode->localName, vctxt->inode->nsName);
22449 	else
22450 	    res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
22451 		vctxt->inode->localName, vctxt->inode->nsName);
22452 
22453 	if (res == -1) {
22454 	    VERROR_INT("xmlSchemaXPathEvaluate",
22455 		"calling xmlStreamPush()");
22456 	    return (-1);
22457 	}
22458 	if (res == 0)
22459 	    goto next_sto;
22460 	/*
22461 	* Full match.
22462 	*/
22463 	/*
22464 	* Register a match in the state object history.
22465 	*/
22466 	if (sto->history == NULL) {
22467 	    sto->history = (int *) xmlMalloc(5 * sizeof(int));
22468 	    if (sto->history == NULL) {
22469 		xmlSchemaVErrMemory(NULL);
22470 		return(-1);
22471 	    }
22472 	    sto->sizeHistory = 5;
22473 	} else if (sto->sizeHistory <= sto->nbHistory) {
22474 	    sto->sizeHistory *= 2;
22475 	    sto->history = (int *) xmlRealloc(sto->history,
22476 		sto->sizeHistory * sizeof(int));
22477 	    if (sto->history == NULL) {
22478 		xmlSchemaVErrMemory(NULL);
22479 		return(-1);
22480 	    }
22481 	}
22482 	sto->history[sto->nbHistory++] = depth;
22483 
22484 	if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
22485 	    xmlSchemaIDCSelectPtr sel;
22486 	    /*
22487 	    * Activate state objects for the IDC fields of
22488 	    * the IDC selector.
22489 	    */
22490 	    sel = sto->matcher->aidc->def->fields;
22491 	    while (sel != NULL) {
22492 		if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
22493 		    sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
22494 		    return (-1);
22495 		sel = sel->next;
22496 	    }
22497 	} else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22498 	    /*
22499 	    * An IDC key node was found by the IDC field.
22500 	    */
22501 	    /*
22502 	    * Notify that the character value of this node is
22503 	    * needed.
22504 	    */
22505 	    if (resolved == 0) {
22506 		if ((vctxt->inode->flags &
22507 		    XML_SCHEMA_NODE_INFO_VALUE_NEEDED) == 0)
22508 		vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
22509 	    }
22510 	    resolved++;
22511 	}
22512 next_sto:
22513 	if (sto->next == NULL) {
22514 	    /*
22515 	    * Evaluate field state objects created on this node as well.
22516 	    */
22517 	    head = first;
22518 	    sto = vctxt->xpathStates;
22519 	} else
22520 	    sto = sto->next;
22521     }
22522     return (resolved);
22523 }
22524 
22525 static const xmlChar *
xmlSchemaFormatIDCKeySequence_1(xmlSchemaValidCtxtPtr vctxt,xmlChar ** buf,xmlSchemaPSVIIDCKeyPtr * seq,int count,int for_hash)22526 xmlSchemaFormatIDCKeySequence_1(xmlSchemaValidCtxtPtr vctxt,
22527 				xmlChar **buf,
22528 				xmlSchemaPSVIIDCKeyPtr *seq,
22529 				int count, int for_hash)
22530 {
22531     int i, res;
22532     xmlChar *value = NULL;
22533 
22534     *buf = xmlStrdup(BAD_CAST "[");
22535     for (i = 0; i < count; i++) {
22536 	*buf = xmlStrcat(*buf, BAD_CAST "'");
22537 	if (!for_hash)
22538 	    res = xmlSchemaGetCanonValueWhtspExt(seq[i]->val,
22539 		    xmlSchemaGetWhiteSpaceFacetValue(seq[i]->type),
22540 		    &value);
22541 	else {
22542 	    res = xmlSchemaGetCanonValueHash(seq[i]->val, &value);
22543 	}
22544 	if (res == 0)
22545 	    *buf = xmlStrcat(*buf, BAD_CAST value);
22546 	else {
22547 	    VERROR_INT("xmlSchemaFormatIDCKeySequence",
22548 		"failed to compute a canonical value");
22549 	    *buf = xmlStrcat(*buf, BAD_CAST "???");
22550 	}
22551 	if (i < count -1)
22552 	    *buf = xmlStrcat(*buf, BAD_CAST "', ");
22553 	else
22554 	    *buf = xmlStrcat(*buf, BAD_CAST "'");
22555 	if (value != NULL) {
22556 	    xmlFree(value);
22557 	    value = NULL;
22558 	}
22559     }
22560     *buf = xmlStrcat(*buf, BAD_CAST "]");
22561 
22562     return (BAD_CAST *buf);
22563 }
22564 
22565 static const xmlChar *
xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,xmlChar ** buf,xmlSchemaPSVIIDCKeyPtr * seq,int count)22566 xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,
22567 			      xmlChar **buf,
22568 			      xmlSchemaPSVIIDCKeyPtr *seq,
22569 			      int count)
22570 {
22571     return xmlSchemaFormatIDCKeySequence_1(vctxt, buf, seq, count, 0);
22572 }
22573 
22574 static const xmlChar *
xmlSchemaHashKeySequence(xmlSchemaValidCtxtPtr vctxt,xmlChar ** buf,xmlSchemaPSVIIDCKeyPtr * seq,int count)22575 xmlSchemaHashKeySequence(xmlSchemaValidCtxtPtr vctxt,
22576 			 xmlChar **buf,
22577 			 xmlSchemaPSVIIDCKeyPtr *seq,
22578 			 int count)
22579 {
22580     return xmlSchemaFormatIDCKeySequence_1(vctxt, buf, seq, count, 1);
22581 }
22582 
22583 /**
22584  * xmlSchemaXPathPop:
22585  * @vctxt: the WXS validation context
22586  *
22587  * Pops all XPath states.
22588  *
22589  * Returns 0 on success and -1 on internal errors.
22590  */
22591 static int
xmlSchemaXPathPop(xmlSchemaValidCtxtPtr vctxt)22592 xmlSchemaXPathPop(xmlSchemaValidCtxtPtr vctxt)
22593 {
22594     xmlSchemaIDCStateObjPtr sto;
22595     int res;
22596 
22597     if (vctxt->xpathStates == NULL)
22598 	return(0);
22599     sto = vctxt->xpathStates;
22600     do {
22601 	res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22602 	if (res == -1)
22603 	    return (-1);
22604 	sto = sto->next;
22605     } while (sto != NULL);
22606     return(0);
22607 }
22608 
22609 /**
22610  * xmlSchemaXPathProcessHistory:
22611  * @vctxt: the WXS validation context
22612  * @type: the simple/complex type of the current node if any at all
22613  * @val: the precompiled value
22614  *
22615  * Processes and pops the history items of the IDC state objects.
22616  * IDC key-sequences are validated/created on IDC bindings.
22617  *
22618  * Returns 0 on success and -1 on internal errors.
22619  */
22620 static int
xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,int depth)22621 xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
22622 			     int depth)
22623 {
22624     xmlSchemaIDCStateObjPtr sto, nextsto;
22625     int res, matchDepth;
22626     xmlSchemaPSVIIDCKeyPtr key = NULL;
22627     xmlSchemaTypePtr type = vctxt->inode->typeDef, simpleType = NULL;
22628 
22629     if (vctxt->xpathStates == NULL)
22630 	return (0);
22631     sto = vctxt->xpathStates;
22632 
22633     /*
22634     * Evaluate the state objects.
22635     */
22636     while (sto != NULL) {
22637 	res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22638 	if (res == -1) {
22639 	    VERROR_INT("xmlSchemaXPathProcessHistory",
22640 		"calling xmlStreamPop()");
22641 	    return (-1);
22642 	}
22643 	if (sto->nbHistory == 0)
22644 	    goto deregister_check;
22645 
22646 	matchDepth = sto->history[sto->nbHistory -1];
22647 
22648 	/*
22649 	* Only matches at the current depth are of interest.
22650 	*/
22651 	if (matchDepth != depth) {
22652 	    sto = sto->next;
22653 	    continue;
22654 	}
22655 	if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22656 	    /*
22657 	    * NOTE: According to
22658 	    *   http://www.w3.org/Bugs/Public/show_bug.cgi?id=2198
22659 	    *   ... the simple-content of complex types is also allowed.
22660 	    */
22661 
22662 	    if (WXS_IS_COMPLEX(type)) {
22663 		if (WXS_HAS_SIMPLE_CONTENT(type)) {
22664 		    /*
22665 		    * Sanity check for complex types with simple content.
22666 		    */
22667 		    simpleType = type->contentTypeDef;
22668 		    if (simpleType == NULL) {
22669 			VERROR_INT("xmlSchemaXPathProcessHistory",
22670 			    "field resolves to a CT with simple content "
22671 			    "but the CT is missing the ST definition");
22672 			return (-1);
22673 		    }
22674 		} else
22675 		    simpleType = NULL;
22676 	    } else
22677 		simpleType = type;
22678 	    if (simpleType == NULL) {
22679 		xmlChar *str = NULL;
22680 
22681 		/*
22682 		* Not qualified if the field resolves to a node of non
22683 		* simple type.
22684 		*/
22685 		xmlSchemaCustomErr(ACTXT_CAST vctxt,
22686 		    XML_SCHEMAV_CVC_IDC, NULL,
22687 		    WXS_BASIC_CAST sto->matcher->aidc->def,
22688 		    "The XPath '%s' of a field of %s does evaluate to a node of "
22689 		    "non-simple type",
22690 		    sto->sel->xpath,
22691 		    xmlSchemaGetIDCDesignation(&str, sto->matcher->aidc->def));
22692 		FREE_AND_NULL(str);
22693 		sto->nbHistory--;
22694 		goto deregister_check;
22695 	    }
22696 
22697 	    if ((key == NULL) && (vctxt->inode->val == NULL)) {
22698 		/*
22699 		* Failed to provide the normalized value; maybe
22700 		* the value was invalid.
22701 		*/
22702 		VERROR(XML_SCHEMAV_CVC_IDC,
22703 		    WXS_BASIC_CAST sto->matcher->aidc->def,
22704 		    "Warning: No precomputed value available, the value "
22705 		    "was either invalid or something strange happened");
22706 		sto->nbHistory--;
22707 		goto deregister_check;
22708 	    } else {
22709 		xmlSchemaIDCMatcherPtr matcher = sto->matcher;
22710 		xmlSchemaPSVIIDCKeyPtr *keySeq;
22711 		int pos, idx;
22712 
22713 		/*
22714 		* The key will be anchored on the matcher's list of
22715 		* key-sequences. The position in this list is determined
22716 		* by the target node's depth relative to the matcher's
22717 		* depth of creation (i.e. the depth of the scope element).
22718 		*
22719 		* Element        Depth    Pos   List-entries
22720 		* <scope>          0              NULL
22721 		*   <bar>          1              NULL
22722 		*     <target/>    2       2      target
22723 		*   <bar>
22724                 * </scope>
22725 		*
22726 		* The size of the list is only dependent on the depth of
22727 		* the tree.
22728 		* An entry will be NULLed in selector_leave, i.e. when
22729 		* we hit the target's
22730 		*/
22731 		pos = sto->depth - matcher->depth;
22732 		idx = sto->sel->index;
22733 
22734 		/*
22735 		* Create/grow the array of key-sequences.
22736 		*/
22737 		if (matcher->keySeqs == NULL) {
22738 		    if (pos > 9)
22739 			matcher->sizeKeySeqs = pos * 2;
22740 		    else
22741 			matcher->sizeKeySeqs = 10;
22742 		    matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22743 			xmlMalloc(matcher->sizeKeySeqs *
22744 			sizeof(xmlSchemaPSVIIDCKeyPtr *));
22745 		    if (matcher->keySeqs == NULL) {
22746 			xmlSchemaVErrMemory(NULL);
22747 			return(-1);
22748 		    }
22749 		    memset(matcher->keySeqs, 0,
22750 			matcher->sizeKeySeqs *
22751 			sizeof(xmlSchemaPSVIIDCKeyPtr *));
22752 		} else if (pos >= matcher->sizeKeySeqs) {
22753 		    int i = matcher->sizeKeySeqs;
22754 
22755 		    matcher->sizeKeySeqs = pos * 2;
22756 		    matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22757 			xmlRealloc(matcher->keySeqs,
22758 			matcher->sizeKeySeqs *
22759 			sizeof(xmlSchemaPSVIIDCKeyPtr *));
22760 		    if (matcher->keySeqs == NULL) {
22761 			xmlSchemaVErrMemory(NULL);
22762 			return (-1);
22763 		    }
22764 		    /*
22765 		    * The array needs to be NULLed.
22766 		    * TODO: Use memset?
22767 		    */
22768 		    for (; i < matcher->sizeKeySeqs; i++)
22769 			matcher->keySeqs[i] = NULL;
22770 		}
22771 
22772 		/*
22773 		* Get/create the key-sequence.
22774 		*/
22775 		keySeq = matcher->keySeqs[pos];
22776 		if (keySeq == NULL) {
22777 		    goto create_sequence;
22778 		} else if (keySeq[idx] != NULL) {
22779 		    xmlChar *str = NULL;
22780 		    /*
22781 		    * cvc-identity-constraint:
22782 		    * 3 For each node in the `target node set` all
22783 		    * of the {fields}, with that node as the context
22784 		    * node, evaluate to either an empty node-set or
22785 		    * a node-set with exactly one member, which must
22786 		    * have a simple type.
22787 		    *
22788 		    * The key was already set; report an error.
22789 		    */
22790 		    xmlSchemaCustomErr(ACTXT_CAST vctxt,
22791 			XML_SCHEMAV_CVC_IDC, NULL,
22792 			WXS_BASIC_CAST matcher->aidc->def,
22793 			"The XPath '%s' of a field of %s evaluates to a "
22794 			"node-set with more than one member",
22795 			sto->sel->xpath,
22796 			xmlSchemaGetIDCDesignation(&str, matcher->aidc->def));
22797 		    FREE_AND_NULL(str);
22798 		    sto->nbHistory--;
22799 		    goto deregister_check;
22800 		} else
22801 		    goto create_key;
22802 
22803 create_sequence:
22804 		/*
22805 		* Create a key-sequence.
22806 		*/
22807 		keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
22808 		    matcher->aidc->def->nbFields *
22809 		    sizeof(xmlSchemaPSVIIDCKeyPtr));
22810 		if (keySeq == NULL) {
22811 		    xmlSchemaVErrMemory(NULL);
22812 		    return(-1);
22813 		}
22814 		memset(keySeq, 0, matcher->aidc->def->nbFields *
22815 		    sizeof(xmlSchemaPSVIIDCKeyPtr));
22816 		matcher->keySeqs[pos] = keySeq;
22817 create_key:
22818 		/*
22819 		* Create a key once per node only.
22820 		*/
22821 		if (key == NULL) {
22822 		    key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
22823 			sizeof(xmlSchemaPSVIIDCKey));
22824 		    if (key == NULL) {
22825 			xmlSchemaVErrMemory(NULL);
22826 			xmlFree(keySeq);
22827 			matcher->keySeqs[pos] = NULL;
22828 			return(-1);
22829 		    }
22830 		    /*
22831 		    * Consume the compiled value.
22832 		    */
22833 		    key->type = simpleType;
22834 		    key->val = vctxt->inode->val;
22835 		    vctxt->inode->val = NULL;
22836 		    /*
22837 		    * Store the key in a global list.
22838 		    */
22839 		    if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
22840 			xmlSchemaIDCFreeKey(key);
22841 			return (-1);
22842 		    }
22843 		}
22844 		keySeq[idx] = key;
22845 	    }
22846 	} else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
22847 
22848 	    xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
22849 	    /* xmlSchemaPSVIIDCBindingPtr bind; */
22850 	    xmlSchemaPSVIIDCNodePtr ntItem;
22851 	    xmlSchemaIDCMatcherPtr matcher;
22852 	    xmlSchemaIDCPtr idc;
22853 	    xmlSchemaItemListPtr targets;
22854 	    int pos, i, j, nbKeys;
22855 	    /*
22856 	    * Here we have the following scenario:
22857 	    * An IDC 'selector' state object resolved to a target node,
22858 	    * during the time this target node was in the
22859 	    * ancestor-or-self axis, the 'field' state object(s) looked
22860 	    * out for matching nodes to create a key-sequence for this
22861 	    * target node. Now we are back to this target node and need
22862 	    * to put the key-sequence, together with the target node
22863 	    * itself, into the node-table of the corresponding IDC
22864 	    * binding.
22865 	    */
22866 	    matcher = sto->matcher;
22867 	    idc = matcher->aidc->def;
22868 	    nbKeys = idc->nbFields;
22869 	    pos = depth - matcher->depth;
22870 	    /*
22871 	    * Check if the matcher has any key-sequences at all, plus
22872 	    * if it has a key-sequence for the current target node.
22873 	    */
22874 	    if ((matcher->keySeqs == NULL) ||
22875 		(matcher->sizeKeySeqs <= pos)) {
22876 		if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
22877 		    goto selector_key_error;
22878 		else
22879 		    goto selector_leave;
22880 	    }
22881 
22882 	    keySeq = &(matcher->keySeqs[pos]);
22883 	    if (*keySeq == NULL) {
22884 		if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
22885 		    goto selector_key_error;
22886 		else
22887 		    goto selector_leave;
22888 	    }
22889 
22890 	    for (i = 0; i < nbKeys; i++) {
22891 		if ((*keySeq)[i] == NULL) {
22892 		    /*
22893 		    * Not qualified, if not all fields did resolve.
22894 		    */
22895 		    if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
22896 			/*
22897 			* All fields of a "key" IDC must resolve.
22898 			*/
22899 			goto selector_key_error;
22900 		    }
22901 		    goto selector_leave;
22902 		}
22903 	    }
22904 	    /*
22905 	    * All fields did resolve.
22906 	    */
22907 
22908 	    /*
22909 	    * 4.1 If the {identity-constraint category} is unique(/key),
22910 	    * then no two members of the `qualified node set` have
22911 	    * `key-sequences` whose members are pairwise equal, as
22912 	    * defined by Equal in [XML Schemas: Datatypes].
22913 	    *
22914 	    * Get the IDC binding from the matcher and check for
22915 	    * duplicate key-sequences.
22916 	    */
22917 #if 0
22918 	    bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
22919 #endif
22920 	    targets = xmlSchemaIDCAcquireTargetList(vctxt, matcher);
22921 	    if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
22922 		(targets->nbItems != 0)) {
22923 		xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
22924 		xmlIDCHashEntryPtr e;
22925 
22926 		res = 0;
22927 
22928 		if (!matcher->htab)
22929 		    e = NULL;
22930 		else {
22931 		    xmlChar *value = NULL;
22932 		    xmlSchemaHashKeySequence(vctxt, &value, *keySeq, nbKeys);
22933 		    e = xmlHashLookup(matcher->htab, value);
22934 		    FREE_AND_NULL(value);
22935 		}
22936 
22937 		/*
22938 		* Compare the key-sequences, key by key.
22939 		*/
22940 		for (;e; e = e->next) {
22941 		    bkeySeq =
22942 			((xmlSchemaPSVIIDCNodePtr) targets->items[e->index])->keys;
22943 		    for (j = 0; j < nbKeys; j++) {
22944 			ckey = (*keySeq)[j];
22945 			bkey = bkeySeq[j];
22946 			res = xmlSchemaAreValuesEqual(ckey->val, bkey->val);
22947 			if (res == -1) {
22948 			    return (-1);
22949 			} else if (res == 0) {
22950 			    /*
22951 			    * One of the keys differs, so the key-sequence
22952 			    * won't be equal; get out.
22953 			    */
22954 			    break;
22955 			}
22956 		    }
22957 		    if (res == 1) {
22958 			/*
22959 			* Duplicate key-sequence found.
22960 			*/
22961 			break;
22962 		    }
22963 		}
22964 		if (e) {
22965 		    xmlChar *str = NULL, *strB = NULL;
22966 		    /*
22967 		    * TODO: Try to report the key-sequence.
22968 		    */
22969 		    xmlSchemaCustomErr(ACTXT_CAST vctxt,
22970 			XML_SCHEMAV_CVC_IDC, NULL,
22971 			WXS_BASIC_CAST idc,
22972 			"Duplicate key-sequence %s in %s",
22973 			xmlSchemaFormatIDCKeySequence(vctxt, &str,
22974 			    (*keySeq), nbKeys),
22975 			xmlSchemaGetIDCDesignation(&strB, idc));
22976 		    FREE_AND_NULL(str);
22977 		    FREE_AND_NULL(strB);
22978 		    goto selector_leave;
22979 		}
22980 	    }
22981 	    /*
22982 	    * Add a node-table item to the IDC binding.
22983 	    */
22984 	    ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
22985 		sizeof(xmlSchemaPSVIIDCNode));
22986 	    if (ntItem == NULL) {
22987 		xmlSchemaVErrMemory(NULL);
22988 		xmlFree(*keySeq);
22989 		*keySeq = NULL;
22990 		return(-1);
22991 	    }
22992 	    memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
22993 
22994 	    /*
22995 	    * Store the node-table item in a global list.
22996 	    */
22997 	    if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
22998 		if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
22999 		    xmlFree(ntItem);
23000 		    xmlFree(*keySeq);
23001 		    *keySeq = NULL;
23002 		    return (-1);
23003 		}
23004 		ntItem->nodeQNameID = -1;
23005 	    } else {
23006 		/*
23007 		* Save a cached QName for this node on the IDC node, to be
23008 		* able to report it, even if the node is not saved.
23009 		*/
23010 		ntItem->nodeQNameID = xmlSchemaVAddNodeQName(vctxt,
23011 		    vctxt->inode->localName, vctxt->inode->nsName);
23012 		if (ntItem->nodeQNameID == -1) {
23013 		    xmlFree(ntItem);
23014 		    xmlFree(*keySeq);
23015 		    *keySeq = NULL;
23016 		    return (-1);
23017 		}
23018 	    }
23019 	    /*
23020 	    * Init the node-table item: Save the node, position and
23021 	    * consume the key-sequence.
23022 	    */
23023 	    ntItem->node = vctxt->node;
23024 	    ntItem->nodeLine = vctxt->inode->nodeLine;
23025 	    ntItem->keys = *keySeq;
23026 	    *keySeq = NULL;
23027 #if 0
23028 	    if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1)
23029 #endif
23030 	    if (xmlSchemaItemListAdd(targets, ntItem) == -1) {
23031 		if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
23032 		    /*
23033 		    * Free the item, since keyref items won't be
23034 		    * put on a global list.
23035 		    */
23036 		    xmlFree(ntItem->keys);
23037 		    xmlFree(ntItem);
23038 		}
23039 		return (-1);
23040 	    }
23041 	    if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
23042 		xmlChar *value = NULL;
23043 		xmlIDCHashEntryPtr r, e;
23044 		if (!matcher->htab)
23045 		  matcher->htab = xmlHashCreate(4);
23046 		xmlSchemaHashKeySequence(vctxt, &value, ntItem->keys, nbKeys);
23047 		e = xmlMalloc(sizeof *e);
23048 		e->index = targets->nbItems - 1;
23049 		r = xmlHashLookup(matcher->htab, value);
23050 		if (r) {
23051 		    e->next = r->next;
23052 		    r->next = e;
23053 		} else {
23054 		    e->next = NULL;
23055 		    xmlHashAddEntry(matcher->htab, value, e);
23056 		}
23057 		FREE_AND_NULL(value);
23058 	    }
23059 
23060 	    goto selector_leave;
23061 selector_key_error:
23062 	    {
23063 		xmlChar *str = NULL;
23064 		/*
23065 		* 4.2.1 (KEY) The `target node set` and the
23066 		* `qualified node set` are equal, that is, every
23067 		* member of the `target node set` is also a member
23068 		* of the `qualified node set` and vice versa.
23069 		*/
23070 		xmlSchemaCustomErr(ACTXT_CAST vctxt,
23071 		    XML_SCHEMAV_CVC_IDC, NULL,
23072 		    WXS_BASIC_CAST idc,
23073 		    "Not all fields of %s evaluate to a node",
23074 		    xmlSchemaGetIDCDesignation(&str, idc), NULL);
23075 		FREE_AND_NULL(str);
23076 	    }
23077 selector_leave:
23078 	    /*
23079 	    * Free the key-sequence if not added to the IDC table.
23080 	    */
23081 	    if ((keySeq != NULL) && (*keySeq != NULL)) {
23082 		xmlFree(*keySeq);
23083 		*keySeq = NULL;
23084 	    }
23085 	} /* if selector */
23086 
23087 	sto->nbHistory--;
23088 
23089 deregister_check:
23090 	/*
23091 	* Deregister state objects if they reach the depth of creation.
23092 	*/
23093 	if ((sto->nbHistory == 0) && (sto->depth == depth)) {
23094 	    if (vctxt->xpathStates != sto) {
23095 		VERROR_INT("xmlSchemaXPathProcessHistory",
23096 		    "The state object to be removed is not the first "
23097 		    "in the list");
23098 	    }
23099 	    nextsto = sto->next;
23100 	    /*
23101 	    * Unlink from the list of active XPath state objects.
23102 	    */
23103 	    vctxt->xpathStates = sto->next;
23104 	    sto->next = vctxt->xpathStatePool;
23105 	    /*
23106 	    * Link it to the pool of reusable state objects.
23107 	    */
23108 	    vctxt->xpathStatePool = sto;
23109 	    sto = nextsto;
23110 	} else
23111 	    sto = sto->next;
23112     } /* while (sto != NULL) */
23113     return (0);
23114 }
23115 
23116 /**
23117  * xmlSchemaIDCRegisterMatchers:
23118  * @vctxt: the WXS validation context
23119  * @elemDecl: the element declaration
23120  *
23121  * Creates helper objects to evaluate IDC selectors/fields
23122  * successively.
23123  *
23124  * Returns 0 if OK and -1 on internal errors.
23125  */
23126 static int
xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,xmlSchemaElementPtr elemDecl)23127 xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
23128 			     xmlSchemaElementPtr elemDecl)
23129 {
23130     xmlSchemaIDCMatcherPtr matcher, last = NULL;
23131     xmlSchemaIDCPtr idc, refIdc;
23132     xmlSchemaIDCAugPtr aidc;
23133 
23134     idc = (xmlSchemaIDCPtr) elemDecl->idcs;
23135     if (idc == NULL)
23136 	return (0);
23137 
23138     if (vctxt->inode->idcMatchers != NULL) {
23139 	VERROR_INT("xmlSchemaIDCRegisterMatchers",
23140 	    "The chain of IDC matchers is expected to be empty");
23141 	return (-1);
23142     }
23143     do {
23144 	if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
23145 	    /*
23146 	    * Since IDCs bubbles are expensive we need to know the
23147 	    * depth at which the bubbles should stop; this will be
23148 	    * the depth of the top-most keyref IDC. If no keyref
23149 	    * references a key/unique IDC, the keyrefDepth will
23150 	    * be -1, indicating that no bubbles are needed.
23151 	    */
23152 	    refIdc = (xmlSchemaIDCPtr) idc->ref->item;
23153 	    if (refIdc != NULL) {
23154 		/*
23155 		* Remember that we have keyrefs on this node.
23156 		*/
23157 		vctxt->inode->hasKeyrefs = 1;
23158 		/*
23159 		* Lookup the referenced augmented IDC info.
23160 		*/
23161 		aidc = vctxt->aidcs;
23162 		while (aidc != NULL) {
23163 		    if (aidc->def == refIdc)
23164 			break;
23165 		    aidc = aidc->next;
23166 		}
23167 		if (aidc == NULL) {
23168 		    VERROR_INT("xmlSchemaIDCRegisterMatchers",
23169 			"Could not find an augmented IDC item for an IDC "
23170 			"definition");
23171 		    return (-1);
23172 		}
23173 		if ((aidc->keyrefDepth == -1) ||
23174 		    (vctxt->depth < aidc->keyrefDepth))
23175 		    aidc->keyrefDepth = vctxt->depth;
23176 	    }
23177 	}
23178 	/*
23179 	* Lookup the augmented IDC item for the IDC definition.
23180 	*/
23181 	aidc = vctxt->aidcs;
23182 	while (aidc != NULL) {
23183 	    if (aidc->def == idc)
23184 		break;
23185 	    aidc = aidc->next;
23186 	}
23187 	if (aidc == NULL) {
23188 	    VERROR_INT("xmlSchemaIDCRegisterMatchers",
23189 		"Could not find an augmented IDC item for an IDC definition");
23190 	    return (-1);
23191 	}
23192 	/*
23193 	* Create an IDC matcher for every IDC definition.
23194 	*/
23195 	if (vctxt->idcMatcherCache != NULL) {
23196 	    /*
23197 	    * Reuse a cached matcher.
23198 	    */
23199 	    matcher = vctxt->idcMatcherCache;
23200 	    vctxt->idcMatcherCache = matcher->nextCached;
23201 	    matcher->nextCached = NULL;
23202 	} else {
23203 	    matcher = (xmlSchemaIDCMatcherPtr)
23204 		xmlMalloc(sizeof(xmlSchemaIDCMatcher));
23205 	    if (matcher == NULL) {
23206 		xmlSchemaVErrMemory(vctxt);
23207 		return (-1);
23208 	    }
23209 	    memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
23210 	}
23211 	if (last == NULL)
23212 	    vctxt->inode->idcMatchers = matcher;
23213 	else
23214 	    last->next = matcher;
23215 	last = matcher;
23216 
23217 	matcher->type = IDC_MATCHER;
23218 	matcher->depth = vctxt->depth;
23219 	matcher->aidc = aidc;
23220 	matcher->idcType = aidc->def->type;
23221 	/*
23222 	* Init the automaton state object.
23223 	*/
23224 	if (xmlSchemaIDCAddStateObject(vctxt, matcher,
23225 	    idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
23226 	    return (-1);
23227 
23228 	idc = idc->next;
23229     } while (idc != NULL);
23230     return (0);
23231 }
23232 
23233 static int
xmlSchemaIDCFillNodeTables(xmlSchemaValidCtxtPtr vctxt,xmlSchemaNodeInfoPtr ielem)23234 xmlSchemaIDCFillNodeTables(xmlSchemaValidCtxtPtr vctxt,
23235 			   xmlSchemaNodeInfoPtr ielem)
23236 {
23237     xmlSchemaPSVIIDCBindingPtr bind;
23238     int res, i, j, k, nbTargets, nbFields, nbDupls, nbNodeTable;
23239     xmlSchemaPSVIIDCKeyPtr *keys, *ntkeys;
23240     xmlSchemaPSVIIDCNodePtr *targets, *dupls;
23241 
23242     xmlSchemaIDCMatcherPtr matcher = ielem->idcMatchers;
23243     /* vctxt->createIDCNodeTables */
23244     while (matcher != NULL) {
23245 	/*
23246 	* Skip keyref IDCs and empty IDC target-lists.
23247 	*/
23248 	if ((matcher->aidc->def->type == XML_SCHEMA_TYPE_IDC_KEYREF) ||
23249 	    WXS_ILIST_IS_EMPTY(matcher->targets))
23250 	{
23251 	    matcher = matcher->next;
23252 	    continue;
23253 	}
23254 	/*
23255 	* If we _want_ the IDC node-table to be created in any case
23256 	* then do so. Otherwise create them only if keyrefs need them.
23257 	*/
23258 	if ((! vctxt->createIDCNodeTables) &&
23259 	    ((matcher->aidc->keyrefDepth == -1) ||
23260 	     (matcher->aidc->keyrefDepth > vctxt->depth)))
23261 	{
23262 	    matcher = matcher->next;
23263 	    continue;
23264 	}
23265 	/*
23266 	* Get/create the IDC binding on this element for the IDC definition.
23267 	*/
23268 	bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
23269 	if (bind == NULL)
23270 	   goto internal_error;
23271 
23272 	if (! WXS_ILIST_IS_EMPTY(bind->dupls)) {
23273 	    dupls = (xmlSchemaPSVIIDCNodePtr *) bind->dupls->items;
23274 	    nbDupls = bind->dupls->nbItems;
23275 	} else {
23276 	    dupls = NULL;
23277 	    nbDupls = 0;
23278 	}
23279 	if (bind->nodeTable != NULL) {
23280 	    nbNodeTable = bind->nbNodes;
23281 	} else {
23282 	    nbNodeTable = 0;
23283 	}
23284 
23285 	if ((nbNodeTable == 0) && (nbDupls == 0)) {
23286 	    /*
23287 	    * Transfer all IDC target-nodes to the IDC node-table.
23288 	    */
23289 	    bind->nodeTable =
23290 		(xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
23291 	    bind->sizeNodes = matcher->targets->sizeItems;
23292 	    bind->nbNodes = matcher->targets->nbItems;
23293 
23294 	    matcher->targets->items = NULL;
23295 	    matcher->targets->sizeItems = 0;
23296 	    matcher->targets->nbItems = 0;
23297 	    if (matcher->htab) {
23298 		xmlHashFree(matcher->htab, xmlFreeIDCHashEntry);
23299 		matcher->htab = NULL;
23300 	    }
23301 	} else {
23302 	    /*
23303 	    * Compare the key-sequences and add to the IDC node-table.
23304 	    */
23305 	    nbTargets = matcher->targets->nbItems;
23306 	    targets = (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
23307 	    nbFields = matcher->aidc->def->nbFields;
23308 	    i = 0;
23309 	    do {
23310 		keys = targets[i]->keys;
23311 		if (nbDupls) {
23312 		    /*
23313 		    * Search in already found duplicates first.
23314 		    */
23315 		    j = 0;
23316 		    do {
23317 			if (nbFields == 1) {
23318 			    res = xmlSchemaAreValuesEqual(keys[0]->val,
23319 				dupls[j]->keys[0]->val);
23320 			    if (res == -1)
23321 				goto internal_error;
23322 			    if (res == 1) {
23323 				/*
23324 				* Equal key-sequence.
23325 				*/
23326 				goto next_target;
23327 			    }
23328 			} else {
23329 			    res = 0;
23330 			    ntkeys = dupls[j]->keys;
23331 			    for (k = 0; k < nbFields; k++) {
23332 				res = xmlSchemaAreValuesEqual(keys[k]->val,
23333 				    ntkeys[k]->val);
23334 				if (res == -1)
23335 				    goto internal_error;
23336 				if (res == 0) {
23337 				    /*
23338 				    * One of the keys differs.
23339 				    */
23340 				    break;
23341 				}
23342 			    }
23343 			    if (res == 1) {
23344 				/*
23345 				* Equal key-sequence found.
23346 				*/
23347 				goto next_target;
23348 			    }
23349 			}
23350 			j++;
23351 		    } while (j < nbDupls);
23352 		}
23353 		if (nbNodeTable) {
23354 		    j = 0;
23355 		    do {
23356 			if (nbFields == 1) {
23357 			    res = xmlSchemaAreValuesEqual(keys[0]->val,
23358 				bind->nodeTable[j]->keys[0]->val);
23359 			    if (res == -1)
23360 				goto internal_error;
23361 			    if (res == 0) {
23362 				/*
23363 				* The key-sequence differs.
23364 				*/
23365 				goto next_node_table_entry;
23366 			    }
23367 			} else {
23368 			    res = 0;
23369 			    ntkeys = bind->nodeTable[j]->keys;
23370 			    for (k = 0; k < nbFields; k++) {
23371 				res = xmlSchemaAreValuesEqual(keys[k]->val,
23372 				    ntkeys[k]->val);
23373 				if (res == -1)
23374 				    goto internal_error;
23375 				if (res == 0) {
23376 				    /*
23377 				    * One of the keys differs.
23378 				    */
23379 				    goto next_node_table_entry;
23380 				}
23381 			    }
23382 			}
23383 			/*
23384 			* Add the duplicate to the list of duplicates.
23385 			*/
23386 			if (bind->dupls == NULL) {
23387 			    bind->dupls = xmlSchemaItemListCreate();
23388 			    if (bind->dupls == NULL)
23389 				goto internal_error;
23390 			}
23391 			if (xmlSchemaItemListAdd(bind->dupls, bind->nodeTable[j]) == -1)
23392 			    goto internal_error;
23393 			/*
23394 			* Remove the duplicate entry from the IDC node-table.
23395 			*/
23396 			bind->nodeTable[j] = bind->nodeTable[bind->nbNodes -1];
23397 			bind->nbNodes--;
23398 
23399 			goto next_target;
23400 
23401 next_node_table_entry:
23402 			j++;
23403 		    } while (j < nbNodeTable);
23404 		}
23405 		/*
23406 		* If everything is fine, then add the IDC target-node to
23407 		* the IDC node-table.
23408 		*/
23409 		if (xmlSchemaIDCAppendNodeTableItem(bind, targets[i]) == -1)
23410 		    goto internal_error;
23411 
23412 next_target:
23413 		i++;
23414 	    } while (i < nbTargets);
23415 	}
23416 	matcher = matcher->next;
23417     }
23418     return(0);
23419 
23420 internal_error:
23421     return(-1);
23422 }
23423 
23424 /**
23425  * xmlSchemaBubbleIDCNodeTables:
23426  * @depth: the current tree depth
23427  *
23428  * Merges IDC bindings of an element at @depth into the corresponding IDC
23429  * bindings of its parent element. If a duplicate note-table entry is found,
23430  * both, the parent node-table entry and child entry are discarded from the
23431  * node-table of the parent.
23432  *
23433  * Returns 0 if OK and -1 on internal errors.
23434  */
23435 static int
xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)23436 xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
23437 {
23438     xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
23439     xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL; /* parent IDC bindings. */
23440     xmlSchemaPSVIIDCNodePtr node, parNode = NULL, *dupls, *parNodes; /* node-table entries. */
23441     xmlSchemaIDCAugPtr aidc;
23442     int i, j, k, ret = 0, nbFields, oldNum, oldDupls;
23443 
23444     bind = vctxt->inode->idcTable;
23445     if (bind == NULL) {
23446 	/* Fine, no table, no bubbles. */
23447 	return (0);
23448     }
23449 
23450     parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
23451     /*
23452     * Walk all bindings; create new or add to existing bindings.
23453     * Remove duplicate key-sequences.
23454     */
23455     while (bind != NULL) {
23456 
23457 	if ((bind->nbNodes == 0) && WXS_ILIST_IS_EMPTY(bind->dupls))
23458 	    goto next_binding;
23459 	/*
23460 	* Check if the key/unique IDC table needs to be bubbled.
23461 	*/
23462 	if (! vctxt->createIDCNodeTables) {
23463 	    aidc = vctxt->aidcs;
23464 	    do {
23465 		if (aidc->def == bind->definition) {
23466 		    if ((aidc->keyrefDepth == -1) ||
23467 			(aidc->keyrefDepth >= vctxt->depth)) {
23468 			goto next_binding;
23469 		    }
23470 		    break;
23471 		}
23472 		aidc = aidc->next;
23473 	    } while (aidc != NULL);
23474 	}
23475 
23476 	if (parTable != NULL)
23477 	    parBind = *parTable;
23478 	/*
23479 	* Search a matching parent binding for the
23480 	* IDC definition.
23481 	*/
23482 	while (parBind != NULL) {
23483 	    if (parBind->definition == bind->definition)
23484 		break;
23485 	    parBind = parBind->next;
23486 	}
23487 
23488 	if (parBind != NULL) {
23489 	    /*
23490 	    * Compare every node-table entry of the child node,
23491 	    * i.e. the key-sequence within, ...
23492 	    */
23493 	    oldNum = parBind->nbNodes; /* Skip newly added items. */
23494 
23495 	    if (! WXS_ILIST_IS_EMPTY(parBind->dupls)) {
23496 		oldDupls = parBind->dupls->nbItems;
23497 		dupls = (xmlSchemaPSVIIDCNodePtr *) parBind->dupls->items;
23498 	    } else {
23499 		dupls = NULL;
23500 		oldDupls = 0;
23501 	    }
23502 
23503 	    parNodes = parBind->nodeTable;
23504 	    nbFields = bind->definition->nbFields;
23505 
23506 	    for (i = 0; i < bind->nbNodes; i++) {
23507 		node = bind->nodeTable[i];
23508 		if (node == NULL)
23509 		    continue;
23510 		/*
23511 		* ...with every key-sequence of the parent node, already
23512 		* evaluated to be a duplicate key-sequence.
23513 		*/
23514 		if (oldDupls) {
23515 		    j = 0;
23516 		    while (j < oldDupls) {
23517 			if (nbFields == 1) {
23518 			    ret = xmlSchemaAreValuesEqual(
23519 				node->keys[0]->val,
23520 				dupls[j]->keys[0]->val);
23521 			    if (ret == -1)
23522 				goto internal_error;
23523 			    if (ret == 0) {
23524 				j++;
23525 				continue;
23526 			    }
23527 			} else {
23528 			    parNode = dupls[j];
23529 			    for (k = 0; k < nbFields; k++) {
23530 				ret = xmlSchemaAreValuesEqual(
23531 				    node->keys[k]->val,
23532 				    parNode->keys[k]->val);
23533 				if (ret == -1)
23534 				    goto internal_error;
23535 				if (ret == 0)
23536 				    break;
23537 			    }
23538 			}
23539 			if (ret == 1)
23540 			    /* Duplicate found. */
23541 			    break;
23542 			j++;
23543 		    }
23544 		    if (j != oldDupls) {
23545 			/* Duplicate found. Skip this entry. */
23546 			continue;
23547 		    }
23548 		}
23549 		/*
23550 		* ... and with every key-sequence of the parent node.
23551 		*/
23552 		if (oldNum) {
23553 		    j = 0;
23554 		    while (j < oldNum) {
23555 			parNode = parNodes[j];
23556 			if (nbFields == 1) {
23557 			    ret = xmlSchemaAreValuesEqual(
23558 				node->keys[0]->val,
23559 				parNode->keys[0]->val);
23560 			    if (ret == -1)
23561 				goto internal_error;
23562 			    if (ret == 0) {
23563 				j++;
23564 				continue;
23565 			    }
23566 			} else {
23567 			    for (k = 0; k < nbFields; k++) {
23568 				ret = xmlSchemaAreValuesEqual(
23569 				    node->keys[k]->val,
23570 				    parNode->keys[k]->val);
23571 				if (ret == -1)
23572 				    goto internal_error;
23573 				if (ret == 0)
23574 				    break;
23575 			    }
23576 			}
23577 			if (ret == 1)
23578 			    /* Duplicate found. */
23579 			    break;
23580 			j++;
23581 		    }
23582 		    if (j != oldNum) {
23583 			/*
23584 			* Handle duplicates. Move the duplicate in
23585 			* the parent's node-table to the list of
23586 			* duplicates.
23587 			*/
23588 			oldNum--;
23589 			parBind->nbNodes--;
23590 			/*
23591 			* Move last old item to pos of duplicate.
23592 			*/
23593 			parNodes[j] = parNodes[oldNum];
23594 
23595 			if (parBind->nbNodes != oldNum) {
23596 			    /*
23597 			    * If new items exist, move last new item to
23598 			    * last of old items.
23599 			    */
23600 			    parNodes[oldNum] =
23601 				parNodes[parBind->nbNodes];
23602 			}
23603 			if (parBind->dupls == NULL) {
23604 			    parBind->dupls = xmlSchemaItemListCreate();
23605 			    if (parBind->dupls == NULL)
23606 				goto internal_error;
23607 			}
23608 			xmlSchemaItemListAdd(parBind->dupls, parNode);
23609 		    } else {
23610 			/*
23611 			* Add the node-table entry (node and key-sequence) of
23612 			* the child node to the node table of the parent node.
23613 			*/
23614 			if (parBind->nodeTable == NULL) {
23615 			    parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23616 				xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
23617 			    if (parBind->nodeTable == NULL) {
23618 				xmlSchemaVErrMemory(NULL);
23619 				goto internal_error;
23620 			    }
23621 			    parBind->sizeNodes = 1;
23622 			} else if (parBind->nbNodes >= parBind->sizeNodes) {
23623 			    parBind->sizeNodes *= 2;
23624 			    parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23625 				xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
23626 				sizeof(xmlSchemaPSVIIDCNodePtr));
23627 			    if (parBind->nodeTable == NULL) {
23628 				xmlSchemaVErrMemory(NULL);
23629 				goto internal_error;
23630 			    }
23631 			}
23632 			parNodes = parBind->nodeTable;
23633 			/*
23634 			* Append the new node-table entry to the 'new node-table
23635 			* entries' section.
23636 			*/
23637 			parNodes[parBind->nbNodes++] = node;
23638 		    }
23639 
23640 		}
23641 
23642 	    }
23643 	} else {
23644 	    /*
23645 	    * No binding for the IDC was found: create a new one and
23646 	    * copy all node-tables.
23647 	    */
23648 	    parBind = xmlSchemaIDCNewBinding(bind->definition);
23649 	    if (parBind == NULL)
23650 		goto internal_error;
23651 
23652 	    /*
23653 	    * TODO: Hmm, how to optimize the initial number of
23654 	    * allocated entries?
23655 	    */
23656 	    if (bind->nbNodes != 0) {
23657 		/*
23658 		* Add all IDC node-table entries.
23659 		*/
23660 		if (! vctxt->psviExposeIDCNodeTables) {
23661 		    /*
23662 		    * Just move the entries.
23663 		    * NOTE: this is quite save here, since
23664 		    * all the keyref lookups have already been
23665 		    * performed.
23666 		    */
23667 		    parBind->nodeTable = bind->nodeTable;
23668 		    bind->nodeTable = NULL;
23669 		    parBind->sizeNodes = bind->sizeNodes;
23670 		    bind->sizeNodes = 0;
23671 		    parBind->nbNodes = bind->nbNodes;
23672 		    bind->nbNodes = 0;
23673 		} else {
23674 		    /*
23675 		    * Copy the entries.
23676 		    */
23677 		    parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23678 			xmlMalloc(bind->nbNodes *
23679 			sizeof(xmlSchemaPSVIIDCNodePtr));
23680 		    if (parBind->nodeTable == NULL) {
23681 			xmlSchemaVErrMemory(NULL);
23682 			xmlSchemaIDCFreeBinding(parBind);
23683 			goto internal_error;
23684 		    }
23685 		    parBind->sizeNodes = bind->nbNodes;
23686 		    parBind->nbNodes = bind->nbNodes;
23687 		    memcpy(parBind->nodeTable, bind->nodeTable,
23688 			bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
23689 		}
23690 	    }
23691 	    if (bind->dupls) {
23692 		/*
23693 		* Move the duplicates.
23694 		*/
23695 		if (parBind->dupls != NULL)
23696 		    xmlSchemaItemListFree(parBind->dupls);
23697 		parBind->dupls = bind->dupls;
23698 		bind->dupls = NULL;
23699 	    }
23700             if (parTable != NULL) {
23701                 if (*parTable == NULL)
23702                     *parTable = parBind;
23703                 else {
23704                     parBind->next = *parTable;
23705                     *parTable = parBind;
23706                 }
23707             }
23708 	}
23709 
23710 next_binding:
23711 	bind = bind->next;
23712     }
23713     return (0);
23714 
23715 internal_error:
23716     return(-1);
23717 }
23718 
23719 /**
23720  * xmlSchemaCheckCVCIDCKeyRef:
23721  * @vctxt: the WXS validation context
23722  * @elemDecl: the element declaration
23723  *
23724  * Check the cvc-idc-keyref constraints.
23725  */
23726 static int
xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)23727 xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
23728 {
23729     xmlSchemaIDCMatcherPtr matcher;
23730     xmlSchemaPSVIIDCBindingPtr bind;
23731 
23732     matcher = vctxt->inode->idcMatchers;
23733     /*
23734     * Find a keyref.
23735     */
23736     while (matcher != NULL) {
23737 	if ((matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) &&
23738 	    matcher->targets &&
23739 	    matcher->targets->nbItems)
23740 	{
23741 	    int i, j, k, res, nbFields, hasDupls;
23742 	    xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
23743 	    xmlSchemaPSVIIDCNodePtr refNode = NULL;
23744 	    xmlHashTablePtr table = NULL;
23745 
23746 	    nbFields = matcher->aidc->def->nbFields;
23747 
23748 	    /*
23749 	    * Find the IDC node-table for the referenced IDC key/unique.
23750 	    */
23751 	    bind = vctxt->inode->idcTable;
23752 	    while (bind != NULL) {
23753 		if ((xmlSchemaIDCPtr) matcher->aidc->def->ref->item ==
23754 		    bind->definition)
23755 		    break;
23756 		bind = bind->next;
23757 	    }
23758 	    hasDupls = (bind && bind->dupls && bind->dupls->nbItems) ? 1 : 0;
23759 	    /*
23760 	    * Search for a matching key-sequences.
23761 	    */
23762 	    if (bind) {
23763 		table = xmlHashCreate(bind->nbNodes * 2);
23764 		for (j = 0; j < bind->nbNodes; j++) {
23765 		    xmlChar *value;
23766 		    xmlIDCHashEntryPtr r, e;
23767 		    keys = bind->nodeTable[j]->keys;
23768 		    xmlSchemaHashKeySequence(vctxt, &value, keys, nbFields);
23769 		    e = xmlMalloc(sizeof *e);
23770 		    e->index = j;
23771 		    r = xmlHashLookup(table, value);
23772 		    if (r) {
23773 			e->next = r->next;
23774 			r->next = e;
23775 		    } else {
23776 			e->next = NULL;
23777 			xmlHashAddEntry(table, value, e);
23778 		    }
23779 		    FREE_AND_NULL(value);
23780 		}
23781 	    }
23782 	    for (i = 0; i < matcher->targets->nbItems; i++) {
23783 		res = 0;
23784 		refNode = matcher->targets->items[i];
23785 		if (bind != NULL) {
23786 		    xmlChar *value;
23787 		    xmlIDCHashEntryPtr e;
23788 		    refKeys = refNode->keys;
23789 		    xmlSchemaHashKeySequence(vctxt, &value, refKeys, nbFields);
23790 		    e = xmlHashLookup(table, value);
23791 		    FREE_AND_NULL(value);
23792 		    res = 0;
23793 		    for (;e; e = e->next) {
23794 			keys = bind->nodeTable[e->index]->keys;
23795 			for (k = 0; k < nbFields; k++) {
23796 			    res = xmlSchemaAreValuesEqual(keys[k]->val,
23797 							  refKeys[k]->val);
23798 			    if (res == 0)
23799 			        break;
23800 			    else if (res == -1) {
23801 				return (-1);
23802 			    }
23803 			}
23804 			if (res == 1) {
23805 			    /*
23806 			     * Match found.
23807 			     */
23808 			    break;
23809 			}
23810 		    }
23811 		    if ((res == 0) && hasDupls) {
23812 			/*
23813 			* Search in duplicates
23814 			*/
23815 			for (j = 0; j < bind->dupls->nbItems; j++) {
23816 			    keys = ((xmlSchemaPSVIIDCNodePtr)
23817 				bind->dupls->items[j])->keys;
23818 			    for (k = 0; k < nbFields; k++) {
23819 				res = xmlSchemaAreValuesEqual(keys[k]->val,
23820 				    refKeys[k]->val);
23821 				if (res == 0)
23822 				    break;
23823 				else if (res == -1) {
23824 				    return (-1);
23825 				}
23826 			    }
23827 			    if (res == 1) {
23828 				/*
23829 				* Match in duplicates found.
23830 				*/
23831 				xmlChar *str = NULL, *strB = NULL;
23832 				xmlSchemaKeyrefErr(vctxt,
23833 				    XML_SCHEMAV_CVC_IDC, refNode,
23834 				    (xmlSchemaTypePtr) matcher->aidc->def,
23835 				    "More than one match found for "
23836 				    "key-sequence %s of keyref '%s'",
23837 				    xmlSchemaFormatIDCKeySequence(vctxt, &str,
23838 					refNode->keys, nbFields),
23839 				    xmlSchemaGetComponentQName(&strB,
23840 					matcher->aidc->def));
23841 				FREE_AND_NULL(str);
23842 				FREE_AND_NULL(strB);
23843 				break;
23844 			    }
23845 			}
23846 		    }
23847 		}
23848 
23849 		if (res == 0) {
23850 		    xmlChar *str = NULL, *strB = NULL;
23851 		    xmlSchemaKeyrefErr(vctxt,
23852 			XML_SCHEMAV_CVC_IDC, refNode,
23853 			(xmlSchemaTypePtr) matcher->aidc->def,
23854 			"No match found for key-sequence %s of keyref '%s'",
23855 			xmlSchemaFormatIDCKeySequence(vctxt, &str,
23856 			    refNode->keys, nbFields),
23857 			xmlSchemaGetComponentQName(&strB, matcher->aidc->def));
23858 		    FREE_AND_NULL(str);
23859 		    FREE_AND_NULL(strB);
23860 		}
23861 	    }
23862 	    if (table) {
23863 		xmlHashFree(table, xmlFreeIDCHashEntry);
23864 	    }
23865 	}
23866 	matcher = matcher->next;
23867     }
23868     /* TODO: Return an error if any error encountered. */
23869     return (0);
23870 }
23871 
23872 /************************************************************************
23873  *									*
23874  *			XML Reader validation code                      *
23875  *									*
23876  ************************************************************************/
23877 
23878 static xmlSchemaAttrInfoPtr
xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)23879 xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)
23880 {
23881     xmlSchemaAttrInfoPtr iattr;
23882     /*
23883     * Grow/create list of attribute infos.
23884     */
23885     if (vctxt->attrInfos == NULL) {
23886 	vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
23887 	    xmlMalloc(sizeof(xmlSchemaAttrInfoPtr));
23888 	vctxt->sizeAttrInfos = 1;
23889 	if (vctxt->attrInfos == NULL) {
23890 	    xmlSchemaVErrMemory(vctxt);
23891 	    return (NULL);
23892 	}
23893     } else if (vctxt->sizeAttrInfos <= vctxt->nbAttrInfos) {
23894 	vctxt->sizeAttrInfos++;
23895 	vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
23896 	    xmlRealloc(vctxt->attrInfos,
23897 		vctxt->sizeAttrInfos * sizeof(xmlSchemaAttrInfoPtr));
23898 	if (vctxt->attrInfos == NULL) {
23899 	    xmlSchemaVErrMemory(vctxt);
23900 	    return (NULL);
23901 	}
23902     } else {
23903 	iattr = vctxt->attrInfos[vctxt->nbAttrInfos++];
23904 	if (iattr->localName != NULL) {
23905 	    VERROR_INT("xmlSchemaGetFreshAttrInfo",
23906 		"attr info not cleared");
23907 	    return (NULL);
23908 	}
23909 	iattr->nodeType = XML_ATTRIBUTE_NODE;
23910 	return (iattr);
23911     }
23912     /*
23913     * Create an attribute info.
23914     */
23915     iattr = (xmlSchemaAttrInfoPtr)
23916 	xmlMalloc(sizeof(xmlSchemaAttrInfo));
23917     if (iattr == NULL) {
23918 	xmlSchemaVErrMemory(vctxt);
23919 	return (NULL);
23920     }
23921     memset(iattr, 0, sizeof(xmlSchemaAttrInfo));
23922     iattr->nodeType = XML_ATTRIBUTE_NODE;
23923     vctxt->attrInfos[vctxt->nbAttrInfos++] = iattr;
23924 
23925     return (iattr);
23926 }
23927 
23928 static int
xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,xmlNodePtr attrNode,int nodeLine,const xmlChar * localName,const xmlChar * nsName,int ownedNames,xmlChar * value,int ownedValue)23929 xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,
23930 			xmlNodePtr attrNode,
23931 			int nodeLine,
23932 			const xmlChar *localName,
23933 			const xmlChar *nsName,
23934 			int ownedNames,
23935 			xmlChar *value,
23936 			int ownedValue)
23937 {
23938     xmlSchemaAttrInfoPtr attr;
23939 
23940     attr = xmlSchemaGetFreshAttrInfo(vctxt);
23941     if (attr == NULL) {
23942 	VERROR_INT("xmlSchemaPushAttribute",
23943 	    "calling xmlSchemaGetFreshAttrInfo()");
23944 	return (-1);
23945     }
23946     attr->node = attrNode;
23947     attr->nodeLine = nodeLine;
23948     attr->state = XML_SCHEMAS_ATTR_UNKNOWN;
23949     attr->localName = localName;
23950     attr->nsName = nsName;
23951     if (ownedNames)
23952 	attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
23953     /*
23954     * Evaluate if it's an XSI attribute.
23955     */
23956     if (nsName != NULL) {
23957 	if (xmlStrEqual(localName, BAD_CAST "nil")) {
23958 	    if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23959 		attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NIL;
23960 	    }
23961 	} else if (xmlStrEqual(localName, BAD_CAST "type")) {
23962 	    if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23963 		attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_TYPE;
23964 	    }
23965 	} else if (xmlStrEqual(localName, BAD_CAST "schemaLocation")) {
23966 	    if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23967 		attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC;
23968 	    }
23969 	} else if (xmlStrEqual(localName, BAD_CAST "noNamespaceSchemaLocation")) {
23970 	    if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23971 		attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC;
23972 	    }
23973 	} else if (xmlStrEqual(attr->nsName, xmlNamespaceNs)) {
23974 	    attr->metaType = XML_SCHEMA_ATTR_INFO_META_XMLNS;
23975 	}
23976     }
23977     attr->value = value;
23978     if (ownedValue)
23979 	attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
23980     if (attr->metaType != 0)
23981 	attr->state = XML_SCHEMAS_ATTR_META;
23982     return (0);
23983 }
23984 
23985 /**
23986  * xmlSchemaClearElemInfo:
23987  * @vctxt: the WXS validation context
23988  * @ielem: the element information item
23989  */
23990 static void
xmlSchemaClearElemInfo(xmlSchemaValidCtxtPtr vctxt,xmlSchemaNodeInfoPtr ielem)23991 xmlSchemaClearElemInfo(xmlSchemaValidCtxtPtr vctxt,
23992 		       xmlSchemaNodeInfoPtr ielem)
23993 {
23994     ielem->hasKeyrefs = 0;
23995     ielem->appliedXPath = 0;
23996     if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
23997 	FREE_AND_NULL(ielem->localName);
23998 	FREE_AND_NULL(ielem->nsName);
23999     } else {
24000 	ielem->localName = NULL;
24001 	ielem->nsName = NULL;
24002     }
24003     if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
24004 	FREE_AND_NULL(ielem->value);
24005     } else {
24006 	ielem->value = NULL;
24007     }
24008     if (ielem->val != NULL) {
24009 	/*
24010 	* PSVI TODO: Be careful not to free it when the value is
24011 	* exposed via PSVI.
24012 	*/
24013 	xmlSchemaFreeValue(ielem->val);
24014 	ielem->val = NULL;
24015     }
24016     if (ielem->idcMatchers != NULL) {
24017 	/*
24018 	* REVISIT OPTIMIZE TODO: Use a pool of IDC matchers.
24019 	*   Does it work?
24020 	*/
24021 	xmlSchemaIDCReleaseMatcherList(vctxt, ielem->idcMatchers);
24022 #if 0
24023 	xmlSchemaIDCFreeMatcherList(ielem->idcMatchers);
24024 #endif
24025 	ielem->idcMatchers = NULL;
24026     }
24027     if (ielem->idcTable != NULL) {
24028 	/*
24029 	* OPTIMIZE TODO: Use a pool of IDC tables??.
24030 	*/
24031 	xmlSchemaIDCFreeIDCTable(ielem->idcTable);
24032 	ielem->idcTable = NULL;
24033     }
24034     if (ielem->regexCtxt != NULL) {
24035 	xmlRegFreeExecCtxt(ielem->regexCtxt);
24036 	ielem->regexCtxt = NULL;
24037     }
24038     if (ielem->nsBindings != NULL) {
24039 	xmlFree((xmlChar **)ielem->nsBindings);
24040 	ielem->nsBindings = NULL;
24041 	ielem->nbNsBindings = 0;
24042 	ielem->sizeNsBindings = 0;
24043     }
24044 }
24045 
24046 /**
24047  * xmlSchemaGetFreshElemInfo:
24048  * @vctxt: the schema validation context
24049  *
24050  * Creates/reuses and initializes the element info item for
24051  * the current tree depth.
24052  *
24053  * Returns the element info item or NULL on API or internal errors.
24054  */
24055 static xmlSchemaNodeInfoPtr
xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)24056 xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)
24057 {
24058     xmlSchemaNodeInfoPtr info = NULL;
24059 
24060     if (vctxt->depth > vctxt->sizeElemInfos) {
24061 	VERROR_INT("xmlSchemaGetFreshElemInfo",
24062 	    "inconsistent depth encountered");
24063 	return (NULL);
24064     }
24065     if (vctxt->elemInfos == NULL) {
24066 	vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
24067 	    xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
24068 	if (vctxt->elemInfos == NULL) {
24069 	    xmlSchemaVErrMemory(vctxt);
24070 	    return (NULL);
24071 	}
24072 	memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
24073 	vctxt->sizeElemInfos = 10;
24074     } else if (vctxt->sizeElemInfos <= vctxt->depth) {
24075 	int i = vctxt->sizeElemInfos;
24076 
24077 	vctxt->sizeElemInfos *= 2;
24078 	vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
24079 	    xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
24080 	    sizeof(xmlSchemaNodeInfoPtr));
24081 	if (vctxt->elemInfos == NULL) {
24082 	    xmlSchemaVErrMemory(vctxt);
24083 	    return (NULL);
24084 	}
24085 	/*
24086 	* We need the new memory to be NULLed.
24087 	* TODO: Use memset instead?
24088 	*/
24089 	for (; i < vctxt->sizeElemInfos; i++)
24090 	    vctxt->elemInfos[i] = NULL;
24091     } else
24092 	info = vctxt->elemInfos[vctxt->depth];
24093 
24094     if (info == NULL) {
24095 	info = (xmlSchemaNodeInfoPtr)
24096 	    xmlMalloc(sizeof(xmlSchemaNodeInfo));
24097 	if (info == NULL) {
24098 	    xmlSchemaVErrMemory(vctxt);
24099 	    return (NULL);
24100 	}
24101 	vctxt->elemInfos[vctxt->depth] = info;
24102     } else {
24103 	if (info->localName != NULL) {
24104 	    VERROR_INT("xmlSchemaGetFreshElemInfo",
24105 		"elem info has not been cleared");
24106 	    return (NULL);
24107 	}
24108     }
24109     memset(info, 0, sizeof(xmlSchemaNodeInfo));
24110     info->nodeType = XML_ELEMENT_NODE;
24111     info->depth = vctxt->depth;
24112 
24113     return (info);
24114 }
24115 
24116 #define ACTIVATE_ATTRIBUTE(item) vctxt->inode = (xmlSchemaNodeInfoPtr) item;
24117 #define ACTIVATE_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth];
24118 #define ACTIVATE_PARENT_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth -1];
24119 
24120 static int
xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,xmlNodePtr node,xmlSchemaTypePtr type,xmlSchemaValType valType,const xmlChar * value,xmlSchemaValPtr val,unsigned long length,int fireErrors)24121 xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,
24122 			xmlNodePtr node,
24123 			xmlSchemaTypePtr type,
24124 			xmlSchemaValType valType,
24125 			const xmlChar * value,
24126 			xmlSchemaValPtr val,
24127 			unsigned long length,
24128 			int fireErrors)
24129 {
24130     int ret, error = 0, found;
24131 
24132     xmlSchemaTypePtr tmpType;
24133     xmlSchemaFacetLinkPtr facetLink;
24134     xmlSchemaFacetPtr facet;
24135     unsigned long len = 0;
24136     xmlSchemaWhitespaceValueType ws;
24137 
24138     /*
24139     * In Libxml2, derived built-in types have currently no explicit facets.
24140     */
24141     if (type->type == XML_SCHEMA_TYPE_BASIC)
24142 	return (0);
24143 
24144     /*
24145     * NOTE: Do not jump away, if the facetSet of the given type is
24146     * empty: until now, "pattern" and "enumeration" facets of the
24147     * *base types* need to be checked as well.
24148     */
24149     if (type->facetSet == NULL)
24150 	goto pattern_and_enum;
24151 
24152     if (! WXS_IS_ATOMIC(type)) {
24153 	if (WXS_IS_LIST(type))
24154 	    goto WXS_IS_LIST;
24155 	else
24156 	    goto pattern_and_enum;
24157     }
24158 
24159     /*
24160     * Whitespace handling is only of importance for string-based
24161     * types.
24162     */
24163     tmpType = xmlSchemaGetPrimitiveType(type);
24164     if ((tmpType->builtInType == XML_SCHEMAS_STRING) ||
24165 	WXS_IS_ANY_SIMPLE_TYPE(tmpType)) {
24166 	ws = xmlSchemaGetWhiteSpaceFacetValue(type);
24167     } else
24168 	ws = XML_SCHEMA_WHITESPACE_COLLAPSE;
24169 
24170     /*
24171     * If the value was not computed (for string or
24172     * anySimpleType based types), then use the provided
24173     * type.
24174     */
24175     if (val != NULL)
24176 	valType = xmlSchemaGetValType(val);
24177 
24178     ret = 0;
24179     for (facetLink = type->facetSet; facetLink != NULL;
24180 	facetLink = facetLink->next) {
24181 	/*
24182 	* Skip the pattern "whiteSpace": it is used to
24183 	* format the character content beforehand.
24184 	*/
24185 	switch (facetLink->facet->type) {
24186 	    case XML_SCHEMA_FACET_WHITESPACE:
24187 	    case XML_SCHEMA_FACET_PATTERN:
24188 	    case XML_SCHEMA_FACET_ENUMERATION:
24189 		continue;
24190 	    case XML_SCHEMA_FACET_LENGTH:
24191 	    case XML_SCHEMA_FACET_MINLENGTH:
24192 	    case XML_SCHEMA_FACET_MAXLENGTH:
24193 		ret = xmlSchemaValidateLengthFacetWhtsp(facetLink->facet,
24194 		    valType, value, val, &len, ws);
24195 		break;
24196 	    default:
24197 		ret = xmlSchemaValidateFacetWhtsp(facetLink->facet, ws,
24198 		    valType, value, val, ws);
24199 		break;
24200 	}
24201 	if (ret < 0) {
24202 	    AERROR_INT("xmlSchemaValidateFacets",
24203 		"validating against a atomic type facet");
24204 	    return (-1);
24205 	} else if (ret > 0) {
24206 	    if (fireErrors)
24207 		xmlSchemaFacetErr(actxt, ret, node,
24208 		value, len, type, facetLink->facet, NULL, NULL, NULL);
24209 	    else
24210 		return (ret);
24211 	    if (error == 0)
24212 		error = ret;
24213 	}
24214 	ret = 0;
24215     }
24216 
24217 WXS_IS_LIST:
24218     if (! WXS_IS_LIST(type))
24219 	goto pattern_and_enum;
24220     /*
24221     * "length", "minLength" and "maxLength" of list types.
24222     */
24223     ret = 0;
24224     for (facetLink = type->facetSet; facetLink != NULL;
24225 	facetLink = facetLink->next) {
24226 
24227 	switch (facetLink->facet->type) {
24228 	    case XML_SCHEMA_FACET_LENGTH:
24229 	    case XML_SCHEMA_FACET_MINLENGTH:
24230 	    case XML_SCHEMA_FACET_MAXLENGTH:
24231 		ret = xmlSchemaValidateListSimpleTypeFacet(facetLink->facet,
24232 		    value, length, NULL);
24233 		break;
24234 	    default:
24235 		continue;
24236 	}
24237 	if (ret < 0) {
24238 	    AERROR_INT("xmlSchemaValidateFacets",
24239 		"validating against a list type facet");
24240 	    return (-1);
24241 	} else if (ret > 0) {
24242 	    if (fireErrors)
24243 		xmlSchemaFacetErr(actxt, ret, node,
24244 		value, length, type, facetLink->facet, NULL, NULL, NULL);
24245 	    else
24246 		return (ret);
24247 	    if (error == 0)
24248 		error = ret;
24249 	}
24250 	ret = 0;
24251     }
24252 
24253 pattern_and_enum:
24254     found = 0;
24255     /*
24256     * Process enumerations. Facet values are in the value space
24257     * of the defining type's base type. This seems to be a bug in the
24258     * XML Schema 1.0 spec. Use the whitespace type of the base type.
24259     * Only the first set of enumerations in the ancestor-or-self axis
24260     * is used for validation.
24261     */
24262     ret = 0;
24263     tmpType = type;
24264     do {
24265         for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
24266             if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
24267                 continue;
24268             found = 1;
24269             ret = xmlSchemaAreValuesEqual(facet->val, val);
24270             if (ret == 1)
24271                 break;
24272             else if (ret < 0) {
24273                 AERROR_INT("xmlSchemaValidateFacets",
24274                     "validating against an enumeration facet");
24275                 return (-1);
24276             }
24277         }
24278         if (ret != 0)
24279             break;
24280         /*
24281         * Break on the first set of enumerations. Any additional
24282         *  enumerations which might be existent on the ancestors
24283         *  of the current type are restricted by this set; thus
24284         *  *must* *not* be taken into account.
24285         */
24286         if (found)
24287             break;
24288         tmpType = tmpType->baseType;
24289     } while ((tmpType != NULL) &&
24290         (tmpType->type != XML_SCHEMA_TYPE_BASIC));
24291     if (found && (ret == 0)) {
24292         ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
24293         if (fireErrors) {
24294             xmlSchemaFacetErr(actxt, ret, node,
24295                 value, 0, type, NULL, NULL, NULL, NULL);
24296         } else
24297             return (ret);
24298         if (error == 0)
24299             error = ret;
24300     }
24301 
24302     /*
24303     * Process patters. Pattern facets are ORed at type level
24304     * and ANDed if derived. Walk the base type axis.
24305     */
24306     tmpType = type;
24307     facet = NULL;
24308     do {
24309         found = 0;
24310         for (facetLink = tmpType->facetSet; facetLink != NULL;
24311             facetLink = facetLink->next) {
24312             if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
24313                 continue;
24314             found = 1;
24315             /*
24316             * NOTE that for patterns, @value needs to be the
24317             * normalized value.
24318             */
24319             ret = xmlRegexpExec(facetLink->facet->regexp, value);
24320             if (ret == 1)
24321                 break;
24322             else if (ret < 0) {
24323                 AERROR_INT("xmlSchemaValidateFacets",
24324                     "validating against a pattern facet");
24325                 return (-1);
24326             } else {
24327                 /*
24328                 * Save the last non-validating facet.
24329                 */
24330                 facet = facetLink->facet;
24331             }
24332         }
24333         if (found && (ret != 1)) {
24334             ret = XML_SCHEMAV_CVC_PATTERN_VALID;
24335             if (fireErrors) {
24336                 xmlSchemaFacetErr(actxt, ret, node,
24337                     value, 0, type, facet, NULL, NULL, NULL);
24338             } else
24339                 return (ret);
24340             if (error == 0)
24341                 error = ret;
24342             break;
24343         }
24344         tmpType = tmpType->baseType;
24345     } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
24346 
24347     return (error);
24348 }
24349 
24350 static xmlChar *
xmlSchemaNormalizeValue(xmlSchemaTypePtr type,const xmlChar * value)24351 xmlSchemaNormalizeValue(xmlSchemaTypePtr type,
24352 			const xmlChar *value)
24353 {
24354     switch (xmlSchemaGetWhiteSpaceFacetValue(type)) {
24355 	case XML_SCHEMA_WHITESPACE_COLLAPSE:
24356 	    return (xmlSchemaCollapseString(value));
24357 	case XML_SCHEMA_WHITESPACE_REPLACE:
24358 	    return (xmlSchemaWhiteSpaceReplace(value));
24359 	default:
24360 	    return (NULL);
24361     }
24362 }
24363 
24364 static int
xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt,const xmlChar * value,xmlSchemaValPtr * val,int valNeeded)24365 xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt,
24366 		       const xmlChar *value,
24367 		       xmlSchemaValPtr *val,
24368 		       int valNeeded)
24369 {
24370     int ret;
24371     xmlChar *stripped;
24372     const xmlChar *nsName;
24373     xmlChar *local, *prefix = NULL;
24374 
24375     ret = xmlValidateQName(value, 1);
24376     if (ret != 0) {
24377 	if (ret == -1) {
24378 	    VERROR_INT("xmlSchemaValidateQName",
24379 		"calling xmlValidateQName()");
24380 	    return (-1);
24381 	}
24382 	return( XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
24383     }
24384     /*
24385     * NOTE: xmlSplitQName2 will always return a duplicated
24386     * strings.
24387     */
24388     /* TODO: Export and use xmlSchemaStrip instead */
24389     stripped = xmlSchemaCollapseString(value);
24390     local = xmlSplitQName2(stripped ? stripped : value, &prefix);
24391     xmlFree(stripped);
24392     if (local == NULL)
24393 	local = xmlStrdup(value);
24394     /*
24395     * OPTIMIZE TODO: Use flags for:
24396     *  - is there any namespace binding?
24397     *  - is there a default namespace?
24398     */
24399     nsName = xmlSchemaLookupNamespace(vctxt, prefix);
24400 
24401     if (prefix != NULL) {
24402 	xmlFree(prefix);
24403 	/*
24404 	* A namespace must be found if the prefix is
24405 	* NOT NULL.
24406 	*/
24407 	if (nsName == NULL) {
24408 	    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24409 	    xmlSchemaCustomErr(ACTXT_CAST vctxt, ret, NULL,
24410 		WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24411 		"The QName value '%s' has no "
24412 		"corresponding namespace declaration in "
24413 		"scope", value, NULL);
24414 	    if (local != NULL)
24415 		xmlFree(local);
24416 	    return (ret);
24417 	}
24418     }
24419     if (valNeeded && val) {
24420 	if (nsName != NULL)
24421 	    *val = xmlSchemaNewQNameValue(
24422 		BAD_CAST xmlStrdup(nsName), BAD_CAST local);
24423 	else
24424 	    *val = xmlSchemaNewQNameValue(NULL,
24425 		BAD_CAST local);
24426     } else
24427 	xmlFree(local);
24428     return (0);
24429 }
24430 
24431 /*
24432 * cvc-simple-type
24433 */
24434 static int
xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,xmlNodePtr node,xmlSchemaTypePtr type,const xmlChar * value,xmlSchemaValPtr * retVal,int fireErrors,int normalize,int isNormalized)24435 xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
24436 			     xmlNodePtr node,
24437 			     xmlSchemaTypePtr type,
24438 			     const xmlChar *value,
24439 			     xmlSchemaValPtr *retVal,
24440 			     int fireErrors,
24441 			     int normalize,
24442 			     int isNormalized)
24443 {
24444     int ret = 0, valNeeded = (retVal) ? 1 : 0;
24445     xmlSchemaValPtr val = NULL;
24446     /* xmlSchemaWhitespaceValueType ws; */
24447     xmlChar *normValue = NULL;
24448 
24449 #define NORMALIZE(atype) \
24450     if ((! isNormalized) && \
24451     (normalize || (type->flags & XML_SCHEMAS_TYPE_NORMVALUENEEDED))) { \
24452 	normValue = xmlSchemaNormalizeValue(atype, value); \
24453 	if (normValue != NULL) \
24454 	    value = normValue; \
24455 	isNormalized = 1; \
24456     }
24457 
24458     if ((retVal != NULL) && (*retVal != NULL)) {
24459 	xmlSchemaFreeValue(*retVal);
24460 	*retVal = NULL;
24461     }
24462     /*
24463     * 3.14.4 Simple Type Definition Validation Rules
24464     * Validation Rule: String Valid
24465     */
24466     /*
24467     * 1 It is schema-valid with respect to that definition as defined
24468     * by Datatype Valid in [XML Schemas: Datatypes].
24469     */
24470     /*
24471     * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
24472     * the empty set, as defined in Type Derivation OK (Simple) ($3.14.6), then
24473     * the string must be a `declared entity name`.
24474     */
24475     /*
24476     * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
24477     * given the empty set, as defined in Type Derivation OK (Simple) ($3.14.6),
24478     * then every whitespace-delimited substring of the string must be a `declared
24479     * entity name`.
24480     */
24481     /*
24482     * 2.3 otherwise no further condition applies.
24483     */
24484     if ((! valNeeded) && (type->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
24485 	valNeeded = 1;
24486     if (value == NULL)
24487 	value = BAD_CAST "";
24488     if (WXS_IS_ANY_SIMPLE_TYPE(type) || WXS_IS_ATOMIC(type)) {
24489 	xmlSchemaTypePtr biType; /* The built-in type. */
24490 	/*
24491 	* SPEC (1.2.1) "if {variety} is `atomic` then the string must `match`
24492 	* a literal in the `lexical space` of {base type definition}"
24493 	*/
24494 	/*
24495 	* Whitespace-normalize.
24496 	*/
24497 	NORMALIZE(type);
24498 	if (type->type != XML_SCHEMA_TYPE_BASIC) {
24499 	    /*
24500 	    * Get the built-in type.
24501 	    */
24502 	    biType = type->baseType;
24503 	    while ((biType != NULL) &&
24504 		(biType->type != XML_SCHEMA_TYPE_BASIC))
24505 		biType = biType->baseType;
24506 
24507 	    if (biType == NULL) {
24508 		AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24509 		    "could not get the built-in type");
24510 		goto internal_error;
24511 	    }
24512 	} else
24513 	    biType = type;
24514 	/*
24515 	* NOTATIONs need to be processed here, since they need
24516 	* to lookup in the hashtable of NOTATION declarations of the schema.
24517 	*/
24518 	if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
24519 	    switch (biType->builtInType) {
24520 		case XML_SCHEMAS_NOTATION:
24521 		    ret = xmlSchemaValidateNotation(
24522 			(xmlSchemaValidCtxtPtr) actxt,
24523 			((xmlSchemaValidCtxtPtr) actxt)->schema,
24524 			NULL, value, &val, valNeeded);
24525 		    break;
24526 		case XML_SCHEMAS_QNAME:
24527 		    ret = xmlSchemaValidateQName((xmlSchemaValidCtxtPtr) actxt,
24528 			value, &val, valNeeded);
24529 		    break;
24530 		default:
24531 		    /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
24532 		    if (valNeeded)
24533 			ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24534 			    value, &val, node);
24535 		    else
24536 			ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24537 			    value, NULL, node);
24538 		    break;
24539 	    }
24540 	} else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
24541 	    switch (biType->builtInType) {
24542 		case XML_SCHEMAS_NOTATION:
24543 		    ret = xmlSchemaValidateNotation(NULL,
24544 			((xmlSchemaParserCtxtPtr) actxt)->schema, node,
24545 			value, &val, valNeeded);
24546 		    break;
24547 		default:
24548 		    /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
24549 		    if (valNeeded)
24550 			ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24551 			    value, &val, node);
24552 		    else
24553 			ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24554 			    value, NULL, node);
24555 		    break;
24556 	    }
24557 	} else {
24558 	    /*
24559 	    * Validation via a public API is not implemented yet.
24560 	    */
24561 	    goto internal_error;
24562 	}
24563 	if (ret != 0) {
24564 	    if (ret < 0) {
24565 		AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24566 		    "validating against a built-in type");
24567 		goto internal_error;
24568 	    }
24569 	    if (WXS_IS_LIST(type))
24570 		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24571 	    else
24572 		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24573 	}
24574 	if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24575 	    /*
24576 	    * Check facets.
24577 	    */
24578 	    ret = xmlSchemaValidateFacets(actxt, node, type,
24579 		(xmlSchemaValType) biType->builtInType, value, val,
24580 		0, fireErrors);
24581 	    if (ret != 0) {
24582 		if (ret < 0) {
24583 		    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24584 			"validating facets of atomic simple type");
24585 		    goto internal_error;
24586 		}
24587 		if (WXS_IS_LIST(type))
24588 		    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24589 		else
24590 		    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24591 	    }
24592 	}
24593 	else if (fireErrors && (ret > 0))
24594 	    xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24595     } else if (WXS_IS_LIST(type)) {
24596 
24597 	xmlSchemaTypePtr itemType;
24598 	const xmlChar *cur, *end;
24599 	xmlChar *tmpValue = NULL;
24600 	unsigned long len = 0;
24601 	xmlSchemaValPtr prevVal = NULL, curVal = NULL;
24602 	/* 1.2.2 if {variety} is `list` then the string must be a sequence
24603 	* of white space separated tokens, each of which `match`es a literal
24604 	* in the `lexical space` of {item type definition}
24605 	*/
24606 	/*
24607 	* Note that XML_SCHEMAS_TYPE_NORMVALUENEEDED will be set if
24608 	* the list type has an enum or pattern facet.
24609 	*/
24610 	NORMALIZE(type);
24611 	/*
24612 	* VAL TODO: Optimize validation of empty values.
24613 	* VAL TODO: We do not have computed values for lists.
24614 	*/
24615 	itemType = WXS_LIST_ITEMTYPE(type);
24616 	cur = value;
24617 	do {
24618 	    while (IS_BLANK_CH(*cur))
24619 		cur++;
24620 	    end = cur;
24621 	    while ((*end != 0) && (!(IS_BLANK_CH(*end))))
24622 		end++;
24623 	    if (end == cur)
24624 		break;
24625 	    tmpValue = xmlStrndup(cur, end - cur);
24626 	    len++;
24627 
24628 	    if (valNeeded)
24629 		ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24630 		    tmpValue, &curVal, fireErrors, 0, 1);
24631 	    else
24632 		ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24633 		    tmpValue, NULL, fireErrors, 0, 1);
24634 	    FREE_AND_NULL(tmpValue);
24635 	    if (curVal != NULL) {
24636 		/*
24637 		* Add to list of computed values.
24638 		*/
24639 		if (val == NULL)
24640 		    val = curVal;
24641 		else
24642 		    xmlSchemaValueAppend(prevVal, curVal);
24643 		prevVal = curVal;
24644 		curVal = NULL;
24645 	    }
24646 	    if (ret != 0) {
24647 		if (ret < 0) {
24648 		    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24649 			"validating an item of list simple type");
24650 		    goto internal_error;
24651 		}
24652 		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24653 		break;
24654 	    }
24655 	    cur = end;
24656 	} while (*cur != 0);
24657 	FREE_AND_NULL(tmpValue);
24658 	if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24659 	    /*
24660 	    * Apply facets (pattern, enumeration).
24661 	    */
24662 	    ret = xmlSchemaValidateFacets(actxt, node, type,
24663 		XML_SCHEMAS_UNKNOWN, value, val,
24664 		len, fireErrors);
24665 	    if (ret != 0) {
24666 		if (ret < 0) {
24667 		    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24668 			"validating facets of list simple type");
24669 		    goto internal_error;
24670 		}
24671 		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24672 	    }
24673 	}
24674 	if (fireErrors && (ret > 0)) {
24675 	    /*
24676 	    * Report the normalized value.
24677 	    */
24678 	    normalize = 1;
24679 	    NORMALIZE(type);
24680 	    xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24681 	}
24682     } else if (WXS_IS_UNION(type)) {
24683 	xmlSchemaTypeLinkPtr memberLink;
24684 	/*
24685 	* TODO: For all datatypes `derived` by `union`  whiteSpace does
24686 	* not apply directly; however, the normalization behavior of `union`
24687 	* types is controlled by the value of whiteSpace on that one of the
24688 	* `memberTypes` against which the `union` is successfully validated.
24689 	*
24690 	* This means that the value is normalized by the first validating
24691 	* member type, then the facets of the union type are applied. This
24692 	* needs changing of the value!
24693 	*/
24694 
24695 	/*
24696 	* 1.2.3 if {variety} is `union` then the string must `match` a
24697 	* literal in the `lexical space` of at least one member of
24698 	* {member type definitions}
24699 	*/
24700 	memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
24701 	if (memberLink == NULL) {
24702 	    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24703 		"union simple type has no member types");
24704 	    goto internal_error;
24705 	}
24706 	/*
24707 	* Always normalize union type values, since we currently
24708 	* cannot store the whitespace information with the value
24709 	* itself; otherwise a later value-comparison would be
24710 	* not possible.
24711 	*/
24712 	while (memberLink != NULL) {
24713 	    if (valNeeded)
24714 		ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24715 		    memberLink->type, value, &val, 0, 1, 0);
24716 	    else
24717 		ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24718 		    memberLink->type, value, NULL, 0, 1, 0);
24719 	    if (ret <= 0)
24720 		break;
24721 	    memberLink = memberLink->next;
24722 	}
24723 	if (ret != 0) {
24724 	    if (ret < 0) {
24725 		AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24726 		    "validating members of union simple type");
24727 		goto internal_error;
24728 	    }
24729 	    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
24730 	}
24731 	/*
24732 	* Apply facets (pattern, enumeration).
24733 	*/
24734 	if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24735 	    /*
24736 	    * The normalization behavior of `union` types is controlled by
24737 	    * the value of whiteSpace on that one of the `memberTypes`
24738 	    * against which the `union` is successfully validated.
24739 	    */
24740 	    NORMALIZE(memberLink->type);
24741 	    ret = xmlSchemaValidateFacets(actxt, node, type,
24742 		XML_SCHEMAS_UNKNOWN, value, val,
24743 		0, fireErrors);
24744 	    if (ret != 0) {
24745 		if (ret < 0) {
24746 		    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24747 			"validating facets of union simple type");
24748 		    goto internal_error;
24749 		}
24750 		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
24751 	    }
24752 	}
24753 	if (fireErrors && (ret > 0))
24754 	    xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24755     }
24756 
24757     if (normValue != NULL)
24758 	xmlFree(normValue);
24759     if (ret == 0) {
24760 	if (retVal != NULL)
24761 	    *retVal = val;
24762 	else if (val != NULL)
24763 	    xmlSchemaFreeValue(val);
24764     } else if (val != NULL)
24765 	xmlSchemaFreeValue(val);
24766     return (ret);
24767 internal_error:
24768     if (normValue != NULL)
24769 	xmlFree(normValue);
24770     if (val != NULL)
24771 	xmlSchemaFreeValue(val);
24772     return (-1);
24773 }
24774 
24775 static int
xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt,const xmlChar * value,const xmlChar ** nsName,const xmlChar ** localName)24776 xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt,
24777 			   const xmlChar *value,
24778 			   const xmlChar **nsName,
24779 			   const xmlChar **localName)
24780 {
24781     int ret = 0;
24782 
24783     if ((nsName == NULL) || (localName == NULL))
24784 	return (-1);
24785     *nsName = NULL;
24786     *localName = NULL;
24787 
24788     ret = xmlValidateQName(value, 1);
24789     if (ret == -1)
24790 	return (-1);
24791     if (ret > 0) {
24792 	xmlSchemaSimpleTypeErr(ACTXT_CAST vctxt,
24793 	    XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
24794 	    value, xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), 1);
24795 	return (1);
24796     }
24797     {
24798 	xmlChar *local = NULL;
24799 	xmlChar *prefix;
24800 
24801 	/*
24802 	* NOTE: xmlSplitQName2 will return a duplicated
24803 	* string.
24804 	*/
24805 	local = xmlSplitQName2(value, &prefix);
24806 	if (local == NULL)
24807 	    *localName = xmlDictLookup(vctxt->dict, value, -1);
24808 	else {
24809 	    *localName = xmlDictLookup(vctxt->dict, local, -1);
24810 	    xmlFree(local);
24811 	}
24812 
24813 	*nsName = xmlSchemaLookupNamespace(vctxt, prefix);
24814 
24815 	if (prefix != NULL) {
24816 	    xmlFree(prefix);
24817 	    /*
24818 	    * A namespace must be found if the prefix is NOT NULL.
24819 	    */
24820 	    if (*nsName == NULL) {
24821 		xmlSchemaCustomErr(ACTXT_CAST vctxt,
24822 		    XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
24823 		    WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24824 		    "The QName value '%s' has no "
24825 		    "corresponding namespace declaration in scope",
24826 		    value, NULL);
24827 		return (2);
24828 	    }
24829 	}
24830     }
24831     return (0);
24832 }
24833 
24834 static int
xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,xmlSchemaAttrInfoPtr iattr,xmlSchemaTypePtr * localType,xmlSchemaElementPtr elemDecl)24835 xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,
24836 			xmlSchemaAttrInfoPtr iattr,
24837 			xmlSchemaTypePtr *localType,
24838 			xmlSchemaElementPtr elemDecl)
24839 {
24840     int ret = 0;
24841     /*
24842     * cvc-elt (3.3.4) : (4)
24843     * AND
24844     * Schema-Validity Assessment (Element) (cvc-assess-elt)
24845     *   (1.2.1.2.1) - (1.2.1.2.4)
24846     * Handle 'xsi:type'.
24847     */
24848     if (localType == NULL)
24849 	return (-1);
24850     *localType = NULL;
24851     if (iattr == NULL)
24852 	return (0);
24853     else {
24854 	const xmlChar *nsName = NULL, *local = NULL;
24855 	/*
24856 	* TODO: We should report a *warning* that the type was overridden
24857 	* by the instance.
24858 	*/
24859 	ACTIVATE_ATTRIBUTE(iattr);
24860 	/*
24861 	* (cvc-elt) (3.3.4) : (4.1)
24862 	* (cvc-assess-elt) (1.2.1.2.2)
24863 	*/
24864 	ret = xmlSchemaVExpandQName(vctxt, iattr->value,
24865 	    &nsName, &local);
24866 	if (ret != 0) {
24867 	    if (ret < 0) {
24868 		VERROR_INT("xmlSchemaValidateElementByDeclaration",
24869 		    "calling xmlSchemaQNameExpand() to validate the "
24870 		    "attribute 'xsi:type'");
24871 		goto internal_error;
24872 	    }
24873 	    goto exit;
24874 	}
24875 	/*
24876 	* (cvc-elt) (3.3.4) : (4.2)
24877 	* (cvc-assess-elt) (1.2.1.2.3)
24878 	*/
24879 	*localType = xmlSchemaGetType(vctxt->schema, local, nsName);
24880 	if (*localType == NULL) {
24881 	    xmlChar *str = NULL;
24882 
24883 	    xmlSchemaCustomErr(ACTXT_CAST vctxt,
24884 		XML_SCHEMAV_CVC_ELT_4_2, NULL,
24885 		WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24886 		"The QName value '%s' of the xsi:type attribute does not "
24887 		"resolve to a type definition",
24888 		xmlSchemaFormatQName(&str, nsName, local), NULL);
24889 	    FREE_AND_NULL(str);
24890 	    ret = vctxt->err;
24891 	    goto exit;
24892 	}
24893 	if (elemDecl != NULL) {
24894 	    int set = 0;
24895 
24896 	    /*
24897 	    * SPEC cvc-elt (3.3.4) : (4.3) (Type Derivation OK)
24898 	    * "The `local type definition` must be validly
24899 	    * derived from the {type definition} given the union of
24900 	    * the {disallowed substitutions} and the {type definition}'s
24901 	    * {prohibited substitutions}, as defined in
24902 	    * Type Derivation OK (Complex) ($3.4.6)
24903 	    * (if it is a complex type definition),
24904 	    * or given {disallowed substitutions} as defined in Type
24905 	    * Derivation OK (Simple) ($3.14.6) (if it is a simple type
24906 	    * definition)."
24907 	    *
24908 	    * {disallowed substitutions}: the "block" on the element decl.
24909 	    * {prohibited substitutions}: the "block" on the type def.
24910 	    */
24911 	    /*
24912 	    * OPTIMIZE TODO: We could map types already evaluated
24913 	    * to be validly derived from other types to avoid checking
24914 	    * this over and over for the same types.
24915 	    */
24916 	    if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) ||
24917 		(elemDecl->subtypes->flags &
24918 		    XML_SCHEMAS_TYPE_BLOCK_EXTENSION))
24919 		set |= SUBSET_EXTENSION;
24920 
24921 	    if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) ||
24922 		(elemDecl->subtypes->flags &
24923 		    XML_SCHEMAS_TYPE_BLOCK_RESTRICTION))
24924 		set |= SUBSET_RESTRICTION;
24925 
24926 	    /*
24927 	    * REMOVED and CHANGED since this produced a parser context
24928 	    * which adds to the string dict of the schema. So this would
24929 	    * change the schema and we don't want this. We don't need
24930 	    * the parser context anymore.
24931 	    *
24932 	    * if ((vctxt->pctxt == NULL) &&
24933 	    *	(xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
24934 	    *	    return (-1);
24935 	    */
24936 
24937 	    if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST vctxt, *localType,
24938 		elemDecl->subtypes, set) != 0) {
24939 		xmlChar *str = NULL;
24940 
24941 		xmlSchemaCustomErr(ACTXT_CAST vctxt,
24942 		    XML_SCHEMAV_CVC_ELT_4_3, NULL, NULL,
24943 		    "The type definition '%s', specified by xsi:type, is "
24944 		    "blocked or not validly derived from the type definition "
24945 		    "of the element declaration",
24946 		    xmlSchemaFormatQName(&str,
24947 			(*localType)->targetNamespace,
24948 			(*localType)->name),
24949 		    NULL);
24950 		FREE_AND_NULL(str);
24951 		ret = vctxt->err;
24952 		*localType = NULL;
24953 	    }
24954 	}
24955     }
24956 exit:
24957     ACTIVATE_ELEM;
24958     return (ret);
24959 internal_error:
24960     ACTIVATE_ELEM;
24961     return (-1);
24962 }
24963 
24964 static int
xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt)24965 xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt)
24966 {
24967     xmlSchemaElementPtr elemDecl = vctxt->inode->decl;
24968     xmlSchemaTypePtr actualType;
24969 
24970     /*
24971     * cvc-elt (3.3.4) : 1
24972     */
24973     if (elemDecl == NULL) {
24974 	VERROR(XML_SCHEMAV_CVC_ELT_1, NULL,
24975 	    "No matching declaration available");
24976         return (vctxt->err);
24977     }
24978     actualType = WXS_ELEM_TYPEDEF(elemDecl);
24979     /*
24980     * cvc-elt (3.3.4) : 2
24981     */
24982     if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
24983 	VERROR(XML_SCHEMAV_CVC_ELT_2, NULL,
24984 	    "The element declaration is abstract");
24985         return (vctxt->err);
24986     }
24987     if (actualType == NULL) {
24988 	VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
24989 	    "The type definition is absent");
24990 	return (XML_SCHEMAV_CVC_TYPE_1);
24991     }
24992     if (vctxt->nbAttrInfos != 0) {
24993 	int ret;
24994 	xmlSchemaAttrInfoPtr iattr;
24995 	/*
24996 	* cvc-elt (3.3.4) : 3
24997 	* Handle 'xsi:nil'.
24998 	*/
24999 	iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25000 	    XML_SCHEMA_ATTR_INFO_META_XSI_NIL);
25001 	if (iattr) {
25002 	    ACTIVATE_ATTRIBUTE(iattr);
25003 	    /*
25004 	    * Validate the value.
25005 	    */
25006 	    ret = xmlSchemaVCheckCVCSimpleType(
25007 		ACTXT_CAST vctxt, NULL,
25008 		xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
25009 		iattr->value, &(iattr->val), 1, 0, 0);
25010 	    ACTIVATE_ELEM;
25011 	    if (ret < 0) {
25012 		VERROR_INT("xmlSchemaValidateElemDecl",
25013 		    "calling xmlSchemaVCheckCVCSimpleType() to "
25014 		    "validate the attribute 'xsi:nil'");
25015 		return (-1);
25016 	    }
25017 	    if (ret == 0) {
25018 		if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
25019 		    /*
25020 		    * cvc-elt (3.3.4) : 3.1
25021 		    */
25022 		    VERROR(XML_SCHEMAV_CVC_ELT_3_1, NULL,
25023 			"The element is not 'nillable'");
25024 		    /* Does not return an error on purpose. */
25025 		} else {
25026 		    if (xmlSchemaValueGetAsBoolean(iattr->val)) {
25027 			/*
25028 			* cvc-elt (3.3.4) : 3.2.2
25029 			*/
25030 			if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
25031 			    (elemDecl->value != NULL)) {
25032 			    VERROR(XML_SCHEMAV_CVC_ELT_3_2_2, NULL,
25033 				"The element cannot be 'nilled' because "
25034 				"there is a fixed value constraint defined "
25035 				"for it");
25036 			     /* Does not return an error on purpose. */
25037 			} else
25038 			    vctxt->inode->flags |=
25039 				XML_SCHEMA_ELEM_INFO_NILLED;
25040 		    }
25041 		}
25042 	    }
25043 	}
25044 	/*
25045 	* cvc-elt (3.3.4) : 4
25046 	* Handle 'xsi:type'.
25047 	*/
25048 	iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25049 	    XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
25050 	if (iattr) {
25051 	    xmlSchemaTypePtr localType = NULL;
25052 
25053 	    ret = xmlSchemaProcessXSIType(vctxt, iattr, &localType,
25054 		elemDecl);
25055 	    if (ret != 0) {
25056 		if (ret == -1) {
25057 		    VERROR_INT("xmlSchemaValidateElemDecl",
25058 			"calling xmlSchemaProcessXSIType() to "
25059 			"process the attribute 'xsi:type'");
25060 		    return (-1);
25061 		}
25062 		/* Does not return an error on purpose. */
25063 	    }
25064 	    if (localType != NULL) {
25065 		vctxt->inode->flags |= XML_SCHEMA_ELEM_INFO_LOCAL_TYPE;
25066 		actualType = localType;
25067 	    }
25068 	}
25069     }
25070     /*
25071     * IDC: Register identity-constraint XPath matchers.
25072     */
25073     if ((elemDecl->idcs != NULL) &&
25074 	(xmlSchemaIDCRegisterMatchers(vctxt, elemDecl) == -1))
25075 	    return (-1);
25076     /*
25077     * No actual type definition.
25078     */
25079     if (actualType == NULL) {
25080 	VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
25081 	    "The type definition is absent");
25082 	return (XML_SCHEMAV_CVC_TYPE_1);
25083     }
25084     /*
25085     * Remember the actual type definition.
25086     */
25087     vctxt->inode->typeDef = actualType;
25088 
25089     return (0);
25090 }
25091 
25092 static int
xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt)25093 xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt)
25094 {
25095     xmlSchemaAttrInfoPtr iattr;
25096     int ret = 0, i;
25097 
25098     /*
25099     * SPEC cvc-type (3.1.1)
25100     * "The attributes of must be empty, excepting those whose namespace
25101     * name is identical to http://www.w3.org/2001/XMLSchema-instance and
25102     * whose local name is one of type, nil, schemaLocation or
25103     * noNamespaceSchemaLocation."
25104     */
25105     if (vctxt->nbAttrInfos == 0)
25106 	return (0);
25107     for (i = 0; i < vctxt->nbAttrInfos; i++) {
25108 	iattr = vctxt->attrInfos[i];
25109 	if (! iattr->metaType) {
25110 	    ACTIVATE_ATTRIBUTE(iattr)
25111 	    xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25112 		XML_SCHEMAV_CVC_TYPE_3_1_1, iattr, NULL);
25113 	    ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
25114         }
25115     }
25116     ACTIVATE_ELEM
25117     return (ret);
25118 }
25119 
25120 /*
25121 * Cleanup currently used attribute infos.
25122 */
25123 static void
xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)25124 xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)
25125 {
25126     int i;
25127     xmlSchemaAttrInfoPtr attr;
25128 
25129     if (vctxt->nbAttrInfos == 0)
25130 	return;
25131     for (i = 0; i < vctxt->nbAttrInfos; i++) {
25132 	attr = vctxt->attrInfos[i];
25133 	if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
25134 	    if (attr->localName != NULL)
25135 		xmlFree((xmlChar *) attr->localName);
25136 	    if (attr->nsName != NULL)
25137 		xmlFree((xmlChar *) attr->nsName);
25138 	}
25139 	if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
25140 	    if (attr->value != NULL)
25141 		xmlFree((xmlChar *) attr->value);
25142 	}
25143 	if (attr->val != NULL) {
25144 	    xmlSchemaFreeValue(attr->val);
25145 	    attr->val = NULL;
25146 	}
25147 	memset(attr, 0, sizeof(xmlSchemaAttrInfo));
25148     }
25149     vctxt->nbAttrInfos = 0;
25150 }
25151 
25152 /*
25153 * 3.4.4 Complex Type Definition Validation Rules
25154 *   Element Locally Valid (Complex Type) (cvc-complex-type)
25155 * 3.2.4 Attribute Declaration Validation Rules
25156 *   Validation Rule: Attribute Locally Valid (cvc-attribute)
25157 *   Attribute Locally Valid (Use) (cvc-au)
25158 *
25159 * Only "assessed" attribute information items will be visible to
25160 * IDCs. I.e. not "lax" (without declaration) and "skip" wild attributes.
25161 */
25162 static int
xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)25163 xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)
25164 {
25165     xmlSchemaTypePtr type = vctxt->inode->typeDef;
25166     xmlSchemaItemListPtr attrUseList;
25167     xmlSchemaAttributeUsePtr attrUse = NULL;
25168     xmlSchemaAttributePtr attrDecl = NULL;
25169     xmlSchemaAttrInfoPtr iattr, tmpiattr;
25170     int i, j, found, nbAttrs, nbUses;
25171     int xpathRes = 0, res, wildIDs = 0, fixed;
25172     xmlNodePtr defAttrOwnerElem = NULL;
25173 
25174     /*
25175     * SPEC (cvc-attribute)
25176     * (1) "The declaration must not be `absent` (see Missing
25177     * Sub-components ($5.3) for how this can fail to be
25178     * the case)."
25179     * (2) "Its {type definition} must not be absent."
25180     *
25181     * NOTE (1) + (2): This is not handled here, since we currently do not
25182     * allow validation against schemas which have missing sub-components.
25183     *
25184     * SPEC (cvc-complex-type)
25185     * (3) "For each attribute information item in the element information
25186     * item's [attributes] excepting those whose [namespace name] is
25187     * identical to http://www.w3.org/2001/XMLSchema-instance and whose
25188     * [local name] is one of type, nil, schemaLocation or
25189     * noNamespaceSchemaLocation, the appropriate case among the following
25190     * must be true:
25191     *
25192     */
25193     attrUseList = (xmlSchemaItemListPtr) type->attrUses;
25194     /*
25195     * @nbAttrs is the number of attributes present in the instance.
25196     */
25197     nbAttrs = vctxt->nbAttrInfos;
25198     if (attrUseList != NULL)
25199 	nbUses = attrUseList->nbItems;
25200     else
25201 	nbUses = 0;
25202     for (i = 0; i < nbUses; i++) {
25203         found = 0;
25204 	attrUse = attrUseList->items[i];
25205 	attrDecl = WXS_ATTRUSE_DECL(attrUse);
25206         for (j = 0; j < nbAttrs; j++) {
25207 	    iattr = vctxt->attrInfos[j];
25208 	    /*
25209 	    * SPEC (cvc-complex-type) (3)
25210 	    * Skip meta attributes.
25211 	    */
25212 	    if (iattr->metaType)
25213 		continue;
25214 	    if (iattr->localName[0] != attrDecl->name[0])
25215 		continue;
25216 	    if (!xmlStrEqual(iattr->localName, attrDecl->name))
25217 		continue;
25218 	    if (!xmlStrEqual(iattr->nsName, attrDecl->targetNamespace))
25219 		continue;
25220 	    found = 1;
25221 	    /*
25222 	    * SPEC (cvc-complex-type)
25223 	    * (3.1) "If there is among the {attribute uses} an attribute
25224 	    * use with an {attribute declaration} whose {name} matches
25225 	    * the attribute information item's [local name] and whose
25226 	    * {target namespace} is identical to the attribute information
25227 	    * item's [namespace name] (where an `absent` {target namespace}
25228 	    * is taken to be identical to a [namespace name] with no value),
25229 	    * then the attribute information must be `valid` with respect
25230 	    * to that attribute use as per Attribute Locally Valid (Use)
25231 	    * ($3.5.4). In this case the {attribute declaration} of that
25232 	    * attribute use is the `context-determined declaration` for the
25233 	    * attribute information item with respect to Schema-Validity
25234 	    * Assessment (Attribute) ($3.2.4) and
25235 	    * Assessment Outcome (Attribute) ($3.2.5).
25236 	    */
25237 	    iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
25238 	    iattr->use = attrUse;
25239 	    /*
25240 	    * Context-determined declaration.
25241 	    */
25242 	    iattr->decl = attrDecl;
25243 	    iattr->typeDef = attrDecl->subtypes;
25244 	    break;
25245 	}
25246 
25247 	if (found)
25248 	    continue;
25249 
25250 	if (attrUse->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
25251 	    /*
25252 	    * Handle non-existent, required attributes.
25253 	    *
25254 	    * SPEC (cvc-complex-type)
25255 	    * (4) "The {attribute declaration} of each attribute use in
25256 	    * the {attribute uses} whose {required} is true matches one
25257 	    * of the attribute information items in the element information
25258 	    * item's [attributes] as per clause 3.1 above."
25259 	    */
25260 	    tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
25261 	    if (tmpiattr == NULL) {
25262 		VERROR_INT(
25263 		    "xmlSchemaVAttributesComplex",
25264 		    "calling xmlSchemaGetFreshAttrInfo()");
25265 		return (-1);
25266 	    }
25267 	    tmpiattr->state = XML_SCHEMAS_ATTR_ERR_MISSING;
25268 	    tmpiattr->use = attrUse;
25269 	    tmpiattr->decl = attrDecl;
25270 	} else if ((attrUse->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
25271 	    ((attrUse->defValue != NULL) ||
25272 	     (attrDecl->defValue != NULL))) {
25273 	    /*
25274 	    * Handle non-existent, optional, default/fixed attributes.
25275 	    */
25276 	    tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
25277 	    if (tmpiattr == NULL) {
25278 		VERROR_INT(
25279 		    "xmlSchemaVAttributesComplex",
25280 		    "calling xmlSchemaGetFreshAttrInfo()");
25281 		return (-1);
25282 	    }
25283 	    tmpiattr->state = XML_SCHEMAS_ATTR_DEFAULT;
25284 	    tmpiattr->use = attrUse;
25285 	    tmpiattr->decl = attrDecl;
25286 	    tmpiattr->typeDef = attrDecl->subtypes;
25287 	    tmpiattr->localName = attrDecl->name;
25288 	    tmpiattr->nsName = attrDecl->targetNamespace;
25289 	}
25290     }
25291 
25292     if (vctxt->nbAttrInfos == 0)
25293 	return (0);
25294     /*
25295     * Validate against the wildcard.
25296     */
25297     if (type->attributeWildcard != NULL) {
25298 	/*
25299 	* SPEC (cvc-complex-type)
25300 	* (3.2.1) "There must be an {attribute wildcard}."
25301 	*/
25302 	for (i = 0; i < nbAttrs; i++) {
25303 	    iattr = vctxt->attrInfos[i];
25304 	    /*
25305 	    * SPEC (cvc-complex-type) (3)
25306 	    * Skip meta attributes.
25307 	    */
25308 	    if (iattr->state != XML_SCHEMAS_ATTR_UNKNOWN)
25309 		continue;
25310 	    /*
25311 	    * SPEC (cvc-complex-type)
25312 	    * (3.2.2) "The attribute information item must be `valid` with
25313 	    * respect to it as defined in Item Valid (Wildcard) ($3.10.4)."
25314 	    *
25315 	    * SPEC Item Valid (Wildcard) (cvc-wildcard)
25316 	    * "... its [namespace name] must be `valid` with respect to
25317 	    * the wildcard constraint, as defined in Wildcard allows
25318 	    * Namespace Name ($3.10.4)."
25319 	    */
25320 	    if (xmlSchemaCheckCVCWildcardNamespace(type->attributeWildcard,
25321 		    iattr->nsName) == 0) {
25322 		/*
25323 		* Handle processContents.
25324 		*
25325 		* SPEC (cvc-wildcard):
25326 		* processContents | context-determined declaration:
25327 		* "strict"          "mustFind"
25328 		* "lax"             "none"
25329 		* "skip"            "skip"
25330 		*/
25331 		if (type->attributeWildcard->processContents ==
25332 		    XML_SCHEMAS_ANY_SKIP) {
25333 		     /*
25334 		    * context-determined declaration = "skip"
25335 		    *
25336 		    * SPEC PSVI Assessment Outcome (Attribute)
25337 		    * [validity] = "notKnown"
25338 		    * [validation attempted] = "none"
25339 		    */
25340 		    iattr->state = XML_SCHEMAS_ATTR_WILD_SKIP;
25341 		    continue;
25342 		}
25343 		/*
25344 		* Find an attribute declaration.
25345 		*/
25346 		iattr->decl = xmlSchemaGetAttributeDecl(vctxt->schema,
25347 		    iattr->localName, iattr->nsName);
25348 		if (iattr->decl != NULL) {
25349 		    iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
25350 		    /*
25351 		    * SPEC (cvc-complex-type)
25352 		    * (5) "Let [Definition:]  the wild IDs be the set of
25353 		    * all attribute information item to which clause 3.2
25354 		    * applied and whose `validation` resulted in a
25355 		    * `context-determined declaration` of mustFind or no
25356 		    * `context-determined declaration` at all, and whose
25357 		    * [local name] and [namespace name] resolve (as
25358 		    * defined by QName resolution (Instance) ($3.15.4)) to
25359 		    * an attribute declaration whose {type definition} is
25360 		    * or is derived from ID. Then all of the following
25361 		    * must be true:"
25362 		    */
25363 		    iattr->typeDef = WXS_ATTR_TYPEDEF(iattr->decl);
25364 		    if (xmlSchemaIsDerivedFromBuiltInType(
25365 			iattr->typeDef, XML_SCHEMAS_ID)) {
25366 			/*
25367 			* SPEC (5.1) "There must be no more than one
25368 			* item in `wild IDs`."
25369 			*/
25370 			if (wildIDs != 0) {
25371 			    /* VAL TODO */
25372 			    iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID;
25373 			    continue;
25374 			}
25375 			wildIDs++;
25376 			/*
25377 			* SPEC (cvc-complex-type)
25378 			* (5.2) "If `wild IDs` is non-empty, there must not
25379 			* be any attribute uses among the {attribute uses}
25380 			* whose {attribute declaration}'s {type definition}
25381 			* is or is derived from ID."
25382 			*/
25383                         if (attrUseList != NULL) {
25384                             for (j = 0; j < attrUseList->nbItems; j++) {
25385                                 if (xmlSchemaIsDerivedFromBuiltInType(
25386                                     WXS_ATTRUSE_TYPEDEF(attrUseList->items[j]),
25387                                     XML_SCHEMAS_ID)) {
25388                                     /* URGENT VAL TODO: implement */
25389                             iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID;
25390                                     break;
25391                                 }
25392                             }
25393                         }
25394 		    }
25395 		} else if (type->attributeWildcard->processContents ==
25396 		    XML_SCHEMAS_ANY_LAX) {
25397 		    iattr->state = XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL;
25398 		    /*
25399 		    * SPEC PSVI Assessment Outcome (Attribute)
25400 		    * [validity] = "notKnown"
25401 		    * [validation attempted] = "none"
25402 		    */
25403 		} else {
25404 		    iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL;
25405 		}
25406 	    }
25407 	}
25408     }
25409 
25410     if (vctxt->nbAttrInfos == 0)
25411 	return (0);
25412 
25413     /*
25414     * Get the owner element; needed for creation of default attributes.
25415     * This fixes bug #341337, reported by David Grohmann.
25416     */
25417     if (vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
25418 	xmlSchemaNodeInfoPtr ielem = vctxt->elemInfos[vctxt->depth];
25419 	if (ielem && ielem->node && ielem->node->doc)
25420 	    defAttrOwnerElem = ielem->node;
25421     }
25422     /*
25423     * Validate values, create default attributes, evaluate IDCs.
25424     */
25425     for (i = 0; i < vctxt->nbAttrInfos; i++) {
25426 	iattr = vctxt->attrInfos[i];
25427 	/*
25428 	* VAL TODO: Note that we won't try to resolve IDCs to
25429 	* "lax" and "skip" validated attributes. Check what to
25430 	* do in this case.
25431 	*/
25432 	if ((iattr->state != XML_SCHEMAS_ATTR_ASSESSED) &&
25433 	    (iattr->state != XML_SCHEMAS_ATTR_DEFAULT))
25434 	    continue;
25435 	/*
25436 	* VAL TODO: What to do if the type definition is missing?
25437 	*/
25438 	if (iattr->typeDef == NULL) {
25439 	    iattr->state = XML_SCHEMAS_ATTR_ERR_NO_TYPE;
25440 	    continue;
25441 	}
25442 
25443 	ACTIVATE_ATTRIBUTE(iattr);
25444 	fixed = 0;
25445 	xpathRes = 0;
25446 
25447 	if (vctxt->xpathStates != NULL) {
25448 	    /*
25449 	    * Evaluate IDCs.
25450 	    */
25451 	    xpathRes = xmlSchemaXPathEvaluate(vctxt,
25452 		XML_ATTRIBUTE_NODE);
25453 	    if (xpathRes == -1) {
25454 		VERROR_INT("xmlSchemaVAttributesComplex",
25455 		    "calling xmlSchemaXPathEvaluate()");
25456 		goto internal_error;
25457 	    }
25458 	}
25459 
25460 	if (iattr->state == XML_SCHEMAS_ATTR_DEFAULT) {
25461 	    /*
25462 	    * Default/fixed attributes.
25463 	    * We need the value only if we need to resolve IDCs or
25464 	    * will create default attributes.
25465 	    */
25466 	    if ((xpathRes) || (defAttrOwnerElem)) {
25467 		if (iattr->use->defValue != NULL) {
25468 		    iattr->value = (xmlChar *) iattr->use->defValue;
25469 		    iattr->val = iattr->use->defVal;
25470 		} else {
25471 		    iattr->value = (xmlChar *) iattr->decl->defValue;
25472 		    iattr->val = iattr->decl->defVal;
25473 		}
25474 		/*
25475 		* IDCs will consume the precomputed default value,
25476 		* so we need to clone it.
25477 		*/
25478 		if (iattr->val == NULL) {
25479 		    VERROR_INT("xmlSchemaVAttributesComplex",
25480 			"default/fixed value on an attribute use was "
25481 			"not precomputed");
25482 		    goto internal_error;
25483 		}
25484 		iattr->val = xmlSchemaCopyValue(iattr->val);
25485 		if (iattr->val == NULL) {
25486 		    VERROR_INT("xmlSchemaVAttributesComplex",
25487 			"calling xmlSchemaCopyValue()");
25488 		    goto internal_error;
25489 		}
25490 	    }
25491 	    /*
25492 	    * PSVI: Add the default attribute to the current element.
25493 	    * VAL TODO: Should we use the *normalized* value? This currently
25494 	    *   uses the *initial* value.
25495 	    */
25496 
25497 	    if (defAttrOwnerElem) {
25498 		xmlChar *normValue;
25499 		const xmlChar *value;
25500 
25501 		value = iattr->value;
25502 		/*
25503 		* Normalize the value.
25504 		*/
25505 		normValue = xmlSchemaNormalizeValue(iattr->typeDef,
25506 		    iattr->value);
25507 		if (normValue != NULL)
25508 		    value = BAD_CAST normValue;
25509 
25510 		if (iattr->nsName == NULL) {
25511 		    if (xmlNewProp(defAttrOwnerElem,
25512 			iattr->localName, value) == NULL) {
25513 			VERROR_INT("xmlSchemaVAttributesComplex",
25514 			    "calling xmlNewProp()");
25515 			if (normValue != NULL)
25516 			    xmlFree(normValue);
25517 			goto internal_error;
25518 		    }
25519 		} else {
25520 		    xmlNsPtr ns;
25521 
25522 		    ns = xmlSearchNsByHref(defAttrOwnerElem->doc,
25523 			defAttrOwnerElem, iattr->nsName);
25524 		    if (ns == NULL) {
25525 			xmlChar prefix[13];
25526 			int counter = 0;
25527 
25528 			/*
25529 			* Create a namespace declaration on the validation
25530 			* root node if no namespace declaration is in scope.
25531 			*/
25532 			do {
25533 			    snprintf((char *) prefix, 13, "p%d", counter++);
25534 			    ns = xmlSearchNs(defAttrOwnerElem->doc,
25535 				defAttrOwnerElem, BAD_CAST prefix);
25536 			    if (counter > 1000) {
25537 				VERROR_INT(
25538 				    "xmlSchemaVAttributesComplex",
25539 				    "could not compute a ns prefix for a "
25540 				    "default/fixed attribute");
25541 				if (normValue != NULL)
25542 				    xmlFree(normValue);
25543 				goto internal_error;
25544 			    }
25545 			} while (ns != NULL);
25546 			ns = xmlNewNs(vctxt->validationRoot,
25547 			    iattr->nsName, BAD_CAST prefix);
25548 		    }
25549 		    /*
25550 		    * TODO:
25551 		    * http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0406.html
25552 		    * If we have QNames: do we need to ensure there's a
25553 		    * prefix defined for the QName?
25554 		    */
25555 		    xmlNewNsProp(defAttrOwnerElem, ns, iattr->localName, value);
25556 		}
25557 		if (normValue != NULL)
25558 		    xmlFree(normValue);
25559 	    }
25560 	    /*
25561 	    * Go directly to IDC evaluation.
25562 	    */
25563 	    goto eval_idcs;
25564 	}
25565 	/*
25566 	* Validate the value.
25567 	*/
25568 	if (vctxt->value != NULL) {
25569 	    /*
25570 	    * Free last computed value; just for safety reasons.
25571 	    */
25572 	    xmlSchemaFreeValue(vctxt->value);
25573 	    vctxt->value = NULL;
25574 	}
25575 	/*
25576 	* Note that the attribute *use* can be unavailable, if
25577 	* the attribute was a wild attribute.
25578 	*/
25579 	if ((iattr->decl->flags & XML_SCHEMAS_ATTR_FIXED) ||
25580 	    ((iattr->use != NULL) &&
25581 	     (iattr->use->flags & XML_SCHEMAS_ATTR_FIXED)))
25582 	    fixed = 1;
25583 	else
25584 	    fixed = 0;
25585 	/*
25586 	* SPEC (cvc-attribute)
25587 	* (3) "The item's `normalized value` must be locally `valid`
25588 	* with respect to that {type definition} as per
25589 	* String Valid ($3.14.4)."
25590 	*
25591 	* VAL TODO: Do we already have the
25592 	* "normalized attribute value" here?
25593 	*/
25594 	if (xpathRes || fixed) {
25595 	    iattr->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
25596 	    /*
25597 	    * Request a computed value.
25598 	    */
25599 	    res = xmlSchemaVCheckCVCSimpleType(
25600 		ACTXT_CAST vctxt,
25601 		iattr->node, iattr->typeDef, iattr->value, &(iattr->val),
25602 		1, 1, 0);
25603 	} else {
25604 	    res = xmlSchemaVCheckCVCSimpleType(
25605 		ACTXT_CAST vctxt,
25606 		iattr->node, iattr->typeDef, iattr->value, NULL,
25607 		1, 0, 0);
25608 	}
25609 
25610 	if (res != 0) {
25611 	    if (res == -1) {
25612 		VERROR_INT("xmlSchemaVAttributesComplex",
25613 		    "calling xmlSchemaStreamValidateSimpleTypeValue()");
25614 		goto internal_error;
25615 	    }
25616 	    iattr->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
25617 	    /*
25618 	    * SPEC PSVI Assessment Outcome (Attribute)
25619 	    * [validity] = "invalid"
25620 	    */
25621 	    goto eval_idcs;
25622 	}
25623 
25624 	if (fixed) {
25625 	    /*
25626 	    * SPEC Attribute Locally Valid (Use) (cvc-au)
25627 	    * "For an attribute information item to be `valid`
25628 	    * with respect to an attribute use its *normalized*
25629 	    * value must match the *canonical* lexical
25630 	    * representation of the attribute use's {value
25631 	    * constraint}value, if it is present and fixed."
25632 	    *
25633 	    * VAL TODO: The requirement for the *canonical* value
25634 	    * will be removed in XML Schema 1.1.
25635 	    */
25636 	    /*
25637 	    * SPEC Attribute Locally Valid (cvc-attribute)
25638 	    * (4) "The item's *actual* value must match the *value* of
25639 	    * the {value constraint}, if it is present and fixed."
25640 	    */
25641 	    if (iattr->val == NULL) {
25642 		/* VAL TODO: A value was not precomputed. */
25643 		goto eval_idcs;
25644 	    }
25645 	    if ((iattr->use != NULL) &&
25646 		(iattr->use->defValue != NULL)) {
25647 		if (iattr->use->defVal == NULL) {
25648 		    /* VAL TODO: A default value was not precomputed. */
25649 		    goto eval_idcs;
25650 		}
25651 		iattr->vcValue = iattr->use->defValue;
25652 		/*
25653 		if (xmlSchemaCompareValuesWhtsp(attr->val,
25654 		    (xmlSchemaWhitespaceValueType) ws,
25655 		    attr->use->defVal,
25656 		    (xmlSchemaWhitespaceValueType) ws) != 0) {
25657 		*/
25658 		if (! xmlSchemaAreValuesEqual(iattr->val, iattr->use->defVal))
25659 		    iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
25660 	    } else {
25661 		if (iattr->decl->defVal == NULL) {
25662 		    /* VAL TODO: A default value was not precomputed. */
25663 		    goto eval_idcs;
25664 		}
25665 		iattr->vcValue = iattr->decl->defValue;
25666 		/*
25667 		if (xmlSchemaCompareValuesWhtsp(attr->val,
25668 		    (xmlSchemaWhitespaceValueType) ws,
25669 		    attrDecl->defVal,
25670 		    (xmlSchemaWhitespaceValueType) ws) != 0) {
25671 		*/
25672 		if (! xmlSchemaAreValuesEqual(iattr->val, iattr->decl->defVal))
25673 		    iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
25674 	    }
25675 	    /*
25676 	    * [validity] = "valid"
25677 	    */
25678 	}
25679 eval_idcs:
25680 	/*
25681 	* Evaluate IDCs.
25682 	*/
25683 	if (xpathRes) {
25684 	    if (xmlSchemaXPathProcessHistory(vctxt,
25685 		vctxt->depth +1) == -1) {
25686 		VERROR_INT("xmlSchemaVAttributesComplex",
25687 		    "calling xmlSchemaXPathEvaluate()");
25688 		goto internal_error;
25689 	    }
25690 	} else if (vctxt->xpathStates != NULL)
25691 	    xmlSchemaXPathPop(vctxt);
25692     }
25693 
25694     /*
25695     * Report errors.
25696     */
25697     for (i = 0; i < vctxt->nbAttrInfos; i++) {
25698 	iattr = vctxt->attrInfos[i];
25699 	if ((iattr->state == XML_SCHEMAS_ATTR_META) ||
25700 	    (iattr->state == XML_SCHEMAS_ATTR_ASSESSED) ||
25701 	    (iattr->state == XML_SCHEMAS_ATTR_WILD_SKIP) ||
25702 	    (iattr->state == XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL))
25703 	    continue;
25704 	ACTIVATE_ATTRIBUTE(iattr);
25705 	switch (iattr->state) {
25706 	    case XML_SCHEMAS_ATTR_ERR_MISSING: {
25707 		    xmlChar *str = NULL;
25708 		    ACTIVATE_ELEM;
25709 		    xmlSchemaCustomErr(ACTXT_CAST vctxt,
25710 			XML_SCHEMAV_CVC_COMPLEX_TYPE_4, NULL, NULL,
25711 			"The attribute '%s' is required but missing",
25712 			xmlSchemaFormatQName(&str,
25713 			    iattr->decl->targetNamespace,
25714 			    iattr->decl->name),
25715 			NULL);
25716 		    FREE_AND_NULL(str)
25717 		    break;
25718 		}
25719 	    case XML_SCHEMAS_ATTR_ERR_NO_TYPE:
25720 		VERROR(XML_SCHEMAV_CVC_ATTRIBUTE_2, NULL,
25721 		    "The type definition is absent");
25722 		break;
25723 	    case XML_SCHEMAS_ATTR_ERR_FIXED_VALUE:
25724 		xmlSchemaCustomErr(ACTXT_CAST vctxt,
25725 		    XML_SCHEMAV_CVC_AU, NULL, NULL,
25726 		    "The value '%s' does not match the fixed "
25727 		    "value constraint '%s'",
25728 		    iattr->value, iattr->vcValue);
25729 		break;
25730 	    case XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL:
25731 		VERROR(XML_SCHEMAV_CVC_WILDCARD, NULL,
25732 		    "No matching global attribute declaration available, but "
25733 		    "demanded by the strict wildcard");
25734 		break;
25735 	    case XML_SCHEMAS_ATTR_UNKNOWN:
25736 		if (iattr->metaType)
25737 		    break;
25738 		/*
25739 		* MAYBE VAL TODO: One might report different error messages
25740 		* for the following errors.
25741 		*/
25742 		if (type->attributeWildcard == NULL) {
25743 		    xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25744 			XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, iattr, NULL);
25745 		} else {
25746 		    xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25747 			XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, iattr, NULL);
25748 		}
25749 		break;
25750 	    default:
25751 		break;
25752 	}
25753     }
25754 
25755     ACTIVATE_ELEM;
25756     return (0);
25757 internal_error:
25758     ACTIVATE_ELEM;
25759     return (-1);
25760 }
25761 
25762 static int
xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt,int * skip)25763 xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt,
25764 			      int *skip)
25765 {
25766     xmlSchemaWildcardPtr wild = (xmlSchemaWildcardPtr) vctxt->inode->decl;
25767     /*
25768     * The namespace of the element was already identified to be
25769     * matching the wildcard.
25770     */
25771     if ((skip == NULL) || (wild == NULL) ||
25772 	(wild->type != XML_SCHEMA_TYPE_ANY)) {
25773 	VERROR_INT("xmlSchemaValidateElemWildcard",
25774 	    "bad arguments");
25775 	return (-1);
25776     }
25777     *skip = 0;
25778     if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
25779 	/*
25780 	* URGENT VAL TODO: Either we need to position the stream to the
25781 	* next sibling, or walk the whole subtree.
25782 	*/
25783 	*skip = 1;
25784 	return (0);
25785     }
25786     {
25787 	xmlSchemaElementPtr decl = NULL;
25788 
25789 	decl = xmlSchemaGetElem(vctxt->schema,
25790 	    vctxt->inode->localName, vctxt->inode->nsName);
25791 	if (decl != NULL) {
25792 	    vctxt->inode->decl = decl;
25793 	    return (0);
25794 	}
25795     }
25796     if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
25797 	/* VAL TODO: Change to proper error code. */
25798 	VERROR(XML_SCHEMAV_CVC_ELT_1, NULL, /* WXS_BASIC_CAST wild */
25799 	    "No matching global element declaration available, but "
25800 	    "demanded by the strict wildcard");
25801 	return (vctxt->err);
25802     }
25803     if (vctxt->nbAttrInfos != 0) {
25804 	xmlSchemaAttrInfoPtr iattr;
25805 	/*
25806 	* SPEC Validation Rule: Schema-Validity Assessment (Element)
25807 	* (1.2.1.2.1) - (1.2.1.2.3 )
25808 	*
25809 	* Use the xsi:type attribute for the type definition.
25810 	*/
25811 	iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25812 	    XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
25813 	if (iattr != NULL) {
25814 	    if (xmlSchemaProcessXSIType(vctxt, iattr,
25815 		&(vctxt->inode->typeDef), NULL) == -1) {
25816 		VERROR_INT("xmlSchemaValidateElemWildcard",
25817 		    "calling xmlSchemaProcessXSIType() to "
25818 		    "process the attribute 'xsi:nil'");
25819 		return (-1);
25820 	    }
25821 	    /*
25822 	    * Don't return an error on purpose.
25823 	    */
25824 	    return (0);
25825 	}
25826     }
25827     /*
25828     * SPEC Validation Rule: Schema-Validity Assessment (Element)
25829     *
25830     * Fallback to "anyType".
25831     */
25832     vctxt->inode->typeDef =
25833 	xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
25834     return (0);
25835 }
25836 
25837 /*
25838 * xmlSchemaCheckCOSValidDefault:
25839 *
25840 * This will be called if: not nilled, no content and a default/fixed
25841 * value is provided.
25842 */
25843 
25844 static int
xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt,const xmlChar * value,xmlSchemaValPtr * val)25845 xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt,
25846 			      const xmlChar *value,
25847 			      xmlSchemaValPtr *val)
25848 {
25849     int ret = 0;
25850     xmlSchemaNodeInfoPtr inode = vctxt->inode;
25851 
25852     /*
25853     * cos-valid-default:
25854     * Schema Component Constraint: Element Default Valid (Immediate)
25855     * For a string to be a valid default with respect to a type
25856     * definition the appropriate case among the following must be true:
25857     */
25858     if WXS_IS_COMPLEX(inode->typeDef) {
25859 	/*
25860 	* Complex type.
25861 	*
25862 	* SPEC (2.1) "its {content type} must be a simple type definition
25863 	* or mixed."
25864 	* SPEC (2.2.2) "If the {content type} is mixed, then the {content
25865 	* type}'s particle must be `emptiable` as defined by
25866 	* Particle Emptiable ($3.9.6)."
25867 	*/
25868 	if ((! WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) &&
25869 	    ((! WXS_HAS_MIXED_CONTENT(inode->typeDef)) ||
25870 	     (! WXS_EMPTIABLE(inode->typeDef)))) {
25871 	    ret = XML_SCHEMAP_COS_VALID_DEFAULT_2_1;
25872 	    /* NOTE that this covers (2.2.2) as well. */
25873 	    VERROR(ret, NULL,
25874 		"For a string to be a valid default, the type definition "
25875 		"must be a simple type or a complex type with simple content "
25876 		"or mixed content and a particle emptiable");
25877 	    return(ret);
25878 	}
25879     }
25880     /*
25881     * 1 If the type definition is a simple type definition, then the string
25882     * must be `valid` with respect to that definition as defined by String
25883     * Valid ($3.14.4).
25884     *
25885     * AND
25886     *
25887     * 2.2.1 If the {content type} is a simple type definition, then the
25888     * string must be `valid` with respect to that simple type definition
25889     * as defined by String Valid ($3.14.4).
25890     */
25891     if (WXS_IS_SIMPLE(inode->typeDef)) {
25892 
25893 	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
25894 	    NULL, inode->typeDef, value, val, 1, 1, 0);
25895 
25896     } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
25897 
25898 	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
25899 	    NULL, inode->typeDef->contentTypeDef, value, val, 1, 1, 0);
25900     }
25901     if (ret < 0) {
25902 	VERROR_INT("xmlSchemaCheckCOSValidDefault",
25903 	    "calling xmlSchemaVCheckCVCSimpleType()");
25904     }
25905     return (ret);
25906 }
25907 
25908 static void
xmlSchemaVContentModelCallback(xmlRegExecCtxtPtr exec ATTRIBUTE_UNUSED,const xmlChar * name ATTRIBUTE_UNUSED,void * transdata,void * inputdata)25909 xmlSchemaVContentModelCallback(xmlRegExecCtxtPtr exec ATTRIBUTE_UNUSED,
25910 			       const xmlChar * name ATTRIBUTE_UNUSED,
25911 			       void *transdata, void *inputdata)
25912 {
25913     xmlSchemaElementPtr item = (xmlSchemaElementPtr) transdata;
25914     xmlSchemaNodeInfoPtr inode = (xmlSchemaNodeInfoPtr) inputdata;
25915     inode->decl = item;
25916 }
25917 
25918 static int
xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt)25919 xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt)
25920 {
25921     vctxt->inode = xmlSchemaGetFreshElemInfo(vctxt);
25922     if (vctxt->inode == NULL) {
25923 	VERROR_INT("xmlSchemaValidatorPushElem",
25924 	    "calling xmlSchemaGetFreshElemInfo()");
25925 	return (-1);
25926     }
25927     vctxt->nbAttrInfos = 0;
25928     return (0);
25929 }
25930 
25931 static int
xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt,xmlSchemaNodeInfoPtr inode,xmlSchemaTypePtr type,const xmlChar * value)25932 xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt,
25933 			     xmlSchemaNodeInfoPtr inode,
25934 			     xmlSchemaTypePtr type,
25935 			     const xmlChar *value)
25936 {
25937     if (inode->flags & XML_SCHEMA_NODE_INFO_VALUE_NEEDED)
25938 	return (xmlSchemaVCheckCVCSimpleType(
25939 	    ACTXT_CAST vctxt, NULL,
25940 	    type, value, &(inode->val), 1, 1, 0));
25941     else
25942 	return (xmlSchemaVCheckCVCSimpleType(
25943 	    ACTXT_CAST vctxt, NULL,
25944 	    type, value, NULL, 1, 0, 0));
25945 }
25946 
25947 
25948 
25949 /*
25950 * Process END of element.
25951 */
25952 static int
xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)25953 xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)
25954 {
25955     int ret = 0;
25956     xmlSchemaNodeInfoPtr inode = vctxt->inode;
25957 
25958     if (vctxt->nbAttrInfos != 0)
25959 	xmlSchemaClearAttrInfos(vctxt);
25960     if (inode->flags & XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED) {
25961 	/*
25962 	* This element was not expected;
25963 	* we will not validate child elements of broken parents.
25964 	* Skip validation of all content of the parent.
25965 	*/
25966 	vctxt->skipDepth = vctxt->depth -1;
25967 	goto end_elem;
25968     }
25969     if ((inode->typeDef == NULL) ||
25970 	(inode->flags & XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE)) {
25971 	/*
25972 	* 1. the type definition might be missing if the element was
25973 	*    error prone
25974 	* 2. it might be abstract.
25975 	*/
25976 	goto end_elem;
25977     }
25978     /*
25979     * Check the content model.
25980     */
25981     if ((inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) ||
25982 	(inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)) {
25983 
25984 	/*
25985 	* Workaround for "anyType".
25986 	*/
25987 	if (inode->typeDef->builtInType == XML_SCHEMAS_ANYTYPE)
25988 	    goto character_content;
25989 
25990 	if ((inode->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0) {
25991 	    xmlChar *values[10];
25992 	    int terminal, nbval = 10, nbneg;
25993 
25994 	    if (inode->regexCtxt == NULL) {
25995 		/*
25996 		* Create the regex context.
25997 		*/
25998 		inode->regexCtxt =
25999 		    xmlRegNewExecCtxt(inode->typeDef->contModel,
26000 		    xmlSchemaVContentModelCallback, vctxt);
26001 		if (inode->regexCtxt == NULL) {
26002 		    VERROR_INT("xmlSchemaValidatorPopElem",
26003 			"failed to create a regex context");
26004 		    goto internal_error;
26005 		}
26006 	    }
26007 
26008 	    /*
26009 	     * Do not check further content if the node has been nilled
26010 	     */
26011 	    if (INODE_NILLED(inode)) {
26012 		ret = 0;
26013                 goto skip_nilled;
26014 	    }
26015 
26016 	    /*
26017 	    * Get hold of the still expected content, since a further
26018 	    * call to xmlRegExecPushString() will lose this information.
26019 	    */
26020 	    xmlRegExecNextValues(inode->regexCtxt,
26021 		&nbval, &nbneg, &values[0], &terminal);
26022 	    ret = xmlRegExecPushString(inode->regexCtxt, NULL, NULL);
26023 	    if ((ret<0) || ((ret==0) && (!INODE_NILLED(inode)))) {
26024 		/*
26025 		* Still missing something.
26026 		*/
26027 		ret = 1;
26028 		inode->flags |=
26029 		    XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
26030 		xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
26031 		    XML_SCHEMAV_ELEMENT_CONTENT, NULL, NULL,
26032 		    "Missing child element(s)",
26033 		    nbval, nbneg, values);
26034 	    } else {
26035 		/*
26036 		* Content model is satisfied.
26037 		*/
26038 		ret = 0;
26039 	    }
26040 
26041 	}
26042     }
26043 
26044 skip_nilled:
26045 
26046     if (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)
26047 	goto end_elem;
26048 
26049 character_content:
26050 
26051     if (vctxt->value != NULL) {
26052 	xmlSchemaFreeValue(vctxt->value);
26053 	vctxt->value = NULL;
26054     }
26055     /*
26056     * Check character content.
26057     */
26058     if (inode->decl == NULL) {
26059 	/*
26060 	* Speedup if no declaration exists.
26061 	*/
26062 	if (WXS_IS_SIMPLE(inode->typeDef)) {
26063 	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26064 		inode, inode->typeDef, inode->value);
26065 	} else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26066 	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26067 		inode, inode->typeDef->contentTypeDef,
26068 		inode->value);
26069 	}
26070 	if (ret < 0) {
26071 	    VERROR_INT("xmlSchemaValidatorPopElem",
26072 		"calling xmlSchemaVCheckCVCSimpleType()");
26073 	    goto internal_error;
26074 	}
26075 	goto end_elem;
26076     }
26077     /*
26078     * cvc-elt (3.3.4) : 5
26079     * The appropriate case among the following must be true:
26080     */
26081     /*
26082     * cvc-elt (3.3.4) : 5.1
26083     * If the declaration has a {value constraint},
26084     * the item has neither element nor character [children] and
26085     * clause 3.2 has not applied, then all of the following must be true:
26086     */
26087     if ((inode->decl->value != NULL) &&
26088 	(inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) &&
26089 	(! INODE_NILLED(inode))) {
26090 	/*
26091 	* cvc-elt (3.3.4) : 5.1.1
26092 	* If the `actual type definition` is a `local type definition`
26093 	* then the canonical lexical representation of the {value constraint}
26094 	* value must be a valid default for the `actual type definition` as
26095 	* defined in Element Default Valid (Immediate) ($3.3.6).
26096 	*/
26097 	/*
26098 	* NOTE: 'local' above means types acquired by xsi:type.
26099 	* NOTE: Although the *canonical* value is stated, it is not
26100 	* relevant if canonical or not. Additionally XML Schema 1.1
26101 	* will removed this requirement as well.
26102 	*/
26103 	if (inode->flags & XML_SCHEMA_ELEM_INFO_LOCAL_TYPE) {
26104 
26105 	    ret = xmlSchemaCheckCOSValidDefault(vctxt,
26106 		inode->decl->value, &(inode->val));
26107 	    if (ret != 0) {
26108 		if (ret < 0) {
26109 		    VERROR_INT("xmlSchemaValidatorPopElem",
26110 			"calling xmlSchemaCheckCOSValidDefault()");
26111 		    goto internal_error;
26112 		}
26113 		goto end_elem;
26114 	    }
26115 	    /*
26116 	    * Stop here, to avoid redundant validation of the value
26117 	    * (see following).
26118 	    */
26119 	    goto default_psvi;
26120 	}
26121 	/*
26122 	* cvc-elt (3.3.4) : 5.1.2
26123 	* The element information item with the canonical lexical
26124 	* representation of the {value constraint} value used as its
26125 	* `normalized value` must be `valid` with respect to the
26126 	* `actual type definition` as defined by Element Locally Valid (Type)
26127 	* ($3.3.4).
26128 	*/
26129 	if (WXS_IS_SIMPLE(inode->typeDef)) {
26130 	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26131 		inode, inode->typeDef, inode->decl->value);
26132 	} else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26133 	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26134 		inode, inode->typeDef->contentTypeDef,
26135 		inode->decl->value);
26136 	}
26137 	if (ret != 0) {
26138 	    if (ret < 0) {
26139 		VERROR_INT("xmlSchemaValidatorPopElem",
26140 		    "calling xmlSchemaVCheckCVCSimpleType()");
26141 		goto internal_error;
26142 	    }
26143 	    goto end_elem;
26144 	}
26145 
26146 default_psvi:
26147 	/*
26148 	* PSVI: Create a text node on the instance element.
26149 	*/
26150 	if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
26151 	    (inode->node != NULL)) {
26152 	    xmlNodePtr textChild;
26153 	    xmlChar *normValue;
26154 	    /*
26155 	    * VAL TODO: Normalize the value.
26156 	    */
26157 	    normValue = xmlSchemaNormalizeValue(inode->typeDef,
26158 		inode->decl->value);
26159 	    if (normValue != NULL) {
26160 		textChild = xmlNewDocText(inode->node->doc,
26161                         BAD_CAST normValue);
26162 		xmlFree(normValue);
26163 	    } else
26164 		textChild = xmlNewDocText(inode->node->doc,
26165                         inode->decl->value);
26166 	    if (textChild == NULL) {
26167 		VERROR_INT("xmlSchemaValidatorPopElem",
26168 		    "calling xmlNewDocText()");
26169 		goto internal_error;
26170 	    } else
26171 		xmlAddChild(inode->node, textChild);
26172 	}
26173 
26174     } else if (! INODE_NILLED(inode)) {
26175 	/*
26176 	* 5.2.1 The element information item must be `valid` with respect
26177 	* to the `actual type definition` as defined by Element Locally
26178 	* Valid (Type) ($3.3.4).
26179 	*/
26180 	if (WXS_IS_SIMPLE(inode->typeDef)) {
26181 	     /*
26182 	    * SPEC (cvc-type) (3.1)
26183 	    * "If the type definition is a simple type definition, ..."
26184 	    * (3.1.3) "If clause 3.2 of Element Locally Valid
26185 	    * (Element) ($3.3.4) did not apply, then the `normalized value`
26186 	    * must be `valid` with respect to the type definition as defined
26187 	    * by String Valid ($3.14.4).
26188 	    */
26189 	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26190 		    inode, inode->typeDef, inode->value);
26191 	} else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26192 	    /*
26193 	    * SPEC (cvc-type) (3.2) "If the type definition is a complex type
26194 	    * definition, then the element information item must be
26195 	    * `valid` with respect to the type definition as per
26196 	    * Element Locally Valid (Complex Type) ($3.4.4);"
26197 	    *
26198 	    * SPEC (cvc-complex-type) (2.2)
26199 	    * "If the {content type} is a simple type definition, ...
26200 	    * the `normalized value` of the element information item is
26201 	    * `valid` with respect to that simple type definition as
26202 	    * defined by String Valid ($3.14.4)."
26203 	    */
26204 	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26205 		inode, inode->typeDef->contentTypeDef, inode->value);
26206 	}
26207 	if (ret != 0) {
26208 	    if (ret < 0) {
26209 		VERROR_INT("xmlSchemaValidatorPopElem",
26210 		    "calling xmlSchemaVCheckCVCSimpleType()");
26211 		goto internal_error;
26212 	    }
26213 	    goto end_elem;
26214 	}
26215 	/*
26216 	* 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
26217 	* not applied, all of the following must be true:
26218 	*/
26219 	if ((inode->decl->value != NULL) &&
26220 	    (inode->decl->flags & XML_SCHEMAS_ELEM_FIXED)) {
26221 
26222 	    /*
26223 	    * TODO: We will need a computed value, when comparison is
26224 	    * done on computed values.
26225 	    */
26226 	    /*
26227 	    * 5.2.2.1 The element information item must have no element
26228 	    * information item [children].
26229 	    */
26230 	    if (inode->flags &
26231 		    XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT) {
26232 		ret = XML_SCHEMAV_CVC_ELT_5_2_2_1;
26233 		VERROR(ret, NULL,
26234 		    "The content must not contain element nodes since "
26235 		    "there is a fixed value constraint");
26236 		goto end_elem;
26237 	    } else {
26238 		/*
26239 		* 5.2.2.2 The appropriate case among the following must
26240 		* be true:
26241 		*/
26242 		if (WXS_HAS_MIXED_CONTENT(inode->typeDef)) {
26243 		    /*
26244 		    * 5.2.2.2.1 If the {content type} of the `actual type
26245 		    * definition` is mixed, then the *initial value* of the
26246 		    * item must match the canonical lexical representation
26247 		    * of the {value constraint} value.
26248 		    *
26249 		    * ... the *initial value* of an element information
26250 		    * item is the string composed of, in order, the
26251 		    * [character code] of each character information item in
26252 		    * the [children] of that element information item.
26253 		    */
26254 		    if (! xmlStrEqual(inode->value, inode->decl->value)){
26255 			/*
26256 			* VAL TODO: Report invalid & expected values as well.
26257 			* VAL TODO: Implement the canonical stuff.
26258 			*/
26259 			ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_1;
26260 			xmlSchemaCustomErr(ACTXT_CAST vctxt,
26261 			    ret, NULL, NULL,
26262 			    "The initial value '%s' does not match the fixed "
26263 			    "value constraint '%s'",
26264 			    inode->value, inode->decl->value);
26265 			goto end_elem;
26266 		    }
26267 		} else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26268 		    /*
26269 		    * 5.2.2.2.2 If the {content type} of the `actual type
26270 		    * definition` is a simple type definition, then the
26271 		    * *actual value* of the item must match the canonical
26272 		    * lexical representation of the {value constraint} value.
26273 		    */
26274 		    /*
26275 		    * VAL TODO: *actual value* is the normalized value, impl.
26276 		    *           this.
26277 		    * VAL TODO: Report invalid & expected values as well.
26278 		    * VAL TODO: Implement a comparison with the computed values.
26279 		    */
26280 		    if (! xmlStrEqual(inode->value,
26281 			    inode->decl->value)) {
26282 			ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_2;
26283 			xmlSchemaCustomErr(ACTXT_CAST vctxt,
26284 			    ret, NULL, NULL,
26285 			    "The actual value '%s' does not match the fixed "
26286 			    "value constraint '%s'",
26287 			    inode->value,
26288 			    inode->decl->value);
26289 			goto end_elem;
26290 		    }
26291 		}
26292 	    }
26293 	}
26294     }
26295 
26296 end_elem:
26297     if (vctxt->depth < 0) {
26298 	/* TODO: raise error? */
26299 	return (0);
26300     }
26301     if (vctxt->depth == vctxt->skipDepth)
26302 	vctxt->skipDepth = -1;
26303     /*
26304     * Evaluate the history of XPath state objects.
26305     */
26306     if (inode->appliedXPath &&
26307 	(xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1))
26308 	goto internal_error;
26309     /*
26310     * MAYBE TODO:
26311     * SPEC (6) "The element information item must be `valid` with
26312     * respect to each of the {identity-constraint definitions} as per
26313     * Identity-constraint Satisfied ($3.11.4)."
26314     */
26315     /*
26316     * PSVI TODO: If we expose IDC node-tables via PSVI then the tables
26317     *   need to be built in any case.
26318     *   We will currently build IDC node-tables and bubble them only if
26319     *   keyrefs do exist.
26320     */
26321 
26322     /*
26323     * Add the current IDC target-nodes to the IDC node-tables.
26324     */
26325     if ((inode->idcMatchers != NULL) &&
26326 	(vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
26327     {
26328 	if (xmlSchemaIDCFillNodeTables(vctxt, inode) == -1)
26329 	    goto internal_error;
26330     }
26331     /*
26332     * Validate IDC keyrefs.
26333     */
26334     if (vctxt->inode->hasKeyrefs)
26335 	if (xmlSchemaCheckCVCIDCKeyRef(vctxt) == -1)
26336 	    goto internal_error;
26337     /*
26338     * Merge/free the IDC table.
26339     */
26340     if (inode->idcTable != NULL) {
26341 	if ((vctxt->depth > 0) &&
26342 	    (vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
26343 	{
26344 	    /*
26345 	    * Merge the IDC node table with the table of the parent node.
26346 	    */
26347 	    if (xmlSchemaBubbleIDCNodeTables(vctxt) == -1)
26348 		goto internal_error;
26349 	}
26350     }
26351     /*
26352     * Clear the current ielem.
26353     * VAL TODO: Don't free the PSVI IDC tables if they are
26354     * requested for the PSVI.
26355     */
26356     xmlSchemaClearElemInfo(vctxt, inode);
26357     /*
26358     * Skip further processing if we are on the validation root.
26359     */
26360     if (vctxt->depth == 0) {
26361 	vctxt->depth--;
26362 	vctxt->inode = NULL;
26363 	return (0);
26364     }
26365     /*
26366     * Reset the keyrefDepth if needed.
26367     */
26368     if (vctxt->aidcs != NULL) {
26369 	xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
26370 	do {
26371 	    if (aidc->keyrefDepth == vctxt->depth) {
26372 		/*
26373 		* A 'keyrefDepth' of a key/unique IDC matches the current
26374 		* depth, this means that we are leaving the scope of the
26375 		* top-most keyref IDC which refers to this IDC.
26376 		*/
26377 		aidc->keyrefDepth = -1;
26378 	    }
26379 	    aidc = aidc->next;
26380 	} while (aidc != NULL);
26381     }
26382     vctxt->depth--;
26383     vctxt->inode = vctxt->elemInfos[vctxt->depth];
26384     /*
26385     * VAL TODO: 7 If the element information item is the `validation root`, it must be
26386     * `valid` per Validation Root Valid (ID/IDREF) ($3.3.4).
26387     */
26388     return (ret);
26389 
26390 internal_error:
26391     vctxt->err = -1;
26392     return (-1);
26393 }
26394 
26395 /*
26396 * 3.4.4 Complex Type Definition Validation Rules
26397 * Validation Rule: Element Locally Valid (Complex Type) (cvc-complex-type)
26398 */
26399 static int
xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)26400 xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)
26401 {
26402     xmlSchemaNodeInfoPtr pielem;
26403     xmlSchemaTypePtr ptype;
26404     int ret = 0;
26405 
26406     if (vctxt->depth <= 0) {
26407 	VERROR_INT("xmlSchemaValidateChildElem",
26408 	    "not intended for the validation root");
26409 	return (-1);
26410     }
26411     pielem = vctxt->elemInfos[vctxt->depth -1];
26412     if (pielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26413 	pielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
26414     /*
26415     * Handle 'nilled' elements.
26416     */
26417     if (INODE_NILLED(pielem)) {
26418 	/*
26419 	* SPEC (cvc-elt) (3.3.4) : (3.2.1)
26420 	*/
26421 	ACTIVATE_PARENT_ELEM;
26422 	ret = XML_SCHEMAV_CVC_ELT_3_2_1;
26423 	VERROR(ret, NULL,
26424 	    "Neither character nor element content is allowed, "
26425 	    "because the element was 'nilled'");
26426 	ACTIVATE_ELEM;
26427 	goto unexpected_elem;
26428     }
26429 
26430     ptype = pielem->typeDef;
26431 
26432     if (ptype->builtInType == XML_SCHEMAS_ANYTYPE) {
26433 	/*
26434 	* Workaround for "anyType": we have currently no content model
26435 	* assigned for "anyType", so handle it explicitly.
26436 	* "anyType" has an unbounded, lax "any" wildcard.
26437 	*/
26438 	vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26439 	    vctxt->inode->localName,
26440 	    vctxt->inode->nsName);
26441 
26442 	if (vctxt->inode->decl == NULL) {
26443 	    xmlSchemaAttrInfoPtr iattr;
26444 	    /*
26445 	    * Process "xsi:type".
26446 	    * SPEC (cvc-assess-elt) (1.2.1.2.1) - (1.2.1.2.3)
26447 	    */
26448 	    iattr = xmlSchemaGetMetaAttrInfo(vctxt,
26449 		XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
26450 	    if (iattr != NULL) {
26451 		ret = xmlSchemaProcessXSIType(vctxt, iattr,
26452 		    &(vctxt->inode->typeDef), NULL);
26453 		if (ret != 0) {
26454 		    if (ret == -1) {
26455 			VERROR_INT("xmlSchemaValidateChildElem",
26456 			    "calling xmlSchemaProcessXSIType() to "
26457 			    "process the attribute 'xsi:nil'");
26458 			return (-1);
26459 		    }
26460 		    return (ret);
26461 		}
26462 	    } else {
26463 		 /*
26464 		 * Fallback to "anyType".
26465 		 *
26466 		 * SPEC (cvc-assess-elt)
26467 		 * "If the item cannot be `strictly assessed`, [...]
26468 		 * an element information item's schema validity may be laxly
26469 		 * assessed if its `context-determined declaration` is not
26470 		 * skip by `validating` with respect to the `ur-type
26471 		 * definition` as per Element Locally Valid (Type) ($3.3.4)."
26472 		*/
26473 		vctxt->inode->typeDef =
26474 		    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
26475 	    }
26476 	}
26477 	return (0);
26478     }
26479 
26480     switch (ptype->contentType) {
26481 	case XML_SCHEMA_CONTENT_EMPTY:
26482 	    /*
26483 	    * SPEC (2.1) "If the {content type} is empty, then the
26484 	    * element information item has no character or element
26485 	    * information item [children]."
26486 	    */
26487 	    ACTIVATE_PARENT_ELEM
26488 	    ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1;
26489 	    VERROR(ret, NULL,
26490 		"Element content is not allowed, "
26491 		"because the content type is empty");
26492 	    ACTIVATE_ELEM
26493 	    goto unexpected_elem;
26494 	    break;
26495 
26496 	case XML_SCHEMA_CONTENT_MIXED:
26497         case XML_SCHEMA_CONTENT_ELEMENTS: {
26498 	    xmlRegExecCtxtPtr regexCtxt;
26499 	    xmlChar *values[10];
26500 	    int terminal, nbval = 10, nbneg;
26501 
26502 	    /* VAL TODO: Optimized "anyType" validation.*/
26503 
26504 	    if (ptype->contModel == NULL) {
26505 		VERROR_INT("xmlSchemaValidateChildElem",
26506 		    "type has elem content but no content model");
26507 		return (-1);
26508 	    }
26509 	    /*
26510 	    * Safety belt for evaluation if the cont. model was already
26511 	    * examined to be invalid.
26512 	    */
26513 	    if (pielem->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) {
26514 		VERROR_INT("xmlSchemaValidateChildElem",
26515 		    "validating elem, but elem content is already invalid");
26516 		return (-1);
26517 	    }
26518 
26519 	    regexCtxt = pielem->regexCtxt;
26520 	    if (regexCtxt == NULL) {
26521 		/*
26522 		* Create the regex context.
26523 		*/
26524 		regexCtxt = xmlRegNewExecCtxt(ptype->contModel,
26525 		    xmlSchemaVContentModelCallback, vctxt);
26526 		if (regexCtxt == NULL) {
26527 		    VERROR_INT("xmlSchemaValidateChildElem",
26528 			"failed to create a regex context");
26529 		    return (-1);
26530 		}
26531 		pielem->regexCtxt = regexCtxt;
26532 	    }
26533 
26534 	    /*
26535 	    * SPEC (2.4) "If the {content type} is element-only or mixed,
26536 	    * then the sequence of the element information item's
26537 	    * element information item [children], if any, taken in
26538 	    * order, is `valid` with respect to the {content type}'s
26539 	    * particle, as defined in Element Sequence Locally Valid
26540 	    * (Particle) ($3.9.4)."
26541 	    */
26542 	    ret = xmlRegExecPushString2(regexCtxt,
26543 		vctxt->inode->localName,
26544 		vctxt->inode->nsName,
26545 		vctxt->inode);
26546 	    if (vctxt->err == XML_SCHEMAV_INTERNAL) {
26547 		VERROR_INT("xmlSchemaValidateChildElem",
26548 		    "calling xmlRegExecPushString2()");
26549 		return (-1);
26550 	    }
26551 	    if (ret < 0) {
26552 		xmlRegExecErrInfo(regexCtxt, NULL, &nbval, &nbneg,
26553 		    &values[0], &terminal);
26554 		xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
26555 		    XML_SCHEMAV_ELEMENT_CONTENT, NULL,NULL,
26556 		    "This element is not expected",
26557 		    nbval, nbneg, values);
26558 		ret = vctxt->err;
26559 		goto unexpected_elem;
26560 	    } else
26561 		ret = 0;
26562 	}
26563 	    break;
26564 	case XML_SCHEMA_CONTENT_SIMPLE:
26565 	case XML_SCHEMA_CONTENT_BASIC:
26566 	    ACTIVATE_PARENT_ELEM
26567 	    if (WXS_IS_COMPLEX(ptype)) {
26568 		/*
26569 		* SPEC (cvc-complex-type) (2.2)
26570 		* "If the {content type} is a simple type definition, then
26571 		* the element information item has no element information
26572 		* item [children], ..."
26573 		*/
26574 		ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
26575 		VERROR(ret, NULL, "Element content is not allowed, "
26576 		    "because the content type is a simple type definition");
26577 	    } else {
26578 		/*
26579 		* SPEC (cvc-type) (3.1.2) "The element information item must
26580 		* have no element information item [children]."
26581 		*/
26582 		ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
26583 		VERROR(ret, NULL, "Element content is not allowed, "
26584 		    "because the type definition is simple");
26585 	    }
26586 	    ACTIVATE_ELEM
26587 	    ret = vctxt->err;
26588 	    goto unexpected_elem;
26589 	    break;
26590 
26591 	default:
26592 	    break;
26593     }
26594     return (ret);
26595 unexpected_elem:
26596     /*
26597     * Pop this element and set the skipDepth to skip
26598     * all further content of the parent element.
26599     */
26600     vctxt->skipDepth = vctxt->depth;
26601     vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
26602     pielem->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
26603     return (ret);
26604 }
26605 
26606 #define XML_SCHEMA_PUSH_TEXT_PERSIST 1
26607 #define XML_SCHEMA_PUSH_TEXT_CREATED 2
26608 #define XML_SCHEMA_PUSH_TEXT_VOLATILE 3
26609 
26610 static int
xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,int nodeType,const xmlChar * value,int len,int mode,int * consumed)26611 xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,
26612 		  int nodeType, const xmlChar *value, int len,
26613 		  int mode, int *consumed)
26614 {
26615     /*
26616     * Unfortunately we have to duplicate the text sometimes.
26617     * OPTIMIZE: Maybe we could skip it, if:
26618     *   1. content type is simple
26619     *   2. whitespace is "collapse"
26620     *   3. it consists of whitespace only
26621     *
26622     * Process character content.
26623     */
26624     if (consumed != NULL)
26625 	*consumed = 0;
26626     if (INODE_NILLED(vctxt->inode)) {
26627 	/*
26628 	* SPEC cvc-elt (3.3.4 - 3.2.1)
26629 	* "The element information item must have no character or
26630 	* element information item [children]."
26631 	*/
26632 	VERROR(XML_SCHEMAV_CVC_ELT_3_2_1, NULL,
26633 	    "Neither character nor element content is allowed "
26634 	    "because the element is 'nilled'");
26635 	return (vctxt->err);
26636     }
26637     /*
26638     * SPEC (2.1) "If the {content type} is empty, then the
26639     * element information item has no character or element
26640     * information item [children]."
26641     */
26642     if (vctxt->inode->typeDef->contentType ==
26643 	    XML_SCHEMA_CONTENT_EMPTY) {
26644 	VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1, NULL,
26645 	    "Character content is not allowed, "
26646 	    "because the content type is empty");
26647 	return (vctxt->err);
26648     }
26649 
26650     if (vctxt->inode->typeDef->contentType ==
26651 	    XML_SCHEMA_CONTENT_ELEMENTS) {
26652 	if ((nodeType != XML_TEXT_NODE) ||
26653 	    (! xmlSchemaIsBlank((xmlChar *) value, len))) {
26654 	    /*
26655 	    * SPEC cvc-complex-type (2.3)
26656 	    * "If the {content type} is element-only, then the
26657 	    * element information item has no character information
26658 	    * item [children] other than those whose [character
26659 	    * code] is defined as a white space in [XML 1.0 (Second
26660 	    * Edition)]."
26661 	    */
26662 	    VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3, NULL,
26663 		"Character content other than whitespace is not allowed "
26664 		"because the content type is 'element-only'");
26665 	    return (vctxt->err);
26666 	}
26667 	return (0);
26668     }
26669 
26670     if ((value == NULL) || (value[0] == 0))
26671 	return (0);
26672     /*
26673     * Save the value.
26674     * NOTE that even if the content type is *mixed*, we need the
26675     * *initial value* for default/fixed value constraints.
26676     */
26677     if ((vctxt->inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) &&
26678 	((vctxt->inode->decl == NULL) ||
26679 	(vctxt->inode->decl->value == NULL)))
26680 	return (0);
26681 
26682     if (vctxt->inode->value == NULL) {
26683 	/*
26684 	* Set the value.
26685 	*/
26686 	switch (mode) {
26687 	    case XML_SCHEMA_PUSH_TEXT_PERSIST:
26688 		/*
26689 		* When working on a tree.
26690 		*/
26691 		vctxt->inode->value = value;
26692 		break;
26693 	    case XML_SCHEMA_PUSH_TEXT_CREATED:
26694 		/*
26695 		* When working with the reader.
26696 		* The value will be freed by the element info.
26697 		*/
26698 		vctxt->inode->value = value;
26699 		if (consumed != NULL)
26700 		    *consumed = 1;
26701 		vctxt->inode->flags |=
26702 		    XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26703 		break;
26704 	    case XML_SCHEMA_PUSH_TEXT_VOLATILE:
26705 		/*
26706 		* When working with SAX.
26707 		* The value will be freed by the element info.
26708 		*/
26709 		if (len != -1)
26710 		    vctxt->inode->value = BAD_CAST xmlStrndup(value, len);
26711 		else
26712 		    vctxt->inode->value = BAD_CAST xmlStrdup(value);
26713 		vctxt->inode->flags |=
26714 		    XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26715 		break;
26716 	    default:
26717 		break;
26718 	}
26719     } else {
26720 	if (len < 0)
26721 	    len = xmlStrlen(value);
26722 	/*
26723 	* Concat the value.
26724 	*/
26725 	if (vctxt->inode->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
26726 	    vctxt->inode->value = BAD_CAST xmlStrncat(
26727 		(xmlChar *) vctxt->inode->value, value, len);
26728 	} else {
26729 	    vctxt->inode->value =
26730 		BAD_CAST xmlStrncatNew(vctxt->inode->value, value, len);
26731 	    vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26732 	}
26733     }
26734 
26735     return (0);
26736 }
26737 
26738 static int
xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt)26739 xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt)
26740 {
26741     int ret = 0;
26742 
26743     if ((vctxt->skipDepth != -1) &&
26744 	(vctxt->depth >= vctxt->skipDepth)) {
26745 	VERROR_INT("xmlSchemaValidateElem",
26746 	    "in skip-state");
26747 	goto internal_error;
26748     }
26749     if (vctxt->xsiAssemble) {
26750 	/*
26751 	* We will stop validation if there was an error during
26752 	* dynamic schema construction.
26753 	* Note that we simply set @skipDepth to 0, this could
26754 	* mean that a streaming document via SAX would be
26755 	* still read to the end but it won't be validated any more.
26756 	* TODO: If we are sure how to stop the validation at once
26757 	*   for all input scenarios, then this should be changed to
26758 	*   instantly stop the validation.
26759 	*/
26760 	ret = xmlSchemaAssembleByXSI(vctxt);
26761 	if (ret != 0) {
26762 	    if (ret == -1)
26763 		goto internal_error;
26764 	    vctxt->skipDepth = 0;
26765 	    return(ret);
26766 	}
26767         /*
26768          * Augment the IDC definitions for the main schema and all imported ones
26769          * NOTE: main schema is the first in the imported list
26770          */
26771         xmlHashScan(vctxt->schema->schemasImports, xmlSchemaAugmentImportedIDC,
26772                     vctxt);
26773     }
26774     if (vctxt->depth > 0) {
26775 	/*
26776 	* Validate this element against the content model
26777 	* of the parent.
26778 	*/
26779 	ret = xmlSchemaValidateChildElem(vctxt);
26780 	if (ret != 0) {
26781 	    if (ret < 0) {
26782 		VERROR_INT("xmlSchemaValidateElem",
26783 		    "calling xmlSchemaStreamValidateChildElement()");
26784 		goto internal_error;
26785 	    }
26786 	    goto exit;
26787 	}
26788 	if (vctxt->depth == vctxt->skipDepth)
26789 	    goto exit;
26790 	if ((vctxt->inode->decl == NULL) &&
26791 	    (vctxt->inode->typeDef == NULL)) {
26792 	    VERROR_INT("xmlSchemaValidateElem",
26793 		"the child element was valid but neither the "
26794 		"declaration nor the type was set");
26795 	    goto internal_error;
26796 	}
26797     } else {
26798 	/*
26799 	* Get the declaration of the validation root.
26800 	*/
26801 	vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26802 	    vctxt->inode->localName,
26803 	    vctxt->inode->nsName);
26804 	if (vctxt->inode->decl == NULL) {
26805 	    ret = XML_SCHEMAV_CVC_ELT_1;
26806 	    VERROR(ret, NULL,
26807 		"No matching global declaration available "
26808 		"for the validation root");
26809 	    goto exit;
26810 	}
26811     }
26812 
26813     if (vctxt->inode->decl == NULL)
26814 	goto type_validation;
26815 
26816     if (vctxt->inode->decl->type == XML_SCHEMA_TYPE_ANY) {
26817 	int skip;
26818 	/*
26819 	* Wildcards.
26820 	*/
26821 	ret = xmlSchemaValidateElemWildcard(vctxt, &skip);
26822 	if (ret != 0) {
26823 	    if (ret < 0) {
26824 		VERROR_INT("xmlSchemaValidateElem",
26825 		    "calling xmlSchemaValidateElemWildcard()");
26826 		goto internal_error;
26827 	    }
26828 	    goto exit;
26829 	}
26830 	if (skip) {
26831 	    vctxt->skipDepth = vctxt->depth;
26832 	    goto exit;
26833 	}
26834 	/*
26835 	* The declaration might be set by the wildcard validation,
26836 	* when the processContents is "lax" or "strict".
26837 	*/
26838 	if (vctxt->inode->decl->type != XML_SCHEMA_TYPE_ELEMENT) {
26839 	    /*
26840 	    * Clear the "decl" field to not confuse further processing.
26841 	    */
26842 	    vctxt->inode->decl = NULL;
26843 	    goto type_validation;
26844 	}
26845     }
26846     /*
26847     * Validate against the declaration.
26848     */
26849     ret = xmlSchemaValidateElemDecl(vctxt);
26850     if (ret != 0) {
26851 	if (ret < 0) {
26852 	    VERROR_INT("xmlSchemaValidateElem",
26853 		"calling xmlSchemaValidateElemDecl()");
26854 	    goto internal_error;
26855 	}
26856 	goto exit;
26857     }
26858     /*
26859     * Validate against the type definition.
26860     */
26861 type_validation:
26862 
26863     if (vctxt->inode->typeDef == NULL) {
26864 	vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
26865 	ret = XML_SCHEMAV_CVC_TYPE_1;
26866 	VERROR(ret, NULL,
26867 	    "The type definition is absent");
26868 	goto exit;
26869     }
26870     if (vctxt->inode->typeDef->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
26871 	vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
26872 	ret = XML_SCHEMAV_CVC_TYPE_2;
26873 	    VERROR(ret, NULL,
26874 	    "The type definition is abstract");
26875 	goto exit;
26876     }
26877     /*
26878     * Evaluate IDCs. Do it here, since new IDC matchers are registered
26879     * during validation against the declaration. This must be done
26880     * _before_ attribute validation.
26881     */
26882     if (vctxt->xpathStates != NULL) {
26883 	ret = xmlSchemaXPathEvaluate(vctxt, XML_ELEMENT_NODE);
26884 	vctxt->inode->appliedXPath = 1;
26885 	if (ret == -1) {
26886 	    VERROR_INT("xmlSchemaValidateElem",
26887 		"calling xmlSchemaXPathEvaluate()");
26888 	    goto internal_error;
26889 	}
26890     }
26891     /*
26892     * Validate attributes.
26893     */
26894     if (WXS_IS_COMPLEX(vctxt->inode->typeDef)) {
26895 	if ((vctxt->nbAttrInfos != 0) ||
26896 	    (vctxt->inode->typeDef->attrUses != NULL)) {
26897 
26898 	    ret = xmlSchemaVAttributesComplex(vctxt);
26899 	}
26900     } else if (vctxt->nbAttrInfos != 0) {
26901 
26902 	ret = xmlSchemaVAttributesSimple(vctxt);
26903     }
26904     /*
26905     * Clear registered attributes.
26906     */
26907     if (vctxt->nbAttrInfos != 0)
26908 	xmlSchemaClearAttrInfos(vctxt);
26909     if (ret == -1) {
26910 	VERROR_INT("xmlSchemaValidateElem",
26911 	    "calling attributes validation");
26912 	goto internal_error;
26913     }
26914     /*
26915     * Don't return an error if attributes are invalid on purpose.
26916     */
26917     ret = 0;
26918 
26919 exit:
26920     if (ret != 0)
26921 	vctxt->skipDepth = vctxt->depth;
26922     return (ret);
26923 internal_error:
26924     return (-1);
26925 }
26926 
26927 #ifdef XML_SCHEMA_READER_ENABLED
26928 static int
xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt)26929 xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt)
26930 {
26931     const int WHTSP = 13, SIGN_WHTSP = 14, END_ELEM = 15;
26932     int depth, nodeType, ret = 0, consumed;
26933     xmlSchemaNodeInfoPtr ielem;
26934 
26935     vctxt->depth = -1;
26936     ret = xmlTextReaderRead(vctxt->reader);
26937     /*
26938     * Move to the document element.
26939     */
26940     while (ret == 1) {
26941 	nodeType = xmlTextReaderNodeType(vctxt->reader);
26942 	if (nodeType == XML_ELEMENT_NODE)
26943 	    goto root_found;
26944 	ret = xmlTextReaderRead(vctxt->reader);
26945     }
26946     goto exit;
26947 
26948 root_found:
26949 
26950     do {
26951 	depth = xmlTextReaderDepth(vctxt->reader);
26952 	nodeType = xmlTextReaderNodeType(vctxt->reader);
26953 
26954 	if (nodeType == XML_ELEMENT_NODE) {
26955 
26956 	    vctxt->depth++;
26957 	    if (xmlSchemaValidatorPushElem(vctxt) == -1) {
26958 		VERROR_INT("xmlSchemaVReaderWalk",
26959 		    "calling xmlSchemaValidatorPushElem()");
26960 		goto internal_error;
26961 	    }
26962 	    ielem = vctxt->inode;
26963 	    ielem->localName = xmlTextReaderLocalName(vctxt->reader);
26964 	    ielem->nsName = xmlTextReaderNamespaceUri(vctxt->reader);
26965 	    ielem->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
26966 	    /*
26967 	    * Is the element empty?
26968 	    */
26969 	    ret = xmlTextReaderIsEmptyElement(vctxt->reader);
26970 	    if (ret == -1) {
26971 		VERROR_INT("xmlSchemaVReaderWalk",
26972 		    "calling xmlTextReaderIsEmptyElement()");
26973 		goto internal_error;
26974 	    }
26975 	    if (ret) {
26976 		ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
26977 	    }
26978 	    /*
26979 	    * Register attributes.
26980 	    */
26981 	    vctxt->nbAttrInfos = 0;
26982 	    ret = xmlTextReaderMoveToFirstAttribute(vctxt->reader);
26983 	    if (ret == -1) {
26984 		VERROR_INT("xmlSchemaVReaderWalk",
26985 		    "calling xmlTextReaderMoveToFirstAttribute()");
26986 		goto internal_error;
26987 	    }
26988 	    if (ret == 1) {
26989 		do {
26990 		    /*
26991 		    * VAL TODO: How do we know that the reader works on a
26992 		    * node tree, to be able to pass a node here?
26993 		    */
26994 		    if (xmlSchemaValidatorPushAttribute(vctxt, NULL,
26995 			(const xmlChar *) xmlTextReaderLocalName(vctxt->reader),
26996 			xmlTextReaderNamespaceUri(vctxt->reader), 1,
26997 			xmlTextReaderValue(vctxt->reader), 1) == -1) {
26998 
26999 			VERROR_INT("xmlSchemaVReaderWalk",
27000 			    "calling xmlSchemaValidatorPushAttribute()");
27001 			goto internal_error;
27002 		    }
27003 		    ret = xmlTextReaderMoveToNextAttribute(vctxt->reader);
27004 		    if (ret == -1) {
27005 			VERROR_INT("xmlSchemaVReaderWalk",
27006 			    "calling xmlTextReaderMoveToFirstAttribute()");
27007 			goto internal_error;
27008 		    }
27009 		} while (ret == 1);
27010 		/*
27011 		* Back to element position.
27012 		*/
27013 		ret = xmlTextReaderMoveToElement(vctxt->reader);
27014 		if (ret == -1) {
27015 		    VERROR_INT("xmlSchemaVReaderWalk",
27016 			"calling xmlTextReaderMoveToElement()");
27017 		    goto internal_error;
27018 		}
27019 	    }
27020 	    /*
27021 	    * Validate the element.
27022 	    */
27023 	    ret= xmlSchemaValidateElem(vctxt);
27024 	    if (ret != 0) {
27025 		if (ret == -1) {
27026 		    VERROR_INT("xmlSchemaVReaderWalk",
27027 			"calling xmlSchemaValidateElem()");
27028 		    goto internal_error;
27029 		}
27030 		goto exit;
27031 	    }
27032 	    if (vctxt->depth == vctxt->skipDepth) {
27033 		int curDepth;
27034 		/*
27035 		* Skip all content.
27036 		*/
27037 		if ((ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) == 0) {
27038 		    ret = xmlTextReaderRead(vctxt->reader);
27039 		    curDepth = xmlTextReaderDepth(vctxt->reader);
27040 		    while ((ret == 1) && (curDepth != depth)) {
27041 			ret = xmlTextReaderRead(vctxt->reader);
27042 			curDepth = xmlTextReaderDepth(vctxt->reader);
27043 		    }
27044 		    if (ret < 0) {
27045 			/*
27046 			* VAL TODO: A reader error occurred; what to do here?
27047 			*/
27048 			ret = 1;
27049 			goto exit;
27050 		    }
27051 		}
27052 		goto leave_elem;
27053 	    }
27054 	    /*
27055 	    * READER VAL TODO: Is an END_ELEM really never called
27056 	    * if the elem is empty?
27057 	    */
27058 	    if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27059 		goto leave_elem;
27060 	} else if (nodeType == END_ELEM) {
27061 	    /*
27062 	    * Process END of element.
27063 	    */
27064 leave_elem:
27065 	    ret = xmlSchemaValidatorPopElem(vctxt);
27066 	    if (ret != 0) {
27067 		if (ret < 0) {
27068 		    VERROR_INT("xmlSchemaVReaderWalk",
27069 			"calling xmlSchemaValidatorPopElem()");
27070 		    goto internal_error;
27071 		}
27072 		goto exit;
27073 	    }
27074 	    if (vctxt->depth >= 0)
27075 		ielem = vctxt->inode;
27076 	    else
27077 		ielem = NULL;
27078 	} else if ((nodeType == XML_TEXT_NODE) ||
27079 	    (nodeType == XML_CDATA_SECTION_NODE) ||
27080 	    (nodeType == WHTSP) ||
27081 	    (nodeType == SIGN_WHTSP)) {
27082 	    /*
27083 	    * Process character content.
27084 	    */
27085 	    xmlChar *value;
27086 
27087 	    if ((nodeType == WHTSP) || (nodeType == SIGN_WHTSP))
27088 		nodeType = XML_TEXT_NODE;
27089 
27090 	    value = xmlTextReaderValue(vctxt->reader);
27091 	    ret = xmlSchemaVPushText(vctxt, nodeType, BAD_CAST value,
27092 		-1, XML_SCHEMA_PUSH_TEXT_CREATED, &consumed);
27093 	    if (! consumed)
27094 		xmlFree(value);
27095 	    if (ret == -1) {
27096 		VERROR_INT("xmlSchemaVReaderWalk",
27097 		    "calling xmlSchemaVPushText()");
27098 		goto internal_error;
27099 	    }
27100 	} else if ((nodeType == XML_ENTITY_NODE) ||
27101 	    (nodeType == XML_ENTITY_REF_NODE)) {
27102 	    /*
27103 	    * VAL TODO: What to do with entities?
27104 	    */
27105 	    TODO
27106 	}
27107 	/*
27108 	* Read next node.
27109 	*/
27110 	ret = xmlTextReaderRead(vctxt->reader);
27111     } while (ret == 1);
27112 
27113 exit:
27114     return (ret);
27115 internal_error:
27116     return (-1);
27117 }
27118 #endif
27119 
27120 /************************************************************************
27121  *									*
27122  *			SAX validation handlers				*
27123  *									*
27124  ************************************************************************/
27125 
27126 /*
27127 * Process text content.
27128 */
27129 static void
xmlSchemaSAXHandleText(void * ctx,const xmlChar * ch,int len)27130 xmlSchemaSAXHandleText(void *ctx,
27131 		       const xmlChar * ch,
27132 		       int len)
27133 {
27134     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27135 
27136     if (vctxt->depth < 0)
27137 	return;
27138     if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27139 	return;
27140     if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27141 	vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27142     if (xmlSchemaVPushText(vctxt, XML_TEXT_NODE, ch, len,
27143 	XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
27144 	VERROR_INT("xmlSchemaSAXHandleCDataSection",
27145 	    "calling xmlSchemaVPushText()");
27146 	vctxt->err = -1;
27147 	xmlStopParser(vctxt->parserCtxt);
27148     }
27149 }
27150 
27151 /*
27152 * Process CDATA content.
27153 */
27154 static void
xmlSchemaSAXHandleCDataSection(void * ctx,const xmlChar * ch,int len)27155 xmlSchemaSAXHandleCDataSection(void *ctx,
27156 			     const xmlChar * ch,
27157 			     int len)
27158 {
27159     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27160 
27161     if (vctxt->depth < 0)
27162 	return;
27163     if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27164 	return;
27165     if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27166 	vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27167     if (xmlSchemaVPushText(vctxt, XML_CDATA_SECTION_NODE, ch, len,
27168 	XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
27169 	VERROR_INT("xmlSchemaSAXHandleCDataSection",
27170 	    "calling xmlSchemaVPushText()");
27171 	vctxt->err = -1;
27172 	xmlStopParser(vctxt->parserCtxt);
27173     }
27174 }
27175 
27176 static void
xmlSchemaSAXHandleReference(void * ctx ATTRIBUTE_UNUSED,const xmlChar * name ATTRIBUTE_UNUSED)27177 xmlSchemaSAXHandleReference(void *ctx ATTRIBUTE_UNUSED,
27178 			    const xmlChar * name ATTRIBUTE_UNUSED)
27179 {
27180     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27181 
27182     if (vctxt->depth < 0)
27183 	return;
27184     if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27185 	return;
27186     /* SAX VAL TODO: What to do here? */
27187 }
27188 
27189 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)27190 xmlSchemaSAXHandleStartElementNs(void *ctx,
27191 				 const xmlChar * localname,
27192 				 const xmlChar * prefix ATTRIBUTE_UNUSED,
27193 				 const xmlChar * URI,
27194 				 int nb_namespaces,
27195 				 const xmlChar ** namespaces,
27196 				 int nb_attributes,
27197 				 int nb_defaulted ATTRIBUTE_UNUSED,
27198 				 const xmlChar ** attributes)
27199 {
27200     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27201     int ret;
27202     xmlSchemaNodeInfoPtr ielem;
27203     int i, j;
27204 
27205     /*
27206     * SAX VAL TODO: What to do with nb_defaulted?
27207     */
27208     /*
27209     * Skip elements if inside a "skip" wildcard or invalid.
27210     */
27211     vctxt->depth++;
27212     if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27213 	return;
27214     /*
27215     * Push the element.
27216     */
27217     if (xmlSchemaValidatorPushElem(vctxt) == -1) {
27218 	VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27219 	    "calling xmlSchemaValidatorPushElem()");
27220 	goto internal_error;
27221     }
27222     ielem = vctxt->inode;
27223     /*
27224     * TODO: Is this OK?
27225     */
27226     ielem->nodeLine = xmlSAX2GetLineNumber(vctxt->parserCtxt);
27227     ielem->localName = localname;
27228     ielem->nsName = URI;
27229     ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27230     /*
27231     * Register namespaces on the elem info.
27232     */
27233     if (nb_namespaces != 0) {
27234 	/*
27235 	* Although the parser builds its own namespace list,
27236 	* we have no access to it, so we'll use an own one.
27237 	*/
27238         for (i = 0, j = 0; i < nb_namespaces; i++, j += 2) {
27239 	    /*
27240 	    * Store prefix and namespace name.
27241 	    */
27242 	    if (ielem->nsBindings == NULL) {
27243 		ielem->nsBindings =
27244 		    (const xmlChar **) xmlMalloc(10 *
27245 			sizeof(const xmlChar *));
27246 		if (ielem->nsBindings == NULL) {
27247 		    xmlSchemaVErrMemory(vctxt);
27248 		    goto internal_error;
27249 		}
27250 		ielem->nbNsBindings = 0;
27251 		ielem->sizeNsBindings = 5;
27252 	    } else if (ielem->sizeNsBindings <= ielem->nbNsBindings) {
27253 		ielem->sizeNsBindings *= 2;
27254 		ielem->nsBindings =
27255 		    (const xmlChar **) xmlRealloc(
27256 			(void *) ielem->nsBindings,
27257 			ielem->sizeNsBindings * 2 * sizeof(const xmlChar *));
27258 		if (ielem->nsBindings == NULL) {
27259 		    xmlSchemaVErrMemory(vctxt);
27260 		    goto internal_error;
27261 		}
27262 	    }
27263 
27264 	    ielem->nsBindings[ielem->nbNsBindings * 2] = namespaces[j];
27265 	    if (namespaces[j+1][0] == 0) {
27266 		/*
27267 		* Handle xmlns="".
27268 		*/
27269 		ielem->nsBindings[ielem->nbNsBindings * 2 + 1] = NULL;
27270 	    } else
27271 		ielem->nsBindings[ielem->nbNsBindings * 2 + 1] =
27272 		    namespaces[j+1];
27273 	    ielem->nbNsBindings++;
27274 	}
27275     }
27276     /*
27277     * Register attributes.
27278     * SAX VAL TODO: We are not adding namespace declaration
27279     * attributes yet.
27280     */
27281     if (nb_attributes != 0) {
27282 	int valueLen, k, l;
27283 	xmlChar *value;
27284 
27285         for (j = 0, i = 0; i < nb_attributes; i++, j += 5) {
27286 	    /*
27287 	    * Duplicate the value, changing any &#38; to a literal ampersand.
27288 	    *
27289 	    * libxml2 differs from normal SAX here in that it escapes all ampersands
27290 	    * as &#38; instead of delivering the raw converted string. Changing the
27291 	    * behavior at this point would break applications that use this API, so
27292 	    * we are forced to work around it.
27293 	    */
27294 	    valueLen = attributes[j+4] - attributes[j+3];
27295 	    value = xmlMalloc(valueLen + 1);
27296 	    if (value == NULL) {
27297 		xmlSchemaVErrMemory(vctxt);
27298 		goto internal_error;
27299 	    }
27300 	    for (k = 0, l = 0; k < valueLen; l++) {
27301 		if (k < valueLen - 4 &&
27302 		    attributes[j+3][k+0] == '&' &&
27303 		    attributes[j+3][k+1] == '#' &&
27304 		    attributes[j+3][k+2] == '3' &&
27305 		    attributes[j+3][k+3] == '8' &&
27306 		    attributes[j+3][k+4] == ';') {
27307 		    value[l] = '&';
27308 		    k += 5;
27309 		} else {
27310 		    value[l] = attributes[j+3][k];
27311 		    k++;
27312 		}
27313 	    }
27314 	    value[l] = '\0';
27315 	    /*
27316 	    * TODO: Set the node line.
27317 	    */
27318 	    ret = xmlSchemaValidatorPushAttribute(vctxt,
27319 		NULL, ielem->nodeLine, attributes[j], attributes[j+2], 0,
27320 		value, 1);
27321 	    if (ret == -1) {
27322 		VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27323 		    "calling xmlSchemaValidatorPushAttribute()");
27324 		goto internal_error;
27325 	    }
27326 	}
27327     }
27328     /*
27329     * Validate the element.
27330     */
27331     ret = xmlSchemaValidateElem(vctxt);
27332     if (ret != 0) {
27333 	if (ret == -1) {
27334 	    VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27335 		"calling xmlSchemaValidateElem()");
27336 	    goto internal_error;
27337 	}
27338 	goto exit;
27339     }
27340 
27341 exit:
27342     return;
27343 internal_error:
27344     vctxt->err = -1;
27345     xmlStopParser(vctxt->parserCtxt);
27346 }
27347 
27348 static void
xmlSchemaSAXHandleEndElementNs(void * ctx,const xmlChar * localname ATTRIBUTE_UNUSED,const xmlChar * prefix ATTRIBUTE_UNUSED,const xmlChar * URI ATTRIBUTE_UNUSED)27349 xmlSchemaSAXHandleEndElementNs(void *ctx,
27350 			       const xmlChar * localname ATTRIBUTE_UNUSED,
27351 			       const xmlChar * prefix ATTRIBUTE_UNUSED,
27352 			       const xmlChar * URI ATTRIBUTE_UNUSED)
27353 {
27354     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27355     int res;
27356 
27357     /*
27358     * Skip elements if inside a "skip" wildcard or if invalid.
27359     */
27360     if (vctxt->skipDepth != -1) {
27361 	if (vctxt->depth > vctxt->skipDepth) {
27362 	    vctxt->depth--;
27363 	    return;
27364 	} else
27365 	    vctxt->skipDepth = -1;
27366     }
27367     /*
27368     * SAX VAL TODO: Just a temporary check.
27369     */
27370     if ((!xmlStrEqual(vctxt->inode->localName, localname)) ||
27371 	(!xmlStrEqual(vctxt->inode->nsName, URI))) {
27372 	VERROR_INT("xmlSchemaSAXHandleEndElementNs",
27373 	    "elem pop mismatch");
27374     }
27375     res = xmlSchemaValidatorPopElem(vctxt);
27376     if (res != 0) {
27377 	if (res < 0) {
27378 	    VERROR_INT("xmlSchemaSAXHandleEndElementNs",
27379 		"calling xmlSchemaValidatorPopElem()");
27380 	    goto internal_error;
27381 	}
27382 	goto exit;
27383     }
27384 exit:
27385     return;
27386 internal_error:
27387     vctxt->err = -1;
27388     xmlStopParser(vctxt->parserCtxt);
27389 }
27390 
27391 /************************************************************************
27392  *									*
27393  *			Validation interfaces				*
27394  *									*
27395  ************************************************************************/
27396 
27397 /**
27398  * xmlSchemaNewValidCtxt:
27399  * @schema:  a precompiled XML Schemas
27400  *
27401  * Create an XML Schemas validation context based on the given schema.
27402  *
27403  * Returns the validation context or NULL in case of error
27404  */
27405 xmlSchemaValidCtxtPtr
xmlSchemaNewValidCtxt(xmlSchemaPtr schema)27406 xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
27407 {
27408     xmlSchemaValidCtxtPtr ret;
27409 
27410     ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
27411     if (ret == NULL) {
27412         xmlSchemaVErrMemory(NULL);
27413         return (NULL);
27414     }
27415     memset(ret, 0, sizeof(xmlSchemaValidCtxt));
27416     ret->type = XML_SCHEMA_CTXT_VALIDATOR;
27417     ret->dict = xmlDictCreate();
27418     ret->nodeQNames = xmlSchemaItemListCreate();
27419     ret->schema = schema;
27420     return (ret);
27421 }
27422 
27423 /**
27424  * xmlSchemaValidateSetFilename:
27425  * @vctxt: the schema validation context
27426  * @filename: the file name
27427  *
27428  * Workaround to provide file error reporting information when this is
27429  * not provided by current APIs
27430  */
27431 void
xmlSchemaValidateSetFilename(xmlSchemaValidCtxtPtr vctxt,const char * filename)27432 xmlSchemaValidateSetFilename(xmlSchemaValidCtxtPtr vctxt, const char *filename) {
27433     if (vctxt == NULL)
27434         return;
27435     if (vctxt->filename != NULL)
27436         xmlFree(vctxt->filename);
27437     if (filename != NULL)
27438         vctxt->filename = (char *) xmlStrdup((const xmlChar *) filename);
27439     else
27440         vctxt->filename = NULL;
27441 }
27442 
27443 /**
27444  * xmlSchemaClearValidCtxt:
27445  * @vctxt: the schema validation context
27446  *
27447  * Free the resources associated to the schema validation context;
27448  * leaves some fields alive intended for reuse of the context.
27449  */
27450 static void
xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)27451 xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
27452 {
27453     if (vctxt == NULL)
27454         return;
27455 
27456     /*
27457     * TODO: Should we clear the flags?
27458     *   Might be problematic if one reuses the context
27459     *   and assumes that the options remain the same.
27460     */
27461     vctxt->flags = 0;
27462     vctxt->validationRoot = NULL;
27463     vctxt->doc = NULL;
27464 #ifdef LIBXML_READER_ENABLED
27465     vctxt->reader = NULL;
27466 #endif
27467     vctxt->hasKeyrefs = 0;
27468 
27469     if (vctxt->value != NULL) {
27470         xmlSchemaFreeValue(vctxt->value);
27471 	vctxt->value = NULL;
27472     }
27473     /*
27474     * Augmented IDC information.
27475     */
27476     if (vctxt->aidcs != NULL) {
27477 	xmlSchemaIDCAugPtr cur = vctxt->aidcs, next;
27478 	do {
27479 	    next = cur->next;
27480 	    xmlFree(cur);
27481 	    cur = next;
27482 	} while (cur != NULL);
27483 	vctxt->aidcs = NULL;
27484     }
27485 
27486     if (vctxt->idcNodes != NULL) {
27487 	int i;
27488 	xmlSchemaPSVIIDCNodePtr item;
27489 
27490 	for (i = 0; i < vctxt->nbIdcNodes; i++) {
27491 	    item = vctxt->idcNodes[i];
27492 	    xmlFree(item->keys);
27493 	    xmlFree(item);
27494 	}
27495 	xmlFree(vctxt->idcNodes);
27496 	vctxt->idcNodes = NULL;
27497 	vctxt->nbIdcNodes = 0;
27498 	vctxt->sizeIdcNodes = 0;
27499     }
27500 
27501     if (vctxt->idcKeys != NULL) {
27502 	int i;
27503 	for (i = 0; i < vctxt->nbIdcKeys; i++)
27504 	    xmlSchemaIDCFreeKey(vctxt->idcKeys[i]);
27505 	xmlFree(vctxt->idcKeys);
27506 	vctxt->idcKeys = NULL;
27507 	vctxt->nbIdcKeys = 0;
27508 	vctxt->sizeIdcKeys = 0;
27509     }
27510 
27511     /*
27512     * Note that we won't delete the XPath state pool here.
27513     */
27514     if (vctxt->xpathStates != NULL) {
27515 	xmlSchemaFreeIDCStateObjList(vctxt->xpathStates);
27516 	vctxt->xpathStates = NULL;
27517     }
27518     /*
27519     * Attribute info.
27520     */
27521     if (vctxt->nbAttrInfos != 0) {
27522 	xmlSchemaClearAttrInfos(vctxt);
27523     }
27524     /*
27525     * Element info.
27526     */
27527     if (vctxt->elemInfos != NULL) {
27528 	int i;
27529 	xmlSchemaNodeInfoPtr ei;
27530 
27531 	for (i = 0; i < vctxt->sizeElemInfos; i++) {
27532 	    ei = vctxt->elemInfos[i];
27533 	    if (ei == NULL)
27534 		break;
27535 	    xmlSchemaClearElemInfo(vctxt, ei);
27536 	}
27537     }
27538     xmlSchemaItemListClear(vctxt->nodeQNames);
27539     /* Recreate the dict. */
27540     xmlDictFree(vctxt->dict);
27541     /*
27542     * TODO: Is is save to recreate it? Do we have a scenario
27543     * where the user provides the dict?
27544     */
27545     vctxt->dict = xmlDictCreate();
27546 
27547     if (vctxt->filename != NULL) {
27548         xmlFree(vctxt->filename);
27549 	vctxt->filename = NULL;
27550     }
27551 
27552     /*
27553      * Note that some cleanup functions can move items to the cache,
27554      * so the cache shouldn't be freed too early.
27555      */
27556     if (vctxt->idcMatcherCache != NULL) {
27557 	xmlSchemaIDCMatcherPtr matcher = vctxt->idcMatcherCache, tmp;
27558 
27559 	while (matcher) {
27560 	    tmp = matcher;
27561 	    matcher = matcher->nextCached;
27562 	    xmlSchemaIDCFreeMatcherList(tmp);
27563 	}
27564 	vctxt->idcMatcherCache = NULL;
27565     }
27566 }
27567 
27568 /**
27569  * xmlSchemaFreeValidCtxt:
27570  * @ctxt:  the schema validation context
27571  *
27572  * Free the resources associated to the schema validation context
27573  */
27574 void
xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)27575 xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
27576 {
27577     if (ctxt == NULL)
27578         return;
27579     if (ctxt->value != NULL)
27580         xmlSchemaFreeValue(ctxt->value);
27581     if (ctxt->pctxt != NULL)
27582 	xmlSchemaFreeParserCtxt(ctxt->pctxt);
27583     if (ctxt->idcNodes != NULL) {
27584 	int i;
27585 	xmlSchemaPSVIIDCNodePtr item;
27586 
27587 	for (i = 0; i < ctxt->nbIdcNodes; i++) {
27588 	    item = ctxt->idcNodes[i];
27589 	    xmlFree(item->keys);
27590 	    xmlFree(item);
27591 	}
27592 	xmlFree(ctxt->idcNodes);
27593     }
27594     if (ctxt->idcKeys != NULL) {
27595 	int i;
27596 	for (i = 0; i < ctxt->nbIdcKeys; i++)
27597 	    xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
27598 	xmlFree(ctxt->idcKeys);
27599     }
27600 
27601     if (ctxt->xpathStates != NULL) {
27602 	xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
27603 	ctxt->xpathStates = NULL;
27604     }
27605     if (ctxt->xpathStatePool != NULL) {
27606 	xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
27607 	ctxt->xpathStatePool = NULL;
27608     }
27609 
27610     /*
27611     * Augmented IDC information.
27612     */
27613     if (ctxt->aidcs != NULL) {
27614 	xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
27615 	do {
27616 	    next = cur->next;
27617 	    xmlFree(cur);
27618 	    cur = next;
27619 	} while (cur != NULL);
27620     }
27621     if (ctxt->attrInfos != NULL) {
27622 	int i;
27623 	xmlSchemaAttrInfoPtr attr;
27624 
27625 	/* Just a paranoid call to the cleanup. */
27626 	if (ctxt->nbAttrInfos != 0)
27627 	    xmlSchemaClearAttrInfos(ctxt);
27628 	for (i = 0; i < ctxt->sizeAttrInfos; i++) {
27629 	    attr = ctxt->attrInfos[i];
27630 	    xmlFree(attr);
27631 	}
27632 	xmlFree(ctxt->attrInfos);
27633     }
27634     if (ctxt->elemInfos != NULL) {
27635 	int i;
27636 	xmlSchemaNodeInfoPtr ei;
27637 
27638 	for (i = 0; i < ctxt->sizeElemInfos; i++) {
27639 	    ei = ctxt->elemInfos[i];
27640 	    if (ei == NULL)
27641 		break;
27642 	    xmlSchemaClearElemInfo(ctxt, ei);
27643 	    xmlFree(ei);
27644 	}
27645 	xmlFree(ctxt->elemInfos);
27646     }
27647     if (ctxt->nodeQNames != NULL)
27648 	xmlSchemaItemListFree(ctxt->nodeQNames);
27649     if (ctxt->dict != NULL)
27650 	xmlDictFree(ctxt->dict);
27651     if (ctxt->filename != NULL)
27652 	xmlFree(ctxt->filename);
27653     xmlFree(ctxt);
27654 }
27655 
27656 /**
27657  * xmlSchemaIsValid:
27658  * @ctxt: the schema validation context
27659  *
27660  * Check if any error was detected during validation.
27661  *
27662  * Returns 1 if valid so far, 0 if errors were detected, and -1 in case
27663  *         of internal error.
27664  */
27665 int
xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt)27666 xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt)
27667 {
27668     if (ctxt == NULL)
27669         return(-1);
27670     return(ctxt->err == 0);
27671 }
27672 
27673 /**
27674  * xmlSchemaSetValidErrors:
27675  * @ctxt:  a schema validation context
27676  * @err:  the error function
27677  * @warn: the warning function
27678  * @ctx: the functions context
27679  *
27680  * DEPRECATED: Use xmlSchemaSetValidStructuredErrors.
27681  *
27682  * Set the error and warning callback information
27683  */
27684 void
xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,xmlSchemaValidityErrorFunc err,xmlSchemaValidityWarningFunc warn,void * ctx)27685 xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
27686                         xmlSchemaValidityErrorFunc err,
27687                         xmlSchemaValidityWarningFunc warn, void *ctx)
27688 {
27689     if (ctxt == NULL)
27690         return;
27691     ctxt->error = err;
27692     ctxt->warning = warn;
27693     ctxt->errCtxt = ctx;
27694     if (ctxt->pctxt != NULL)
27695 	xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
27696 }
27697 
27698 /**
27699  * xmlSchemaSetValidStructuredErrors:
27700  * @ctxt:  a schema validation context
27701  * @serror:  the structured error function
27702  * @ctx: the functions context
27703  *
27704  * Set the structured error callback
27705  */
27706 void
xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt,xmlStructuredErrorFunc serror,void * ctx)27707 xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt,
27708 				  xmlStructuredErrorFunc serror, void *ctx)
27709 {
27710     if (ctxt == NULL)
27711         return;
27712     ctxt->serror = serror;
27713     ctxt->error = NULL;
27714     ctxt->warning = NULL;
27715     ctxt->errCtxt = ctx;
27716     if (ctxt->pctxt != NULL)
27717 	xmlSchemaSetParserStructuredErrors(ctxt->pctxt, serror, ctx);
27718 }
27719 
27720 /**
27721  * xmlSchemaGetValidErrors:
27722  * @ctxt: a XML-Schema validation context
27723  * @err: the error function result
27724  * @warn: the warning function result
27725  * @ctx: the functions context result
27726  *
27727  * Get the error and warning callback information
27728  *
27729  * Returns -1 in case of error and 0 otherwise
27730  */
27731 int
xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,xmlSchemaValidityErrorFunc * err,xmlSchemaValidityWarningFunc * warn,void ** ctx)27732 xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
27733 			xmlSchemaValidityErrorFunc * err,
27734 			xmlSchemaValidityWarningFunc * warn, void **ctx)
27735 {
27736 	if (ctxt == NULL)
27737 		return (-1);
27738 	if (err != NULL)
27739 		*err = ctxt->error;
27740 	if (warn != NULL)
27741 		*warn = ctxt->warning;
27742 	if (ctx != NULL)
27743 		*ctx = ctxt->errCtxt;
27744 	return (0);
27745 }
27746 
27747 
27748 /**
27749  * xmlSchemaSetValidOptions:
27750  * @ctxt:	a schema validation context
27751  * @options: a combination of xmlSchemaValidOption
27752  *
27753  * Sets the options to be used during the validation.
27754  *
27755  * Returns 0 in case of success, -1 in case of an
27756  * API error.
27757  */
27758 int
xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,int options)27759 xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
27760 			 int options)
27761 
27762 {
27763     int i;
27764 
27765     if (ctxt == NULL)
27766 	return (-1);
27767     /*
27768     * WARNING: Change the start value if adding to the
27769     * xmlSchemaValidOption.
27770     * TODO: Is there an other, more easy to maintain,
27771     * way?
27772     */
27773     for (i = 1; i < (int) sizeof(int) * 8; i++) {
27774         if (options & 1<<i)
27775 	    return (-1);
27776     }
27777     ctxt->options = options;
27778     return (0);
27779 }
27780 
27781 /**
27782  * xmlSchemaValidCtxtGetOptions:
27783  * @ctxt: a schema validation context
27784  *
27785  * Get the validation context options.
27786  *
27787  * Returns the option combination or -1 on error.
27788  */
27789 int
xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)27790 xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
27791 
27792 {
27793     if (ctxt == NULL)
27794 	return (-1);
27795     else
27796 	return (ctxt->options);
27797 }
27798 
27799 static int
xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)27800 xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)
27801 {
27802     xmlAttrPtr attr;
27803     int ret = 0;
27804     xmlSchemaNodeInfoPtr ielem = NULL;
27805     xmlNodePtr node, valRoot;
27806     const xmlChar *nsName;
27807 
27808     /* DOC VAL TODO: Move this to the start function. */
27809     if (vctxt->validationRoot != NULL)
27810         valRoot = vctxt->validationRoot;
27811     else
27812 	valRoot = xmlDocGetRootElement(vctxt->doc);
27813     if (valRoot == NULL) {
27814 	/* VAL TODO: Error code? */
27815 	VERROR(1, NULL, "The document has no document element");
27816 	return (1);
27817     }
27818     vctxt->depth = -1;
27819     vctxt->validationRoot = valRoot;
27820     node = valRoot;
27821     while (node != NULL) {
27822 	if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27823 	    goto next_sibling;
27824 	if (node->type == XML_ELEMENT_NODE) {
27825 
27826 	    /*
27827 	    * Init the node-info.
27828 	    */
27829 	    vctxt->depth++;
27830 	    if (xmlSchemaValidatorPushElem(vctxt) == -1)
27831 		goto internal_error;
27832 	    ielem = vctxt->inode;
27833 	    ielem->node = node;
27834 	    ielem->nodeLine = node->line;
27835 	    ielem->localName = node->name;
27836 	    if (node->ns != NULL)
27837 		ielem->nsName = node->ns->href;
27838 	    ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27839 	    /*
27840 	    * Register attributes.
27841 	    * DOC VAL TODO: We do not register namespace declaration
27842 	    * attributes yet.
27843 	    */
27844 	    vctxt->nbAttrInfos = 0;
27845 	    if (node->properties != NULL) {
27846 		attr = node->properties;
27847 		do {
27848 		    if (attr->ns != NULL)
27849 			nsName = attr->ns->href;
27850 		    else
27851 			nsName = NULL;
27852 		    ret = xmlSchemaValidatorPushAttribute(vctxt,
27853 			(xmlNodePtr) attr,
27854 			/*
27855 			* Note that we give it the line number of the
27856 			* parent element.
27857 			*/
27858 			ielem->nodeLine,
27859 			attr->name, nsName, 0,
27860 			xmlNodeListGetString(attr->doc, attr->children, 1), 1);
27861 		    if (ret == -1) {
27862 			VERROR_INT("xmlSchemaDocWalk",
27863 			    "calling xmlSchemaValidatorPushAttribute()");
27864 			goto internal_error;
27865 		    }
27866 		    attr = attr->next;
27867 		} while (attr);
27868 	    }
27869 	    /*
27870 	    * Validate the element.
27871 	    */
27872 	    ret = xmlSchemaValidateElem(vctxt);
27873 	    if (ret != 0) {
27874 		if (ret == -1) {
27875 		    VERROR_INT("xmlSchemaDocWalk",
27876 			"calling xmlSchemaValidateElem()");
27877 		    goto internal_error;
27878 		}
27879 		/*
27880 		* Don't stop validation; just skip the content
27881 		* of this element.
27882 		*/
27883 		goto leave_node;
27884 	    }
27885 	    if ((vctxt->skipDepth != -1) &&
27886 		(vctxt->depth >= vctxt->skipDepth))
27887 		goto leave_node;
27888 	} else if ((node->type == XML_TEXT_NODE) ||
27889 	    (node->type == XML_CDATA_SECTION_NODE)) {
27890 	    /*
27891 	    * Process character content.
27892 	    */
27893 	    if ((ielem != NULL) && (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY))
27894 		ielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27895 	    ret = xmlSchemaVPushText(vctxt, node->type, node->content,
27896 		-1, XML_SCHEMA_PUSH_TEXT_PERSIST, NULL);
27897 	    if (ret < 0) {
27898 		VERROR_INT("xmlSchemaVDocWalk",
27899 		    "calling xmlSchemaVPushText()");
27900 		goto internal_error;
27901 	    }
27902 	    /*
27903 	    * DOC VAL TODO: Should we skip further validation of the
27904 	    * element content here?
27905 	    */
27906 	} else if ((node->type == XML_ENTITY_NODE) ||
27907 	    (node->type == XML_ENTITY_REF_NODE)) {
27908 	    /*
27909 	    * DOC VAL TODO: What to do with entities?
27910 	    */
27911 	    VERROR_INT("xmlSchemaVDocWalk",
27912 		"there is at least one entity reference in the node-tree "
27913 		"currently being validated. Processing of entities with "
27914 		"this XML Schema processor is not supported (yet). Please "
27915 		"substitute entities before validation.");
27916 	    goto internal_error;
27917 	} else {
27918 	    goto leave_node;
27919 	    /*
27920 	    * DOC VAL TODO: XInclude nodes, etc.
27921 	    */
27922 	}
27923 	/*
27924 	* Walk the doc.
27925 	*/
27926 	if (node->children != NULL) {
27927 	    node = node->children;
27928 	    continue;
27929 	}
27930 leave_node:
27931 	if (node->type == XML_ELEMENT_NODE) {
27932 	    /*
27933 	    * Leaving the scope of an element.
27934 	    */
27935 	    if (node != vctxt->inode->node) {
27936 		VERROR_INT("xmlSchemaVDocWalk",
27937 		    "element position mismatch");
27938 		goto internal_error;
27939 	    }
27940 	    ret = xmlSchemaValidatorPopElem(vctxt);
27941 	    if (ret != 0) {
27942 		if (ret < 0) {
27943 		    VERROR_INT("xmlSchemaVDocWalk",
27944 			"calling xmlSchemaValidatorPopElem()");
27945 		    goto internal_error;
27946 		}
27947 	    }
27948 	    if (node == valRoot)
27949 		goto exit;
27950 	}
27951 next_sibling:
27952 	if (node->next != NULL)
27953 	    node = node->next;
27954 	else {
27955 	    node = node->parent;
27956 	    goto leave_node;
27957 	}
27958     }
27959 
27960 exit:
27961     return (ret);
27962 internal_error:
27963     return (-1);
27964 }
27965 
27966 static int
xmlSchemaPreRun(xmlSchemaValidCtxtPtr vctxt)27967 xmlSchemaPreRun(xmlSchemaValidCtxtPtr vctxt) {
27968     /*
27969     * Some initialization.
27970     */
27971     vctxt->err = 0;
27972     vctxt->nberrors = 0;
27973     vctxt->depth = -1;
27974     vctxt->skipDepth = -1;
27975     vctxt->hasKeyrefs = 0;
27976 #ifdef ENABLE_IDC_NODE_TABLES_TEST
27977     vctxt->createIDCNodeTables = 1;
27978 #else
27979     vctxt->createIDCNodeTables = 0;
27980 #endif
27981     /*
27982     * Create a schema + parser if necessary.
27983     */
27984     if (vctxt->schema == NULL) {
27985 	xmlSchemaParserCtxtPtr pctxt;
27986 
27987 	vctxt->xsiAssemble = 1;
27988 	/*
27989 	* If not schema was given then we will create a schema
27990 	* dynamically using XSI schema locations.
27991 	*
27992 	* Create the schema parser context.
27993 	*/
27994 	if ((vctxt->pctxt == NULL) &&
27995 	   (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
27996 	   return (-1);
27997 	pctxt = vctxt->pctxt;
27998 	pctxt->xsiAssemble = 1;
27999 	/*
28000 	* Create the schema.
28001 	*/
28002 	vctxt->schema = xmlSchemaNewSchema(pctxt);
28003 	if (vctxt->schema == NULL)
28004 	    return (-1);
28005 	/*
28006 	* Create the schema construction context.
28007 	*/
28008 	pctxt->constructor = xmlSchemaConstructionCtxtCreate(pctxt->dict);
28009 	if (pctxt->constructor == NULL)
28010 	    return(-1);
28011 	pctxt->constructor->mainSchema = vctxt->schema;
28012 	/*
28013 	* Take ownership of the constructor to be able to free it.
28014 	*/
28015 	pctxt->ownsConstructor = 1;
28016     }
28017     /*
28018     * Augment the IDC definitions for the main schema and all imported ones
28019     * NOTE: main schema if the first in the imported list
28020     */
28021     xmlHashScan(vctxt->schema->schemasImports, xmlSchemaAugmentImportedIDC,
28022                 vctxt);
28023 
28024     return(0);
28025 }
28026 
28027 static void
xmlSchemaPostRun(xmlSchemaValidCtxtPtr vctxt)28028 xmlSchemaPostRun(xmlSchemaValidCtxtPtr vctxt) {
28029     if (vctxt->xsiAssemble) {
28030 	if (vctxt->schema != NULL) {
28031 	    xmlSchemaFree(vctxt->schema);
28032 	    vctxt->schema = NULL;
28033 	}
28034     }
28035     xmlSchemaClearValidCtxt(vctxt);
28036 }
28037 
28038 static int
xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt)28039 xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt)
28040 {
28041     int ret = 0;
28042 
28043     if (xmlSchemaPreRun(vctxt) < 0)
28044         return(-1);
28045 
28046     if (vctxt->doc != NULL) {
28047 	/*
28048 	 * Tree validation.
28049 	 */
28050 	ret = xmlSchemaVDocWalk(vctxt);
28051 #ifdef LIBXML_READER_ENABLED
28052     } else if (vctxt->reader != NULL) {
28053 	/*
28054 	 * XML Reader validation.
28055 	 */
28056 #ifdef XML_SCHEMA_READER_ENABLED
28057 	ret = xmlSchemaVReaderWalk(vctxt);
28058 #endif
28059 #endif
28060     } else if ((vctxt->sax != NULL) && (vctxt->parserCtxt != NULL)) {
28061 	/*
28062 	 * SAX validation.
28063 	 */
28064 	ret = xmlParseDocument(vctxt->parserCtxt);
28065     } else {
28066 	VERROR_INT("xmlSchemaVStart",
28067 	    "no instance to validate");
28068 	ret = -1;
28069     }
28070 
28071     xmlSchemaPostRun(vctxt);
28072     if (ret == 0)
28073 	ret = vctxt->err;
28074     return (ret);
28075 }
28076 
28077 /**
28078  * xmlSchemaValidateOneElement:
28079  * @ctxt:  a schema validation context
28080  * @elem:  an element node
28081  *
28082  * Validate a branch of a tree, starting with the given @elem.
28083  *
28084  * Returns 0 if the element and its subtree is valid, a positive error
28085  * code number otherwise and -1 in case of an internal or API error.
28086  */
28087 int
xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt,xmlNodePtr elem)28088 xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
28089 {
28090     if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
28091 	return (-1);
28092 
28093     if (ctxt->schema == NULL)
28094 	return (-1);
28095 
28096     ctxt->doc = elem->doc;
28097     ctxt->node = elem;
28098     ctxt->validationRoot = elem;
28099     return(xmlSchemaVStart(ctxt));
28100 }
28101 
28102 /**
28103  * xmlSchemaValidateDoc:
28104  * @ctxt:  a schema validation context
28105  * @doc:  a parsed document tree
28106  *
28107  * Validate a document tree in memory.
28108  *
28109  * Returns 0 if the document is schemas valid, a positive error code
28110  *     number otherwise and -1 in case of internal or API error.
28111  */
28112 int
xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt,xmlDocPtr doc)28113 xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
28114 {
28115     if ((ctxt == NULL) || (doc == NULL))
28116         return (-1);
28117 
28118     ctxt->doc = doc;
28119     ctxt->node = xmlDocGetRootElement(doc);
28120     if (ctxt->node == NULL) {
28121         xmlSchemaCustomErr(ACTXT_CAST ctxt,
28122 	    XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
28123 	    (xmlNodePtr) doc, NULL,
28124 	    "The document has no document element", NULL, NULL);
28125         return (ctxt->err);
28126     }
28127     ctxt->validationRoot = ctxt->node;
28128     return (xmlSchemaVStart(ctxt));
28129 }
28130 
28131 
28132 /************************************************************************
28133  *									*
28134  *		Function and data for SAX streaming API			*
28135  *									*
28136  ************************************************************************/
28137 typedef struct _xmlSchemaSplitSAXData xmlSchemaSplitSAXData;
28138 typedef xmlSchemaSplitSAXData *xmlSchemaSplitSAXDataPtr;
28139 
28140 struct _xmlSchemaSplitSAXData {
28141     xmlSAXHandlerPtr      user_sax;
28142     void                 *user_data;
28143     xmlSchemaValidCtxtPtr ctxt;
28144     xmlSAXHandlerPtr      schemas_sax;
28145 };
28146 
28147 #define XML_SAX_PLUG_MAGIC 0xdc43ba21
28148 
28149 struct _xmlSchemaSAXPlug {
28150     unsigned int magic;
28151 
28152     /* the original callbacks information */
28153     xmlSAXHandlerPtr     *user_sax_ptr;
28154     xmlSAXHandlerPtr      user_sax;
28155     void                **user_data_ptr;
28156     void                 *user_data;
28157 
28158     /* the block plugged back and validation information */
28159     xmlSAXHandler         schemas_sax;
28160     xmlSchemaValidCtxtPtr ctxt;
28161 };
28162 
28163 /* All those functions just bounces to the user provided SAX handlers */
28164 static void
internalSubsetSplit(void * ctx,const xmlChar * name,const xmlChar * ExternalID,const xmlChar * SystemID)28165 internalSubsetSplit(void *ctx, const xmlChar *name,
28166 	       const xmlChar *ExternalID, const xmlChar *SystemID)
28167 {
28168     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28169     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28170         (ctxt->user_sax->internalSubset != NULL))
28171 	ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
28172 	                               SystemID);
28173 }
28174 
28175 static int
isStandaloneSplit(void * ctx)28176 isStandaloneSplit(void *ctx)
28177 {
28178     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28179     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28180         (ctxt->user_sax->isStandalone != NULL))
28181 	return(ctxt->user_sax->isStandalone(ctxt->user_data));
28182     return(0);
28183 }
28184 
28185 static int
hasInternalSubsetSplit(void * ctx)28186 hasInternalSubsetSplit(void *ctx)
28187 {
28188     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28189     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28190         (ctxt->user_sax->hasInternalSubset != NULL))
28191 	return(ctxt->user_sax->hasInternalSubset(ctxt->user_data));
28192     return(0);
28193 }
28194 
28195 static int
hasExternalSubsetSplit(void * ctx)28196 hasExternalSubsetSplit(void *ctx)
28197 {
28198     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28199     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28200         (ctxt->user_sax->hasExternalSubset != NULL))
28201 	return(ctxt->user_sax->hasExternalSubset(ctxt->user_data));
28202     return(0);
28203 }
28204 
28205 static void
externalSubsetSplit(void * ctx,const xmlChar * name,const xmlChar * ExternalID,const xmlChar * SystemID)28206 externalSubsetSplit(void *ctx, const xmlChar *name,
28207 	       const xmlChar *ExternalID, const xmlChar *SystemID)
28208 {
28209     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28210     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28211         (ctxt->user_sax->externalSubset != NULL))
28212 	ctxt->user_sax->externalSubset(ctxt->user_data, name, ExternalID,
28213 	                               SystemID);
28214 }
28215 
28216 static xmlParserInputPtr
resolveEntitySplit(void * ctx,const xmlChar * publicId,const xmlChar * systemId)28217 resolveEntitySplit(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
28218 {
28219     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28220     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28221         (ctxt->user_sax->resolveEntity != NULL))
28222 	return(ctxt->user_sax->resolveEntity(ctxt->user_data, publicId,
28223 	                                     systemId));
28224     return(NULL);
28225 }
28226 
28227 static xmlEntityPtr
getEntitySplit(void * ctx,const xmlChar * name)28228 getEntitySplit(void *ctx, const xmlChar *name)
28229 {
28230     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28231     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28232         (ctxt->user_sax->getEntity != NULL))
28233 	return(ctxt->user_sax->getEntity(ctxt->user_data, name));
28234     return(NULL);
28235 }
28236 
28237 static xmlEntityPtr
getParameterEntitySplit(void * ctx,const xmlChar * name)28238 getParameterEntitySplit(void *ctx, const xmlChar *name)
28239 {
28240     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28241     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28242         (ctxt->user_sax->getParameterEntity != NULL))
28243 	return(ctxt->user_sax->getParameterEntity(ctxt->user_data, name));
28244     return(NULL);
28245 }
28246 
28247 
28248 static void
entityDeclSplit(void * ctx,const xmlChar * name,int type,const xmlChar * publicId,const xmlChar * systemId,xmlChar * content)28249 entityDeclSplit(void *ctx, const xmlChar *name, int type,
28250           const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
28251 {
28252     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28253     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28254         (ctxt->user_sax->entityDecl != NULL))
28255 	ctxt->user_sax->entityDecl(ctxt->user_data, name, type, publicId,
28256 	                           systemId, content);
28257 }
28258 
28259 static void
attributeDeclSplit(void * ctx,const xmlChar * elem,const xmlChar * name,int type,int def,const xmlChar * defaultValue,xmlEnumerationPtr tree)28260 attributeDeclSplit(void *ctx, const xmlChar * elem,
28261                    const xmlChar * name, int type, int def,
28262                    const xmlChar * defaultValue, xmlEnumerationPtr tree)
28263 {
28264     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28265     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28266         (ctxt->user_sax->attributeDecl != NULL)) {
28267 	ctxt->user_sax->attributeDecl(ctxt->user_data, elem, name, type,
28268 	                              def, defaultValue, tree);
28269     } else {
28270 	xmlFreeEnumeration(tree);
28271     }
28272 }
28273 
28274 static void
elementDeclSplit(void * ctx,const xmlChar * name,int type,xmlElementContentPtr content)28275 elementDeclSplit(void *ctx, const xmlChar *name, int type,
28276 	    xmlElementContentPtr content)
28277 {
28278     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28279     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28280         (ctxt->user_sax->elementDecl != NULL))
28281 	ctxt->user_sax->elementDecl(ctxt->user_data, name, type, content);
28282 }
28283 
28284 static void
notationDeclSplit(void * ctx,const xmlChar * name,const xmlChar * publicId,const xmlChar * systemId)28285 notationDeclSplit(void *ctx, const xmlChar *name,
28286 	     const xmlChar *publicId, const xmlChar *systemId)
28287 {
28288     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28289     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28290         (ctxt->user_sax->notationDecl != NULL))
28291 	ctxt->user_sax->notationDecl(ctxt->user_data, name, publicId,
28292 	                             systemId);
28293 }
28294 
28295 static void
unparsedEntityDeclSplit(void * ctx,const xmlChar * name,const xmlChar * publicId,const xmlChar * systemId,const xmlChar * notationName)28296 unparsedEntityDeclSplit(void *ctx, const xmlChar *name,
28297 		   const xmlChar *publicId, const xmlChar *systemId,
28298 		   const xmlChar *notationName)
28299 {
28300     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28301     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28302         (ctxt->user_sax->unparsedEntityDecl != NULL))
28303 	ctxt->user_sax->unparsedEntityDecl(ctxt->user_data, name, publicId,
28304 	                                   systemId, notationName);
28305 }
28306 
28307 static void
setDocumentLocatorSplit(void * ctx,xmlSAXLocatorPtr loc)28308 setDocumentLocatorSplit(void *ctx, xmlSAXLocatorPtr loc)
28309 {
28310     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28311     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28312         (ctxt->user_sax->setDocumentLocator != NULL))
28313 	ctxt->user_sax->setDocumentLocator(ctxt->user_data, loc);
28314 }
28315 
28316 static void
startDocumentSplit(void * ctx)28317 startDocumentSplit(void *ctx)
28318 {
28319     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28320     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28321         (ctxt->user_sax->startDocument != NULL))
28322 	ctxt->user_sax->startDocument(ctxt->user_data);
28323 }
28324 
28325 static void
endDocumentSplit(void * ctx)28326 endDocumentSplit(void *ctx)
28327 {
28328     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28329     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28330         (ctxt->user_sax->endDocument != NULL))
28331 	ctxt->user_sax->endDocument(ctxt->user_data);
28332 }
28333 
28334 static void
processingInstructionSplit(void * ctx,const xmlChar * target,const xmlChar * data)28335 processingInstructionSplit(void *ctx, const xmlChar *target,
28336                       const xmlChar *data)
28337 {
28338     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28339     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28340         (ctxt->user_sax->processingInstruction != NULL))
28341 	ctxt->user_sax->processingInstruction(ctxt->user_data, target, data);
28342 }
28343 
28344 static void
commentSplit(void * ctx,const xmlChar * value)28345 commentSplit(void *ctx, const xmlChar *value)
28346 {
28347     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28348     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28349         (ctxt->user_sax->comment != NULL))
28350 	ctxt->user_sax->comment(ctxt->user_data, value);
28351 }
28352 
28353 /*
28354  * Varargs error callbacks to the user application, harder ...
28355  */
28356 
28357 static void
warningSplit(void * ctx,const char * msg ATTRIBUTE_UNUSED,...)28358 warningSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28359     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28360     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28361         (ctxt->user_sax->warning != NULL)) {
28362 	/* TODO */
28363     }
28364 }
28365 static void
errorSplit(void * ctx,const char * msg ATTRIBUTE_UNUSED,...)28366 errorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28367     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28368     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28369         (ctxt->user_sax->error != NULL)) {
28370 	/* TODO */
28371     }
28372 }
28373 static void
fatalErrorSplit(void * ctx,const char * msg ATTRIBUTE_UNUSED,...)28374 fatalErrorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28375     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28376     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28377         (ctxt->user_sax->fatalError != NULL)) {
28378 	/* TODO */
28379     }
28380 }
28381 
28382 /*
28383  * Those are function where both the user handler and the schemas handler
28384  * need to be called.
28385  */
28386 static void
charactersSplit(void * ctx,const xmlChar * ch,int len)28387 charactersSplit(void *ctx, const xmlChar *ch, int len)
28388 {
28389     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28390     if (ctxt == NULL)
28391         return;
28392     if ((ctxt->user_sax != NULL) && (ctxt->user_sax->characters != NULL))
28393 	ctxt->user_sax->characters(ctxt->user_data, ch, len);
28394     if (ctxt->ctxt != NULL)
28395 	xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
28396 }
28397 
28398 static void
ignorableWhitespaceSplit(void * ctx,const xmlChar * ch,int len)28399 ignorableWhitespaceSplit(void *ctx, const xmlChar *ch, int len)
28400 {
28401     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28402     if (ctxt == NULL)
28403         return;
28404     if ((ctxt->user_sax != NULL) &&
28405         (ctxt->user_sax->ignorableWhitespace != NULL))
28406 	ctxt->user_sax->ignorableWhitespace(ctxt->user_data, ch, len);
28407     if (ctxt->ctxt != NULL)
28408 	xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
28409 }
28410 
28411 static void
cdataBlockSplit(void * ctx,const xmlChar * value,int len)28412 cdataBlockSplit(void *ctx, const xmlChar *value, int len)
28413 {
28414     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28415     if (ctxt == NULL)
28416         return;
28417     if ((ctxt->user_sax != NULL) &&
28418         (ctxt->user_sax->cdataBlock != NULL))
28419 	ctxt->user_sax->cdataBlock(ctxt->user_data, value, len);
28420     if (ctxt->ctxt != NULL)
28421 	xmlSchemaSAXHandleCDataSection(ctxt->ctxt, value, len);
28422 }
28423 
28424 static void
referenceSplit(void * ctx,const xmlChar * name)28425 referenceSplit(void *ctx, const xmlChar *name)
28426 {
28427     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28428     if (ctxt == NULL)
28429         return;
28430     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28431         (ctxt->user_sax->reference != NULL))
28432 	ctxt->user_sax->reference(ctxt->user_data, name);
28433     if (ctxt->ctxt != NULL)
28434         xmlSchemaSAXHandleReference(ctxt->user_data, name);
28435 }
28436 
28437 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)28438 startElementNsSplit(void *ctx, const xmlChar * localname,
28439 		    const xmlChar * prefix, const xmlChar * URI,
28440 		    int nb_namespaces, const xmlChar ** namespaces,
28441 		    int nb_attributes, int nb_defaulted,
28442 		    const xmlChar ** attributes) {
28443     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28444     if (ctxt == NULL)
28445         return;
28446     if ((ctxt->user_sax != NULL) &&
28447         (ctxt->user_sax->startElementNs != NULL))
28448 	ctxt->user_sax->startElementNs(ctxt->user_data, localname, prefix,
28449 	                               URI, nb_namespaces, namespaces,
28450 				       nb_attributes, nb_defaulted,
28451 				       attributes);
28452     if (ctxt->ctxt != NULL)
28453 	xmlSchemaSAXHandleStartElementNs(ctxt->ctxt, localname, prefix,
28454 	                                 URI, nb_namespaces, namespaces,
28455 					 nb_attributes, nb_defaulted,
28456 					 attributes);
28457 }
28458 
28459 static void
endElementNsSplit(void * ctx,const xmlChar * localname,const xmlChar * prefix,const xmlChar * URI)28460 endElementNsSplit(void *ctx, const xmlChar * localname,
28461 		    const xmlChar * prefix, const xmlChar * URI) {
28462     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28463     if (ctxt == NULL)
28464         return;
28465     if ((ctxt->user_sax != NULL) &&
28466         (ctxt->user_sax->endElementNs != NULL))
28467 	ctxt->user_sax->endElementNs(ctxt->user_data, localname, prefix, URI);
28468     if (ctxt->ctxt != NULL)
28469 	xmlSchemaSAXHandleEndElementNs(ctxt->ctxt, localname, prefix, URI);
28470 }
28471 
28472 /**
28473  * xmlSchemaSAXPlug:
28474  * @ctxt:  a schema validation context
28475  * @sax:  a pointer to the original xmlSAXHandlerPtr
28476  * @user_data:  a pointer to the original SAX user data pointer
28477  *
28478  * Plug a SAX based validation layer in a SAX parsing event flow.
28479  * The original @saxptr and @dataptr data are replaced by new pointers
28480  * but the calls to the original will be maintained.
28481  *
28482  * Returns a pointer to a data structure needed to unplug the validation layer
28483  *         or NULL in case of errors.
28484  */
28485 xmlSchemaSAXPlugPtr
xmlSchemaSAXPlug(xmlSchemaValidCtxtPtr ctxt,xmlSAXHandlerPtr * sax,void ** user_data)28486 xmlSchemaSAXPlug(xmlSchemaValidCtxtPtr ctxt,
28487 		 xmlSAXHandlerPtr *sax, void **user_data)
28488 {
28489     xmlSchemaSAXPlugPtr ret;
28490     xmlSAXHandlerPtr old_sax;
28491 
28492     if ((ctxt == NULL) || (sax == NULL) || (user_data == NULL))
28493         return(NULL);
28494 
28495     /*
28496      * We only allow to plug into SAX2 event streams
28497      */
28498     old_sax = *sax;
28499     if ((old_sax != NULL) && (old_sax->initialized != XML_SAX2_MAGIC))
28500         return(NULL);
28501     if ((old_sax != NULL) &&
28502         (old_sax->startElementNs == NULL) && (old_sax->endElementNs == NULL) &&
28503         ((old_sax->startElement != NULL) || (old_sax->endElement != NULL)))
28504         return(NULL);
28505 
28506     /*
28507      * everything seems right allocate the local data needed for that layer
28508      */
28509     ret = (xmlSchemaSAXPlugPtr) xmlMalloc(sizeof(xmlSchemaSAXPlugStruct));
28510     if (ret == NULL) {
28511         return(NULL);
28512     }
28513     memset(ret, 0, sizeof(xmlSchemaSAXPlugStruct));
28514     ret->magic = XML_SAX_PLUG_MAGIC;
28515     ret->schemas_sax.initialized = XML_SAX2_MAGIC;
28516     ret->ctxt = ctxt;
28517     ret->user_sax_ptr = sax;
28518     ret->user_sax = old_sax;
28519     if (old_sax == NULL) {
28520         /*
28521 	 * go direct, no need for the split block and functions.
28522 	 */
28523 	ret->schemas_sax.startElementNs = xmlSchemaSAXHandleStartElementNs;
28524 	ret->schemas_sax.endElementNs = xmlSchemaSAXHandleEndElementNs;
28525 	/*
28526 	 * Note that we use the same text-function for both, to prevent
28527 	 * the parser from testing for ignorable whitespace.
28528 	 */
28529 	ret->schemas_sax.ignorableWhitespace = xmlSchemaSAXHandleText;
28530 	ret->schemas_sax.characters = xmlSchemaSAXHandleText;
28531 
28532 	ret->schemas_sax.cdataBlock = xmlSchemaSAXHandleCDataSection;
28533 	ret->schemas_sax.reference = xmlSchemaSAXHandleReference;
28534 
28535 	ret->user_data = ctxt;
28536 	*user_data = ctxt;
28537     } else {
28538        /*
28539         * for each callback unused by Schemas initialize it to the Split
28540 	* routine only if non NULL in the user block, this can speed up
28541 	* things at the SAX level.
28542 	*/
28543         if (old_sax->internalSubset != NULL)
28544             ret->schemas_sax.internalSubset = internalSubsetSplit;
28545         if (old_sax->isStandalone != NULL)
28546             ret->schemas_sax.isStandalone = isStandaloneSplit;
28547         if (old_sax->hasInternalSubset != NULL)
28548             ret->schemas_sax.hasInternalSubset = hasInternalSubsetSplit;
28549         if (old_sax->hasExternalSubset != NULL)
28550             ret->schemas_sax.hasExternalSubset = hasExternalSubsetSplit;
28551         if (old_sax->resolveEntity != NULL)
28552             ret->schemas_sax.resolveEntity = resolveEntitySplit;
28553         if (old_sax->getEntity != NULL)
28554             ret->schemas_sax.getEntity = getEntitySplit;
28555         if (old_sax->entityDecl != NULL)
28556             ret->schemas_sax.entityDecl = entityDeclSplit;
28557         if (old_sax->notationDecl != NULL)
28558             ret->schemas_sax.notationDecl = notationDeclSplit;
28559         if (old_sax->attributeDecl != NULL)
28560             ret->schemas_sax.attributeDecl = attributeDeclSplit;
28561         if (old_sax->elementDecl != NULL)
28562             ret->schemas_sax.elementDecl = elementDeclSplit;
28563         if (old_sax->unparsedEntityDecl != NULL)
28564             ret->schemas_sax.unparsedEntityDecl = unparsedEntityDeclSplit;
28565         if (old_sax->setDocumentLocator != NULL)
28566             ret->schemas_sax.setDocumentLocator = setDocumentLocatorSplit;
28567         if (old_sax->startDocument != NULL)
28568             ret->schemas_sax.startDocument = startDocumentSplit;
28569         if (old_sax->endDocument != NULL)
28570             ret->schemas_sax.endDocument = endDocumentSplit;
28571         if (old_sax->processingInstruction != NULL)
28572             ret->schemas_sax.processingInstruction = processingInstructionSplit;
28573         if (old_sax->comment != NULL)
28574             ret->schemas_sax.comment = commentSplit;
28575         if (old_sax->warning != NULL)
28576             ret->schemas_sax.warning = warningSplit;
28577         if (old_sax->error != NULL)
28578             ret->schemas_sax.error = errorSplit;
28579         if (old_sax->fatalError != NULL)
28580             ret->schemas_sax.fatalError = fatalErrorSplit;
28581         if (old_sax->getParameterEntity != NULL)
28582             ret->schemas_sax.getParameterEntity = getParameterEntitySplit;
28583         if (old_sax->externalSubset != NULL)
28584             ret->schemas_sax.externalSubset = externalSubsetSplit;
28585 
28586 	/*
28587 	 * the 6 schemas callback have to go to the splitter functions
28588 	 * Note that we use the same text-function for ignorableWhitespace
28589 	 * if possible, to prevent the parser from testing for ignorable
28590 	 * whitespace.
28591 	 */
28592         ret->schemas_sax.characters = charactersSplit;
28593 	if ((old_sax->ignorableWhitespace != NULL) &&
28594 	    (old_sax->ignorableWhitespace != old_sax->characters))
28595 	    ret->schemas_sax.ignorableWhitespace = ignorableWhitespaceSplit;
28596 	else
28597 	    ret->schemas_sax.ignorableWhitespace = charactersSplit;
28598         ret->schemas_sax.cdataBlock = cdataBlockSplit;
28599         ret->schemas_sax.reference = referenceSplit;
28600         ret->schemas_sax.startElementNs = startElementNsSplit;
28601         ret->schemas_sax.endElementNs = endElementNsSplit;
28602 
28603 	ret->user_data_ptr = user_data;
28604 	ret->user_data = *user_data;
28605 	*user_data = ret;
28606     }
28607 
28608     /*
28609      * plug the pointers back.
28610      */
28611     *sax = &(ret->schemas_sax);
28612     ctxt->sax = *sax;
28613     ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28614     xmlSchemaPreRun(ctxt);
28615     return(ret);
28616 }
28617 
28618 /**
28619  * xmlSchemaSAXUnplug:
28620  * @plug:  a data structure returned by xmlSchemaSAXPlug
28621  *
28622  * Unplug a SAX based validation layer in a SAX parsing event flow.
28623  * The original pointers used in the call are restored.
28624  *
28625  * Returns 0 in case of success and -1 in case of failure.
28626  */
28627 int
xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug)28628 xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug)
28629 {
28630     xmlSAXHandlerPtr *sax;
28631     void **user_data;
28632 
28633     if ((plug == NULL) || (plug->magic != XML_SAX_PLUG_MAGIC))
28634         return(-1);
28635     plug->magic = 0;
28636 
28637     xmlSchemaPostRun(plug->ctxt);
28638     /* restore the data */
28639     sax = plug->user_sax_ptr;
28640     *sax = plug->user_sax;
28641     if (plug->user_sax != NULL) {
28642 	user_data = plug->user_data_ptr;
28643 	*user_data = plug->user_data;
28644     }
28645 
28646     /* free and return */
28647     xmlFree(plug);
28648     return(0);
28649 }
28650 
28651 /**
28652  * xmlSchemaValidateSetLocator:
28653  * @vctxt: a schema validation context
28654  * @f: the locator function pointer
28655  * @ctxt: the locator context
28656  *
28657  * Allows to set a locator function to the validation context,
28658  * which will be used to provide file and line information since
28659  * those are not provided as part of the SAX validation flow
28660  * Setting @f to NULL disable the locator.
28661  */
28662 
28663 void
xmlSchemaValidateSetLocator(xmlSchemaValidCtxtPtr vctxt,xmlSchemaValidityLocatorFunc f,void * ctxt)28664 xmlSchemaValidateSetLocator(xmlSchemaValidCtxtPtr vctxt,
28665                             xmlSchemaValidityLocatorFunc f,
28666 			    void *ctxt)
28667 {
28668     if (vctxt == NULL) return;
28669     vctxt->locFunc = f;
28670     vctxt->locCtxt = ctxt;
28671 }
28672 
28673 /**
28674  * xmlSchemaValidateStreamLocator:
28675  * @ctx: the xmlTextReaderPtr used
28676  * @file: returned file information
28677  * @line: returned line information
28678  *
28679  * Internal locator function for the readers
28680  *
28681  * Returns 0 in case the Schema validation could be (de)activated and
28682  *         -1 in case of error.
28683  */
28684 static int
xmlSchemaValidateStreamLocator(void * ctx,const char ** file,unsigned long * line)28685 xmlSchemaValidateStreamLocator(void *ctx, const char **file,
28686                                unsigned long *line) {
28687     xmlParserCtxtPtr ctxt;
28688 
28689     if ((ctx == NULL) || ((file == NULL) && (line == NULL)))
28690         return(-1);
28691 
28692     if (file != NULL)
28693         *file = NULL;
28694     if (line != NULL)
28695         *line = 0;
28696 
28697     ctxt = (xmlParserCtxtPtr) ctx;
28698     if (ctxt->input != NULL) {
28699        if (file != NULL)
28700            *file = ctxt->input->filename;
28701        if (line != NULL)
28702            *line = ctxt->input->line;
28703        return(0);
28704     }
28705     return(-1);
28706 }
28707 
28708 /**
28709  * xmlSchemaValidateStreamInternal:
28710  * @ctxt:  a schema validation context
28711  * @pctxt:  a parser context
28712  *
28713  * Returns 0 if the document is schemas valid, a positive error code
28714  *     number otherwise and -1 in case of internal or API error.
28715  */
28716 static int
xmlSchemaValidateStreamInternal(xmlSchemaValidCtxtPtr ctxt,xmlParserCtxtPtr pctxt)28717 xmlSchemaValidateStreamInternal(xmlSchemaValidCtxtPtr ctxt,
28718                                  xmlParserCtxtPtr pctxt) {
28719     xmlSchemaSAXPlugPtr plug = NULL;
28720     int ret;
28721 
28722     pctxt->linenumbers = 1;
28723     xmlSchemaValidateSetLocator(ctxt, xmlSchemaValidateStreamLocator, pctxt);
28724 
28725     ctxt->parserCtxt = pctxt;
28726     ctxt->input = pctxt->input->buf;
28727 
28728     /*
28729      * Plug the validation and launch the parsing
28730      */
28731     plug = xmlSchemaSAXPlug(ctxt, &(pctxt->sax), &(pctxt->userData));
28732     if (plug == NULL) {
28733         ret = -1;
28734 	goto done;
28735     }
28736     ctxt->input = pctxt->input->buf;
28737     ctxt->sax = pctxt->sax;
28738     ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28739     ret = xmlSchemaVStart(ctxt);
28740 
28741     if ((ret == 0) && (! ctxt->parserCtxt->wellFormed)) {
28742 	ret = ctxt->parserCtxt->errNo;
28743 	if (ret == 0)
28744 	    ret = 1;
28745     }
28746 
28747 done:
28748     ctxt->parserCtxt = NULL;
28749     ctxt->sax = NULL;
28750     ctxt->input = NULL;
28751     if (plug != NULL) {
28752         xmlSchemaSAXUnplug(plug);
28753     }
28754     return (ret);
28755 }
28756 
28757 /**
28758  * xmlSchemaValidateStream:
28759  * @ctxt:  a schema validation context
28760  * @input:  the input to use for reading the data
28761  * @enc:  an optional encoding information
28762  * @sax:  a SAX handler for the resulting events
28763  * @user_data:  the context to provide to the SAX handler.
28764  *
28765  * Validate an input based on a flow of SAX event from the parser
28766  * and forward the events to the @sax handler with the provided @user_data
28767  * the user provided @sax handler must be a SAX2 one.
28768  *
28769  * Returns 0 if the document is schemas valid, a positive error code
28770  *     number otherwise and -1 in case of internal or API error.
28771  */
28772 int
xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,xmlParserInputBufferPtr input,xmlCharEncoding enc,xmlSAXHandlerPtr sax,void * user_data)28773 xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
28774                         xmlParserInputBufferPtr input, xmlCharEncoding enc,
28775                         xmlSAXHandlerPtr sax, void *user_data)
28776 {
28777     xmlParserCtxtPtr pctxt = NULL;
28778     xmlParserInputPtr inputStream = NULL;
28779     int ret;
28780 
28781     if ((ctxt == NULL) || (input == NULL))
28782         return (-1);
28783 
28784     /*
28785      * prepare the parser
28786      */
28787     if (sax != NULL) {
28788         pctxt = xmlNewSAXParserCtxt(sax, user_data);
28789         if (pctxt == NULL)
28790             return (-1);
28791     } else {
28792         pctxt = xmlNewParserCtxt();
28793         if (pctxt == NULL)
28794             return (-1);
28795         /* We really want pctxt->sax to be NULL here. */
28796         xmlFree(pctxt->sax);
28797         pctxt->sax = NULL;
28798     }
28799 #if 0
28800     if (options)
28801         xmlCtxtUseOptions(pctxt, options);
28802 #endif
28803 
28804     inputStream = xmlNewIOInputStream(pctxt, input, enc);;
28805     if (inputStream == NULL) {
28806         ret = -1;
28807 	goto done;
28808     }
28809     if (inputPush(pctxt, inputStream) < 0) {
28810         xmlFreeInputStream(inputStream);
28811         ret = -1;
28812         goto done;
28813     }
28814 
28815     ctxt->enc = enc;
28816 
28817     ret = xmlSchemaValidateStreamInternal(ctxt, pctxt);
28818 
28819 done:
28820     /* cleanup */
28821     if (pctxt != NULL) {
28822 	xmlFreeParserCtxt(pctxt);
28823     }
28824     return (ret);
28825 }
28826 
28827 /**
28828  * xmlSchemaValidateFile:
28829  * @ctxt: a schema validation context
28830  * @filename: the URI of the instance
28831  * @options: a future set of options, currently unused
28832  *
28833  * Do a schemas validation of the given resource, it will use the
28834  * SAX streamable validation internally.
28835  *
28836  * Returns 0 if the document is valid, a positive error code
28837  *     number otherwise and -1 in case of an internal or API error.
28838  */
28839 int
xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt,const char * filename,int options ATTRIBUTE_UNUSED)28840 xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt,
28841                       const char * filename,
28842 		      int options ATTRIBUTE_UNUSED)
28843 {
28844     int ret;
28845     xmlParserCtxtPtr pctxt = NULL;
28846 
28847     if ((ctxt == NULL) || (filename == NULL))
28848         return (-1);
28849 
28850     pctxt = xmlCreateURLParserCtxt(filename, 0);
28851     if (pctxt == NULL)
28852 	return (-1);
28853     /* We really want pctxt->sax to be NULL here. */
28854     xmlFree(pctxt->sax);
28855     pctxt->sax = NULL;
28856     ret = xmlSchemaValidateStreamInternal(ctxt, pctxt);
28857     xmlFreeParserCtxt(pctxt);
28858     return (ret);
28859 }
28860 
28861 /**
28862  * xmlSchemaValidCtxtGetParserCtxt:
28863  * @ctxt: a schema validation context
28864  *
28865  * allow access to the parser context of the schema validation context
28866  *
28867  * Returns the parser context of the schema validation context or NULL
28868  *         in case of error.
28869  */
28870 xmlParserCtxtPtr
xmlSchemaValidCtxtGetParserCtxt(xmlSchemaValidCtxtPtr ctxt)28871 xmlSchemaValidCtxtGetParserCtxt(xmlSchemaValidCtxtPtr ctxt)
28872 {
28873     if (ctxt == NULL)
28874         return(NULL);
28875     return (ctxt->parserCtxt);
28876 }
28877 
28878 #endif /* LIBXML_SCHEMAS_ENABLED */
28879