1 /* libxml2 - Library for parsing XML documents
2  * Copyright (C) 2006-2019 Free Software Foundation, Inc.
3  *
4  * This file is not part of the GNU gettext program, but is used with
5  * GNU gettext.
6  *
7  * The original copyright notice is as follows:
8  */
9 
10 /*
11  * Copyright (C) 1998-2012 Daniel Veillard.  All Rights Reserved.
12  *
13  * Permission is hereby granted, free of charge, to any person obtaining a copy
14  * of this software and associated documentation files (the "Software"), to deal
15  * in the Software without restriction, including without limitation the rights
16  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17  * copies of the Software, and to permit persons to whom the Software is fur-
18  * nished to do so, subject to the following conditions:
19  *
20  * The above copyright notice and this permission notice shall be included in
21  * all copies or substantial portions of the Software.
22  *
23  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
25  * NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
26  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
29  * THE SOFTWARE.
30  *
31  * Daniel Veillard <veillard@redhat.com>
32  */
33 
34 /*
35  * schemas.c : implementation of the XML Schema handling and
36  *             schema validity checking
37  */
38 
39 /*
40  * TODO:
41  *   - when types are redefined in includes, check that all
42  *     types in the redef list are equal
43  *     -> need a type equality operation.
44  *   - if we don't intend to use the schema for schemas, we
45  *     need to validate all schema attributes (ref, type, name)
46  *     against their types.
47  *   - Eliminate item creation for: ??
48  *
49  * URGENT TODO:
50  *   - For xsi-driven schema acquisition, augment the IDCs after every
51  *     acquisition episode (xmlSchemaAugmentIDC).
52  *
53  * NOTES:
54  *   - Elimated item creation for: <restriction>, <extension>,
55  *     <simpleContent>, <complexContent>, <list>, <union>
56  *
57  * PROBLEMS:
58  *   - http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0337.html
59  *     IDC XPath expression and chameleon includes: the targetNamespace is changed, so
60  *     XPath will have trouble to resolve to this namespace, since not known.
61  *
62  *
63  * CONSTRAINTS:
64  *
65  * Schema Component Constraint:
66  *   All Group Limited (cos-all-limited)
67  *   Status: complete
68  *   (1.2)
69  *     In xmlSchemaGroupDefReferenceTermFixup() and
70  *   (2)
71  *     In xmlSchemaParseModelGroup()
72  *     TODO: Actually this should go to component-level checks,
73  *     but is done here due to performance. Move it to an other layer
74  *     is schema construction via an API is implemented.
75  */
76 
77 /* To avoid EBCDIC trouble when parsing on zOS */
78 #if defined(__MVS__)
79 #pragma convert("ISO8859-1")
80 #endif
81 
82 #define IN_LIBXML
83 #include "libxml.h"
84 
85 #ifdef LIBXML_SCHEMAS_ENABLED
86 
87 #include <string.h>
88 #include <libxml/xmlmemory.h>
89 #include <libxml/parser.h>
90 #include <libxml/parserInternals.h>
91 #include <libxml/hash.h>
92 #include <libxml/uri.h>
93 #include <libxml/xmlschemas.h>
94 #include <libxml/schemasInternals.h>
95 #include <libxml/xmlschemastypes.h>
96 #include <libxml/xmlautomata.h>
97 #include <libxml/xmlregexp.h>
98 #include <libxml/dict.h>
99 #include <libxml/encoding.h>
100 #include <libxml/xmlIO.h>
101 #ifdef LIBXML_PATTERN_ENABLED
102 #include <libxml/pattern.h>
103 #endif
104 #ifdef LIBXML_READER_ENABLED
105 #include <libxml/xmlreader.h>
106 #endif
107 
108 /* #define DEBUG 1 */
109 
110 /* #define DEBUG_CONTENT 1 */
111 
112 /* #define DEBUG_TYPE 1 */
113 
114 /* #define DEBUG_CONTENT_REGEXP 1 */
115 
116 /* #define DEBUG_AUTOMATA 1 */
117 
118 /* #define DEBUG_IDC */
119 
120 /* #define DEBUG_IDC_NODE_TABLE */
121 
122 /* #define WXS_ELEM_DECL_CONS_ENABLED */
123 
124 #ifdef DEBUG_IDC
125  #ifndef DEBUG_IDC_NODE_TABLE
126   #define DEBUG_IDC_NODE_TABLE
127  #endif
128 #endif
129 
130 /* #define ENABLE_PARTICLE_RESTRICTION 1 */
131 
132 #define ENABLE_REDEFINE
133 
134 /* #define ENABLE_NAMED_LOCALS */
135 
136 /* #define ENABLE_IDC_NODE_TABLES_TEST */
137 
138 #define DUMP_CONTENT_MODEL
139 
140 #ifdef LIBXML_READER_ENABLED
141 /* #define XML_SCHEMA_READER_ENABLED */
142 #endif
143 
144 #define UNBOUNDED (1 << 30)
145 #define TODO								\
146     xmlGenericError(xmlGenericErrorContext,				\
147 	    "Unimplemented block at %s:%d\n",				\
148             __FILE__, __LINE__);
149 
150 #define XML_SCHEMAS_NO_NAMESPACE (const xmlChar *) "##"
151 
152 /*
153  * The XML Schemas namespaces
154  */
155 static const xmlChar *xmlSchemaNs = (const xmlChar *)
156     "http://www.w3.org/2001/XMLSchema";
157 
158 static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
159     "http://www.w3.org/2001/XMLSchema-instance";
160 
161 static const xmlChar *xmlNamespaceNs = (const xmlChar *)
162     "http://www.w3.org/2000/xmlns/";
163 
164 /*
165 * Come casting macros.
166 */
167 #define ACTXT_CAST (xmlSchemaAbstractCtxtPtr)
168 #define PCTXT_CAST (xmlSchemaParserCtxtPtr)
169 #define VCTXT_CAST (xmlSchemaValidCtxtPtr)
170 #define WXS_BASIC_CAST (xmlSchemaBasicItemPtr)
171 #define WXS_TREE_CAST (xmlSchemaTreeItemPtr)
172 #define WXS_PTC_CAST (xmlSchemaParticlePtr)
173 #define WXS_TYPE_CAST (xmlSchemaTypePtr)
174 #define WXS_ELEM_CAST (xmlSchemaElementPtr)
175 #define WXS_ATTR_GROUP_CAST (xmlSchemaAttributeGroupPtr)
176 #define WXS_ATTR_CAST (xmlSchemaAttributePtr)
177 #define WXS_ATTR_USE_CAST (xmlSchemaAttributeUsePtr)
178 #define WXS_ATTR_PROHIB_CAST (xmlSchemaAttributeUseProhibPtr)
179 #define WXS_MODEL_GROUPDEF_CAST (xmlSchemaModelGroupDefPtr)
180 #define WXS_MODEL_GROUP_CAST (xmlSchemaModelGroupPtr)
181 #define WXS_IDC_CAST (xmlSchemaIDCPtr)
182 #define WXS_QNAME_CAST (xmlSchemaQNameRefPtr)
183 #define WXS_LIST_CAST (xmlSchemaItemListPtr)
184 
185 /*
186 * Macros to query common properties of components.
187 */
188 #define WXS_ITEM_NODE(i) xmlSchemaGetComponentNode(WXS_BASIC_CAST (i))
189 
190 #define WXS_ITEM_TYPE_NAME(i) xmlSchemaGetComponentTypeStr(WXS_BASIC_CAST (i))
191 /*
192 * Macros for element declarations.
193 */
194 #define WXS_ELEM_TYPEDEF(e) (e)->subtypes
195 
196 #define WXS_SUBST_HEAD(item) (item)->refDecl
197 /*
198 * Macros for attribute declarations.
199 */
200 #define WXS_ATTR_TYPEDEF(a) (a)->subtypes
201 /*
202 * Macros for attribute uses.
203 */
204 #define WXS_ATTRUSE_DECL(au) (WXS_ATTR_USE_CAST (au))->attrDecl
205 
206 #define WXS_ATTRUSE_TYPEDEF(au) WXS_ATTR_TYPEDEF(WXS_ATTRUSE_DECL( WXS_ATTR_USE_CAST au))
207 
208 #define WXS_ATTRUSE_DECL_NAME(au) (WXS_ATTRUSE_DECL(au))->name
209 
210 #define WXS_ATTRUSE_DECL_TNS(au) (WXS_ATTRUSE_DECL(au))->targetNamespace
211 /*
212 * Macros for attribute groups.
213 */
214 #define WXS_ATTR_GROUP_HAS_REFS(ag) ((WXS_ATTR_GROUP_CAST (ag))->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS)
215 #define WXS_ATTR_GROUP_EXPANDED(ag) ((WXS_ATTR_GROUP_CAST (ag))->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED)
216 /*
217 * Macros for particles.
218 */
219 #define WXS_PARTICLE(p) WXS_PTC_CAST (p)
220 
221 #define WXS_PARTICLE_TERM(p) (WXS_PARTICLE(p))->children
222 
223 #define WXS_PARTICLE_TERM_AS_ELEM(p) (WXS_ELEM_CAST WXS_PARTICLE_TERM(p))
224 
225 #define WXS_PARTICLE_MODEL(p) WXS_MODEL_GROUP_CAST WXS_PARTICLE(p)->children
226 /*
227 * Macros for model groups definitions.
228 */
229 #define WXS_MODELGROUPDEF_MODEL(mgd) (WXS_MODEL_GROUP_CAST (mgd))->children
230 /*
231 * Macros for model groups.
232 */
233 #define WXS_IS_MODEL_GROUP(i) \
234     (((i)->type == XML_SCHEMA_TYPE_SEQUENCE) || \
235      ((i)->type == XML_SCHEMA_TYPE_CHOICE) || \
236      ((i)->type == XML_SCHEMA_TYPE_ALL))
237 
238 #define WXS_MODELGROUP_PARTICLE(mg) WXS_PTC_CAST (mg)->children
239 /*
240 * Macros for schema buckets.
241 */
242 #define WXS_IS_BUCKET_INCREDEF(t) (((t) == XML_SCHEMA_SCHEMA_INCLUDE) || \
243     ((t) == XML_SCHEMA_SCHEMA_REDEFINE))
244 
245 #define WXS_IS_BUCKET_IMPMAIN(t) (((t) == XML_SCHEMA_SCHEMA_MAIN) || \
246     ((t) == XML_SCHEMA_SCHEMA_IMPORT))
247 
248 #define WXS_IMPBUCKET(b) ((xmlSchemaImportPtr) (b))
249 
250 #define WXS_INCBUCKET(b) ((xmlSchemaIncludePtr) (b))
251 /*
252 * Macros for complex/simple types.
253 */
254 #define WXS_IS_ANYTYPE(i) \
255      (( (i)->type == XML_SCHEMA_TYPE_BASIC) && \
256       ( (WXS_TYPE_CAST (i))->builtInType == XML_SCHEMAS_ANYTYPE))
257 
258 #define WXS_IS_COMPLEX(i) \
259     (((i)->type == XML_SCHEMA_TYPE_COMPLEX) || \
260      ((i)->builtInType == XML_SCHEMAS_ANYTYPE))
261 
262 #define WXS_IS_SIMPLE(item) \
263     ((item->type == XML_SCHEMA_TYPE_SIMPLE) || \
264      ((item->type == XML_SCHEMA_TYPE_BASIC) && \
265       (item->builtInType != XML_SCHEMAS_ANYTYPE)))
266 
267 #define WXS_IS_ANY_SIMPLE_TYPE(i) \
268     (((i)->type == XML_SCHEMA_TYPE_BASIC) && \
269       ((i)->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
270 
271 #define WXS_IS_RESTRICTION(t) \
272     ((t)->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)
273 
274 #define WXS_IS_EXTENSION(t) \
275     ((t)->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)
276 
277 #define WXS_IS_TYPE_NOT_FIXED(i) \
278     (((i)->type != XML_SCHEMA_TYPE_BASIC) && \
279      (((i)->flags & XML_SCHEMAS_TYPE_INTERNAL_RESOLVED) == 0))
280 
281 #define WXS_IS_TYPE_NOT_FIXED_1(item) \
282     (((item)->type != XML_SCHEMA_TYPE_BASIC) && \
283      (((item)->flags & XML_SCHEMAS_TYPE_FIXUP_1) == 0))
284 
285 #define WXS_TYPE_IS_GLOBAL(t) ((t)->flags & XML_SCHEMAS_TYPE_GLOBAL)
286 
287 #define WXS_TYPE_IS_LOCAL(t) (((t)->flags & XML_SCHEMAS_TYPE_GLOBAL) == 0)
288 /*
289 * Macros for exclusively for complex types.
290 */
291 #define WXS_HAS_COMPLEX_CONTENT(item) \
292     ((item->contentType == XML_SCHEMA_CONTENT_MIXED) || \
293      (item->contentType == XML_SCHEMA_CONTENT_EMPTY) || \
294      (item->contentType == XML_SCHEMA_CONTENT_ELEMENTS))
295 
296 #define WXS_HAS_SIMPLE_CONTENT(item) \
297     ((item->contentType == XML_SCHEMA_CONTENT_SIMPLE) || \
298      (item->contentType == XML_SCHEMA_CONTENT_BASIC))
299 
300 #define WXS_HAS_MIXED_CONTENT(item) \
301     (item->contentType == XML_SCHEMA_CONTENT_MIXED)
302 
303 #define WXS_EMPTIABLE(t) \
304     (xmlSchemaIsParticleEmptiable(WXS_PTC_CAST (t)->subtypes))
305 
306 #define WXS_TYPE_CONTENTTYPE(t) (t)->subtypes
307 
308 #define WXS_TYPE_PARTICLE(t) WXS_PTC_CAST (t)->subtypes
309 
310 #define WXS_TYPE_PARTICLE_TERM(t) WXS_PARTICLE_TERM(WXS_TYPE_PARTICLE(t))
311 /*
312 * Macros for exclusively for simple types.
313 */
314 #define WXS_LIST_ITEMTYPE(t) (t)->subtypes
315 
316 #define WXS_IS_ATOMIC(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
317 
318 #define WXS_IS_LIST(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
319 
320 #define WXS_IS_UNION(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)
321 /*
322 * Misc parser context macros.
323 */
324 #define WXS_CONSTRUCTOR(ctx) (ctx)->constructor
325 
326 #define WXS_HAS_BUCKETS(ctx) \
327 ( (WXS_CONSTRUCTOR((ctx))->buckets != NULL) && \
328 (WXS_CONSTRUCTOR((ctx))->buckets->nbItems > 0) )
329 
330 #define WXS_SUBST_GROUPS(ctx) WXS_CONSTRUCTOR((ctx))->substGroups
331 
332 #define WXS_BUCKET(ctx) WXS_CONSTRUCTOR((ctx))->bucket
333 
334 #define WXS_SCHEMA(ctx) (ctx)->schema
335 
336 #define WXS_ADD_LOCAL(ctx, item) \
337     xmlSchemaAddItemSize(&(WXS_BUCKET(ctx)->locals), 10, item)
338 
339 #define WXS_ADD_GLOBAL(ctx, item) \
340     xmlSchemaAddItemSize(&(WXS_BUCKET(ctx)->globals), 5, item)
341 
342 #define WXS_ADD_PENDING(ctx, item) \
343     xmlSchemaAddItemSize(&((ctx)->constructor->pending), 10, item)
344 /*
345 * xmlSchemaItemList macros.
346 */
347 #define WXS_ILIST_IS_EMPTY(l) ((l == NULL) || ((l)->nbItems == 0))
348 /*
349 * Misc macros.
350 */
351 #define IS_SCHEMA(node, type) \
352    ((node != NULL) && (node->ns != NULL) && \
353     (xmlStrEqual(node->name, (const xmlChar *) type)) && \
354     (xmlStrEqual(node->ns->href, xmlSchemaNs)))
355 
356 #define FREE_AND_NULL(str) if ((str) != NULL) { xmlFree((xmlChar *) (str)); str = NULL; }
357 
358 /*
359 * Since we put the default/fixed values into the dict, we can
360 * use pointer comparison for those values.
361 * REMOVED: (xmlStrEqual((v1), (v2)))
362 */
363 #define WXS_ARE_DEFAULT_STR_EQUAL(v1, v2) ((v1) == (v2))
364 
365 #define INODE_NILLED(item) (item->flags & XML_SCHEMA_ELEM_INFO_NILLED)
366 
367 #define CAN_PARSE_SCHEMA(b) (((b)->doc != NULL) && ((b)->parsed == 0))
368 
369 #define HFAILURE if (res == -1) goto exit_failure;
370 
371 #define HERROR if (res != 0) goto exit_error;
372 
373 #define HSTOP(ctx) if ((ctx)->stop) goto exit;
374 /*
375 * Some flags used for various schema constraints.
376 */
377 #define SUBSET_RESTRICTION  1<<0
378 #define SUBSET_EXTENSION    1<<1
379 #define SUBSET_SUBSTITUTION 1<<2
380 #define SUBSET_LIST         1<<3
381 #define SUBSET_UNION        1<<4
382 
383 typedef struct _xmlSchemaNodeInfo xmlSchemaNodeInfo;
384 typedef xmlSchemaNodeInfo *xmlSchemaNodeInfoPtr;
385 
386 typedef struct _xmlSchemaItemList xmlSchemaItemList;
387 typedef xmlSchemaItemList *xmlSchemaItemListPtr;
388 struct _xmlSchemaItemList {
389     void **items;  /* used for dynamic addition of schemata */
390     int nbItems; /* used for dynamic addition of schemata */
391     int sizeItems; /* used for dynamic addition of schemata */
392 };
393 
394 #define XML_SCHEMA_CTXT_PARSER 1
395 #define XML_SCHEMA_CTXT_VALIDATOR 2
396 
397 typedef struct _xmlSchemaAbstractCtxt xmlSchemaAbstractCtxt;
398 typedef xmlSchemaAbstractCtxt *xmlSchemaAbstractCtxtPtr;
399 struct _xmlSchemaAbstractCtxt {
400     int type; /* E.g. XML_SCHEMA_CTXT_VALIDATOR */
401     void *dummy; /* Fix alignment issues */
402 };
403 
404 typedef struct _xmlSchemaBucket xmlSchemaBucket;
405 typedef xmlSchemaBucket *xmlSchemaBucketPtr;
406 
407 #define XML_SCHEMA_SCHEMA_MAIN 0
408 #define XML_SCHEMA_SCHEMA_IMPORT 1
409 #define XML_SCHEMA_SCHEMA_INCLUDE 2
410 #define XML_SCHEMA_SCHEMA_REDEFINE 3
411 
412 /**
413  * xmlSchemaSchemaRelation:
414  *
415  * Used to create a graph of schema relationships.
416  */
417 typedef struct _xmlSchemaSchemaRelation xmlSchemaSchemaRelation;
418 typedef xmlSchemaSchemaRelation *xmlSchemaSchemaRelationPtr;
419 struct _xmlSchemaSchemaRelation {
420     xmlSchemaSchemaRelationPtr next;
421     int type; /* E.g. XML_SCHEMA_SCHEMA_IMPORT */
422     const xmlChar *importNamespace;
423     xmlSchemaBucketPtr bucket;
424 };
425 
426 #define XML_SCHEMA_BUCKET_MARKED 1<<0
427 #define XML_SCHEMA_BUCKET_COMPS_ADDED 1<<1
428 
429 struct _xmlSchemaBucket {
430     int type;
431     int flags;
432     const xmlChar *schemaLocation;
433     const xmlChar *origTargetNamespace;
434     const xmlChar *targetNamespace;
435     xmlDocPtr doc;
436     xmlSchemaSchemaRelationPtr relations;
437     int located;
438     int parsed;
439     int imported;
440     int preserveDoc;
441     xmlSchemaItemListPtr globals; /* Global components. */
442     xmlSchemaItemListPtr locals; /* Local components. */
443 };
444 
445 /**
446  * xmlSchemaImport:
447  * (extends xmlSchemaBucket)
448  *
449  * Reflects a schema. Holds some information
450  * about the schema and its toplevel components. Duplicate
451  * toplevel components are not checked at this level.
452  */
453 typedef struct _xmlSchemaImport xmlSchemaImport;
454 typedef xmlSchemaImport *xmlSchemaImportPtr;
455 struct _xmlSchemaImport {
456     int type; /* Main OR import OR include. */
457     int flags;
458     const xmlChar *schemaLocation; /* The URI of the schema document. */
459     /* For chameleon includes, @origTargetNamespace will be NULL */
460     const xmlChar *origTargetNamespace;
461     /*
462     * For chameleon includes, @targetNamespace will be the
463     * targetNamespace of the including schema.
464     */
465     const xmlChar *targetNamespace;
466     xmlDocPtr doc; /* The schema node-tree. */
467     /* @relations will hold any included/imported/redefined schemas. */
468     xmlSchemaSchemaRelationPtr relations;
469     int located;
470     int parsed;
471     int imported;
472     int preserveDoc;
473     xmlSchemaItemListPtr globals;
474     xmlSchemaItemListPtr locals;
475     /* The imported schema. */
476     xmlSchemaPtr schema;
477 };
478 
479 /*
480 * (extends xmlSchemaBucket)
481 */
482 typedef struct _xmlSchemaInclude xmlSchemaInclude;
483 typedef xmlSchemaInclude *xmlSchemaIncludePtr;
484 struct _xmlSchemaInclude {
485     int type;
486     int flags;
487     const xmlChar *schemaLocation;
488     const xmlChar *origTargetNamespace;
489     const xmlChar *targetNamespace;
490     xmlDocPtr doc;
491     xmlSchemaSchemaRelationPtr relations;
492     int located;
493     int parsed;
494     int imported;
495     int preserveDoc;
496     xmlSchemaItemListPtr globals; /* Global components. */
497     xmlSchemaItemListPtr locals; /* Local components. */
498 
499     /* The owning main or import schema bucket. */
500     xmlSchemaImportPtr ownerImport;
501 };
502 
503 /**
504  * xmlSchemaBasicItem:
505  *
506  * The abstract base type for schema components.
507  */
508 typedef struct _xmlSchemaBasicItem xmlSchemaBasicItem;
509 typedef xmlSchemaBasicItem *xmlSchemaBasicItemPtr;
510 struct _xmlSchemaBasicItem {
511     xmlSchemaTypeType type;
512     void *dummy; /* Fix alignment issues */
513 };
514 
515 /**
516  * xmlSchemaAnnotItem:
517  *
518  * The abstract base type for annotated schema components.
519  * (Extends xmlSchemaBasicItem)
520  */
521 typedef struct _xmlSchemaAnnotItem xmlSchemaAnnotItem;
522 typedef xmlSchemaAnnotItem *xmlSchemaAnnotItemPtr;
523 struct _xmlSchemaAnnotItem {
524     xmlSchemaTypeType type;
525     xmlSchemaAnnotPtr annot;
526 };
527 
528 /**
529  * xmlSchemaTreeItem:
530  *
531  * The abstract base type for tree-like structured schema components.
532  * (Extends xmlSchemaAnnotItem)
533  */
534 typedef struct _xmlSchemaTreeItem xmlSchemaTreeItem;
535 typedef xmlSchemaTreeItem *xmlSchemaTreeItemPtr;
536 struct _xmlSchemaTreeItem {
537     xmlSchemaTypeType type;
538     xmlSchemaAnnotPtr annot;
539     xmlSchemaTreeItemPtr next;
540     xmlSchemaTreeItemPtr children;
541 };
542 
543 
544 #define XML_SCHEMA_ATTR_USE_FIXED 1<<0
545 /**
546  * xmlSchemaAttributeUsePtr:
547  *
548  * The abstract base type for tree-like structured schema components.
549  * (Extends xmlSchemaTreeItem)
550  */
551 typedef struct _xmlSchemaAttributeUse xmlSchemaAttributeUse;
552 typedef xmlSchemaAttributeUse *xmlSchemaAttributeUsePtr;
553 struct _xmlSchemaAttributeUse {
554     xmlSchemaTypeType type;
555     xmlSchemaAnnotPtr annot;
556     xmlSchemaAttributeUsePtr next; /* The next attr. use. */
557     /*
558     * The attr. decl. OR a QName-ref. to an attr. decl. OR
559     * a QName-ref. to an attribute group definition.
560     */
561     xmlSchemaAttributePtr attrDecl;
562 
563     int flags;
564     xmlNodePtr node;
565     int occurs; /* required, optional */
566     const xmlChar * defValue;
567     xmlSchemaValPtr defVal;
568 };
569 
570 /**
571  * xmlSchemaAttributeUseProhibPtr:
572  *
573  * A helper component to reflect attribute prohibitions.
574  * (Extends xmlSchemaBasicItem)
575  */
576 typedef struct _xmlSchemaAttributeUseProhib xmlSchemaAttributeUseProhib;
577 typedef xmlSchemaAttributeUseProhib *xmlSchemaAttributeUseProhibPtr;
578 struct _xmlSchemaAttributeUseProhib {
579     xmlSchemaTypeType type; /* == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB */
580     xmlNodePtr node;
581     const xmlChar *name;
582     const xmlChar *targetNamespace;
583     int isRef;
584 };
585 
586 /**
587  * xmlSchemaRedef:
588  */
589 typedef struct _xmlSchemaRedef xmlSchemaRedef;
590 typedef xmlSchemaRedef *xmlSchemaRedefPtr;
591 struct _xmlSchemaRedef {
592     xmlSchemaRedefPtr next;
593     xmlSchemaBasicItemPtr item; /* The redefining component. */
594     xmlSchemaBasicItemPtr reference; /* The referencing component. */
595     xmlSchemaBasicItemPtr target; /* The to-be-redefined component. */
596     const xmlChar *refName; /* The name of the to-be-redefined component. */
597     const xmlChar *refTargetNs; /* The target namespace of the
598                                    to-be-redefined comp. */
599     xmlSchemaBucketPtr targetBucket; /* The redefined schema. */
600 };
601 
602 /**
603  * xmlSchemaConstructionCtxt:
604  */
605 typedef struct _xmlSchemaConstructionCtxt xmlSchemaConstructionCtxt;
606 typedef xmlSchemaConstructionCtxt *xmlSchemaConstructionCtxtPtr;
607 struct _xmlSchemaConstructionCtxt {
608     xmlSchemaPtr mainSchema; /* The main schema. */
609     xmlSchemaBucketPtr mainBucket; /* The main schema bucket */
610     xmlDictPtr dict;
611     xmlSchemaItemListPtr buckets; /* List of schema buckets. */
612     /* xmlSchemaItemListPtr relations; */ /* List of schema relations. */
613     xmlSchemaBucketPtr bucket; /* The current schema bucket */
614     xmlSchemaItemListPtr pending; /* All Components of all schemas that
615                                      need to be fixed. */
616     xmlHashTablePtr substGroups;
617     xmlSchemaRedefPtr redefs;
618     xmlSchemaRedefPtr lastRedef;
619 };
620 
621 #define XML_SCHEMAS_PARSE_ERROR		1
622 #define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
623 
624 struct _xmlSchemaParserCtxt {
625     int type;
626     void *errCtxt;             /* user specific error context */
627     xmlSchemaValidityErrorFunc error;   /* the callback in case of errors */
628     xmlSchemaValidityWarningFunc warning;       /* the callback in case of warning */
629     int err;
630     int nberrors;
631     xmlStructuredErrorFunc serror;
632 
633     xmlSchemaConstructionCtxtPtr constructor;
634     int ownsConstructor; /* TODO: Move this to parser *flags*. */
635 
636     /* xmlSchemaPtr topschema;	*/
637     /* xmlHashTablePtr namespaces;  */
638 
639     xmlSchemaPtr schema;        /* The main schema in use */
640     int counter;
641 
642     const xmlChar *URL;
643     xmlDocPtr doc;
644     int preserve;		/* Whether the doc should be freed  */
645 
646     const char *buffer;
647     int size;
648 
649     /*
650      * Used to build complex element content models
651      */
652     xmlAutomataPtr am;
653     xmlAutomataStatePtr start;
654     xmlAutomataStatePtr end;
655     xmlAutomataStatePtr state;
656 
657     xmlDictPtr dict;		/* dictionary for interned string names */
658     xmlSchemaTypePtr ctxtType; /* The current context simple/complex type */
659     int options;
660     xmlSchemaValidCtxtPtr vctxt;
661     int isS4S;
662     int isRedefine;
663     int xsiAssemble;
664     int stop; /* If the parser should stop; i.e. a critical error. */
665     const xmlChar *targetNamespace;
666     xmlSchemaBucketPtr redefined; /* The schema to be redefined. */
667 
668     xmlSchemaRedefPtr redef; /* Used for redefinitions. */
669     int redefCounter; /* Used for redefinitions. */
670     xmlSchemaItemListPtr attrProhibs;
671 };
672 
673 /**
674  * xmlSchemaQNameRef:
675  *
676  * A component reference item (not a schema component)
677  * (Extends xmlSchemaBasicItem)
678  */
679 typedef struct _xmlSchemaQNameRef xmlSchemaQNameRef;
680 typedef xmlSchemaQNameRef *xmlSchemaQNameRefPtr;
681 struct _xmlSchemaQNameRef {
682     xmlSchemaTypeType type;
683     xmlSchemaBasicItemPtr item; /* The resolved referenced item. */
684     xmlSchemaTypeType itemType;
685     const xmlChar *name;
686     const xmlChar *targetNamespace;
687     xmlNodePtr node;
688 };
689 
690 /**
691  * xmlSchemaParticle:
692  *
693  * A particle component.
694  * (Extends xmlSchemaTreeItem)
695  */
696 typedef struct _xmlSchemaParticle xmlSchemaParticle;
697 typedef xmlSchemaParticle *xmlSchemaParticlePtr;
698 struct _xmlSchemaParticle {
699     xmlSchemaTypeType type;
700     xmlSchemaAnnotPtr annot;
701     xmlSchemaTreeItemPtr next; /* next particle */
702     xmlSchemaTreeItemPtr children; /* the "term" (e.g. a model group,
703 	a group definition, a XML_SCHEMA_EXTRA_QNAMEREF (if a reference),
704         etc.) */
705     int minOccurs;
706     int maxOccurs;
707     xmlNodePtr node;
708 };
709 
710 /**
711  * xmlSchemaModelGroup:
712  *
713  * A model group component.
714  * (Extends xmlSchemaTreeItem)
715  */
716 typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
717 typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
718 struct _xmlSchemaModelGroup {
719     xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_SEQUENCE, XML_SCHEMA_TYPE_CHOICE, XML_SCHEMA_TYPE_ALL */
720     xmlSchemaAnnotPtr annot;
721     xmlSchemaTreeItemPtr next; /* not used */
722     xmlSchemaTreeItemPtr children; /* first particle (OR "element decl" OR "wildcard") */
723     xmlNodePtr node;
724 };
725 
726 #define XML_SCHEMA_MODEL_GROUP_DEF_MARKED 1<<0
727 #define XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED 1<<1
728 /**
729  * xmlSchemaModelGroupDef:
730  *
731  * A model group definition component.
732  * (Extends xmlSchemaTreeItem)
733  */
734 typedef struct _xmlSchemaModelGroupDef xmlSchemaModelGroupDef;
735 typedef xmlSchemaModelGroupDef *xmlSchemaModelGroupDefPtr;
736 struct _xmlSchemaModelGroupDef {
737     xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_GROUP */
738     xmlSchemaAnnotPtr annot;
739     xmlSchemaTreeItemPtr next; /* not used */
740     xmlSchemaTreeItemPtr children; /* the "model group" */
741     const xmlChar *name;
742     const xmlChar *targetNamespace;
743     xmlNodePtr node;
744     int flags;
745 };
746 
747 typedef struct _xmlSchemaIDC xmlSchemaIDC;
748 typedef xmlSchemaIDC *xmlSchemaIDCPtr;
749 
750 /**
751  * xmlSchemaIDCSelect:
752  *
753  * The identity-constraint "field" and "selector" item, holding the
754  * XPath expression.
755  */
756 typedef struct _xmlSchemaIDCSelect xmlSchemaIDCSelect;
757 typedef xmlSchemaIDCSelect *xmlSchemaIDCSelectPtr;
758 struct _xmlSchemaIDCSelect {
759     xmlSchemaIDCSelectPtr next;
760     xmlSchemaIDCPtr idc;
761     int index; /* an index position if significant for IDC key-sequences */
762     const xmlChar *xpath; /* the XPath expression */
763     void *xpathComp; /* the compiled XPath expression */
764 };
765 
766 /**
767  * xmlSchemaIDC:
768  *
769  * The identity-constraint definition component.
770  * (Extends xmlSchemaAnnotItem)
771  */
772 
773 struct _xmlSchemaIDC {
774     xmlSchemaTypeType type;
775     xmlSchemaAnnotPtr annot;
776     xmlSchemaIDCPtr next;
777     xmlNodePtr node;
778     const xmlChar *name;
779     const xmlChar *targetNamespace;
780     xmlSchemaIDCSelectPtr selector;
781     xmlSchemaIDCSelectPtr fields;
782     int nbFields;
783     xmlSchemaQNameRefPtr ref;
784 };
785 
786 /**
787  * xmlSchemaIDCAug:
788  *
789  * The augmented IDC information used for validation.
790  */
791 typedef struct _xmlSchemaIDCAug xmlSchemaIDCAug;
792 typedef xmlSchemaIDCAug *xmlSchemaIDCAugPtr;
793 struct _xmlSchemaIDCAug {
794     xmlSchemaIDCAugPtr next; /* next in a list */
795     xmlSchemaIDCPtr def; /* the IDC definition */
796     int keyrefDepth; /* the lowest tree level to which IDC
797                         tables need to be bubbled upwards */
798 };
799 
800 /**
801  * xmlSchemaPSVIIDCKeySequence:
802  *
803  * The key sequence of a node table item.
804  */
805 typedef struct _xmlSchemaPSVIIDCKey xmlSchemaPSVIIDCKey;
806 typedef xmlSchemaPSVIIDCKey *xmlSchemaPSVIIDCKeyPtr;
807 struct _xmlSchemaPSVIIDCKey {
808     xmlSchemaTypePtr type;
809     xmlSchemaValPtr val;
810 };
811 
812 /**
813  * xmlSchemaPSVIIDCNode:
814  *
815  * The node table item of a node table.
816  */
817 typedef struct _xmlSchemaPSVIIDCNode xmlSchemaPSVIIDCNode;
818 typedef xmlSchemaPSVIIDCNode *xmlSchemaPSVIIDCNodePtr;
819 struct _xmlSchemaPSVIIDCNode {
820     xmlNodePtr node;
821     xmlSchemaPSVIIDCKeyPtr *keys;
822     int nodeLine;
823     int nodeQNameID;
824 
825 };
826 
827 /**
828  * xmlSchemaPSVIIDCBinding:
829  *
830  * The identity-constraint binding item of the [identity-constraint table].
831  */
832 typedef struct _xmlSchemaPSVIIDCBinding xmlSchemaPSVIIDCBinding;
833 typedef xmlSchemaPSVIIDCBinding *xmlSchemaPSVIIDCBindingPtr;
834 struct _xmlSchemaPSVIIDCBinding {
835     xmlSchemaPSVIIDCBindingPtr next; /* next binding of a specific node */
836     xmlSchemaIDCPtr definition; /* the IDC definition */
837     xmlSchemaPSVIIDCNodePtr *nodeTable; /* array of key-sequences */
838     int nbNodes; /* number of entries in the node table */
839     int sizeNodes; /* size of the node table */
840     xmlSchemaItemListPtr dupls;
841 };
842 
843 
844 #define XPATH_STATE_OBJ_TYPE_IDC_SELECTOR 1
845 #define XPATH_STATE_OBJ_TYPE_IDC_FIELD 2
846 
847 #define XPATH_STATE_OBJ_MATCHES -2
848 #define XPATH_STATE_OBJ_BLOCKED -3
849 
850 typedef struct _xmlSchemaIDCMatcher xmlSchemaIDCMatcher;
851 typedef xmlSchemaIDCMatcher *xmlSchemaIDCMatcherPtr;
852 
853 /**
854  * xmlSchemaIDCStateObj:
855  *
856  * The state object used to evaluate XPath expressions.
857  */
858 typedef struct _xmlSchemaIDCStateObj xmlSchemaIDCStateObj;
859 typedef xmlSchemaIDCStateObj *xmlSchemaIDCStateObjPtr;
860 struct _xmlSchemaIDCStateObj {
861     int type;
862     xmlSchemaIDCStateObjPtr next; /* next if in a list */
863     int depth; /* depth of creation */
864     int *history; /* list of (depth, state-id) tuples */
865     int nbHistory;
866     int sizeHistory;
867     xmlSchemaIDCMatcherPtr matcher; /* the correspondent field/selector
868                                        matcher */
869     xmlSchemaIDCSelectPtr sel;
870     void *xpathCtxt;
871 };
872 
873 #define IDC_MATCHER 0
874 
875 /**
876  * xmlSchemaIDCMatcher:
877  *
878  * Used to evaluate IDC selectors (and fields).
879  */
880 struct _xmlSchemaIDCMatcher {
881     int type;
882     int depth; /* the tree depth at creation time */
883     xmlSchemaIDCMatcherPtr next; /* next in the list */
884     xmlSchemaIDCMatcherPtr nextCached; /* next in the cache list */
885     xmlSchemaIDCAugPtr aidc; /* the augmented IDC item */
886     int idcType;
887     xmlSchemaPSVIIDCKeyPtr **keySeqs; /* the key-sequences of the target
888                                          elements */
889     int sizeKeySeqs;
890     xmlSchemaItemListPtr targets; /* list of target-node
891                                      (xmlSchemaPSVIIDCNodePtr) entries */
892 };
893 
894 /*
895 * Element info flags.
896 */
897 #define XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES  1<<0
898 #define XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES 1<<1
899 #define XML_SCHEMA_ELEM_INFO_NILLED	       1<<2
900 #define XML_SCHEMA_ELEM_INFO_LOCAL_TYPE	       1<<3
901 
902 #define XML_SCHEMA_NODE_INFO_VALUE_NEEDED      1<<4
903 #define XML_SCHEMA_ELEM_INFO_EMPTY             1<<5
904 #define XML_SCHEMA_ELEM_INFO_HAS_CONTENT       1<<6
905 
906 #define XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT  1<<7
907 #define XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT  1<<8
908 #define XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED  1<<9
909 #define XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE  1<<10
910 
911 /**
912  * xmlSchemaNodeInfo:
913  *
914  * Holds information of an element node.
915  */
916 struct _xmlSchemaNodeInfo {
917     int nodeType;
918     xmlNodePtr node;
919     int nodeLine;
920     const xmlChar *localName;
921     const xmlChar *nsName;
922     const xmlChar *value;
923     xmlSchemaValPtr val; /* the pre-computed value if any */
924     xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
925 
926     int flags; /* combination of node info flags */
927 
928     int valNeeded;
929     int normVal;
930 
931     xmlSchemaElementPtr decl; /* the element/attribute declaration */
932     int depth;
933     xmlSchemaPSVIIDCBindingPtr idcTable; /* the table of PSVI IDC bindings
934                                             for the scope element*/
935     xmlSchemaIDCMatcherPtr idcMatchers; /* the IDC matchers for the scope
936                                            element */
937     xmlRegExecCtxtPtr regexCtxt;
938 
939     const xmlChar **nsBindings; /* Namespace bindings on this element */
940     int nbNsBindings;
941     int sizeNsBindings;
942 
943     int hasKeyrefs;
944     int appliedXPath; /* Indicates that an XPath has been applied. */
945 };
946 
947 #define XML_SCHEMAS_ATTR_UNKNOWN 1
948 #define XML_SCHEMAS_ATTR_ASSESSED 2
949 #define XML_SCHEMAS_ATTR_PROHIBITED 3
950 #define XML_SCHEMAS_ATTR_ERR_MISSING 4
951 #define XML_SCHEMAS_ATTR_INVALID_VALUE 5
952 #define XML_SCHEMAS_ATTR_ERR_NO_TYPE 6
953 #define XML_SCHEMAS_ATTR_ERR_FIXED_VALUE 7
954 #define XML_SCHEMAS_ATTR_DEFAULT 8
955 #define XML_SCHEMAS_ATTR_VALIDATE_VALUE 9
956 #define XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL 10
957 #define XML_SCHEMAS_ATTR_HAS_ATTR_USE 11
958 #define XML_SCHEMAS_ATTR_HAS_ATTR_DECL 12
959 #define XML_SCHEMAS_ATTR_WILD_SKIP 13
960 #define XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL 14
961 #define XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID 15
962 #define XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID 16
963 #define XML_SCHEMAS_ATTR_META 17
964 /*
965 * @metaType values of xmlSchemaAttrInfo.
966 */
967 #define XML_SCHEMA_ATTR_INFO_META_XSI_TYPE 1
968 #define XML_SCHEMA_ATTR_INFO_META_XSI_NIL 2
969 #define XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC 3
970 #define XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC 4
971 #define XML_SCHEMA_ATTR_INFO_META_XMLNS 5
972 
973 typedef struct _xmlSchemaAttrInfo xmlSchemaAttrInfo;
974 typedef xmlSchemaAttrInfo *xmlSchemaAttrInfoPtr;
975 struct _xmlSchemaAttrInfo {
976     int nodeType;
977     xmlNodePtr node;
978     int nodeLine;
979     const xmlChar *localName;
980     const xmlChar *nsName;
981     const xmlChar *value;
982     xmlSchemaValPtr val; /* the pre-computed value if any */
983     xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
984     int flags; /* combination of node info flags */
985 
986     xmlSchemaAttributePtr decl; /* the attribute declaration */
987     xmlSchemaAttributeUsePtr use;  /* the attribute use */
988     int state;
989     int metaType;
990     const xmlChar *vcValue; /* the value constraint value */
991     xmlSchemaNodeInfoPtr parent;
992 };
993 
994 
995 #define XML_SCHEMA_VALID_CTXT_FLAG_STREAM 1
996 /**
997  * xmlSchemaValidCtxt:
998  *
999  * A Schemas validation context
1000  */
1001 struct _xmlSchemaValidCtxt {
1002     int type;
1003     void *errCtxt;             /* user specific data block */
1004     xmlSchemaValidityErrorFunc error;   /* the callback in case of errors */
1005     xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
1006     xmlStructuredErrorFunc serror;
1007 
1008     xmlSchemaPtr schema;        /* The schema in use */
1009     xmlDocPtr doc;
1010     xmlParserInputBufferPtr input;
1011     xmlCharEncoding enc;
1012     xmlSAXHandlerPtr sax;
1013     xmlParserCtxtPtr parserCtxt;
1014     void *user_data; /* TODO: What is this for? */
1015     char *filename;
1016 
1017     int err;
1018     int nberrors;
1019 
1020     xmlNodePtr node;
1021     xmlNodePtr cur;
1022     /* xmlSchemaTypePtr type; */
1023 
1024     xmlRegExecCtxtPtr regexp;
1025     xmlSchemaValPtr value;
1026 
1027     int valueWS;
1028     int options;
1029     xmlNodePtr validationRoot;
1030     xmlSchemaParserCtxtPtr pctxt;
1031     int xsiAssemble;
1032 
1033     int depth;
1034     xmlSchemaNodeInfoPtr *elemInfos; /* array of element informations */
1035     int sizeElemInfos;
1036     xmlSchemaNodeInfoPtr inode; /* the current element information */
1037 
1038     xmlSchemaIDCAugPtr aidcs; /* a list of augmented IDC informations */
1039 
1040     xmlSchemaIDCStateObjPtr xpathStates; /* first active state object. */
1041     xmlSchemaIDCStateObjPtr xpathStatePool; /* first stored state object. */
1042     xmlSchemaIDCMatcherPtr idcMatcherCache; /* Cache for IDC matcher objects. */
1043 
1044     xmlSchemaPSVIIDCNodePtr *idcNodes; /* list of all IDC node-table entries*/
1045     int nbIdcNodes;
1046     int sizeIdcNodes;
1047 
1048     xmlSchemaPSVIIDCKeyPtr *idcKeys; /* list of all IDC node-table entries */
1049     int nbIdcKeys;
1050     int sizeIdcKeys;
1051 
1052     int flags;
1053 
1054     xmlDictPtr dict;
1055 
1056 #ifdef LIBXML_READER_ENABLED
1057     xmlTextReaderPtr reader;
1058 #endif
1059 
1060     xmlSchemaAttrInfoPtr *attrInfos;
1061     int nbAttrInfos;
1062     int sizeAttrInfos;
1063 
1064     int skipDepth;
1065     xmlSchemaItemListPtr nodeQNames;
1066     int hasKeyrefs;
1067     int createIDCNodeTables;
1068     int psviExposeIDCNodeTables;
1069 
1070     /* Locator for error reporting in streaming mode */
1071     xmlSchemaValidityLocatorFunc locFunc;
1072     void *locCtxt;
1073 };
1074 
1075 /**
1076  * xmlSchemaSubstGroup:
1077  *
1078  *
1079  */
1080 typedef struct _xmlSchemaSubstGroup xmlSchemaSubstGroup;
1081 typedef xmlSchemaSubstGroup *xmlSchemaSubstGroupPtr;
1082 struct _xmlSchemaSubstGroup {
1083     xmlSchemaElementPtr head;
1084     xmlSchemaItemListPtr members;
1085 };
1086 
1087 /************************************************************************
1088  *									*
1089  *			Some predeclarations				*
1090  *									*
1091  ************************************************************************/
1092 
1093 static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
1094                                  xmlSchemaPtr schema,
1095                                  xmlNodePtr node);
1096 static int xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr ctxt,
1097                                  xmlSchemaPtr schema,
1098                                  xmlNodePtr node);
1099 static int
1100 xmlSchemaTypeFixup(xmlSchemaTypePtr type,
1101                    xmlSchemaAbstractCtxtPtr ctxt);
1102 static const xmlChar *
1103 xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
1104 static int
1105 xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1106                      xmlNodePtr node);
1107 static int
1108 xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
1109                        xmlSchemaParserCtxtPtr ctxt);
1110 static void
1111 xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt);
1112 static xmlSchemaWhitespaceValueType
1113 xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type);
1114 static xmlSchemaTreeItemPtr
1115 xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1116 			 xmlNodePtr node, xmlSchemaTypeType type,
1117 			 int withParticle);
1118 static const xmlChar *
1119 xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item);
1120 static xmlSchemaTypeLinkPtr
1121 xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type);
1122 static void
1123 xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
1124 		     const char *funcName,
1125 		     const char *message) LIBXML_ATTR_FORMAT(3,0);
1126 static int
1127 xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr ctxt,
1128 			     xmlSchemaTypePtr type,
1129 			     xmlSchemaTypePtr baseType,
1130 			     int subset);
1131 static void
1132 xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
1133 				   xmlSchemaParserCtxtPtr ctxt);
1134 static void
1135 xmlSchemaComponentListFree(xmlSchemaItemListPtr list);
1136 static xmlSchemaQNameRefPtr
1137 xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,
1138 				xmlSchemaPtr schema,
1139 				xmlNodePtr node);
1140 
1141 /************************************************************************
1142  *									*
1143  *			Helper functions			        *
1144  *									*
1145  ************************************************************************/
1146 
1147 /**
1148  * xmlSchemaItemTypeToStr:
1149  * @type: the type of the schema item
1150  *
1151  * Returns the component name of a schema item.
1152  */
1153 static const xmlChar *
xmlSchemaItemTypeToStr(xmlSchemaTypeType type)1154 xmlSchemaItemTypeToStr(xmlSchemaTypeType type)
1155 {
1156     switch (type) {
1157 	case XML_SCHEMA_TYPE_BASIC:
1158 	    return(BAD_CAST "simple type definition");
1159 	case XML_SCHEMA_TYPE_SIMPLE:
1160 	    return(BAD_CAST "simple type definition");
1161 	case XML_SCHEMA_TYPE_COMPLEX:
1162 	    return(BAD_CAST "complex type definition");
1163 	case XML_SCHEMA_TYPE_ELEMENT:
1164 	    return(BAD_CAST "element declaration");
1165 	case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1166 	    return(BAD_CAST "attribute use");
1167 	case XML_SCHEMA_TYPE_ATTRIBUTE:
1168 	    return(BAD_CAST "attribute declaration");
1169 	case XML_SCHEMA_TYPE_GROUP:
1170 	    return(BAD_CAST "model group definition");
1171 	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1172 	    return(BAD_CAST "attribute group definition");
1173 	case XML_SCHEMA_TYPE_NOTATION:
1174 	    return(BAD_CAST "notation declaration");
1175 	case XML_SCHEMA_TYPE_SEQUENCE:
1176 	    return(BAD_CAST "model group (sequence)");
1177 	case XML_SCHEMA_TYPE_CHOICE:
1178 	    return(BAD_CAST "model group (choice)");
1179 	case XML_SCHEMA_TYPE_ALL:
1180 	    return(BAD_CAST "model group (all)");
1181 	case XML_SCHEMA_TYPE_PARTICLE:
1182 	    return(BAD_CAST "particle");
1183 	case XML_SCHEMA_TYPE_IDC_UNIQUE:
1184 	    return(BAD_CAST "unique identity-constraint");
1185 	    /* return(BAD_CAST "IDC (unique)"); */
1186 	case XML_SCHEMA_TYPE_IDC_KEY:
1187 	    return(BAD_CAST "key identity-constraint");
1188 	    /* return(BAD_CAST "IDC (key)"); */
1189 	case XML_SCHEMA_TYPE_IDC_KEYREF:
1190 	    return(BAD_CAST "keyref identity-constraint");
1191 	    /* return(BAD_CAST "IDC (keyref)"); */
1192 	case XML_SCHEMA_TYPE_ANY:
1193 	    return(BAD_CAST "wildcard (any)");
1194 	case XML_SCHEMA_EXTRA_QNAMEREF:
1195 	    return(BAD_CAST "[helper component] QName reference");
1196 	case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
1197 	    return(BAD_CAST "[helper component] attribute use prohibition");
1198 	default:
1199 	    return(BAD_CAST "Not a schema component");
1200     }
1201 }
1202 
1203 /**
1204  * xmlSchemaGetComponentTypeStr:
1205  * @type: the type of the schema item
1206  *
1207  * Returns the component name of a schema item.
1208  */
1209 static const xmlChar *
xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item)1210 xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item)
1211 {
1212     switch (item->type) {
1213 	case XML_SCHEMA_TYPE_BASIC:
1214 	    if (WXS_IS_COMPLEX(WXS_TYPE_CAST item))
1215 		return(BAD_CAST "complex type definition");
1216 	    else
1217 		return(BAD_CAST "simple type definition");
1218 	default:
1219 	    return(xmlSchemaItemTypeToStr(item->type));
1220     }
1221 }
1222 
1223 /**
1224  * xmlSchemaGetComponentNode:
1225  * @item: a schema component
1226  *
1227  * Returns node associated with the schema component.
1228  * NOTE that such a node need not be available; plus, a component's
1229  * node need not to reflect the component directly, since there is no
1230  * one-to-one relationship between the XML Schema representation and
1231  * the component representation.
1232  */
1233 static xmlNodePtr
xmlSchemaGetComponentNode(xmlSchemaBasicItemPtr item)1234 xmlSchemaGetComponentNode(xmlSchemaBasicItemPtr item)
1235 {
1236     switch (item->type) {
1237 	case XML_SCHEMA_TYPE_ELEMENT:
1238 	    return (((xmlSchemaElementPtr) item)->node);
1239 	case XML_SCHEMA_TYPE_ATTRIBUTE:
1240 	    return (((xmlSchemaAttributePtr) item)->node);
1241 	case XML_SCHEMA_TYPE_COMPLEX:
1242 	case XML_SCHEMA_TYPE_SIMPLE:
1243 	    return (((xmlSchemaTypePtr) item)->node);
1244 	case XML_SCHEMA_TYPE_ANY:
1245 	case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1246 	    return (((xmlSchemaWildcardPtr) item)->node);
1247 	case XML_SCHEMA_TYPE_PARTICLE:
1248 	    return (((xmlSchemaParticlePtr) item)->node);
1249 	case XML_SCHEMA_TYPE_SEQUENCE:
1250 	case XML_SCHEMA_TYPE_CHOICE:
1251 	case XML_SCHEMA_TYPE_ALL:
1252 	    return (((xmlSchemaModelGroupPtr) item)->node);
1253 	case XML_SCHEMA_TYPE_GROUP:
1254 	    return (((xmlSchemaModelGroupDefPtr) item)->node);
1255 	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1256 	    return (((xmlSchemaAttributeGroupPtr) item)->node);
1257 	case XML_SCHEMA_TYPE_IDC_UNIQUE:
1258 	case XML_SCHEMA_TYPE_IDC_KEY:
1259 	case XML_SCHEMA_TYPE_IDC_KEYREF:
1260 	    return (((xmlSchemaIDCPtr) item)->node);
1261 	case XML_SCHEMA_EXTRA_QNAMEREF:
1262 	    return(((xmlSchemaQNameRefPtr) item)->node);
1263 	/* TODO: What to do with NOTATIONs?
1264 	case XML_SCHEMA_TYPE_NOTATION:
1265 	    return (((xmlSchemaNotationPtr) item)->node);
1266 	*/
1267 	case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1268 	    return (((xmlSchemaAttributeUsePtr) item)->node);
1269 	default:
1270 	    return (NULL);
1271     }
1272 }
1273 
1274 #if 0
1275 /**
1276  * xmlSchemaGetNextComponent:
1277  * @item: a schema component
1278  *
1279  * Returns the next sibling of the schema component.
1280  */
1281 static xmlSchemaBasicItemPtr
1282 xmlSchemaGetNextComponent(xmlSchemaBasicItemPtr item)
1283 {
1284     switch (item->type) {
1285 	case XML_SCHEMA_TYPE_ELEMENT:
1286 	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaElementPtr) item)->next);
1287 	case XML_SCHEMA_TYPE_ATTRIBUTE:
1288 	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributePtr) item)->next);
1289 	case XML_SCHEMA_TYPE_COMPLEX:
1290 	case XML_SCHEMA_TYPE_SIMPLE:
1291 	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaTypePtr) item)->next);
1292 	case XML_SCHEMA_TYPE_ANY:
1293 	case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1294 	    return (NULL);
1295 	case XML_SCHEMA_TYPE_PARTICLE:
1296 	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaParticlePtr) item)->next);
1297 	case XML_SCHEMA_TYPE_SEQUENCE:
1298 	case XML_SCHEMA_TYPE_CHOICE:
1299 	case XML_SCHEMA_TYPE_ALL:
1300 	    return (NULL);
1301 	case XML_SCHEMA_TYPE_GROUP:
1302 	    return (NULL);
1303 	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1304 	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributeGroupPtr) item)->next);
1305 	case XML_SCHEMA_TYPE_IDC_UNIQUE:
1306 	case XML_SCHEMA_TYPE_IDC_KEY:
1307 	case XML_SCHEMA_TYPE_IDC_KEYREF:
1308 	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaIDCPtr) item)->next);
1309 	default:
1310 	    return (NULL);
1311     }
1312 }
1313 #endif
1314 
1315 
1316 /**
1317  * xmlSchemaFormatQName:
1318  * @buf: the string buffer
1319  * @namespaceName:  the namespace name
1320  * @localName: the local name
1321  *
1322  * Returns the given QName in the format "{namespaceName}localName" or
1323  * just "localName" if @namespaceName is NULL.
1324  *
1325  * Returns the localName if @namespaceName is NULL, a formatted
1326  * string otherwise.
1327  */
1328 static const xmlChar*
xmlSchemaFormatQName(xmlChar ** buf,const xmlChar * namespaceName,const xmlChar * localName)1329 xmlSchemaFormatQName(xmlChar **buf,
1330 		     const xmlChar *namespaceName,
1331 		     const xmlChar *localName)
1332 {
1333     FREE_AND_NULL(*buf)
1334     if (namespaceName != NULL) {
1335 	*buf = xmlStrdup(BAD_CAST "{");
1336 	*buf = xmlStrcat(*buf, namespaceName);
1337 	*buf = xmlStrcat(*buf, BAD_CAST "}");
1338     }
1339     if (localName != NULL) {
1340 	if (namespaceName == NULL)
1341 	    return(localName);
1342 	*buf = xmlStrcat(*buf, localName);
1343     } else {
1344 	*buf = xmlStrcat(*buf, BAD_CAST "(NULL)");
1345     }
1346     return ((const xmlChar *) *buf);
1347 }
1348 
1349 static const xmlChar*
xmlSchemaFormatQNameNs(xmlChar ** buf,xmlNsPtr ns,const xmlChar * localName)1350 xmlSchemaFormatQNameNs(xmlChar **buf, xmlNsPtr ns, const xmlChar *localName)
1351 {
1352     if (ns != NULL)
1353 	return (xmlSchemaFormatQName(buf, ns->href, localName));
1354     else
1355 	return (xmlSchemaFormatQName(buf, NULL, localName));
1356 }
1357 
1358 static const xmlChar *
xmlSchemaGetComponentName(xmlSchemaBasicItemPtr item)1359 xmlSchemaGetComponentName(xmlSchemaBasicItemPtr item)
1360 {
1361     switch (item->type) {
1362 	case XML_SCHEMA_TYPE_ELEMENT:
1363 	    return (((xmlSchemaElementPtr) item)->name);
1364 	case XML_SCHEMA_TYPE_ATTRIBUTE:
1365 	    return (((xmlSchemaAttributePtr) item)->name);
1366 	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1367 	    return (((xmlSchemaAttributeGroupPtr) item)->name);
1368 	case XML_SCHEMA_TYPE_BASIC:
1369 	case XML_SCHEMA_TYPE_SIMPLE:
1370 	case XML_SCHEMA_TYPE_COMPLEX:
1371 	    return (((xmlSchemaTypePtr) item)->name);
1372 	case XML_SCHEMA_TYPE_GROUP:
1373 	    return (((xmlSchemaModelGroupDefPtr) item)->name);
1374 	case XML_SCHEMA_TYPE_IDC_KEY:
1375 	case XML_SCHEMA_TYPE_IDC_UNIQUE:
1376 	case XML_SCHEMA_TYPE_IDC_KEYREF:
1377 	    return (((xmlSchemaIDCPtr) item)->name);
1378 	case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1379 	    if (WXS_ATTRUSE_DECL(item) != NULL) {
1380 		return(xmlSchemaGetComponentName(
1381 		    WXS_BASIC_CAST WXS_ATTRUSE_DECL(item)));
1382 	    } else
1383 		return(NULL);
1384 	case XML_SCHEMA_EXTRA_QNAMEREF:
1385 	    return (((xmlSchemaQNameRefPtr) item)->name);
1386 	case XML_SCHEMA_TYPE_NOTATION:
1387 	    return (((xmlSchemaNotationPtr) item)->name);
1388 	default:
1389 	    /*
1390 	    * Other components cannot have names.
1391 	    */
1392 	    break;
1393     }
1394     return (NULL);
1395 }
1396 
1397 #define xmlSchemaGetQNameRefName(r) (WXS_QNAME_CAST (r))->name
1398 #define xmlSchemaGetQNameRefTargetNs(r) (WXS_QNAME_CAST (r))->targetNamespace
1399 /*
1400 static const xmlChar *
1401 xmlSchemaGetQNameRefName(void *ref)
1402 {
1403     return(((xmlSchemaQNameRefPtr) ref)->name);
1404 }
1405 
1406 static const xmlChar *
1407 xmlSchemaGetQNameRefTargetNs(void *ref)
1408 {
1409     return(((xmlSchemaQNameRefPtr) ref)->targetNamespace);
1410 }
1411 */
1412 
1413 static const xmlChar *
xmlSchemaGetComponentTargetNs(xmlSchemaBasicItemPtr item)1414 xmlSchemaGetComponentTargetNs(xmlSchemaBasicItemPtr item)
1415 {
1416     switch (item->type) {
1417 	case XML_SCHEMA_TYPE_ELEMENT:
1418 	    return (((xmlSchemaElementPtr) item)->targetNamespace);
1419 	case XML_SCHEMA_TYPE_ATTRIBUTE:
1420 	    return (((xmlSchemaAttributePtr) item)->targetNamespace);
1421 	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1422 	    return (((xmlSchemaAttributeGroupPtr) item)->targetNamespace);
1423 	case XML_SCHEMA_TYPE_BASIC:
1424 	    return (BAD_CAST "http://www.w3.org/2001/XMLSchema");
1425 	case XML_SCHEMA_TYPE_SIMPLE:
1426 	case XML_SCHEMA_TYPE_COMPLEX:
1427 	    return (((xmlSchemaTypePtr) item)->targetNamespace);
1428 	case XML_SCHEMA_TYPE_GROUP:
1429 	    return (((xmlSchemaModelGroupDefPtr) item)->targetNamespace);
1430 	case XML_SCHEMA_TYPE_IDC_KEY:
1431 	case XML_SCHEMA_TYPE_IDC_UNIQUE:
1432 	case XML_SCHEMA_TYPE_IDC_KEYREF:
1433 	    return (((xmlSchemaIDCPtr) item)->targetNamespace);
1434 	case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1435 	    if (WXS_ATTRUSE_DECL(item) != NULL) {
1436 		return(xmlSchemaGetComponentTargetNs(
1437 		    WXS_BASIC_CAST WXS_ATTRUSE_DECL(item)));
1438 	    }
1439 	    /* TODO: Will returning NULL break something? */
1440 	    break;
1441 	case XML_SCHEMA_EXTRA_QNAMEREF:
1442 	    return (((xmlSchemaQNameRefPtr) item)->targetNamespace);
1443 	case XML_SCHEMA_TYPE_NOTATION:
1444 	    return (((xmlSchemaNotationPtr) item)->targetNamespace);
1445 	default:
1446 	    /*
1447 	    * Other components cannot have names.
1448 	    */
1449 	    break;
1450     }
1451     return (NULL);
1452 }
1453 
1454 static const xmlChar*
xmlSchemaGetComponentQName(xmlChar ** buf,void * item)1455 xmlSchemaGetComponentQName(xmlChar **buf,
1456 			   void *item)
1457 {
1458     return (xmlSchemaFormatQName(buf,
1459 	xmlSchemaGetComponentTargetNs((xmlSchemaBasicItemPtr) item),
1460 	xmlSchemaGetComponentName((xmlSchemaBasicItemPtr) item)));
1461 }
1462 
1463 static const xmlChar*
xmlSchemaGetComponentDesignation(xmlChar ** buf,void * item)1464 xmlSchemaGetComponentDesignation(xmlChar **buf, void *item)
1465 {
1466     xmlChar *str = NULL;
1467 
1468     *buf = xmlStrcat(*buf, WXS_ITEM_TYPE_NAME(item));
1469     *buf = xmlStrcat(*buf, BAD_CAST " '");
1470     *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str,
1471 	(xmlSchemaBasicItemPtr) item));
1472     *buf = xmlStrcat(*buf, BAD_CAST "'");
1473     FREE_AND_NULL(str);
1474     return(*buf);
1475 }
1476 
1477 static const xmlChar*
xmlSchemaGetIDCDesignation(xmlChar ** buf,xmlSchemaIDCPtr idc)1478 xmlSchemaGetIDCDesignation(xmlChar **buf, xmlSchemaIDCPtr idc)
1479 {
1480     return(xmlSchemaGetComponentDesignation(buf, idc));
1481 }
1482 
1483 /**
1484  * xmlSchemaWildcardPCToString:
1485  * @pc: the type of processContents
1486  *
1487  * Returns a string representation of the type of
1488  * processContents.
1489  */
1490 static const xmlChar *
xmlSchemaWildcardPCToString(int pc)1491 xmlSchemaWildcardPCToString(int pc)
1492 {
1493     switch (pc) {
1494 	case XML_SCHEMAS_ANY_SKIP:
1495 	    return (BAD_CAST "skip");
1496 	case XML_SCHEMAS_ANY_LAX:
1497 	    return (BAD_CAST "lax");
1498 	case XML_SCHEMAS_ANY_STRICT:
1499 	    return (BAD_CAST "strict");
1500 	default:
1501 	    return (BAD_CAST "invalid process contents");
1502     }
1503 }
1504 
1505 /**
1506  * xmlSchemaGetCanonValueWhtspExt:
1507  * @val: the precomputed value
1508  * @retValue: the returned value
1509  * @ws: the whitespace type of the value
1510  *
1511  * Get a the canonical representation of the value.
1512  * The caller has to free the returned retValue.
1513  *
1514  * Returns 0 if the value could be built and -1 in case of
1515  *         API errors or if the value type is not supported yet.
1516  */
1517 static int
xmlSchemaGetCanonValueWhtspExt(xmlSchemaValPtr val,xmlSchemaWhitespaceValueType ws,xmlChar ** retValue)1518 xmlSchemaGetCanonValueWhtspExt(xmlSchemaValPtr val,
1519 			       xmlSchemaWhitespaceValueType ws,
1520 			       xmlChar **retValue)
1521 {
1522     int list;
1523     xmlSchemaValType valType;
1524     const xmlChar *value, *value2 = NULL;
1525 
1526 
1527     if ((retValue == NULL) || (val == NULL))
1528 	return (-1);
1529     list = xmlSchemaValueGetNext(val) ? 1 : 0;
1530     *retValue = NULL;
1531     do {
1532 	value = NULL;
1533 	valType = xmlSchemaGetValType(val);
1534 	switch (valType) {
1535 	    case XML_SCHEMAS_STRING:
1536 	    case XML_SCHEMAS_NORMSTRING:
1537 	    case XML_SCHEMAS_ANYSIMPLETYPE:
1538 		value = xmlSchemaValueGetAsString(val);
1539 		if (value != NULL) {
1540 		    if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
1541 			value2 = xmlSchemaCollapseString(value);
1542 		    else if (ws == XML_SCHEMA_WHITESPACE_REPLACE)
1543 			value2 = xmlSchemaWhiteSpaceReplace(value);
1544 		    if (value2 != NULL)
1545 			value = value2;
1546 		}
1547 		break;
1548 	    default:
1549 		if (xmlSchemaGetCanonValue(val, &value2) == -1) {
1550 		    if (value2 != NULL)
1551 			xmlFree((xmlChar *) value2);
1552 		    goto internal_error;
1553 		}
1554 		value = value2;
1555 	}
1556 	if (*retValue == NULL)
1557 	    if (value == NULL) {
1558 		if (! list)
1559 		    *retValue = xmlStrdup(BAD_CAST "");
1560 	    } else
1561 		*retValue = xmlStrdup(value);
1562 	else if (value != NULL) {
1563 	    /* List. */
1564 	    *retValue = xmlStrcat((xmlChar *) *retValue, BAD_CAST " ");
1565 	    *retValue = xmlStrcat((xmlChar *) *retValue, value);
1566 	}
1567 	FREE_AND_NULL(value2)
1568 	val = xmlSchemaValueGetNext(val);
1569     } while (val != NULL);
1570 
1571     return (0);
1572 internal_error:
1573     if (*retValue != NULL)
1574 	xmlFree((xmlChar *) (*retValue));
1575     if (value2 != NULL)
1576 	xmlFree((xmlChar *) value2);
1577     return (-1);
1578 }
1579 
1580 /**
1581  * xmlSchemaFormatItemForReport:
1582  * @buf: the string buffer
1583  * @itemDes: the designation of the item
1584  * @itemName: the name of the item
1585  * @item: the item as an object
1586  * @itemNode: the node of the item
1587  * @local: the local name
1588  * @parsing: if the function is used during the parse
1589  *
1590  * Returns a representation of the given item used
1591  * for error reports.
1592  *
1593  * The following order is used to build the resulting
1594  * designation if the arguments are not NULL:
1595  * 1a. If itemDes not NULL -> itemDes
1596  * 1b. If (itemDes not NULL) and (itemName not NULL)
1597  *     -> itemDes + itemName
1598  * 2. If the preceding was NULL and (item not NULL) -> item
1599  * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
1600  *
1601  * If the itemNode is an attribute node, the name of the attribute
1602  * will be appended to the result.
1603  *
1604  * Returns the formatted string and sets @buf to the resulting value.
1605  */
1606 static xmlChar*
xmlSchemaFormatItemForReport(xmlChar ** buf,const xmlChar * itemDes,xmlSchemaBasicItemPtr item,xmlNodePtr itemNode)1607 xmlSchemaFormatItemForReport(xmlChar **buf,
1608 		     const xmlChar *itemDes,
1609 		     xmlSchemaBasicItemPtr item,
1610 		     xmlNodePtr itemNode)
1611 {
1612     xmlChar *str = NULL;
1613     int named = 1;
1614 
1615     if (*buf != NULL) {
1616 	xmlFree(*buf);
1617 	*buf = NULL;
1618     }
1619 
1620     if (itemDes != NULL) {
1621 	*buf = xmlStrdup(itemDes);
1622     } else if (item != NULL) {
1623 	switch (item->type) {
1624 	case XML_SCHEMA_TYPE_BASIC: {
1625 	    xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1626 
1627 	    if (WXS_IS_ATOMIC(type))
1628 		*buf = xmlStrdup(BAD_CAST "atomic type 'xs:");
1629 	    else if (WXS_IS_LIST(type))
1630 		*buf = xmlStrdup(BAD_CAST "list type 'xs:");
1631 	    else if (WXS_IS_UNION(type))
1632 		*buf = xmlStrdup(BAD_CAST "union type 'xs:");
1633 	    else
1634 		*buf = xmlStrdup(BAD_CAST "simple type 'xs:");
1635 	    *buf = xmlStrcat(*buf, type->name);
1636 	    *buf = xmlStrcat(*buf, BAD_CAST "'");
1637 	    }
1638 	    break;
1639 	case XML_SCHEMA_TYPE_SIMPLE: {
1640 	    xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1641 
1642 	    if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1643 		*buf = xmlStrdup(BAD_CAST"");
1644 	    } else {
1645 		*buf = xmlStrdup(BAD_CAST "local ");
1646 	    }
1647 	    if (WXS_IS_ATOMIC(type))
1648 		*buf = xmlStrcat(*buf, BAD_CAST "atomic type");
1649 	    else if (WXS_IS_LIST(type))
1650 		*buf = xmlStrcat(*buf, BAD_CAST "list type");
1651 	    else if (WXS_IS_UNION(type))
1652 		*buf = xmlStrcat(*buf, BAD_CAST "union type");
1653 	    else
1654 		*buf = xmlStrcat(*buf, BAD_CAST "simple type");
1655 	    if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1656 		*buf = xmlStrcat(*buf, BAD_CAST " '");
1657 		*buf = xmlStrcat(*buf, type->name);
1658 		*buf = xmlStrcat(*buf, BAD_CAST "'");
1659 	    }
1660 	    }
1661 	    break;
1662 	case XML_SCHEMA_TYPE_COMPLEX: {
1663 	    xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1664 
1665 	    if (type->flags & XML_SCHEMAS_TYPE_GLOBAL)
1666 		*buf = xmlStrdup(BAD_CAST "");
1667 	    else
1668 		*buf = xmlStrdup(BAD_CAST "local ");
1669 	    *buf = xmlStrcat(*buf, BAD_CAST "complex type");
1670 	    if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1671 		*buf = xmlStrcat(*buf, BAD_CAST " '");
1672 		*buf = xmlStrcat(*buf, type->name);
1673 		*buf = xmlStrcat(*buf, BAD_CAST "'");
1674 	    }
1675 	    }
1676 	    break;
1677 	case XML_SCHEMA_TYPE_ATTRIBUTE_USE: {
1678 		xmlSchemaAttributeUsePtr ause;
1679 
1680 		ause = WXS_ATTR_USE_CAST item;
1681 		*buf = xmlStrdup(BAD_CAST "attribute use ");
1682 		if (WXS_ATTRUSE_DECL(ause) != NULL) {
1683 		    *buf = xmlStrcat(*buf, BAD_CAST "'");
1684 		    *buf = xmlStrcat(*buf,
1685 			xmlSchemaGetComponentQName(&str, WXS_ATTRUSE_DECL(ause)));
1686 		    FREE_AND_NULL(str)
1687 			*buf = xmlStrcat(*buf, BAD_CAST "'");
1688 		} else {
1689 		    *buf = xmlStrcat(*buf, BAD_CAST "(unknown)");
1690 		}
1691 	    }
1692 	    break;
1693 	case XML_SCHEMA_TYPE_ATTRIBUTE: {
1694 		xmlSchemaAttributePtr attr;
1695 
1696 		attr = (xmlSchemaAttributePtr) item;
1697 		*buf = xmlStrdup(BAD_CAST "attribute decl.");
1698 		*buf = xmlStrcat(*buf, BAD_CAST " '");
1699 		*buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1700 		    attr->targetNamespace, attr->name));
1701 		FREE_AND_NULL(str)
1702 		    *buf = xmlStrcat(*buf, BAD_CAST "'");
1703 	    }
1704 	    break;
1705 	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1706 	    xmlSchemaGetComponentDesignation(buf, item);
1707 	    break;
1708 	case XML_SCHEMA_TYPE_ELEMENT: {
1709 		xmlSchemaElementPtr elem;
1710 
1711 		elem = (xmlSchemaElementPtr) item;
1712 		*buf = xmlStrdup(BAD_CAST "element decl.");
1713 		*buf = xmlStrcat(*buf, BAD_CAST " '");
1714 		*buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1715 		    elem->targetNamespace, elem->name));
1716 		*buf = xmlStrcat(*buf, BAD_CAST "'");
1717 	    }
1718 	    break;
1719 	case XML_SCHEMA_TYPE_IDC_UNIQUE:
1720 	case XML_SCHEMA_TYPE_IDC_KEY:
1721 	case XML_SCHEMA_TYPE_IDC_KEYREF:
1722 	    if (item->type == XML_SCHEMA_TYPE_IDC_UNIQUE)
1723 		*buf = xmlStrdup(BAD_CAST "unique '");
1724 	    else if (item->type == XML_SCHEMA_TYPE_IDC_KEY)
1725 		*buf = xmlStrdup(BAD_CAST "key '");
1726 	    else
1727 		*buf = xmlStrdup(BAD_CAST "keyRef '");
1728 	    *buf = xmlStrcat(*buf, ((xmlSchemaIDCPtr) item)->name);
1729 	    *buf = xmlStrcat(*buf, BAD_CAST "'");
1730 	    break;
1731 	case XML_SCHEMA_TYPE_ANY:
1732 	case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1733 	    *buf = xmlStrdup(xmlSchemaWildcardPCToString(
1734 		    ((xmlSchemaWildcardPtr) item)->processContents));
1735 	    *buf = xmlStrcat(*buf, BAD_CAST " wildcard");
1736 	    break;
1737 	case XML_SCHEMA_FACET_MININCLUSIVE:
1738 	case XML_SCHEMA_FACET_MINEXCLUSIVE:
1739 	case XML_SCHEMA_FACET_MAXINCLUSIVE:
1740 	case XML_SCHEMA_FACET_MAXEXCLUSIVE:
1741 	case XML_SCHEMA_FACET_TOTALDIGITS:
1742 	case XML_SCHEMA_FACET_FRACTIONDIGITS:
1743 	case XML_SCHEMA_FACET_PATTERN:
1744 	case XML_SCHEMA_FACET_ENUMERATION:
1745 	case XML_SCHEMA_FACET_WHITESPACE:
1746 	case XML_SCHEMA_FACET_LENGTH:
1747 	case XML_SCHEMA_FACET_MAXLENGTH:
1748 	case XML_SCHEMA_FACET_MINLENGTH:
1749 	    *buf = xmlStrdup(BAD_CAST "facet '");
1750 	    *buf = xmlStrcat(*buf, xmlSchemaFacetTypeToString(item->type));
1751 	    *buf = xmlStrcat(*buf, BAD_CAST "'");
1752 	    break;
1753 	case XML_SCHEMA_TYPE_GROUP: {
1754 		*buf = xmlStrdup(BAD_CAST "model group def.");
1755 		*buf = xmlStrcat(*buf, BAD_CAST " '");
1756 		*buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, item));
1757 		*buf = xmlStrcat(*buf, BAD_CAST "'");
1758 		FREE_AND_NULL(str)
1759 	    }
1760 	    break;
1761 	case XML_SCHEMA_TYPE_SEQUENCE:
1762 	case XML_SCHEMA_TYPE_CHOICE:
1763 	case XML_SCHEMA_TYPE_ALL:
1764 	case XML_SCHEMA_TYPE_PARTICLE:
1765 	    *buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item));
1766 	    break;
1767 	case XML_SCHEMA_TYPE_NOTATION: {
1768 		*buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item));
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             /* Falls through. */
1775 	default:
1776 	    named = 0;
1777 	}
1778     } else
1779 	named = 0;
1780 
1781     if ((named == 0) && (itemNode != NULL)) {
1782 	xmlNodePtr elem;
1783 
1784 	if (itemNode->type == XML_ATTRIBUTE_NODE)
1785 	    elem = itemNode->parent;
1786 	else
1787 	    elem = itemNode;
1788 	*buf = xmlStrdup(BAD_CAST "Element '");
1789 	if (elem->ns != NULL) {
1790 	    *buf = xmlStrcat(*buf,
1791 		xmlSchemaFormatQName(&str, elem->ns->href, elem->name));
1792 	    FREE_AND_NULL(str)
1793 	} else
1794 	    *buf = xmlStrcat(*buf, elem->name);
1795 	*buf = xmlStrcat(*buf, BAD_CAST "'");
1796 
1797     }
1798     if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
1799 	*buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
1800 	if (itemNode->ns != NULL) {
1801 	    *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1802 		itemNode->ns->href, itemNode->name));
1803 	    FREE_AND_NULL(str)
1804 	} else
1805 	    *buf = xmlStrcat(*buf, itemNode->name);
1806 	*buf = xmlStrcat(*buf, BAD_CAST "'");
1807     }
1808     FREE_AND_NULL(str)
1809 
1810     return (xmlEscapeFormatString(buf));
1811 }
1812 
1813 /**
1814  * xmlSchemaFormatFacetEnumSet:
1815  * @buf: the string buffer
1816  * @type: the type holding the enumeration facets
1817  *
1818  * Builds a string consisting of all enumeration elements.
1819  *
1820  * Returns a string of all enumeration elements.
1821  */
1822 static const xmlChar *
xmlSchemaFormatFacetEnumSet(xmlSchemaAbstractCtxtPtr actxt,xmlChar ** buf,xmlSchemaTypePtr type)1823 xmlSchemaFormatFacetEnumSet(xmlSchemaAbstractCtxtPtr actxt,
1824 			    xmlChar **buf, xmlSchemaTypePtr type)
1825 {
1826     xmlSchemaFacetPtr facet;
1827     xmlSchemaWhitespaceValueType ws;
1828     xmlChar *value = NULL;
1829     int res, found = 0;
1830 
1831     if (*buf != NULL)
1832 	xmlFree(*buf);
1833     *buf = NULL;
1834 
1835     do {
1836 	/*
1837 	* Use the whitespace type of the base type.
1838 	*/
1839 	ws = xmlSchemaGetWhiteSpaceFacetValue(type->baseType);
1840 	for (facet = type->facets; facet != NULL; facet = facet->next) {
1841 	    if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
1842 		continue;
1843 	    found = 1;
1844 	    res = xmlSchemaGetCanonValueWhtspExt(facet->val,
1845 		ws, &value);
1846 	    if (res == -1) {
1847 		xmlSchemaInternalErr(actxt,
1848 		    "xmlSchemaFormatFacetEnumSet",
1849 		    "compute the canonical lexical representation");
1850 		if (*buf != NULL)
1851 		    xmlFree(*buf);
1852 		*buf = NULL;
1853 		return (NULL);
1854 	    }
1855 	    if (*buf == NULL)
1856 		*buf = xmlStrdup(BAD_CAST "'");
1857 	    else
1858 		*buf = xmlStrcat(*buf, BAD_CAST ", '");
1859 	    *buf = xmlStrcat(*buf, BAD_CAST value);
1860 	    *buf = xmlStrcat(*buf, BAD_CAST "'");
1861 	    if (value != NULL) {
1862 		xmlFree((xmlChar *)value);
1863 		value = NULL;
1864 	    }
1865 	}
1866 	/*
1867 	* The enumeration facet of a type restricts the enumeration
1868 	* facet of the ancestor type; i.e., such restricted enumerations
1869 	* do not belong to the set of the given type. Thus we break
1870 	* on the first found enumeration.
1871 	*/
1872 	if (found)
1873 	    break;
1874 	type = type->baseType;
1875     } while ((type != NULL) && (type->type != XML_SCHEMA_TYPE_BASIC));
1876 
1877     return ((const xmlChar *) *buf);
1878 }
1879 
1880 /************************************************************************
1881  *									*
1882  *			Error functions				        *
1883  *									*
1884  ************************************************************************/
1885 
1886 #if 0
1887 static void
1888 xmlSchemaErrMemory(const char *msg)
1889 {
1890     __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
1891                      msg);
1892 }
1893 #endif
1894 
1895 static void
xmlSchemaPSimpleErr(const char * msg)1896 xmlSchemaPSimpleErr(const char *msg)
1897 {
1898     __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
1899                      msg);
1900 }
1901 
1902 /**
1903  * xmlSchemaPErrMemory:
1904  * @node: a context node
1905  * @extra:  extra informations
1906  *
1907  * Handle an out of memory condition
1908  */
1909 static void
xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,const char * extra,xmlNodePtr node)1910 xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
1911                     const char *extra, xmlNodePtr node)
1912 {
1913     if (ctxt != NULL)
1914         ctxt->nberrors++;
1915     __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
1916                      extra);
1917 }
1918 
1919 /**
1920  * xmlSchemaPErr:
1921  * @ctxt: the parsing context
1922  * @node: the context node
1923  * @error: the error code
1924  * @msg: the error message
1925  * @str1: extra data
1926  * @str2: extra data
1927  *
1928  * Handle a parser error
1929  */
1930 static void LIBXML_ATTR_FORMAT(4,0)
xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,int error,const char * msg,const xmlChar * str1,const xmlChar * str2)1931 xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1932               const char *msg, const xmlChar * str1, const xmlChar * str2)
1933 {
1934     xmlGenericErrorFunc channel = NULL;
1935     xmlStructuredErrorFunc schannel = NULL;
1936     void *data = NULL;
1937 
1938     if (ctxt != NULL) {
1939         ctxt->nberrors++;
1940 	ctxt->err = error;
1941         channel = ctxt->error;
1942         data = ctxt->errCtxt;
1943 	schannel = ctxt->serror;
1944     }
1945     __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
1946                     error, XML_ERR_ERROR, NULL, 0,
1947                     (const char *) str1, (const char *) str2, NULL, 0, 0,
1948                     msg, str1, str2);
1949 }
1950 
1951 /**
1952  * xmlSchemaPErr2:
1953  * @ctxt: the parsing context
1954  * @node: the context node
1955  * @node: the current child
1956  * @error: the error code
1957  * @msg: the error message
1958  * @str1: extra data
1959  * @str2: extra data
1960  *
1961  * Handle a parser error
1962  */
1963 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)1964 xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
1965                xmlNodePtr child, int error,
1966                const char *msg, const xmlChar * str1, const xmlChar * str2)
1967 {
1968     if (child != NULL)
1969         xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
1970     else
1971         xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
1972 }
1973 
1974 
1975 /**
1976  * xmlSchemaPErrExt:
1977  * @ctxt: the parsing context
1978  * @node: the context node
1979  * @error: the error code
1980  * @strData1: extra data
1981  * @strData2: extra data
1982  * @strData3: extra data
1983  * @msg: the message
1984  * @str1:  extra parameter for the message display
1985  * @str2:  extra parameter for the message display
1986  * @str3:  extra parameter for the message display
1987  * @str4:  extra parameter for the message display
1988  * @str5:  extra parameter for the message display
1989  *
1990  * Handle a parser error
1991  */
1992 static void LIBXML_ATTR_FORMAT(7,0)
xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,int error,const xmlChar * strData1,const xmlChar * strData2,const xmlChar * strData3,const char * msg,const xmlChar * str1,const xmlChar * str2,const xmlChar * str3,const xmlChar * str4,const xmlChar * str5)1993 xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1994 		const xmlChar * strData1, const xmlChar * strData2,
1995 		const xmlChar * strData3, const char *msg, const xmlChar * str1,
1996 		const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
1997 		const xmlChar * str5)
1998 {
1999 
2000     xmlGenericErrorFunc channel = NULL;
2001     xmlStructuredErrorFunc schannel = NULL;
2002     void *data = NULL;
2003 
2004     if (ctxt != NULL) {
2005         ctxt->nberrors++;
2006 	ctxt->err = error;
2007         channel = ctxt->error;
2008         data = ctxt->errCtxt;
2009 	schannel = ctxt->serror;
2010     }
2011     __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
2012                     error, XML_ERR_ERROR, NULL, 0,
2013                     (const char *) strData1, (const char *) strData2,
2014 		    (const char *) strData3, 0, 0, msg, str1, str2,
2015 		    str3, str4, str5);
2016 }
2017 
2018 /************************************************************************
2019  *									*
2020  *			Allround error functions			*
2021  *									*
2022  ************************************************************************/
2023 
2024 /**
2025  * xmlSchemaVTypeErrMemory:
2026  * @node: a context node
2027  * @extra:  extra informations
2028  *
2029  * Handle an out of memory condition
2030  */
2031 static void
xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,const char * extra,xmlNodePtr node)2032 xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
2033                     const char *extra, xmlNodePtr node)
2034 {
2035     if (ctxt != NULL) {
2036         ctxt->nberrors++;
2037         ctxt->err = XML_SCHEMAV_INTERNAL;
2038     }
2039     __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
2040                      extra);
2041 }
2042 
2043 static void LIBXML_ATTR_FORMAT(2,0)
xmlSchemaPSimpleInternalErr(xmlNodePtr node,const char * msg,const xmlChar * str)2044 xmlSchemaPSimpleInternalErr(xmlNodePtr node,
2045 			    const char *msg, const xmlChar *str)
2046 {
2047      __xmlSimpleError(XML_FROM_SCHEMASP, XML_SCHEMAP_INTERNAL, node,
2048 	 msg, (const char *) str);
2049 }
2050 
2051 #define WXS_ERROR_TYPE_ERROR 1
2052 #define WXS_ERROR_TYPE_WARNING 2
2053 /**
2054  * xmlSchemaErr4Line:
2055  * @ctxt: the validation context
2056  * @errorLevel: the error level
2057  * @error: the error code
2058  * @node: the context node
2059  * @line: the line number
2060  * @msg: the error message
2061  * @str1: extra data
2062  * @str2: extra data
2063  * @str3: extra data
2064  * @str4: extra data
2065  *
2066  * Handle a validation error
2067  */
2068 static void LIBXML_ATTR_FORMAT(6,0)
xmlSchemaErr4Line(xmlSchemaAbstractCtxtPtr ctxt,xmlErrorLevel errorLevel,int error,xmlNodePtr node,int line,const char * msg,const xmlChar * str1,const xmlChar * str2,const xmlChar * str3,const xmlChar * str4)2069 xmlSchemaErr4Line(xmlSchemaAbstractCtxtPtr ctxt,
2070 		  xmlErrorLevel errorLevel,
2071 		  int error, xmlNodePtr node, int line, const char *msg,
2072 		  const xmlChar *str1, const xmlChar *str2,
2073 		  const xmlChar *str3, const xmlChar *str4)
2074 {
2075     xmlStructuredErrorFunc schannel = NULL;
2076     xmlGenericErrorFunc channel = NULL;
2077     void *data = NULL;
2078 
2079     if (ctxt != NULL) {
2080 	if (ctxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
2081 	    xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctxt;
2082 	    const char *file = NULL;
2083 	    int col = 0;
2084 	    if (errorLevel != XML_ERR_WARNING) {
2085 		vctxt->nberrors++;
2086 		vctxt->err = error;
2087 		channel = vctxt->error;
2088 	    } else {
2089 		channel = vctxt->warning;
2090 	    }
2091 	    schannel = vctxt->serror;
2092 	    data = vctxt->errCtxt;
2093 
2094 	    /*
2095 	    * Error node. If we specify a line number, then
2096 	    * do not channel any node to the error function.
2097 	    */
2098 	    if (line == 0) {
2099 		if ((node == NULL) &&
2100 		    (vctxt->depth >= 0) &&
2101 		    (vctxt->inode != NULL)) {
2102 		    node = vctxt->inode->node;
2103 		}
2104 		/*
2105 		* Get filename and line if no node-tree.
2106 		*/
2107 		if ((node == NULL) &&
2108 		    (vctxt->parserCtxt != NULL) &&
2109 		    (vctxt->parserCtxt->input != NULL)) {
2110 		    file = vctxt->parserCtxt->input->filename;
2111 		    line = vctxt->parserCtxt->input->line;
2112 		    col = vctxt->parserCtxt->input->col;
2113 		}
2114 	    } else {
2115 		/*
2116 		* Override the given node's (if any) position
2117 		* and channel only the given line number.
2118 		*/
2119 		node = NULL;
2120 		/*
2121 		* Get filename.
2122 		*/
2123 		if (vctxt->doc != NULL)
2124 		    file = (const char *) vctxt->doc->URL;
2125 		else if ((vctxt->parserCtxt != NULL) &&
2126 		    (vctxt->parserCtxt->input != NULL))
2127 		    file = vctxt->parserCtxt->input->filename;
2128 	    }
2129 	    if (vctxt->locFunc != NULL) {
2130 	        if ((file == NULL) || (line == 0)) {
2131 		    unsigned long l;
2132 		    const char *f;
2133 		    vctxt->locFunc(vctxt->locCtxt, &f, &l);
2134 		    if (file == NULL)
2135 		        file = f;
2136 		    if (line == 0)
2137 		        line = (int) l;
2138 		}
2139 	    }
2140 	    if ((file == NULL) && (vctxt->filename != NULL))
2141 	        file = vctxt->filename;
2142 
2143 	    __xmlRaiseError(schannel, channel, data, ctxt,
2144 		node, XML_FROM_SCHEMASV,
2145 		error, errorLevel, file, line,
2146 		(const char *) str1, (const char *) str2,
2147 		(const char *) str3, 0, col, msg, str1, str2, str3, str4);
2148 
2149 	} else if (ctxt->type == XML_SCHEMA_CTXT_PARSER) {
2150 	    xmlSchemaParserCtxtPtr pctxt = (xmlSchemaParserCtxtPtr) ctxt;
2151 	    if (errorLevel != XML_ERR_WARNING) {
2152 		pctxt->nberrors++;
2153 		pctxt->err = error;
2154 		channel = pctxt->error;
2155 	    } else {
2156 		channel = pctxt->warning;
2157 	    }
2158 	    schannel = pctxt->serror;
2159 	    data = pctxt->errCtxt;
2160 	    __xmlRaiseError(schannel, channel, data, ctxt,
2161 		node, XML_FROM_SCHEMASP, error,
2162 		errorLevel, NULL, 0,
2163 		(const char *) str1, (const char *) str2,
2164 		(const char *) str3, 0, 0, msg, str1, str2, str3, str4);
2165 	} else {
2166 	    TODO
2167 	}
2168     }
2169 }
2170 
2171 /**
2172  * xmlSchemaErr3:
2173  * @ctxt: the validation context
2174  * @node: the context node
2175  * @error: the error code
2176  * @msg: the error message
2177  * @str1: extra data
2178  * @str2: extra data
2179  * @str3: extra data
2180  *
2181  * Handle a validation error
2182  */
2183 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)2184 xmlSchemaErr3(xmlSchemaAbstractCtxtPtr actxt,
2185 	      int error, xmlNodePtr node, const char *msg,
2186 	      const xmlChar *str1, const xmlChar *str2, const xmlChar *str3)
2187 {
2188     xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0,
2189 	msg, str1, str2, str3, NULL);
2190 }
2191 
2192 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)2193 xmlSchemaErr4(xmlSchemaAbstractCtxtPtr actxt,
2194 	      int error, xmlNodePtr node, const char *msg,
2195 	      const xmlChar *str1, const xmlChar *str2,
2196 	      const xmlChar *str3, const xmlChar *str4)
2197 {
2198     xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0,
2199 	msg, str1, str2, str3, str4);
2200 }
2201 
2202 static void LIBXML_ATTR_FORMAT(4,0)
xmlSchemaErr(xmlSchemaAbstractCtxtPtr actxt,int error,xmlNodePtr node,const char * msg,const xmlChar * str1,const xmlChar * str2)2203 xmlSchemaErr(xmlSchemaAbstractCtxtPtr actxt,
2204 	     int error, xmlNodePtr node, const char *msg,
2205 	     const xmlChar *str1, const xmlChar *str2)
2206 {
2207     xmlSchemaErr4(actxt, error, node, msg, str1, str2, NULL, NULL);
2208 }
2209 
2210 static xmlChar *
xmlSchemaFormatNodeForError(xmlChar ** msg,xmlSchemaAbstractCtxtPtr actxt,xmlNodePtr node)2211 xmlSchemaFormatNodeForError(xmlChar ** msg,
2212 			    xmlSchemaAbstractCtxtPtr actxt,
2213 			    xmlNodePtr node)
2214 {
2215     xmlChar *str = NULL;
2216 
2217     *msg = NULL;
2218     if ((node != NULL) &&
2219 	(node->type != XML_ELEMENT_NODE) &&
2220 	(node->type != XML_ATTRIBUTE_NODE))
2221     {
2222 	/*
2223 	* Don't try to format other nodes than element and
2224 	* attribute nodes.
2225 	* Play safe and return an empty string.
2226 	*/
2227 	*msg = xmlStrdup(BAD_CAST "");
2228 	return(*msg);
2229     }
2230     if (node != NULL) {
2231 	/*
2232 	* Work on tree nodes.
2233 	*/
2234 	if (node->type == XML_ATTRIBUTE_NODE) {
2235 	    xmlNodePtr elem = node->parent;
2236 
2237 	    *msg = xmlStrdup(BAD_CAST "Element '");
2238 	    if (elem->ns != NULL)
2239 		*msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2240 		    elem->ns->href, elem->name));
2241 	    else
2242 		*msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2243 		    NULL, elem->name));
2244 	    FREE_AND_NULL(str);
2245 	    *msg = xmlStrcat(*msg, BAD_CAST "', ");
2246 	    *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
2247 	} else {
2248 	    *msg = xmlStrdup(BAD_CAST "Element '");
2249 	}
2250 	if (node->ns != NULL)
2251 	    *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2252 	    node->ns->href, node->name));
2253 	else
2254 	    *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2255 	    NULL, node->name));
2256 	FREE_AND_NULL(str);
2257 	*msg = xmlStrcat(*msg, BAD_CAST "': ");
2258     } else if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
2259 	xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) actxt;
2260 	/*
2261 	* Work on node infos.
2262 	*/
2263 	if (vctxt->inode->nodeType == XML_ATTRIBUTE_NODE) {
2264 	    xmlSchemaNodeInfoPtr ielem =
2265 		vctxt->elemInfos[vctxt->depth];
2266 
2267 	    *msg = xmlStrdup(BAD_CAST "Element '");
2268 	    *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2269 		ielem->nsName, ielem->localName));
2270 	    FREE_AND_NULL(str);
2271 	    *msg = xmlStrcat(*msg, BAD_CAST "', ");
2272 	    *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
2273 	} else {
2274 	    *msg = xmlStrdup(BAD_CAST "Element '");
2275 	}
2276 	*msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2277 	    vctxt->inode->nsName, vctxt->inode->localName));
2278 	FREE_AND_NULL(str);
2279 	*msg = xmlStrcat(*msg, BAD_CAST "': ");
2280     } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
2281 	/*
2282 	* Hmm, no node while parsing?
2283 	* Return an empty string, in case NULL will break something.
2284 	*/
2285 	*msg = xmlStrdup(BAD_CAST "");
2286     } else {
2287 	TODO
2288 	return (NULL);
2289     }
2290 
2291     /*
2292      * xmlSchemaFormatItemForReport() also returns an escaped format
2293      * string, so do this before calling it below (in the future).
2294      */
2295     xmlEscapeFormatString(msg);
2296 
2297     /*
2298     * VAL TODO: The output of the given schema component is currently
2299     * disabled.
2300     */
2301 #if 0
2302     if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
2303 	*msg = xmlStrcat(*msg, BAD_CAST " [");
2304 	*msg = xmlStrcat(*msg, xmlSchemaFormatItemForReport(&str,
2305 	    NULL, type, NULL, 0));
2306 	FREE_AND_NULL(str)
2307 	*msg = xmlStrcat(*msg, BAD_CAST "]");
2308     }
2309 #endif
2310     return (*msg);
2311 }
2312 
2313 static void LIBXML_ATTR_FORMAT(3,0)
xmlSchemaInternalErr2(xmlSchemaAbstractCtxtPtr actxt,const char * funcName,const char * message,const xmlChar * str1,const xmlChar * str2)2314 xmlSchemaInternalErr2(xmlSchemaAbstractCtxtPtr actxt,
2315 		     const char *funcName,
2316 		     const char *message,
2317 		     const xmlChar *str1,
2318 		     const xmlChar *str2)
2319 {
2320     xmlChar *msg = NULL;
2321 
2322     if (actxt == NULL)
2323         return;
2324     msg = xmlStrdup(BAD_CAST "Internal error: %s, ");
2325     msg = xmlStrcat(msg, BAD_CAST message);
2326     msg = xmlStrcat(msg, BAD_CAST ".\n");
2327 
2328     if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR)
2329 	xmlSchemaErr3(actxt, XML_SCHEMAV_INTERNAL, NULL,
2330 	    (const char *) msg, (const xmlChar *) funcName, str1, str2);
2331     else if (actxt->type == XML_SCHEMA_CTXT_PARSER)
2332 	xmlSchemaErr3(actxt, XML_SCHEMAP_INTERNAL, NULL,
2333 	    (const char *) msg, (const xmlChar *) funcName, str1, str2);
2334 
2335     FREE_AND_NULL(msg)
2336 }
2337 
2338 static void LIBXML_ATTR_FORMAT(3,0)
xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,const char * funcName,const char * message)2339 xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
2340 		     const char *funcName,
2341 		     const char *message)
2342 {
2343     xmlSchemaInternalErr2(actxt, funcName, message, NULL, NULL);
2344 }
2345 
2346 #if 0
2347 static void LIBXML_ATTR_FORMAT(3,0)
2348 xmlSchemaPInternalErr(xmlSchemaParserCtxtPtr pctxt,
2349 		     const char *funcName,
2350 		     const char *message,
2351 		     const xmlChar *str1,
2352 		     const xmlChar *str2)
2353 {
2354     xmlSchemaInternalErr2(ACTXT_CAST pctxt, funcName, message,
2355 	str1, str2);
2356 }
2357 #endif
2358 
2359 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)2360 xmlSchemaCustomErr4(xmlSchemaAbstractCtxtPtr actxt,
2361 		   xmlParserErrors error,
2362 		   xmlNodePtr node,
2363 		   xmlSchemaBasicItemPtr item,
2364 		   const char *message,
2365 		   const xmlChar *str1, const xmlChar *str2,
2366 		   const xmlChar *str3, const xmlChar *str4)
2367 {
2368     xmlChar *msg = NULL;
2369 
2370     if ((node == NULL) && (item != NULL) &&
2371 	(actxt->type == XML_SCHEMA_CTXT_PARSER)) {
2372 	node = WXS_ITEM_NODE(item);
2373 	xmlSchemaFormatItemForReport(&msg, NULL, item, NULL);
2374 	msg = xmlStrcat(msg, BAD_CAST ": ");
2375     } else
2376 	xmlSchemaFormatNodeForError(&msg, actxt, node);
2377     msg = xmlStrcat(msg, (const xmlChar *) message);
2378     msg = xmlStrcat(msg, BAD_CAST ".\n");
2379     xmlSchemaErr4(actxt, error, node,
2380 	(const char *) msg, str1, str2, str3, str4);
2381     FREE_AND_NULL(msg)
2382 }
2383 
2384 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)2385 xmlSchemaCustomErr(xmlSchemaAbstractCtxtPtr actxt,
2386 		   xmlParserErrors error,
2387 		   xmlNodePtr node,
2388 		   xmlSchemaBasicItemPtr item,
2389 		   const char *message,
2390 		   const xmlChar *str1,
2391 		   const xmlChar *str2)
2392 {
2393     xmlSchemaCustomErr4(actxt, error, node, item,
2394 	message, str1, str2, NULL, NULL);
2395 }
2396 
2397 
2398 
2399 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)2400 xmlSchemaCustomWarning(xmlSchemaAbstractCtxtPtr actxt,
2401 		   xmlParserErrors error,
2402 		   xmlNodePtr node,
2403 		   xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2404 		   const char *message,
2405 		   const xmlChar *str1,
2406 		   const xmlChar *str2,
2407 		   const xmlChar *str3)
2408 {
2409     xmlChar *msg = NULL;
2410 
2411     xmlSchemaFormatNodeForError(&msg, actxt, node);
2412     msg = xmlStrcat(msg, (const xmlChar *) message);
2413     msg = xmlStrcat(msg, BAD_CAST ".\n");
2414 
2415     /* URGENT TODO: Set the error code to something sane. */
2416     xmlSchemaErr4Line(actxt, XML_ERR_WARNING, error, node, 0,
2417 	(const char *) msg, str1, str2, str3, NULL);
2418 
2419     FREE_AND_NULL(msg)
2420 }
2421 
2422 
2423 
2424 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)2425 xmlSchemaKeyrefErr(xmlSchemaValidCtxtPtr vctxt,
2426 		   xmlParserErrors error,
2427 		   xmlSchemaPSVIIDCNodePtr idcNode,
2428 		   xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2429 		   const char *message,
2430 		   const xmlChar *str1,
2431 		   const xmlChar *str2)
2432 {
2433     xmlChar *msg = NULL, *qname = NULL;
2434 
2435     msg = xmlStrdup(BAD_CAST "Element '%s': ");
2436     msg = xmlStrcat(msg, (const xmlChar *) message);
2437     msg = xmlStrcat(msg, BAD_CAST ".\n");
2438     xmlSchemaErr4Line(ACTXT_CAST vctxt, XML_ERR_ERROR,
2439 	error, NULL, idcNode->nodeLine, (const char *) msg,
2440 	xmlSchemaFormatQName(&qname,
2441 	    vctxt->nodeQNames->items[idcNode->nodeQNameID +1],
2442 	    vctxt->nodeQNames->items[idcNode->nodeQNameID]),
2443 	str1, str2, NULL);
2444     FREE_AND_NULL(qname);
2445     FREE_AND_NULL(msg);
2446 }
2447 
2448 static int
xmlSchemaEvalErrorNodeType(xmlSchemaAbstractCtxtPtr actxt,xmlNodePtr node)2449 xmlSchemaEvalErrorNodeType(xmlSchemaAbstractCtxtPtr actxt,
2450 			   xmlNodePtr node)
2451 {
2452     if (node != NULL)
2453 	return (node->type);
2454     if ((actxt->type == XML_SCHEMA_CTXT_VALIDATOR) &&
2455 	(((xmlSchemaValidCtxtPtr) actxt)->inode != NULL))
2456 	return ( ((xmlSchemaValidCtxtPtr) actxt)->inode->nodeType);
2457     return (-1);
2458 }
2459 
2460 static int
xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)2461 xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
2462 {
2463     switch (item->type) {
2464 	case XML_SCHEMA_TYPE_COMPLEX:
2465 	case XML_SCHEMA_TYPE_SIMPLE:
2466 	    if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
2467 		return(1);
2468 	    break;
2469 	case XML_SCHEMA_TYPE_GROUP:
2470 	    return (1);
2471 	case XML_SCHEMA_TYPE_ELEMENT:
2472 	    if ( ((xmlSchemaElementPtr) item)->flags &
2473 		XML_SCHEMAS_ELEM_GLOBAL)
2474 		return(1);
2475 	    break;
2476 	case XML_SCHEMA_TYPE_ATTRIBUTE:
2477 	    if ( ((xmlSchemaAttributePtr) item)->flags &
2478 		XML_SCHEMAS_ATTR_GLOBAL)
2479 		return(1);
2480 	    break;
2481 	/* Note that attribute groups are always global. */
2482 	default:
2483 	    return(1);
2484     }
2485     return (0);
2486 }
2487 
2488 static void
xmlSchemaSimpleTypeErr(xmlSchemaAbstractCtxtPtr actxt,xmlParserErrors error,xmlNodePtr node,const xmlChar * value,xmlSchemaTypePtr type,int displayValue)2489 xmlSchemaSimpleTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2490 		       xmlParserErrors error,
2491 		       xmlNodePtr node,
2492 		       const xmlChar *value,
2493 		       xmlSchemaTypePtr type,
2494 		       int displayValue)
2495 {
2496     xmlChar *msg = NULL;
2497 
2498     xmlSchemaFormatNodeForError(&msg, actxt, node);
2499 
2500     if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2501 	    XML_ATTRIBUTE_NODE))
2502 	msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
2503     else
2504 	msg = xmlStrcat(msg, BAD_CAST "The character content is not a valid "
2505 	    "value of ");
2506 
2507     if (! xmlSchemaIsGlobalItem(type))
2508 	msg = xmlStrcat(msg, BAD_CAST "the local ");
2509     else
2510 	msg = xmlStrcat(msg, BAD_CAST "the ");
2511 
2512     if (WXS_IS_ATOMIC(type))
2513 	msg = xmlStrcat(msg, BAD_CAST "atomic type");
2514     else if (WXS_IS_LIST(type))
2515 	msg = xmlStrcat(msg, BAD_CAST "list type");
2516     else if (WXS_IS_UNION(type))
2517 	msg = xmlStrcat(msg, BAD_CAST "union type");
2518 
2519     if (xmlSchemaIsGlobalItem(type)) {
2520 	xmlChar *str = NULL;
2521 	msg = xmlStrcat(msg, BAD_CAST " '");
2522 	if (type->builtInType != 0) {
2523 	    msg = xmlStrcat(msg, BAD_CAST "xs:");
2524 	    str = xmlStrdup(type->name);
2525 	} else {
2526 	    const xmlChar *qName = xmlSchemaFormatQName(&str, type->targetNamespace, type->name);
2527 	    if (!str)
2528 		str = xmlStrdup(qName);
2529 	}
2530 	msg = xmlStrcat(msg, xmlEscapeFormatString(&str));
2531 	msg = xmlStrcat(msg, BAD_CAST "'");
2532 	FREE_AND_NULL(str);
2533     }
2534     msg = xmlStrcat(msg, BAD_CAST ".\n");
2535     if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2536 	    XML_ATTRIBUTE_NODE))
2537 	xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2538     else
2539 	xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2540     FREE_AND_NULL(msg)
2541 }
2542 
2543 static const xmlChar *
xmlSchemaFormatErrorNodeQName(xmlChar ** str,xmlSchemaNodeInfoPtr ni,xmlNodePtr node)2544 xmlSchemaFormatErrorNodeQName(xmlChar ** str,
2545 			      xmlSchemaNodeInfoPtr ni,
2546 			      xmlNodePtr node)
2547 {
2548     if (node != NULL) {
2549 	if (node->ns != NULL)
2550 	    return (xmlSchemaFormatQName(str, node->ns->href, node->name));
2551 	else
2552 	    return (xmlSchemaFormatQName(str, NULL, node->name));
2553     } else if (ni != NULL)
2554 	return (xmlSchemaFormatQName(str, ni->nsName, ni->localName));
2555     return (NULL);
2556 }
2557 
2558 static void
xmlSchemaIllegalAttrErr(xmlSchemaAbstractCtxtPtr actxt,xmlParserErrors error,xmlSchemaAttrInfoPtr ni,xmlNodePtr node)2559 xmlSchemaIllegalAttrErr(xmlSchemaAbstractCtxtPtr actxt,
2560 			xmlParserErrors error,
2561 			xmlSchemaAttrInfoPtr ni,
2562 			xmlNodePtr node)
2563 {
2564     xmlChar *msg = NULL, *str = NULL;
2565 
2566     xmlSchemaFormatNodeForError(&msg, actxt, node);
2567     msg = xmlStrcat(msg, BAD_CAST "The attribute '%s' is not allowed.\n");
2568     xmlSchemaErr(actxt, error, node, (const char *) msg,
2569 	xmlSchemaFormatErrorNodeQName(&str, (xmlSchemaNodeInfoPtr) ni, node),
2570 	NULL);
2571     FREE_AND_NULL(str)
2572     FREE_AND_NULL(msg)
2573 }
2574 
2575 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)2576 xmlSchemaComplexTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2577 		        xmlParserErrors error,
2578 		        xmlNodePtr node,
2579 			xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2580 			const char *message,
2581 			int nbval,
2582 			int nbneg,
2583 			xmlChar **values)
2584 {
2585     xmlChar *str = NULL, *msg = NULL;
2586     xmlChar *localName, *nsName;
2587     const xmlChar *cur, *end;
2588     int i;
2589 
2590     xmlSchemaFormatNodeForError(&msg, actxt, node);
2591     msg = xmlStrcat(msg, (const xmlChar *) message);
2592     msg = xmlStrcat(msg, BAD_CAST ".");
2593     /*
2594     * Note that is does not make sense to report that we have a
2595     * wildcard here, since the wildcard might be unfolded into
2596     * multiple transitions.
2597     */
2598     if (nbval + nbneg > 0) {
2599 	if (nbval + nbneg > 1) {
2600 	    str = xmlStrdup(BAD_CAST " Expected is one of ( ");
2601 	} else
2602 	    str = xmlStrdup(BAD_CAST " Expected is ( ");
2603 	nsName = NULL;
2604 
2605 	for (i = 0; i < nbval + nbneg; i++) {
2606 	    cur = values[i];
2607 	    if (cur == NULL)
2608 	        continue;
2609 	    if ((cur[0] == 'n') && (cur[1] == 'o') && (cur[2] == 't') &&
2610 	        (cur[3] == ' ')) {
2611 		cur += 4;
2612 		str = xmlStrcat(str, BAD_CAST "##other");
2613 	    }
2614 	    /*
2615 	    * Get the local name.
2616 	    */
2617 	    localName = NULL;
2618 
2619 	    end = cur;
2620 	    if (*end == '*') {
2621 		localName = xmlStrdup(BAD_CAST "*");
2622 		end++;
2623 	    } else {
2624 		while ((*end != 0) && (*end != '|'))
2625 		    end++;
2626 		localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
2627 	    }
2628 	    if (*end != 0) {
2629 		end++;
2630 		/*
2631 		* Skip "*|*" if they come with negated expressions, since
2632 		* they represent the same negated wildcard.
2633 		*/
2634 		if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
2635 		    /*
2636 		    * Get the namespace name.
2637 		    */
2638 		    cur = end;
2639 		    if (*end == '*') {
2640 			nsName = xmlStrdup(BAD_CAST "{*}");
2641 		    } else {
2642 			while (*end != 0)
2643 			    end++;
2644 
2645 			if (i >= nbval)
2646 			    nsName = xmlStrdup(BAD_CAST "{##other:");
2647 			else
2648 			    nsName = xmlStrdup(BAD_CAST "{");
2649 
2650 			nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
2651 			nsName = xmlStrcat(nsName, BAD_CAST "}");
2652 		    }
2653 		    str = xmlStrcat(str, BAD_CAST nsName);
2654 		    FREE_AND_NULL(nsName)
2655 		} else {
2656 		    FREE_AND_NULL(localName);
2657 		    continue;
2658 		}
2659 	    }
2660 	    str = xmlStrcat(str, BAD_CAST localName);
2661 	    FREE_AND_NULL(localName);
2662 
2663 	    if (i < nbval + nbneg -1)
2664 		str = xmlStrcat(str, BAD_CAST ", ");
2665 	}
2666 	str = xmlStrcat(str, BAD_CAST " ).\n");
2667 	msg = xmlStrcat(msg, xmlEscapeFormatString(&str));
2668 	FREE_AND_NULL(str)
2669     } else
2670       msg = xmlStrcat(msg, BAD_CAST "\n");
2671     xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2672     xmlFree(msg);
2673 }
2674 
2675 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)2676 xmlSchemaFacetErr(xmlSchemaAbstractCtxtPtr actxt,
2677 		  xmlParserErrors error,
2678 		  xmlNodePtr node,
2679 		  const xmlChar *value,
2680 		  unsigned long length,
2681 		  xmlSchemaTypePtr type,
2682 		  xmlSchemaFacetPtr facet,
2683 		  const char *message,
2684 		  const xmlChar *str1,
2685 		  const xmlChar *str2)
2686 {
2687     xmlChar *str = NULL, *msg = NULL;
2688     xmlSchemaTypeType facetType;
2689     int nodeType = xmlSchemaEvalErrorNodeType(actxt, node);
2690 
2691     xmlSchemaFormatNodeForError(&msg, actxt, node);
2692     if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
2693 	facetType = XML_SCHEMA_FACET_ENUMERATION;
2694 	/*
2695 	* If enumerations are validated, one must not expect the
2696 	* facet to be given.
2697 	*/
2698     } else
2699 	facetType = facet->type;
2700     msg = xmlStrcat(msg, BAD_CAST "[");
2701     msg = xmlStrcat(msg, BAD_CAST "facet '");
2702     msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facetType));
2703     msg = xmlStrcat(msg, BAD_CAST "'] ");
2704     if (message == NULL) {
2705 	/*
2706 	* Use a default message.
2707 	*/
2708 	if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
2709 	    (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
2710 	    (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
2711 
2712 	    char len[25], actLen[25];
2713 
2714 	    /* FIXME, TODO: What is the max expected string length of the
2715 	    * this value?
2716 	    */
2717 	    if (nodeType == XML_ATTRIBUTE_NODE)
2718 		msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
2719 	    else
2720 		msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
2721 
2722 	    snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
2723 	    snprintf(actLen, 24, "%lu", length);
2724 
2725 	    if (facetType == XML_SCHEMA_FACET_LENGTH)
2726 		msg = xmlStrcat(msg,
2727 		BAD_CAST "this differs from the allowed length of '%s'.\n");
2728 	    else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
2729 		msg = xmlStrcat(msg,
2730 		BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
2731 	    else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
2732 		msg = xmlStrcat(msg,
2733 		BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
2734 
2735 	    if (nodeType == XML_ATTRIBUTE_NODE)
2736 		xmlSchemaErr3(actxt, error, node, (const char *) msg,
2737 		    value, (const xmlChar *) actLen, (const xmlChar *) len);
2738 	    else
2739 		xmlSchemaErr(actxt, error, node, (const char *) msg,
2740 		    (const xmlChar *) actLen, (const xmlChar *) len);
2741 
2742 	} else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
2743 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
2744 		"of the set {%s}.\n");
2745 	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2746 		xmlSchemaFormatFacetEnumSet(actxt, &str, type));
2747 	} else if (facetType == XML_SCHEMA_FACET_PATTERN) {
2748 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
2749 		"by the pattern '%s'.\n");
2750 	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2751 		facet->value);
2752 	} else if (facetType == XML_SCHEMA_FACET_MININCLUSIVE) {
2753 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' is less than the "
2754 		"minimum value allowed ('%s').\n");
2755 	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2756 		facet->value);
2757 	} else if (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) {
2758 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' is greater than the "
2759 		"maximum value allowed ('%s').\n");
2760 	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2761 		facet->value);
2762 	} else if (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE) {
2763 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be greater than "
2764 		"'%s'.\n");
2765 	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2766 		facet->value);
2767 	} else if (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) {
2768 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be less than "
2769 		"'%s'.\n");
2770 	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2771 		facet->value);
2772 	} else if (facetType == XML_SCHEMA_FACET_TOTALDIGITS) {
2773 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more "
2774 		"digits than are allowed ('%s').\n");
2775 	    xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2776 		facet->value);
2777 	} else if (facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) {
2778 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more fractional "
2779 		"digits than are allowed ('%s').\n");
2780 	    xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2781 		facet->value);
2782 	} else if (nodeType == XML_ATTRIBUTE_NODE) {
2783 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
2784 	    xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2785 	} else {
2786 	    msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
2787 	    xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2788 	}
2789     } else {
2790 	msg = xmlStrcat(msg, (const xmlChar *) message);
2791 	msg = xmlStrcat(msg, BAD_CAST ".\n");
2792 	xmlSchemaErr(actxt, error, node, (const char *) msg, str1, str2);
2793     }
2794     FREE_AND_NULL(str)
2795     xmlFree(msg);
2796 }
2797 
2798 #define VERROR(err, type, msg) \
2799     xmlSchemaCustomErr(ACTXT_CAST vctxt, err, NULL, type, msg, NULL, NULL);
2800 
2801 #define VERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST vctxt, func, msg);
2802 
2803 #define PERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST pctxt, func, msg);
2804 #define PERROR_INT2(func, msg) xmlSchemaInternalErr(ACTXT_CAST ctxt, func, msg);
2805 
2806 #define AERROR_INT(func, msg) xmlSchemaInternalErr(actxt, func, msg);
2807 
2808 
2809 /**
2810  * xmlSchemaPMissingAttrErr:
2811  * @ctxt: the schema validation context
2812  * @ownerDes: the designation of  the owner
2813  * @ownerName: the name of the owner
2814  * @ownerItem: the owner as a schema object
2815  * @ownerElem: the owner as an element node
2816  * @node: the parent element node of the missing attribute node
2817  * @type: the corresponding type of the attribute node
2818  *
2819  * Reports an illegal attribute.
2820  */
2821 static void
xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaBasicItemPtr ownerItem,xmlNodePtr ownerElem,const char * name,const char * message)2822 xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
2823 			 xmlParserErrors error,
2824 			 xmlSchemaBasicItemPtr ownerItem,
2825 			 xmlNodePtr ownerElem,
2826 			 const char *name,
2827 			 const char *message)
2828 {
2829     xmlChar *des = NULL;
2830 
2831     xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2832 
2833     if (message != NULL)
2834 	xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
2835     else
2836 	xmlSchemaPErr(ctxt, ownerElem, error,
2837 	    "%s: The attribute '%s' is required but missing.\n",
2838 	    BAD_CAST des, BAD_CAST name);
2839     FREE_AND_NULL(des);
2840 }
2841 
2842 
2843 /**
2844  * xmlSchemaPResCompAttrErr:
2845  * @ctxt: the schema validation context
2846  * @error: the error code
2847  * @ownerDes: the designation of  the owner
2848  * @ownerItem: the owner as a schema object
2849  * @ownerElem: the owner as an element node
2850  * @name: the name of the attribute holding the QName
2851  * @refName: the referenced local name
2852  * @refURI: the referenced namespace URI
2853  * @message: optional message
2854  *
2855  * Used to report QName attribute values that failed to resolve
2856  * to schema components.
2857  */
2858 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)2859 xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
2860 			 xmlParserErrors error,
2861 			 xmlSchemaBasicItemPtr ownerItem,
2862 			 xmlNodePtr ownerElem,
2863 			 const char *name,
2864 			 const xmlChar *refName,
2865 			 const xmlChar *refURI,
2866 			 xmlSchemaTypeType refType,
2867 			 const char *refTypeStr)
2868 {
2869     xmlChar *des = NULL, *strA = NULL;
2870 
2871     xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2872     if (refTypeStr == NULL)
2873 	refTypeStr = (const char *) xmlSchemaItemTypeToStr(refType);
2874     xmlSchemaPErrExt(ctxt, ownerElem, error,
2875 	    NULL, NULL, NULL,
2876 	    "%s, attribute '%s': The QName value '%s' does not resolve to a(n) "
2877 	    "%s.\n", BAD_CAST des, BAD_CAST name,
2878 	    xmlSchemaFormatQName(&strA, refURI, refName),
2879 	    BAD_CAST refTypeStr, NULL);
2880     FREE_AND_NULL(des)
2881     FREE_AND_NULL(strA)
2882 }
2883 
2884 /**
2885  * xmlSchemaPCustomAttrErr:
2886  * @ctxt: the schema parser context
2887  * @error: the error code
2888  * @ownerDes: the designation of the owner
2889  * @ownerItem: the owner as a schema object
2890  * @attr: the illegal attribute node
2891  *
2892  * Reports an illegal attribute during the parse.
2893  */
2894 static void
xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlChar ** ownerDes,xmlSchemaBasicItemPtr ownerItem,xmlAttrPtr attr,const char * msg)2895 xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
2896 			xmlParserErrors error,
2897 			xmlChar **ownerDes,
2898 			xmlSchemaBasicItemPtr ownerItem,
2899 			xmlAttrPtr attr,
2900 			const char *msg)
2901 {
2902     xmlChar *des = NULL;
2903 
2904     if (ownerDes == NULL)
2905 	xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
2906     else if (*ownerDes == NULL) {
2907 	xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
2908 	des = *ownerDes;
2909     } else
2910 	des = *ownerDes;
2911     if (attr == NULL) {
2912 	xmlSchemaPErrExt(ctxt, NULL, error, NULL, NULL, NULL,
2913 	    "%s, attribute '%s': %s.\n",
2914 	    BAD_CAST des, (const xmlChar *) "Unknown",
2915 	    (const xmlChar *) msg, NULL, NULL);
2916     } else {
2917 	xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
2918 	    "%s, attribute '%s': %s.\n",
2919 	    BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
2920     }
2921     if (ownerDes == NULL)
2922 	FREE_AND_NULL(des);
2923 }
2924 
2925 /**
2926  * xmlSchemaPIllegalAttrErr:
2927  * @ctxt: the schema parser context
2928  * @error: the error code
2929  * @ownerDes: the designation of the attribute's owner
2930  * @ownerItem: the attribute's owner item
2931  * @attr: the illegal attribute node
2932  *
2933  * Reports an illegal attribute during the parse.
2934  */
2935 static void
xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaBasicItemPtr ownerComp ATTRIBUTE_UNUSED,xmlAttrPtr attr)2936 xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
2937 			 xmlParserErrors error,
2938 			 xmlSchemaBasicItemPtr ownerComp ATTRIBUTE_UNUSED,
2939 			 xmlAttrPtr attr)
2940 {
2941     xmlChar *strA = NULL, *strB = NULL;
2942 
2943     xmlSchemaFormatNodeForError(&strA, ACTXT_CAST ctxt, attr->parent);
2944     xmlSchemaErr4(ACTXT_CAST ctxt, error, (xmlNodePtr) attr,
2945 	"%sThe attribute '%s' is not allowed.\n", BAD_CAST strA,
2946 	xmlSchemaFormatQNameNs(&strB, attr->ns, attr->name),
2947 	NULL, NULL);
2948     FREE_AND_NULL(strA);
2949     FREE_AND_NULL(strB);
2950 }
2951 
2952 /**
2953  * xmlSchemaPCustomErr:
2954  * @ctxt: the schema parser context
2955  * @error: the error code
2956  * @itemDes: the designation of the schema item
2957  * @item: the schema item
2958  * @itemElem: the node of the schema item
2959  * @message: the error message
2960  * @str1: an optional param for the error message
2961  * @str2: an optional param for the error message
2962  * @str3: an optional param for the error message
2963  *
2964  * Reports an error during parsing.
2965  */
2966 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)2967 xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
2968 		    xmlParserErrors error,
2969 		    xmlSchemaBasicItemPtr item,
2970 		    xmlNodePtr itemElem,
2971 		    const char *message,
2972 		    const xmlChar *str1,
2973 		    const xmlChar *str2,
2974 		    const xmlChar *str3)
2975 {
2976     xmlChar *des = NULL, *msg = NULL;
2977 
2978     xmlSchemaFormatItemForReport(&des, NULL, item, itemElem);
2979     msg = xmlStrdup(BAD_CAST "%s: ");
2980     msg = xmlStrcat(msg, (const xmlChar *) message);
2981     msg = xmlStrcat(msg, BAD_CAST ".\n");
2982     if ((itemElem == NULL) && (item != NULL))
2983 	itemElem = WXS_ITEM_NODE(item);
2984     xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
2985 	(const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
2986     FREE_AND_NULL(des);
2987     FREE_AND_NULL(msg);
2988 }
2989 
2990 /**
2991  * xmlSchemaPCustomErr:
2992  * @ctxt: the schema parser context
2993  * @error: the error code
2994  * @itemDes: the designation of the schema item
2995  * @item: the schema item
2996  * @itemElem: the node of the schema item
2997  * @message: the error message
2998  * @str1: the optional param for the error message
2999  *
3000  * Reports an error during parsing.
3001  */
3002 static void LIBXML_ATTR_FORMAT(5,0)
xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaBasicItemPtr item,xmlNodePtr itemElem,const char * message,const xmlChar * str1)3003 xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
3004 		    xmlParserErrors error,
3005 		    xmlSchemaBasicItemPtr item,
3006 		    xmlNodePtr itemElem,
3007 		    const char *message,
3008 		    const xmlChar *str1)
3009 {
3010     xmlSchemaPCustomErrExt(ctxt, error, item, itemElem, message,
3011 	str1, NULL, NULL);
3012 }
3013 
3014 /**
3015  * xmlSchemaPAttrUseErr:
3016  * @ctxt: the schema parser context
3017  * @error: the error code
3018  * @itemDes: the designation of the schema type
3019  * @item: the schema type
3020  * @itemElem: the node of the schema type
3021  * @attr: the invalid schema attribute
3022  * @message: the error message
3023  * @str1: the optional param for the error message
3024  *
3025  * Reports an attribute use error during parsing.
3026  */
3027 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)3028 xmlSchemaPAttrUseErr4(xmlSchemaParserCtxtPtr ctxt,
3029 		    xmlParserErrors error,
3030 		    xmlNodePtr node,
3031 		    xmlSchemaBasicItemPtr ownerItem,
3032 		    const xmlSchemaAttributeUsePtr attruse,
3033 		    const char *message,
3034 		    const xmlChar *str1, const xmlChar *str2,
3035 		    const xmlChar *str3,const xmlChar *str4)
3036 {
3037     xmlChar *str = NULL, *msg = NULL;
3038 
3039     xmlSchemaFormatItemForReport(&msg, NULL, ownerItem, NULL);
3040     msg = xmlStrcat(msg, BAD_CAST ", ");
3041     msg = xmlStrcat(msg,
3042 	BAD_CAST xmlSchemaFormatItemForReport(&str, NULL,
3043 	WXS_BASIC_CAST attruse, NULL));
3044     FREE_AND_NULL(str);
3045     msg = xmlStrcat(msg, BAD_CAST ": ");
3046     msg = xmlStrcat(msg, (const xmlChar *) message);
3047     msg = xmlStrcat(msg, BAD_CAST ".\n");
3048     xmlSchemaErr4(ACTXT_CAST ctxt, error, node,
3049 	(const char *) msg, str1, str2, str3, str4);
3050     xmlFree(msg);
3051 }
3052 
3053 /**
3054  * xmlSchemaPIllegalFacetAtomicErr:
3055  * @ctxt: the schema parser context
3056  * @error: the error code
3057  * @type: the schema type
3058  * @baseType: the base type of type
3059  * @facet: the illegal facet
3060  *
3061  * Reports an illegal facet for atomic simple types.
3062  */
3063 static void
xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaTypePtr type,xmlSchemaTypePtr baseType,xmlSchemaFacetPtr facet)3064 xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
3065 			  xmlParserErrors error,
3066 			  xmlSchemaTypePtr type,
3067 			  xmlSchemaTypePtr baseType,
3068 			  xmlSchemaFacetPtr facet)
3069 {
3070     xmlChar *des = NULL, *strT = NULL;
3071 
3072     xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type, type->node);
3073     xmlSchemaPErrExt(ctxt, type->node, error, NULL, NULL, NULL,
3074 	"%s: The facet '%s' is not allowed on types derived from the "
3075 	"type %s.\n",
3076 	BAD_CAST des, xmlSchemaFacetTypeToString(facet->type),
3077 	xmlSchemaFormatItemForReport(&strT, NULL, WXS_BASIC_CAST baseType, NULL),
3078 	NULL, NULL);
3079     FREE_AND_NULL(des);
3080     FREE_AND_NULL(strT);
3081 }
3082 
3083 /**
3084  * xmlSchemaPIllegalFacetListUnionErr:
3085  * @ctxt: the schema parser context
3086  * @error: the error code
3087  * @itemDes: the designation of the schema item involved
3088  * @item: the schema item involved
3089  * @facet: the illegal facet
3090  *
3091  * Reports an illegal facet for <list> and <union>.
3092  */
3093 static void
xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaTypePtr type,xmlSchemaFacetPtr facet)3094 xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
3095 			  xmlParserErrors error,
3096 			  xmlSchemaTypePtr type,
3097 			  xmlSchemaFacetPtr facet)
3098 {
3099     xmlChar *des = NULL;
3100 
3101     xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type,
3102 	type->node);
3103     xmlSchemaPErr(ctxt, type->node, error,
3104 	"%s: The facet '%s' is not allowed.\n",
3105 	BAD_CAST des, xmlSchemaFacetTypeToString(facet->type));
3106     FREE_AND_NULL(des);
3107 }
3108 
3109 /**
3110  * xmlSchemaPMutualExclAttrErr:
3111  * @ctxt: the schema validation context
3112  * @error: the error code
3113  * @elemDes: the designation of the parent element node
3114  * @attr: the bad attribute node
3115  * @type: the corresponding type of the attribute node
3116  *
3117  * Reports an illegal attribute.
3118  */
3119 static void
xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaBasicItemPtr ownerItem,xmlAttrPtr attr,const char * name1,const char * name2)3120 xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
3121 			 xmlParserErrors error,
3122 			 xmlSchemaBasicItemPtr ownerItem,
3123 			 xmlAttrPtr attr,
3124 			 const char *name1,
3125 			 const char *name2)
3126 {
3127     xmlChar *des = NULL;
3128 
3129     xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST ownerItem, attr->parent);
3130     xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
3131 	"%s: The attributes '%s' and '%s' are mutually exclusive.\n",
3132 	BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
3133     FREE_AND_NULL(des);
3134 }
3135 
3136 /**
3137  * xmlSchemaPSimpleTypeErr:
3138  * @ctxt:  the schema validation context
3139  * @error: the error code
3140  * @type: the type specifier
3141  * @ownerDes: the designation of the owner
3142  * @ownerItem: the schema object if existent
3143  * @node: the validated node
3144  * @value: the validated value
3145  *
3146  * Reports a simple type validation error.
3147  * TODO: Should this report the value of an element as well?
3148  */
3149 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)3150 xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
3151 			xmlParserErrors error,
3152 			xmlSchemaBasicItemPtr ownerItem ATTRIBUTE_UNUSED,
3153 			xmlNodePtr node,
3154 			xmlSchemaTypePtr type,
3155 			const char *expected,
3156 			const xmlChar *value,
3157 			const char *message,
3158 			const xmlChar *str1,
3159 			const xmlChar *str2)
3160 {
3161     xmlChar *msg = NULL;
3162 
3163     xmlSchemaFormatNodeForError(&msg, ACTXT_CAST ctxt, node);
3164     if (message == NULL) {
3165 	/*
3166 	* Use default messages.
3167 	*/
3168 	if (type != NULL) {
3169 	    if (node->type == XML_ATTRIBUTE_NODE)
3170 		msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
3171 	    else
3172 		msg = xmlStrcat(msg, BAD_CAST "The character content is not a "
3173 		"valid value of ");
3174 	    if (! xmlSchemaIsGlobalItem(type))
3175 		msg = xmlStrcat(msg, BAD_CAST "the local ");
3176 	    else
3177 		msg = xmlStrcat(msg, BAD_CAST "the ");
3178 
3179 	    if (WXS_IS_ATOMIC(type))
3180 		msg = xmlStrcat(msg, BAD_CAST "atomic type");
3181 	    else if (WXS_IS_LIST(type))
3182 		msg = xmlStrcat(msg, BAD_CAST "list type");
3183 	    else if (WXS_IS_UNION(type))
3184 		msg = xmlStrcat(msg, BAD_CAST "union type");
3185 
3186 	    if (xmlSchemaIsGlobalItem(type)) {
3187 		xmlChar *str = NULL;
3188 		msg = xmlStrcat(msg, BAD_CAST " '");
3189 		if (type->builtInType != 0) {
3190 		    msg = xmlStrcat(msg, BAD_CAST "xs:");
3191 		    str = xmlStrdup(type->name);
3192 		} else {
3193 		    const xmlChar *qName = xmlSchemaFormatQName(&str, type->targetNamespace, type->name);
3194 		    if (!str)
3195 			str = xmlStrdup(qName);
3196 		}
3197 		msg = xmlStrcat(msg, xmlEscapeFormatString(&str));
3198 		msg = xmlStrcat(msg, BAD_CAST "'.");
3199 		FREE_AND_NULL(str);
3200 	    }
3201 	} else {
3202 	    if (node->type == XML_ATTRIBUTE_NODE)
3203 		msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not valid.");
3204 	    else
3205 		msg = xmlStrcat(msg, BAD_CAST "The character content is not "
3206 		"valid.");
3207 	}
3208 	if (expected) {
3209 	    xmlChar *expectedEscaped = xmlCharStrdup(expected);
3210 	    msg = xmlStrcat(msg, BAD_CAST " Expected is '");
3211 	    msg = xmlStrcat(msg, xmlEscapeFormatString(&expectedEscaped));
3212 	    FREE_AND_NULL(expectedEscaped);
3213 	    msg = xmlStrcat(msg, BAD_CAST "'.\n");
3214 	} else
3215 	    msg = xmlStrcat(msg, BAD_CAST "\n");
3216 	if (node->type == XML_ATTRIBUTE_NODE)
3217 	    xmlSchemaPErr(ctxt, node, error, (const char *) msg, value, NULL);
3218 	else
3219 	    xmlSchemaPErr(ctxt, node, error, (const char *) msg, NULL, NULL);
3220     } else {
3221 	msg = xmlStrcat(msg, BAD_CAST message);
3222 	msg = xmlStrcat(msg, BAD_CAST ".\n");
3223 	xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
3224 	     (const char*) msg, str1, str2, NULL, NULL, NULL);
3225     }
3226     /* Cleanup. */
3227     FREE_AND_NULL(msg)
3228 }
3229 
3230 /**
3231  * xmlSchemaPContentErr:
3232  * @ctxt: the schema parser context
3233  * @error: the error code
3234  * @onwerDes: the designation of the holder of the content
3235  * @ownerItem: the owner item of the holder of the content
3236  * @ownerElem: the node of the holder of the content
3237  * @child: the invalid child node
3238  * @message: the optional error message
3239  * @content: the optional string describing the correct content
3240  *
3241  * Reports an error concerning the content of a schema element.
3242  */
3243 static void
xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaBasicItemPtr ownerItem,xmlNodePtr ownerElem,xmlNodePtr child,const char * message,const char * content)3244 xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
3245 		     xmlParserErrors error,
3246 		     xmlSchemaBasicItemPtr ownerItem,
3247 		     xmlNodePtr ownerElem,
3248 		     xmlNodePtr child,
3249 		     const char *message,
3250 		     const char *content)
3251 {
3252     xmlChar *des = NULL;
3253 
3254     xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
3255     if (message != NULL)
3256 	xmlSchemaPErr2(ctxt, ownerElem, child, error,
3257 	    "%s: %s.\n",
3258 	    BAD_CAST des, BAD_CAST message);
3259     else {
3260 	if (content != NULL) {
3261 	    xmlSchemaPErr2(ctxt, ownerElem, child, error,
3262 		"%s: The content is not valid. Expected is %s.\n",
3263 		BAD_CAST des, BAD_CAST content);
3264 	} else {
3265 	    xmlSchemaPErr2(ctxt, ownerElem, child, error,
3266 		"%s: The content is not valid.\n",
3267 		BAD_CAST des, NULL);
3268 	}
3269     }
3270     FREE_AND_NULL(des)
3271 }
3272 
3273 /************************************************************************
3274  *									*
3275  *			Streamable error functions                      *
3276  *									*
3277  ************************************************************************/
3278 
3279 
3280 
3281 
3282 /************************************************************************
3283  *									*
3284  *			Validation helper functions			*
3285  *									*
3286  ************************************************************************/
3287 
3288 
3289 /************************************************************************
3290  *									*
3291  *			Allocation functions				*
3292  *									*
3293  ************************************************************************/
3294 
3295 /**
3296  * xmlSchemaNewSchemaForParserCtxt:
3297  * @ctxt:  a schema validation context
3298  *
3299  * Allocate a new Schema structure.
3300  *
3301  * Returns the newly allocated structure or NULL in case or error
3302  */
3303 static xmlSchemaPtr
xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)3304 xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
3305 {
3306     xmlSchemaPtr ret;
3307 
3308     ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
3309     if (ret == NULL) {
3310         xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
3311         return (NULL);
3312     }
3313     memset(ret, 0, sizeof(xmlSchema));
3314     ret->dict = ctxt->dict;
3315     xmlDictReference(ret->dict);
3316 
3317     return (ret);
3318 }
3319 
3320 /**
3321  * xmlSchemaNewFacet:
3322  *
3323  * Allocate a new Facet structure.
3324  *
3325  * Returns the newly allocated structure or NULL in case or error
3326  */
3327 xmlSchemaFacetPtr
xmlSchemaNewFacet(void)3328 xmlSchemaNewFacet(void)
3329 {
3330     xmlSchemaFacetPtr ret;
3331 
3332     ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
3333     if (ret == NULL) {
3334         return (NULL);
3335     }
3336     memset(ret, 0, sizeof(xmlSchemaFacet));
3337 
3338     return (ret);
3339 }
3340 
3341 /**
3342  * xmlSchemaNewAnnot:
3343  * @ctxt:  a schema validation context
3344  * @node:  a node
3345  *
3346  * Allocate a new annotation structure.
3347  *
3348  * Returns the newly allocated structure or NULL in case or error
3349  */
3350 static xmlSchemaAnnotPtr
xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node)3351 xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3352 {
3353     xmlSchemaAnnotPtr ret;
3354 
3355     ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
3356     if (ret == NULL) {
3357         xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
3358         return (NULL);
3359     }
3360     memset(ret, 0, sizeof(xmlSchemaAnnot));
3361     ret->content = node;
3362     return (ret);
3363 }
3364 
3365 static xmlSchemaItemListPtr
xmlSchemaItemListCreate(void)3366 xmlSchemaItemListCreate(void)
3367 {
3368     xmlSchemaItemListPtr ret;
3369 
3370     ret = xmlMalloc(sizeof(xmlSchemaItemList));
3371     if (ret == NULL) {
3372 	xmlSchemaPErrMemory(NULL,
3373 	    "allocating an item list structure", NULL);
3374 	return (NULL);
3375     }
3376     memset(ret, 0, sizeof(xmlSchemaItemList));
3377     return (ret);
3378 }
3379 
3380 static void
xmlSchemaItemListClear(xmlSchemaItemListPtr list)3381 xmlSchemaItemListClear(xmlSchemaItemListPtr list)
3382 {
3383     if (list->items != NULL) {
3384 	xmlFree(list->items);
3385 	list->items = NULL;
3386     }
3387     list->nbItems = 0;
3388     list->sizeItems = 0;
3389 }
3390 
3391 static int
xmlSchemaItemListAdd(xmlSchemaItemListPtr list,void * item)3392 xmlSchemaItemListAdd(xmlSchemaItemListPtr list, void *item)
3393 {
3394     if (list->items == NULL) {
3395 	list->items = (void **) xmlMalloc(
3396 	    20 * sizeof(void *));
3397 	if (list->items == NULL) {
3398 	    xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3399 	    return(-1);
3400 	}
3401 	list->sizeItems = 20;
3402     } else if (list->sizeItems <= list->nbItems) {
3403 	list->sizeItems *= 2;
3404 	list->items = (void **) xmlRealloc(list->items,
3405 	    list->sizeItems * sizeof(void *));
3406 	if (list->items == NULL) {
3407 	    xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3408 	    list->sizeItems = 0;
3409 	    return(-1);
3410 	}
3411     }
3412     list->items[list->nbItems++] = item;
3413     return(0);
3414 }
3415 
3416 static int
xmlSchemaItemListAddSize(xmlSchemaItemListPtr list,int initialSize,void * item)3417 xmlSchemaItemListAddSize(xmlSchemaItemListPtr list,
3418 			 int initialSize,
3419 			 void *item)
3420 {
3421     if (list->items == NULL) {
3422 	if (initialSize <= 0)
3423 	    initialSize = 1;
3424 	list->items = (void **) xmlMalloc(
3425 	    initialSize * sizeof(void *));
3426 	if (list->items == NULL) {
3427 	    xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3428 	    return(-1);
3429 	}
3430 	list->sizeItems = initialSize;
3431     } else if (list->sizeItems <= list->nbItems) {
3432 	list->sizeItems *= 2;
3433 	list->items = (void **) xmlRealloc(list->items,
3434 	    list->sizeItems * sizeof(void *));
3435 	if (list->items == NULL) {
3436 	    xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3437 	    list->sizeItems = 0;
3438 	    return(-1);
3439 	}
3440     }
3441     list->items[list->nbItems++] = item;
3442     return(0);
3443 }
3444 
3445 static int
xmlSchemaItemListInsert(xmlSchemaItemListPtr list,void * item,int idx)3446 xmlSchemaItemListInsert(xmlSchemaItemListPtr list, void *item, int idx)
3447 {
3448     if (list->items == NULL) {
3449 	list->items = (void **) xmlMalloc(
3450 	    20 * sizeof(void *));
3451 	if (list->items == NULL) {
3452 	    xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3453 	    return(-1);
3454 	}
3455 	list->sizeItems = 20;
3456     } else if (list->sizeItems <= list->nbItems) {
3457 	list->sizeItems *= 2;
3458 	list->items = (void **) xmlRealloc(list->items,
3459 	    list->sizeItems * sizeof(void *));
3460 	if (list->items == NULL) {
3461 	    xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3462 	    list->sizeItems = 0;
3463 	    return(-1);
3464 	}
3465     }
3466     /*
3467     * Just append if the index is greater/equal than the item count.
3468     */
3469     if (idx >= list->nbItems) {
3470 	list->items[list->nbItems++] = item;
3471     } else {
3472 	int i;
3473 	for (i = list->nbItems; i > idx; i--)
3474 	    list->items[i] = list->items[i-1];
3475 	list->items[idx] = item;
3476 	list->nbItems++;
3477     }
3478     return(0);
3479 }
3480 
3481 #if 0 /* enable if ever needed */
3482 static int
3483 xmlSchemaItemListInsertSize(xmlSchemaItemListPtr list,
3484 			    int initialSize,
3485 			    void *item,
3486 			    int idx)
3487 {
3488     if (list->items == NULL) {
3489 	if (initialSize <= 0)
3490 	    initialSize = 1;
3491 	list->items = (void **) xmlMalloc(
3492 	    initialSize * sizeof(void *));
3493 	if (list->items == NULL) {
3494 	    xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3495 	    return(-1);
3496 	}
3497 	list->sizeItems = initialSize;
3498     } else if (list->sizeItems <= list->nbItems) {
3499 	list->sizeItems *= 2;
3500 	list->items = (void **) xmlRealloc(list->items,
3501 	    list->sizeItems * sizeof(void *));
3502 	if (list->items == NULL) {
3503 	    xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3504 	    list->sizeItems = 0;
3505 	    return(-1);
3506 	}
3507     }
3508     /*
3509     * Just append if the index is greater/equal than the item count.
3510     */
3511     if (idx >= list->nbItems) {
3512 	list->items[list->nbItems++] = item;
3513     } else {
3514 	int i;
3515 	for (i = list->nbItems; i > idx; i--)
3516 	    list->items[i] = list->items[i-1];
3517 	list->items[idx] = item;
3518 	list->nbItems++;
3519     }
3520     return(0);
3521 }
3522 #endif
3523 
3524 static int
xmlSchemaItemListRemove(xmlSchemaItemListPtr list,int idx)3525 xmlSchemaItemListRemove(xmlSchemaItemListPtr list, int idx)
3526 {
3527     int i;
3528     if ((list->items == NULL) || (idx >= list->nbItems)) {
3529 	xmlSchemaPSimpleErr("Internal error: xmlSchemaItemListRemove, "
3530 	    "index error.\n");
3531 	return(-1);
3532     }
3533 
3534     if (list->nbItems == 1) {
3535 	/* TODO: Really free the list? */
3536 	xmlFree(list->items);
3537 	list->items = NULL;
3538 	list->nbItems = 0;
3539 	list->sizeItems = 0;
3540     } else if (list->nbItems -1 == idx) {
3541 	list->nbItems--;
3542     } else {
3543 	for (i = idx; i < list->nbItems -1; i++)
3544 	    list->items[i] = list->items[i+1];
3545 	list->nbItems--;
3546     }
3547     return(0);
3548 }
3549 
3550 /**
3551  * xmlSchemaItemListFree:
3552  * @annot:  a schema type structure
3553  *
3554  * Deallocate a annotation structure
3555  */
3556 static void
xmlSchemaItemListFree(xmlSchemaItemListPtr list)3557 xmlSchemaItemListFree(xmlSchemaItemListPtr list)
3558 {
3559     if (list == NULL)
3560 	return;
3561     if (list->items != NULL)
3562 	xmlFree(list->items);
3563     xmlFree(list);
3564 }
3565 
3566 static void
xmlSchemaBucketFree(xmlSchemaBucketPtr bucket)3567 xmlSchemaBucketFree(xmlSchemaBucketPtr bucket)
3568 {
3569     if (bucket == NULL)
3570 	return;
3571     if (bucket->globals != NULL) {
3572 	xmlSchemaComponentListFree(bucket->globals);
3573 	xmlSchemaItemListFree(bucket->globals);
3574     }
3575     if (bucket->locals != NULL) {
3576 	xmlSchemaComponentListFree(bucket->locals);
3577 	xmlSchemaItemListFree(bucket->locals);
3578     }
3579     if (bucket->relations != NULL) {
3580 	xmlSchemaSchemaRelationPtr prev, cur = bucket->relations;
3581 	do {
3582 	    prev = cur;
3583 	    cur = cur->next;
3584 	    xmlFree(prev);
3585 	} while (cur != NULL);
3586     }
3587     if ((! bucket->preserveDoc) && (bucket->doc != NULL)) {
3588 	xmlFreeDoc(bucket->doc);
3589     }
3590     if (bucket->type == XML_SCHEMA_SCHEMA_IMPORT) {
3591 	if (WXS_IMPBUCKET(bucket)->schema != NULL)
3592 	    xmlSchemaFree(WXS_IMPBUCKET(bucket)->schema);
3593     }
3594     xmlFree(bucket);
3595 }
3596 
3597 static void
xmlSchemaBucketFreeEntry(void * bucket,const xmlChar * name ATTRIBUTE_UNUSED)3598 xmlSchemaBucketFreeEntry(void *bucket, const xmlChar *name ATTRIBUTE_UNUSED)
3599 {
3600     xmlSchemaBucketFree((xmlSchemaBucketPtr) bucket);
3601 }
3602 
3603 static xmlSchemaBucketPtr
xmlSchemaBucketCreate(xmlSchemaParserCtxtPtr pctxt,int type,const xmlChar * targetNamespace)3604 xmlSchemaBucketCreate(xmlSchemaParserCtxtPtr pctxt,
3605 			 int type, const xmlChar *targetNamespace)
3606 {
3607     xmlSchemaBucketPtr ret;
3608     int size;
3609     xmlSchemaPtr mainSchema;
3610 
3611     if (WXS_CONSTRUCTOR(pctxt)->mainSchema == NULL) {
3612 	PERROR_INT("xmlSchemaBucketCreate",
3613 	    "no main schema on constructor");
3614 	return(NULL);
3615     }
3616     mainSchema = WXS_CONSTRUCTOR(pctxt)->mainSchema;
3617     /* Create the schema bucket. */
3618     if (WXS_IS_BUCKET_INCREDEF(type))
3619 	size = sizeof(xmlSchemaInclude);
3620     else
3621 	size = sizeof(xmlSchemaImport);
3622     ret = (xmlSchemaBucketPtr) xmlMalloc(size);
3623     if (ret == NULL) {
3624 	xmlSchemaPErrMemory(NULL, "allocating schema bucket", NULL);
3625 	return(NULL);
3626     }
3627     memset(ret, 0, size);
3628     ret->targetNamespace = targetNamespace;
3629     ret->type = type;
3630     ret->globals = xmlSchemaItemListCreate();
3631     if (ret->globals == NULL) {
3632 	xmlFree(ret);
3633 	return(NULL);
3634     }
3635     ret->locals = xmlSchemaItemListCreate();
3636     if (ret->locals == NULL) {
3637 	xmlFree(ret);
3638 	return(NULL);
3639     }
3640     /*
3641     * The following will assure that only the first bucket is marked as
3642     * XML_SCHEMA_SCHEMA_MAIN and it points to the *main* schema.
3643     * For each following import buckets an xmlSchema will be created.
3644     * An xmlSchema will be created for every distinct targetNamespace.
3645     * We assign the targetNamespace to the schemata here.
3646     */
3647     if (! WXS_HAS_BUCKETS(pctxt)) {
3648 	if (WXS_IS_BUCKET_INCREDEF(type)) {
3649 	    PERROR_INT("xmlSchemaBucketCreate",
3650 		"first bucket but it's an include or redefine");
3651 	    xmlSchemaBucketFree(ret);
3652 	    return(NULL);
3653 	}
3654 	/* Force the type to be XML_SCHEMA_SCHEMA_MAIN. */
3655 	ret->type = XML_SCHEMA_SCHEMA_MAIN;
3656 	/* Point to the *main* schema. */
3657 	WXS_CONSTRUCTOR(pctxt)->mainBucket = ret;
3658 	WXS_IMPBUCKET(ret)->schema = mainSchema;
3659 	/*
3660 	* Ensure that the main schema gets a targetNamespace.
3661 	*/
3662 	mainSchema->targetNamespace = targetNamespace;
3663     } else {
3664 	if (type == XML_SCHEMA_SCHEMA_MAIN) {
3665 	    PERROR_INT("xmlSchemaBucketCreate",
3666 		"main bucket but it's not the first one");
3667 	    xmlSchemaBucketFree(ret);
3668 	    return(NULL);
3669 	} else if (type == XML_SCHEMA_SCHEMA_IMPORT) {
3670 	    /*
3671 	    * Create a schema for imports and assign the
3672 	    * targetNamespace.
3673 	    */
3674 	    WXS_IMPBUCKET(ret)->schema = xmlSchemaNewSchema(pctxt);
3675 	    if (WXS_IMPBUCKET(ret)->schema == NULL) {
3676 		xmlSchemaBucketFree(ret);
3677 		return(NULL);
3678 	    }
3679 	    WXS_IMPBUCKET(ret)->schema->targetNamespace = targetNamespace;
3680 	}
3681     }
3682     if (WXS_IS_BUCKET_IMPMAIN(type)) {
3683 	int res;
3684 	/*
3685 	* Imports go into the "schemasImports" slot of the main *schema*.
3686 	* Note that we create an import entry for the main schema as well; i.e.,
3687 	* even if there's only one schema, we'll get an import.
3688 	*/
3689 	if (mainSchema->schemasImports == NULL) {
3690 	    mainSchema->schemasImports = xmlHashCreateDict(5,
3691 		WXS_CONSTRUCTOR(pctxt)->dict);
3692 	    if (mainSchema->schemasImports == NULL) {
3693 		xmlSchemaBucketFree(ret);
3694 		return(NULL);
3695 	    }
3696 	}
3697 	if (targetNamespace == NULL)
3698 	    res = xmlHashAddEntry(mainSchema->schemasImports,
3699 		XML_SCHEMAS_NO_NAMESPACE, ret);
3700 	else
3701 	    res = xmlHashAddEntry(mainSchema->schemasImports,
3702 		targetNamespace, ret);
3703 	if (res != 0) {
3704 	    PERROR_INT("xmlSchemaBucketCreate",
3705 		"failed to add the schema bucket to the hash");
3706 	    xmlSchemaBucketFree(ret);
3707 	    return(NULL);
3708 	}
3709     } else {
3710 	/* Set the @ownerImport of an include bucket. */
3711 	if (WXS_IS_BUCKET_IMPMAIN(WXS_CONSTRUCTOR(pctxt)->bucket->type))
3712 	    WXS_INCBUCKET(ret)->ownerImport =
3713 		WXS_IMPBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket);
3714 	else
3715 	    WXS_INCBUCKET(ret)->ownerImport =
3716 		WXS_INCBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket)->ownerImport;
3717 
3718 	/* Includes got into the "includes" slot of the *main* schema. */
3719 	if (mainSchema->includes == NULL) {
3720 	    mainSchema->includes = xmlSchemaItemListCreate();
3721 	    if (mainSchema->includes == NULL) {
3722 		xmlSchemaBucketFree(ret);
3723 		return(NULL);
3724 	    }
3725 	}
3726 	xmlSchemaItemListAdd(mainSchema->includes, ret);
3727     }
3728     /*
3729     * Add to list of all buckets; this is used for lookup
3730     * during schema construction time only.
3731     */
3732     if (xmlSchemaItemListAdd(WXS_CONSTRUCTOR(pctxt)->buckets, ret) == -1)
3733 	return(NULL);
3734     return(ret);
3735 }
3736 
3737 static int
xmlSchemaAddItemSize(xmlSchemaItemListPtr * list,int initialSize,void * item)3738 xmlSchemaAddItemSize(xmlSchemaItemListPtr *list, int initialSize, void *item)
3739 {
3740     if (*list == NULL) {
3741 	*list = xmlSchemaItemListCreate();
3742 	if (*list == NULL)
3743 	    return(-1);
3744     }
3745     xmlSchemaItemListAddSize(*list, initialSize, item);
3746     return(0);
3747 }
3748 
3749 /**
3750  * xmlSchemaFreeAnnot:
3751  * @annot:  a schema type structure
3752  *
3753  * Deallocate a annotation structure
3754  */
3755 static void
xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)3756 xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
3757 {
3758     if (annot == NULL)
3759         return;
3760     if (annot->next == NULL) {
3761 	xmlFree(annot);
3762     } else {
3763 	xmlSchemaAnnotPtr prev;
3764 
3765 	do {
3766 	    prev = annot;
3767 	    annot = annot->next;
3768 	    xmlFree(prev);
3769 	} while (annot != NULL);
3770     }
3771 }
3772 
3773 /**
3774  * xmlSchemaFreeNotation:
3775  * @schema:  a schema notation structure
3776  *
3777  * Deallocate a Schema Notation structure.
3778  */
3779 static void
xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)3780 xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
3781 {
3782     if (nota == NULL)
3783         return;
3784     xmlFree(nota);
3785 }
3786 
3787 /**
3788  * xmlSchemaFreeAttribute:
3789  * @attr:  an attribute declaration
3790  *
3791  * Deallocates an attribute declaration structure.
3792  */
3793 static void
xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)3794 xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
3795 {
3796     if (attr == NULL)
3797         return;
3798     if (attr->annot != NULL)
3799 	xmlSchemaFreeAnnot(attr->annot);
3800     if (attr->defVal != NULL)
3801 	xmlSchemaFreeValue(attr->defVal);
3802     xmlFree(attr);
3803 }
3804 
3805 /**
3806  * xmlSchemaFreeAttributeUse:
3807  * @use:  an attribute use
3808  *
3809  * Deallocates an attribute use structure.
3810  */
3811 static void
xmlSchemaFreeAttributeUse(xmlSchemaAttributeUsePtr use)3812 xmlSchemaFreeAttributeUse(xmlSchemaAttributeUsePtr use)
3813 {
3814     if (use == NULL)
3815         return;
3816     if (use->annot != NULL)
3817 	xmlSchemaFreeAnnot(use->annot);
3818     if (use->defVal != NULL)
3819 	xmlSchemaFreeValue(use->defVal);
3820     xmlFree(use);
3821 }
3822 
3823 /**
3824  * xmlSchemaFreeAttributeUseProhib:
3825  * @prohib:  an attribute use prohibition
3826  *
3827  * Deallocates an attribute use structure.
3828  */
3829 static void
xmlSchemaFreeAttributeUseProhib(xmlSchemaAttributeUseProhibPtr prohib)3830 xmlSchemaFreeAttributeUseProhib(xmlSchemaAttributeUseProhibPtr prohib)
3831 {
3832     if (prohib == NULL)
3833         return;
3834     xmlFree(prohib);
3835 }
3836 
3837 /**
3838  * xmlSchemaFreeWildcardNsSet:
3839  * set:  a schema wildcard namespace
3840  *
3841  * Deallocates a list of wildcard constraint structures.
3842  */
3843 static void
xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)3844 xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
3845 {
3846     xmlSchemaWildcardNsPtr next;
3847 
3848     while (set != NULL) {
3849 	next = set->next;
3850 	xmlFree(set);
3851 	set = next;
3852     }
3853 }
3854 
3855 /**
3856  * xmlSchemaFreeWildcard:
3857  * @wildcard:  a wildcard structure
3858  *
3859  * Deallocates a wildcard structure.
3860  */
3861 void
xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)3862 xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
3863 {
3864     if (wildcard == NULL)
3865         return;
3866     if (wildcard->annot != NULL)
3867         xmlSchemaFreeAnnot(wildcard->annot);
3868     if (wildcard->nsSet != NULL)
3869 	xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
3870     if (wildcard->negNsSet != NULL)
3871 	xmlFree(wildcard->negNsSet);
3872     xmlFree(wildcard);
3873 }
3874 
3875 /**
3876  * xmlSchemaFreeAttributeGroup:
3877  * @schema:  a schema attribute group structure
3878  *
3879  * Deallocate a Schema Attribute Group structure.
3880  */
3881 static void
xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attrGr)3882 xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attrGr)
3883 {
3884     if (attrGr == NULL)
3885         return;
3886     if (attrGr->annot != NULL)
3887         xmlSchemaFreeAnnot(attrGr->annot);
3888     if (attrGr->attrUses != NULL)
3889 	xmlSchemaItemListFree(WXS_LIST_CAST attrGr->attrUses);
3890     xmlFree(attrGr);
3891 }
3892 
3893 /**
3894  * xmlSchemaFreeQNameRef:
3895  * @item: a QName reference structure
3896  *
3897  * Deallocatea a QName reference structure.
3898  */
3899 static void
xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item)3900 xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item)
3901 {
3902     xmlFree(item);
3903 }
3904 
3905 /**
3906  * xmlSchemaFreeTypeLinkList:
3907  * @alink: a type link
3908  *
3909  * Deallocate a list of types.
3910  */
3911 static void
xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)3912 xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
3913 {
3914     xmlSchemaTypeLinkPtr next;
3915 
3916     while (link != NULL) {
3917 	next = link->next;
3918 	xmlFree(link);
3919 	link = next;
3920     }
3921 }
3922 
3923 static void
xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)3924 xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
3925 {
3926     xmlSchemaIDCStateObjPtr next;
3927     while (sto != NULL) {
3928 	next = sto->next;
3929 	if (sto->history != NULL)
3930 	    xmlFree(sto->history);
3931 	if (sto->xpathCtxt != NULL)
3932 	    xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
3933 	xmlFree(sto);
3934 	sto = next;
3935     }
3936 }
3937 
3938 /**
3939  * xmlSchemaFreeIDC:
3940  * @idc: a identity-constraint definition
3941  *
3942  * Deallocates an identity-constraint definition.
3943  */
3944 static void
xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)3945 xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)
3946 {
3947     xmlSchemaIDCSelectPtr cur, prev;
3948 
3949     if (idcDef == NULL)
3950 	return;
3951     if (idcDef->annot != NULL)
3952         xmlSchemaFreeAnnot(idcDef->annot);
3953     /* Selector */
3954     if (idcDef->selector != NULL) {
3955 	if (idcDef->selector->xpathComp != NULL)
3956 	    xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp);
3957 	xmlFree(idcDef->selector);
3958     }
3959     /* Fields */
3960     if (idcDef->fields != NULL) {
3961 	cur = idcDef->fields;
3962 	do {
3963 	    prev = cur;
3964 	    cur = cur->next;
3965 	    if (prev->xpathComp != NULL)
3966 		xmlFreePattern((xmlPatternPtr) prev->xpathComp);
3967 	    xmlFree(prev);
3968 	} while (cur != NULL);
3969     }
3970     xmlFree(idcDef);
3971 }
3972 
3973 /**
3974  * xmlSchemaFreeElement:
3975  * @schema:  a schema element structure
3976  *
3977  * Deallocate a Schema Element structure.
3978  */
3979 static void
xmlSchemaFreeElement(xmlSchemaElementPtr elem)3980 xmlSchemaFreeElement(xmlSchemaElementPtr elem)
3981 {
3982     if (elem == NULL)
3983         return;
3984     if (elem->annot != NULL)
3985         xmlSchemaFreeAnnot(elem->annot);
3986     if (elem->contModel != NULL)
3987         xmlRegFreeRegexp(elem->contModel);
3988     if (elem->defVal != NULL)
3989 	xmlSchemaFreeValue(elem->defVal);
3990     xmlFree(elem);
3991 }
3992 
3993 /**
3994  * xmlSchemaFreeFacet:
3995  * @facet:  a schema facet structure
3996  *
3997  * Deallocate a Schema Facet structure.
3998  */
3999 void
xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)4000 xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
4001 {
4002     if (facet == NULL)
4003         return;
4004     if (facet->val != NULL)
4005         xmlSchemaFreeValue(facet->val);
4006     if (facet->regexp != NULL)
4007         xmlRegFreeRegexp(facet->regexp);
4008     if (facet->annot != NULL)
4009         xmlSchemaFreeAnnot(facet->annot);
4010     xmlFree(facet);
4011 }
4012 
4013 /**
4014  * xmlSchemaFreeType:
4015  * @type:  a schema type structure
4016  *
4017  * Deallocate a Schema Type structure.
4018  */
4019 void
xmlSchemaFreeType(xmlSchemaTypePtr type)4020 xmlSchemaFreeType(xmlSchemaTypePtr type)
4021 {
4022     if (type == NULL)
4023         return;
4024     if (type->annot != NULL)
4025         xmlSchemaFreeAnnot(type->annot);
4026     if (type->facets != NULL) {
4027         xmlSchemaFacetPtr facet, next;
4028 
4029         facet = type->facets;
4030         while (facet != NULL) {
4031             next = facet->next;
4032             xmlSchemaFreeFacet(facet);
4033             facet = next;
4034         }
4035     }
4036     if (type->attrUses != NULL)
4037 	xmlSchemaItemListFree((xmlSchemaItemListPtr) type->attrUses);
4038     if (type->memberTypes != NULL)
4039 	xmlSchemaFreeTypeLinkList(type->memberTypes);
4040     if (type->facetSet != NULL) {
4041 	xmlSchemaFacetLinkPtr next, link;
4042 
4043 	link = type->facetSet;
4044 	do {
4045 	    next = link->next;
4046 	    xmlFree(link);
4047 	    link = next;
4048 	} while (link != NULL);
4049     }
4050     if (type->contModel != NULL)
4051         xmlRegFreeRegexp(type->contModel);
4052     xmlFree(type);
4053 }
4054 
4055 /**
4056  * xmlSchemaFreeModelGroupDef:
4057  * @item:  a schema model group definition
4058  *
4059  * Deallocates a schema model group definition.
4060  */
4061 static void
xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item)4062 xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item)
4063 {
4064     if (item->annot != NULL)
4065 	xmlSchemaFreeAnnot(item->annot);
4066     xmlFree(item);
4067 }
4068 
4069 /**
4070  * xmlSchemaFreeModelGroup:
4071  * @item:  a schema model group
4072  *
4073  * Deallocates a schema model group structure.
4074  */
4075 static void
xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item)4076 xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item)
4077 {
4078     if (item->annot != NULL)
4079 	xmlSchemaFreeAnnot(item->annot);
4080     xmlFree(item);
4081 }
4082 
4083 static void
xmlSchemaComponentListFree(xmlSchemaItemListPtr list)4084 xmlSchemaComponentListFree(xmlSchemaItemListPtr list)
4085 {
4086     if ((list == NULL) || (list->nbItems == 0))
4087 	return;
4088     {
4089 	xmlSchemaTreeItemPtr item;
4090 	xmlSchemaTreeItemPtr *items = (xmlSchemaTreeItemPtr *) list->items;
4091 	int i;
4092 
4093 	for (i = 0; i < list->nbItems; i++) {
4094 	    item = items[i];
4095 	    if (item == NULL)
4096 		continue;
4097 	    switch (item->type) {
4098 		case XML_SCHEMA_TYPE_SIMPLE:
4099 		case XML_SCHEMA_TYPE_COMPLEX:
4100 		    xmlSchemaFreeType((xmlSchemaTypePtr) item);
4101 		    break;
4102 		case XML_SCHEMA_TYPE_ATTRIBUTE:
4103 		    xmlSchemaFreeAttribute((xmlSchemaAttributePtr) item);
4104 		    break;
4105 		case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
4106 		    xmlSchemaFreeAttributeUse((xmlSchemaAttributeUsePtr) item);
4107 		    break;
4108 		case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
4109 		    xmlSchemaFreeAttributeUseProhib(
4110 			(xmlSchemaAttributeUseProhibPtr) item);
4111 		    break;
4112 		case XML_SCHEMA_TYPE_ELEMENT:
4113 		    xmlSchemaFreeElement((xmlSchemaElementPtr) item);
4114 		    break;
4115 		case XML_SCHEMA_TYPE_PARTICLE:
4116 		    if (item->annot != NULL)
4117 			xmlSchemaFreeAnnot(item->annot);
4118 		    xmlFree(item);
4119 		    break;
4120 		case XML_SCHEMA_TYPE_SEQUENCE:
4121 		case XML_SCHEMA_TYPE_CHOICE:
4122 		case XML_SCHEMA_TYPE_ALL:
4123 		    xmlSchemaFreeModelGroup((xmlSchemaModelGroupPtr) item);
4124 		    break;
4125 		case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
4126 		    xmlSchemaFreeAttributeGroup(
4127 			(xmlSchemaAttributeGroupPtr) item);
4128 		    break;
4129 		case XML_SCHEMA_TYPE_GROUP:
4130 		    xmlSchemaFreeModelGroupDef(
4131 			(xmlSchemaModelGroupDefPtr) item);
4132 		    break;
4133 		case XML_SCHEMA_TYPE_ANY:
4134 		case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
4135 		    xmlSchemaFreeWildcard((xmlSchemaWildcardPtr) item);
4136 		    break;
4137 		case XML_SCHEMA_TYPE_IDC_KEY:
4138 		case XML_SCHEMA_TYPE_IDC_UNIQUE:
4139 		case XML_SCHEMA_TYPE_IDC_KEYREF:
4140 		    xmlSchemaFreeIDC((xmlSchemaIDCPtr) item);
4141 		    break;
4142 		case XML_SCHEMA_TYPE_NOTATION:
4143 		    xmlSchemaFreeNotation((xmlSchemaNotationPtr) item);
4144 		    break;
4145 		case XML_SCHEMA_EXTRA_QNAMEREF:
4146 		    xmlSchemaFreeQNameRef((xmlSchemaQNameRefPtr) item);
4147 		    break;
4148 		default: {
4149 		    /* TODO: This should never be hit. */
4150 		    xmlSchemaPSimpleInternalErr(NULL,
4151 			"Internal error: xmlSchemaComponentListFree, "
4152 			"unexpected component type '%s'\n",
4153 			(const xmlChar *) WXS_ITEM_TYPE_NAME(item));
4154 			 }
4155 		    break;
4156 	    }
4157 	}
4158 	list->nbItems = 0;
4159     }
4160 }
4161 
4162 /**
4163  * xmlSchemaFree:
4164  * @schema:  a schema structure
4165  *
4166  * Deallocate a Schema structure.
4167  */
4168 void
xmlSchemaFree(xmlSchemaPtr schema)4169 xmlSchemaFree(xmlSchemaPtr schema)
4170 {
4171     if (schema == NULL)
4172         return;
4173     /* @volatiles is not used anymore :-/ */
4174     if (schema->volatiles != NULL)
4175 	TODO
4176     /*
4177     * Note that those slots are not responsible for freeing
4178     * schema components anymore; this will now be done by
4179     * the schema buckets.
4180     */
4181     if (schema->notaDecl != NULL)
4182         xmlHashFree(schema->notaDecl, NULL);
4183     if (schema->attrDecl != NULL)
4184         xmlHashFree(schema->attrDecl, NULL);
4185     if (schema->attrgrpDecl != NULL)
4186         xmlHashFree(schema->attrgrpDecl, NULL);
4187     if (schema->elemDecl != NULL)
4188         xmlHashFree(schema->elemDecl, NULL);
4189     if (schema->typeDecl != NULL)
4190         xmlHashFree(schema->typeDecl, NULL);
4191     if (schema->groupDecl != NULL)
4192         xmlHashFree(schema->groupDecl, NULL);
4193     if (schema->idcDef != NULL)
4194         xmlHashFree(schema->idcDef, NULL);
4195 
4196     if (schema->schemasImports != NULL)
4197 	xmlHashFree(schema->schemasImports, xmlSchemaBucketFreeEntry);
4198     if (schema->includes != NULL) {
4199 	xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) schema->includes;
4200 	int i;
4201 	for (i = 0; i < list->nbItems; i++) {
4202 	    xmlSchemaBucketFree((xmlSchemaBucketPtr) list->items[i]);
4203 	}
4204 	xmlSchemaItemListFree(list);
4205     }
4206     if (schema->annot != NULL)
4207         xmlSchemaFreeAnnot(schema->annot);
4208     /* Never free the doc here, since this will be done by the buckets. */
4209 
4210     xmlDictFree(schema->dict);
4211     xmlFree(schema);
4212 }
4213 
4214 /************************************************************************
4215  *									*
4216  *			Debug functions					*
4217  *									*
4218  ************************************************************************/
4219 
4220 #ifdef LIBXML_OUTPUT_ENABLED
4221 
4222 static void
4223 xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output); /* forward */
4224 
4225 /**
4226  * xmlSchemaElementDump:
4227  * @elem:  an element
4228  * @output:  the file output
4229  *
4230  * Dump the element
4231  */
4232 static void
xmlSchemaElementDump(void * payload,void * data,const xmlChar * name ATTRIBUTE_UNUSED,const xmlChar * namespace ATTRIBUTE_UNUSED,const xmlChar * context ATTRIBUTE_UNUSED)4233 xmlSchemaElementDump(void *payload, void *data,
4234                      const xmlChar * name ATTRIBUTE_UNUSED,
4235 		     const xmlChar * namespace ATTRIBUTE_UNUSED,
4236                      const xmlChar * context ATTRIBUTE_UNUSED)
4237 {
4238     xmlSchemaElementPtr elem = (xmlSchemaElementPtr) payload;
4239     FILE *output = (FILE *) data;
4240     if (elem == NULL)
4241         return;
4242 
4243 
4244     fprintf(output, "Element");
4245     if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
4246 	fprintf(output, " (global)");
4247     fprintf(output, ": '%s' ", elem->name);
4248     if (namespace != NULL)
4249 	fprintf(output, "ns '%s'", namespace);
4250     fprintf(output, "\n");
4251 #if 0
4252     if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
4253 	fprintf(output, "  min %d ", elem->minOccurs);
4254         if (elem->maxOccurs >= UNBOUNDED)
4255             fprintf(output, "max: unbounded\n");
4256         else if (elem->maxOccurs != 1)
4257             fprintf(output, "max: %d\n", elem->maxOccurs);
4258         else
4259             fprintf(output, "\n");
4260     }
4261 #endif
4262     /*
4263     * Misc other properties.
4264     */
4265     if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
4266 	(elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
4267 	(elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
4268 	(elem->flags & XML_SCHEMAS_ELEM_DEFAULT)) {
4269 	fprintf(output, "  props: ");
4270 	if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
4271 	    fprintf(output, "[fixed] ");
4272 	if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
4273 	    fprintf(output, "[default] ");
4274 	if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
4275 	    fprintf(output, "[abstract] ");
4276 	if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
4277 	    fprintf(output, "[nillable] ");
4278 	fprintf(output, "\n");
4279     }
4280     /*
4281     * Default/fixed value.
4282     */
4283     if (elem->value != NULL)
4284 	fprintf(output, "  value: '%s'\n", elem->value);
4285     /*
4286     * Type.
4287     */
4288     if (elem->namedType != NULL) {
4289 	fprintf(output, "  type: '%s' ", elem->namedType);
4290 	if (elem->namedTypeNs != NULL)
4291 	    fprintf(output, "ns '%s'\n", elem->namedTypeNs);
4292 	else
4293 	    fprintf(output, "\n");
4294     } else if (elem->subtypes != NULL) {
4295 	/*
4296 	* Dump local types.
4297 	*/
4298 	xmlSchemaTypeDump(elem->subtypes, output);
4299     }
4300     /*
4301     * Substitution group.
4302     */
4303     if (elem->substGroup != NULL) {
4304 	fprintf(output, "  substitutionGroup: '%s' ", elem->substGroup);
4305 	if (elem->substGroupNs != NULL)
4306 	    fprintf(output, "ns '%s'\n", elem->substGroupNs);
4307 	else
4308 	    fprintf(output, "\n");
4309     }
4310 }
4311 
4312 /**
4313  * xmlSchemaAnnotDump:
4314  * @output:  the file output
4315  * @annot:  a annotation
4316  *
4317  * Dump the annotation
4318  */
4319 static void
xmlSchemaAnnotDump(FILE * output,xmlSchemaAnnotPtr annot)4320 xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
4321 {
4322     xmlChar *content;
4323 
4324     if (annot == NULL)
4325         return;
4326 
4327     content = xmlNodeGetContent(annot->content);
4328     if (content != NULL) {
4329         fprintf(output, "  Annot: %s\n", content);
4330         xmlFree(content);
4331     } else
4332         fprintf(output, "  Annot: empty\n");
4333 }
4334 
4335 /**
4336  * xmlSchemaContentModelDump:
4337  * @particle: the schema particle
4338  * @output: the file output
4339  * @depth: the depth used for intentation
4340  *
4341  * Dump a SchemaType structure
4342  */
4343 static void
xmlSchemaContentModelDump(xmlSchemaParticlePtr particle,FILE * output,int depth)4344 xmlSchemaContentModelDump(xmlSchemaParticlePtr particle, FILE * output, int depth)
4345 {
4346     xmlChar *str = NULL;
4347     xmlSchemaTreeItemPtr term;
4348     char shift[100];
4349     int i;
4350 
4351     if (particle == NULL)
4352 	return;
4353     for (i = 0;((i < depth) && (i < 25));i++)
4354         shift[2 * i] = shift[2 * i + 1] = ' ';
4355     shift[2 * i] = shift[2 * i + 1] = 0;
4356     fprintf(output, "%s", shift);
4357     if (particle->children == NULL) {
4358 	fprintf(output, "MISSING particle term\n");
4359 	return;
4360     }
4361     term = particle->children;
4362     if (term == NULL) {
4363 	fprintf(output, "(NULL)");
4364     } else {
4365 	switch (term->type) {
4366 	    case XML_SCHEMA_TYPE_ELEMENT:
4367 		fprintf(output, "ELEM '%s'", xmlSchemaFormatQName(&str,
4368 		    ((xmlSchemaElementPtr)term)->targetNamespace,
4369 		    ((xmlSchemaElementPtr)term)->name));
4370 		FREE_AND_NULL(str);
4371 		break;
4372 	    case XML_SCHEMA_TYPE_SEQUENCE:
4373 		fprintf(output, "SEQUENCE");
4374 		break;
4375 	    case XML_SCHEMA_TYPE_CHOICE:
4376 		fprintf(output, "CHOICE");
4377 		break;
4378 	    case XML_SCHEMA_TYPE_ALL:
4379 		fprintf(output, "ALL");
4380 		break;
4381 	    case XML_SCHEMA_TYPE_ANY:
4382 		fprintf(output, "ANY");
4383 		break;
4384 	    default:
4385 		fprintf(output, "UNKNOWN\n");
4386 		return;
4387 	}
4388     }
4389     if (particle->minOccurs != 1)
4390 	fprintf(output, " min: %d", particle->minOccurs);
4391     if (particle->maxOccurs >= UNBOUNDED)
4392 	fprintf(output, " max: unbounded");
4393     else if (particle->maxOccurs != 1)
4394 	fprintf(output, " max: %d", particle->maxOccurs);
4395     fprintf(output, "\n");
4396     if (term &&
4397 	((term->type == XML_SCHEMA_TYPE_SEQUENCE) ||
4398 	 (term->type == XML_SCHEMA_TYPE_CHOICE) ||
4399 	 (term->type == XML_SCHEMA_TYPE_ALL)) &&
4400 	 (term->children != NULL)) {
4401 	xmlSchemaContentModelDump((xmlSchemaParticlePtr) term->children,
4402 	    output, depth +1);
4403     }
4404     if (particle->next != NULL)
4405 	xmlSchemaContentModelDump((xmlSchemaParticlePtr) particle->next,
4406 		output, depth);
4407 }
4408 
4409 /**
4410  * xmlSchemaAttrUsesDump:
4411  * @uses:  attribute uses list
4412  * @output:  the file output
4413  *
4414  * Dumps a list of attribute use components.
4415  */
4416 static void
xmlSchemaAttrUsesDump(xmlSchemaItemListPtr uses,FILE * output)4417 xmlSchemaAttrUsesDump(xmlSchemaItemListPtr uses, FILE * output)
4418 {
4419     xmlSchemaAttributeUsePtr use;
4420     xmlSchemaAttributeUseProhibPtr prohib;
4421     xmlSchemaQNameRefPtr ref;
4422     const xmlChar *name, *tns;
4423     xmlChar *str = NULL;
4424     int i;
4425 
4426     if ((uses == NULL) || (uses->nbItems == 0))
4427         return;
4428 
4429     fprintf(output, "  attributes:\n");
4430     for (i = 0; i < uses->nbItems; i++) {
4431 	use = uses->items[i];
4432 	if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
4433 	    fprintf(output, "  [prohibition] ");
4434 	    prohib = (xmlSchemaAttributeUseProhibPtr) use;
4435 	    name = prohib->name;
4436 	    tns = prohib->targetNamespace;
4437 	} else if (use->type == XML_SCHEMA_EXTRA_QNAMEREF) {
4438 	    fprintf(output, "  [reference] ");
4439 	    ref = (xmlSchemaQNameRefPtr) use;
4440 	    name = ref->name;
4441 	    tns = ref->targetNamespace;
4442 	} else {
4443 	    fprintf(output, "  [use] ");
4444 	    name = WXS_ATTRUSE_DECL_NAME(use);
4445 	    tns = WXS_ATTRUSE_DECL_TNS(use);
4446 	}
4447 	fprintf(output, "'%s'\n",
4448 	    (const char *) xmlSchemaFormatQName(&str, tns, name));
4449 	FREE_AND_NULL(str);
4450     }
4451 }
4452 
4453 /**
4454  * xmlSchemaTypeDump:
4455  * @output:  the file output
4456  * @type:  a type structure
4457  *
4458  * Dump a SchemaType structure
4459  */
4460 static void
xmlSchemaTypeDump(xmlSchemaTypePtr type,FILE * output)4461 xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
4462 {
4463     if (type == NULL) {
4464         fprintf(output, "Type: NULL\n");
4465         return;
4466     }
4467     fprintf(output, "Type: ");
4468     if (type->name != NULL)
4469         fprintf(output, "'%s' ", type->name);
4470     else
4471         fprintf(output, "(no name) ");
4472     if (type->targetNamespace != NULL)
4473 	fprintf(output, "ns '%s' ", type->targetNamespace);
4474     switch (type->type) {
4475         case XML_SCHEMA_TYPE_BASIC:
4476             fprintf(output, "[basic] ");
4477             break;
4478         case XML_SCHEMA_TYPE_SIMPLE:
4479             fprintf(output, "[simple] ");
4480             break;
4481         case XML_SCHEMA_TYPE_COMPLEX:
4482             fprintf(output, "[complex] ");
4483             break;
4484         case XML_SCHEMA_TYPE_SEQUENCE:
4485             fprintf(output, "[sequence] ");
4486             break;
4487         case XML_SCHEMA_TYPE_CHOICE:
4488             fprintf(output, "[choice] ");
4489             break;
4490         case XML_SCHEMA_TYPE_ALL:
4491             fprintf(output, "[all] ");
4492             break;
4493         case XML_SCHEMA_TYPE_UR:
4494             fprintf(output, "[ur] ");
4495             break;
4496         case XML_SCHEMA_TYPE_RESTRICTION:
4497             fprintf(output, "[restriction] ");
4498             break;
4499         case XML_SCHEMA_TYPE_EXTENSION:
4500             fprintf(output, "[extension] ");
4501             break;
4502         default:
4503             fprintf(output, "[unknown type %d] ", type->type);
4504             break;
4505     }
4506     fprintf(output, "content: ");
4507     switch (type->contentType) {
4508         case XML_SCHEMA_CONTENT_UNKNOWN:
4509             fprintf(output, "[unknown] ");
4510             break;
4511         case XML_SCHEMA_CONTENT_EMPTY:
4512             fprintf(output, "[empty] ");
4513             break;
4514         case XML_SCHEMA_CONTENT_ELEMENTS:
4515             fprintf(output, "[element] ");
4516             break;
4517         case XML_SCHEMA_CONTENT_MIXED:
4518             fprintf(output, "[mixed] ");
4519             break;
4520         case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
4521 	/* not used. */
4522             break;
4523         case XML_SCHEMA_CONTENT_BASIC:
4524             fprintf(output, "[basic] ");
4525             break;
4526         case XML_SCHEMA_CONTENT_SIMPLE:
4527             fprintf(output, "[simple] ");
4528             break;
4529         case XML_SCHEMA_CONTENT_ANY:
4530             fprintf(output, "[any] ");
4531             break;
4532     }
4533     fprintf(output, "\n");
4534     if (type->base != NULL) {
4535         fprintf(output, "  base type: '%s'", type->base);
4536 	if (type->baseNs != NULL)
4537 	    fprintf(output, " ns '%s'\n", type->baseNs);
4538 	else
4539 	    fprintf(output, "\n");
4540     }
4541     if (type->attrUses != NULL)
4542 	xmlSchemaAttrUsesDump(type->attrUses, output);
4543     if (type->annot != NULL)
4544         xmlSchemaAnnotDump(output, type->annot);
4545 #ifdef DUMP_CONTENT_MODEL
4546     if ((type->type == XML_SCHEMA_TYPE_COMPLEX) &&
4547 	(type->subtypes != NULL)) {
4548 	xmlSchemaContentModelDump((xmlSchemaParticlePtr) type->subtypes,
4549 	    output, 1);
4550     }
4551 #endif
4552 }
4553 
4554 static void
xmlSchemaTypeDumpEntry(void * type,void * output,const xmlChar * name ATTRIBUTE_UNUSED)4555 xmlSchemaTypeDumpEntry(void *type, void *output,
4556                        const xmlChar *name ATTRIBUTE_UNUSED)
4557 {
4558     xmlSchemaTypeDump((xmlSchemaTypePtr) type, (FILE *) output);
4559 }
4560 
4561 /**
4562  * xmlSchemaDump:
4563  * @output:  the file output
4564  * @schema:  a schema structure
4565  *
4566  * Dump a Schema structure.
4567  */
4568 void
xmlSchemaDump(FILE * output,xmlSchemaPtr schema)4569 xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
4570 {
4571     if (output == NULL)
4572         return;
4573     if (schema == NULL) {
4574         fprintf(output, "Schemas: NULL\n");
4575         return;
4576     }
4577     fprintf(output, "Schemas: ");
4578     if (schema->name != NULL)
4579         fprintf(output, "%s, ", schema->name);
4580     else
4581         fprintf(output, "no name, ");
4582     if (schema->targetNamespace != NULL)
4583         fprintf(output, "%s", (const char *) schema->targetNamespace);
4584     else
4585         fprintf(output, "no target namespace");
4586     fprintf(output, "\n");
4587     if (schema->annot != NULL)
4588         xmlSchemaAnnotDump(output, schema->annot);
4589     xmlHashScan(schema->typeDecl, xmlSchemaTypeDumpEntry, output);
4590     xmlHashScanFull(schema->elemDecl, xmlSchemaElementDump, output);
4591 }
4592 
4593 #ifdef DEBUG_IDC_NODE_TABLE
4594 /**
4595  * xmlSchemaDebugDumpIDCTable:
4596  * @vctxt: the WXS validation context
4597  *
4598  * Displays the current IDC table for debug purposes.
4599  */
4600 static void
xmlSchemaDebugDumpIDCTable(FILE * output,const xmlChar * namespaceName,const xmlChar * localName,xmlSchemaPSVIIDCBindingPtr bind)4601 xmlSchemaDebugDumpIDCTable(FILE * output,
4602 			   const xmlChar *namespaceName,
4603 			   const xmlChar *localName,
4604 			   xmlSchemaPSVIIDCBindingPtr bind)
4605 {
4606     xmlChar *str = NULL;
4607     const xmlChar *value;
4608     xmlSchemaPSVIIDCNodePtr tab;
4609     xmlSchemaPSVIIDCKeyPtr key;
4610     int i, j, res;
4611 
4612     fprintf(output, "IDC: TABLES on '%s'\n",
4613 	xmlSchemaFormatQName(&str, namespaceName, localName));
4614     FREE_AND_NULL(str)
4615 
4616     if (bind == NULL)
4617 	return;
4618     do {
4619 	fprintf(output, "IDC:   BINDING '%s' (%d)\n",
4620 	    xmlSchemaGetComponentQName(&str,
4621 		bind->definition), bind->nbNodes);
4622 	FREE_AND_NULL(str)
4623 	for (i = 0; i < bind->nbNodes; i++) {
4624 	    tab = bind->nodeTable[i];
4625 	    fprintf(output, "         ( ");
4626 	    for (j = 0; j < bind->definition->nbFields; j++) {
4627 		key = tab->keys[j];
4628 		if ((key != NULL) && (key->val != NULL)) {
4629 		    res = xmlSchemaGetCanonValue(key->val, &value);
4630 		    if (res >= 0)
4631 			fprintf(output, "'%s' ", value);
4632 		    else
4633 			fprintf(output, "CANON-VALUE-FAILED ");
4634 		    if (res == 0)
4635 			FREE_AND_NULL(value)
4636 		} else if (key != NULL)
4637 		    fprintf(output, "(no val), ");
4638 		else
4639 		    fprintf(output, "(key missing), ");
4640 	    }
4641 	    fprintf(output, ")\n");
4642 	}
4643 	if (bind->dupls && bind->dupls->nbItems) {
4644 	    fprintf(output, "IDC:     dupls (%d):\n", bind->dupls->nbItems);
4645 	    for (i = 0; i < bind->dupls->nbItems; i++) {
4646 		tab = bind->dupls->items[i];
4647 		fprintf(output, "         ( ");
4648 		for (j = 0; j < bind->definition->nbFields; j++) {
4649 		    key = tab->keys[j];
4650 		    if ((key != NULL) && (key->val != NULL)) {
4651 			res = xmlSchemaGetCanonValue(key->val, &value);
4652 			if (res >= 0)
4653 			    fprintf(output, "'%s' ", value);
4654 			else
4655 			    fprintf(output, "CANON-VALUE-FAILED ");
4656 			if (res == 0)
4657 			    FREE_AND_NULL(value)
4658 		    } else if (key != NULL)
4659 		    fprintf(output, "(no val), ");
4660 			else
4661 			    fprintf(output, "(key missing), ");
4662 		}
4663 		fprintf(output, ")\n");
4664 	    }
4665 	}
4666 	bind = bind->next;
4667     } while (bind != NULL);
4668 }
4669 #endif /* DEBUG_IDC */
4670 #endif /* LIBXML_OUTPUT_ENABLED */
4671 
4672 /************************************************************************
4673  *									*
4674  *			Utilities					*
4675  *									*
4676  ************************************************************************/
4677 
4678 /**
4679  * xmlSchemaGetPropNode:
4680  * @node: the element node
4681  * @name: the name of the attribute
4682  *
4683  * Seeks an attribute with a name of @name in
4684  * no namespace.
4685  *
4686  * Returns the attribute or NULL if not present.
4687  */
4688 static xmlAttrPtr
xmlSchemaGetPropNode(xmlNodePtr node,const char * name)4689 xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
4690 {
4691     xmlAttrPtr prop;
4692 
4693     if ((node == NULL) || (name == NULL))
4694 	return(NULL);
4695     prop = node->properties;
4696     while (prop != NULL) {
4697         if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
4698 	    return(prop);
4699 	prop = prop->next;
4700     }
4701     return (NULL);
4702 }
4703 
4704 /**
4705  * xmlSchemaGetPropNodeNs:
4706  * @node: the element node
4707  * @uri: the uri
4708  * @name: the name of the attribute
4709  *
4710  * Seeks an attribute with a local name of @name and
4711  * a namespace URI of @uri.
4712  *
4713  * Returns the attribute or NULL if not present.
4714  */
4715 static xmlAttrPtr
xmlSchemaGetPropNodeNs(xmlNodePtr node,const char * uri,const char * name)4716 xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
4717 {
4718     xmlAttrPtr prop;
4719 
4720     if ((node == NULL) || (name == NULL))
4721 	return(NULL);
4722     prop = node->properties;
4723     while (prop != NULL) {
4724 	if ((prop->ns != NULL) &&
4725 	    xmlStrEqual(prop->name, BAD_CAST name) &&
4726 	    xmlStrEqual(prop->ns->href, BAD_CAST uri))
4727 	    return(prop);
4728 	prop = prop->next;
4729     }
4730     return (NULL);
4731 }
4732 
4733 static const xmlChar *
xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node)4734 xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
4735 {
4736     xmlChar *val;
4737     const xmlChar *ret;
4738 
4739     val = xmlNodeGetContent(node);
4740     if (val == NULL)
4741 	val = xmlStrdup((xmlChar *)"");
4742     ret = xmlDictLookup(ctxt->dict, val, -1);
4743     xmlFree(val);
4744     return(ret);
4745 }
4746 
4747 static const xmlChar *
xmlSchemaGetNodeContentNoDict(xmlNodePtr node)4748 xmlSchemaGetNodeContentNoDict(xmlNodePtr node)
4749 {
4750     return((const xmlChar*) xmlNodeGetContent(node));
4751 }
4752 
4753 /**
4754  * xmlSchemaGetProp:
4755  * @ctxt: the parser context
4756  * @node: the node
4757  * @name: the property name
4758  *
4759  * Read a attribute value and internalize the string
4760  *
4761  * Returns the string or NULL if not present.
4762  */
4763 static const xmlChar *
xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,const char * name)4764 xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
4765                  const char *name)
4766 {
4767     xmlChar *val;
4768     const xmlChar *ret;
4769 
4770     val = xmlGetNoNsProp(node, BAD_CAST name);
4771     if (val == NULL)
4772         return(NULL);
4773     ret = xmlDictLookup(ctxt->dict, val, -1);
4774     xmlFree(val);
4775     return(ret);
4776 }
4777 
4778 /************************************************************************
4779  *									*
4780  *			Parsing functions				*
4781  *									*
4782  ************************************************************************/
4783 
4784 #define WXS_FIND_GLOBAL_ITEM(slot)			\
4785     if (xmlStrEqual(nsName, schema->targetNamespace)) { \
4786 	ret = xmlHashLookup(schema->slot, name); \
4787 	if (ret != NULL) goto exit; \
4788     } \
4789     if (xmlHashSize(schema->schemasImports) > 1) { \
4790 	xmlSchemaImportPtr import; \
4791 	if (nsName == NULL) \
4792 	    import = xmlHashLookup(schema->schemasImports, \
4793 		XML_SCHEMAS_NO_NAMESPACE); \
4794 	else \
4795 	    import = xmlHashLookup(schema->schemasImports, nsName); \
4796 	if (import == NULL) \
4797 	    goto exit; \
4798 	ret = xmlHashLookup(import->schema->slot, name); \
4799     }
4800 
4801 /**
4802  * xmlSchemaGetElem:
4803  * @schema:  the schema context
4804  * @name:  the element name
4805  * @ns:  the element namespace
4806  *
4807  * Lookup a global element declaration in the schema.
4808  *
4809  * Returns the element declaration or NULL if not found.
4810  */
4811 static xmlSchemaElementPtr
xmlSchemaGetElem(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName)4812 xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
4813                  const xmlChar * nsName)
4814 {
4815     xmlSchemaElementPtr ret = NULL;
4816 
4817     if ((name == NULL) || (schema == NULL))
4818         return(NULL);
4819     if (schema != NULL) {
4820 	WXS_FIND_GLOBAL_ITEM(elemDecl)
4821     }
4822 exit:
4823 #ifdef DEBUG
4824     if (ret == NULL) {
4825         if (nsName == NULL)
4826             fprintf(stderr, "Unable to lookup element decl. %s", name);
4827         else
4828             fprintf(stderr, "Unable to lookup element decl. %s:%s", name,
4829                     nsName);
4830     }
4831 #endif
4832     return (ret);
4833 }
4834 
4835 /**
4836  * xmlSchemaGetType:
4837  * @schema:  the main schema
4838  * @name:  the type's name
4839  * nsName:  the type's namespace
4840  *
4841  * Lookup a type in the schemas or the predefined types
4842  *
4843  * Returns the group definition or NULL if not found.
4844  */
4845 static xmlSchemaTypePtr
xmlSchemaGetType(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName)4846 xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
4847                  const xmlChar * nsName)
4848 {
4849     xmlSchemaTypePtr ret = NULL;
4850 
4851     if (name == NULL)
4852         return (NULL);
4853     /* First try the built-in types. */
4854     if ((nsName != NULL) && xmlStrEqual(nsName, xmlSchemaNs)) {
4855 	ret = xmlSchemaGetPredefinedType(name, nsName);
4856 	if (ret != NULL)
4857 	    goto exit;
4858 	/*
4859 	* Note that we try the parsed schemas as well here
4860 	* since one might have parsed the S4S, which contain more
4861 	* than the built-in types.
4862 	* TODO: Can we optimize this?
4863 	*/
4864     }
4865     if (schema != NULL) {
4866 	WXS_FIND_GLOBAL_ITEM(typeDecl)
4867     }
4868 exit:
4869 
4870 #ifdef DEBUG
4871     if (ret == NULL) {
4872         if (nsName == NULL)
4873             fprintf(stderr, "Unable to lookup type %s", name);
4874         else
4875             fprintf(stderr, "Unable to lookup type %s:%s", name,
4876                     nsName);
4877     }
4878 #endif
4879     return (ret);
4880 }
4881 
4882 /**
4883  * xmlSchemaGetAttributeDecl:
4884  * @schema:  the context of the schema
4885  * @name:  the name of the attribute
4886  * @ns:  the target namespace of the attribute
4887  *
4888  * Lookup a an attribute in the schema or imported schemas
4889  *
4890  * Returns the attribute declaration or NULL if not found.
4891  */
4892 static xmlSchemaAttributePtr
xmlSchemaGetAttributeDecl(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName)4893 xmlSchemaGetAttributeDecl(xmlSchemaPtr schema, const xmlChar * name,
4894                  const xmlChar * nsName)
4895 {
4896     xmlSchemaAttributePtr ret = NULL;
4897 
4898     if ((name == NULL) || (schema == NULL))
4899         return (NULL);
4900     if (schema != NULL) {
4901 	WXS_FIND_GLOBAL_ITEM(attrDecl)
4902     }
4903 exit:
4904 #ifdef DEBUG
4905     if (ret == NULL) {
4906         if (nsName == NULL)
4907             fprintf(stderr, "Unable to lookup attribute %s", name);
4908         else
4909             fprintf(stderr, "Unable to lookup attribute %s:%s", name,
4910                     nsName);
4911     }
4912 #endif
4913     return (ret);
4914 }
4915 
4916 /**
4917  * xmlSchemaGetAttributeGroup:
4918  * @schema:  the context of the schema
4919  * @name:  the name of the attribute group
4920  * @ns:  the target namespace of the attribute group
4921  *
4922  * Lookup a an attribute group in the schema or imported schemas
4923  *
4924  * Returns the attribute group definition or NULL if not found.
4925  */
4926 static xmlSchemaAttributeGroupPtr
xmlSchemaGetAttributeGroup(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName)4927 xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
4928                  const xmlChar * nsName)
4929 {
4930     xmlSchemaAttributeGroupPtr ret = NULL;
4931 
4932     if ((name == NULL) || (schema == NULL))
4933         return (NULL);
4934     if (schema != NULL) {
4935 	WXS_FIND_GLOBAL_ITEM(attrgrpDecl)
4936     }
4937 exit:
4938     /* TODO:
4939     if ((ret != NULL) && (ret->redef != NULL)) {
4940 	* Return the last redefinition. *
4941 	ret = ret->redef;
4942     }
4943     */
4944 #ifdef DEBUG
4945     if (ret == NULL) {
4946         if (nsName == NULL)
4947             fprintf(stderr, "Unable to lookup attribute group %s", name);
4948         else
4949             fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
4950                     nsName);
4951     }
4952 #endif
4953     return (ret);
4954 }
4955 
4956 /**
4957  * xmlSchemaGetGroup:
4958  * @schema:  the context of the schema
4959  * @name:  the name of the group
4960  * @ns:  the target namespace of the group
4961  *
4962  * Lookup a group in the schema or imported schemas
4963  *
4964  * Returns the group definition or NULL if not found.
4965  */
4966 static xmlSchemaModelGroupDefPtr
xmlSchemaGetGroup(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName)4967 xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
4968                  const xmlChar * nsName)
4969 {
4970     xmlSchemaModelGroupDefPtr ret = NULL;
4971 
4972     if ((name == NULL) || (schema == NULL))
4973         return (NULL);
4974     if (schema != NULL) {
4975 	WXS_FIND_GLOBAL_ITEM(groupDecl)
4976     }
4977 exit:
4978 
4979 #ifdef DEBUG
4980     if (ret == NULL) {
4981         if (nsName == NULL)
4982             fprintf(stderr, "Unable to lookup group %s", name);
4983         else
4984             fprintf(stderr, "Unable to lookup group %s:%s", name,
4985                     nsName);
4986     }
4987 #endif
4988     return (ret);
4989 }
4990 
4991 static xmlSchemaNotationPtr
xmlSchemaGetNotation(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName)4992 xmlSchemaGetNotation(xmlSchemaPtr schema,
4993 		     const xmlChar *name,
4994 		     const xmlChar *nsName)
4995 {
4996     xmlSchemaNotationPtr ret = NULL;
4997 
4998     if ((name == NULL) || (schema == NULL))
4999         return (NULL);
5000     if (schema != NULL) {
5001 	WXS_FIND_GLOBAL_ITEM(notaDecl)
5002     }
5003 exit:
5004     return (ret);
5005 }
5006 
5007 static xmlSchemaIDCPtr
xmlSchemaGetIDC(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName)5008 xmlSchemaGetIDC(xmlSchemaPtr schema,
5009 		const xmlChar *name,
5010 		const xmlChar *nsName)
5011 {
5012     xmlSchemaIDCPtr ret = NULL;
5013 
5014     if ((name == NULL) || (schema == NULL))
5015         return (NULL);
5016     if (schema != NULL) {
5017 	WXS_FIND_GLOBAL_ITEM(idcDef)
5018     }
5019 exit:
5020     return (ret);
5021 }
5022 
5023 /**
5024  * xmlSchemaGetNamedComponent:
5025  * @schema:  the schema
5026  * @name:  the name of the group
5027  * @ns:  the target namespace of the group
5028  *
5029  * Lookup a group in the schema or imported schemas
5030  *
5031  * Returns the group definition or NULL if not found.
5032  */
5033 static xmlSchemaBasicItemPtr
xmlSchemaGetNamedComponent(xmlSchemaPtr schema,xmlSchemaTypeType itemType,const xmlChar * name,const xmlChar * targetNs)5034 xmlSchemaGetNamedComponent(xmlSchemaPtr schema,
5035 			   xmlSchemaTypeType itemType,
5036 			   const xmlChar *name,
5037 			   const xmlChar *targetNs)
5038 {
5039     switch (itemType) {
5040 	case XML_SCHEMA_TYPE_GROUP:
5041 	    return ((xmlSchemaBasicItemPtr) xmlSchemaGetGroup(schema,
5042 		name, targetNs));
5043 	case XML_SCHEMA_TYPE_ELEMENT:
5044 	    return ((xmlSchemaBasicItemPtr) xmlSchemaGetElem(schema,
5045 		name, targetNs));
5046 	default:
5047 	    TODO
5048 	    return (NULL);
5049     }
5050 }
5051 
5052 /************************************************************************
5053  *									*
5054  *			Parsing functions				*
5055  *									*
5056  ************************************************************************/
5057 
5058 #define IS_BLANK_NODE(n)						\
5059     (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content, -1)))
5060 
5061 /**
5062  * xmlSchemaIsBlank:
5063  * @str:  a string
5064  * @len: the length of the string or -1
5065  *
5066  * Check if a string is ignorable
5067  *
5068  * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
5069  */
5070 static int
xmlSchemaIsBlank(xmlChar * str,int len)5071 xmlSchemaIsBlank(xmlChar * str, int len)
5072 {
5073     if (str == NULL)
5074         return (1);
5075     if (len < 0) {
5076 	while (*str != 0) {
5077 	    if (!(IS_BLANK_CH(*str)))
5078 		return (0);
5079 	    str++;
5080 	}
5081     } else while ((*str != 0) && (len != 0)) {
5082 	if (!(IS_BLANK_CH(*str)))
5083 	    return (0);
5084 	str++;
5085 	len--;
5086     }
5087 
5088     return (1);
5089 }
5090 
5091 #define WXS_COMP_NAME(c, t) ((t) (c))->name
5092 #define WXS_COMP_TNS(c, t) ((t) (c))->targetNamespace
5093 /*
5094 * xmlSchemaFindRedefCompInGraph:
5095 * ATTENTION TODO: This uses pointer comp. for strings.
5096 */
5097 static xmlSchemaBasicItemPtr
xmlSchemaFindRedefCompInGraph(xmlSchemaBucketPtr bucket,xmlSchemaTypeType type,const xmlChar * name,const xmlChar * nsName)5098 xmlSchemaFindRedefCompInGraph(xmlSchemaBucketPtr bucket,
5099 			      xmlSchemaTypeType type,
5100 			      const xmlChar *name,
5101 			      const xmlChar *nsName)
5102 {
5103     xmlSchemaBasicItemPtr ret;
5104     int i;
5105 
5106     if ((bucket == NULL) || (name == NULL))
5107 	return(NULL);
5108     if ((bucket->globals == NULL) ||
5109 	(bucket->globals->nbItems == 0))
5110 	goto subschemas;
5111     /*
5112     * Search in global components.
5113     */
5114     for (i = 0; i < bucket->globals->nbItems; i++) {
5115 	ret = bucket->globals->items[i];
5116 	if (ret->type == type) {
5117 	    switch (type) {
5118 		case XML_SCHEMA_TYPE_COMPLEX:
5119 		case XML_SCHEMA_TYPE_SIMPLE:
5120 		    if ((WXS_COMP_NAME(ret, xmlSchemaTypePtr) == name) &&
5121 			(WXS_COMP_TNS(ret, xmlSchemaTypePtr) ==
5122 			nsName))
5123 		    {
5124 			return(ret);
5125 		    }
5126 		    break;
5127 		case XML_SCHEMA_TYPE_GROUP:
5128 		    if ((WXS_COMP_NAME(ret,
5129 			    xmlSchemaModelGroupDefPtr) == name) &&
5130 			(WXS_COMP_TNS(ret,
5131 			    xmlSchemaModelGroupDefPtr) == nsName))
5132 		    {
5133 			return(ret);
5134 		    }
5135 		    break;
5136 		case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
5137 		    if ((WXS_COMP_NAME(ret,
5138 			    xmlSchemaAttributeGroupPtr) == name) &&
5139 			(WXS_COMP_TNS(ret,
5140 			    xmlSchemaAttributeGroupPtr) == nsName))
5141 		    {
5142 			return(ret);
5143 		    }
5144 		    break;
5145 		default:
5146 		    /* Should not be hit. */
5147 		    return(NULL);
5148 	    }
5149 	}
5150     }
5151 subschemas:
5152     /*
5153     * Process imported/included schemas.
5154     */
5155     if (bucket->relations != NULL) {
5156 	xmlSchemaSchemaRelationPtr rel = bucket->relations;
5157 
5158 	/*
5159 	* TODO: Marking the bucket will not avoid multiple searches
5160 	* in the same schema, but avoids at least circularity.
5161 	*/
5162 	bucket->flags |= XML_SCHEMA_BUCKET_MARKED;
5163 	do {
5164 	    if ((rel->bucket != NULL) &&
5165 		((rel->bucket->flags & XML_SCHEMA_BUCKET_MARKED) == 0)) {
5166 		ret = xmlSchemaFindRedefCompInGraph(rel->bucket,
5167 		    type, name, nsName);
5168 		if (ret != NULL)
5169 		    return(ret);
5170 	    }
5171 	    rel = rel->next;
5172 	} while (rel != NULL);
5173 	 bucket->flags ^= XML_SCHEMA_BUCKET_MARKED;
5174     }
5175     return(NULL);
5176 }
5177 
5178 /**
5179  * xmlSchemaAddNotation:
5180  * @ctxt:  a schema parser context
5181  * @schema:  the schema being built
5182  * @name:  the item name
5183  *
5184  * Add an XML schema annotation declaration
5185  * *WARNING* this interface is highly subject to change
5186  *
5187  * Returns the new struture or NULL in case of error
5188  */
5189 static xmlSchemaNotationPtr
xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName,xmlNodePtr node ATTRIBUTE_UNUSED)5190 xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5191                      const xmlChar *name, const xmlChar *nsName,
5192 		     xmlNodePtr node ATTRIBUTE_UNUSED)
5193 {
5194     xmlSchemaNotationPtr ret = NULL;
5195 
5196     if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5197         return (NULL);
5198 
5199     ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
5200     if (ret == NULL) {
5201         xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
5202         return (NULL);
5203     }
5204     memset(ret, 0, sizeof(xmlSchemaNotation));
5205     ret->type = XML_SCHEMA_TYPE_NOTATION;
5206     ret->name = name;
5207     ret->targetNamespace = nsName;
5208     /* TODO: do we need the node to be set?
5209     * ret->node = node;*/
5210     WXS_ADD_GLOBAL(ctxt, ret);
5211     return (ret);
5212 }
5213 
5214 /**
5215  * xmlSchemaAddAttribute:
5216  * @ctxt:  a schema parser context
5217  * @schema:  the schema being built
5218  * @name:  the item name
5219  * @namespace:  the namespace
5220  *
5221  * Add an XML schema Attrribute declaration
5222  * *WARNING* this interface is highly subject to change
5223  *
5224  * Returns the new struture or NULL in case of error
5225  */
5226 static xmlSchemaAttributePtr
xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName,xmlNodePtr node,int topLevel)5227 xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5228                       const xmlChar * name, const xmlChar * nsName,
5229 		      xmlNodePtr node, int topLevel)
5230 {
5231     xmlSchemaAttributePtr ret = NULL;
5232 
5233     if ((ctxt == NULL) || (schema == NULL))
5234         return (NULL);
5235 
5236     ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
5237     if (ret == NULL) {
5238         xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
5239         return (NULL);
5240     }
5241     memset(ret, 0, sizeof(xmlSchemaAttribute));
5242     ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
5243     ret->node = node;
5244     ret->name = name;
5245     ret->targetNamespace = nsName;
5246 
5247     if (topLevel)
5248 	WXS_ADD_GLOBAL(ctxt, ret);
5249     else
5250 	WXS_ADD_LOCAL(ctxt, ret);
5251     WXS_ADD_PENDING(ctxt, ret);
5252     return (ret);
5253 }
5254 
5255 /**
5256  * xmlSchemaAddAttributeUse:
5257  * @ctxt:  a schema parser context
5258  * @schema:  the schema being built
5259  * @name:  the item name
5260  * @namespace:  the namespace
5261  *
5262  * Add an XML schema Attrribute declaration
5263  * *WARNING* this interface is highly subject to change
5264  *
5265  * Returns the new struture or NULL in case of error
5266  */
5267 static xmlSchemaAttributeUsePtr
xmlSchemaAddAttributeUse(xmlSchemaParserCtxtPtr pctxt,xmlNodePtr node)5268 xmlSchemaAddAttributeUse(xmlSchemaParserCtxtPtr pctxt,
5269 			 xmlNodePtr node)
5270 {
5271     xmlSchemaAttributeUsePtr ret = NULL;
5272 
5273     if (pctxt == NULL)
5274         return (NULL);
5275 
5276     ret = (xmlSchemaAttributeUsePtr) xmlMalloc(sizeof(xmlSchemaAttributeUse));
5277     if (ret == NULL) {
5278         xmlSchemaPErrMemory(pctxt, "allocating attribute", NULL);
5279         return (NULL);
5280     }
5281     memset(ret, 0, sizeof(xmlSchemaAttributeUse));
5282     ret->type = XML_SCHEMA_TYPE_ATTRIBUTE_USE;
5283     ret->node = node;
5284 
5285     WXS_ADD_LOCAL(pctxt, ret);
5286     return (ret);
5287 }
5288 
5289 /*
5290 * xmlSchemaAddRedef:
5291 *
5292 * Adds a redefinition information. This is used at a later stage to:
5293 * resolve references to the redefined components and to check constraints.
5294 */
5295 static xmlSchemaRedefPtr
xmlSchemaAddRedef(xmlSchemaParserCtxtPtr pctxt,xmlSchemaBucketPtr targetBucket,void * item,const xmlChar * refName,const xmlChar * refTargetNs)5296 xmlSchemaAddRedef(xmlSchemaParserCtxtPtr pctxt,
5297 		  xmlSchemaBucketPtr targetBucket,
5298 		  void *item,
5299 		  const xmlChar *refName,
5300 		  const xmlChar *refTargetNs)
5301 {
5302     xmlSchemaRedefPtr ret;
5303 
5304     ret = (xmlSchemaRedefPtr)
5305 	xmlMalloc(sizeof(xmlSchemaRedef));
5306     if (ret == NULL) {
5307 	xmlSchemaPErrMemory(pctxt,
5308 	    "allocating redefinition info", NULL);
5309 	return (NULL);
5310     }
5311     memset(ret, 0, sizeof(xmlSchemaRedef));
5312     ret->item = item;
5313     ret->targetBucket = targetBucket;
5314     ret->refName = refName;
5315     ret->refTargetNs = refTargetNs;
5316     if (WXS_CONSTRUCTOR(pctxt)->redefs == NULL)
5317 	WXS_CONSTRUCTOR(pctxt)->redefs = ret;
5318     else
5319 	WXS_CONSTRUCTOR(pctxt)->lastRedef->next = ret;
5320     WXS_CONSTRUCTOR(pctxt)->lastRedef = ret;
5321 
5322     return (ret);
5323 }
5324 
5325 /**
5326  * xmlSchemaAddAttributeGroupDefinition:
5327  * @ctxt:  a schema parser context
5328  * @schema:  the schema being built
5329  * @name:  the item name
5330  * @nsName:  the target namespace
5331  * @node: the corresponding node
5332  *
5333  * Add an XML schema Attrribute Group definition.
5334  *
5335  * Returns the new struture or NULL in case of error
5336  */
5337 static xmlSchemaAttributeGroupPtr
xmlSchemaAddAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema ATTRIBUTE_UNUSED,const xmlChar * name,const xmlChar * nsName,xmlNodePtr node)5338 xmlSchemaAddAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
5339                            xmlSchemaPtr schema ATTRIBUTE_UNUSED,
5340 			   const xmlChar *name,
5341 			   const xmlChar *nsName,
5342 			   xmlNodePtr node)
5343 {
5344     xmlSchemaAttributeGroupPtr ret = NULL;
5345 
5346     if ((pctxt == NULL) || (name == NULL))
5347         return (NULL);
5348 
5349     ret = (xmlSchemaAttributeGroupPtr)
5350         xmlMalloc(sizeof(xmlSchemaAttributeGroup));
5351     if (ret == NULL) {
5352 	xmlSchemaPErrMemory(pctxt, "allocating attribute group", NULL);
5353 	return (NULL);
5354     }
5355     memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
5356     ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5357     ret->name = name;
5358     ret->targetNamespace = nsName;
5359     ret->node = node;
5360 
5361     /* TODO: Remove the flag. */
5362     ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
5363     if (pctxt->isRedefine) {
5364 	pctxt->redef = xmlSchemaAddRedef(pctxt, pctxt->redefined,
5365 	    ret, name, nsName);
5366 	if (pctxt->redef == NULL) {
5367 	    xmlFree(ret);
5368 	    return(NULL);
5369 	}
5370 	pctxt->redefCounter = 0;
5371     }
5372     WXS_ADD_GLOBAL(pctxt, ret);
5373     WXS_ADD_PENDING(pctxt, ret);
5374     return (ret);
5375 }
5376 
5377 /**
5378  * xmlSchemaAddElement:
5379  * @ctxt:  a schema parser context
5380  * @schema:  the schema being built
5381  * @name:  the type name
5382  * @namespace:  the type namespace
5383  *
5384  * Add an XML schema Element declaration
5385  * *WARNING* this interface is highly subject to change
5386  *
5387  * Returns the new struture or NULL in case of error
5388  */
5389 static xmlSchemaElementPtr
xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt,const xmlChar * name,const xmlChar * nsName,xmlNodePtr node,int topLevel)5390 xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt,
5391                     const xmlChar * name, const xmlChar * nsName,
5392 		    xmlNodePtr node, int topLevel)
5393 {
5394     xmlSchemaElementPtr ret = NULL;
5395 
5396     if ((ctxt == NULL) || (name == NULL))
5397         return (NULL);
5398 
5399     ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
5400     if (ret == NULL) {
5401         xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
5402         return (NULL);
5403     }
5404     memset(ret, 0, sizeof(xmlSchemaElement));
5405     ret->type = XML_SCHEMA_TYPE_ELEMENT;
5406     ret->name = name;
5407     ret->targetNamespace = nsName;
5408     ret->node = node;
5409 
5410     if (topLevel)
5411 	WXS_ADD_GLOBAL(ctxt, ret);
5412     else
5413 	WXS_ADD_LOCAL(ctxt, ret);
5414     WXS_ADD_PENDING(ctxt, ret);
5415     return (ret);
5416 }
5417 
5418 /**
5419  * xmlSchemaAddType:
5420  * @ctxt:  a schema parser context
5421  * @schema:  the schema being built
5422  * @name:  the item name
5423  * @namespace:  the namespace
5424  *
5425  * Add an XML schema item
5426  * *WARNING* this interface is highly subject to change
5427  *
5428  * Returns the new struture or NULL in case of error
5429  */
5430 static xmlSchemaTypePtr
xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlSchemaTypeType type,const xmlChar * name,const xmlChar * nsName,xmlNodePtr node,int topLevel)5431 xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5432 		 xmlSchemaTypeType type,
5433                  const xmlChar * name, const xmlChar * nsName,
5434 		 xmlNodePtr node, int topLevel)
5435 {
5436     xmlSchemaTypePtr ret = NULL;
5437 
5438     if ((ctxt == NULL) || (schema == NULL))
5439         return (NULL);
5440 
5441     ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
5442     if (ret == NULL) {
5443         xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
5444         return (NULL);
5445     }
5446     memset(ret, 0, sizeof(xmlSchemaType));
5447     ret->type = type;
5448     ret->name = name;
5449     ret->targetNamespace = nsName;
5450     ret->node = node;
5451     if (topLevel) {
5452 	if (ctxt->isRedefine) {
5453 	    ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5454 		ret, name, nsName);
5455 	    if (ctxt->redef == NULL) {
5456 		xmlFree(ret);
5457 		return(NULL);
5458 	    }
5459 	    ctxt->redefCounter = 0;
5460 	}
5461 	WXS_ADD_GLOBAL(ctxt, ret);
5462     } else
5463 	WXS_ADD_LOCAL(ctxt, ret);
5464     WXS_ADD_PENDING(ctxt, ret);
5465     return (ret);
5466 }
5467 
5468 static xmlSchemaQNameRefPtr
xmlSchemaNewQNameRef(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypeType refType,const xmlChar * refName,const xmlChar * refNs)5469 xmlSchemaNewQNameRef(xmlSchemaParserCtxtPtr pctxt,
5470 		     xmlSchemaTypeType refType,
5471 		     const xmlChar *refName,
5472 		     const xmlChar *refNs)
5473 {
5474     xmlSchemaQNameRefPtr ret;
5475 
5476     ret = (xmlSchemaQNameRefPtr)
5477 	xmlMalloc(sizeof(xmlSchemaQNameRef));
5478     if (ret == NULL) {
5479 	xmlSchemaPErrMemory(pctxt,
5480 	    "allocating QName reference item", NULL);
5481 	return (NULL);
5482     }
5483     ret->node = NULL;
5484     ret->type = XML_SCHEMA_EXTRA_QNAMEREF;
5485     ret->name = refName;
5486     ret->targetNamespace = refNs;
5487     ret->item = NULL;
5488     ret->itemType = refType;
5489     /*
5490     * Store the reference item in the schema.
5491     */
5492     WXS_ADD_LOCAL(pctxt, ret);
5493     return (ret);
5494 }
5495 
5496 static xmlSchemaAttributeUseProhibPtr
xmlSchemaAddAttributeUseProhib(xmlSchemaParserCtxtPtr pctxt)5497 xmlSchemaAddAttributeUseProhib(xmlSchemaParserCtxtPtr pctxt)
5498 {
5499     xmlSchemaAttributeUseProhibPtr ret;
5500 
5501     ret = (xmlSchemaAttributeUseProhibPtr)
5502 	xmlMalloc(sizeof(xmlSchemaAttributeUseProhib));
5503     if (ret == NULL) {
5504 	xmlSchemaPErrMemory(pctxt,
5505 	    "allocating attribute use prohibition", NULL);
5506 	return (NULL);
5507     }
5508     memset(ret, 0, sizeof(xmlSchemaAttributeUseProhib));
5509     ret->type = XML_SCHEMA_EXTRA_ATTR_USE_PROHIB;
5510     WXS_ADD_LOCAL(pctxt, ret);
5511     return (ret);
5512 }
5513 
5514 
5515 /**
5516  * xmlSchemaAddModelGroup:
5517  * @ctxt:  a schema parser context
5518  * @schema:  the schema being built
5519  * @type: the "compositor" type of the model group
5520  * @node: the node in the schema doc
5521  *
5522  * Adds a schema model group
5523  * *WARNING* this interface is highly subject to change
5524  *
5525  * Returns the new struture or NULL in case of error
5526  */
5527 static xmlSchemaModelGroupPtr
xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlSchemaTypeType type,xmlNodePtr node)5528 xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt,
5529 		       xmlSchemaPtr schema,
5530 		       xmlSchemaTypeType type,
5531 		       xmlNodePtr node)
5532 {
5533     xmlSchemaModelGroupPtr ret = NULL;
5534 
5535     if ((ctxt == NULL) || (schema == NULL))
5536         return (NULL);
5537 
5538     ret = (xmlSchemaModelGroupPtr)
5539 	xmlMalloc(sizeof(xmlSchemaModelGroup));
5540     if (ret == NULL) {
5541 	xmlSchemaPErrMemory(ctxt, "allocating model group component",
5542 	    NULL);
5543 	return (NULL);
5544     }
5545     memset(ret, 0, sizeof(xmlSchemaModelGroup));
5546     ret->type = type;
5547     ret->node = node;
5548     WXS_ADD_LOCAL(ctxt, ret);
5549     if ((type == XML_SCHEMA_TYPE_SEQUENCE) ||
5550 	(type == XML_SCHEMA_TYPE_CHOICE))
5551 	WXS_ADD_PENDING(ctxt, ret);
5552     return (ret);
5553 }
5554 
5555 
5556 /**
5557  * xmlSchemaAddParticle:
5558  * @ctxt:  a schema parser context
5559  * @schema:  the schema being built
5560  * @node: the corresponding node in the schema doc
5561  * @min: the minOccurs
5562  * @max: the maxOccurs
5563  *
5564  * Adds an XML schema particle component.
5565  * *WARNING* this interface is highly subject to change
5566  *
5567  * Returns the new struture or NULL in case of error
5568  */
5569 static xmlSchemaParticlePtr
xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,int min,int max)5570 xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt,
5571 		     xmlNodePtr node, int min, int max)
5572 {
5573     xmlSchemaParticlePtr ret = NULL;
5574     if (ctxt == NULL)
5575         return (NULL);
5576 
5577 #ifdef DEBUG
5578     fprintf(stderr, "Adding particle component\n");
5579 #endif
5580     ret = (xmlSchemaParticlePtr)
5581 	xmlMalloc(sizeof(xmlSchemaParticle));
5582     if (ret == NULL) {
5583 	xmlSchemaPErrMemory(ctxt, "allocating particle component",
5584 	    NULL);
5585 	return (NULL);
5586     }
5587     ret->type = XML_SCHEMA_TYPE_PARTICLE;
5588     ret->annot = NULL;
5589     ret->node = node;
5590     ret->minOccurs = min;
5591     ret->maxOccurs = max;
5592     ret->next = NULL;
5593     ret->children = NULL;
5594 
5595     WXS_ADD_LOCAL(ctxt, ret);
5596     /*
5597     * Note that addition to pending components will be done locally
5598     * to the specific parsing function, since the most particles
5599     * need not to be fixed up (i.e. the reference to be resolved).
5600     * REMOVED: WXS_ADD_PENDING(ctxt, ret);
5601     */
5602     return (ret);
5603 }
5604 
5605 /**
5606  * xmlSchemaAddModelGroupDefinition:
5607  * @ctxt:  a schema validation context
5608  * @schema:  the schema being built
5609  * @name:  the group name
5610  *
5611  * Add an XML schema Group definition
5612  *
5613  * Returns the new struture or NULL in case of error
5614  */
5615 static xmlSchemaModelGroupDefPtr
xmlSchemaAddModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName,xmlNodePtr node)5616 xmlSchemaAddModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
5617 				 xmlSchemaPtr schema,
5618 				 const xmlChar *name,
5619 				 const xmlChar *nsName,
5620 				 xmlNodePtr node)
5621 {
5622     xmlSchemaModelGroupDefPtr ret = NULL;
5623 
5624     if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5625         return (NULL);
5626 
5627     ret = (xmlSchemaModelGroupDefPtr)
5628 	xmlMalloc(sizeof(xmlSchemaModelGroupDef));
5629     if (ret == NULL) {
5630         xmlSchemaPErrMemory(ctxt, "adding group", NULL);
5631         return (NULL);
5632     }
5633     memset(ret, 0, sizeof(xmlSchemaModelGroupDef));
5634     ret->name = name;
5635     ret->type = XML_SCHEMA_TYPE_GROUP;
5636     ret->node = node;
5637     ret->targetNamespace = nsName;
5638 
5639     if (ctxt->isRedefine) {
5640 	ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5641 	    ret, name, nsName);
5642 	if (ctxt->redef == NULL) {
5643 	    xmlFree(ret);
5644 	    return(NULL);
5645 	}
5646 	ctxt->redefCounter = 0;
5647     }
5648     WXS_ADD_GLOBAL(ctxt, ret);
5649     WXS_ADD_PENDING(ctxt, ret);
5650     return (ret);
5651 }
5652 
5653 /**
5654  * xmlSchemaNewWildcardNs:
5655  * @ctxt:  a schema validation context
5656  *
5657  * Creates a new wildcard namespace constraint.
5658  *
5659  * Returns the new struture or NULL in case of error
5660  */
5661 static xmlSchemaWildcardNsPtr
xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)5662 xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
5663 {
5664     xmlSchemaWildcardNsPtr ret;
5665 
5666     ret = (xmlSchemaWildcardNsPtr)
5667 	xmlMalloc(sizeof(xmlSchemaWildcardNs));
5668     if (ret == NULL) {
5669 	xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
5670 	return (NULL);
5671     }
5672     ret->value = NULL;
5673     ret->next = NULL;
5674     return (ret);
5675 }
5676 
5677 static xmlSchemaIDCPtr
xmlSchemaAddIDC(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName,int category,xmlNodePtr node)5678 xmlSchemaAddIDC(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5679                   const xmlChar *name, const xmlChar *nsName,
5680 		  int category, xmlNodePtr node)
5681 {
5682     xmlSchemaIDCPtr ret = NULL;
5683 
5684     if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5685         return (NULL);
5686 
5687     ret = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
5688     if (ret == NULL) {
5689         xmlSchemaPErrMemory(ctxt,
5690 	    "allocating an identity-constraint definition", NULL);
5691         return (NULL);
5692     }
5693     memset(ret, 0, sizeof(xmlSchemaIDC));
5694     /* The target namespace of the parent element declaration. */
5695     ret->targetNamespace = nsName;
5696     ret->name = name;
5697     ret->type = category;
5698     ret->node = node;
5699 
5700     WXS_ADD_GLOBAL(ctxt, ret);
5701     /*
5702     * Only keyrefs need to be fixup up.
5703     */
5704     if (category == XML_SCHEMA_TYPE_IDC_KEYREF)
5705 	WXS_ADD_PENDING(ctxt, ret);
5706     return (ret);
5707 }
5708 
5709 /**
5710  * xmlSchemaAddWildcard:
5711  * @ctxt:  a schema validation context
5712  * @schema: a schema
5713  *
5714  * Adds a wildcard.
5715  * It corresponds to a xsd:anyAttribute and xsd:any.
5716  *
5717  * Returns the new struture or NULL in case of error
5718  */
5719 static xmlSchemaWildcardPtr
xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlSchemaTypeType type,xmlNodePtr node)5720 xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5721 		     xmlSchemaTypeType type, xmlNodePtr node)
5722 {
5723     xmlSchemaWildcardPtr ret = NULL;
5724 
5725     if ((ctxt == NULL) || (schema == NULL))
5726         return (NULL);
5727 
5728     ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
5729     if (ret == NULL) {
5730         xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
5731         return (NULL);
5732     }
5733     memset(ret, 0, sizeof(xmlSchemaWildcard));
5734     ret->type = type;
5735     ret->node = node;
5736     WXS_ADD_LOCAL(ctxt, ret);
5737     return (ret);
5738 }
5739 
5740 static void
xmlSchemaSubstGroupFree(xmlSchemaSubstGroupPtr group)5741 xmlSchemaSubstGroupFree(xmlSchemaSubstGroupPtr group)
5742 {
5743     if (group == NULL)
5744 	return;
5745     if (group->members != NULL)
5746 	xmlSchemaItemListFree(group->members);
5747     xmlFree(group);
5748 }
5749 
5750 static void
xmlSchemaSubstGroupFreeEntry(void * group,const xmlChar * name ATTRIBUTE_UNUSED)5751 xmlSchemaSubstGroupFreeEntry(void *group, const xmlChar *name ATTRIBUTE_UNUSED)
5752 {
5753     xmlSchemaSubstGroupFree((xmlSchemaSubstGroupPtr) group);
5754 }
5755 
5756 static xmlSchemaSubstGroupPtr
xmlSchemaSubstGroupAdd(xmlSchemaParserCtxtPtr pctxt,xmlSchemaElementPtr head)5757 xmlSchemaSubstGroupAdd(xmlSchemaParserCtxtPtr pctxt,
5758 		       xmlSchemaElementPtr head)
5759 {
5760     xmlSchemaSubstGroupPtr ret;
5761 
5762     /* Init subst group hash. */
5763     if (WXS_SUBST_GROUPS(pctxt) == NULL) {
5764 	WXS_SUBST_GROUPS(pctxt) = xmlHashCreateDict(10, pctxt->dict);
5765 	if (WXS_SUBST_GROUPS(pctxt) == NULL)
5766 	    return(NULL);
5767     }
5768     /* Create a new substitution group. */
5769     ret = (xmlSchemaSubstGroupPtr) xmlMalloc(sizeof(xmlSchemaSubstGroup));
5770     if (ret == NULL) {
5771 	xmlSchemaPErrMemory(NULL,
5772 	    "allocating a substitution group container", NULL);
5773 	return(NULL);
5774     }
5775     memset(ret, 0, sizeof(xmlSchemaSubstGroup));
5776     ret->head = head;
5777     /* Create list of members. */
5778     ret->members = xmlSchemaItemListCreate();
5779     if (ret->members == NULL) {
5780 	xmlSchemaSubstGroupFree(ret);
5781 	return(NULL);
5782     }
5783     /* Add subst group to hash. */
5784     if (xmlHashAddEntry2(WXS_SUBST_GROUPS(pctxt),
5785 	head->name, head->targetNamespace, ret) != 0) {
5786 	PERROR_INT("xmlSchemaSubstGroupAdd",
5787 	    "failed to add a new substitution container");
5788 	xmlSchemaSubstGroupFree(ret);
5789 	return(NULL);
5790     }
5791     return(ret);
5792 }
5793 
5794 static xmlSchemaSubstGroupPtr
xmlSchemaSubstGroupGet(xmlSchemaParserCtxtPtr pctxt,xmlSchemaElementPtr head)5795 xmlSchemaSubstGroupGet(xmlSchemaParserCtxtPtr pctxt,
5796 		       xmlSchemaElementPtr head)
5797 {
5798     if (WXS_SUBST_GROUPS(pctxt) == NULL)
5799 	return(NULL);
5800     return(xmlHashLookup2(WXS_SUBST_GROUPS(pctxt),
5801 	head->name, head->targetNamespace));
5802 
5803 }
5804 
5805 /**
5806  * xmlSchemaAddElementSubstitutionMember:
5807  * @pctxt:  a schema parser context
5808  * @head:  the head of the substitution group
5809  * @member: the new member of the substitution group
5810  *
5811  * Allocate a new annotation structure.
5812  *
5813  * Returns the newly allocated structure or NULL in case or error
5814  */
5815 static int
xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt,xmlSchemaElementPtr head,xmlSchemaElementPtr member)5816 xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt,
5817 				      xmlSchemaElementPtr head,
5818 				      xmlSchemaElementPtr member)
5819 {
5820     xmlSchemaSubstGroupPtr substGroup = NULL;
5821 
5822     if ((pctxt == NULL) || (head == NULL) || (member == NULL))
5823 	return (-1);
5824 
5825     substGroup = xmlSchemaSubstGroupGet(pctxt, head);
5826     if (substGroup == NULL)
5827 	substGroup = xmlSchemaSubstGroupAdd(pctxt, head);
5828     if (substGroup == NULL)
5829 	return(-1);
5830     if (xmlSchemaItemListAdd(substGroup->members, member) == -1)
5831 	return(-1);
5832     return(0);
5833 }
5834 
5835 /************************************************************************
5836  *									*
5837  *		Utilities for parsing					*
5838  *									*
5839  ************************************************************************/
5840 
5841 /**
5842  * xmlSchemaPValAttrNodeQNameValue:
5843  * @ctxt:  a schema parser context
5844  * @schema: the schema context
5845  * @ownerDes: the designation of the parent element
5846  * @ownerItem: the parent as a schema object
5847  * @value:  the QName value
5848  * @local: the resulting local part if found, the attribute value otherwise
5849  * @uri:  the resulting namespace URI if found
5850  *
5851  * Extracts the local name and the URI of a QName value and validates it.
5852  * This one is intended to be used on attribute values that
5853  * should resolve to schema components.
5854  *
5855  * Returns 0, in case the QName is valid, a positive error code
5856  * if not valid and -1 if an internal error occurs.
5857  */
5858 static int
xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlSchemaBasicItemPtr ownerItem,xmlAttrPtr attr,const xmlChar * value,const xmlChar ** uri,const xmlChar ** local)5859 xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
5860 				       xmlSchemaPtr schema,
5861 				       xmlSchemaBasicItemPtr ownerItem,
5862 				       xmlAttrPtr attr,
5863 				       const xmlChar *value,
5864 				       const xmlChar **uri,
5865 				       const xmlChar **local)
5866 {
5867     const xmlChar *pref;
5868     xmlNsPtr ns;
5869     int len, ret;
5870 
5871     *uri = NULL;
5872     *local = NULL;
5873     ret = xmlValidateQName(value, 1);
5874     if (ret > 0) {
5875 	xmlSchemaPSimpleTypeErr(ctxt,
5876 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5877 	    ownerItem, (xmlNodePtr) attr,
5878 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
5879 	    NULL, value, NULL, NULL, NULL);
5880 	*local = value;
5881 	return (ctxt->err);
5882     } else if (ret < 0)
5883 	return (-1);
5884 
5885     if (!strchr((char *) value, ':')) {
5886 	ns = xmlSearchNs(attr->doc, attr->parent, NULL);
5887 	if (ns)
5888 	    *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5889 	else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
5890 	    /* TODO: move XML_SCHEMAS_INCLUDING_CONVERT_NS to the
5891 	    * parser context. */
5892 	    /*
5893 	    * This one takes care of included schemas with no
5894 	    * target namespace.
5895 	    */
5896 	    *uri = ctxt->targetNamespace;
5897 	}
5898 	*local = xmlDictLookup(ctxt->dict, value, -1);
5899 	return (0);
5900     }
5901     /*
5902     * At this point xmlSplitQName3 has to return a local name.
5903     */
5904     *local = xmlSplitQName3(value, &len);
5905     *local = xmlDictLookup(ctxt->dict, *local, -1);
5906     pref = xmlDictLookup(ctxt->dict, value, len);
5907     ns = xmlSearchNs(attr->doc, attr->parent, pref);
5908     if (ns == NULL) {
5909 	xmlSchemaPSimpleTypeErr(ctxt,
5910 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5911 	    ownerItem, (xmlNodePtr) attr,
5912 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, value,
5913 	    "The value '%s' of simple type 'xs:QName' has no "
5914 	    "corresponding namespace declaration in scope", value, NULL);
5915 	return (ctxt->err);
5916     } else {
5917         *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5918     }
5919     return (0);
5920 }
5921 
5922 /**
5923  * xmlSchemaPValAttrNodeQName:
5924  * @ctxt:  a schema parser context
5925  * @schema: the schema context
5926  * @ownerDes: the designation of the owner element
5927  * @ownerItem: the owner as a schema object
5928  * @attr:  the attribute node
5929  * @local: the resulting local part if found, the attribute value otherwise
5930  * @uri:  the resulting namespace URI if found
5931  *
5932  * Extracts and validates the QName of an attribute value.
5933  * This one is intended to be used on attribute values that
5934  * should resolve to schema components.
5935  *
5936  * Returns 0, in case the QName is valid, a positive error code
5937  * if not valid and -1 if an internal error occurs.
5938  */
5939 static int
xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlSchemaBasicItemPtr ownerItem,xmlAttrPtr attr,const xmlChar ** uri,const xmlChar ** local)5940 xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
5941 				       xmlSchemaPtr schema,
5942 				       xmlSchemaBasicItemPtr ownerItem,
5943 				       xmlAttrPtr attr,
5944 				       const xmlChar **uri,
5945 				       const xmlChar **local)
5946 {
5947     const xmlChar *value;
5948 
5949     value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5950     return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
5951 	ownerItem, attr, value, uri, local));
5952 }
5953 
5954 /**
5955  * xmlSchemaPValAttrQName:
5956  * @ctxt:  a schema parser context
5957  * @schema: the schema context
5958  * @ownerDes: the designation of the parent element
5959  * @ownerItem: the owner as a schema object
5960  * @ownerElem:  the parent node of the attribute
5961  * @name:  the name of the attribute
5962  * @local: the resulting local part if found, the attribute value otherwise
5963  * @uri:  the resulting namespace URI if found
5964  *
5965  * Extracts and validates the QName of an attribute value.
5966  *
5967  * Returns 0, in case the QName is valid, a positive error code
5968  * if not valid and -1 if an internal error occurs.
5969  */
5970 static int
xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlSchemaBasicItemPtr ownerItem,xmlNodePtr ownerElem,const char * name,const xmlChar ** uri,const xmlChar ** local)5971 xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
5972 				   xmlSchemaPtr schema,
5973 				   xmlSchemaBasicItemPtr ownerItem,
5974 				   xmlNodePtr ownerElem,
5975 				   const char *name,
5976 				   const xmlChar **uri,
5977 				   const xmlChar **local)
5978 {
5979     xmlAttrPtr attr;
5980 
5981     attr = xmlSchemaGetPropNode(ownerElem, name);
5982     if (attr == NULL) {
5983 	*local = NULL;
5984 	*uri = NULL;
5985 	return (0);
5986     }
5987     return (xmlSchemaPValAttrNodeQName(ctxt, schema,
5988 	ownerItem, attr, uri, local));
5989 }
5990 
5991 /**
5992  * xmlSchemaPValAttrID:
5993  * @ctxt:  a schema parser context
5994  * @schema: the schema context
5995  * @ownerDes: the designation of the parent element
5996  * @ownerItem: the owner as a schema object
5997  * @ownerElem:  the parent node of the attribute
5998  * @name:  the name of the attribute
5999  *
6000  * Extracts and validates the ID of an attribute value.
6001  *
6002  * Returns 0, in case the ID is valid, a positive error code
6003  * if not valid and -1 if an internal error occurs.
6004  */
6005 static int
xmlSchemaPValAttrNodeID(xmlSchemaParserCtxtPtr ctxt,xmlAttrPtr attr)6006 xmlSchemaPValAttrNodeID(xmlSchemaParserCtxtPtr ctxt, xmlAttrPtr attr)
6007 {
6008     int ret;
6009     const xmlChar *value;
6010 
6011     if (attr == NULL)
6012 	return(0);
6013     value = xmlSchemaGetNodeContentNoDict((xmlNodePtr) attr);
6014     ret = xmlValidateNCName(value, 1);
6015     if (ret == 0) {
6016 	/*
6017 	* NOTE: the IDness might have already be declared in the DTD
6018 	*/
6019 	if (attr->atype != XML_ATTRIBUTE_ID) {
6020 	    xmlIDPtr res;
6021 	    xmlChar *strip;
6022 
6023 	    /*
6024 	    * TODO: Use xmlSchemaStrip here; it's not exported at this
6025 	    * moment.
6026 	    */
6027 	    strip = xmlSchemaCollapseString(value);
6028 	    if (strip != NULL) {
6029 		xmlFree((xmlChar *) value);
6030 		value = strip;
6031 	    }
6032 	    res = xmlAddID(NULL, attr->doc, value, attr);
6033 	    if (res == NULL) {
6034 		ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
6035 		xmlSchemaPSimpleTypeErr(ctxt,
6036 		    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6037 		    NULL, (xmlNodePtr) attr,
6038 		    xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
6039 		    NULL, NULL, "Duplicate value '%s' of simple "
6040 		    "type 'xs:ID'", value, NULL);
6041 	    } else
6042 		attr->atype = XML_ATTRIBUTE_ID;
6043 	}
6044     } else if (ret > 0) {
6045 	ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
6046 	xmlSchemaPSimpleTypeErr(ctxt,
6047 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6048 	    NULL, (xmlNodePtr) attr,
6049 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
6050 	    NULL, NULL, "The value '%s' of simple type 'xs:ID' is "
6051 	    "not a valid 'xs:NCName'",
6052 	    value, NULL);
6053     }
6054     if (value != NULL)
6055 	xmlFree((xmlChar *)value);
6056 
6057     return (ret);
6058 }
6059 
6060 static int
xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr ownerElem,const xmlChar * name)6061 xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,
6062 		    xmlNodePtr ownerElem,
6063 		    const xmlChar *name)
6064 {
6065     xmlAttrPtr attr;
6066 
6067     attr = xmlSchemaGetPropNode(ownerElem, (const char *) name);
6068     if (attr == NULL)
6069 	return(0);
6070     return(xmlSchemaPValAttrNodeID(ctxt, attr));
6071 
6072 }
6073 
6074 /**
6075  * xmlGetMaxOccurs:
6076  * @ctxt:  a schema validation context
6077  * @node:  a subtree containing XML Schema informations
6078  *
6079  * Get the maxOccurs property
6080  *
6081  * Returns the default if not found, or the value
6082  */
6083 static int
xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,int min,int max,int def,const char * expected)6084 xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
6085 		int min, int max, int def, const char *expected)
6086 {
6087     const xmlChar *val, *cur;
6088     int ret = 0;
6089     xmlAttrPtr attr;
6090 
6091     attr = xmlSchemaGetPropNode(node, "maxOccurs");
6092     if (attr == NULL)
6093 	return (def);
6094     val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6095 
6096     if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
6097 	if (max != UNBOUNDED) {
6098 	    xmlSchemaPSimpleTypeErr(ctxt,
6099 		XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6100 		/* XML_SCHEMAP_INVALID_MINOCCURS, */
6101 		NULL, (xmlNodePtr) attr, NULL, expected,
6102 		val, NULL, NULL, NULL);
6103 	    return (def);
6104 	} else
6105 	    return (UNBOUNDED);  /* encoding it with -1 might be another option */
6106     }
6107 
6108     cur = val;
6109     while (IS_BLANK_CH(*cur))
6110         cur++;
6111     if (*cur == 0) {
6112         xmlSchemaPSimpleTypeErr(ctxt,
6113 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6114 	    /* XML_SCHEMAP_INVALID_MINOCCURS, */
6115 	    NULL, (xmlNodePtr) attr, NULL, expected,
6116 	    val, NULL, NULL, NULL);
6117 	return (def);
6118     }
6119     while ((*cur >= '0') && (*cur <= '9')) {
6120         ret = ret * 10 + (*cur - '0');
6121         cur++;
6122     }
6123     while (IS_BLANK_CH(*cur))
6124         cur++;
6125     /*
6126     * TODO: Restrict the maximal value to Integer.
6127     */
6128     if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
6129 	xmlSchemaPSimpleTypeErr(ctxt,
6130 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6131 	    /* XML_SCHEMAP_INVALID_MINOCCURS, */
6132 	    NULL, (xmlNodePtr) attr, NULL, expected,
6133 	    val, NULL, NULL, NULL);
6134         return (def);
6135     }
6136     return (ret);
6137 }
6138 
6139 /**
6140  * xmlGetMinOccurs:
6141  * @ctxt:  a schema validation context
6142  * @node:  a subtree containing XML Schema informations
6143  *
6144  * Get the minOccurs property
6145  *
6146  * Returns the default if not found, or the value
6147  */
6148 static int
xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,int min,int max,int def,const char * expected)6149 xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
6150 		int min, int max, int def, const char *expected)
6151 {
6152     const xmlChar *val, *cur;
6153     int ret = 0;
6154     xmlAttrPtr attr;
6155 
6156     attr = xmlSchemaGetPropNode(node, "minOccurs");
6157     if (attr == NULL)
6158 	return (def);
6159     val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6160     cur = val;
6161     while (IS_BLANK_CH(*cur))
6162         cur++;
6163     if (*cur == 0) {
6164         xmlSchemaPSimpleTypeErr(ctxt,
6165 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6166 	    /* XML_SCHEMAP_INVALID_MINOCCURS, */
6167 	    NULL, (xmlNodePtr) attr, NULL, expected,
6168 	    val, NULL, NULL, NULL);
6169         return (def);
6170     }
6171     while ((*cur >= '0') && (*cur <= '9')) {
6172         ret = ret * 10 + (*cur - '0');
6173         cur++;
6174     }
6175     while (IS_BLANK_CH(*cur))
6176         cur++;
6177     /*
6178     * TODO: Restrict the maximal value to Integer.
6179     */
6180     if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
6181 	xmlSchemaPSimpleTypeErr(ctxt,
6182 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6183 	    /* XML_SCHEMAP_INVALID_MINOCCURS, */
6184 	    NULL, (xmlNodePtr) attr, NULL, expected,
6185 	    val, NULL, NULL, NULL);
6186         return (def);
6187     }
6188     return (ret);
6189 }
6190 
6191 /**
6192  * xmlSchemaPGetBoolNodeValue:
6193  * @ctxt:  a schema validation context
6194  * @ownerDes:  owner designation
6195  * @ownerItem:  the owner as a schema item
6196  * @node: the node holding the value
6197  *
6198  * Converts a boolean string value into 1 or 0.
6199  *
6200  * Returns 0 or 1.
6201  */
6202 static int
xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,xmlSchemaBasicItemPtr ownerItem,xmlNodePtr node)6203 xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
6204 			   xmlSchemaBasicItemPtr ownerItem,
6205 			   xmlNodePtr node)
6206 {
6207     xmlChar *value = NULL;
6208     int res = 0;
6209 
6210     value = xmlNodeGetContent(node);
6211     /*
6212     * 3.2.2.1 Lexical representation
6213     * An instance of a datatype that is defined as `boolean`
6214     * can have the following legal literals {true, false, 1, 0}.
6215     */
6216     if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
6217         res = 1;
6218     else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
6219         res = 0;
6220     else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
6221 	res = 1;
6222     else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
6223         res = 0;
6224     else {
6225         xmlSchemaPSimpleTypeErr(ctxt,
6226 	    XML_SCHEMAP_INVALID_BOOLEAN,
6227 	    ownerItem, node,
6228 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6229 	    NULL, BAD_CAST value,
6230 	    NULL, NULL, NULL);
6231     }
6232     if (value != NULL)
6233 	xmlFree(value);
6234     return (res);
6235 }
6236 
6237 /**
6238  * xmlGetBooleanProp:
6239  * @ctxt:  a schema validation context
6240  * @node:  a subtree containing XML Schema informations
6241  * @name:  the attribute name
6242  * @def:  the default value
6243  *
6244  * Evaluate if a boolean property is set
6245  *
6246  * Returns the default if not found, 0 if found to be false,
6247  * 1 if found to be true
6248  */
6249 static int
xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,const char * name,int def)6250 xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
6251 		  xmlNodePtr node,
6252                   const char *name, int def)
6253 {
6254     const xmlChar *val;
6255 
6256     val = xmlSchemaGetProp(ctxt, node, name);
6257     if (val == NULL)
6258         return (def);
6259     /*
6260     * 3.2.2.1 Lexical representation
6261     * An instance of a datatype that is defined as `boolean`
6262     * can have the following legal literals {true, false, 1, 0}.
6263     */
6264     if (xmlStrEqual(val, BAD_CAST "true"))
6265         def = 1;
6266     else if (xmlStrEqual(val, BAD_CAST "false"))
6267         def = 0;
6268     else if (xmlStrEqual(val, BAD_CAST "1"))
6269 	def = 1;
6270     else if (xmlStrEqual(val, BAD_CAST "0"))
6271         def = 0;
6272     else {
6273         xmlSchemaPSimpleTypeErr(ctxt,
6274 	    XML_SCHEMAP_INVALID_BOOLEAN,
6275 	    NULL,
6276 	    (xmlNodePtr) xmlSchemaGetPropNode(node, name),
6277 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6278 	    NULL, val, NULL, NULL, NULL);
6279     }
6280     return (def);
6281 }
6282 
6283 /************************************************************************
6284  *									*
6285  *		Shema extraction from an Infoset			*
6286  *									*
6287  ************************************************************************/
6288 static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
6289                                                  ctxt, xmlSchemaPtr schema,
6290                                                  xmlNodePtr node,
6291 						 int topLevel);
6292 static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
6293                                                   ctxt,
6294                                                   xmlSchemaPtr schema,
6295                                                   xmlNodePtr node,
6296 						  int topLevel);
6297 static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
6298                                                   ctxt,
6299                                                   xmlSchemaPtr schema,
6300                                                   xmlNodePtr node,
6301 						  xmlSchemaTypeType parentType);
6302 static xmlSchemaBasicItemPtr
6303 xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
6304 			     xmlSchemaPtr schema,
6305 			     xmlNodePtr node,
6306 			     xmlSchemaItemListPtr uses,
6307 			     int parentType);
6308 static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
6309                                            xmlSchemaPtr schema,
6310                                            xmlNodePtr node);
6311 static xmlSchemaWildcardPtr
6312 xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
6313                            xmlSchemaPtr schema, xmlNodePtr node);
6314 
6315 /**
6316  * xmlSchemaPValAttrNodeValue:
6317  *
6318  * @ctxt:  a schema parser context
6319  * @ownerDes: the designation of the parent element
6320  * @ownerItem: the schema object owner if existent
6321  * @attr:  the schema attribute node being validated
6322  * @value: the value
6323  * @type: the built-in type to be validated against
6324  *
6325  * Validates a value against the given built-in type.
6326  * This one is intended to be used internally for validation
6327  * of schema attribute values during parsing of the schema.
6328  *
6329  * Returns 0 if the value is valid, a positive error code
6330  * number otherwise and -1 in case of an internal or API error.
6331  */
6332 static int
xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr pctxt,xmlSchemaBasicItemPtr ownerItem,xmlAttrPtr attr,const xmlChar * value,xmlSchemaTypePtr type)6333 xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr pctxt,
6334 			   xmlSchemaBasicItemPtr ownerItem,
6335 			   xmlAttrPtr attr,
6336 			   const xmlChar *value,
6337 			   xmlSchemaTypePtr type)
6338 {
6339 
6340     int ret = 0;
6341 
6342     /*
6343     * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
6344     * one is really meant to be used internally, so better not.
6345     */
6346     if ((pctxt == NULL) || (type == NULL) || (attr == NULL))
6347 	return (-1);
6348     if (type->type != XML_SCHEMA_TYPE_BASIC) {
6349 	PERROR_INT("xmlSchemaPValAttrNodeValue",
6350 	    "the given type is not a built-in type");
6351 	return (-1);
6352     }
6353     switch (type->builtInType) {
6354 	case XML_SCHEMAS_NCNAME:
6355 	case XML_SCHEMAS_QNAME:
6356 	case XML_SCHEMAS_ANYURI:
6357 	case XML_SCHEMAS_TOKEN:
6358 	case XML_SCHEMAS_LANGUAGE:
6359 	    ret = xmlSchemaValPredefTypeNode(type, value, NULL,
6360 		(xmlNodePtr) attr);
6361 	    break;
6362 	default: {
6363 	    PERROR_INT("xmlSchemaPValAttrNodeValue",
6364 		"validation using the given type is not supported while "
6365 		"parsing a schema");
6366 	    return (-1);
6367 	}
6368     }
6369     /*
6370     * TODO: Should we use the S4S error codes instead?
6371     */
6372     if (ret < 0) {
6373 	PERROR_INT("xmlSchemaPValAttrNodeValue",
6374 	    "failed to validate a schema attribute value");
6375 	return (-1);
6376     } else if (ret > 0) {
6377 	if (WXS_IS_LIST(type))
6378 	    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
6379 	else
6380 	    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
6381 	xmlSchemaPSimpleTypeErr(pctxt,
6382 	    ret, ownerItem, (xmlNodePtr) attr,
6383 	    type, NULL, value, NULL, NULL, NULL);
6384     }
6385     return (ret);
6386 }
6387 
6388 /**
6389  * xmlSchemaPValAttrNode:
6390  *
6391  * @ctxt:  a schema parser context
6392  * @ownerDes: the designation of the parent element
6393  * @ownerItem: the schema object owner if existent
6394  * @attr:  the schema attribute node being validated
6395  * @type: the built-in type to be validated against
6396  * @value: the resulting value if any
6397  *
6398  * Extracts and validates a value against the given built-in type.
6399  * This one is intended to be used internally for validation
6400  * of schema attribute values during parsing of the schema.
6401  *
6402  * Returns 0 if the value is valid, a positive error code
6403  * number otherwise and -1 in case of an internal or API error.
6404  */
6405 static int
xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,xmlSchemaBasicItemPtr ownerItem,xmlAttrPtr attr,xmlSchemaTypePtr type,const xmlChar ** value)6406 xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
6407 			   xmlSchemaBasicItemPtr ownerItem,
6408 			   xmlAttrPtr attr,
6409 			   xmlSchemaTypePtr type,
6410 			   const xmlChar **value)
6411 {
6412     const xmlChar *val;
6413 
6414     if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
6415 	return (-1);
6416 
6417     val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6418     if (value != NULL)
6419 	*value = val;
6420 
6421     return (xmlSchemaPValAttrNodeValue(ctxt, ownerItem, attr,
6422 	val, type));
6423 }
6424 
6425 /**
6426  * xmlSchemaPValAttr:
6427  *
6428  * @ctxt:  a schema parser context
6429  * @node: the element node of the attribute
6430  * @ownerDes: the designation of the parent element
6431  * @ownerItem: the schema object owner if existent
6432  * @ownerElem: the owner element node
6433  * @name:  the name of the schema attribute node
6434  * @type: the built-in type to be validated against
6435  * @value: the resulting value if any
6436  *
6437  * Extracts and validates a value against the given built-in type.
6438  * This one is intended to be used internally for validation
6439  * of schema attribute values during parsing of the schema.
6440  *
6441  * Returns 0 if the value is valid, a positive error code
6442  * number otherwise and -1 in case of an internal or API error.
6443  */
6444 static int
xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,xmlSchemaBasicItemPtr ownerItem,xmlNodePtr ownerElem,const char * name,xmlSchemaTypePtr type,const xmlChar ** value)6445 xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
6446 		       xmlSchemaBasicItemPtr ownerItem,
6447 		       xmlNodePtr ownerElem,
6448 		       const char *name,
6449 		       xmlSchemaTypePtr type,
6450 		       const xmlChar **value)
6451 {
6452     xmlAttrPtr attr;
6453 
6454     if ((ctxt == NULL) || (type == NULL)) {
6455 	if (value != NULL)
6456 	    *value = NULL;
6457 	return (-1);
6458     }
6459     if (type->type != XML_SCHEMA_TYPE_BASIC) {
6460 	if (value != NULL)
6461 	    *value = NULL;
6462 	xmlSchemaPErr(ctxt, ownerElem,
6463 	    XML_SCHEMAP_INTERNAL,
6464 	    "Internal error: xmlSchemaPValAttr, the given "
6465 	    "type '%s' is not a built-in type.\n",
6466 	    type->name, NULL);
6467 	return (-1);
6468     }
6469     attr = xmlSchemaGetPropNode(ownerElem, name);
6470     if (attr == NULL) {
6471 	if (value != NULL)
6472 	    *value = NULL;
6473 	return (0);
6474     }
6475     return (xmlSchemaPValAttrNode(ctxt, ownerItem, attr,
6476 	type, value));
6477 }
6478 
6479 static int
xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema ATTRIBUTE_UNUSED,xmlNodePtr node,xmlAttrPtr attr,const xmlChar * namespaceName)6480 xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,
6481 		  xmlSchemaPtr schema ATTRIBUTE_UNUSED,
6482 		  xmlNodePtr node,
6483 		  xmlAttrPtr attr,
6484 		  const xmlChar *namespaceName)
6485 {
6486     /* TODO: Pointer comparison instead? */
6487     if (xmlStrEqual(pctxt->targetNamespace, namespaceName))
6488 	return (0);
6489     if (xmlStrEqual(xmlSchemaNs, namespaceName))
6490 	return (0);
6491     /*
6492     * Check if the referenced namespace was <import>ed.
6493     */
6494     if (WXS_BUCKET(pctxt)->relations != NULL) {
6495 	xmlSchemaSchemaRelationPtr rel;
6496 
6497 	rel = WXS_BUCKET(pctxt)->relations;
6498 	do {
6499 	    if (WXS_IS_BUCKET_IMPMAIN(rel->type) &&
6500 		xmlStrEqual(namespaceName, rel->importNamespace))
6501 		return (0);
6502 	    rel = rel->next;
6503 	} while (rel != NULL);
6504     }
6505     /*
6506     * No matching <import>ed namespace found.
6507     */
6508     {
6509 	xmlNodePtr n = (attr != NULL) ? (xmlNodePtr) attr : node;
6510 
6511 	if (namespaceName == NULL)
6512 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
6513 		XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6514 		"References from this schema to components in no "
6515 		"namespace are not allowed, since not indicated by an "
6516 		"import statement", NULL, NULL);
6517 	else
6518 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
6519 		XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6520 		"References from this schema to components in the "
6521 		"namespace '%s' are not allowed, since not indicated by an "
6522 		"import statement", namespaceName, NULL);
6523     }
6524     return (XML_SCHEMAP_SRC_RESOLVE);
6525 }
6526 
6527 /**
6528  * xmlSchemaParseLocalAttributes:
6529  * @ctxt:  a schema validation context
6530  * @schema:  the schema being built
6531  * @node:  a subtree containing XML Schema informations
6532  * @type:  the hosting type where the attributes will be anchored
6533  *
6534  * Parses attribute uses and attribute declarations and
6535  * attribute group references.
6536  */
6537 static int
xmlSchemaParseLocalAttributes(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr * child,xmlSchemaItemListPtr * list,int parentType,int * hasRefs)6538 xmlSchemaParseLocalAttributes(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6539                         xmlNodePtr *child, xmlSchemaItemListPtr *list,
6540 			int parentType, int *hasRefs)
6541 {
6542     void *item;
6543 
6544     while ((IS_SCHEMA((*child), "attribute")) ||
6545            (IS_SCHEMA((*child), "attributeGroup"))) {
6546         if (IS_SCHEMA((*child), "attribute")) {
6547 	    item = xmlSchemaParseLocalAttribute(ctxt, schema, *child,
6548 		*list, parentType);
6549         } else {
6550             item = xmlSchemaParseAttributeGroupRef(ctxt, schema, *child);
6551 	    if ((item != NULL) && (hasRefs != NULL))
6552 		*hasRefs = 1;
6553         }
6554 	if (item != NULL) {
6555 	    if (*list == NULL) {
6556 		/* TODO: Customize grow factor. */
6557 		*list = xmlSchemaItemListCreate();
6558 		if (*list == NULL)
6559 		    return(-1);
6560 	    }
6561 	    if (xmlSchemaItemListAddSize(*list, 2, item) == -1)
6562 		return(-1);
6563 	}
6564         *child = (*child)->next;
6565     }
6566     return (0);
6567 }
6568 
6569 /**
6570  * xmlSchemaParseAnnotation:
6571  * @ctxt:  a schema validation context
6572  * @schema:  the schema being built
6573  * @node:  a subtree containing XML Schema informations
6574  *
6575  * parse a XML schema Attrribute declaration
6576  * *WARNING* this interface is highly subject to change
6577  *
6578  * Returns -1 in case of error, 0 if the declaration is improper and
6579  *         1 in case of success.
6580  */
6581 static xmlSchemaAnnotPtr
xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,int needed)6582 xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int needed)
6583 {
6584     xmlSchemaAnnotPtr ret;
6585     xmlNodePtr child = NULL;
6586     xmlAttrPtr attr;
6587     int barked = 0;
6588 
6589     /*
6590     * INFO: S4S completed.
6591     */
6592     /*
6593     * id = ID
6594     * {any attributes with non-schema namespace . . .}>
6595     * Content: (appinfo | documentation)*
6596     */
6597     if ((ctxt == NULL) || (node == NULL))
6598         return (NULL);
6599     if (needed)
6600 	ret = xmlSchemaNewAnnot(ctxt, node);
6601     else
6602 	ret = NULL;
6603     attr = node->properties;
6604     while (attr != NULL) {
6605 	if (((attr->ns == NULL) &&
6606 	    (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
6607 	    ((attr->ns != NULL) &&
6608 	    xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
6609 
6610 	    xmlSchemaPIllegalAttrErr(ctxt,
6611 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6612 	}
6613 	attr = attr->next;
6614     }
6615     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6616     /*
6617     * And now for the children...
6618     */
6619     child = node->children;
6620     while (child != NULL) {
6621 	if (IS_SCHEMA(child, "appinfo")) {
6622 	    /* TODO: make available the content of "appinfo". */
6623 	    /*
6624 	    * source = anyURI
6625 	    * {any attributes with non-schema namespace . . .}>
6626 	    * Content: ({any})*
6627 	    */
6628 	    attr = child->properties;
6629 	    while (attr != NULL) {
6630 		if (((attr->ns == NULL) &&
6631 		     (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
6632 		     ((attr->ns != NULL) &&
6633 		      xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
6634 
6635 		    xmlSchemaPIllegalAttrErr(ctxt,
6636 			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6637 		}
6638 		attr = attr->next;
6639 	    }
6640 	    xmlSchemaPValAttr(ctxt, NULL, child, "source",
6641 		xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
6642 	    child = child->next;
6643 	} else if (IS_SCHEMA(child, "documentation")) {
6644 	    /* TODO: make available the content of "documentation". */
6645 	    /*
6646 	    * source = anyURI
6647 	    * {any attributes with non-schema namespace . . .}>
6648 	    * Content: ({any})*
6649 	    */
6650 	    attr = child->properties;
6651 	    while (attr != NULL) {
6652 		if (attr->ns == NULL) {
6653 		    if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
6654 			xmlSchemaPIllegalAttrErr(ctxt,
6655 			    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6656 		    }
6657 		} else {
6658 		    if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
6659 			(xmlStrEqual(attr->name, BAD_CAST "lang") &&
6660 			(!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
6661 
6662 			xmlSchemaPIllegalAttrErr(ctxt,
6663 			    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6664 		    }
6665 		}
6666 		attr = attr->next;
6667 	    }
6668 	    /*
6669 	    * Attribute "xml:lang".
6670 	    */
6671 	    attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
6672 	    if (attr != NULL)
6673 		xmlSchemaPValAttrNode(ctxt, NULL, attr,
6674 		xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
6675 	    child = child->next;
6676 	} else {
6677 	    if (!barked)
6678 		xmlSchemaPContentErr(ctxt,
6679 		    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6680 		    NULL, node, child, NULL, "(appinfo | documentation)*");
6681 	    barked = 1;
6682 	    child = child->next;
6683 	}
6684     }
6685 
6686     return (ret);
6687 }
6688 
6689 /**
6690  * xmlSchemaParseFacet:
6691  * @ctxt:  a schema validation context
6692  * @schema:  the schema being built
6693  * @node:  a subtree containing XML Schema informations
6694  *
6695  * parse a XML schema Facet declaration
6696  * *WARNING* this interface is highly subject to change
6697  *
6698  * Returns the new type structure or NULL in case of error
6699  */
6700 static xmlSchemaFacetPtr
xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)6701 xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6702                     xmlNodePtr node)
6703 {
6704     xmlSchemaFacetPtr facet;
6705     xmlNodePtr child = NULL;
6706     const xmlChar *value;
6707 
6708     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6709         return (NULL);
6710 
6711     facet = xmlSchemaNewFacet();
6712     if (facet == NULL) {
6713         xmlSchemaPErrMemory(ctxt, "allocating facet", node);
6714         return (NULL);
6715     }
6716     facet->node = node;
6717     value = xmlSchemaGetProp(ctxt, node, "value");
6718     if (value == NULL) {
6719         xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
6720                        "Facet %s has no value\n", node->name, NULL);
6721         xmlSchemaFreeFacet(facet);
6722         return (NULL);
6723     }
6724     if (IS_SCHEMA(node, "minInclusive")) {
6725         facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
6726     } else if (IS_SCHEMA(node, "minExclusive")) {
6727         facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
6728     } else if (IS_SCHEMA(node, "maxInclusive")) {
6729         facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
6730     } else if (IS_SCHEMA(node, "maxExclusive")) {
6731         facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
6732     } else if (IS_SCHEMA(node, "totalDigits")) {
6733         facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
6734     } else if (IS_SCHEMA(node, "fractionDigits")) {
6735         facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
6736     } else if (IS_SCHEMA(node, "pattern")) {
6737         facet->type = XML_SCHEMA_FACET_PATTERN;
6738     } else if (IS_SCHEMA(node, "enumeration")) {
6739         facet->type = XML_SCHEMA_FACET_ENUMERATION;
6740     } else if (IS_SCHEMA(node, "whiteSpace")) {
6741         facet->type = XML_SCHEMA_FACET_WHITESPACE;
6742     } else if (IS_SCHEMA(node, "length")) {
6743         facet->type = XML_SCHEMA_FACET_LENGTH;
6744     } else if (IS_SCHEMA(node, "maxLength")) {
6745         facet->type = XML_SCHEMA_FACET_MAXLENGTH;
6746     } else if (IS_SCHEMA(node, "minLength")) {
6747         facet->type = XML_SCHEMA_FACET_MINLENGTH;
6748     } else {
6749         xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
6750                        "Unknown facet type %s\n", node->name, NULL);
6751         xmlSchemaFreeFacet(facet);
6752         return (NULL);
6753     }
6754     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6755     facet->value = value;
6756     if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
6757 	(facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
6758 	const xmlChar *fixed;
6759 
6760 	fixed = xmlSchemaGetProp(ctxt, node, "fixed");
6761 	if (fixed != NULL) {
6762 	    if (xmlStrEqual(fixed, BAD_CAST "true"))
6763 		facet->fixed = 1;
6764 	}
6765     }
6766     child = node->children;
6767 
6768     if (IS_SCHEMA(child, "annotation")) {
6769         facet->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
6770         child = child->next;
6771     }
6772     if (child != NULL) {
6773         xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
6774                        "Facet %s has unexpected child content\n",
6775                        node->name, NULL);
6776     }
6777     return (facet);
6778 }
6779 
6780 /**
6781  * xmlSchemaParseWildcardNs:
6782  * @ctxt:  a schema parser context
6783  * @wildc:  the wildcard, already created
6784  * @node:  a subtree containing XML Schema informations
6785  *
6786  * Parses the attribute "processContents" and "namespace"
6787  * of a xsd:anyAttribute and xsd:any.
6788  * *WARNING* this interface is highly subject to change
6789  *
6790  * Returns 0 if everything goes fine, a positive error code
6791  * if something is not valid and -1 if an internal error occurs.
6792  */
6793 static int
xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema ATTRIBUTE_UNUSED,xmlSchemaWildcardPtr wildc,xmlNodePtr node)6794 xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
6795 			 xmlSchemaPtr schema ATTRIBUTE_UNUSED,
6796 			 xmlSchemaWildcardPtr wildc,
6797 			 xmlNodePtr node)
6798 {
6799     const xmlChar *pc, *ns, *dictnsItem;
6800     int ret = 0;
6801     xmlChar *nsItem;
6802     xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
6803     xmlAttrPtr attr;
6804 
6805     pc = xmlSchemaGetProp(ctxt, node, "processContents");
6806     if ((pc == NULL)
6807         || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
6808         wildc->processContents = XML_SCHEMAS_ANY_STRICT;
6809     } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
6810         wildc->processContents = XML_SCHEMAS_ANY_SKIP;
6811     } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
6812         wildc->processContents = XML_SCHEMAS_ANY_LAX;
6813     } else {
6814         xmlSchemaPSimpleTypeErr(ctxt,
6815 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6816 	    NULL, node,
6817 	    NULL, "(strict | skip | lax)", pc,
6818 	    NULL, NULL, NULL);
6819         wildc->processContents = XML_SCHEMAS_ANY_STRICT;
6820 	ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
6821     }
6822     /*
6823      * Build the namespace constraints.
6824      */
6825     attr = xmlSchemaGetPropNode(node, "namespace");
6826     ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6827     if ((attr == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
6828 	wildc->any = 1;
6829     else if (xmlStrEqual(ns, BAD_CAST "##other")) {
6830 	wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
6831 	if (wildc->negNsSet == NULL) {
6832 	    return (-1);
6833 	}
6834 	wildc->negNsSet->value = ctxt->targetNamespace;
6835     } else {
6836 	const xmlChar *end, *cur;
6837 
6838 	cur = ns;
6839 	do {
6840 	    while (IS_BLANK_CH(*cur))
6841 		cur++;
6842 	    end = cur;
6843 	    while ((*end != 0) && (!(IS_BLANK_CH(*end))))
6844 		end++;
6845 	    if (end == cur)
6846 		break;
6847 	    nsItem = xmlStrndup(cur, end - cur);
6848 	    if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
6849 		    (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
6850 		xmlSchemaPSimpleTypeErr(ctxt,
6851 		    XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
6852 		    NULL, (xmlNodePtr) attr,
6853 		    NULL,
6854 		    "((##any | ##other) | List of (xs:anyURI | "
6855 		    "(##targetNamespace | ##local)))",
6856 		    nsItem, NULL, NULL, NULL);
6857 		ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
6858 	    } else {
6859 		if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
6860 		    dictnsItem = ctxt->targetNamespace;
6861 		} else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
6862 		    dictnsItem = NULL;
6863 		} else {
6864 		    /*
6865 		    * Validate the item (anyURI).
6866 		    */
6867 		    xmlSchemaPValAttrNodeValue(ctxt, NULL, attr,
6868 			nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
6869 		    dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
6870 		}
6871 		/*
6872 		* Avoid dublicate namespaces.
6873 		*/
6874 		tmp = wildc->nsSet;
6875 		while (tmp != NULL) {
6876 		    if (dictnsItem == tmp->value)
6877 			break;
6878 		    tmp = tmp->next;
6879 		}
6880 		if (tmp == NULL) {
6881 		    tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
6882 		    if (tmp == NULL) {
6883 			xmlFree(nsItem);
6884 			return (-1);
6885 		    }
6886 		    tmp->value = dictnsItem;
6887 		    tmp->next = NULL;
6888 		    if (wildc->nsSet == NULL)
6889 			wildc->nsSet = tmp;
6890 		    else if (lastNs != NULL)
6891 			lastNs->next = tmp;
6892 		    lastNs = tmp;
6893 		}
6894 
6895 	    }
6896 	    xmlFree(nsItem);
6897 	    cur = end;
6898 	} while (*cur != 0);
6899     }
6900     return (ret);
6901 }
6902 
6903 static int
xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr item ATTRIBUTE_UNUSED,xmlNodePtr node,int minOccurs,int maxOccurs)6904 xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
6905 				 xmlSchemaParticlePtr item ATTRIBUTE_UNUSED,
6906 				 xmlNodePtr node,
6907 				 int minOccurs,
6908 				 int maxOccurs) {
6909 
6910     if ((maxOccurs == 0) && ( minOccurs == 0))
6911 	return (0);
6912     if (maxOccurs != UNBOUNDED) {
6913 	/*
6914 	* TODO: Maybe we should better not create the particle,
6915 	* if min/max is invalid, since it could confuse the build of the
6916 	* content model.
6917 	*/
6918 	/*
6919 	* 3.9.6 Schema Component Constraint: Particle Correct
6920 	*
6921 	*/
6922 	if (maxOccurs < 1) {
6923 	    /*
6924 	    * 2.2 {max occurs} must be greater than or equal to 1.
6925 	    */
6926 	    xmlSchemaPCustomAttrErr(ctxt,
6927 		XML_SCHEMAP_P_PROPS_CORRECT_2_2,
6928 		NULL, NULL,
6929 		xmlSchemaGetPropNode(node, "maxOccurs"),
6930 		"The value must be greater than or equal to 1");
6931 	    return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
6932 	} else if (minOccurs > maxOccurs) {
6933 	    /*
6934 	    * 2.1 {min occurs} must not be greater than {max occurs}.
6935 	    */
6936 	    xmlSchemaPCustomAttrErr(ctxt,
6937 		XML_SCHEMAP_P_PROPS_CORRECT_2_1,
6938 		NULL, NULL,
6939 		xmlSchemaGetPropNode(node, "minOccurs"),
6940 		"The value must not be greater than the value of 'maxOccurs'");
6941 	    return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
6942 	}
6943     }
6944     return (0);
6945 }
6946 
6947 /**
6948  * xmlSchemaParseAny:
6949  * @ctxt:  a schema validation context
6950  * @schema:  the schema being built
6951  * @node:  a subtree containing XML Schema informations
6952  *
6953  * Parsea a XML schema <any> element. A particle and wildcard
6954  * will be created (except if minOccurs==maxOccurs==0, in this case
6955  * nothing will be created).
6956  * *WARNING* this interface is highly subject to change
6957  *
6958  * Returns the particle or NULL in case of error or if minOccurs==maxOccurs==0
6959  */
6960 static xmlSchemaParticlePtr
xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)6961 xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6962                   xmlNodePtr node)
6963 {
6964     xmlSchemaParticlePtr particle;
6965     xmlNodePtr child = NULL;
6966     xmlSchemaWildcardPtr wild;
6967     int min, max;
6968     xmlAttrPtr attr;
6969     xmlSchemaAnnotPtr annot = NULL;
6970 
6971     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6972         return (NULL);
6973     /*
6974     * Check for illegal attributes.
6975     */
6976     attr = node->properties;
6977     while (attr != NULL) {
6978 	if (attr->ns == NULL) {
6979 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6980 		(!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
6981 		(!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
6982 	        (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6983 		(!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
6984 		xmlSchemaPIllegalAttrErr(ctxt,
6985 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6986 	    }
6987 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6988 	    xmlSchemaPIllegalAttrErr(ctxt,
6989 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6990 	}
6991 	attr = attr->next;
6992     }
6993     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6994     /*
6995     * minOccurs/maxOccurs.
6996     */
6997     max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
6998 	"(xs:nonNegativeInteger | unbounded)");
6999     min = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
7000 	"xs:nonNegativeInteger");
7001     xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
7002     /*
7003     * Create & parse the wildcard.
7004     */
7005     wild = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY, node);
7006     if (wild == NULL)
7007 	return (NULL);
7008     xmlSchemaParseWildcardNs(ctxt, schema, wild, node);
7009     /*
7010     * And now for the children...
7011     */
7012     child = node->children;
7013     if (IS_SCHEMA(child, "annotation")) {
7014         annot = xmlSchemaParseAnnotation(ctxt, child, 1);
7015         child = child->next;
7016     }
7017     if (child != NULL) {
7018 	xmlSchemaPContentErr(ctxt,
7019 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7020 	    NULL, node, child,
7021 	    NULL, "(annotation?)");
7022     }
7023     /*
7024     * No component if minOccurs==maxOccurs==0.
7025     */
7026     if ((min == 0) && (max == 0)) {
7027 	/* Don't free the wildcard, since it's already on the list. */
7028 	return (NULL);
7029     }
7030     /*
7031     * Create the particle.
7032     */
7033     particle = xmlSchemaAddParticle(ctxt, node, min, max);
7034     if (particle == NULL)
7035         return (NULL);
7036     particle->annot = annot;
7037     particle->children = (xmlSchemaTreeItemPtr) wild;
7038 
7039     return (particle);
7040 }
7041 
7042 /**
7043  * xmlSchemaParseNotation:
7044  * @ctxt:  a schema validation context
7045  * @schema:  the schema being built
7046  * @node:  a subtree containing XML Schema informations
7047  *
7048  * parse a XML schema Notation declaration
7049  *
7050  * Returns the new structure or NULL in case of error
7051  */
7052 static xmlSchemaNotationPtr
xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)7053 xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
7054                        xmlNodePtr node)
7055 {
7056     const xmlChar *name;
7057     xmlSchemaNotationPtr ret;
7058     xmlNodePtr child = NULL;
7059 
7060     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7061         return (NULL);
7062     name = xmlSchemaGetProp(ctxt, node, "name");
7063     if (name == NULL) {
7064         xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
7065                        "Notation has no name\n", NULL, NULL);
7066         return (NULL);
7067     }
7068     ret = xmlSchemaAddNotation(ctxt, schema, name,
7069 	ctxt->targetNamespace, node);
7070     if (ret == NULL)
7071         return (NULL);
7072     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
7073 
7074     child = node->children;
7075     if (IS_SCHEMA(child, "annotation")) {
7076         ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
7077         child = child->next;
7078     }
7079     if (child != NULL) {
7080 	xmlSchemaPContentErr(ctxt,
7081 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7082 	    NULL, node, child,
7083 	    NULL, "(annotation?)");
7084     }
7085 
7086     return (ret);
7087 }
7088 
7089 /**
7090  * xmlSchemaParseAnyAttribute:
7091  * @ctxt:  a schema validation context
7092  * @schema:  the schema being built
7093  * @node:  a subtree containing XML Schema informations
7094  *
7095  * parse a XML schema AnyAttrribute declaration
7096  * *WARNING* this interface is highly subject to change
7097  *
7098  * Returns a wildcard or NULL.
7099  */
7100 static xmlSchemaWildcardPtr
xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)7101 xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
7102                            xmlSchemaPtr schema, xmlNodePtr node)
7103 {
7104     xmlSchemaWildcardPtr ret;
7105     xmlNodePtr child = NULL;
7106     xmlAttrPtr attr;
7107 
7108     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7109         return (NULL);
7110 
7111     ret = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
7112 	node);
7113     if (ret == NULL) {
7114         return (NULL);
7115     }
7116     /*
7117     * Check for illegal attributes.
7118     */
7119     attr = node->properties;
7120     while (attr != NULL) {
7121 	if (attr->ns == NULL) {
7122 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7123 	        (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
7124 		(!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
7125 		xmlSchemaPIllegalAttrErr(ctxt,
7126 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7127 	    }
7128 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7129 	    xmlSchemaPIllegalAttrErr(ctxt,
7130 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7131 	}
7132 	attr = attr->next;
7133     }
7134     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
7135     /*
7136     * Parse the namespace list.
7137     */
7138     if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0)
7139 	return (NULL);
7140     /*
7141     * And now for the children...
7142     */
7143     child = node->children;
7144     if (IS_SCHEMA(child, "annotation")) {
7145         ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
7146         child = child->next;
7147     }
7148     if (child != NULL) {
7149 	xmlSchemaPContentErr(ctxt,
7150 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7151 	    NULL, node, child,
7152 	    NULL, "(annotation?)");
7153     }
7154 
7155     return (ret);
7156 }
7157 
7158 
7159 /**
7160  * xmlSchemaParseAttribute:
7161  * @ctxt:  a schema validation context
7162  * @schema:  the schema being built
7163  * @node:  a subtree containing XML Schema informations
7164  *
7165  * parse a XML schema Attrribute declaration
7166  * *WARNING* this interface is highly subject to change
7167  *
7168  * Returns the attribute declaration.
7169  */
7170 static xmlSchemaBasicItemPtr
xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node,xmlSchemaItemListPtr uses,int parentType)7171 xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
7172 			     xmlSchemaPtr schema,
7173 			     xmlNodePtr node,
7174 			     xmlSchemaItemListPtr uses,
7175 			     int parentType)
7176 {
7177     const xmlChar *attrValue, *name = NULL, *ns = NULL;
7178     xmlSchemaAttributeUsePtr use = NULL;
7179     xmlNodePtr child = NULL;
7180     xmlAttrPtr attr;
7181     const xmlChar *tmpNs = NULL, *tmpName = NULL, *defValue = NULL;
7182     int isRef = 0, occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7183     int	nberrors, hasForm = 0, defValueType = 0;
7184 
7185 #define WXS_ATTR_DEF_VAL_DEFAULT 1
7186 #define WXS_ATTR_DEF_VAL_FIXED 2
7187 
7188     /*
7189      * 3.2.3 Constraints on XML Representations of Attribute Declarations
7190      */
7191 
7192     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7193         return (NULL);
7194     attr = xmlSchemaGetPropNode(node, "ref");
7195     if (attr != NULL) {
7196 	if (xmlSchemaPValAttrNodeQName(pctxt, schema,
7197 	    NULL, attr, &tmpNs, &tmpName) != 0) {
7198 	    return (NULL);
7199 	}
7200 	if (xmlSchemaCheckReference(pctxt, schema, node, attr, tmpNs) != 0)
7201 	    return(NULL);
7202 	isRef = 1;
7203     }
7204     nberrors = pctxt->nberrors;
7205     /*
7206     * Check for illegal attributes.
7207     */
7208     attr = node->properties;
7209     while (attr != NULL) {
7210 	if (attr->ns == NULL) {
7211 	    if (isRef) {
7212 		if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7213 		    xmlSchemaPValAttrNodeID(pctxt, attr);
7214 		    goto attr_next;
7215 		} else if (xmlStrEqual(attr->name, BAD_CAST "ref")) {
7216 		    goto attr_next;
7217 		}
7218 	    } else {
7219 		if (xmlStrEqual(attr->name, BAD_CAST "name")) {
7220 		    goto attr_next;
7221 		} else if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7222 		    xmlSchemaPValAttrNodeID(pctxt, attr);
7223 		    goto attr_next;
7224 		} else if (xmlStrEqual(attr->name, BAD_CAST "type")) {
7225 		    xmlSchemaPValAttrNodeQName(pctxt, schema, NULL,
7226 			attr, &tmpNs, &tmpName);
7227 		    goto attr_next;
7228 		} else if (xmlStrEqual(attr->name, BAD_CAST "form")) {
7229 		    /*
7230 		    * Evaluate the target namespace
7231 		    */
7232 		    hasForm = 1;
7233 		    attrValue = xmlSchemaGetNodeContent(pctxt,
7234 			(xmlNodePtr) attr);
7235 		    if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
7236 			ns = pctxt->targetNamespace;
7237 		    } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified"))
7238 		    {
7239 			xmlSchemaPSimpleTypeErr(pctxt,
7240 			    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7241 			    NULL, (xmlNodePtr) attr,
7242 			    NULL, "(qualified | unqualified)",
7243 			    attrValue, NULL, NULL, NULL);
7244 		    }
7245 		    goto attr_next;
7246 		}
7247 	    }
7248 	    if (xmlStrEqual(attr->name, BAD_CAST "use")) {
7249 
7250 		attrValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7251 		/* TODO: Maybe we need to normalize the value beforehand. */
7252 		if (xmlStrEqual(attrValue, BAD_CAST "optional"))
7253 		    occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7254 		else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
7255 		    occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
7256 		else if (xmlStrEqual(attrValue, BAD_CAST "required"))
7257 		    occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
7258 		else {
7259 		    xmlSchemaPSimpleTypeErr(pctxt,
7260 			XML_SCHEMAP_INVALID_ATTR_USE,
7261 			NULL, (xmlNodePtr) attr,
7262 			NULL, "(optional | prohibited | required)",
7263 			attrValue, NULL, NULL, NULL);
7264 		}
7265 		goto attr_next;
7266 	    } else if (xmlStrEqual(attr->name, BAD_CAST "default")) {
7267 		/*
7268 		* 3.2.3 : 1
7269 		* default and fixed must not both be present.
7270 		*/
7271 		if (defValue) {
7272 		    xmlSchemaPMutualExclAttrErr(pctxt,
7273 			XML_SCHEMAP_SRC_ATTRIBUTE_1,
7274 			NULL, attr, "default", "fixed");
7275 		} else {
7276 		    defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7277 		    defValueType = WXS_ATTR_DEF_VAL_DEFAULT;
7278 		}
7279 		goto attr_next;
7280 	    } else if (xmlStrEqual(attr->name, BAD_CAST "fixed")) {
7281 		/*
7282 		* 3.2.3 : 1
7283 		* default and fixed must not both be present.
7284 		*/
7285 		if (defValue) {
7286 		    xmlSchemaPMutualExclAttrErr(pctxt,
7287 			XML_SCHEMAP_SRC_ATTRIBUTE_1,
7288 			NULL, attr, "default", "fixed");
7289 		} else {
7290 		    defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7291 		    defValueType = WXS_ATTR_DEF_VAL_FIXED;
7292 		}
7293 		goto attr_next;
7294 	    }
7295 	} else if (! xmlStrEqual(attr->ns->href, xmlSchemaNs))
7296 	    goto attr_next;
7297 
7298 	xmlSchemaPIllegalAttrErr(pctxt,
7299 	    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7300 
7301 attr_next:
7302 	attr = attr->next;
7303     }
7304     /*
7305     * 3.2.3 : 2
7306     * If default and use are both present, use must have
7307     * the actual value optional.
7308     */
7309     if ((defValueType == WXS_ATTR_DEF_VAL_DEFAULT) &&
7310 	(occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL)) {
7311 	xmlSchemaPSimpleTypeErr(pctxt,
7312 	    XML_SCHEMAP_SRC_ATTRIBUTE_2,
7313 	    NULL, node, NULL,
7314 	    "(optional | prohibited | required)", NULL,
7315 	    "The value of the attribute 'use' must be 'optional' "
7316 	    "if the attribute 'default' is present",
7317 	    NULL, NULL);
7318     }
7319     /*
7320     * We want correct attributes.
7321     */
7322     if (nberrors != pctxt->nberrors)
7323 	return(NULL);
7324     if (! isRef) {
7325 	xmlSchemaAttributePtr attrDecl;
7326 
7327 	/* TODO: move XML_SCHEMAS_QUALIF_ATTR to the parser. */
7328 	if ((! hasForm) && (schema->flags & XML_SCHEMAS_QUALIF_ATTR))
7329 	    ns = pctxt->targetNamespace;
7330 	/*
7331 	* 3.2.6 Schema Component Constraint: xsi: Not Allowed
7332 	* TODO: Move this to the component layer.
7333 	*/
7334 	if (xmlStrEqual(ns, xmlSchemaInstanceNs)) {
7335 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
7336 		XML_SCHEMAP_NO_XSI,
7337 		node, NULL,
7338 		"The target namespace must not match '%s'",
7339 		xmlSchemaInstanceNs, NULL);
7340 	}
7341 	attr = xmlSchemaGetPropNode(node, "name");
7342 	if (attr == NULL) {
7343 	    xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7344 		NULL, node, "name", NULL);
7345 	    return (NULL);
7346 	}
7347 	if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7348 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7349 	    return (NULL);
7350 	}
7351 	/*
7352 	* 3.2.6 Schema Component Constraint: xmlns Not Allowed
7353 	* TODO: Move this to the component layer.
7354 	*/
7355 	if (xmlStrEqual(name, BAD_CAST "xmlns")) {
7356 	    xmlSchemaPSimpleTypeErr(pctxt,
7357 		XML_SCHEMAP_NO_XMLNS,
7358 		NULL, (xmlNodePtr) attr,
7359 		xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7360 		"The value of the attribute must not match 'xmlns'",
7361 		NULL, NULL);
7362 	    return (NULL);
7363 	}
7364 	if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED)
7365 	    goto check_children;
7366 	/*
7367 	* Create the attribute use component.
7368 	*/
7369 	use = xmlSchemaAddAttributeUse(pctxt, node);
7370 	if (use == NULL)
7371 	    return(NULL);
7372 	use->occurs = occurs;
7373 	/*
7374 	* Create the attribute declaration.
7375 	*/
7376 	attrDecl = xmlSchemaAddAttribute(pctxt, schema, name, ns, node, 0);
7377 	if (attrDecl == NULL)
7378 	    return (NULL);
7379 	if (tmpName != NULL) {
7380 	    attrDecl->typeName = tmpName;
7381 	    attrDecl->typeNs = tmpNs;
7382 	}
7383 	use->attrDecl = attrDecl;
7384 	/*
7385 	* Value constraint.
7386 	*/
7387 	if (defValue != NULL) {
7388 	    attrDecl->defValue = defValue;
7389 	    if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7390 		attrDecl->flags |= XML_SCHEMAS_ATTR_FIXED;
7391 	}
7392     } else if (occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7393 	xmlSchemaQNameRefPtr ref;
7394 
7395 	/*
7396 	* Create the attribute use component.
7397 	*/
7398 	use = xmlSchemaAddAttributeUse(pctxt, node);
7399 	if (use == NULL)
7400 	    return(NULL);
7401 	/*
7402 	* We need to resolve the reference at later stage.
7403 	*/
7404 	WXS_ADD_PENDING(pctxt, use);
7405 	use->occurs = occurs;
7406 	/*
7407 	* Create a QName reference to the attribute declaration.
7408 	*/
7409 	ref = xmlSchemaNewQNameRef(pctxt, XML_SCHEMA_TYPE_ATTRIBUTE,
7410 	    tmpName, tmpNs);
7411 	if (ref == NULL)
7412 	    return(NULL);
7413 	/*
7414 	* Assign the reference. This will be substituted for the
7415 	* referenced attribute declaration when the QName is resolved.
7416 	*/
7417 	use->attrDecl = WXS_ATTR_CAST ref;
7418 	/*
7419 	* Value constraint.
7420 	*/
7421 	if (defValue != NULL)
7422 	    use->defValue = defValue;
7423 	if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7424 	    use->flags |= XML_SCHEMA_ATTR_USE_FIXED;
7425     }
7426 
7427 check_children:
7428     /*
7429     * And now for the children...
7430     */
7431     child = node->children;
7432     if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7433 	xmlSchemaAttributeUseProhibPtr prohib;
7434 
7435 	if (IS_SCHEMA(child, "annotation")) {
7436 	    xmlSchemaParseAnnotation(pctxt, child, 0);
7437 	    child = child->next;
7438 	}
7439 	if (child != NULL) {
7440 	    xmlSchemaPContentErr(pctxt,
7441 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7442 		NULL, node, child, NULL,
7443 		"(annotation?)");
7444 	}
7445 	/*
7446 	* Check for pointlessness of attribute prohibitions.
7447 	*/
7448 	if (parentType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
7449 	    xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7450 		XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7451 		node, NULL,
7452 		"Skipping attribute use prohibition, since it is "
7453 		"pointless inside an <attributeGroup>",
7454 		NULL, NULL, NULL);
7455 	    return(NULL);
7456 	} else if (parentType == XML_SCHEMA_TYPE_EXTENSION) {
7457 	    xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7458 		XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7459 		node, NULL,
7460 		"Skipping attribute use prohibition, since it is "
7461 		"pointless when extending a type",
7462 		NULL, NULL, NULL);
7463 	    return(NULL);
7464 	}
7465 	if (! isRef) {
7466 	    tmpName = name;
7467 	    tmpNs = ns;
7468 	}
7469 	/*
7470 	* Check for duplicate attribute prohibitions.
7471 	*/
7472 	if (uses) {
7473 	    int i;
7474 
7475 	    for (i = 0; i < uses->nbItems; i++) {
7476 		use = uses->items[i];
7477 		if ((use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) &&
7478 		    (tmpName == (WXS_ATTR_PROHIB_CAST use)->name) &&
7479 		    (tmpNs == (WXS_ATTR_PROHIB_CAST use)->targetNamespace))
7480 		{
7481 		    xmlChar *str = NULL;
7482 
7483 		    xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7484 			XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7485 			node, NULL,
7486 			"Skipping duplicate attribute use prohibition '%s'",
7487 			xmlSchemaFormatQName(&str, tmpNs, tmpName),
7488 			NULL, NULL);
7489 		    FREE_AND_NULL(str)
7490 		    return(NULL);
7491 		}
7492 	    }
7493 	}
7494 	/*
7495 	* Create the attribute prohibition helper component.
7496 	*/
7497 	prohib = xmlSchemaAddAttributeUseProhib(pctxt);
7498 	if (prohib == NULL)
7499 	    return(NULL);
7500 	prohib->node = node;
7501 	prohib->name = tmpName;
7502 	prohib->targetNamespace = tmpNs;
7503 	if (isRef) {
7504 	    /*
7505 	    * We need at least to resolve to the attribute declaration.
7506 	    */
7507 	    WXS_ADD_PENDING(pctxt, prohib);
7508 	}
7509 	return(WXS_BASIC_CAST prohib);
7510     } else {
7511 	if (IS_SCHEMA(child, "annotation")) {
7512 	    /*
7513 	    * TODO: Should this go into the attr decl?
7514 	    */
7515 	    use->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7516 	    child = child->next;
7517 	}
7518 	if (isRef) {
7519 	    if (child != NULL) {
7520 		if (IS_SCHEMA(child, "simpleType"))
7521 		    /*
7522 		    * 3.2.3 : 3.2
7523 		    * If ref is present, then all of <simpleType>,
7524 		    * form and type must be absent.
7525 		    */
7526 		    xmlSchemaPContentErr(pctxt,
7527 			XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
7528 			NULL, node, child, NULL,
7529 			"(annotation?)");
7530 		else
7531 		    xmlSchemaPContentErr(pctxt,
7532 			XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7533 			NULL, node, child, NULL,
7534 			"(annotation?)");
7535 	    }
7536 	} else {
7537 	    if (IS_SCHEMA(child, "simpleType")) {
7538 		if (WXS_ATTRUSE_DECL(use)->typeName != NULL) {
7539 		    /*
7540 		    * 3.2.3 : 4
7541 		    * type and <simpleType> must not both be present.
7542 		    */
7543 		    xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7544 			NULL, node, child,
7545 			"The attribute 'type' and the <simpleType> child "
7546 			"are mutually exclusive", NULL);
7547 		} else
7548 		    WXS_ATTRUSE_TYPEDEF(use) =
7549 			xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7550 		child = child->next;
7551 	    }
7552 	    if (child != NULL)
7553 		xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7554 		NULL, node, child, NULL,
7555 		"(annotation?, simpleType?)");
7556 	}
7557     }
7558     return (WXS_BASIC_CAST use);
7559 }
7560 
7561 
7562 static xmlSchemaAttributePtr
xmlSchemaParseGlobalAttribute(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node)7563 xmlSchemaParseGlobalAttribute(xmlSchemaParserCtxtPtr pctxt,
7564 			      xmlSchemaPtr schema,
7565 			      xmlNodePtr node)
7566 {
7567     const xmlChar *attrValue;
7568     xmlSchemaAttributePtr ret;
7569     xmlNodePtr child = NULL;
7570     xmlAttrPtr attr;
7571 
7572     /*
7573      * Note that the w3c spec assumes the schema to be validated with schema
7574      * for schemas beforehand.
7575      *
7576      * 3.2.3 Constraints on XML Representations of Attribute Declarations
7577      */
7578     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7579         return (NULL);
7580     /*
7581     * 3.2.3 : 3.1
7582     * One of ref or name must be present, but not both
7583     */
7584     attr = xmlSchemaGetPropNode(node, "name");
7585     if (attr == NULL) {
7586 	xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7587 	    NULL, node, "name", NULL);
7588 	return (NULL);
7589     }
7590     if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7591 	xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
7592 	return (NULL);
7593     }
7594     /*
7595     * 3.2.6 Schema Component Constraint: xmlns Not Allowed
7596     * TODO: Move this to the component layer.
7597     */
7598     if (xmlStrEqual(attrValue, BAD_CAST "xmlns")) {
7599 	xmlSchemaPSimpleTypeErr(pctxt,
7600 	    XML_SCHEMAP_NO_XMLNS,
7601 	    NULL, (xmlNodePtr) attr,
7602 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7603 	    "The value of the attribute must not match 'xmlns'",
7604 	    NULL, NULL);
7605 	return (NULL);
7606     }
7607     /*
7608     * 3.2.6 Schema Component Constraint: xsi: Not Allowed
7609     * TODO: Move this to the component layer.
7610     *       Or better leave it here and add it to the component layer
7611     *       if we have a schema construction API.
7612     */
7613     if (xmlStrEqual(pctxt->targetNamespace, xmlSchemaInstanceNs)) {
7614 	xmlSchemaCustomErr(ACTXT_CAST pctxt,
7615 	    XML_SCHEMAP_NO_XSI, node, NULL,
7616 	    "The target namespace must not match '%s'",
7617 	    xmlSchemaInstanceNs, NULL);
7618     }
7619 
7620     ret = xmlSchemaAddAttribute(pctxt, schema, attrValue,
7621 	pctxt->targetNamespace, node, 1);
7622     if (ret == NULL)
7623 	return (NULL);
7624     ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
7625 
7626     /*
7627     * Check for illegal attributes.
7628     */
7629     attr = node->properties;
7630     while (attr != NULL) {
7631 	if (attr->ns == NULL) {
7632 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7633 		(!xmlStrEqual(attr->name, BAD_CAST "default")) &&
7634 		(!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
7635 		(!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7636 		(!xmlStrEqual(attr->name, BAD_CAST "type")))
7637 	    {
7638 		xmlSchemaPIllegalAttrErr(pctxt,
7639 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7640 	    }
7641 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7642 	    xmlSchemaPIllegalAttrErr(pctxt,
7643 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7644 	}
7645 	attr = attr->next;
7646     }
7647     xmlSchemaPValAttrQName(pctxt, schema, NULL,
7648 	node, "type", &ret->typeNs, &ret->typeName);
7649 
7650     xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7651     /*
7652     * Attribute "fixed".
7653     */
7654     ret->defValue = xmlSchemaGetProp(pctxt, node, "fixed");
7655     if (ret->defValue != NULL)
7656 	ret->flags |= XML_SCHEMAS_ATTR_FIXED;
7657     /*
7658     * Attribute "default".
7659     */
7660     attr = xmlSchemaGetPropNode(node, "default");
7661     if (attr != NULL) {
7662 	/*
7663 	* 3.2.3 : 1
7664 	* default and fixed must not both be present.
7665 	*/
7666 	if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
7667 	    xmlSchemaPMutualExclAttrErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
7668 		WXS_BASIC_CAST ret, attr, "default", "fixed");
7669 	} else
7670 	    ret->defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7671     }
7672     /*
7673     * And now for the children...
7674     */
7675     child = node->children;
7676     if (IS_SCHEMA(child, "annotation")) {
7677         ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7678         child = child->next;
7679     }
7680     if (IS_SCHEMA(child, "simpleType")) {
7681 	if (ret->typeName != NULL) {
7682 	    /*
7683 	    * 3.2.3 : 4
7684 	    * type and <simpleType> must not both be present.
7685 	    */
7686 	    xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7687 		NULL, node, child,
7688 		"The attribute 'type' and the <simpleType> child "
7689 		"are mutually exclusive", NULL);
7690 	} else
7691 	    ret->subtypes = xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7692 	child = child->next;
7693     }
7694     if (child != NULL)
7695 	xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7696 	    NULL, node, child, NULL,
7697 	    "(annotation?, simpleType?)");
7698 
7699     return (ret);
7700 }
7701 
7702 /**
7703  * xmlSchemaParseAttributeGroupRef:
7704  * @ctxt:  a schema validation context
7705  * @schema:  the schema being built
7706  * @node:  a subtree containing XML Schema informations
7707  *
7708  * Parse an attribute group definition reference.
7709  * Note that a reference to an attribute group does not
7710  * correspond to any component at all.
7711  * *WARNING* this interface is highly subject to change
7712  *
7713  * Returns the attribute group or NULL in case of error.
7714  */
7715 static xmlSchemaQNameRefPtr
xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node)7716 xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,
7717 				xmlSchemaPtr schema,
7718 				xmlNodePtr node)
7719 {
7720     xmlSchemaQNameRefPtr ret;
7721     xmlNodePtr child = NULL;
7722     xmlAttrPtr attr;
7723     const xmlChar *refNs = NULL, *ref = NULL;
7724 
7725     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7726         return (NULL);
7727 
7728     attr = xmlSchemaGetPropNode(node, "ref");
7729     if (attr == NULL) {
7730 	xmlSchemaPMissingAttrErr(pctxt,
7731 	    XML_SCHEMAP_S4S_ATTR_MISSING,
7732 	    NULL, node, "ref", NULL);
7733 	return (NULL);
7734     }
7735     xmlSchemaPValAttrNodeQName(pctxt, schema,
7736 	NULL, attr, &refNs, &ref);
7737     if (xmlSchemaCheckReference(pctxt, schema, node, attr, refNs) != 0)
7738 	return(NULL);
7739 
7740     /*
7741     * Check for illegal attributes.
7742     */
7743     attr = node->properties;
7744     while (attr != NULL) {
7745 	if (attr->ns == NULL) {
7746 	    if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
7747 		(!xmlStrEqual(attr->name, BAD_CAST "id")))
7748 	    {
7749 		xmlSchemaPIllegalAttrErr(pctxt,
7750 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7751 	    }
7752 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7753 	    xmlSchemaPIllegalAttrErr(pctxt,
7754 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7755 	}
7756 	attr = attr->next;
7757     }
7758     /* Attribute ID */
7759     xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7760 
7761     /*
7762     * And now for the children...
7763     */
7764     child = node->children;
7765     if (IS_SCHEMA(child, "annotation")) {
7766 	/*
7767 	* TODO: We do not have a place to store the annotation, do we?
7768 	*/
7769         xmlSchemaParseAnnotation(pctxt, child, 0);
7770         child = child->next;
7771     }
7772     if (child != NULL) {
7773 	xmlSchemaPContentErr(pctxt,
7774 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7775 	    NULL, node, child, NULL,
7776 	    "(annotation?)");
7777     }
7778 
7779     /*
7780     * Handle attribute group redefinitions.
7781     */
7782     if (pctxt->isRedefine && pctxt->redef &&
7783 	(pctxt->redef->item->type ==
7784 	    XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
7785 	(ref == pctxt->redef->refName) &&
7786 	(refNs == pctxt->redef->refTargetNs))
7787     {
7788 	/*
7789 	* SPEC src-redefine:
7790 	* (7.1) "If it has an <attributeGroup> among its contents
7791 	* the `actual value` of whose ref [attribute] is the same
7792 	* as the `actual value` of its own name attribute plus
7793 	* target namespace, then it must have exactly one such group."
7794 	*/
7795 	if (pctxt->redefCounter != 0) {
7796 	    xmlChar *str = NULL;
7797 
7798 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
7799 		XML_SCHEMAP_SRC_REDEFINE, node, NULL,
7800 		"The redefining attribute group definition "
7801 		"'%s' must not contain more than one "
7802 		"reference to the redefined definition",
7803 		xmlSchemaFormatQName(&str, refNs, ref), NULL);
7804 	    FREE_AND_NULL(str);
7805 	    return(NULL);
7806 	}
7807 	pctxt->redefCounter++;
7808 	/*
7809 	* URGENT TODO: How to ensure that the reference will not be
7810 	* handled by the normal component resolution mechanism?
7811 	*/
7812 	ret = xmlSchemaNewQNameRef(pctxt,
7813 	    XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7814 	if (ret == NULL)
7815 	    return(NULL);
7816 	ret->node = node;
7817 	pctxt->redef->reference = WXS_BASIC_CAST ret;
7818     } else {
7819 	/*
7820 	* Create a QName-reference helper component. We will substitute this
7821 	* component for the attribute uses of the referenced attribute group
7822 	* definition.
7823 	*/
7824 	ret = xmlSchemaNewQNameRef(pctxt,
7825 	    XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7826 	if (ret == NULL)
7827 	    return(NULL);
7828 	ret->node = node;
7829 	/* Add to pending items, to be able to resolve the reference. */
7830 	WXS_ADD_PENDING(pctxt, ret);
7831     }
7832     return (ret);
7833 }
7834 
7835 /**
7836  * xmlSchemaParseAttributeGroupDefinition:
7837  * @pctxt:  a schema validation context
7838  * @schema:  the schema being built
7839  * @node:  a subtree containing XML Schema informations
7840  *
7841  * parse a XML schema Attribute Group declaration
7842  * *WARNING* this interface is highly subject to change
7843  *
7844  * Returns the attribute group definition or NULL in case of error.
7845  */
7846 static xmlSchemaAttributeGroupPtr
xmlSchemaParseAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node)7847 xmlSchemaParseAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
7848 				       xmlSchemaPtr schema,
7849 				       xmlNodePtr node)
7850 {
7851     const xmlChar *name;
7852     xmlSchemaAttributeGroupPtr ret;
7853     xmlNodePtr child = NULL;
7854     xmlAttrPtr attr;
7855     int hasRefs = 0;
7856 
7857     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7858         return (NULL);
7859 
7860     attr = xmlSchemaGetPropNode(node, "name");
7861     if (attr == NULL) {
7862 	xmlSchemaPMissingAttrErr(pctxt,
7863 	    XML_SCHEMAP_S4S_ATTR_MISSING,
7864 	    NULL, node, "name", NULL);
7865 	return (NULL);
7866     }
7867     /*
7868     * The name is crucial, exit if invalid.
7869     */
7870     if (xmlSchemaPValAttrNode(pctxt,
7871 	NULL, attr,
7872 	xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7873 	return (NULL);
7874     }
7875     ret = xmlSchemaAddAttributeGroupDefinition(pctxt, schema,
7876 	name, pctxt->targetNamespace, node);
7877     if (ret == NULL)
7878 	return (NULL);
7879     /*
7880     * Check for illegal attributes.
7881     */
7882     attr = node->properties;
7883     while (attr != NULL) {
7884 	if (attr->ns == NULL) {
7885 	    if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7886 		(!xmlStrEqual(attr->name, BAD_CAST "id")))
7887 	    {
7888 		xmlSchemaPIllegalAttrErr(pctxt,
7889 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7890 	    }
7891 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7892 	    xmlSchemaPIllegalAttrErr(pctxt,
7893 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7894 	}
7895 	attr = attr->next;
7896     }
7897     /* Attribute ID */
7898     xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7899     /*
7900     * And now for the children...
7901     */
7902     child = node->children;
7903     if (IS_SCHEMA(child, "annotation")) {
7904         ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7905         child = child->next;
7906     }
7907     /*
7908     * Parse contained attribute decls/refs.
7909     */
7910     if (xmlSchemaParseLocalAttributes(pctxt, schema, &child,
7911 	(xmlSchemaItemListPtr *) &(ret->attrUses),
7912 	XML_SCHEMA_TYPE_ATTRIBUTEGROUP, &hasRefs) == -1)
7913 	return(NULL);
7914     if (hasRefs)
7915 	ret->flags |= XML_SCHEMAS_ATTRGROUP_HAS_REFS;
7916     /*
7917     * Parse the attribute wildcard.
7918     */
7919     if (IS_SCHEMA(child, "anyAttribute")) {
7920 	ret->attributeWildcard = xmlSchemaParseAnyAttribute(pctxt,
7921 	    schema, child);
7922 	child = child->next;
7923     }
7924     if (child != NULL) {
7925 	xmlSchemaPContentErr(pctxt,
7926 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7927 	    NULL, node, child, NULL,
7928 	    "(annotation?, ((attribute | attributeGroup)*, anyAttribute?))");
7929     }
7930     return (ret);
7931 }
7932 
7933 /**
7934  * xmlSchemaPValAttrFormDefault:
7935  * @value:  the value
7936  * @flags: the flags to be modified
7937  * @flagQualified: the specific flag for "qualified"
7938  *
7939  * Returns 0 if the value is valid, 1 otherwise.
7940  */
7941 static int
xmlSchemaPValAttrFormDefault(const xmlChar * value,int * flags,int flagQualified)7942 xmlSchemaPValAttrFormDefault(const xmlChar *value,
7943 			     int *flags,
7944 			     int flagQualified)
7945 {
7946     if (xmlStrEqual(value, BAD_CAST "qualified")) {
7947 	if  ((*flags & flagQualified) == 0)
7948 	    *flags |= flagQualified;
7949     } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
7950 	return (1);
7951 
7952     return (0);
7953 }
7954 
7955 /**
7956  * xmlSchemaPValAttrBlockFinal:
7957  * @value:  the value
7958  * @flags: the flags to be modified
7959  * @flagAll: the specific flag for "#all"
7960  * @flagExtension: the specific flag for "extension"
7961  * @flagRestriction: the specific flag for "restriction"
7962  * @flagSubstitution: the specific flag for "substitution"
7963  * @flagList: the specific flag for "list"
7964  * @flagUnion: the specific flag for "union"
7965  *
7966  * Validates the value of the attribute "final" and "block". The value
7967  * is converted into the specified flag values and returned in @flags.
7968  *
7969  * Returns 0 if the value is valid, 1 otherwise.
7970  */
7971 
7972 static int
xmlSchemaPValAttrBlockFinal(const xmlChar * value,int * flags,int flagAll,int flagExtension,int flagRestriction,int flagSubstitution,int flagList,int flagUnion)7973 xmlSchemaPValAttrBlockFinal(const xmlChar *value,
7974 			    int *flags,
7975 			    int flagAll,
7976 			    int flagExtension,
7977 			    int flagRestriction,
7978 			    int flagSubstitution,
7979 			    int flagList,
7980 			    int flagUnion)
7981 {
7982     int ret = 0;
7983 
7984     /*
7985     * TODO: This does not check for dublicate entries.
7986     */
7987     if ((flags == NULL) || (value == NULL))
7988 	return (-1);
7989     if (value[0] == 0)
7990 	return (0);
7991     if (xmlStrEqual(value, BAD_CAST "#all")) {
7992 	if (flagAll != -1)
7993 	    *flags |= flagAll;
7994 	else {
7995 	    if (flagExtension != -1)
7996 		*flags |= flagExtension;
7997 	    if (flagRestriction != -1)
7998 		*flags |= flagRestriction;
7999 	    if (flagSubstitution != -1)
8000 		*flags |= flagSubstitution;
8001 	    if (flagList != -1)
8002 		*flags |= flagList;
8003 	    if (flagUnion != -1)
8004 		*flags |= flagUnion;
8005 	}
8006     } else {
8007 	const xmlChar *end, *cur = value;
8008 	xmlChar *item;
8009 
8010 	do {
8011 	    while (IS_BLANK_CH(*cur))
8012 		cur++;
8013 	    end = cur;
8014 	    while ((*end != 0) && (!(IS_BLANK_CH(*end))))
8015 		end++;
8016 	    if (end == cur)
8017 		break;
8018 	    item = xmlStrndup(cur, end - cur);
8019 	    if (xmlStrEqual(item, BAD_CAST "extension")) {
8020 		if (flagExtension != -1) {
8021 		    if ((*flags & flagExtension) == 0)
8022 			*flags |= flagExtension;
8023 		} else
8024 		    ret = 1;
8025 	    } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
8026 		if (flagRestriction != -1) {
8027 		    if ((*flags & flagRestriction) == 0)
8028 			*flags |= flagRestriction;
8029 		} else
8030 		    ret = 1;
8031 	    } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
8032 		if (flagSubstitution != -1) {
8033 		    if ((*flags & flagSubstitution) == 0)
8034 			*flags |= flagSubstitution;
8035 		} else
8036 		    ret = 1;
8037 	    } else if (xmlStrEqual(item, BAD_CAST "list")) {
8038 		if (flagList != -1) {
8039 		    if ((*flags & flagList) == 0)
8040 			*flags |= flagList;
8041 		} else
8042 		    ret = 1;
8043 	    } else if (xmlStrEqual(item, BAD_CAST "union")) {
8044 		if (flagUnion != -1) {
8045 		    if ((*flags & flagUnion) == 0)
8046 			*flags |= flagUnion;
8047 		} else
8048 		    ret = 1;
8049 	    } else
8050 		ret = 1;
8051 	    if (item != NULL)
8052 		xmlFree(item);
8053 	    cur = end;
8054 	} while ((ret == 0) && (*cur != 0));
8055     }
8056 
8057     return (ret);
8058 }
8059 
8060 static int
xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,xmlSchemaIDCPtr idc,xmlSchemaIDCSelectPtr selector,xmlAttrPtr attr,int isField)8061 xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
8062 			     xmlSchemaIDCPtr idc,
8063 			     xmlSchemaIDCSelectPtr selector,
8064 			     xmlAttrPtr attr,
8065 			     int isField)
8066 {
8067     xmlNodePtr node;
8068 
8069     /*
8070     * c-selector-xpath:
8071     * Schema Component Constraint: Selector Value OK
8072     *
8073     * TODO: 1 The {selector} must be a valid XPath expression, as defined
8074     * in [XPath].
8075     */
8076     if (selector == NULL) {
8077 	xmlSchemaPErr(ctxt, idc->node,
8078 	    XML_SCHEMAP_INTERNAL,
8079 	    "Internal error: xmlSchemaCheckCSelectorXPath, "
8080 	    "the selector is not specified.\n", NULL, NULL);
8081 	return (-1);
8082     }
8083     if (attr == NULL)
8084 	node = idc->node;
8085     else
8086 	node = (xmlNodePtr) attr;
8087     if (selector->xpath == NULL) {
8088 	xmlSchemaPCustomErr(ctxt,
8089 	    /* TODO: Adjust error code. */
8090 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8091 	    NULL, node,
8092 	    "The XPath expression of the selector is not valid", NULL);
8093 	return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
8094     } else {
8095 	const xmlChar **nsArray = NULL;
8096 	xmlNsPtr *nsList = NULL;
8097 	/*
8098 	* Compile the XPath expression.
8099 	*/
8100 	/*
8101 	* TODO: We need the array of in-scope namespaces for compilation.
8102 	* TODO: Call xmlPatterncompile with different options for selector/
8103 	* field.
8104 	*/
8105 	if (attr == NULL)
8106 	    nsList = NULL;
8107 	else
8108 	    nsList = xmlGetNsList(attr->doc, attr->parent);
8109 	/*
8110 	* Build an array of prefixes and namespaces.
8111 	*/
8112 	if (nsList != NULL) {
8113 	    int i, count = 0;
8114 
8115 	    for (i = 0; nsList[i] != NULL; i++)
8116 		count++;
8117 
8118 	    nsArray = (const xmlChar **) xmlMalloc(
8119 		(count * 2 + 1) * sizeof(const xmlChar *));
8120 	    if (nsArray == NULL) {
8121 		xmlSchemaPErrMemory(ctxt, "allocating a namespace array",
8122 		    NULL);
8123 		xmlFree(nsList);
8124 		return (-1);
8125 	    }
8126 	    for (i = 0; i < count; i++) {
8127 		nsArray[2 * i] = nsList[i]->href;
8128 		nsArray[2 * i + 1] = nsList[i]->prefix;
8129 	    }
8130 	    nsArray[count * 2] = NULL;
8131 	    xmlFree(nsList);
8132 	}
8133 	/*
8134 	* TODO: Differentiate between "selector" and "field".
8135 	*/
8136 	if (isField)
8137 	    selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
8138 		NULL, XML_PATTERN_XSFIELD, nsArray);
8139 	else
8140 	    selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
8141 		NULL, XML_PATTERN_XSSEL, nsArray);
8142 	if (nsArray != NULL)
8143 	    xmlFree((xmlChar **) nsArray);
8144 
8145 	if (selector->xpathComp == NULL) {
8146 	    xmlSchemaPCustomErr(ctxt,
8147 		/* TODO: Adjust error code? */
8148 		XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8149 		NULL, node,
8150 		"The XPath expression '%s' could not be "
8151 		"compiled", selector->xpath);
8152 	    return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
8153 	}
8154     }
8155     return (0);
8156 }
8157 
8158 #define ADD_ANNOTATION(annot)   \
8159     xmlSchemaAnnotPtr cur = item->annot; \
8160     if (item->annot == NULL) {  \
8161 	item->annot = annot;    \
8162 	return (annot);         \
8163     }                           \
8164     cur = item->annot;          \
8165     if (cur->next != NULL) {    \
8166 	cur = cur->next;	\
8167     }                           \
8168     cur->next = annot;
8169 
8170 /**
8171  * xmlSchemaAssignAnnotation:
8172  * @item: the schema component
8173  * @annot: the annotation
8174  *
8175  * Adds the annotation to the given schema component.
8176  *
8177  * Returns the given annotaion.
8178  */
8179 static xmlSchemaAnnotPtr
xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem,xmlSchemaAnnotPtr annot)8180 xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem,
8181 		       xmlSchemaAnnotPtr annot)
8182 {
8183     if ((annItem == NULL) || (annot == NULL))
8184 	return (NULL);
8185     switch (annItem->type) {
8186 	case XML_SCHEMA_TYPE_ELEMENT: {
8187 		xmlSchemaElementPtr item = (xmlSchemaElementPtr) annItem;
8188 		ADD_ANNOTATION(annot)
8189 	    }
8190 	    break;
8191 	case XML_SCHEMA_TYPE_ATTRIBUTE: {
8192 		xmlSchemaAttributePtr item = (xmlSchemaAttributePtr) annItem;
8193 		ADD_ANNOTATION(annot)
8194 	    }
8195 	    break;
8196 	case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
8197 	case XML_SCHEMA_TYPE_ANY: {
8198 		xmlSchemaWildcardPtr item = (xmlSchemaWildcardPtr) annItem;
8199 		ADD_ANNOTATION(annot)
8200 	    }
8201 	    break;
8202 	case XML_SCHEMA_TYPE_PARTICLE:
8203 	case XML_SCHEMA_TYPE_IDC_KEY:
8204 	case XML_SCHEMA_TYPE_IDC_KEYREF:
8205 	case XML_SCHEMA_TYPE_IDC_UNIQUE: {
8206 		xmlSchemaAnnotItemPtr item = (xmlSchemaAnnotItemPtr) annItem;
8207 		ADD_ANNOTATION(annot)
8208 	    }
8209 	    break;
8210 	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: {
8211 		xmlSchemaAttributeGroupPtr item =
8212 		    (xmlSchemaAttributeGroupPtr) annItem;
8213 		ADD_ANNOTATION(annot)
8214 	    }
8215 	    break;
8216 	case XML_SCHEMA_TYPE_NOTATION: {
8217 		xmlSchemaNotationPtr item = (xmlSchemaNotationPtr) annItem;
8218 		ADD_ANNOTATION(annot)
8219 	    }
8220 	    break;
8221 	case XML_SCHEMA_FACET_MININCLUSIVE:
8222 	case XML_SCHEMA_FACET_MINEXCLUSIVE:
8223 	case XML_SCHEMA_FACET_MAXINCLUSIVE:
8224 	case XML_SCHEMA_FACET_MAXEXCLUSIVE:
8225 	case XML_SCHEMA_FACET_TOTALDIGITS:
8226 	case XML_SCHEMA_FACET_FRACTIONDIGITS:
8227 	case XML_SCHEMA_FACET_PATTERN:
8228 	case XML_SCHEMA_FACET_ENUMERATION:
8229 	case XML_SCHEMA_FACET_WHITESPACE:
8230 	case XML_SCHEMA_FACET_LENGTH:
8231 	case XML_SCHEMA_FACET_MAXLENGTH:
8232 	case XML_SCHEMA_FACET_MINLENGTH: {
8233 		xmlSchemaFacetPtr item = (xmlSchemaFacetPtr) annItem;
8234 		ADD_ANNOTATION(annot)
8235 	    }
8236 	    break;
8237 	case XML_SCHEMA_TYPE_SIMPLE:
8238 	case XML_SCHEMA_TYPE_COMPLEX: {
8239 		xmlSchemaTypePtr item = (xmlSchemaTypePtr) annItem;
8240 		ADD_ANNOTATION(annot)
8241 	    }
8242 	    break;
8243 	case XML_SCHEMA_TYPE_GROUP: {
8244 		xmlSchemaModelGroupDefPtr item = (xmlSchemaModelGroupDefPtr) annItem;
8245 		ADD_ANNOTATION(annot)
8246 	    }
8247 	    break;
8248 	case XML_SCHEMA_TYPE_SEQUENCE:
8249 	case XML_SCHEMA_TYPE_CHOICE:
8250 	case XML_SCHEMA_TYPE_ALL: {
8251 		xmlSchemaModelGroupPtr item = (xmlSchemaModelGroupPtr) annItem;
8252 		ADD_ANNOTATION(annot)
8253 	    }
8254 	    break;
8255 	default:
8256 	     xmlSchemaPCustomErr(NULL,
8257 		XML_SCHEMAP_INTERNAL,
8258 		NULL, NULL,
8259 		"Internal error: xmlSchemaAddAnnotation, "
8260 		"The item is not a annotated schema component", NULL);
8261 	     break;
8262     }
8263     return (annot);
8264 }
8265 
8266 /**
8267  * xmlSchemaParseIDCSelectorAndField:
8268  * @ctxt:  a schema validation context
8269  * @schema:  the schema being built
8270  * @node:  a subtree containing XML Schema informations
8271  *
8272  * Parses a XML Schema identity-contraint definition's
8273  * <selector> and <field> elements.
8274  *
8275  * Returns the parsed identity-constraint definition.
8276  */
8277 static xmlSchemaIDCSelectPtr
xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,xmlSchemaIDCPtr idc,xmlNodePtr node,int isField)8278 xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
8279 			  xmlSchemaIDCPtr idc,
8280 			  xmlNodePtr node,
8281 			  int isField)
8282 {
8283     xmlSchemaIDCSelectPtr item;
8284     xmlNodePtr child = NULL;
8285     xmlAttrPtr attr;
8286 
8287     /*
8288     * Check for illegal attributes.
8289     */
8290     attr = node->properties;
8291     while (attr != NULL) {
8292 	if (attr->ns == NULL) {
8293 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8294 		(!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
8295 		xmlSchemaPIllegalAttrErr(ctxt,
8296 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8297 	    }
8298 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8299 	    xmlSchemaPIllegalAttrErr(ctxt,
8300 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8301 	}
8302 	attr = attr->next;
8303     }
8304     /*
8305     * Create the item.
8306     */
8307     item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
8308     if (item == NULL) {
8309         xmlSchemaPErrMemory(ctxt,
8310 	    "allocating a 'selector' of an identity-constraint definition",
8311 	    NULL);
8312         return (NULL);
8313     }
8314     memset(item, 0, sizeof(xmlSchemaIDCSelect));
8315     /*
8316     * Attribute "xpath" (mandatory).
8317     */
8318     attr = xmlSchemaGetPropNode(node, "xpath");
8319     if (attr == NULL) {
8320 	xmlSchemaPMissingAttrErr(ctxt,
8321 	    XML_SCHEMAP_S4S_ATTR_MISSING,
8322 	    NULL, node,
8323 	    "name", NULL);
8324     } else {
8325 	item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8326 	/*
8327 	* URGENT TODO: "field"s have an other syntax than "selector"s.
8328 	*/
8329 
8330 	if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr,
8331 	    isField) == -1) {
8332 	    xmlSchemaPErr(ctxt,
8333 		(xmlNodePtr) attr,
8334 		XML_SCHEMAP_INTERNAL,
8335 		"Internal error: xmlSchemaParseIDCSelectorAndField, "
8336 		"validating the XPath expression of a IDC selector.\n",
8337 		NULL, NULL);
8338 	}
8339 
8340     }
8341     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8342     /*
8343     * And now for the children...
8344     */
8345     child = node->children;
8346     if (IS_SCHEMA(child, "annotation")) {
8347 	/*
8348 	* Add the annotation to the parent IDC.
8349 	*/
8350 	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) idc,
8351 	    xmlSchemaParseAnnotation(ctxt, child, 1));
8352 	child = child->next;
8353     }
8354     if (child != NULL) {
8355 	xmlSchemaPContentErr(ctxt,
8356 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8357 	    NULL, node, child,
8358 	    NULL, "(annotation?)");
8359     }
8360 
8361     return (item);
8362 }
8363 
8364 /**
8365  * xmlSchemaParseIDC:
8366  * @ctxt:  a schema validation context
8367  * @schema:  the schema being built
8368  * @node:  a subtree containing XML Schema informations
8369  *
8370  * Parses a XML Schema identity-contraint definition.
8371  *
8372  * Returns the parsed identity-constraint definition.
8373  */
8374 static xmlSchemaIDCPtr
xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,xmlSchemaTypeType idcCategory,const xmlChar * targetNamespace)8375 xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
8376 		  xmlSchemaPtr schema,
8377 		  xmlNodePtr node,
8378 		  xmlSchemaTypeType idcCategory,
8379 		  const xmlChar *targetNamespace)
8380 {
8381     xmlSchemaIDCPtr item = NULL;
8382     xmlNodePtr child = NULL;
8383     xmlAttrPtr attr;
8384     const xmlChar *name = NULL;
8385     xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
8386 
8387     /*
8388     * Check for illegal attributes.
8389     */
8390     attr = node->properties;
8391     while (attr != NULL) {
8392 	if (attr->ns == NULL) {
8393 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8394 		(!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8395 		((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
8396 		 (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
8397 		xmlSchemaPIllegalAttrErr(ctxt,
8398 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8399 	    }
8400 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8401 	    xmlSchemaPIllegalAttrErr(ctxt,
8402 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8403 	}
8404 	attr = attr->next;
8405     }
8406     /*
8407     * Attribute "name" (mandatory).
8408     */
8409     attr = xmlSchemaGetPropNode(node, "name");
8410     if (attr == NULL) {
8411 	xmlSchemaPMissingAttrErr(ctxt,
8412 	    XML_SCHEMAP_S4S_ATTR_MISSING,
8413 	    NULL, node,
8414 	    "name", NULL);
8415 	return (NULL);
8416     } else if (xmlSchemaPValAttrNode(ctxt,
8417 	NULL, attr,
8418 	xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
8419 	return (NULL);
8420     }
8421     /* Create the component. */
8422     item = xmlSchemaAddIDC(ctxt, schema, name, targetNamespace,
8423 	idcCategory, node);
8424     if (item == NULL)
8425 	return(NULL);
8426 
8427     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8428     if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
8429 	/*
8430 	* Attribute "refer" (mandatory).
8431 	*/
8432 	attr = xmlSchemaGetPropNode(node, "refer");
8433 	if (attr == NULL) {
8434 	    xmlSchemaPMissingAttrErr(ctxt,
8435 		XML_SCHEMAP_S4S_ATTR_MISSING,
8436 		NULL, node,
8437 		"refer", NULL);
8438 	} else {
8439 	    /*
8440 	    * Create a reference item.
8441 	    */
8442 	    item->ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_IDC_KEY,
8443 		NULL, NULL);
8444 	    if (item->ref == NULL)
8445 		return (NULL);
8446 	    xmlSchemaPValAttrNodeQName(ctxt, schema,
8447 		NULL, attr,
8448 		&(item->ref->targetNamespace),
8449 		&(item->ref->name));
8450 	    xmlSchemaCheckReference(ctxt, schema, node, attr,
8451 		item->ref->targetNamespace);
8452 	}
8453     }
8454     /*
8455     * And now for the children...
8456     */
8457     child = node->children;
8458     if (IS_SCHEMA(child, "annotation")) {
8459 	item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
8460 	child = child->next;
8461     }
8462     if (child == NULL) {
8463 	xmlSchemaPContentErr(ctxt,
8464 		XML_SCHEMAP_S4S_ELEM_MISSING,
8465 		NULL, node, child,
8466 		"A child element is missing",
8467 		"(annotation?, (selector, field+))");
8468     }
8469     /*
8470     * Child element <selector>.
8471     */
8472     if (IS_SCHEMA(child, "selector")) {
8473 	item->selector = xmlSchemaParseIDCSelectorAndField(ctxt,
8474 	    item, child, 0);
8475 	child = child->next;
8476 	/*
8477 	* Child elements <field>.
8478 	*/
8479 	if (IS_SCHEMA(child, "field")) {
8480 	    do {
8481 		field = xmlSchemaParseIDCSelectorAndField(ctxt,
8482 		    item, child, 1);
8483 		if (field != NULL) {
8484 		    field->index = item->nbFields;
8485 		    item->nbFields++;
8486 		    if (lastField != NULL)
8487 			lastField->next = field;
8488 		    else
8489 			item->fields = field;
8490 		    lastField = field;
8491 		}
8492 		child = child->next;
8493 	    } while (IS_SCHEMA(child, "field"));
8494 	} else {
8495 	    xmlSchemaPContentErr(ctxt,
8496 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8497 		NULL, node, child,
8498 		NULL, "(annotation?, (selector, field+))");
8499 	}
8500     }
8501     if (child != NULL) {
8502 	xmlSchemaPContentErr(ctxt,
8503 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8504 	    NULL, node, child,
8505 	    NULL, "(annotation?, (selector, field+))");
8506     }
8507 
8508     return (item);
8509 }
8510 
8511 /**
8512  * xmlSchemaParseElement:
8513  * @ctxt:  a schema validation context
8514  * @schema:  the schema being built
8515  * @node:  a subtree containing XML Schema informations
8516  * @topLevel: indicates if this is global declaration
8517  *
8518  * Parses a XML schema element declaration.
8519  * *WARNING* this interface is highly subject to change
8520  *
8521  * Returns the element declaration or a particle; NULL in case
8522  * of an error or if the particle has minOccurs==maxOccurs==0.
8523  */
8524 static xmlSchemaBasicItemPtr
xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,int * isElemRef,int topLevel)8525 xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
8526                       xmlNodePtr node, int *isElemRef, int topLevel)
8527 {
8528     xmlSchemaElementPtr decl = NULL;
8529     xmlSchemaParticlePtr particle = NULL;
8530     xmlSchemaAnnotPtr annot = NULL;
8531     xmlNodePtr child = NULL;
8532     xmlAttrPtr attr, nameAttr;
8533     int min, max, isRef = 0;
8534     xmlChar *des = NULL;
8535 
8536     /* 3.3.3 Constraints on XML Representations of Element Declarations */
8537     /* TODO: Complete implementation of 3.3.6 */
8538 
8539     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8540         return (NULL);
8541 
8542     if (isElemRef != NULL)
8543 	*isElemRef = 0;
8544     /*
8545     * If we get a "ref" attribute on a local <element> we will assume it's
8546     * a reference - even if there's a "name" attribute; this seems to be more
8547     * robust.
8548     */
8549     nameAttr = xmlSchemaGetPropNode(node, "name");
8550     attr = xmlSchemaGetPropNode(node, "ref");
8551     if ((topLevel) || (attr == NULL)) {
8552 	if (nameAttr == NULL) {
8553 	    xmlSchemaPMissingAttrErr(ctxt,
8554 		XML_SCHEMAP_S4S_ATTR_MISSING,
8555 		NULL, node, "name", NULL);
8556 	    return (NULL);
8557 	}
8558     } else
8559 	isRef = 1;
8560 
8561     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8562     child = node->children;
8563     if (IS_SCHEMA(child, "annotation")) {
8564 	annot = xmlSchemaParseAnnotation(ctxt, child, 1);
8565 	child = child->next;
8566     }
8567     /*
8568     * Skip particle part if a global declaration.
8569     */
8570     if (topLevel)
8571 	goto declaration_part;
8572     /*
8573     * The particle part ==================================================
8574     */
8575     min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
8576     max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(xs:nonNegativeInteger | unbounded)");
8577     xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
8578     particle = xmlSchemaAddParticle(ctxt, node, min, max);
8579     if (particle == NULL)
8580 	goto return_null;
8581 
8582     /* ret->flags |= XML_SCHEMAS_ELEM_REF; */
8583 
8584     if (isRef) {
8585 	const xmlChar *refNs = NULL, *ref = NULL;
8586 	xmlSchemaQNameRefPtr refer = NULL;
8587 	/*
8588 	* The reference part =============================================
8589 	*/
8590 	if (isElemRef != NULL)
8591 	    *isElemRef = 1;
8592 
8593 	xmlSchemaPValAttrNodeQName(ctxt, schema,
8594 	    NULL, attr, &refNs, &ref);
8595 	xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
8596 	/*
8597 	* SPEC (3.3.3 : 2.1) "One of ref or name must be present, but not both"
8598 	*/
8599 	if (nameAttr != NULL) {
8600 	    xmlSchemaPMutualExclAttrErr(ctxt,
8601 		XML_SCHEMAP_SRC_ELEMENT_2_1, NULL, nameAttr, "ref", "name");
8602 	}
8603 	/*
8604 	* Check for illegal attributes.
8605 	*/
8606 	attr = node->properties;
8607 	while (attr != NULL) {
8608 	    if (attr->ns == NULL) {
8609 		if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
8610 		    xmlStrEqual(attr->name, BAD_CAST "name") ||
8611 		    xmlStrEqual(attr->name, BAD_CAST "id") ||
8612 		    xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
8613 		    xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
8614 		{
8615 		    attr = attr->next;
8616 		    continue;
8617 		} else {
8618 		    /* SPEC (3.3.3 : 2.2) */
8619 		    xmlSchemaPCustomAttrErr(ctxt,
8620 			XML_SCHEMAP_SRC_ELEMENT_2_2,
8621 			NULL, NULL, attr,
8622 			"Only the attributes 'minOccurs', 'maxOccurs' and "
8623 			"'id' are allowed in addition to 'ref'");
8624 		    break;
8625 		}
8626 	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8627 		xmlSchemaPIllegalAttrErr(ctxt,
8628 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8629 	    }
8630 	    attr = attr->next;
8631 	}
8632 	/*
8633 	* No children except <annotation> expected.
8634 	*/
8635 	if (child != NULL) {
8636 	    xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8637 		NULL, node, child, NULL, "(annotation?)");
8638 	}
8639 	if ((min == 0) && (max == 0))
8640 	    goto return_null;
8641 	/*
8642 	* Create the reference item and attach it to the particle.
8643 	*/
8644 	refer = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_ELEMENT,
8645 	    ref, refNs);
8646 	if (refer == NULL)
8647 	    goto return_null;
8648 	particle->children = (xmlSchemaTreeItemPtr) refer;
8649 	particle->annot = annot;
8650 	/*
8651 	* Add the particle to pending components, since the reference
8652 	* need to be resolved.
8653 	*/
8654 	WXS_ADD_PENDING(ctxt, particle);
8655 	return ((xmlSchemaBasicItemPtr) particle);
8656     }
8657     /*
8658     * The declaration part ===============================================
8659     */
8660 declaration_part:
8661     {
8662 	const xmlChar *ns = NULL, *fixed, *name, *attrValue;
8663 	xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;
8664 
8665 	if (xmlSchemaPValAttrNode(ctxt, NULL, nameAttr,
8666 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
8667 	    goto return_null;
8668 	/*
8669 	* Evaluate the target namespace.
8670 	*/
8671 	if (topLevel) {
8672 	    ns = ctxt->targetNamespace;
8673 	} else {
8674 	    attr = xmlSchemaGetPropNode(node, "form");
8675 	    if (attr != NULL) {
8676 		attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8677 		if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
8678 		    ns = ctxt->targetNamespace;
8679 		} else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
8680 		    xmlSchemaPSimpleTypeErr(ctxt,
8681 			XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8682 			NULL, (xmlNodePtr) attr,
8683 			NULL, "(qualified | unqualified)",
8684 			attrValue, NULL, NULL, NULL);
8685 		}
8686 	    } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
8687 		ns = ctxt->targetNamespace;
8688 	}
8689 	decl = xmlSchemaAddElement(ctxt, name, ns, node, topLevel);
8690 	if (decl == NULL) {
8691 	    goto return_null;
8692 	}
8693 	/*
8694 	* Check for illegal attributes.
8695 	*/
8696 	attr = node->properties;
8697 	while (attr != NULL) {
8698 	    if (attr->ns == NULL) {
8699 		if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8700 		    (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
8701 		    (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8702 		    (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
8703 		    (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
8704 		    (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
8705 		    (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
8706 		{
8707 		    if (topLevel == 0) {
8708 			if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
8709 			    (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
8710 			    (!xmlStrEqual(attr->name, BAD_CAST "form")))
8711 			{
8712 			    xmlSchemaPIllegalAttrErr(ctxt,
8713 				XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8714 			}
8715 		    } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
8716 			(!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
8717 			(!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
8718 
8719 			xmlSchemaPIllegalAttrErr(ctxt,
8720 			    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8721 		    }
8722 		}
8723 	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8724 
8725 		xmlSchemaPIllegalAttrErr(ctxt,
8726 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8727 	    }
8728 	    attr = attr->next;
8729 	}
8730 	/*
8731 	* Extract/validate attributes.
8732 	*/
8733 	if (topLevel) {
8734 	    /*
8735 	    * Process top attributes of global element declarations here.
8736 	    */
8737 	    decl->flags |= XML_SCHEMAS_ELEM_GLOBAL;
8738 	    decl->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
8739 	    xmlSchemaPValAttrQName(ctxt, schema,
8740 		NULL, node, "substitutionGroup",
8741 		&(decl->substGroupNs), &(decl->substGroup));
8742 	    if (xmlGetBooleanProp(ctxt, node, "abstract", 0))
8743 		decl->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
8744 	    /*
8745 	    * Attribute "final".
8746 	    */
8747 	    attr = xmlSchemaGetPropNode(node, "final");
8748 	    if (attr == NULL) {
8749 		if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
8750 		    decl->flags |= XML_SCHEMAS_ELEM_FINAL_EXTENSION;
8751 		if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8752 		    decl->flags |= XML_SCHEMAS_ELEM_FINAL_RESTRICTION;
8753 	    } else {
8754 		attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8755 		if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
8756 		    -1,
8757 		    XML_SCHEMAS_ELEM_FINAL_EXTENSION,
8758 		    XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
8759 		    xmlSchemaPSimpleTypeErr(ctxt,
8760 			XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8761 			NULL, (xmlNodePtr) attr,
8762 			NULL, "(#all | List of (extension | restriction))",
8763 			attrValue, NULL, NULL, NULL);
8764 		}
8765 	    }
8766 	}
8767 	/*
8768 	* Attribute "block".
8769 	*/
8770 	attr = xmlSchemaGetPropNode(node, "block");
8771 	if (attr == NULL) {
8772 	    /*
8773 	    * Apply default "block" values.
8774 	    */
8775 	    if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
8776 		decl->flags |= XML_SCHEMAS_ELEM_BLOCK_RESTRICTION;
8777 	    if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
8778 		decl->flags |= XML_SCHEMAS_ELEM_BLOCK_EXTENSION;
8779 	    if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
8780 		decl->flags |= XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION;
8781 	} else {
8782 	    attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8783 	    if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
8784 		-1,
8785 		XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
8786 		XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
8787 		XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
8788 		xmlSchemaPSimpleTypeErr(ctxt,
8789 		    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8790 		    NULL, (xmlNodePtr) attr,
8791 		    NULL, "(#all | List of (extension | "
8792 		    "restriction | substitution))", attrValue,
8793 		    NULL, NULL, NULL);
8794 	    }
8795 	}
8796 	if (xmlGetBooleanProp(ctxt, node, "nillable", 0))
8797 	    decl->flags |= XML_SCHEMAS_ELEM_NILLABLE;
8798 
8799 	attr = xmlSchemaGetPropNode(node, "type");
8800 	if (attr != NULL) {
8801 	    xmlSchemaPValAttrNodeQName(ctxt, schema,
8802 		NULL, attr,
8803 		&(decl->namedTypeNs), &(decl->namedType));
8804 	    xmlSchemaCheckReference(ctxt, schema, node,
8805 		attr, decl->namedTypeNs);
8806 	}
8807 	decl->value = xmlSchemaGetProp(ctxt, node, "default");
8808 	attr = xmlSchemaGetPropNode(node, "fixed");
8809 	if (attr != NULL) {
8810 	    fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8811 	    if (decl->value != NULL) {
8812 		/*
8813 		* 3.3.3 : 1
8814 		* default and fixed must not both be present.
8815 		*/
8816 		xmlSchemaPMutualExclAttrErr(ctxt,
8817 		    XML_SCHEMAP_SRC_ELEMENT_1,
8818 		    NULL, attr, "default", "fixed");
8819 	    } else {
8820 		decl->flags |= XML_SCHEMAS_ELEM_FIXED;
8821 		decl->value = fixed;
8822 	    }
8823 	}
8824 	/*
8825 	* And now for the children...
8826 	*/
8827 	if (IS_SCHEMA(child, "complexType")) {
8828 	    /*
8829 	    * 3.3.3 : 3
8830 	    * "type" and either <simpleType> or <complexType> are mutually
8831 	    * exclusive
8832 	    */
8833 	    if (decl->namedType != NULL) {
8834 		xmlSchemaPContentErr(ctxt,
8835 		    XML_SCHEMAP_SRC_ELEMENT_3,
8836 		    NULL, node, child,
8837 		    "The attribute 'type' and the <complexType> child are "
8838 		    "mutually exclusive", NULL);
8839 	    } else
8840 		WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseComplexType(ctxt, schema, child, 0);
8841 	    child = child->next;
8842 	} else if (IS_SCHEMA(child, "simpleType")) {
8843 	    /*
8844 	    * 3.3.3 : 3
8845 	    * "type" and either <simpleType> or <complexType> are
8846 	    * mutually exclusive
8847 	    */
8848 	    if (decl->namedType != NULL) {
8849 		xmlSchemaPContentErr(ctxt,
8850 		    XML_SCHEMAP_SRC_ELEMENT_3,
8851 		    NULL, node, child,
8852 		    "The attribute 'type' and the <simpleType> child are "
8853 		    "mutually exclusive", NULL);
8854 	    } else
8855 		WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8856 	    child = child->next;
8857 	}
8858 	while ((IS_SCHEMA(child, "unique")) ||
8859 	    (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
8860 	    if (IS_SCHEMA(child, "unique")) {
8861 		curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8862 		    XML_SCHEMA_TYPE_IDC_UNIQUE, decl->targetNamespace);
8863 	    } else if (IS_SCHEMA(child, "key")) {
8864 		curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8865 		    XML_SCHEMA_TYPE_IDC_KEY, decl->targetNamespace);
8866 	    } else if (IS_SCHEMA(child, "keyref")) {
8867 		curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8868 		    XML_SCHEMA_TYPE_IDC_KEYREF, decl->targetNamespace);
8869 	    }
8870 	    if (lastIDC != NULL)
8871 		lastIDC->next = curIDC;
8872 	    else
8873 		decl->idcs = (void *) curIDC;
8874 	    lastIDC = curIDC;
8875 	    child = child->next;
8876 	}
8877 	if (child != NULL) {
8878 	    xmlSchemaPContentErr(ctxt,
8879 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8880 		NULL, node, child,
8881 		NULL, "(annotation?, ((simpleType | complexType)?, "
8882 		"(unique | key | keyref)*))");
8883 	}
8884 	decl->annot = annot;
8885     }
8886     /*
8887     * NOTE: Element Declaration Representation OK 4. will be checked at a
8888     * different layer.
8889     */
8890     FREE_AND_NULL(des)
8891     if (topLevel)
8892 	return ((xmlSchemaBasicItemPtr) decl);
8893     else {
8894 	particle->children = (xmlSchemaTreeItemPtr) decl;
8895 	return ((xmlSchemaBasicItemPtr) particle);
8896     }
8897 
8898 return_null:
8899     FREE_AND_NULL(des);
8900     if (annot != NULL) {
8901 	if (particle != NULL)
8902 	    particle->annot = NULL;
8903 	if (decl != NULL)
8904 	    decl->annot = NULL;
8905 	xmlSchemaFreeAnnot(annot);
8906     }
8907     return (NULL);
8908 }
8909 
8910 /**
8911  * xmlSchemaParseUnion:
8912  * @ctxt:  a schema validation context
8913  * @schema:  the schema being built
8914  * @node:  a subtree containing XML Schema informations
8915  *
8916  * parse a XML schema Union definition
8917  * *WARNING* this interface is highly subject to change
8918  *
8919  * Returns -1 in case of internal error, 0 in case of success and a positive
8920  * error code otherwise.
8921  */
8922 static int
xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)8923 xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
8924                     xmlNodePtr node)
8925 {
8926     xmlSchemaTypePtr type;
8927     xmlNodePtr child = NULL;
8928     xmlAttrPtr attr;
8929     const xmlChar *cur = NULL;
8930 
8931     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8932         return (-1);
8933     /* Not a component, don't create it. */
8934     type = ctxt->ctxtType;
8935     /*
8936     * Mark the simple type as being of variety "union".
8937     */
8938     type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
8939     /*
8940     * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
8941     * then the `simple ur-type definition`."
8942     */
8943     type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
8944     /*
8945     * Check for illegal attributes.
8946     */
8947     attr = node->properties;
8948     while (attr != NULL) {
8949 	if (attr->ns == NULL) {
8950 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8951 		(!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
8952 		xmlSchemaPIllegalAttrErr(ctxt,
8953 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8954 	    }
8955 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8956 	    xmlSchemaPIllegalAttrErr(ctxt,
8957 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8958 	}
8959 	attr = attr->next;
8960     }
8961     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8962     /*
8963     * Attribute "memberTypes". This is a list of QNames.
8964     * TODO: Check the value to contain anything.
8965     */
8966     attr = xmlSchemaGetPropNode(node, "memberTypes");
8967     if (attr != NULL) {
8968 	const xmlChar *end;
8969 	xmlChar *tmp;
8970 	const xmlChar *localName, *nsName;
8971 	xmlSchemaTypeLinkPtr link, lastLink = NULL;
8972 	xmlSchemaQNameRefPtr ref;
8973 
8974 	cur = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8975 	type->base = cur;
8976 	do {
8977 	    while (IS_BLANK_CH(*cur))
8978 		cur++;
8979 	    end = cur;
8980 	    while ((*end != 0) && (!(IS_BLANK_CH(*end))))
8981 		end++;
8982 	    if (end == cur)
8983 		break;
8984 	    tmp = xmlStrndup(cur, end - cur);
8985 	    if (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
8986 		NULL, attr, BAD_CAST tmp, &nsName, &localName) == 0) {
8987 		/*
8988 		* Create the member type link.
8989 		*/
8990 		link = (xmlSchemaTypeLinkPtr)
8991 		    xmlMalloc(sizeof(xmlSchemaTypeLink));
8992 		if (link == NULL) {
8993 		    xmlSchemaPErrMemory(ctxt, "xmlSchemaParseUnion, "
8994 			"allocating a type link", NULL);
8995 		    return (-1);
8996 		}
8997 		link->type = NULL;
8998 		link->next = NULL;
8999 		if (lastLink == NULL)
9000 		    type->memberTypes = link;
9001 		else
9002 		    lastLink->next = link;
9003 		lastLink = link;
9004 		/*
9005 		* Create a reference item.
9006 		*/
9007 		ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_SIMPLE,
9008 		    localName, nsName);
9009 		if (ref == NULL) {
9010 		    FREE_AND_NULL(tmp)
9011 		    return (-1);
9012 		}
9013 		/*
9014 		* Assign the reference to the link, it will be resolved
9015 		* later during fixup of the union simple type.
9016 		*/
9017 		link->type = (xmlSchemaTypePtr) ref;
9018 	    }
9019 	    FREE_AND_NULL(tmp)
9020 	    cur = end;
9021 	} while (*cur != 0);
9022 
9023     }
9024     /*
9025     * And now for the children...
9026     */
9027     child = node->children;
9028     if (IS_SCHEMA(child, "annotation")) {
9029 	/*
9030 	* Add the annotation to the simple type ancestor.
9031 	*/
9032 	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
9033 	    xmlSchemaParseAnnotation(ctxt, child, 1));
9034         child = child->next;
9035     }
9036     if (IS_SCHEMA(child, "simpleType")) {
9037 	xmlSchemaTypePtr subtype, last = NULL;
9038 
9039 	/*
9040 	* Anchor the member types in the "subtypes" field of the
9041 	* simple type.
9042 	*/
9043 	while (IS_SCHEMA(child, "simpleType")) {
9044 	    subtype = (xmlSchemaTypePtr)
9045 		xmlSchemaParseSimpleType(ctxt, schema, child, 0);
9046 	    if (subtype != NULL) {
9047 		if (last == NULL) {
9048 		    type->subtypes = subtype;
9049 		    last = subtype;
9050 		} else {
9051 		    last->next = subtype;
9052 		    last = subtype;
9053 		}
9054 		last->next = NULL;
9055 	    }
9056 	    child = child->next;
9057 	}
9058     }
9059     if (child != NULL) {
9060 	xmlSchemaPContentErr(ctxt,
9061 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9062 	    NULL, node, child, NULL, "(annotation?, simpleType*)");
9063     }
9064     if ((attr == NULL) && (type->subtypes == NULL)) {
9065 	 /*
9066 	* src-union-memberTypes-or-simpleTypes
9067 	* Either the memberTypes [attribute] of the <union> element must
9068 	* be non-empty or there must be at least one simpleType [child].
9069 	*/
9070 	xmlSchemaPCustomErr(ctxt,
9071 	    XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
9072 	    NULL, node,
9073 	    "Either the attribute 'memberTypes' or "
9074 	    "at least one <simpleType> child must be present", NULL);
9075     }
9076     return (0);
9077 }
9078 
9079 /**
9080  * xmlSchemaParseList:
9081  * @ctxt:  a schema validation context
9082  * @schema:  the schema being built
9083  * @node:  a subtree containing XML Schema informations
9084  *
9085  * parse a XML schema List definition
9086  * *WARNING* this interface is highly subject to change
9087  *
9088  * Returns -1 in case of error, 0 if the declaration is improper and
9089  *         1 in case of success.
9090  */
9091 static xmlSchemaTypePtr
xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)9092 xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9093                    xmlNodePtr node)
9094 {
9095     xmlSchemaTypePtr type;
9096     xmlNodePtr child = NULL;
9097     xmlAttrPtr attr;
9098 
9099     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9100         return (NULL);
9101     /* Not a component, don't create it. */
9102     type = ctxt->ctxtType;
9103     /*
9104     * Mark the type as being of variety "list".
9105     */
9106     type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
9107     /*
9108     * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
9109     * then the `simple ur-type definition`."
9110     */
9111     type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
9112     /*
9113     * Check for illegal attributes.
9114     */
9115     attr = node->properties;
9116     while (attr != NULL) {
9117 	if (attr->ns == NULL) {
9118 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9119 		(!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
9120 		xmlSchemaPIllegalAttrErr(ctxt,
9121 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9122 	    }
9123 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9124 	    xmlSchemaPIllegalAttrErr(ctxt,
9125 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9126 	}
9127 	attr = attr->next;
9128     }
9129 
9130     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9131 
9132     /*
9133     * Attribute "itemType". NOTE that we will use the "ref" and "refNs"
9134     * fields for holding the reference to the itemType.
9135     *
9136     * REVAMP TODO: Use the "base" and "baseNs" fields, since we will remove
9137     * the "ref" fields.
9138     */
9139     xmlSchemaPValAttrQName(ctxt, schema, NULL,
9140 	node, "itemType", &(type->baseNs), &(type->base));
9141     /*
9142     * And now for the children...
9143     */
9144     child = node->children;
9145     if (IS_SCHEMA(child, "annotation")) {
9146 	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
9147 	    xmlSchemaParseAnnotation(ctxt, child, 1));
9148         child = child->next;
9149     }
9150     if (IS_SCHEMA(child, "simpleType")) {
9151 	/*
9152 	* src-list-itemType-or-simpleType
9153 	* Either the itemType [attribute] or the <simpleType> [child] of
9154 	* the <list> element must be present, but not both.
9155 	*/
9156 	if (type->base != NULL) {
9157 	    xmlSchemaPCustomErr(ctxt,
9158 		XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9159 		NULL, node,
9160 		"The attribute 'itemType' and the <simpleType> child "
9161 		"are mutually exclusive", NULL);
9162 	} else {
9163 	    type->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
9164 	}
9165         child = child->next;
9166     } else if (type->base == NULL) {
9167 	xmlSchemaPCustomErr(ctxt,
9168 	    XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9169 	    NULL, node,
9170 	    "Either the attribute 'itemType' or the <simpleType> child "
9171 	    "must be present", NULL);
9172     }
9173     if (child != NULL) {
9174 	xmlSchemaPContentErr(ctxt,
9175 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9176 	    NULL, node, child, NULL, "(annotation?, simpleType?)");
9177     }
9178     if ((type->base == NULL) &&
9179 	(type->subtypes == NULL) &&
9180 	(xmlSchemaGetPropNode(node, "itemType") == NULL)) {
9181 	xmlSchemaPCustomErr(ctxt,
9182 	    XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9183 	    NULL, node,
9184 	    "Either the attribute 'itemType' or the <simpleType> child "
9185 	    "must be present", NULL);
9186     }
9187     return (NULL);
9188 }
9189 
9190 /**
9191  * xmlSchemaParseSimpleType:
9192  * @ctxt:  a schema validation context
9193  * @schema:  the schema being built
9194  * @node:  a subtree containing XML Schema informations
9195  *
9196  * parse a XML schema Simple Type definition
9197  * *WARNING* this interface is highly subject to change
9198  *
9199  * Returns -1 in case of error, 0 if the declaration is improper and
9200  * 1 in case of success.
9201  */
9202 static xmlSchemaTypePtr
xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,int topLevel)9203 xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9204                          xmlNodePtr node, int topLevel)
9205 {
9206     xmlSchemaTypePtr type, oldCtxtType;
9207     xmlNodePtr child = NULL;
9208     const xmlChar *attrValue = NULL;
9209     xmlAttrPtr attr;
9210     int hasRestriction = 0;
9211 
9212     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9213         return (NULL);
9214 
9215     if (topLevel) {
9216 	attr = xmlSchemaGetPropNode(node, "name");
9217 	if (attr == NULL) {
9218 	    xmlSchemaPMissingAttrErr(ctxt,
9219 		XML_SCHEMAP_S4S_ATTR_MISSING,
9220 		NULL, node,
9221 		"name", NULL);
9222 	    return (NULL);
9223 	} else {
9224 	    if (xmlSchemaPValAttrNode(ctxt,
9225 		NULL, attr,
9226 		xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0)
9227 		return (NULL);
9228 	    /*
9229 	    * Skip built-in types.
9230 	    */
9231 	    if (ctxt->isS4S) {
9232 		xmlSchemaTypePtr biType;
9233 
9234 		if (ctxt->isRedefine) {
9235 		    /*
9236 		    * REDEFINE: Disallow redefinition of built-in-types.
9237 		    * TODO: It seems that the spec does not say anything
9238 		    * about this case.
9239 		    */
9240 		    xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
9241 			NULL, node,
9242 			"Redefinition of built-in simple types is not "
9243 			"supported", NULL);
9244 		    return(NULL);
9245 		}
9246 		biType = xmlSchemaGetPredefinedType(attrValue, xmlSchemaNs);
9247 		if (biType != NULL)
9248 		    return (biType);
9249 	    }
9250 	}
9251     }
9252     /*
9253     * TargetNamespace:
9254     * SPEC "The `actual value` of the targetNamespace [attribute]
9255     * of the <schema> ancestor element information item if present,
9256     * otherwise `absent`.
9257     */
9258     if (topLevel == 0) {
9259 #ifdef ENABLE_NAMED_LOCALS
9260         char buf[40];
9261 #endif
9262 	/*
9263 	* Parse as local simple type definition.
9264 	*/
9265 #ifdef ENABLE_NAMED_LOCALS
9266         snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
9267 	type = xmlSchemaAddType(ctxt, schema,
9268 	    XML_SCHEMA_TYPE_SIMPLE,
9269 	    xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
9270 	    ctxt->targetNamespace, node, 0);
9271 #else
9272 	type = xmlSchemaAddType(ctxt, schema,
9273 	    XML_SCHEMA_TYPE_SIMPLE,
9274 	    NULL, ctxt->targetNamespace, node, 0);
9275 #endif
9276 	if (type == NULL)
9277 	    return (NULL);
9278 	type->type = XML_SCHEMA_TYPE_SIMPLE;
9279 	type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
9280 	/*
9281 	* Check for illegal attributes.
9282 	*/
9283 	attr = node->properties;
9284 	while (attr != NULL) {
9285 	    if (attr->ns == NULL) {
9286 		if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
9287 		    xmlSchemaPIllegalAttrErr(ctxt,
9288 			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9289 		}
9290 	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9291 		    xmlSchemaPIllegalAttrErr(ctxt,
9292 			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9293 	    }
9294 	    attr = attr->next;
9295 	}
9296     } else {
9297 	/*
9298 	* Parse as global simple type definition.
9299 	*
9300 	* Note that attrValue is the value of the attribute "name" here.
9301 	*/
9302 	type = xmlSchemaAddType(ctxt, schema, XML_SCHEMA_TYPE_SIMPLE,
9303 	    attrValue, ctxt->targetNamespace, node, 1);
9304 	if (type == NULL)
9305 	    return (NULL);
9306 	type->type = XML_SCHEMA_TYPE_SIMPLE;
9307 	type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
9308 	type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
9309 	/*
9310 	* Check for illegal attributes.
9311 	*/
9312 	attr = node->properties;
9313 	while (attr != NULL) {
9314 	    if (attr->ns == NULL) {
9315 		if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9316 		    (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
9317 		    (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
9318 		    xmlSchemaPIllegalAttrErr(ctxt,
9319 			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9320 		}
9321 	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9322 		xmlSchemaPIllegalAttrErr(ctxt,
9323 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9324 	    }
9325 	    attr = attr->next;
9326 	}
9327 	/*
9328 	* Attribute "final".
9329 	*/
9330 	attr = xmlSchemaGetPropNode(node, "final");
9331 	if (attr == NULL) {
9332 	    if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9333 		type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
9334 	    if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9335 		type->flags |= XML_SCHEMAS_TYPE_FINAL_LIST;
9336 	    if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9337 		type->flags |= XML_SCHEMAS_TYPE_FINAL_UNION;
9338 	} else {
9339 	    attrValue = xmlSchemaGetProp(ctxt, node, "final");
9340 	    if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
9341 		-1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
9342 		XML_SCHEMAS_TYPE_FINAL_LIST,
9343 		XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
9344 
9345 		xmlSchemaPSimpleTypeErr(ctxt,
9346 		    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9347 		    WXS_BASIC_CAST type, (xmlNodePtr) attr,
9348 		    NULL, "(#all | List of (list | union | restriction)",
9349 		    attrValue, NULL, NULL, NULL);
9350 	    }
9351 	}
9352     }
9353     type->targetNamespace = ctxt->targetNamespace;
9354     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9355     /*
9356     * And now for the children...
9357     */
9358     oldCtxtType = ctxt->ctxtType;
9359 
9360     ctxt->ctxtType = type;
9361 
9362     child = node->children;
9363     if (IS_SCHEMA(child, "annotation")) {
9364         type->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9365         child = child->next;
9366     }
9367     if (child == NULL) {
9368 	xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_MISSING,
9369 	    NULL, node, child, NULL,
9370 	    "(annotation?, (restriction | list | union))");
9371     } else if (IS_SCHEMA(child, "restriction")) {
9372         xmlSchemaParseRestriction(ctxt, schema, child,
9373 	    XML_SCHEMA_TYPE_SIMPLE);
9374 	hasRestriction = 1;
9375         child = child->next;
9376     } else if (IS_SCHEMA(child, "list")) {
9377         xmlSchemaParseList(ctxt, schema, child);
9378         child = child->next;
9379     } else if (IS_SCHEMA(child, "union")) {
9380         xmlSchemaParseUnion(ctxt, schema, child);
9381         child = child->next;
9382     }
9383     if (child != NULL) {
9384 	xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9385 	    NULL, node, child, NULL,
9386 	    "(annotation?, (restriction | list | union))");
9387     }
9388     /*
9389     * REDEFINE: SPEC src-redefine (5)
9390     * "Within the [children], each <simpleType> must have a
9391     * <restriction> among its [children] ... the `actual value` of whose
9392     * base [attribute] must be the same as the `actual value` of its own
9393     * name attribute plus target namespace;"
9394     */
9395     if (topLevel && ctxt->isRedefine && (! hasRestriction)) {
9396 	xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
9397 	    NULL, node, "This is a redefinition, thus the "
9398 	    "<simpleType> must have a <restriction> child", NULL);
9399     }
9400 
9401     ctxt->ctxtType = oldCtxtType;
9402     return (type);
9403 }
9404 
9405 /**
9406  * xmlSchemaParseModelGroupDefRef:
9407  * @ctxt:  the parser context
9408  * @schema: the schema being built
9409  * @node:  the node
9410  *
9411  * Parses a reference to a model group definition.
9412  *
9413  * We will return a particle component with a qname-component or
9414  * NULL in case of an error.
9415  */
9416 static xmlSchemaTreeItemPtr
xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)9417 xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt,
9418 			       xmlSchemaPtr schema,
9419 			       xmlNodePtr node)
9420 {
9421     xmlSchemaParticlePtr item;
9422     xmlNodePtr child = NULL;
9423     xmlAttrPtr attr;
9424     const xmlChar *ref = NULL, *refNs = NULL;
9425     int min, max;
9426 
9427     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9428         return (NULL);
9429 
9430     attr = xmlSchemaGetPropNode(node, "ref");
9431     if (attr == NULL) {
9432 	xmlSchemaPMissingAttrErr(ctxt,
9433 	    XML_SCHEMAP_S4S_ATTR_MISSING,
9434 	    NULL, node, "ref", NULL);
9435 	return (NULL);
9436     } else if (xmlSchemaPValAttrNodeQName(ctxt, schema, NULL,
9437 	attr, &refNs, &ref) != 0) {
9438 	return (NULL);
9439     }
9440     xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
9441     min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
9442     max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
9443 	"(xs:nonNegativeInteger | unbounded)");
9444     /*
9445     * Check for illegal attributes.
9446     */
9447     attr = node->properties;
9448     while (attr != NULL) {
9449 	if (attr->ns == NULL) {
9450 	    if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
9451 		(!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9452 		(!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
9453 		(!xmlStrEqual(attr->name, BAD_CAST "maxOccurs"))) {
9454 		xmlSchemaPIllegalAttrErr(ctxt,
9455 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9456 	    }
9457 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9458 	    xmlSchemaPIllegalAttrErr(ctxt,
9459 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9460 	}
9461 	attr = attr->next;
9462     }
9463     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9464     item = xmlSchemaAddParticle(ctxt, node, min, max);
9465     if (item == NULL)
9466 	return (NULL);
9467     /*
9468     * Create a qname-reference and set as the term; it will be substituted
9469     * for the model group after the reference has been resolved.
9470     */
9471     item->children = (xmlSchemaTreeItemPtr)
9472 	xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_GROUP, ref, refNs);
9473     xmlSchemaPCheckParticleCorrect_2(ctxt, item, node, min, max);
9474     /*
9475     * And now for the children...
9476     */
9477     child = node->children;
9478     /* TODO: Is annotation even allowed for a model group reference? */
9479     if (IS_SCHEMA(child, "annotation")) {
9480 	/*
9481 	* TODO: What to do exactly with the annotation?
9482 	*/
9483 	item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9484 	child = child->next;
9485     }
9486     if (child != NULL) {
9487 	xmlSchemaPContentErr(ctxt,
9488 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9489 	    NULL, node, child, NULL,
9490 	    "(annotation?)");
9491     }
9492     /*
9493     * Corresponds to no component at all if minOccurs==maxOccurs==0.
9494     */
9495     if ((min == 0) && (max == 0))
9496 	return (NULL);
9497 
9498     return ((xmlSchemaTreeItemPtr) item);
9499 }
9500 
9501 /**
9502  * xmlSchemaParseModelGroupDefinition:
9503  * @ctxt:  a schema validation context
9504  * @schema:  the schema being built
9505  * @node:  a subtree containing XML Schema informations
9506  *
9507  * Parses a XML schema model group definition.
9508  *
9509  * Note that the contraint src-redefine (6.2) can't be applied until
9510  * references have been resolved. So we will do this at the
9511  * component fixup level.
9512  *
9513  * *WARNING* this interface is highly subject to change
9514  *
9515  * Returns -1 in case of error, 0 if the declaration is improper and
9516  *         1 in case of success.
9517  */
9518 static xmlSchemaModelGroupDefPtr
xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)9519 xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
9520 				   xmlSchemaPtr schema,
9521 				   xmlNodePtr node)
9522 {
9523     xmlSchemaModelGroupDefPtr item;
9524     xmlNodePtr child = NULL;
9525     xmlAttrPtr attr;
9526     const xmlChar *name;
9527 
9528     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9529         return (NULL);
9530 
9531     attr = xmlSchemaGetPropNode(node, "name");
9532     if (attr == NULL) {
9533 	xmlSchemaPMissingAttrErr(ctxt,
9534 	    XML_SCHEMAP_S4S_ATTR_MISSING,
9535 	    NULL, node,
9536 	    "name", NULL);
9537 	return (NULL);
9538     } else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
9539 	xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
9540 	return (NULL);
9541     }
9542     item = xmlSchemaAddModelGroupDefinition(ctxt, schema, name,
9543 	ctxt->targetNamespace, node);
9544     if (item == NULL)
9545 	return (NULL);
9546     /*
9547     * Check for illegal attributes.
9548     */
9549     attr = node->properties;
9550     while (attr != NULL) {
9551 	if (attr->ns == NULL) {
9552 	    if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
9553 		(!xmlStrEqual(attr->name, BAD_CAST "id"))) {
9554 		xmlSchemaPIllegalAttrErr(ctxt,
9555 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9556 	    }
9557 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9558 	    xmlSchemaPIllegalAttrErr(ctxt,
9559 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9560 	}
9561 	attr = attr->next;
9562     }
9563     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9564     /*
9565     * And now for the children...
9566     */
9567     child = node->children;
9568     if (IS_SCHEMA(child, "annotation")) {
9569 	item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9570 	child = child->next;
9571     }
9572     if (IS_SCHEMA(child, "all")) {
9573 	item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9574 	    XML_SCHEMA_TYPE_ALL, 0);
9575 	child = child->next;
9576     } else if (IS_SCHEMA(child, "choice")) {
9577 	item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9578 	    XML_SCHEMA_TYPE_CHOICE, 0);
9579 	child = child->next;
9580     } else if (IS_SCHEMA(child, "sequence")) {
9581 	item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9582 	    XML_SCHEMA_TYPE_SEQUENCE, 0);
9583 	child = child->next;
9584     }
9585 
9586 
9587 
9588     if (child != NULL) {
9589 	xmlSchemaPContentErr(ctxt,
9590 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9591 	    NULL, node, child, NULL,
9592 	    "(annotation?, (all | choice | sequence)?)");
9593     }
9594     return (item);
9595 }
9596 
9597 /**
9598  * xmlSchemaCleanupDoc:
9599  * @ctxt:  a schema validation context
9600  * @node:  the root of the document.
9601  *
9602  * removes unwanted nodes in a schemas document tree
9603  */
9604 static void
xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr root)9605 xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
9606 {
9607     xmlNodePtr delete, cur;
9608 
9609     if ((ctxt == NULL) || (root == NULL)) return;
9610 
9611     /*
9612      * Remove all the blank text nodes
9613      */
9614     delete = NULL;
9615     cur = root;
9616     while (cur != NULL) {
9617         if (delete != NULL) {
9618             xmlUnlinkNode(delete);
9619             xmlFreeNode(delete);
9620             delete = NULL;
9621         }
9622         if (cur->type == XML_TEXT_NODE) {
9623             if (IS_BLANK_NODE(cur)) {
9624                 if (xmlNodeGetSpacePreserve(cur) != 1) {
9625                     delete = cur;
9626                 }
9627             }
9628         } else if ((cur->type != XML_ELEMENT_NODE) &&
9629                    (cur->type != XML_CDATA_SECTION_NODE)) {
9630             delete = cur;
9631             goto skip_children;
9632         }
9633 
9634         /*
9635          * Skip to next node
9636          */
9637         if (cur->children != NULL) {
9638             if ((cur->children->type != XML_ENTITY_DECL) &&
9639                 (cur->children->type != XML_ENTITY_REF_NODE) &&
9640                 (cur->children->type != XML_ENTITY_NODE)) {
9641                 cur = cur->children;
9642                 continue;
9643             }
9644         }
9645       skip_children:
9646         if (cur->next != NULL) {
9647             cur = cur->next;
9648             continue;
9649         }
9650 
9651         do {
9652             cur = cur->parent;
9653             if (cur == NULL)
9654                 break;
9655             if (cur == root) {
9656                 cur = NULL;
9657                 break;
9658             }
9659             if (cur->next != NULL) {
9660                 cur = cur->next;
9661                 break;
9662             }
9663         } while (cur != NULL);
9664     }
9665     if (delete != NULL) {
9666         xmlUnlinkNode(delete);
9667         xmlFreeNode(delete);
9668         delete = NULL;
9669     }
9670 }
9671 
9672 
9673 static void
xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)9674 xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
9675 {
9676     if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
9677 	schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
9678 
9679     if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
9680 	schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
9681 
9682     if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
9683 	schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
9684     if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9685 	schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
9686     if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9687 	schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
9688     if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9689 	schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
9690 
9691     if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
9692 	schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
9693     if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
9694 	schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
9695     if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
9696 	schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
9697 }
9698 
9699 static int
xmlSchemaParseSchemaElement(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)9700 xmlSchemaParseSchemaElement(xmlSchemaParserCtxtPtr ctxt,
9701 			     xmlSchemaPtr schema,
9702 			     xmlNodePtr node)
9703 {
9704     xmlAttrPtr attr;
9705     const xmlChar *val;
9706     int res = 0, oldErrs = ctxt->nberrors;
9707 
9708     /*
9709     * Those flags should be moved to the parser context flags,
9710     * since they are not visible at the component level. I.e.
9711     * they are used if processing schema *documents* only.
9712     */
9713     res = xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9714     HFAILURE;
9715 
9716     /*
9717     * Since the version is of type xs:token, we won't bother to
9718     * check it.
9719     */
9720     /* REMOVED:
9721     attr = xmlSchemaGetPropNode(node, "version");
9722     if (attr != NULL) {
9723 	res = xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
9724 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &val);
9725 	HFAILURE;
9726     }
9727     */
9728     attr = xmlSchemaGetPropNode(node, "targetNamespace");
9729     if (attr != NULL) {
9730 	res = xmlSchemaPValAttrNode(ctxt, NULL, attr,
9731 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
9732 	HFAILURE;
9733 	if (res != 0) {
9734 	    ctxt->stop = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
9735 	    goto exit;
9736 	}
9737     }
9738     attr = xmlSchemaGetPropNode(node, "elementFormDefault");
9739     if (attr != NULL) {
9740 	val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9741 	res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9742 	    XML_SCHEMAS_QUALIF_ELEM);
9743 	HFAILURE;
9744 	if (res != 0) {
9745 	    xmlSchemaPSimpleTypeErr(ctxt,
9746 		XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
9747 		NULL, (xmlNodePtr) attr, NULL,
9748 		"(qualified | unqualified)", val, NULL, NULL, NULL);
9749 	}
9750     }
9751     attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
9752     if (attr != NULL) {
9753 	val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9754 	res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9755 	    XML_SCHEMAS_QUALIF_ATTR);
9756 	HFAILURE;
9757 	if (res != 0) {
9758 	    xmlSchemaPSimpleTypeErr(ctxt,
9759 		XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
9760 		NULL, (xmlNodePtr) attr, NULL,
9761 		"(qualified | unqualified)", val, NULL, NULL, NULL);
9762 	}
9763     }
9764     attr = xmlSchemaGetPropNode(node, "finalDefault");
9765     if (attr != NULL) {
9766 	val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9767 	res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
9768 	    XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
9769 	    XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
9770 	    -1,
9771 	    XML_SCHEMAS_FINAL_DEFAULT_LIST,
9772 	    XML_SCHEMAS_FINAL_DEFAULT_UNION);
9773 	HFAILURE;
9774 	if (res != 0) {
9775 	    xmlSchemaPSimpleTypeErr(ctxt,
9776 		XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9777 		NULL, (xmlNodePtr) attr, NULL,
9778 		"(#all | List of (extension | restriction | list | union))",
9779 		val, NULL, NULL, NULL);
9780 	}
9781     }
9782     attr = xmlSchemaGetPropNode(node, "blockDefault");
9783     if (attr != NULL) {
9784 	val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9785 	res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
9786 	    XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
9787 	    XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
9788 	    XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1);
9789 	HFAILURE;
9790 	if (res != 0) {
9791 	    xmlSchemaPSimpleTypeErr(ctxt,
9792 		XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9793 		NULL, (xmlNodePtr) attr, NULL,
9794 		"(#all | List of (extension | restriction | substitution))",
9795 		val, NULL, NULL, NULL);
9796 	}
9797     }
9798 
9799 exit:
9800     if (oldErrs != ctxt->nberrors)
9801 	res = ctxt->err;
9802     return(res);
9803 exit_failure:
9804     return(-1);
9805 }
9806 
9807 /**
9808  * xmlSchemaParseSchemaTopLevel:
9809  * @ctxt:  a schema validation context
9810  * @schema:  the schemas
9811  * @nodes:  the list of top level nodes
9812  *
9813  * Returns the internal XML Schema structure built from the resource or
9814  *         NULL in case of error
9815  */
9816 static int
xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr nodes)9817 xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
9818                              xmlSchemaPtr schema, xmlNodePtr nodes)
9819 {
9820     xmlNodePtr child;
9821     xmlSchemaAnnotPtr annot;
9822     int res = 0, oldErrs, tmpOldErrs;
9823 
9824     if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
9825         return(-1);
9826 
9827     oldErrs = ctxt->nberrors;
9828     child = nodes;
9829     while ((IS_SCHEMA(child, "include")) ||
9830 	   (IS_SCHEMA(child, "import")) ||
9831 	   (IS_SCHEMA(child, "redefine")) ||
9832 	   (IS_SCHEMA(child, "annotation"))) {
9833 	if (IS_SCHEMA(child, "annotation")) {
9834 	    annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9835 	    if (schema->annot == NULL)
9836 		schema->annot = annot;
9837 	    else
9838 		xmlSchemaFreeAnnot(annot);
9839 	} else if (IS_SCHEMA(child, "import")) {
9840 	    tmpOldErrs = ctxt->nberrors;
9841 	    res = xmlSchemaParseImport(ctxt, schema, child);
9842 	    HFAILURE;
9843 	    HSTOP(ctxt);
9844 	    if (tmpOldErrs != ctxt->nberrors)
9845 		goto exit;
9846 	} else if (IS_SCHEMA(child, "include")) {
9847 	    tmpOldErrs = ctxt->nberrors;
9848 	    res = xmlSchemaParseInclude(ctxt, schema, child);
9849 	    HFAILURE;
9850 	    HSTOP(ctxt);
9851 	    if (tmpOldErrs != ctxt->nberrors)
9852 		goto exit;
9853 	} else if (IS_SCHEMA(child, "redefine")) {
9854 	    tmpOldErrs = ctxt->nberrors;
9855 	    res = xmlSchemaParseRedefine(ctxt, schema, child);
9856 	    HFAILURE;
9857 	    HSTOP(ctxt);
9858 	    if (tmpOldErrs != ctxt->nberrors)
9859 		goto exit;
9860 	}
9861 	child = child->next;
9862     }
9863     /*
9864     * URGENT TODO: Change the functions to return int results.
9865     * We need especially to catch internal errors.
9866     */
9867     while (child != NULL) {
9868 	if (IS_SCHEMA(child, "complexType")) {
9869 	    xmlSchemaParseComplexType(ctxt, schema, child, 1);
9870 	    child = child->next;
9871 	} else if (IS_SCHEMA(child, "simpleType")) {
9872 	    xmlSchemaParseSimpleType(ctxt, schema, child, 1);
9873 	    child = child->next;
9874 	} else if (IS_SCHEMA(child, "element")) {
9875 	    xmlSchemaParseElement(ctxt, schema, child, NULL, 1);
9876 	    child = child->next;
9877 	} else if (IS_SCHEMA(child, "attribute")) {
9878 	    xmlSchemaParseGlobalAttribute(ctxt, schema, child);
9879 	    child = child->next;
9880 	} else if (IS_SCHEMA(child, "attributeGroup")) {
9881 	    xmlSchemaParseAttributeGroupDefinition(ctxt, schema, child);
9882 	    child = child->next;
9883 	} else if (IS_SCHEMA(child, "group")) {
9884 	    xmlSchemaParseModelGroupDefinition(ctxt, schema, child);
9885 	    child = child->next;
9886 	} else if (IS_SCHEMA(child, "notation")) {
9887 	    xmlSchemaParseNotation(ctxt, schema, child);
9888 	    child = child->next;
9889 	} else {
9890 	    xmlSchemaPContentErr(ctxt,
9891 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9892 		NULL, child->parent, child,
9893 		NULL, "((include | import | redefine | annotation)*, "
9894 		"(((simpleType | complexType | group | attributeGroup) "
9895 		"| element | attribute | notation), annotation*)*)");
9896 	    child = child->next;
9897 	}
9898 	while (IS_SCHEMA(child, "annotation")) {
9899 	    /*
9900 	    * TODO: We should add all annotations.
9901 	    */
9902 	    annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9903 	    if (schema->annot == NULL)
9904 		schema->annot = annot;
9905 	    else
9906 		xmlSchemaFreeAnnot(annot);
9907 	    child = child->next;
9908 	}
9909     }
9910 exit:
9911     ctxt->ctxtType = NULL;
9912     if (oldErrs != ctxt->nberrors)
9913 	res = ctxt->err;
9914     return(res);
9915 exit_failure:
9916     return(-1);
9917 }
9918 
9919 static xmlSchemaSchemaRelationPtr
xmlSchemaSchemaRelationCreate(void)9920 xmlSchemaSchemaRelationCreate(void)
9921 {
9922     xmlSchemaSchemaRelationPtr ret;
9923 
9924     ret = (xmlSchemaSchemaRelationPtr)
9925 	xmlMalloc(sizeof(xmlSchemaSchemaRelation));
9926     if (ret == NULL) {
9927 	xmlSchemaPErrMemory(NULL, "allocating schema relation", NULL);
9928 	return(NULL);
9929     }
9930     memset(ret, 0, sizeof(xmlSchemaSchemaRelation));
9931     return(ret);
9932 }
9933 
9934 #if 0
9935 static void
9936 xmlSchemaSchemaRelationFree(xmlSchemaSchemaRelationPtr rel)
9937 {
9938     xmlFree(rel);
9939 }
9940 #endif
9941 
9942 static void
xmlSchemaRedefListFree(xmlSchemaRedefPtr redef)9943 xmlSchemaRedefListFree(xmlSchemaRedefPtr redef)
9944 {
9945     xmlSchemaRedefPtr prev;
9946 
9947     while (redef != NULL) {
9948 	prev = redef;
9949 	redef = redef->next;
9950 	xmlFree(prev);
9951     }
9952 }
9953 
9954 static void
xmlSchemaConstructionCtxtFree(xmlSchemaConstructionCtxtPtr con)9955 xmlSchemaConstructionCtxtFree(xmlSchemaConstructionCtxtPtr con)
9956 {
9957     /*
9958     * After the construction context has been freed, there will be
9959     * no schema graph available any more. Only the schema buckets
9960     * will stay alive, which are put into the "schemasImports" and
9961     * "includes" slots of the xmlSchema.
9962     */
9963     if (con->buckets != NULL)
9964 	xmlSchemaItemListFree(con->buckets);
9965     if (con->pending != NULL)
9966 	xmlSchemaItemListFree(con->pending);
9967     if (con->substGroups != NULL)
9968 	xmlHashFree(con->substGroups, xmlSchemaSubstGroupFreeEntry);
9969     if (con->redefs != NULL)
9970 	xmlSchemaRedefListFree(con->redefs);
9971     if (con->dict != NULL)
9972 	xmlDictFree(con->dict);
9973     xmlFree(con);
9974 }
9975 
9976 static xmlSchemaConstructionCtxtPtr
xmlSchemaConstructionCtxtCreate(xmlDictPtr dict)9977 xmlSchemaConstructionCtxtCreate(xmlDictPtr dict)
9978 {
9979     xmlSchemaConstructionCtxtPtr ret;
9980 
9981     ret = (xmlSchemaConstructionCtxtPtr)
9982 	xmlMalloc(sizeof(xmlSchemaConstructionCtxt));
9983     if (ret == NULL) {
9984         xmlSchemaPErrMemory(NULL,
9985 	    "allocating schema construction context", NULL);
9986         return (NULL);
9987     }
9988     memset(ret, 0, sizeof(xmlSchemaConstructionCtxt));
9989 
9990     ret->buckets = xmlSchemaItemListCreate();
9991     if (ret->buckets == NULL) {
9992 	xmlSchemaPErrMemory(NULL,
9993 	    "allocating list of schema buckets", NULL);
9994 	xmlFree(ret);
9995         return (NULL);
9996     }
9997     ret->pending = xmlSchemaItemListCreate();
9998     if (ret->pending == NULL) {
9999 	xmlSchemaPErrMemory(NULL,
10000 	    "allocating list of pending global components", NULL);
10001 	xmlSchemaConstructionCtxtFree(ret);
10002         return (NULL);
10003     }
10004     ret->dict = dict;
10005     xmlDictReference(dict);
10006     return(ret);
10007 }
10008 
10009 static xmlSchemaParserCtxtPtr
xmlSchemaParserCtxtCreate(void)10010 xmlSchemaParserCtxtCreate(void)
10011 {
10012     xmlSchemaParserCtxtPtr ret;
10013 
10014     ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
10015     if (ret == NULL) {
10016         xmlSchemaPErrMemory(NULL, "allocating schema parser context",
10017                             NULL);
10018         return (NULL);
10019     }
10020     memset(ret, 0, sizeof(xmlSchemaParserCtxt));
10021     ret->type = XML_SCHEMA_CTXT_PARSER;
10022     ret->attrProhibs = xmlSchemaItemListCreate();
10023     if (ret->attrProhibs == NULL) {
10024 	xmlFree(ret);
10025 	return(NULL);
10026     }
10027     return(ret);
10028 }
10029 
10030 /**
10031  * xmlSchemaNewParserCtxtUseDict:
10032  * @URL:  the location of the schema
10033  * @dict: the dictionary to be used
10034  *
10035  * Create an XML Schemas parse context for that file/resource expected
10036  * to contain an XML Schemas file.
10037  *
10038  * Returns the parser context or NULL in case of error
10039  */
10040 static xmlSchemaParserCtxtPtr
xmlSchemaNewParserCtxtUseDict(const char * URL,xmlDictPtr dict)10041 xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
10042 {
10043     xmlSchemaParserCtxtPtr ret;
10044 
10045     ret = xmlSchemaParserCtxtCreate();
10046     if (ret == NULL)
10047         return (NULL);
10048     ret->dict = dict;
10049     xmlDictReference(dict);
10050     if (URL != NULL)
10051 	ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
10052     return (ret);
10053 }
10054 
10055 static int
xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)10056 xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
10057 {
10058     if (vctxt->pctxt == NULL) {
10059         if (vctxt->schema != NULL)
10060 	    vctxt->pctxt =
10061 		xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
10062 	else
10063 	    vctxt->pctxt = xmlSchemaNewParserCtxt("*");
10064 	if (vctxt->pctxt == NULL) {
10065 	    VERROR_INT("xmlSchemaCreatePCtxtOnVCtxt",
10066 		"failed to create a temp. parser context");
10067 	    return (-1);
10068 	}
10069 	/* TODO: Pass user data. */
10070 	xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error,
10071 	    vctxt->warning, vctxt->errCtxt);
10072 	xmlSchemaSetParserStructuredErrors(vctxt->pctxt, vctxt->serror,
10073 	    vctxt->errCtxt);
10074     }
10075     return (0);
10076 }
10077 
10078 /**
10079  * xmlSchemaGetSchemaBucket:
10080  * @pctxt: the schema parser context
10081  * @schemaLocation: the URI of the schema document
10082  *
10083  * Returns a schema bucket if it was already parsed.
10084  *
10085  * Returns a schema bucket if it was already parsed from
10086  *         @schemaLocation, NULL otherwise.
10087  */
10088 static xmlSchemaBucketPtr
xmlSchemaGetSchemaBucket(xmlSchemaParserCtxtPtr pctxt,const xmlChar * schemaLocation)10089 xmlSchemaGetSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
10090 			    const xmlChar *schemaLocation)
10091 {
10092     xmlSchemaBucketPtr cur;
10093     xmlSchemaItemListPtr list;
10094 
10095     list = pctxt->constructor->buckets;
10096     if (list->nbItems == 0)
10097 	return(NULL);
10098     else {
10099 	int i;
10100 	for (i = 0; i < list->nbItems; i++) {
10101 	    cur = (xmlSchemaBucketPtr) list->items[i];
10102 	    /* Pointer comparison! */
10103 	    if (cur->schemaLocation == schemaLocation)
10104 		return(cur);
10105 	}
10106     }
10107     return(NULL);
10108 }
10109 
10110 static xmlSchemaBucketPtr
xmlSchemaGetChameleonSchemaBucket(xmlSchemaParserCtxtPtr pctxt,const xmlChar * schemaLocation,const xmlChar * targetNamespace)10111 xmlSchemaGetChameleonSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
10112 				     const xmlChar *schemaLocation,
10113 				     const xmlChar *targetNamespace)
10114 {
10115     xmlSchemaBucketPtr cur;
10116     xmlSchemaItemListPtr list;
10117 
10118     list = pctxt->constructor->buckets;
10119     if (list->nbItems == 0)
10120 	return(NULL);
10121     else {
10122 	int i;
10123 	for (i = 0; i < list->nbItems; i++) {
10124 	    cur = (xmlSchemaBucketPtr) list->items[i];
10125 	    /* Pointer comparison! */
10126 	    if ((cur->origTargetNamespace == NULL) &&
10127 		(cur->schemaLocation == schemaLocation) &&
10128 		(cur->targetNamespace == targetNamespace))
10129 		return(cur);
10130 	}
10131     }
10132     return(NULL);
10133 }
10134 
10135 
10136 #define IS_BAD_SCHEMA_DOC(b) \
10137     (((b)->doc == NULL) && ((b)->schemaLocation != NULL))
10138 
10139 static xmlSchemaBucketPtr
xmlSchemaGetSchemaBucketByTNS(xmlSchemaParserCtxtPtr pctxt,const xmlChar * targetNamespace,int imported)10140 xmlSchemaGetSchemaBucketByTNS(xmlSchemaParserCtxtPtr pctxt,
10141 				 const xmlChar *targetNamespace,
10142 				 int imported)
10143 {
10144     xmlSchemaBucketPtr cur;
10145     xmlSchemaItemListPtr list;
10146 
10147     list = pctxt->constructor->buckets;
10148     if (list->nbItems == 0)
10149 	return(NULL);
10150     else {
10151 	int i;
10152 	for (i = 0; i < list->nbItems; i++) {
10153 	    cur = (xmlSchemaBucketPtr) list->items[i];
10154 	    if ((! IS_BAD_SCHEMA_DOC(cur)) &&
10155 		(cur->origTargetNamespace == targetNamespace) &&
10156 		((imported && cur->imported) ||
10157 		 ((!imported) && (!cur->imported))))
10158 		return(cur);
10159 	}
10160     }
10161     return(NULL);
10162 }
10163 
10164 static int
xmlSchemaParseNewDocWithContext(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlSchemaBucketPtr bucket)10165 xmlSchemaParseNewDocWithContext(xmlSchemaParserCtxtPtr pctxt,
10166 		     xmlSchemaPtr schema,
10167 		     xmlSchemaBucketPtr bucket)
10168 {
10169     int oldFlags;
10170     xmlDocPtr oldDoc;
10171     xmlNodePtr node;
10172     int ret, oldErrs;
10173     xmlSchemaBucketPtr oldbucket = pctxt->constructor->bucket;
10174 
10175     /*
10176     * Save old values; reset the *main* schema.
10177     * URGENT TODO: This is not good; move the per-document information
10178     * to the parser. Get rid of passing the main schema to the
10179     * parsing functions.
10180     */
10181     oldFlags = schema->flags;
10182     oldDoc = schema->doc;
10183     if (schema->flags != 0)
10184 	xmlSchemaClearSchemaDefaults(schema);
10185     schema->doc = bucket->doc;
10186     pctxt->schema = schema;
10187     /*
10188     * Keep the current target namespace on the parser *not* on the
10189     * main schema.
10190     */
10191     pctxt->targetNamespace = bucket->targetNamespace;
10192     WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
10193 
10194     if ((bucket->targetNamespace != NULL) &&
10195 	xmlStrEqual(bucket->targetNamespace, xmlSchemaNs)) {
10196 	/*
10197 	* We are parsing the schema for schemas!
10198 	*/
10199 	pctxt->isS4S = 1;
10200     }
10201     /* Mark it as parsed, even if parsing fails. */
10202     bucket->parsed++;
10203     /* Compile the schema doc. */
10204     node = xmlDocGetRootElement(bucket->doc);
10205     ret = xmlSchemaParseSchemaElement(pctxt, schema, node);
10206     if (ret != 0)
10207 	goto exit;
10208     /* An empty schema; just get out. */
10209     if (node->children == NULL)
10210 	goto exit;
10211     oldErrs = pctxt->nberrors;
10212     ret = xmlSchemaParseSchemaTopLevel(pctxt, schema, node->children);
10213     if (ret != 0)
10214 	goto exit;
10215     /*
10216     * TODO: Not nice, but I'm not 100% sure we will get always an error
10217     * as a result of the obove functions; so better rely on pctxt->err
10218     * as well.
10219     */
10220     if ((ret == 0) && (oldErrs != pctxt->nberrors)) {
10221 	ret = pctxt->err;
10222 	goto exit;
10223     }
10224 
10225 exit:
10226     WXS_CONSTRUCTOR(pctxt)->bucket = oldbucket;
10227     /* Restore schema values. */
10228     schema->doc = oldDoc;
10229     schema->flags = oldFlags;
10230     return(ret);
10231 }
10232 
10233 static int
xmlSchemaParseNewDoc(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlSchemaBucketPtr bucket)10234 xmlSchemaParseNewDoc(xmlSchemaParserCtxtPtr pctxt,
10235 		     xmlSchemaPtr schema,
10236 		     xmlSchemaBucketPtr bucket)
10237 {
10238     xmlSchemaParserCtxtPtr newpctxt;
10239     int res = 0;
10240 
10241     if (bucket == NULL)
10242 	return(0);
10243     if (bucket->parsed) {
10244 	PERROR_INT("xmlSchemaParseNewDoc",
10245 	    "reparsing a schema doc");
10246 	return(-1);
10247     }
10248     if (bucket->doc == NULL) {
10249 	PERROR_INT("xmlSchemaParseNewDoc",
10250 	    "parsing a schema doc, but there's no doc");
10251 	return(-1);
10252     }
10253     if (pctxt->constructor == NULL) {
10254 	PERROR_INT("xmlSchemaParseNewDoc",
10255 	    "no constructor");
10256 	return(-1);
10257     }
10258     /* Create and init the temporary parser context. */
10259     newpctxt = xmlSchemaNewParserCtxtUseDict(
10260 	(const char *) bucket->schemaLocation, pctxt->dict);
10261     if (newpctxt == NULL)
10262 	return(-1);
10263     newpctxt->constructor = pctxt->constructor;
10264     /*
10265     * TODO: Can we avoid that the parser knows about the main schema?
10266     * It would be better if he knows about the current schema bucket
10267     * only.
10268     */
10269     newpctxt->schema = schema;
10270     xmlSchemaSetParserErrors(newpctxt, pctxt->error, pctxt->warning,
10271 	pctxt->errCtxt);
10272     xmlSchemaSetParserStructuredErrors(newpctxt, pctxt->serror,
10273 	pctxt->errCtxt);
10274     newpctxt->counter = pctxt->counter;
10275 
10276 
10277     res = xmlSchemaParseNewDocWithContext(newpctxt, schema, bucket);
10278 
10279     /* Channel back errors and cleanup the temporary parser context. */
10280     if (res != 0)
10281 	pctxt->err = res;
10282     pctxt->nberrors += newpctxt->nberrors;
10283     pctxt->counter = newpctxt->counter;
10284     newpctxt->constructor = NULL;
10285     /* Free the parser context. */
10286     xmlSchemaFreeParserCtxt(newpctxt);
10287     return(res);
10288 }
10289 
10290 static void
xmlSchemaSchemaRelationAddChild(xmlSchemaBucketPtr bucket,xmlSchemaSchemaRelationPtr rel)10291 xmlSchemaSchemaRelationAddChild(xmlSchemaBucketPtr bucket,
10292 				xmlSchemaSchemaRelationPtr rel)
10293 {
10294     xmlSchemaSchemaRelationPtr cur = bucket->relations;
10295 
10296     if (cur == NULL) {
10297 	bucket->relations = rel;
10298 	return;
10299     }
10300     while (cur->next != NULL)
10301 	cur = cur->next;
10302     cur->next = rel;
10303 }
10304 
10305 
10306 static const xmlChar *
xmlSchemaBuildAbsoluteURI(xmlDictPtr dict,const xmlChar * location,xmlNodePtr ctxtNode)10307 xmlSchemaBuildAbsoluteURI(xmlDictPtr dict, const xmlChar* location,
10308 			  xmlNodePtr ctxtNode)
10309 {
10310     /*
10311     * Build an absolue location URI.
10312     */
10313     if (location != NULL) {
10314 	if (ctxtNode == NULL)
10315 	    return(location);
10316 	else {
10317 	    xmlChar *base, *URI;
10318 	    const xmlChar *ret = NULL;
10319 
10320 	    base = xmlNodeGetBase(ctxtNode->doc, ctxtNode);
10321 	    if (base == NULL) {
10322 		URI = xmlBuildURI(location, ctxtNode->doc->URL);
10323 	    } else {
10324 		URI = xmlBuildURI(location, base);
10325 		xmlFree(base);
10326 	    }
10327 	    if (URI != NULL) {
10328 		ret = xmlDictLookup(dict, URI, -1);
10329 		xmlFree(URI);
10330 		return(ret);
10331 	    }
10332 	}
10333     }
10334     return(NULL);
10335 }
10336 
10337 
10338 
10339 /**
10340  * xmlSchemaAddSchemaDoc:
10341  * @pctxt:  a schema validation context
10342  * @schema:  the schema being built
10343  * @node:  a subtree containing XML Schema informations
10344  *
10345  * Parse an included (and to-be-redefined) XML schema document.
10346  *
10347  * Returns 0 on success, a positive error code on errors and
10348  *         -1 in case of an internal or API error.
10349  */
10350 
10351 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)10352 xmlSchemaAddSchemaDoc(xmlSchemaParserCtxtPtr pctxt,
10353 		int type, /* import or include or redefine */
10354 		const xmlChar *schemaLocation,
10355 		xmlDocPtr schemaDoc,
10356 		const char *schemaBuffer,
10357 		int schemaBufferLen,
10358 		xmlNodePtr invokingNode,
10359 		const xmlChar *sourceTargetNamespace,
10360 		const xmlChar *importNamespace,
10361 		xmlSchemaBucketPtr *bucket)
10362 {
10363     const xmlChar *targetNamespace = NULL;
10364     xmlSchemaSchemaRelationPtr relation = NULL;
10365     xmlDocPtr doc = NULL;
10366     int res = 0, err = 0, located = 0, preserveDoc = 0;
10367     xmlSchemaBucketPtr bkt = NULL;
10368 
10369     if (bucket != NULL)
10370 	*bucket = NULL;
10371 
10372     switch (type) {
10373 	case XML_SCHEMA_SCHEMA_IMPORT:
10374 	case XML_SCHEMA_SCHEMA_MAIN:
10375 	    err = XML_SCHEMAP_SRC_IMPORT;
10376 	    break;
10377 	case XML_SCHEMA_SCHEMA_INCLUDE:
10378 	    err = XML_SCHEMAP_SRC_INCLUDE;
10379 	    break;
10380 	case XML_SCHEMA_SCHEMA_REDEFINE:
10381 	    err = XML_SCHEMAP_SRC_REDEFINE;
10382 	    break;
10383     }
10384 
10385 
10386     /* Special handling for the main schema:
10387     * skip the location and relation logic and just parse the doc.
10388     * We need just a bucket to be returned in this case.
10389     */
10390     if ((type == XML_SCHEMA_SCHEMA_MAIN) || (! WXS_HAS_BUCKETS(pctxt)))
10391 	goto doc_load;
10392 
10393     /* Note that we expect the location to be an absulute URI. */
10394     if (schemaLocation != NULL) {
10395 	bkt = xmlSchemaGetSchemaBucket(pctxt, schemaLocation);
10396 	if ((bkt != NULL) &&
10397 	    (pctxt->constructor->bucket == bkt)) {
10398 	    /* Report self-imports/inclusions/redefinitions. */
10399 
10400 	    xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10401 		invokingNode, NULL,
10402 		"The schema must not import/include/redefine itself",
10403 		NULL, NULL);
10404 	    goto exit;
10405 	}
10406     }
10407     /*
10408     * Create a relation for the graph of schemas.
10409     */
10410     relation = xmlSchemaSchemaRelationCreate();
10411     if (relation == NULL)
10412 	return(-1);
10413     xmlSchemaSchemaRelationAddChild(pctxt->constructor->bucket,
10414 	relation);
10415     relation->type = type;
10416 
10417     /*
10418     * Save the namespace import information.
10419     */
10420     if (WXS_IS_BUCKET_IMPMAIN(type)) {
10421 	relation->importNamespace = importNamespace;
10422 	if (schemaLocation == NULL) {
10423 	    /*
10424 	    * No location; this is just an import of the namespace.
10425 	    * Note that we don't assign a bucket to the relation
10426 	    * in this case.
10427 	    */
10428 	    goto exit;
10429 	}
10430 	targetNamespace = importNamespace;
10431     }
10432 
10433     /* Did we already fetch the doc? */
10434     if (bkt != NULL) {
10435 	if ((WXS_IS_BUCKET_IMPMAIN(type)) && (! bkt->imported)) {
10436 	    /*
10437 	    * We included/redefined and then try to import a schema,
10438 	    * but the new location provided for import was different.
10439 	    */
10440 	    if (schemaLocation == NULL)
10441 		schemaLocation = BAD_CAST "in_memory_buffer";
10442 	    if (!xmlStrEqual(schemaLocation,
10443 		bkt->schemaLocation)) {
10444 		xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10445 		    invokingNode, NULL,
10446 		    "The schema document '%s' cannot be imported, since "
10447 		    "it was already included or redefined",
10448 		    schemaLocation, NULL);
10449 		goto exit;
10450 	    }
10451 	} else if ((! WXS_IS_BUCKET_IMPMAIN(type)) && (bkt->imported)) {
10452 	    /*
10453 	    * We imported and then try to include/redefine a schema,
10454 	    * but the new location provided for the include/redefine
10455 	    * was different.
10456 	    */
10457 	    if (schemaLocation == NULL)
10458 		schemaLocation = BAD_CAST "in_memory_buffer";
10459 	    if (!xmlStrEqual(schemaLocation,
10460 		bkt->schemaLocation)) {
10461 		xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10462 		    invokingNode, NULL,
10463 		    "The schema document '%s' cannot be included or "
10464 		    "redefined, since it was already imported",
10465 		    schemaLocation, NULL);
10466 		goto exit;
10467 	    }
10468 	}
10469     }
10470 
10471     if (WXS_IS_BUCKET_IMPMAIN(type)) {
10472 	/*
10473 	* Given that the schemaLocation [attribute] is only a hint, it is open
10474 	* to applications to ignore all but the first <import> for a given
10475 	* namespace, regardless of the `actual value` of schemaLocation, but
10476 	* such a strategy risks missing useful information when new
10477 	* schemaLocations are offered.
10478 	*
10479 	* We will use the first <import> that comes with a location.
10480 	* Further <import>s *with* a location, will result in an error.
10481 	* TODO: Better would be to just report a warning here, but
10482 	* we'll try it this way until someone complains.
10483 	*
10484 	* Schema Document Location Strategy:
10485 	* 3 Based on the namespace name, identify an existing schema document,
10486 	* either as a resource which is an XML document or a <schema> element
10487 	* information item, in some local schema repository;
10488 	* 5 Attempt to resolve the namespace name to locate such a resource.
10489 	*
10490 	* NOTE: (3) and (5) are not supported.
10491 	*/
10492 	if (bkt != NULL) {
10493 	    relation->bucket = bkt;
10494 	    goto exit;
10495 	}
10496 	bkt = xmlSchemaGetSchemaBucketByTNS(pctxt,
10497 	    importNamespace, 1);
10498 
10499 	if (bkt != NULL) {
10500 	    relation->bucket = bkt;
10501 	    if (bkt->schemaLocation == NULL) {
10502 		/* First given location of the schema; load the doc. */
10503 		bkt->schemaLocation = schemaLocation;
10504 	    } else {
10505 		if (!xmlStrEqual(schemaLocation,
10506 		    bkt->schemaLocation)) {
10507 		    /*
10508 		    * Additional location given; just skip it.
10509 		    * URGENT TODO: We should report a warning here.
10510 		    * res = XML_SCHEMAP_SRC_IMPORT;
10511 		    */
10512 		    if (schemaLocation == NULL)
10513 			schemaLocation = BAD_CAST "in_memory_buffer";
10514 
10515 		    xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10516 			XML_SCHEMAP_WARN_SKIP_SCHEMA,
10517 			invokingNode, NULL,
10518 			"Skipping import of schema located at '%s' for the "
10519 			"namespace '%s', since this namespace was already "
10520 			"imported with the schema located at '%s'",
10521 			schemaLocation, importNamespace, bkt->schemaLocation);
10522 		}
10523 		goto exit;
10524 	    }
10525 	}
10526 	/*
10527 	* No bucket + first location: load the doc and create a
10528 	* bucket.
10529 	*/
10530     } else {
10531 	/* <include> and <redefine> */
10532 	if (bkt != NULL) {
10533 
10534 	    if ((bkt->origTargetNamespace == NULL) &&
10535 		(bkt->targetNamespace != sourceTargetNamespace)) {
10536 		xmlSchemaBucketPtr chamel;
10537 
10538 		/*
10539 		* Chameleon include/redefine: skip loading only if it was
10540 		* aleady build for the targetNamespace of the including
10541 		* schema.
10542 		*/
10543 		/*
10544 		* URGENT TODO: If the schema is a chameleon-include then copy
10545 		* the components into the including schema and modify the
10546 		* targetNamespace of those components, do nothing otherwise.
10547 		* NOTE: This is currently worked-around by compiling the
10548 		* chameleon for every destinct including targetNamespace; thus
10549 		* not performant at the moment.
10550 		* TODO: Check when the namespace in wildcards for chameleons
10551 		* needs to be converted: before we built wildcard intersections
10552 		* or after.
10553 		*   Answer: after!
10554 		*/
10555 		chamel = xmlSchemaGetChameleonSchemaBucket(pctxt,
10556 		    schemaLocation, sourceTargetNamespace);
10557 		if (chamel != NULL) {
10558 		    /* A fitting chameleon was already parsed; NOP. */
10559 		    relation->bucket = chamel;
10560 		    goto exit;
10561 		}
10562 		/*
10563 		* We need to parse the chameleon again for a different
10564 		* targetNamespace.
10565 		* CHAMELEON TODO: Optimize this by only parsing the
10566 		* chameleon once, and then copying the components to
10567 		* the new targetNamespace.
10568 		*/
10569 		bkt = NULL;
10570 	    } else {
10571 		relation->bucket = bkt;
10572 		goto exit;
10573 	    }
10574 	}
10575     }
10576     if ((bkt != NULL) && (bkt->doc != NULL)) {
10577 	PERROR_INT("xmlSchemaAddSchemaDoc",
10578 	    "trying to load a schema doc, but a doc is already "
10579 	    "assigned to the schema bucket");
10580 	goto exit_failure;
10581     }
10582 
10583 doc_load:
10584     /*
10585     * Load the document.
10586     */
10587     if (schemaDoc != NULL) {
10588 	doc = schemaDoc;
10589 	/* Don' free this one, since it was provided by the caller. */
10590 	preserveDoc = 1;
10591 	/* TODO: Does the context or the doc hold the location? */
10592 	if (schemaDoc->URL != NULL)
10593 	    schemaLocation = xmlDictLookup(pctxt->dict,
10594 		schemaDoc->URL, -1);
10595         else
10596 	    schemaLocation = BAD_CAST "in_memory_buffer";
10597     } else if ((schemaLocation != NULL) || (schemaBuffer != NULL)) {
10598 	xmlParserCtxtPtr parserCtxt;
10599 
10600 	parserCtxt = xmlNewParserCtxt();
10601 	if (parserCtxt == NULL) {
10602 	    xmlSchemaPErrMemory(NULL, "xmlSchemaGetDoc, "
10603 		"allocating a parser context", NULL);
10604 	    goto exit_failure;
10605 	}
10606 	if ((pctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
10607 	    /*
10608 	    * TODO: Do we have to burden the schema parser dict with all
10609 	    * the content of the schema doc?
10610 	    */
10611 	    xmlDictFree(parserCtxt->dict);
10612 	    parserCtxt->dict = pctxt->dict;
10613 	    xmlDictReference(parserCtxt->dict);
10614 	}
10615 	if (schemaLocation != NULL) {
10616 	    /* Parse from file. */
10617 	    doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
10618 		NULL, SCHEMAS_PARSE_OPTIONS);
10619 	} else if (schemaBuffer != NULL) {
10620 	    /* Parse from memory buffer. */
10621 	    doc = xmlCtxtReadMemory(parserCtxt, schemaBuffer, schemaBufferLen,
10622 		NULL, NULL, SCHEMAS_PARSE_OPTIONS);
10623 	    schemaLocation = BAD_CAST "in_memory_buffer";
10624 	    if (doc != NULL)
10625 		doc->URL = xmlStrdup(schemaLocation);
10626 	}
10627 	/*
10628 	* For <import>:
10629 	* 2.1 The referent is (a fragment of) a resource which is an
10630 	* XML document (see clause 1.1), which in turn corresponds to
10631 	* a <schema> element information item in a well-formed information
10632 	* set, which in turn corresponds to a valid schema.
10633 	* TODO: (2.1) fragments of XML documents are not supported.
10634 	*
10635 	* 2.2 The referent is a <schema> element information item in
10636 	* a well-formed information set, which in turn corresponds
10637 	* to a valid schema.
10638 	* TODO: (2.2) is not supported.
10639 	*/
10640 	if (doc == NULL) {
10641 	    xmlErrorPtr lerr;
10642 	    lerr = xmlGetLastError();
10643 	    /*
10644 	    * Check if this a parser error, or if the document could
10645 	    * just not be located.
10646 	    * TODO: Try to find specific error codes to react only on
10647 	    * localisation failures.
10648 	    */
10649 	    if ((lerr == NULL) || (lerr->domain != XML_FROM_IO)) {
10650 		/*
10651 		* We assume a parser error here.
10652 		*/
10653 		located = 1;
10654 		/* TODO: Error code ?? */
10655 		res = XML_SCHEMAP_SRC_IMPORT_2_1;
10656 		xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10657 		    invokingNode, NULL,
10658 		    "Failed to parse the XML resource '%s'",
10659 		    schemaLocation, NULL);
10660 	    }
10661 	}
10662 	xmlFreeParserCtxt(parserCtxt);
10663 	if ((doc == NULL) && located)
10664 	    goto exit_error;
10665     } else {
10666 	xmlSchemaPErr(pctxt, NULL,
10667 	    XML_SCHEMAP_NOTHING_TO_PARSE,
10668 	    "No information for parsing was provided with the "
10669 	    "given schema parser context.\n",
10670 	    NULL, NULL);
10671 	goto exit_failure;
10672     }
10673     /*
10674     * Preprocess the document.
10675     */
10676     if (doc != NULL) {
10677 	xmlNodePtr docElem = NULL;
10678 
10679 	located = 1;
10680 	docElem = xmlDocGetRootElement(doc);
10681 	if (docElem == NULL) {
10682 	    xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOROOT,
10683 		invokingNode, NULL,
10684 		"The document '%s' has no document element",
10685 		schemaLocation, NULL);
10686 	    goto exit_error;
10687 	}
10688 	/*
10689 	* Remove all the blank text nodes.
10690 	*/
10691 	xmlSchemaCleanupDoc(pctxt, docElem);
10692 	/*
10693 	* Check the schema's top level element.
10694 	*/
10695 	if (!IS_SCHEMA(docElem, "schema")) {
10696 	    xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOT_SCHEMA,
10697 		invokingNode, NULL,
10698 		"The XML document '%s' is not a schema document",
10699 		schemaLocation, NULL);
10700 	    goto exit_error;
10701 	}
10702 	/*
10703 	* Note that we don't apply a type check for the
10704 	* targetNamespace value here.
10705 	*/
10706 	targetNamespace = xmlSchemaGetProp(pctxt, docElem,
10707 	    "targetNamespace");
10708     }
10709 
10710 /* after_doc_loading: */
10711     if ((bkt == NULL) && located) {
10712 	/* Only create a bucket if the schema was located. */
10713         bkt = xmlSchemaBucketCreate(pctxt, type,
10714 	    targetNamespace);
10715 	if (bkt == NULL)
10716 	    goto exit_failure;
10717     }
10718     if (bkt != NULL) {
10719 	bkt->schemaLocation = schemaLocation;
10720 	bkt->located = located;
10721 	if (doc != NULL) {
10722 	    bkt->doc = doc;
10723 	    bkt->targetNamespace = targetNamespace;
10724 	    bkt->origTargetNamespace = targetNamespace;
10725 	    if (preserveDoc)
10726 		bkt->preserveDoc = 1;
10727 	}
10728 	if (WXS_IS_BUCKET_IMPMAIN(type))
10729 	    bkt->imported++;
10730 	    /*
10731 	    * Add it to the graph of schemas.
10732 	    */
10733 	if (relation != NULL)
10734 	    relation->bucket = bkt;
10735     }
10736 
10737 exit:
10738     /*
10739     * Return the bucket explicitely; this is needed for the
10740     * main schema.
10741     */
10742     if (bucket != NULL)
10743 	*bucket = bkt;
10744     return (0);
10745 
10746 exit_error:
10747     if ((doc != NULL) && (! preserveDoc)) {
10748 	xmlFreeDoc(doc);
10749 	if (bkt != NULL)
10750 	    bkt->doc = NULL;
10751     }
10752     return(pctxt->err);
10753 
10754 exit_failure:
10755     if ((doc != NULL) && (! preserveDoc)) {
10756 	xmlFreeDoc(doc);
10757 	if (bkt != NULL)
10758 	    bkt->doc = NULL;
10759     }
10760     return (-1);
10761 }
10762 
10763 /**
10764  * xmlSchemaParseImport:
10765  * @ctxt:  a schema validation context
10766  * @schema:  the schema being built
10767  * @node:  a subtree containing XML Schema informations
10768  *
10769  * parse a XML schema Import definition
10770  * *WARNING* this interface is highly subject to change
10771  *
10772  * Returns 0 in case of success, a positive error code if
10773  * not valid and -1 in case of an internal error.
10774  */
10775 static int
xmlSchemaParseImport(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node)10776 xmlSchemaParseImport(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
10777                      xmlNodePtr node)
10778 {
10779     xmlNodePtr child;
10780     const xmlChar *namespaceName = NULL, *schemaLocation = NULL;
10781     const xmlChar *thisTargetNamespace;
10782     xmlAttrPtr attr;
10783     int ret = 0;
10784     xmlSchemaBucketPtr bucket = NULL;
10785 
10786     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
10787         return (-1);
10788 
10789     /*
10790     * Check for illegal attributes.
10791     */
10792     attr = node->properties;
10793     while (attr != NULL) {
10794 	if (attr->ns == NULL) {
10795 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10796 		(!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
10797 		(!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
10798 		xmlSchemaPIllegalAttrErr(pctxt,
10799 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10800 	    }
10801 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10802 	    xmlSchemaPIllegalAttrErr(pctxt,
10803 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10804 	}
10805 	attr = attr->next;
10806     }
10807     /*
10808     * Extract and validate attributes.
10809     */
10810     if (xmlSchemaPValAttr(pctxt, NULL, node,
10811 	"namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10812 	&namespaceName) != 0) {
10813 	xmlSchemaPSimpleTypeErr(pctxt,
10814 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
10815 	    NULL, node,
10816 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10817 	    NULL, namespaceName, NULL, NULL, NULL);
10818 	return (pctxt->err);
10819     }
10820 
10821     if (xmlSchemaPValAttr(pctxt, NULL, node,
10822 	"schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10823 	&schemaLocation) != 0) {
10824 	xmlSchemaPSimpleTypeErr(pctxt,
10825 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
10826 	    NULL, node,
10827 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10828 	    NULL, schemaLocation, NULL, NULL, NULL);
10829 	return (pctxt->err);
10830     }
10831     /*
10832     * And now for the children...
10833     */
10834     child = node->children;
10835     if (IS_SCHEMA(child, "annotation")) {
10836         /*
10837          * the annotation here is simply discarded ...
10838 	 * TODO: really?
10839          */
10840         child = child->next;
10841     }
10842     if (child != NULL) {
10843 	xmlSchemaPContentErr(pctxt,
10844 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10845 	    NULL, node, child, NULL,
10846 	    "(annotation?)");
10847     }
10848     /*
10849     * Apply additional constraints.
10850     *
10851     * Note that it is important to use the original @targetNamespace
10852     * (or none at all), to rule out imports of schemas _with_ a
10853     * @targetNamespace if the importing schema is a chameleon schema
10854     * (with no @targetNamespace).
10855     */
10856     thisTargetNamespace = WXS_BUCKET(pctxt)->origTargetNamespace;
10857     if (namespaceName != NULL) {
10858 	/*
10859 	* 1.1 If the namespace [attribute] is present, then its `actual value`
10860 	* must not match the `actual value` of the enclosing <schema>'s
10861 	* targetNamespace [attribute].
10862 	*/
10863 	if (xmlStrEqual(thisTargetNamespace, namespaceName)) {
10864 	    xmlSchemaPCustomErr(pctxt,
10865 		XML_SCHEMAP_SRC_IMPORT_1_1,
10866 		NULL, node,
10867 		"The value of the attribute 'namespace' must not match "
10868 		"the target namespace '%s' of the importing schema",
10869 		thisTargetNamespace);
10870 	    return (pctxt->err);
10871 	}
10872     } else {
10873 	/*
10874 	* 1.2 If the namespace [attribute] is not present, then the enclosing
10875 	* <schema> must have a targetNamespace [attribute].
10876 	*/
10877 	if (thisTargetNamespace == NULL) {
10878 	    xmlSchemaPCustomErr(pctxt,
10879 		XML_SCHEMAP_SRC_IMPORT_1_2,
10880 		NULL, node,
10881 		"The attribute 'namespace' must be existent if "
10882 		"the importing schema has no target namespace",
10883 		NULL);
10884 	    return (pctxt->err);
10885 	}
10886     }
10887     /*
10888     * Locate and acquire the schema document.
10889     */
10890     if (schemaLocation != NULL)
10891 	schemaLocation = xmlSchemaBuildAbsoluteURI(pctxt->dict,
10892 	    schemaLocation, node);
10893     ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
10894 	schemaLocation, NULL, NULL, 0, node, thisTargetNamespace,
10895 	namespaceName, &bucket);
10896 
10897     if (ret != 0)
10898 	return(ret);
10899 
10900     /*
10901     * For <import>: "It is *not* an error for the application
10902     * schema reference strategy to fail."
10903     * So just don't parse if no schema document was found.
10904     * Note that we will get no bucket if the schema could not be
10905     * located or if there was no schemaLocation.
10906     */
10907     if ((bucket == NULL) && (schemaLocation != NULL)) {
10908 	xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10909 	    XML_SCHEMAP_WARN_UNLOCATED_SCHEMA,
10910 	    node, NULL,
10911 	    "Failed to locate a schema at location '%s'. "
10912 	    "Skipping the import", schemaLocation, NULL, NULL);
10913     }
10914 
10915     if ((bucket != NULL) && CAN_PARSE_SCHEMA(bucket)) {
10916 	ret = xmlSchemaParseNewDoc(pctxt, schema, bucket);
10917     }
10918 
10919     return (ret);
10920 }
10921 
10922 static int
xmlSchemaParseIncludeOrRedefineAttrs(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node,xmlChar ** schemaLocation,int type)10923 xmlSchemaParseIncludeOrRedefineAttrs(xmlSchemaParserCtxtPtr pctxt,
10924 				     xmlSchemaPtr schema,
10925 				     xmlNodePtr node,
10926 				     xmlChar **schemaLocation,
10927 				     int type)
10928 {
10929     xmlAttrPtr attr;
10930 
10931     if ((pctxt == NULL) || (schema == NULL) || (node == NULL) ||
10932 	(schemaLocation == NULL))
10933         return (-1);
10934 
10935     *schemaLocation = NULL;
10936     /*
10937     * Check for illegal attributes.
10938     * Applies for both <include> and <redefine>.
10939     */
10940     attr = node->properties;
10941     while (attr != NULL) {
10942 	if (attr->ns == NULL) {
10943 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10944 		(!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
10945 		xmlSchemaPIllegalAttrErr(pctxt,
10946 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10947 	    }
10948 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10949 	    xmlSchemaPIllegalAttrErr(pctxt,
10950 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10951 	}
10952 	attr = attr->next;
10953     }
10954     xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
10955     /*
10956     * Preliminary step, extract the URI-Reference and make an URI
10957     * from the base.
10958     */
10959     /*
10960     * Attribute "schemaLocation" is mandatory.
10961     */
10962     attr = xmlSchemaGetPropNode(node, "schemaLocation");
10963     if (attr != NULL) {
10964         xmlChar *base = NULL;
10965         xmlChar *uri = NULL;
10966 
10967 	if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
10968 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10969 	    (const xmlChar **) schemaLocation) != 0)
10970 	    goto exit_error;
10971 	base = xmlNodeGetBase(node->doc, node);
10972 	if (base == NULL) {
10973 	    uri = xmlBuildURI(*schemaLocation, node->doc->URL);
10974 	} else {
10975 	    uri = xmlBuildURI(*schemaLocation, base);
10976 	    xmlFree(base);
10977 	}
10978 	if (uri == NULL) {
10979 	    PERROR_INT("xmlSchemaParseIncludeOrRedefine",
10980 		"could not build an URI from the schemaLocation")
10981 	    goto exit_failure;
10982 	}
10983 	(*schemaLocation) = (xmlChar *) xmlDictLookup(pctxt->dict, uri, -1);
10984 	xmlFree(uri);
10985     } else {
10986 	xmlSchemaPMissingAttrErr(pctxt,
10987 	    XML_SCHEMAP_S4S_ATTR_MISSING,
10988 	    NULL, node, "schemaLocation", NULL);
10989 	goto exit_error;
10990     }
10991     /*
10992     * Report self-inclusion and self-redefinition.
10993     */
10994     if (xmlStrEqual(*schemaLocation, pctxt->URL)) {
10995 	if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
10996 	    xmlSchemaPCustomErr(pctxt,
10997 		XML_SCHEMAP_SRC_REDEFINE,
10998 		NULL, node,
10999 		"The schema document '%s' cannot redefine itself.",
11000 		*schemaLocation);
11001 	} else {
11002 	    xmlSchemaPCustomErr(pctxt,
11003 		XML_SCHEMAP_SRC_INCLUDE,
11004 		NULL, node,
11005 		"The schema document '%s' cannot include itself.",
11006 		*schemaLocation);
11007 	}
11008 	goto exit_error;
11009     }
11010 
11011     return(0);
11012 exit_error:
11013     return(pctxt->err);
11014 exit_failure:
11015     return(-1);
11016 }
11017 
11018 static int
xmlSchemaParseIncludeOrRedefine(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node,int type)11019 xmlSchemaParseIncludeOrRedefine(xmlSchemaParserCtxtPtr pctxt,
11020 				xmlSchemaPtr schema,
11021 				xmlNodePtr node,
11022 				int type)
11023 {
11024     xmlNodePtr child = NULL;
11025     const xmlChar *schemaLocation = NULL;
11026     int res = 0; /* hasRedefinitions = 0 */
11027     int isChameleon = 0, wasChameleon = 0;
11028     xmlSchemaBucketPtr bucket = NULL;
11029 
11030     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
11031         return (-1);
11032 
11033     /*
11034     * Parse attributes. Note that the returned schemaLocation will
11035     * be already converted to an absolute URI.
11036     */
11037     res = xmlSchemaParseIncludeOrRedefineAttrs(pctxt, schema,
11038 	node, (xmlChar **) (&schemaLocation), type);
11039     if (res != 0)
11040 	return(res);
11041     /*
11042     * Load and add the schema document.
11043     */
11044     res = xmlSchemaAddSchemaDoc(pctxt, type, schemaLocation, NULL,
11045 	NULL, 0, node, pctxt->targetNamespace, NULL, &bucket);
11046     if (res != 0)
11047 	return(res);
11048     /*
11049     * If we get no schema bucket back, then this means that the schema
11050     * document could not be located or was broken XML or was not
11051     * a schema document.
11052     */
11053     if ((bucket == NULL) || (bucket->doc == NULL)) {
11054 	if (type == XML_SCHEMA_SCHEMA_INCLUDE) {
11055 	    /*
11056 	    * WARNING for <include>:
11057 	    * We will raise an error if the schema cannot be located
11058 	    * for inclusions, since the that was the feedback from the
11059 	    * schema people. I.e. the following spec piece will *not* be
11060 	    * satisfied:
11061 	    * SPEC src-include: "It is not an error for the `actual value` of the
11062 	    * schemaLocation [attribute] to fail to resolve it all, in which
11063 	    * case no corresponding inclusion is performed.
11064 	    * So do we need a warning report here?"
11065 	    */
11066 	    res = XML_SCHEMAP_SRC_INCLUDE;
11067 	    xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
11068 		node, NULL,
11069 		"Failed to load the document '%s' for inclusion",
11070 		schemaLocation, NULL);
11071 	} else {
11072 	    /*
11073 	    * NOTE: This was changed to raise an error even if no redefinitions
11074 	    * are specified.
11075 	    *
11076 	    * SPEC src-redefine (1)
11077 	    * "If there are any element information items among the [children]
11078 	    * other than <annotation> then the `actual value` of the
11079 	    * schemaLocation [attribute] must successfully resolve."
11080 	    * TODO: Ask the WG if a the location has always to resolve
11081 	    * here as well!
11082 	    */
11083 	    res = XML_SCHEMAP_SRC_REDEFINE;
11084 	    xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
11085 		node, NULL,
11086 		"Failed to load the document '%s' for redefinition",
11087 		schemaLocation, NULL);
11088 	}
11089     } else {
11090 	/*
11091 	* Check targetNamespace sanity before parsing the new schema.
11092 	* TODO: Note that we won't check further content if the
11093 	* targetNamespace was bad.
11094 	*/
11095 	if (bucket->origTargetNamespace != NULL) {
11096 	    /*
11097 	    * SPEC src-include (2.1)
11098 	    * "SII has a targetNamespace [attribute], and its `actual
11099 	    * value` is identical to the `actual value` of the targetNamespace
11100 	    * [attribute] of SII' (which must have such an [attribute])."
11101 	    */
11102 	    if (pctxt->targetNamespace == NULL) {
11103 		xmlSchemaCustomErr(ACTXT_CAST pctxt,
11104 		    XML_SCHEMAP_SRC_INCLUDE,
11105 		    node, NULL,
11106 		    "The target namespace of the included/redefined schema "
11107 		    "'%s' has to be absent, since the including/redefining "
11108 		    "schema has no target namespace",
11109 		    schemaLocation, NULL);
11110 		goto exit_error;
11111 	    } else if (!xmlStrEqual(bucket->origTargetNamespace,
11112 		pctxt->targetNamespace)) {
11113 		/* TODO: Change error function. */
11114 		xmlSchemaPCustomErrExt(pctxt,
11115 		    XML_SCHEMAP_SRC_INCLUDE,
11116 		    NULL, node,
11117 		    "The target namespace '%s' of the included/redefined "
11118 		    "schema '%s' differs from '%s' of the "
11119 		    "including/redefining schema",
11120 		    bucket->origTargetNamespace, schemaLocation,
11121 		    pctxt->targetNamespace);
11122 		goto exit_error;
11123 	    }
11124 	} else if (pctxt->targetNamespace != NULL) {
11125 	    /*
11126 	    * Chameleons: the original target namespace will
11127 	    * differ from the resulting namespace.
11128 	    */
11129 	    isChameleon = 1;
11130 	    if (bucket->parsed &&
11131 		bucket->origTargetNamespace != NULL) {
11132 		xmlSchemaCustomErr(ACTXT_CAST pctxt,
11133 		    XML_SCHEMAP_SRC_INCLUDE,
11134 		    node, NULL,
11135 		    "The target namespace of the included/redefined schema "
11136 		    "'%s' has to be absent or the same as the "
11137 		    "including/redefining schema's target namespace",
11138 		    schemaLocation, NULL);
11139 		goto exit_error;
11140 	    }
11141 	    bucket->targetNamespace = pctxt->targetNamespace;
11142 	}
11143     }
11144     /*
11145     * Parse the schema.
11146     */
11147     if (bucket && (!bucket->parsed) && (bucket->doc != NULL)) {
11148 	if (isChameleon) {
11149 	    /* TODO: Get rid of this flag on the schema itself. */
11150 	    if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
11151 		schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11152 	    } else
11153 		wasChameleon = 1;
11154 	}
11155 	xmlSchemaParseNewDoc(pctxt, schema, bucket);
11156 	/* Restore chameleon flag. */
11157 	if (isChameleon && (!wasChameleon))
11158 	    schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11159     }
11160     /*
11161     * And now for the children...
11162     */
11163     child = node->children;
11164     if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
11165 	/*
11166 	* Parse (simpleType | complexType | group | attributeGroup))*
11167 	*/
11168 	pctxt->redefined = bucket;
11169 	/*
11170 	* How to proceed if the redefined schema was not located?
11171 	*/
11172 	pctxt->isRedefine = 1;
11173 	while (IS_SCHEMA(child, "annotation") ||
11174 	    IS_SCHEMA(child, "simpleType") ||
11175 	    IS_SCHEMA(child, "complexType") ||
11176 	    IS_SCHEMA(child, "group") ||
11177 	    IS_SCHEMA(child, "attributeGroup")) {
11178 	    if (IS_SCHEMA(child, "annotation")) {
11179 		/*
11180 		* TODO: discard or not?
11181 		*/
11182 	    } else if (IS_SCHEMA(child, "simpleType")) {
11183 		xmlSchemaParseSimpleType(pctxt, schema, child, 1);
11184 	    } else if (IS_SCHEMA(child, "complexType")) {
11185 		xmlSchemaParseComplexType(pctxt, schema, child, 1);
11186 		/* hasRedefinitions = 1; */
11187 	    } else if (IS_SCHEMA(child, "group")) {
11188 		/* hasRedefinitions = 1; */
11189 		xmlSchemaParseModelGroupDefinition(pctxt,
11190 		    schema, child);
11191 	    } else if (IS_SCHEMA(child, "attributeGroup")) {
11192 		/* hasRedefinitions = 1; */
11193 		xmlSchemaParseAttributeGroupDefinition(pctxt, schema,
11194 		    child);
11195 	    }
11196 	    child = child->next;
11197 	}
11198 	pctxt->redefined = NULL;
11199 	pctxt->isRedefine = 0;
11200     } else {
11201 	if (IS_SCHEMA(child, "annotation")) {
11202 	    /*
11203 	    * TODO: discard or not?
11204 	    */
11205 	    child = child->next;
11206 	}
11207     }
11208     if (child != NULL) {
11209 	res = XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED;
11210 	if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
11211 	    xmlSchemaPContentErr(pctxt, res,
11212 		NULL, node, child, NULL,
11213 		"(annotation | (simpleType | complexType | group | attributeGroup))*");
11214 	} else {
11215 	     xmlSchemaPContentErr(pctxt, res,
11216 		NULL, node, child, NULL,
11217 		"(annotation?)");
11218 	}
11219     }
11220     return(res);
11221 
11222 exit_error:
11223     return(pctxt->err);
11224 }
11225 
11226 static int
xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node)11227 xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11228                        xmlNodePtr node)
11229 {
11230     int res;
11231 #ifndef ENABLE_REDEFINE
11232     TODO
11233     return(0);
11234 #endif
11235     res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11236 	XML_SCHEMA_SCHEMA_REDEFINE);
11237     if (res != 0)
11238 	return(res);
11239     return(0);
11240 }
11241 
11242 static int
xmlSchemaParseInclude(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node)11243 xmlSchemaParseInclude(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11244                        xmlNodePtr node)
11245 {
11246     int res;
11247 
11248     res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11249 	XML_SCHEMA_SCHEMA_INCLUDE);
11250     if (res != 0)
11251 	return(res);
11252     return(0);
11253 }
11254 
11255 /**
11256  * xmlSchemaParseModelGroup:
11257  * @ctxt:  a schema validation context
11258  * @schema:  the schema being built
11259  * @node:  a subtree containing XML Schema informations
11260  * @type: the "compositor" type
11261  * @particleNeeded: if a a model group with a particle
11262  *
11263  * parse a XML schema Sequence definition.
11264  * Applies parts of:
11265  *   Schema Representation Constraint:
11266  *     Redefinition Constraints and Semantics (src-redefine)
11267  *     (6.1), (6.1.1), (6.1.2)
11268  *
11269  *   Schema Component Constraint:
11270  *     All Group Limited (cos-all-limited) (2)
11271  *     TODO: Actually this should go to component-level checks,
11272  *     but is done here due to performance. Move it to an other layer
11273  *     is schema construction via an API is implemented.
11274  *
11275  * *WARNING* this interface is highly subject to change
11276  *
11277  * Returns -1 in case of error, 0 if the declaration is improper and
11278  *         1 in case of success.
11279  */
11280 static xmlSchemaTreeItemPtr
xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,xmlSchemaTypeType type,int withParticle)11281 xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11282 			 xmlNodePtr node, xmlSchemaTypeType type,
11283 			 int withParticle)
11284 {
11285     xmlSchemaModelGroupPtr item;
11286     xmlSchemaParticlePtr particle = NULL;
11287     xmlNodePtr child = NULL;
11288     xmlAttrPtr attr;
11289     int min = 1, max = 1, isElemRef, hasRefs = 0;
11290 
11291     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11292         return (NULL);
11293     /*
11294     * Create a model group with the given compositor.
11295     */
11296     item = xmlSchemaAddModelGroup(ctxt, schema, type, node);
11297     if (item == NULL)
11298 	return (NULL);
11299 
11300     if (withParticle) {
11301 	if (type == XML_SCHEMA_TYPE_ALL) {
11302 	    min = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
11303 	    max = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
11304 	} else {
11305 	    /* choice + sequence */
11306 	    min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
11307 	    max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
11308 		"(xs:nonNegativeInteger | unbounded)");
11309 	}
11310 	xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
11311 	/*
11312 	* Create a particle
11313 	*/
11314 	particle = xmlSchemaAddParticle(ctxt, node, min, max);
11315 	if (particle == NULL)
11316 	    return (NULL);
11317 	particle->children = (xmlSchemaTreeItemPtr) item;
11318 	/*
11319 	* Check for illegal attributes.
11320 	*/
11321 	attr = node->properties;
11322 	while (attr != NULL) {
11323 	    if (attr->ns == NULL) {
11324 		if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11325 		    (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
11326 		    (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
11327 		    xmlSchemaPIllegalAttrErr(ctxt,
11328 			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11329 		}
11330 	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11331 		xmlSchemaPIllegalAttrErr(ctxt,
11332 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11333 	    }
11334 	    attr = attr->next;
11335 	}
11336     } else {
11337 	/*
11338 	* Check for illegal attributes.
11339 	*/
11340 	attr = node->properties;
11341 	while (attr != NULL) {
11342 	    if (attr->ns == NULL) {
11343 		if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
11344 		    xmlSchemaPIllegalAttrErr(ctxt,
11345 			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11346 		}
11347 	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11348 		xmlSchemaPIllegalAttrErr(ctxt,
11349 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11350 	    }
11351 	    attr = attr->next;
11352 	}
11353     }
11354 
11355     /*
11356     * Extract and validate attributes.
11357     */
11358     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11359     /*
11360     * And now for the children...
11361     */
11362     child = node->children;
11363     if (IS_SCHEMA(child, "annotation")) {
11364         item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
11365         child = child->next;
11366     }
11367     if (type == XML_SCHEMA_TYPE_ALL) {
11368 	xmlSchemaParticlePtr part, last = NULL;
11369 
11370 	while (IS_SCHEMA(child, "element")) {
11371 	    part = (xmlSchemaParticlePtr) xmlSchemaParseElement(ctxt,
11372 		schema, child, &isElemRef, 0);
11373 	    /*
11374 	    * SPEC cos-all-limited (2)
11375 	    * "The {max occurs} of all the particles in the {particles}
11376 	    * of the ('all') group must be 0 or 1.
11377 	    */
11378 	    if (part != NULL) {
11379 		if (isElemRef)
11380 		    hasRefs++;
11381 		if (part->minOccurs > 1) {
11382 		    xmlSchemaPCustomErr(ctxt,
11383 			XML_SCHEMAP_COS_ALL_LIMITED,
11384 			NULL, child,
11385 			"Invalid value for minOccurs (must be 0 or 1)",
11386 			NULL);
11387 		    /* Reset to 1. */
11388 		    part->minOccurs = 1;
11389 		}
11390 		if (part->maxOccurs > 1) {
11391 		    xmlSchemaPCustomErr(ctxt,
11392 			XML_SCHEMAP_COS_ALL_LIMITED,
11393 			NULL, child,
11394 			"Invalid value for maxOccurs (must be 0 or 1)",
11395 			NULL);
11396 		    /* Reset to 1. */
11397 		    part->maxOccurs = 1;
11398 		}
11399 		if (last == NULL)
11400 		    item->children = (xmlSchemaTreeItemPtr) part;
11401 		else
11402 		    last->next = (xmlSchemaTreeItemPtr) part;
11403 		last = part;
11404 	    }
11405 	    child = child->next;
11406 	}
11407 	if (child != NULL) {
11408 	    xmlSchemaPContentErr(ctxt,
11409 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11410 		NULL, node, child, NULL,
11411 		"(annotation?, (annotation?, element*)");
11412 	}
11413     } else {
11414 	/* choice + sequence */
11415 	xmlSchemaTreeItemPtr part = NULL, last = NULL;
11416 
11417 	while ((IS_SCHEMA(child, "element")) ||
11418 	    (IS_SCHEMA(child, "group")) ||
11419 	    (IS_SCHEMA(child, "any")) ||
11420 	    (IS_SCHEMA(child, "choice")) ||
11421 	    (IS_SCHEMA(child, "sequence"))) {
11422 
11423 	    if (IS_SCHEMA(child, "element")) {
11424 		part = (xmlSchemaTreeItemPtr)
11425 		    xmlSchemaParseElement(ctxt, schema, child, &isElemRef, 0);
11426 		if (part && isElemRef)
11427 		    hasRefs++;
11428 	    } else if (IS_SCHEMA(child, "group")) {
11429 		part =
11430 		    xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11431 		if (part != NULL)
11432 		    hasRefs++;
11433 		/*
11434 		* Handle redefinitions.
11435 		*/
11436 		if (ctxt->isRedefine && ctxt->redef &&
11437 		    (ctxt->redef->item->type == XML_SCHEMA_TYPE_GROUP) &&
11438 		    part && part->children)
11439 		{
11440 		    if ((xmlSchemaGetQNameRefName(part->children) ==
11441 			    ctxt->redef->refName) &&
11442 			(xmlSchemaGetQNameRefTargetNs(part->children) ==
11443 			    ctxt->redef->refTargetNs))
11444 		    {
11445 			/*
11446 			* SPEC src-redefine:
11447 			* (6.1) "If it has a <group> among its contents at
11448 			* some level the `actual value` of whose ref
11449 			* [attribute] is the same as the `actual value` of
11450 			* its own name attribute plus target namespace, then
11451 			* all of the following must be true:"
11452 			* (6.1.1) "It must have exactly one such group."
11453 			*/
11454 			if (ctxt->redefCounter != 0) {
11455 			    xmlChar *str = NULL;
11456 
11457 			    xmlSchemaCustomErr(ACTXT_CAST ctxt,
11458 				XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11459 				"The redefining model group definition "
11460 				"'%s' must not contain more than one "
11461 				"reference to the redefined definition",
11462 				xmlSchemaFormatQName(&str,
11463 				    ctxt->redef->refTargetNs,
11464 				    ctxt->redef->refName),
11465 				NULL);
11466 			    FREE_AND_NULL(str)
11467 			    part = NULL;
11468 			} else if (((WXS_PARTICLE(part))->minOccurs != 1) ||
11469 			    ((WXS_PARTICLE(part))->maxOccurs != 1))
11470 			{
11471 			    xmlChar *str = NULL;
11472 			    /*
11473 			    * SPEC src-redefine:
11474 			    * (6.1.2) "The `actual value` of both that
11475 			    * group's minOccurs and maxOccurs [attribute]
11476 			    * must be 1 (or `absent`).
11477 			    */
11478 			    xmlSchemaCustomErr(ACTXT_CAST ctxt,
11479 				XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11480 				"The redefining model group definition "
11481 				"'%s' must not contain a reference to the "
11482 				"redefined definition with a "
11483 				"maxOccurs/minOccurs other than 1",
11484 				xmlSchemaFormatQName(&str,
11485 				    ctxt->redef->refTargetNs,
11486 				    ctxt->redef->refName),
11487 				NULL);
11488 			    FREE_AND_NULL(str)
11489 			    part = NULL;
11490 			}
11491 			ctxt->redef->reference = WXS_BASIC_CAST part;
11492 			ctxt->redefCounter++;
11493 		    }
11494 		}
11495 	    } else if (IS_SCHEMA(child, "any")) {
11496 		part = (xmlSchemaTreeItemPtr)
11497 		    xmlSchemaParseAny(ctxt, schema, child);
11498 	    } else if (IS_SCHEMA(child, "choice")) {
11499 		part = xmlSchemaParseModelGroup(ctxt, schema, child,
11500 		    XML_SCHEMA_TYPE_CHOICE, 1);
11501 	    } else if (IS_SCHEMA(child, "sequence")) {
11502 		part = xmlSchemaParseModelGroup(ctxt, schema, child,
11503 		    XML_SCHEMA_TYPE_SEQUENCE, 1);
11504 	    }
11505 	    if (part != NULL) {
11506 		if (last == NULL)
11507 		    item->children = part;
11508 		else
11509 		    last->next = part;
11510 		last = part;
11511 	    }
11512 	    child = child->next;
11513 	}
11514 	if (child != NULL) {
11515 	    xmlSchemaPContentErr(ctxt,
11516 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11517 		NULL, node, child, NULL,
11518 		"(annotation?, (element | group | choice | sequence | any)*)");
11519 	}
11520     }
11521     if ((max == 0) && (min == 0))
11522 	return (NULL);
11523     if (hasRefs) {
11524 	/*
11525 	* We need to resolve references.
11526 	*/
11527 	WXS_ADD_PENDING(ctxt, item);
11528     }
11529     if (withParticle)
11530 	return ((xmlSchemaTreeItemPtr) particle);
11531     else
11532 	return ((xmlSchemaTreeItemPtr) item);
11533 }
11534 
11535 /**
11536  * xmlSchemaParseRestriction:
11537  * @ctxt:  a schema validation context
11538  * @schema:  the schema being built
11539  * @node:  a subtree containing XML Schema informations
11540  *
11541  * parse a XML schema Restriction definition
11542  * *WARNING* this interface is highly subject to change
11543  *
11544  * Returns the type definition or NULL in case of error
11545  */
11546 static xmlSchemaTypePtr
xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,xmlSchemaTypeType parentType)11547 xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11548                           xmlNodePtr node, xmlSchemaTypeType parentType)
11549 {
11550     xmlSchemaTypePtr type;
11551     xmlNodePtr child = NULL;
11552     xmlAttrPtr attr;
11553 
11554     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11555         return (NULL);
11556     /* Not a component, don't create it. */
11557     type = ctxt->ctxtType;
11558     type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
11559 
11560     /*
11561     * Check for illegal attributes.
11562     */
11563     attr = node->properties;
11564     while (attr != NULL) {
11565 	if (attr->ns == NULL) {
11566 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11567 		(!xmlStrEqual(attr->name, BAD_CAST "base"))) {
11568 		xmlSchemaPIllegalAttrErr(ctxt,
11569 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11570 	    }
11571 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11572 	    xmlSchemaPIllegalAttrErr(ctxt,
11573 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11574 	}
11575 	attr = attr->next;
11576     }
11577     /*
11578     * Extract and validate attributes.
11579     */
11580     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11581     /*
11582     * Attribute
11583     */
11584     /*
11585     * Extract the base type. The "base" attribute is mandatory if inside
11586     * a complex type or if redefining.
11587     *
11588     * SPEC (1.2) "...otherwise (<restriction> has no <simpleType> "
11589     * among its [children]), the simple type definition which is
11590     * the {content type} of the type definition `resolved` to by
11591     * the `actual value` of the base [attribute]"
11592     */
11593     if (xmlSchemaPValAttrQName(ctxt, schema, NULL, node, "base",
11594 	&(type->baseNs), &(type->base)) == 0)
11595     {
11596 	if ((type->base == NULL) && (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
11597 	    xmlSchemaPMissingAttrErr(ctxt,
11598 		XML_SCHEMAP_S4S_ATTR_MISSING,
11599 		NULL, node, "base", NULL);
11600 	} else if ((ctxt->isRedefine) &&
11601 	    (type->flags & XML_SCHEMAS_TYPE_GLOBAL))
11602 	{
11603 	    if (type->base == NULL) {
11604 		xmlSchemaPMissingAttrErr(ctxt,
11605 		    XML_SCHEMAP_S4S_ATTR_MISSING,
11606 		    NULL, node, "base", NULL);
11607 	    } else if ((! xmlStrEqual(type->base, type->name)) ||
11608 		(! xmlStrEqual(type->baseNs, type->targetNamespace)))
11609 	    {
11610 		xmlChar *str1 = NULL, *str2 = NULL;
11611 		/*
11612 		* REDEFINE: SPEC src-redefine (5)
11613 		* "Within the [children], each <simpleType> must have a
11614 		* <restriction> among its [children] ... the `actual value` of
11615 		* whose base [attribute] must be the same as the `actual value`
11616 		* of its own name attribute plus target namespace;"
11617 		*/
11618 		xmlSchemaPCustomErrExt(ctxt, XML_SCHEMAP_SRC_REDEFINE,
11619 		    NULL, node, "This is a redefinition, but the QName "
11620 		    "value '%s' of the 'base' attribute does not match the "
11621 		    "type's designation '%s'",
11622 		    xmlSchemaFormatQName(&str1, type->baseNs, type->base),
11623 		    xmlSchemaFormatQName(&str2, type->targetNamespace,
11624 			type->name), NULL);
11625 		FREE_AND_NULL(str1);
11626 		FREE_AND_NULL(str2);
11627 		/* Avoid confusion and erase the values. */
11628 		type->base = NULL;
11629 		type->baseNs = NULL;
11630 	    }
11631 	}
11632     }
11633     /*
11634     * And now for the children...
11635     */
11636     child = node->children;
11637     if (IS_SCHEMA(child, "annotation")) {
11638 	/*
11639 	* Add the annotation to the simple type ancestor.
11640 	*/
11641 	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11642 	    xmlSchemaParseAnnotation(ctxt, child, 1));
11643         child = child->next;
11644     }
11645     if (parentType == XML_SCHEMA_TYPE_SIMPLE) {
11646 	/*
11647 	* Corresponds to <simpleType><restriction><simpleType>.
11648 	*/
11649 	if (IS_SCHEMA(child, "simpleType")) {
11650 	    if (type->base != NULL) {
11651 		/*
11652 		* src-restriction-base-or-simpleType
11653 		* Either the base [attribute] or the simpleType [child] of the
11654 		* <restriction> element must be present, but not both.
11655 		*/
11656 		xmlSchemaPContentErr(ctxt,
11657 		    XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
11658 		    NULL, node, child,
11659 		    "The attribute 'base' and the <simpleType> child are "
11660 		    "mutually exclusive", NULL);
11661 	    } else {
11662 		type->baseType = (xmlSchemaTypePtr)
11663 		    xmlSchemaParseSimpleType(ctxt, schema, child, 0);
11664 	    }
11665 	    child = child->next;
11666 	} else if (type->base == NULL) {
11667 	    xmlSchemaPContentErr(ctxt,
11668 		XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
11669 		NULL, node, child,
11670 		"Either the attribute 'base' or a <simpleType> child "
11671 		"must be present", NULL);
11672 	}
11673     } else if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11674 	/*
11675 	* Corresponds to <complexType><complexContent><restriction>...
11676 	* followed by:
11677 	*
11678 	* Model groups <all>, <choice> and <sequence>.
11679 	*/
11680 	if (IS_SCHEMA(child, "all")) {
11681 	    type->subtypes = (xmlSchemaTypePtr)
11682 		xmlSchemaParseModelGroup(ctxt, schema, child,
11683 		    XML_SCHEMA_TYPE_ALL, 1);
11684 	    child = child->next;
11685 	} else if (IS_SCHEMA(child, "choice")) {
11686 	    type->subtypes = (xmlSchemaTypePtr)
11687 		xmlSchemaParseModelGroup(ctxt,
11688 		    schema, child, XML_SCHEMA_TYPE_CHOICE, 1);
11689 	    child = child->next;
11690 	} else if (IS_SCHEMA(child, "sequence")) {
11691 	    type->subtypes = (xmlSchemaTypePtr)
11692 		xmlSchemaParseModelGroup(ctxt, schema, child,
11693 		    XML_SCHEMA_TYPE_SEQUENCE, 1);
11694 	    child = child->next;
11695 	/*
11696 	* Model group reference <group>.
11697 	*/
11698 	} else if (IS_SCHEMA(child, "group")) {
11699 	    type->subtypes = (xmlSchemaTypePtr)
11700 		xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11701 	    /*
11702 	    * Note that the reference will be resolved in
11703 	    * xmlSchemaResolveTypeReferences();
11704 	    */
11705 	    child = child->next;
11706 	}
11707     } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
11708 	/*
11709 	* Corresponds to <complexType><simpleContent><restriction>...
11710 	*
11711 	* "1.1 the simple type definition corresponding to the <simpleType>
11712 	* among the [children] of <restriction> if there is one;"
11713 	*/
11714 	if (IS_SCHEMA(child, "simpleType")) {
11715 	    /*
11716 	    * We will store the to-be-restricted simple type in
11717 	    * type->contentTypeDef *temporarily*.
11718 	    */
11719 	    type->contentTypeDef = (xmlSchemaTypePtr)
11720 		xmlSchemaParseSimpleType(ctxt, schema, child, 0);
11721 	    if ( type->contentTypeDef == NULL)
11722 		return (NULL);
11723 	    child = child->next;
11724 	}
11725     }
11726 
11727     if ((parentType == XML_SCHEMA_TYPE_SIMPLE) ||
11728 	(parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
11729 	xmlSchemaFacetPtr facet, lastfacet = NULL;
11730 	/*
11731 	* Corresponds to <complexType><simpleContent><restriction>...
11732 	* <simpleType><restriction>...
11733 	*/
11734 
11735 	/*
11736 	* Add the facets to the simple type ancestor.
11737 	*/
11738 	/*
11739 	* TODO: Datatypes: 4.1.3 Constraints on XML Representation of
11740 	* Simple Type Definition Schema Representation Constraint:
11741 	* *Single Facet Value*
11742 	*/
11743 	while ((IS_SCHEMA(child, "minInclusive")) ||
11744 	    (IS_SCHEMA(child, "minExclusive")) ||
11745 	    (IS_SCHEMA(child, "maxInclusive")) ||
11746 	    (IS_SCHEMA(child, "maxExclusive")) ||
11747 	    (IS_SCHEMA(child, "totalDigits")) ||
11748 	    (IS_SCHEMA(child, "fractionDigits")) ||
11749 	    (IS_SCHEMA(child, "pattern")) ||
11750 	    (IS_SCHEMA(child, "enumeration")) ||
11751 	    (IS_SCHEMA(child, "whiteSpace")) ||
11752 	    (IS_SCHEMA(child, "length")) ||
11753 	    (IS_SCHEMA(child, "maxLength")) ||
11754 	    (IS_SCHEMA(child, "minLength"))) {
11755 	    facet = xmlSchemaParseFacet(ctxt, schema, child);
11756 	    if (facet != NULL) {
11757 		if (lastfacet == NULL)
11758 		    type->facets = facet;
11759 		else
11760 		    lastfacet->next = facet;
11761 		lastfacet = facet;
11762 		lastfacet->next = NULL;
11763 	    }
11764 	    child = child->next;
11765 	}
11766 	/*
11767 	* Create links for derivation and validation.
11768 	*/
11769 	if (type->facets != NULL) {
11770 	    xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
11771 
11772 	    facet = type->facets;
11773 	    do {
11774 		facetLink = (xmlSchemaFacetLinkPtr)
11775 		    xmlMalloc(sizeof(xmlSchemaFacetLink));
11776 		if (facetLink == NULL) {
11777 		    xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
11778 		    xmlFree(facetLink);
11779 		    return (NULL);
11780 		}
11781 		facetLink->facet = facet;
11782 		facetLink->next = NULL;
11783 		if (lastFacetLink == NULL)
11784 		    type->facetSet = facetLink;
11785 		else
11786 		    lastFacetLink->next = facetLink;
11787 		lastFacetLink = facetLink;
11788 		facet = facet->next;
11789 	    } while (facet != NULL);
11790 	}
11791     }
11792     if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
11793 	/*
11794 	* Attribute uses/declarations.
11795 	*/
11796 	if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11797 	    (xmlSchemaItemListPtr *) &(type->attrUses),
11798 	    XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
11799 	    return(NULL);
11800 	/*
11801 	* Attribute wildcard.
11802 	*/
11803 	if (IS_SCHEMA(child, "anyAttribute")) {
11804 	    type->attributeWildcard =
11805 		xmlSchemaParseAnyAttribute(ctxt, schema, child);
11806 	    child = child->next;
11807 	}
11808     }
11809     if (child != NULL) {
11810 	if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11811 	    xmlSchemaPContentErr(ctxt,
11812 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11813 		NULL, node, child, NULL,
11814 		"annotation?, (group | all | choice | sequence)?, "
11815 		"((attribute | attributeGroup)*, anyAttribute?))");
11816 	} else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
11817 	     xmlSchemaPContentErr(ctxt,
11818 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11819 		NULL, node, child, NULL,
11820 		"(annotation?, (simpleType?, (minExclusive | minInclusive | "
11821 		"maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11822 		"length | minLength | maxLength | enumeration | whiteSpace | "
11823 		"pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
11824 	} else {
11825 	    /* Simple type */
11826 	    xmlSchemaPContentErr(ctxt,
11827 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11828 		NULL, node, child, NULL,
11829 		"(annotation?, (simpleType?, (minExclusive | minInclusive | "
11830 		"maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11831 		"length | minLength | maxLength | enumeration | whiteSpace | "
11832 		"pattern)*))");
11833 	}
11834     }
11835     return (NULL);
11836 }
11837 
11838 /**
11839  * xmlSchemaParseExtension:
11840  * @ctxt:  a schema validation context
11841  * @schema:  the schema being built
11842  * @node:  a subtree containing XML Schema informations
11843  *
11844  * Parses an <extension>, which is found inside a
11845  * <simpleContent> or <complexContent>.
11846  * *WARNING* this interface is highly subject to change.
11847  *
11848  * TODO: Returns the type definition or NULL in case of error
11849  */
11850 static xmlSchemaTypePtr
xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,xmlSchemaTypeType parentType)11851 xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11852                         xmlNodePtr node, xmlSchemaTypeType parentType)
11853 {
11854     xmlSchemaTypePtr type;
11855     xmlNodePtr child = NULL;
11856     xmlAttrPtr attr;
11857 
11858     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11859         return (NULL);
11860     /* Not a component, don't create it. */
11861     type = ctxt->ctxtType;
11862     type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
11863 
11864     /*
11865     * Check for illegal attributes.
11866     */
11867     attr = node->properties;
11868     while (attr != NULL) {
11869 	if (attr->ns == NULL) {
11870 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11871 		(!xmlStrEqual(attr->name, BAD_CAST "base"))) {
11872 		xmlSchemaPIllegalAttrErr(ctxt,
11873 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11874 	    }
11875 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11876 	    xmlSchemaPIllegalAttrErr(ctxt,
11877 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11878 	}
11879 	attr = attr->next;
11880     }
11881 
11882     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11883 
11884     /*
11885     * Attribute "base" - mandatory.
11886     */
11887     if ((xmlSchemaPValAttrQName(ctxt, schema, NULL, node,
11888 	"base", &(type->baseNs), &(type->base)) == 0) &&
11889 	(type->base == NULL)) {
11890 	xmlSchemaPMissingAttrErr(ctxt,
11891 	    XML_SCHEMAP_S4S_ATTR_MISSING,
11892 	    NULL, node, "base", NULL);
11893     }
11894     /*
11895     * And now for the children...
11896     */
11897     child = node->children;
11898     if (IS_SCHEMA(child, "annotation")) {
11899 	/*
11900 	* Add the annotation to the type ancestor.
11901 	*/
11902 	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11903 	    xmlSchemaParseAnnotation(ctxt, child, 1));
11904         child = child->next;
11905     }
11906     if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11907 	/*
11908 	* Corresponds to <complexType><complexContent><extension>... and:
11909 	*
11910 	* Model groups <all>, <choice>, <sequence> and <group>.
11911 	*/
11912 	if (IS_SCHEMA(child, "all")) {
11913 	    type->subtypes = (xmlSchemaTypePtr)
11914 		xmlSchemaParseModelGroup(ctxt, schema,
11915 		    child, XML_SCHEMA_TYPE_ALL, 1);
11916 	    child = child->next;
11917 	} else if (IS_SCHEMA(child, "choice")) {
11918 	    type->subtypes = (xmlSchemaTypePtr)
11919 		xmlSchemaParseModelGroup(ctxt, schema,
11920 		    child, XML_SCHEMA_TYPE_CHOICE, 1);
11921 	    child = child->next;
11922 	} else if (IS_SCHEMA(child, "sequence")) {
11923 	    type->subtypes = (xmlSchemaTypePtr)
11924 		xmlSchemaParseModelGroup(ctxt, schema,
11925 		child, XML_SCHEMA_TYPE_SEQUENCE, 1);
11926 	    child = child->next;
11927 	} else if (IS_SCHEMA(child, "group")) {
11928 	    type->subtypes = (xmlSchemaTypePtr)
11929 		xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11930 	    /*
11931 	    * Note that the reference will be resolved in
11932 	    * xmlSchemaResolveTypeReferences();
11933 	    */
11934 	    child = child->next;
11935 	}
11936     }
11937     if (child != NULL) {
11938 	/*
11939 	* Attribute uses/declarations.
11940 	*/
11941 	if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11942 	    (xmlSchemaItemListPtr *) &(type->attrUses),
11943 	    XML_SCHEMA_TYPE_EXTENSION, NULL) == -1)
11944 	    return(NULL);
11945 	/*
11946 	* Attribute wildcard.
11947 	*/
11948 	if (IS_SCHEMA(child, "anyAttribute")) {
11949 	    ctxt->ctxtType->attributeWildcard =
11950 		xmlSchemaParseAnyAttribute(ctxt, schema, child);
11951 	    child = child->next;
11952 	}
11953     }
11954     if (child != NULL) {
11955 	if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11956 	    /* Complex content extension. */
11957 	    xmlSchemaPContentErr(ctxt,
11958 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11959 		NULL, node, child, NULL,
11960 		"(annotation?, ((group | all | choice | sequence)?, "
11961 		"((attribute | attributeGroup)*, anyAttribute?)))");
11962 	} else {
11963 	    /* Simple content extension. */
11964 	    xmlSchemaPContentErr(ctxt,
11965 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11966 		NULL, node, child, NULL,
11967 		"(annotation?, ((attribute | attributeGroup)*, "
11968 		"anyAttribute?))");
11969 	}
11970     }
11971     return (NULL);
11972 }
11973 
11974 /**
11975  * xmlSchemaParseSimpleContent:
11976  * @ctxt:  a schema validation context
11977  * @schema:  the schema being built
11978  * @node:  a subtree containing XML Schema informations
11979  *
11980  * parse a XML schema SimpleContent definition
11981  * *WARNING* this interface is highly subject to change
11982  *
11983  * Returns the type definition or NULL in case of error
11984  */
11985 static int
xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,int * hasRestrictionOrExtension)11986 xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
11987                             xmlSchemaPtr schema, xmlNodePtr node,
11988 			    int *hasRestrictionOrExtension)
11989 {
11990     xmlSchemaTypePtr type;
11991     xmlNodePtr child = NULL;
11992     xmlAttrPtr attr;
11993 
11994     if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
11995 	(hasRestrictionOrExtension == NULL))
11996         return (-1);
11997     *hasRestrictionOrExtension = 0;
11998     /* Not a component, don't create it. */
11999     type = ctxt->ctxtType;
12000     type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
12001     /*
12002     * Check for illegal attributes.
12003     */
12004     attr = node->properties;
12005     while (attr != NULL) {
12006 	if (attr->ns == NULL) {
12007 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id"))) {
12008 		xmlSchemaPIllegalAttrErr(ctxt,
12009 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12010 	    }
12011 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
12012 	    xmlSchemaPIllegalAttrErr(ctxt,
12013 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12014 	}
12015 	attr = attr->next;
12016     }
12017 
12018     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
12019 
12020     /*
12021     * And now for the children...
12022     */
12023     child = node->children;
12024     if (IS_SCHEMA(child, "annotation")) {
12025 	/*
12026 	* Add the annotation to the complex type ancestor.
12027 	*/
12028 	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
12029 	    xmlSchemaParseAnnotation(ctxt, child, 1));
12030         child = child->next;
12031     }
12032     if (child == NULL) {
12033 	xmlSchemaPContentErr(ctxt,
12034 	    XML_SCHEMAP_S4S_ELEM_MISSING,
12035 	    NULL, node, NULL, NULL,
12036 	    "(annotation?, (restriction | extension))");
12037     }
12038     if (child == NULL) {
12039 	xmlSchemaPContentErr(ctxt,
12040 	    XML_SCHEMAP_S4S_ELEM_MISSING,
12041 	    NULL, node, NULL, NULL,
12042 	    "(annotation?, (restriction | extension))");
12043     }
12044     if (IS_SCHEMA(child, "restriction")) {
12045         xmlSchemaParseRestriction(ctxt, schema, child,
12046 	    XML_SCHEMA_TYPE_SIMPLE_CONTENT);
12047 	(*hasRestrictionOrExtension) = 1;
12048         child = child->next;
12049     } else if (IS_SCHEMA(child, "extension")) {
12050         xmlSchemaParseExtension(ctxt, schema, child,
12051 	    XML_SCHEMA_TYPE_SIMPLE_CONTENT);
12052 	(*hasRestrictionOrExtension) = 1;
12053         child = child->next;
12054     }
12055     if (child != NULL) {
12056 	xmlSchemaPContentErr(ctxt,
12057 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
12058 	    NULL, node, child, NULL,
12059 	    "(annotation?, (restriction | extension))");
12060     }
12061     return (0);
12062 }
12063 
12064 /**
12065  * xmlSchemaParseComplexContent:
12066  * @ctxt:  a schema validation context
12067  * @schema:  the schema being built
12068  * @node:  a subtree containing XML Schema informations
12069  *
12070  * parse a XML schema ComplexContent definition
12071  * *WARNING* this interface is highly subject to change
12072  *
12073  * Returns the type definition or NULL in case of error
12074  */
12075 static int
xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,int * hasRestrictionOrExtension)12076 xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
12077                              xmlSchemaPtr schema, xmlNodePtr node,
12078 			     int *hasRestrictionOrExtension)
12079 {
12080     xmlSchemaTypePtr type;
12081     xmlNodePtr child = NULL;
12082     xmlAttrPtr attr;
12083 
12084     if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
12085 	(hasRestrictionOrExtension == NULL))
12086         return (-1);
12087     *hasRestrictionOrExtension = 0;
12088     /* Not a component, don't create it. */
12089     type = ctxt->ctxtType;
12090     /*
12091     * Check for illegal attributes.
12092     */
12093     attr = node->properties;
12094     while (attr != NULL) {
12095 	if (attr->ns == NULL) {
12096 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
12097 		(!xmlStrEqual(attr->name, BAD_CAST "mixed")))
12098 	    {
12099 		xmlSchemaPIllegalAttrErr(ctxt,
12100 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12101 	    }
12102 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
12103 	    xmlSchemaPIllegalAttrErr(ctxt,
12104 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12105 	}
12106 	attr = attr->next;
12107     }
12108 
12109     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
12110 
12111     /*
12112     * Set the 'mixed' on the complex type ancestor.
12113     */
12114     if (xmlGetBooleanProp(ctxt, node, "mixed", 0))  {
12115 	if ((type->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
12116 	    type->flags |= XML_SCHEMAS_TYPE_MIXED;
12117     }
12118     child = node->children;
12119     if (IS_SCHEMA(child, "annotation")) {
12120 	/*
12121 	* Add the annotation to the complex type ancestor.
12122 	*/
12123 	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
12124 	    xmlSchemaParseAnnotation(ctxt, child, 1));
12125         child = child->next;
12126     }
12127     if (child == NULL) {
12128 	xmlSchemaPContentErr(ctxt,
12129 	    XML_SCHEMAP_S4S_ELEM_MISSING,
12130 	    NULL, node, NULL,
12131 	    NULL, "(annotation?, (restriction | extension))");
12132     }
12133     if (child == NULL) {
12134 	xmlSchemaPContentErr(ctxt,
12135 	    XML_SCHEMAP_S4S_ELEM_MISSING,
12136 	    NULL, node, NULL,
12137 	    NULL, "(annotation?, (restriction | extension))");
12138     }
12139     if (IS_SCHEMA(child, "restriction")) {
12140         xmlSchemaParseRestriction(ctxt, schema, child,
12141 	    XML_SCHEMA_TYPE_COMPLEX_CONTENT);
12142 	(*hasRestrictionOrExtension) = 1;
12143         child = child->next;
12144     } else if (IS_SCHEMA(child, "extension")) {
12145         xmlSchemaParseExtension(ctxt, schema, child,
12146 	    XML_SCHEMA_TYPE_COMPLEX_CONTENT);
12147 	(*hasRestrictionOrExtension) = 1;
12148         child = child->next;
12149     }
12150     if (child != NULL) {
12151 	xmlSchemaPContentErr(ctxt,
12152 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
12153 	    NULL, node, child,
12154 	    NULL, "(annotation?, (restriction | extension))");
12155     }
12156     return (0);
12157 }
12158 
12159 /**
12160  * xmlSchemaParseComplexType:
12161  * @ctxt:  a schema validation context
12162  * @schema:  the schema being built
12163  * @node:  a subtree containing XML Schema informations
12164  *
12165  * parse a XML schema Complex Type definition
12166  * *WARNING* this interface is highly subject to change
12167  *
12168  * Returns the type definition or NULL in case of error
12169  */
12170 static xmlSchemaTypePtr
xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,int topLevel)12171 xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
12172                           xmlNodePtr node, int topLevel)
12173 {
12174     xmlSchemaTypePtr type, ctxtType;
12175     xmlNodePtr child = NULL;
12176     const xmlChar *name = NULL;
12177     xmlAttrPtr attr;
12178     const xmlChar *attrValue;
12179 #ifdef ENABLE_NAMED_LOCALS
12180     char buf[40];
12181 #endif
12182     int final = 0, block = 0, hasRestrictionOrExtension = 0;
12183 
12184 
12185     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
12186         return (NULL);
12187 
12188     ctxtType = ctxt->ctxtType;
12189 
12190     if (topLevel) {
12191 	attr = xmlSchemaGetPropNode(node, "name");
12192 	if (attr == NULL) {
12193 	    xmlSchemaPMissingAttrErr(ctxt,
12194 		XML_SCHEMAP_S4S_ATTR_MISSING, NULL, node, "name", NULL);
12195 	    return (NULL);
12196 	} else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
12197 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
12198 	    return (NULL);
12199 	}
12200     }
12201 
12202     if (topLevel == 0) {
12203 	/*
12204 	* Parse as local complex type definition.
12205 	*/
12206 #ifdef ENABLE_NAMED_LOCALS
12207         snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
12208 	type = xmlSchemaAddType(ctxt, schema,
12209 	    XML_SCHEMA_TYPE_COMPLEX,
12210 	    xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
12211 	    ctxt->targetNamespace, node, 0);
12212 #else
12213 	type = xmlSchemaAddType(ctxt, schema,
12214 	    XML_SCHEMA_TYPE_COMPLEX,
12215 	    NULL, ctxt->targetNamespace, node, 0);
12216 #endif
12217 	if (type == NULL)
12218 	    return (NULL);
12219 	name = type->name;
12220 	type->node = node;
12221 	type->type = XML_SCHEMA_TYPE_COMPLEX;
12222 	/*
12223 	* TODO: We need the target namespace.
12224 	*/
12225     } else {
12226 	/*
12227 	* Parse as global complex type definition.
12228 	*/
12229 	type = xmlSchemaAddType(ctxt, schema,
12230 	    XML_SCHEMA_TYPE_COMPLEX,
12231 	    name, ctxt->targetNamespace, node, 1);
12232 	if (type == NULL)
12233 	    return (NULL);
12234 	type->node = node;
12235 	type->type = XML_SCHEMA_TYPE_COMPLEX;
12236 	type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
12237     }
12238     type->targetNamespace = ctxt->targetNamespace;
12239     /*
12240     * Handle attributes.
12241     */
12242     attr = node->properties;
12243     while (attr != NULL) {
12244 	if (attr->ns == NULL) {
12245 	    if (xmlStrEqual(attr->name, BAD_CAST "id")) {
12246 		/*
12247 		* Attribute "id".
12248 		*/
12249 		xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
12250 	    } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
12251 		/*
12252 		* Attribute "mixed".
12253 		*/
12254 		if (xmlSchemaPGetBoolNodeValue(ctxt,
12255 			NULL, (xmlNodePtr) attr))
12256 		    type->flags |= XML_SCHEMAS_TYPE_MIXED;
12257 	    } else if (topLevel) {
12258 		/*
12259 		* Attributes of global complex type definitions.
12260 		*/
12261 		if (xmlStrEqual(attr->name, BAD_CAST "name")) {
12262 		    /* Pass. */
12263 		} else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
12264 		    /*
12265 		    * Attribute "abstract".
12266 		    */
12267 		    if (xmlSchemaPGetBoolNodeValue(ctxt,
12268 			    NULL, (xmlNodePtr) attr))
12269 			type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
12270 		} else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
12271 		    /*
12272 		    * Attribute "final".
12273 		    */
12274 		    attrValue = xmlSchemaGetNodeContent(ctxt,
12275 			(xmlNodePtr) attr);
12276 		    if (xmlSchemaPValAttrBlockFinal(attrValue,
12277 			&(type->flags),
12278 			-1,
12279 			XML_SCHEMAS_TYPE_FINAL_EXTENSION,
12280 			XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
12281 			-1, -1, -1) != 0)
12282 		    {
12283 			xmlSchemaPSimpleTypeErr(ctxt,
12284 			    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
12285 			    NULL, (xmlNodePtr) attr, NULL,
12286 			    "(#all | List of (extension | restriction))",
12287 			    attrValue, NULL, NULL, NULL);
12288 		    } else
12289 			final = 1;
12290 		} else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
12291 		    /*
12292 		    * Attribute "block".
12293 		    */
12294 		    attrValue = xmlSchemaGetNodeContent(ctxt,
12295 			(xmlNodePtr) attr);
12296 		    if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
12297 			-1,
12298 			XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
12299 			XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
12300 			-1, -1, -1) != 0) {
12301 			xmlSchemaPSimpleTypeErr(ctxt,
12302 			    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
12303 			    NULL, (xmlNodePtr) attr, NULL,
12304 			    "(#all | List of (extension | restriction)) ",
12305 			    attrValue, NULL, NULL, NULL);
12306 		    } else
12307 			block = 1;
12308 		} else {
12309 			xmlSchemaPIllegalAttrErr(ctxt,
12310 			    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12311 		}
12312 	    } else {
12313 		xmlSchemaPIllegalAttrErr(ctxt,
12314 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12315 	    }
12316 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
12317 	    xmlSchemaPIllegalAttrErr(ctxt,
12318 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12319 	}
12320 	attr = attr->next;
12321     }
12322     if (! block) {
12323 	/*
12324 	* Apply default "block" values.
12325 	*/
12326 	if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
12327 	    type->flags |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
12328 	if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
12329 	    type->flags |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
12330     }
12331     if (! final) {
12332 	/*
12333 	* Apply default "block" values.
12334 	*/
12335 	if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
12336 	    type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
12337 	if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
12338 	    type->flags |= XML_SCHEMAS_TYPE_FINAL_EXTENSION;
12339     }
12340     /*
12341     * And now for the children...
12342     */
12343     child = node->children;
12344     if (IS_SCHEMA(child, "annotation")) {
12345         type->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
12346         child = child->next;
12347     }
12348     ctxt->ctxtType = type;
12349     if (IS_SCHEMA(child, "simpleContent")) {
12350 	/*
12351 	* <complexType><simpleContent>...
12352 	* 3.4.3 : 2.2
12353 	* Specifying mixed='true' when the <simpleContent>
12354 	* alternative is chosen has no effect
12355 	*/
12356 	if (type->flags & XML_SCHEMAS_TYPE_MIXED)
12357 	    type->flags ^= XML_SCHEMAS_TYPE_MIXED;
12358         xmlSchemaParseSimpleContent(ctxt, schema, child,
12359 	    &hasRestrictionOrExtension);
12360         child = child->next;
12361     } else if (IS_SCHEMA(child, "complexContent")) {
12362 	/*
12363 	* <complexType><complexContent>...
12364 	*/
12365 	type->contentType = XML_SCHEMA_CONTENT_EMPTY;
12366         xmlSchemaParseComplexContent(ctxt, schema, child,
12367 	    &hasRestrictionOrExtension);
12368         child = child->next;
12369     } else {
12370 	/*
12371 	* E.g <complexType><sequence>... or <complexType><attribute>... etc.
12372 	*
12373 	* SPEC
12374 	* "...the third alternative (neither <simpleContent> nor
12375 	* <complexContent>) is chosen. This case is understood as shorthand
12376 	* for complex content restricting the `ur-type definition`, and the
12377 	* details of the mappings should be modified as necessary.
12378 	*/
12379 	type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
12380 	type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
12381 	/*
12382 	* Parse model groups.
12383 	*/
12384         if (IS_SCHEMA(child, "all")) {
12385             type->subtypes = (xmlSchemaTypePtr)
12386 		xmlSchemaParseModelGroup(ctxt, schema, child,
12387 		    XML_SCHEMA_TYPE_ALL, 1);
12388             child = child->next;
12389         } else if (IS_SCHEMA(child, "choice")) {
12390             type->subtypes = (xmlSchemaTypePtr)
12391 		xmlSchemaParseModelGroup(ctxt, schema, child,
12392 		    XML_SCHEMA_TYPE_CHOICE, 1);
12393             child = child->next;
12394         } else if (IS_SCHEMA(child, "sequence")) {
12395             type->subtypes = (xmlSchemaTypePtr)
12396 		xmlSchemaParseModelGroup(ctxt, schema, child,
12397 		    XML_SCHEMA_TYPE_SEQUENCE, 1);
12398             child = child->next;
12399         } else if (IS_SCHEMA(child, "group")) {
12400             type->subtypes = (xmlSchemaTypePtr)
12401 		xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
12402 	    /*
12403 	    * Note that the reference will be resolved in
12404 	    * xmlSchemaResolveTypeReferences();
12405 	    */
12406             child = child->next;
12407         }
12408 	/*
12409 	* Parse attribute decls/refs.
12410 	*/
12411         if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
12412 	    (xmlSchemaItemListPtr *) &(type->attrUses),
12413 	    XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
12414 	    return(NULL);
12415 	/*
12416 	* Parse attribute wildcard.
12417 	*/
12418 	if (IS_SCHEMA(child, "anyAttribute")) {
12419 	    type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
12420 	    child = child->next;
12421 	}
12422     }
12423     if (child != NULL) {
12424 	xmlSchemaPContentErr(ctxt,
12425 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
12426 	    NULL, node, child,
12427 	    NULL, "(annotation?, (simpleContent | complexContent | "
12428 	    "((group | all | choice | sequence)?, ((attribute | "
12429 	    "attributeGroup)*, anyAttribute?))))");
12430     }
12431     /*
12432     * REDEFINE: SPEC src-redefine (5)
12433     */
12434     if (topLevel && ctxt->isRedefine && (! hasRestrictionOrExtension)) {
12435 	xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
12436 	    NULL, node, "This is a redefinition, thus the "
12437 	    "<complexType> must have a <restriction> or <extension> "
12438 	    "grand-child", NULL);
12439     }
12440     ctxt->ctxtType = ctxtType;
12441     return (type);
12442 }
12443 
12444 /************************************************************************
12445  *									*
12446  *			Validating using Schemas			*
12447  *									*
12448  ************************************************************************/
12449 
12450 /************************************************************************
12451  *									*
12452  *			Reading/Writing Schemas				*
12453  *									*
12454  ************************************************************************/
12455 
12456 #if 0 /* Will be enabled if it is clear what options are needed. */
12457 /**
12458  * xmlSchemaParserCtxtSetOptions:
12459  * @ctxt:	a schema parser context
12460  * @options: a combination of xmlSchemaParserOption
12461  *
12462  * Sets the options to be used during the parse.
12463  *
12464  * Returns 0 in case of success, -1 in case of an
12465  * API error.
12466  */
12467 static int
12468 xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
12469 			      int options)
12470 
12471 {
12472     int i;
12473 
12474     if (ctxt == NULL)
12475 	return (-1);
12476     /*
12477     * WARNING: Change the start value if adding to the
12478     * xmlSchemaParseOption.
12479     */
12480     for (i = 1; i < (int) sizeof(int) * 8; i++) {
12481         if (options & 1<<i) {
12482 	    return (-1);
12483         }
12484     }
12485     ctxt->options = options;
12486     return (0);
12487 }
12488 
12489 /**
12490  * xmlSchemaValidCtxtGetOptions:
12491  * @ctxt: a schema parser context
12492  *
12493  * Returns the option combination of the parser context.
12494  */
12495 static int
12496 xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
12497 
12498 {
12499     if (ctxt == NULL)
12500 	return (-1);
12501     else
12502 	return (ctxt->options);
12503 }
12504 #endif
12505 
12506 /**
12507  * xmlSchemaNewParserCtxt:
12508  * @URL:  the location of the schema
12509  *
12510  * Create an XML Schemas parse context for that file/resource expected
12511  * to contain an XML Schemas file.
12512  *
12513  * Returns the parser context or NULL in case of error
12514  */
12515 xmlSchemaParserCtxtPtr
xmlSchemaNewParserCtxt(const char * URL)12516 xmlSchemaNewParserCtxt(const char *URL)
12517 {
12518     xmlSchemaParserCtxtPtr ret;
12519 
12520     if (URL == NULL)
12521         return (NULL);
12522 
12523     ret = xmlSchemaParserCtxtCreate();
12524     if (ret == NULL)
12525 	return(NULL);
12526     ret->dict = xmlDictCreate();
12527     ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
12528     return (ret);
12529 }
12530 
12531 /**
12532  * xmlSchemaNewMemParserCtxt:
12533  * @buffer:  a pointer to a char array containing the schemas
12534  * @size:  the size of the array
12535  *
12536  * Create an XML Schemas parse context for that memory buffer expected
12537  * to contain an XML Schemas file.
12538  *
12539  * Returns the parser context or NULL in case of error
12540  */
12541 xmlSchemaParserCtxtPtr
xmlSchemaNewMemParserCtxt(const char * buffer,int size)12542 xmlSchemaNewMemParserCtxt(const char *buffer, int size)
12543 {
12544     xmlSchemaParserCtxtPtr ret;
12545 
12546     if ((buffer == NULL) || (size <= 0))
12547         return (NULL);
12548     ret = xmlSchemaParserCtxtCreate();
12549     if (ret == NULL)
12550 	return(NULL);
12551     ret->buffer = buffer;
12552     ret->size = size;
12553     ret->dict = xmlDictCreate();
12554     return (ret);
12555 }
12556 
12557 /**
12558  * xmlSchemaNewDocParserCtxt:
12559  * @doc:  a preparsed document tree
12560  *
12561  * Create an XML Schemas parse context for that document.
12562  * NB. The document may be modified during the parsing process.
12563  *
12564  * Returns the parser context or NULL in case of error
12565  */
12566 xmlSchemaParserCtxtPtr
xmlSchemaNewDocParserCtxt(xmlDocPtr doc)12567 xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
12568 {
12569     xmlSchemaParserCtxtPtr ret;
12570 
12571     if (doc == NULL)
12572       return (NULL);
12573     ret = xmlSchemaParserCtxtCreate();
12574     if (ret == NULL)
12575 	return(NULL);
12576     ret->doc = doc;
12577     ret->dict = xmlDictCreate();
12578     /* The application has responsibility for the document */
12579     ret->preserve = 1;
12580 
12581     return (ret);
12582 }
12583 
12584 /**
12585  * xmlSchemaFreeParserCtxt:
12586  * @ctxt:  the schema parser context
12587  *
12588  * Free the resources associated to the schema parser context
12589  */
12590 void
xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)12591 xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
12592 {
12593     if (ctxt == NULL)
12594         return;
12595     if (ctxt->doc != NULL && !ctxt->preserve)
12596         xmlFreeDoc(ctxt->doc);
12597     if (ctxt->vctxt != NULL) {
12598 	xmlSchemaFreeValidCtxt(ctxt->vctxt);
12599     }
12600     if (ctxt->ownsConstructor && (ctxt->constructor != NULL)) {
12601 	xmlSchemaConstructionCtxtFree(ctxt->constructor);
12602 	ctxt->constructor = NULL;
12603 	ctxt->ownsConstructor = 0;
12604     }
12605     if (ctxt->attrProhibs != NULL)
12606 	xmlSchemaItemListFree(ctxt->attrProhibs);
12607     xmlDictFree(ctxt->dict);
12608     xmlFree(ctxt);
12609 }
12610 
12611 /************************************************************************
12612  *									*
12613  *			Building the content models			*
12614  *									*
12615  ************************************************************************/
12616 
12617 /**
12618  * xmlSchemaBuildContentModelForSubstGroup:
12619  *
12620  * Returns 1 if nillable, 0 otherwise
12621  */
12622 static int
xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,xmlSchemaParticlePtr particle,int counter,xmlAutomataStatePtr end)12623 xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,
12624 	xmlSchemaParticlePtr particle, int counter, xmlAutomataStatePtr end)
12625 {
12626     xmlAutomataStatePtr start, tmp;
12627     xmlSchemaElementPtr elemDecl, member;
12628     xmlSchemaSubstGroupPtr substGroup;
12629     int i;
12630     int ret = 0;
12631 
12632     elemDecl = (xmlSchemaElementPtr) particle->children;
12633     /*
12634     * Wrap the substitution group with a CHOICE.
12635     */
12636     start = pctxt->state;
12637     if (end == NULL)
12638 	end = xmlAutomataNewState(pctxt->am);
12639     substGroup = xmlSchemaSubstGroupGet(pctxt, elemDecl);
12640     if (substGroup == NULL) {
12641 	xmlSchemaPErr(pctxt, WXS_ITEM_NODE(particle),
12642 	    XML_SCHEMAP_INTERNAL,
12643 	    "Internal error: xmlSchemaBuildContentModelForSubstGroup, "
12644 	    "declaration is marked having a subst. group but none "
12645 	    "available.\n", elemDecl->name, NULL);
12646 	return(0);
12647     }
12648     if (counter >= 0) {
12649 	/*
12650 	* NOTE that we put the declaration in, even if it's abstract.
12651 	* However, an error will be raised during *validation* if an element
12652 	* information item shall be validated against an abstract element
12653 	* declaration.
12654 	*/
12655 	tmp = xmlAutomataNewCountedTrans(pctxt->am, start, NULL, counter);
12656         xmlAutomataNewTransition2(pctxt->am, tmp, end,
12657 	            elemDecl->name, elemDecl->targetNamespace, elemDecl);
12658 	/*
12659 	* Add subst. group members.
12660 	*/
12661 	for (i = 0; i < substGroup->members->nbItems; i++) {
12662 	    member = (xmlSchemaElementPtr) substGroup->members->items[i];
12663             xmlAutomataNewTransition2(pctxt->am, tmp, end,
12664 		               member->name, member->targetNamespace, member);
12665 	}
12666     } else if (particle->maxOccurs == 1) {
12667 	/*
12668 	* NOTE that we put the declaration in, even if it's abstract,
12669 	*/
12670 	xmlAutomataNewEpsilon(pctxt->am,
12671 	    xmlAutomataNewTransition2(pctxt->am,
12672 	    start, NULL,
12673 	    elemDecl->name, elemDecl->targetNamespace, elemDecl), end);
12674 	/*
12675 	* Add subst. group members.
12676 	*/
12677 	for (i = 0; i < substGroup->members->nbItems; i++) {
12678 	    member = (xmlSchemaElementPtr) substGroup->members->items[i];
12679 	    /*
12680 	    * NOTE: This fixes bug #341150. xmlAutomataNewOnceTrans2()
12681 	    *  was incorrectly used instead of xmlAutomataNewTransition2()
12682 	    *  (seems like a copy&paste bug from the XML_SCHEMA_TYPE_ALL
12683 	    *  section in xmlSchemaBuildAContentModel() ).
12684 	    * TODO: Check if xmlAutomataNewOnceTrans2() was instead
12685 	    *  intended for the above "counter" section originally. I.e.,
12686 	    *  check xs:all with subst-groups.
12687 	    *
12688 	    * tmp = xmlAutomataNewOnceTrans2(pctxt->am, start, NULL,
12689 	    *	               member->name, member->targetNamespace,
12690 	    *		       1, 1, member);
12691 	    */
12692 	    tmp = xmlAutomataNewTransition2(pctxt->am, start, NULL,
12693 		member->name, member->targetNamespace, member);
12694 	    xmlAutomataNewEpsilon(pctxt->am, tmp, end);
12695 	}
12696     } else {
12697 	xmlAutomataStatePtr hop;
12698 	int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12699 	    UNBOUNDED : particle->maxOccurs - 1;
12700 	int minOccurs = particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12701 
12702 	counter =
12703 	    xmlAutomataNewCounter(pctxt->am, minOccurs,
12704 	    maxOccurs);
12705 	hop = xmlAutomataNewState(pctxt->am);
12706 
12707 	xmlAutomataNewEpsilon(pctxt->am,
12708 	    xmlAutomataNewTransition2(pctxt->am,
12709 	    start, NULL,
12710 	    elemDecl->name, elemDecl->targetNamespace, elemDecl),
12711 	    hop);
12712 	/*
12713 	 * Add subst. group members.
12714 	 */
12715 	for (i = 0; i < substGroup->members->nbItems; i++) {
12716 	    member = (xmlSchemaElementPtr) substGroup->members->items[i];
12717 	    xmlAutomataNewEpsilon(pctxt->am,
12718 		xmlAutomataNewTransition2(pctxt->am,
12719 		start, NULL,
12720 		member->name, member->targetNamespace, member),
12721 		hop);
12722 	}
12723 	xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12724 	xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12725     }
12726     if (particle->minOccurs == 0) {
12727 	xmlAutomataNewEpsilon(pctxt->am, start, end);
12728         ret = 1;
12729     }
12730     pctxt->state = end;
12731     return(ret);
12732 }
12733 
12734 /**
12735  * xmlSchemaBuildContentModelForElement:
12736  *
12737  * Returns 1 if nillable, 0 otherwise
12738  */
12739 static int
xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr particle)12740 xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,
12741 				     xmlSchemaParticlePtr particle)
12742 {
12743     int ret = 0;
12744 
12745     if (((xmlSchemaElementPtr) particle->children)->flags &
12746 	XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
12747 	/*
12748 	* Substitution groups.
12749 	*/
12750 	ret = xmlSchemaBuildContentModelForSubstGroup(ctxt, particle, -1, NULL);
12751     } else {
12752 	xmlSchemaElementPtr elemDecl;
12753 	xmlAutomataStatePtr start;
12754 
12755 	elemDecl = (xmlSchemaElementPtr) particle->children;
12756 
12757 	if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT)
12758 	    return(0);
12759 	if (particle->maxOccurs == 1) {
12760 	    start = ctxt->state;
12761 	    ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12762 		    elemDecl->name, elemDecl->targetNamespace, elemDecl);
12763 	} else if ((particle->maxOccurs >= UNBOUNDED) &&
12764 	           (particle->minOccurs < 2)) {
12765 	    /* Special case. */
12766 	    start = ctxt->state;
12767 	    ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12768 		elemDecl->name, elemDecl->targetNamespace, elemDecl);
12769 	    ctxt->state = xmlAutomataNewTransition2(ctxt->am, ctxt->state, ctxt->state,
12770 		elemDecl->name, elemDecl->targetNamespace, elemDecl);
12771 	} else {
12772 	    int counter;
12773 	    int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12774 			    UNBOUNDED : particle->maxOccurs - 1;
12775 	    int minOccurs = particle->minOccurs < 1 ?
12776 			    0 : particle->minOccurs - 1;
12777 
12778 	    start = xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
12779 	    counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
12780 	    ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12781 		elemDecl->name, elemDecl->targetNamespace, elemDecl);
12782 	    xmlAutomataNewCountedTrans(ctxt->am, ctxt->state, start, counter);
12783 	    ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, ctxt->state,
12784 		NULL, counter);
12785 	}
12786 	if (particle->minOccurs == 0) {
12787 	    xmlAutomataNewEpsilon(ctxt->am, start, ctxt->state);
12788             ret = 1;
12789         }
12790     }
12791     return(ret);
12792 }
12793 
12794 /**
12795  * xmlSchemaBuildAContentModel:
12796  * @ctxt:  the schema parser context
12797  * @particle:  the particle component
12798  * @name:  the complex type's name whose content is being built
12799  *
12800  * Create the automaton for the {content type} of a complex type.
12801  *
12802  * Returns 1 if the content is nillable, 0 otherwise
12803  */
12804 static int
xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,xmlSchemaParticlePtr particle)12805 xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,
12806 			    xmlSchemaParticlePtr particle)
12807 {
12808     int ret = 0, tmp2;
12809 
12810     if (particle == NULL) {
12811 	PERROR_INT("xmlSchemaBuildAContentModel", "particle is NULL");
12812 	return(1);
12813     }
12814     if (particle->children == NULL) {
12815 	/*
12816 	* Just return in this case. A missing "term" of the particle
12817 	* might arise due to an invalid "term" component.
12818 	*/
12819 	return(1);
12820     }
12821 
12822     switch (particle->children->type) {
12823 	case XML_SCHEMA_TYPE_ANY: {
12824 	    xmlAutomataStatePtr start, end;
12825 	    xmlSchemaWildcardPtr wild;
12826 	    xmlSchemaWildcardNsPtr ns;
12827 
12828 	    wild = (xmlSchemaWildcardPtr) particle->children;
12829 
12830 	    start = pctxt->state;
12831 	    end = xmlAutomataNewState(pctxt->am);
12832 
12833 	    if (particle->maxOccurs == 1) {
12834 		if (wild->any == 1) {
12835 		    /*
12836 		    * We need to add both transitions:
12837 		    *
12838 		    * 1. the {"*", "*"} for elements in a namespace.
12839 		    */
12840 		    pctxt->state =
12841 			xmlAutomataNewTransition2(pctxt->am,
12842 			start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
12843 		    xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12844 		    /*
12845 		    * 2. the {"*"} for elements in no namespace.
12846 		    */
12847 		    pctxt->state =
12848 			xmlAutomataNewTransition2(pctxt->am,
12849 			start, NULL, BAD_CAST "*", NULL, wild);
12850 		    xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12851 
12852 		} else if (wild->nsSet != NULL) {
12853 		    ns = wild->nsSet;
12854 		    do {
12855 			pctxt->state = start;
12856 			pctxt->state = xmlAutomataNewTransition2(pctxt->am,
12857 			    pctxt->state, NULL, BAD_CAST "*", ns->value, wild);
12858 			xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12859 			ns = ns->next;
12860 		    } while (ns != NULL);
12861 
12862 		} else if (wild->negNsSet != NULL) {
12863 		    pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
12864 			start, end, BAD_CAST "*", wild->negNsSet->value,
12865 			wild);
12866 		}
12867 	    } else {
12868 		int counter;
12869 		xmlAutomataStatePtr hop;
12870 		int maxOccurs =
12871 		    particle->maxOccurs == UNBOUNDED ? UNBOUNDED :
12872                                            particle->maxOccurs - 1;
12873 		int minOccurs =
12874 		    particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12875 
12876 		counter = xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
12877 		hop = xmlAutomataNewState(pctxt->am);
12878 		if (wild->any == 1) {
12879 		    pctxt->state =
12880 			xmlAutomataNewTransition2(pctxt->am,
12881 			start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
12882 		    xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12883 		    pctxt->state =
12884 			xmlAutomataNewTransition2(pctxt->am,
12885 			start, NULL, BAD_CAST "*", NULL, wild);
12886 		    xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12887 		} else if (wild->nsSet != NULL) {
12888 		    ns = wild->nsSet;
12889 		    do {
12890 			pctxt->state =
12891 			    xmlAutomataNewTransition2(pctxt->am,
12892 				start, NULL, BAD_CAST "*", ns->value, wild);
12893 			xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12894 			ns = ns->next;
12895 		    } while (ns != NULL);
12896 
12897 		} else if (wild->negNsSet != NULL) {
12898 		    pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
12899 			start, hop, BAD_CAST "*", wild->negNsSet->value,
12900 			wild);
12901 		}
12902 		xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12903 		xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12904 	    }
12905 	    if (particle->minOccurs == 0) {
12906 		xmlAutomataNewEpsilon(pctxt->am, start, end);
12907                 ret = 1;
12908 	    }
12909 	    pctxt->state = end;
12910             break;
12911 	}
12912         case XML_SCHEMA_TYPE_ELEMENT:
12913 	    ret = xmlSchemaBuildContentModelForElement(pctxt, particle);
12914 	    break;
12915         case XML_SCHEMA_TYPE_SEQUENCE:{
12916             xmlSchemaTreeItemPtr sub;
12917 
12918             ret = 1;
12919             /*
12920              * If max and min occurances are default (1) then
12921              * simply iterate over the particles of the <sequence>.
12922              */
12923             if ((particle->minOccurs == 1) && (particle->maxOccurs == 1)) {
12924                 sub = particle->children->children;
12925 
12926                 while (sub != NULL) {
12927                     tmp2 = xmlSchemaBuildAContentModel(pctxt,
12928                                         (xmlSchemaParticlePtr) sub);
12929                     if (tmp2 != 1) ret = 0;
12930                     sub = sub->next;
12931                 }
12932             } else {
12933                 xmlAutomataStatePtr oldstate = pctxt->state;
12934 
12935                 if (particle->maxOccurs >= UNBOUNDED) {
12936                     if (particle->minOccurs > 1) {
12937                         xmlAutomataStatePtr tmp;
12938                         int counter;
12939 
12940                         pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12941                             oldstate, NULL);
12942                         oldstate = pctxt->state;
12943 
12944                         counter = xmlAutomataNewCounter(pctxt->am,
12945                             particle->minOccurs - 1, UNBOUNDED);
12946 
12947                         sub = particle->children->children;
12948                         while (sub != NULL) {
12949                             tmp2 = xmlSchemaBuildAContentModel(pctxt,
12950                                             (xmlSchemaParticlePtr) sub);
12951                             if (tmp2 != 1) ret = 0;
12952                             sub = sub->next;
12953                         }
12954                         tmp = pctxt->state;
12955                         xmlAutomataNewCountedTrans(pctxt->am, tmp,
12956                                                    oldstate, counter);
12957                         pctxt->state =
12958                             xmlAutomataNewCounterTrans(pctxt->am, tmp,
12959                                                        NULL, counter);
12960                         if (ret == 1)
12961                             xmlAutomataNewEpsilon(pctxt->am,
12962                                                 oldstate, pctxt->state);
12963 
12964                     } else {
12965                         pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12966                             oldstate, NULL);
12967                         oldstate = pctxt->state;
12968 
12969                         sub = particle->children->children;
12970                         while (sub != NULL) {
12971                             tmp2 = xmlSchemaBuildAContentModel(pctxt,
12972                                         (xmlSchemaParticlePtr) sub);
12973                             if (tmp2 != 1) ret = 0;
12974                             sub = sub->next;
12975                         }
12976                         xmlAutomataNewEpsilon(pctxt->am, pctxt->state,
12977                                               oldstate);
12978                         /*
12979                          * epsilon needed to block previous trans from
12980                          * being allowed to enter back from another
12981                          * construct
12982                          */
12983                         pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12984                                             pctxt->state, NULL);
12985                         if (particle->minOccurs == 0) {
12986                             xmlAutomataNewEpsilon(pctxt->am,
12987                                 oldstate, pctxt->state);
12988                             ret = 1;
12989                         }
12990                     }
12991                 } else if ((particle->maxOccurs > 1)
12992                            || (particle->minOccurs > 1)) {
12993                     xmlAutomataStatePtr tmp;
12994                     int counter;
12995 
12996                     pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12997                         oldstate, NULL);
12998                     oldstate = pctxt->state;
12999 
13000                     counter = xmlAutomataNewCounter(pctxt->am,
13001                         particle->minOccurs - 1,
13002                         particle->maxOccurs - 1);
13003 
13004                     sub = particle->children->children;
13005                     while (sub != NULL) {
13006                         tmp2 = xmlSchemaBuildAContentModel(pctxt,
13007                                         (xmlSchemaParticlePtr) sub);
13008                         if (tmp2 != 1) ret = 0;
13009                         sub = sub->next;
13010                     }
13011                     tmp = pctxt->state;
13012                     xmlAutomataNewCountedTrans(pctxt->am,
13013                         tmp, oldstate, counter);
13014                     pctxt->state =
13015                         xmlAutomataNewCounterTrans(pctxt->am, tmp, NULL,
13016                                                    counter);
13017                     if ((particle->minOccurs == 0) || (ret == 1)) {
13018                         xmlAutomataNewEpsilon(pctxt->am,
13019                                             oldstate, pctxt->state);
13020                         ret = 1;
13021                     }
13022                 } else {
13023                     sub = particle->children->children;
13024                     while (sub != NULL) {
13025                         tmp2 = xmlSchemaBuildAContentModel(pctxt,
13026                                         (xmlSchemaParticlePtr) sub);
13027                         if (tmp2 != 1) ret = 0;
13028                         sub = sub->next;
13029                     }
13030 
13031 		    /*
13032 		     * epsilon needed to block previous trans from
13033 		     * being allowed to enter back from another
13034 		     * construct
13035 		     */
13036 		    pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
13037 					pctxt->state, NULL);
13038 
13039                     if (particle->minOccurs == 0) {
13040                         xmlAutomataNewEpsilon(pctxt->am, oldstate,
13041                                               pctxt->state);
13042                         ret = 1;
13043                     }
13044                 }
13045             }
13046             break;
13047         }
13048         case XML_SCHEMA_TYPE_CHOICE:{
13049             xmlSchemaTreeItemPtr sub;
13050             xmlAutomataStatePtr start, end;
13051 
13052             ret = 0;
13053             start = pctxt->state;
13054             end = xmlAutomataNewState(pctxt->am);
13055 
13056             /*
13057              * iterate over the subtypes and remerge the end with an
13058              * epsilon transition
13059              */
13060             if (particle->maxOccurs == 1) {
13061                 sub = particle->children->children;
13062                 while (sub != NULL) {
13063                     pctxt->state = start;
13064                     tmp2 = xmlSchemaBuildAContentModel(pctxt,
13065                                         (xmlSchemaParticlePtr) sub);
13066                     if (tmp2 == 1) ret = 1;
13067                     xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
13068                     sub = sub->next;
13069                 }
13070             } else {
13071                 int counter;
13072                 xmlAutomataStatePtr hop, base;
13073                 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
13074                     UNBOUNDED : particle->maxOccurs - 1;
13075                 int minOccurs =
13076                     particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
13077 
13078                 /*
13079                  * use a counter to keep track of the number of transtions
13080                  * which went through the choice.
13081                  */
13082                 counter =
13083                     xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
13084                 hop = xmlAutomataNewState(pctxt->am);
13085                 base = xmlAutomataNewState(pctxt->am);
13086 
13087                 sub = particle->children->children;
13088                 while (sub != NULL) {
13089                     pctxt->state = base;
13090                     tmp2 = xmlSchemaBuildAContentModel(pctxt,
13091                                         (xmlSchemaParticlePtr) sub);
13092                     if (tmp2 == 1) ret = 1;
13093                     xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
13094                     sub = sub->next;
13095                 }
13096                 xmlAutomataNewEpsilon(pctxt->am, start, base);
13097                 xmlAutomataNewCountedTrans(pctxt->am, hop, base, counter);
13098                 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
13099                 if (ret == 1)
13100                     xmlAutomataNewEpsilon(pctxt->am, base, end);
13101             }
13102             if (particle->minOccurs == 0) {
13103                 xmlAutomataNewEpsilon(pctxt->am, start, end);
13104                 ret = 1;
13105             }
13106             pctxt->state = end;
13107             break;
13108         }
13109         case XML_SCHEMA_TYPE_ALL:{
13110             xmlAutomataStatePtr start, tmp;
13111             xmlSchemaParticlePtr sub;
13112             xmlSchemaElementPtr elemDecl;
13113 
13114             ret = 1;
13115 
13116             sub = (xmlSchemaParticlePtr) particle->children->children;
13117             if (sub == NULL)
13118                 break;
13119 
13120             ret = 0;
13121 
13122             start = pctxt->state;
13123             tmp = xmlAutomataNewState(pctxt->am);
13124             xmlAutomataNewEpsilon(pctxt->am, pctxt->state, tmp);
13125             pctxt->state = tmp;
13126             while (sub != NULL) {
13127                 pctxt->state = tmp;
13128 
13129                 elemDecl = (xmlSchemaElementPtr) sub->children;
13130                 if (elemDecl == NULL) {
13131                     PERROR_INT("xmlSchemaBuildAContentModel",
13132                         "<element> particle has no term");
13133                     return(ret);
13134                 };
13135                 /*
13136                 * NOTE: The {max occurs} of all the particles in the
13137                 * {particles} of the group must be 0 or 1; this is
13138                 * already ensured during the parse of the content of
13139                 * <all>.
13140                 */
13141                 if (elemDecl->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
13142                     int counter;
13143 
13144                     /*
13145                      * This is an abstract group, we need to share
13146                      * the same counter for all the element transitions
13147                      * derived from the group
13148                      */
13149                     counter = xmlAutomataNewCounter(pctxt->am,
13150                                        sub->minOccurs, sub->maxOccurs);
13151                     xmlSchemaBuildContentModelForSubstGroup(pctxt,
13152                                        sub, counter, pctxt->state);
13153                 } else {
13154                     if ((sub->minOccurs == 1) &&
13155                         (sub->maxOccurs == 1)) {
13156                         xmlAutomataNewOnceTrans2(pctxt->am, pctxt->state,
13157                                                 pctxt->state,
13158                                                 elemDecl->name,
13159                                                 elemDecl->targetNamespace,
13160                                                 1, 1, elemDecl);
13161                     } else if ((sub->minOccurs == 0) &&
13162                         (sub->maxOccurs == 1)) {
13163 
13164                         xmlAutomataNewCountTrans2(pctxt->am, pctxt->state,
13165                                                  pctxt->state,
13166                                                  elemDecl->name,
13167                                                  elemDecl->targetNamespace,
13168                                                  0,
13169                                                  1,
13170                                                  elemDecl);
13171                     }
13172                 }
13173                 sub = (xmlSchemaParticlePtr) sub->next;
13174             }
13175             pctxt->state =
13176                 xmlAutomataNewAllTrans(pctxt->am, pctxt->state, NULL, 0);
13177             if (particle->minOccurs == 0) {
13178                 xmlAutomataNewEpsilon(pctxt->am, start, pctxt->state);
13179                 ret = 1;
13180             }
13181             break;
13182         }
13183 	case XML_SCHEMA_TYPE_GROUP:
13184 	    /*
13185 	    * If we hit a model group definition, then this means that
13186 	    * it was empty, thus was not substituted for the containing
13187 	    * model group. Just do nothing in this case.
13188 	    * TODO: But the group should be substituted and not occur at
13189 	    * all in the content model at this point. Fix this.
13190 	    */
13191             ret = 1;
13192 	    break;
13193         default:
13194 	    xmlSchemaInternalErr2(ACTXT_CAST pctxt,
13195 		"xmlSchemaBuildAContentModel",
13196 		"found unexpected term of type '%s' in content model",
13197 		WXS_ITEM_TYPE_NAME(particle->children), NULL);
13198             return(ret);
13199     }
13200     return(ret);
13201 }
13202 
13203 /**
13204  * xmlSchemaBuildContentModel:
13205  * @ctxt:  the schema parser context
13206  * @type:  the complex type definition
13207  * @name:  the element name
13208  *
13209  * Builds the content model of the complex type.
13210  */
13211 static void
xmlSchemaBuildContentModel(xmlSchemaTypePtr type,xmlSchemaParserCtxtPtr ctxt)13212 xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
13213 			   xmlSchemaParserCtxtPtr ctxt)
13214 {
13215     if ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
13216 	(type->contModel != NULL) ||
13217 	((type->contentType != XML_SCHEMA_CONTENT_ELEMENTS) &&
13218 	(type->contentType != XML_SCHEMA_CONTENT_MIXED)))
13219 	return;
13220 
13221 #ifdef DEBUG_CONTENT
13222     xmlGenericError(xmlGenericErrorContext,
13223                     "Building content model for %s\n", name);
13224 #endif
13225     ctxt->am = NULL;
13226     ctxt->am = xmlNewAutomata();
13227     if (ctxt->am == NULL) {
13228         xmlGenericError(xmlGenericErrorContext,
13229 	    "Cannot create automata for complex type %s\n", type->name);
13230         return;
13231     }
13232     ctxt->state = xmlAutomataGetInitState(ctxt->am);
13233     /*
13234     * Build the automaton.
13235     */
13236     xmlSchemaBuildAContentModel(ctxt, WXS_TYPE_PARTICLE(type));
13237     xmlAutomataSetFinalState(ctxt->am, ctxt->state);
13238     type->contModel = xmlAutomataCompile(ctxt->am);
13239     if (type->contModel == NULL) {
13240         xmlSchemaPCustomErr(ctxt,
13241 	    XML_SCHEMAP_INTERNAL,
13242 	    WXS_BASIC_CAST type, type->node,
13243 	    "Failed to compile the content model", NULL);
13244     } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
13245         xmlSchemaPCustomErr(ctxt,
13246 	    XML_SCHEMAP_NOT_DETERMINISTIC,
13247 	    /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
13248 	    WXS_BASIC_CAST type, type->node,
13249 	    "The content model is not determinist", NULL);
13250     } else {
13251 #ifdef DEBUG_CONTENT_REGEXP
13252         xmlGenericError(xmlGenericErrorContext,
13253                         "Content model of %s:\n", type->name);
13254         xmlRegexpPrint(stderr, type->contModel);
13255 #endif
13256     }
13257     ctxt->state = NULL;
13258     xmlFreeAutomata(ctxt->am);
13259     ctxt->am = NULL;
13260 }
13261 
13262 /**
13263  * xmlSchemaResolveElementReferences:
13264  * @elem:  the schema element context
13265  * @ctxt:  the schema parser context
13266  *
13267  * Resolves the references of an element declaration
13268  * or particle, which has an element declaration as it's
13269  * term.
13270  */
13271 static void
xmlSchemaResolveElementReferences(xmlSchemaElementPtr elemDecl,xmlSchemaParserCtxtPtr ctxt)13272 xmlSchemaResolveElementReferences(xmlSchemaElementPtr elemDecl,
13273 				  xmlSchemaParserCtxtPtr ctxt)
13274 {
13275     if ((ctxt == NULL) || (elemDecl == NULL) ||
13276 	((elemDecl != NULL) &&
13277 	(elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
13278         return;
13279     elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
13280 
13281     if ((elemDecl->subtypes == NULL) && (elemDecl->namedType != NULL)) {
13282 	xmlSchemaTypePtr type;
13283 
13284 	/* (type definition) ... otherwise the type definition `resolved`
13285 	* to by the `actual value` of the type [attribute] ...
13286 	*/
13287 	type = xmlSchemaGetType(ctxt->schema, elemDecl->namedType,
13288 	    elemDecl->namedTypeNs);
13289 	if (type == NULL) {
13290 	    xmlSchemaPResCompAttrErr(ctxt,
13291 		XML_SCHEMAP_SRC_RESOLVE,
13292 		WXS_BASIC_CAST elemDecl, elemDecl->node,
13293 		"type", elemDecl->namedType, elemDecl->namedTypeNs,
13294 		XML_SCHEMA_TYPE_BASIC, "type definition");
13295 	} else
13296 	    elemDecl->subtypes = type;
13297     }
13298     if (elemDecl->substGroup != NULL) {
13299 	xmlSchemaElementPtr substHead;
13300 
13301 	/*
13302 	* FIXME TODO: Do we need a new field in _xmlSchemaElement for
13303 	* substitutionGroup?
13304 	*/
13305 	substHead = xmlSchemaGetElem(ctxt->schema, elemDecl->substGroup,
13306 	    elemDecl->substGroupNs);
13307 	if (substHead == NULL) {
13308 	    xmlSchemaPResCompAttrErr(ctxt,
13309 		XML_SCHEMAP_SRC_RESOLVE,
13310 		WXS_BASIC_CAST elemDecl, NULL,
13311 		"substitutionGroup", elemDecl->substGroup,
13312 		elemDecl->substGroupNs, XML_SCHEMA_TYPE_ELEMENT, NULL);
13313 	} else {
13314 	    xmlSchemaResolveElementReferences(substHead, ctxt);
13315 	    /*
13316 	    * Set the "substitution group affiliation".
13317 	    * NOTE that now we use the "refDecl" field for this.
13318 	    */
13319 	    WXS_SUBST_HEAD(elemDecl) = substHead;
13320 	    /*
13321 	    * The type definitions is set to:
13322 	    * SPEC "...the {type definition} of the element
13323 	    * declaration `resolved` to by the `actual value`
13324 	    * of the substitutionGroup [attribute], if present"
13325 	    */
13326 	    if (elemDecl->subtypes == NULL)
13327 		elemDecl->subtypes = substHead->subtypes;
13328 	}
13329     }
13330     /*
13331     * SPEC "The definition of anyType serves as the default type definition
13332     * for element declarations whose XML representation does not specify one."
13333     */
13334     if ((elemDecl->subtypes == NULL) &&
13335 	(elemDecl->namedType == NULL) &&
13336 	(elemDecl->substGroup == NULL))
13337 	elemDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
13338 }
13339 
13340 /**
13341  * xmlSchemaResolveUnionMemberTypes:
13342  * @ctxt:  the schema parser context
13343  * @type:  the schema simple type definition
13344  *
13345  * Checks and builds the "member type definitions" property of the union
13346  * simple type. This handles part (1), part (2) is done in
13347  * xmlSchemaFinishMemberTypeDefinitionsProperty()
13348  *
13349  * Returns -1 in case of an internal error, 0 otherwise.
13350  */
13351 static int
xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,xmlSchemaTypePtr type)13352 xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,
13353 				 xmlSchemaTypePtr type)
13354 {
13355 
13356     xmlSchemaTypeLinkPtr link, lastLink, newLink;
13357     xmlSchemaTypePtr memberType;
13358 
13359     /*
13360     * SPEC (1) "If the <union> alternative is chosen, then [Definition:]
13361     * define the explicit members as the type definitions `resolved`
13362     * to by the items in the `actual value` of the memberTypes [attribute],
13363     * if any, followed by the type definitions corresponding to the
13364     * <simpleType>s among the [children] of <union>, if any."
13365     */
13366     /*
13367     * Resolve references.
13368     */
13369     link = type->memberTypes;
13370     lastLink = NULL;
13371     while (link != NULL) {
13372 	const xmlChar *name, *nsName;
13373 
13374 	name = ((xmlSchemaQNameRefPtr) link->type)->name;
13375 	nsName = ((xmlSchemaQNameRefPtr) link->type)->targetNamespace;
13376 
13377 	memberType = xmlSchemaGetType(ctxt->schema, name, nsName);
13378 	if ((memberType == NULL) || (! WXS_IS_SIMPLE(memberType))) {
13379 	    xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
13380 		WXS_BASIC_CAST type, type->node, "memberTypes",
13381 		name, nsName, XML_SCHEMA_TYPE_SIMPLE, NULL);
13382 	    /*
13383 	    * Remove the member type link.
13384 	    */
13385 	    if (lastLink == NULL)
13386 		type->memberTypes = link->next;
13387 	    else
13388 		lastLink->next = link->next;
13389 	    newLink = link;
13390 	    link = link->next;
13391 	    xmlFree(newLink);
13392 	} else {
13393 	    link->type = memberType;
13394 	    lastLink = link;
13395 	    link = link->next;
13396 	}
13397     }
13398     /*
13399     * Add local simple types,
13400     */
13401     memberType = type->subtypes;
13402     while (memberType != NULL) {
13403 	link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
13404 	if (link == NULL) {
13405 	    xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
13406 	    return (-1);
13407 	}
13408 	link->type = memberType;
13409 	link->next = NULL;
13410 	if (lastLink == NULL)
13411 	    type->memberTypes = link;
13412 	else
13413 	    lastLink->next = link;
13414 	lastLink = link;
13415 	memberType = memberType->next;
13416     }
13417     return (0);
13418 }
13419 
13420 /**
13421  * xmlSchemaIsDerivedFromBuiltInType:
13422  * @ctxt:  the schema parser context
13423  * @type:  the type definition
13424  * @valType: the value type
13425  *
13426  *
13427  * Returns 1 if the type has the given value type, or
13428  * is derived from such a type.
13429  */
13430 static int
xmlSchemaIsDerivedFromBuiltInType(xmlSchemaTypePtr type,int valType)13431 xmlSchemaIsDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
13432 {
13433     if (type == NULL)
13434 	return (0);
13435     if (WXS_IS_COMPLEX(type))
13436 	return (0);
13437     if (type->type == XML_SCHEMA_TYPE_BASIC) {
13438 	if (type->builtInType == valType)
13439 	    return(1);
13440 	if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13441 	    (type->builtInType == XML_SCHEMAS_ANYTYPE))
13442 	    return (0);
13443 	return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13444     }
13445     return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13446 }
13447 
13448 #if 0
13449 /**
13450  * xmlSchemaIsDerivedFromBuiltInType:
13451  * @ctxt:  the schema parser context
13452  * @type:  the type definition
13453  * @valType: the value type
13454  *
13455  *
13456  * Returns 1 if the type has the given value type, or
13457  * is derived from such a type.
13458  */
13459 static int
13460 xmlSchemaIsUserDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
13461 {
13462     if (type == NULL)
13463 	return (0);
13464     if (WXS_IS_COMPLEX(type))
13465 	return (0);
13466     if (type->type == XML_SCHEMA_TYPE_BASIC) {
13467 	if (type->builtInType == valType)
13468 	    return(1);
13469 	return (0);
13470     } else
13471 	return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13472 
13473     return (0);
13474 }
13475 
13476 static xmlSchemaTypePtr
13477 xmlSchemaQueryBuiltInType(xmlSchemaTypePtr type)
13478 {
13479     if (type == NULL)
13480 	return (NULL);
13481     if (WXS_IS_COMPLEX(type))
13482 	return (NULL);
13483     if (type->type == XML_SCHEMA_TYPE_BASIC)
13484 	return(type);
13485     return(xmlSchemaQueryBuiltInType(type->subtypes));
13486 }
13487 #endif
13488 
13489 /**
13490  * xmlSchemaGetPrimitiveType:
13491  * @type:  the simpleType definition
13492  *
13493  * Returns the primitive type of the given type or
13494  * NULL in case of error.
13495  */
13496 static xmlSchemaTypePtr
xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)13497 xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
13498 {
13499 
13500     while (type != NULL) {
13501 	/*
13502 	* Note that anySimpleType is actually not a primitive type
13503 	* but we need that here.
13504 	*/
13505 	if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13506 	   (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
13507 	    return (type);
13508 	type = type->baseType;
13509     }
13510 
13511     return (NULL);
13512 }
13513 
13514 #if 0
13515 /**
13516  * xmlSchemaGetBuiltInTypeAncestor:
13517  * @type:  the simpleType definition
13518  *
13519  * Returns the primitive type of the given type or
13520  * NULL in case of error.
13521  */
13522 static xmlSchemaTypePtr
13523 xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
13524 {
13525     if (WXS_IS_LIST(type) || WXS_IS_UNION(type))
13526 	return (0);
13527     while (type != NULL) {
13528 	if (type->type == XML_SCHEMA_TYPE_BASIC)
13529 	    return (type);
13530 	type = type->baseType;
13531     }
13532 
13533     return (NULL);
13534 }
13535 #endif
13536 
13537 /**
13538  * xmlSchemaCloneWildcardNsConstraints:
13539  * @ctxt:  the schema parser context
13540  * @dest:  the destination wildcard
13541  * @source: the source wildcard
13542  *
13543  * Clones the namespace constraints of source
13544  * and assignes them to dest.
13545  * Returns -1 on internal error, 0 otherwise.
13546  */
13547 static int
xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,xmlSchemaWildcardPtr dest,xmlSchemaWildcardPtr source)13548 xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
13549 				    xmlSchemaWildcardPtr dest,
13550 				    xmlSchemaWildcardPtr source)
13551 {
13552     xmlSchemaWildcardNsPtr cur, tmp, last;
13553 
13554     if ((source == NULL) || (dest == NULL))
13555 	return(-1);
13556     dest->any = source->any;
13557     cur = source->nsSet;
13558     last = NULL;
13559     while (cur != NULL) {
13560 	tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
13561 	if (tmp == NULL)
13562 	    return(-1);
13563 	tmp->value = cur->value;
13564 	if (last == NULL)
13565 	    dest->nsSet = tmp;
13566 	else
13567 	    last->next = tmp;
13568 	last = tmp;
13569 	cur = cur->next;
13570     }
13571     if (dest->negNsSet != NULL)
13572 	xmlSchemaFreeWildcardNsSet(dest->negNsSet);
13573     if (source->negNsSet != NULL) {
13574 	dest->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13575 	if (dest->negNsSet == NULL)
13576 	    return(-1);
13577 	dest->negNsSet->value = source->negNsSet->value;
13578     } else
13579 	dest->negNsSet = NULL;
13580     return(0);
13581 }
13582 
13583 /**
13584  * xmlSchemaUnionWildcards:
13585  * @ctxt:  the schema parser context
13586  * @completeWild:  the first wildcard
13587  * @curWild: the second wildcard
13588  *
13589  * Unions the namespace constraints of the given wildcards.
13590  * @completeWild will hold the resulting union.
13591  * Returns a positive error code on failure, -1 in case of an
13592  * internal error, 0 otherwise.
13593  */
13594 static int
xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,xmlSchemaWildcardPtr completeWild,xmlSchemaWildcardPtr curWild)13595 xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
13596 			    xmlSchemaWildcardPtr completeWild,
13597 			    xmlSchemaWildcardPtr curWild)
13598 {
13599     xmlSchemaWildcardNsPtr cur, curB, tmp;
13600 
13601     /*
13602     * 1 If O1 and O2 are the same value, then that value must be the
13603     * value.
13604     */
13605     if ((completeWild->any == curWild->any) &&
13606 	((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13607 	((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
13608 
13609 	if ((completeWild->negNsSet == NULL) ||
13610 	    (completeWild->negNsSet->value == curWild->negNsSet->value)) {
13611 
13612 	    if (completeWild->nsSet != NULL) {
13613 		int found = 0;
13614 
13615 		/*
13616 		* Check equality of sets.
13617 		*/
13618 		cur = completeWild->nsSet;
13619 		while (cur != NULL) {
13620 		    found = 0;
13621 		    curB = curWild->nsSet;
13622 		    while (curB != NULL) {
13623 			if (cur->value == curB->value) {
13624 			    found = 1;
13625 			    break;
13626 			}
13627 			curB = curB->next;
13628 		    }
13629 		    if (!found)
13630 			break;
13631 		    cur = cur->next;
13632 		}
13633 		if (found)
13634 		    return(0);
13635 	    } else
13636 		return(0);
13637 	}
13638     }
13639     /*
13640     * 2 If either O1 or O2 is any, then any must be the value
13641     */
13642     if (completeWild->any != curWild->any) {
13643 	if (completeWild->any == 0) {
13644 	    completeWild->any = 1;
13645 	    if (completeWild->nsSet != NULL) {
13646 		xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13647 		completeWild->nsSet = NULL;
13648 	    }
13649 	    if (completeWild->negNsSet != NULL) {
13650 		xmlFree(completeWild->negNsSet);
13651 		completeWild->negNsSet = NULL;
13652 	    }
13653 	}
13654 	return (0);
13655     }
13656     /*
13657     * 3 If both O1 and O2 are sets of (namespace names or `absent`),
13658     * then the union of those sets must be the value.
13659     */
13660     if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
13661 	int found;
13662 	xmlSchemaWildcardNsPtr start;
13663 
13664 	cur = curWild->nsSet;
13665 	start = completeWild->nsSet;
13666 	while (cur != NULL) {
13667 	    found = 0;
13668 	    curB = start;
13669 	    while (curB != NULL) {
13670 		if (cur->value == curB->value) {
13671 		    found = 1;
13672 		    break;
13673 		}
13674 		curB = curB->next;
13675 	    }
13676 	    if (!found) {
13677 		tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
13678 		if (tmp == NULL)
13679 		    return (-1);
13680 		tmp->value = cur->value;
13681 		tmp->next = completeWild->nsSet;
13682 		completeWild->nsSet = tmp;
13683 	    }
13684 	    cur = cur->next;
13685 	}
13686 
13687 	return(0);
13688     }
13689     /*
13690     * 4 If the two are negations of different values (namespace names
13691     * or `absent`), then a pair of not and `absent` must be the value.
13692     */
13693     if ((completeWild->negNsSet != NULL) &&
13694 	(curWild->negNsSet != NULL) &&
13695 	(completeWild->negNsSet->value != curWild->negNsSet->value)) {
13696 	completeWild->negNsSet->value = NULL;
13697 
13698 	return(0);
13699     }
13700     /*
13701      * 5.
13702      */
13703     if (((completeWild->negNsSet != NULL) &&
13704 	(completeWild->negNsSet->value != NULL) &&
13705 	(curWild->nsSet != NULL)) ||
13706 	((curWild->negNsSet != NULL) &&
13707 	(curWild->negNsSet->value != NULL) &&
13708 	(completeWild->nsSet != NULL))) {
13709 
13710 	int nsFound, absentFound = 0;
13711 
13712 	if (completeWild->nsSet != NULL) {
13713 	    cur = completeWild->nsSet;
13714 	    curB = curWild->negNsSet;
13715 	} else {
13716 	    cur = curWild->nsSet;
13717 	    curB = completeWild->negNsSet;
13718 	}
13719 	nsFound = 0;
13720 	while (cur != NULL) {
13721 	    if (cur->value == NULL)
13722 		absentFound = 1;
13723 	    else if (cur->value == curB->value)
13724 		nsFound = 1;
13725 	    if (nsFound && absentFound)
13726 		break;
13727 	    cur = cur->next;
13728 	}
13729 
13730 	if (nsFound && absentFound) {
13731 	    /*
13732 	    * 5.1 If the set S includes both the negated namespace
13733 	    * name and `absent`, then any must be the value.
13734 	    */
13735 	    completeWild->any = 1;
13736 	    if (completeWild->nsSet != NULL) {
13737 		xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13738 		completeWild->nsSet = NULL;
13739 	    }
13740 	    if (completeWild->negNsSet != NULL) {
13741 		xmlFree(completeWild->negNsSet);
13742 		completeWild->negNsSet = NULL;
13743 	    }
13744 	} else if (nsFound && (!absentFound)) {
13745 	    /*
13746 	    * 5.2 If the set S includes the negated namespace name
13747 	    * but not `absent`, then a pair of not and `absent` must
13748 	    * be the value.
13749 	    */
13750 	    if (completeWild->nsSet != NULL) {
13751 		xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13752 		completeWild->nsSet = NULL;
13753 	    }
13754 	    if (completeWild->negNsSet == NULL) {
13755 		completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13756 		if (completeWild->negNsSet == NULL)
13757 		    return (-1);
13758 	    }
13759 	    completeWild->negNsSet->value = NULL;
13760 	} else if ((!nsFound) && absentFound) {
13761 	    /*
13762 	    * 5.3 If the set S includes `absent` but not the negated
13763 	    * namespace name, then the union is not expressible.
13764 	    */
13765 	    xmlSchemaPErr(ctxt, completeWild->node,
13766 		XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
13767 		"The union of the wilcard is not expressible.\n",
13768 		NULL, NULL);
13769 	    return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
13770 	} else if ((!nsFound) && (!absentFound)) {
13771 	    /*
13772 	    * 5.4 If the set S does not include either the negated namespace
13773 	    * name or `absent`, then whichever of O1 or O2 is a pair of not
13774 	    * and a namespace name must be the value.
13775 	    */
13776 	    if (completeWild->negNsSet == NULL) {
13777 		if (completeWild->nsSet != NULL) {
13778 		    xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13779 		    completeWild->nsSet = NULL;
13780 		}
13781 		completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13782 		if (completeWild->negNsSet == NULL)
13783 		    return (-1);
13784 		completeWild->negNsSet->value = curWild->negNsSet->value;
13785 	    }
13786 	}
13787 	return (0);
13788     }
13789     /*
13790      * 6.
13791      */
13792     if (((completeWild->negNsSet != NULL) &&
13793 	(completeWild->negNsSet->value == NULL) &&
13794 	(curWild->nsSet != NULL)) ||
13795 	((curWild->negNsSet != NULL) &&
13796 	(curWild->negNsSet->value == NULL) &&
13797 	(completeWild->nsSet != NULL))) {
13798 
13799 	if (completeWild->nsSet != NULL) {
13800 	    cur = completeWild->nsSet;
13801 	} else {
13802 	    cur = curWild->nsSet;
13803 	}
13804 	while (cur != NULL) {
13805 	    if (cur->value == NULL) {
13806 		/*
13807 		* 6.1 If the set S includes `absent`, then any must be the
13808 		* value.
13809 		*/
13810 		completeWild->any = 1;
13811 		if (completeWild->nsSet != NULL) {
13812 		    xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13813 		    completeWild->nsSet = NULL;
13814 		}
13815 		if (completeWild->negNsSet != NULL) {
13816 		    xmlFree(completeWild->negNsSet);
13817 		    completeWild->negNsSet = NULL;
13818 		}
13819 		return (0);
13820 	    }
13821 	    cur = cur->next;
13822 	}
13823 	if (completeWild->negNsSet == NULL) {
13824 	    /*
13825 	    * 6.2 If the set S does not include `absent`, then a pair of not
13826 	    * and `absent` must be the value.
13827 	    */
13828 	    if (completeWild->nsSet != NULL) {
13829 		xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13830 		completeWild->nsSet = NULL;
13831 	    }
13832 	    completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13833 	    if (completeWild->negNsSet == NULL)
13834 		return (-1);
13835 	    completeWild->negNsSet->value = NULL;
13836 	}
13837 	return (0);
13838     }
13839     return (0);
13840 
13841 }
13842 
13843 /**
13844  * xmlSchemaIntersectWildcards:
13845  * @ctxt:  the schema parser context
13846  * @completeWild:  the first wildcard
13847  * @curWild: the second wildcard
13848  *
13849  * Intersects the namespace constraints of the given wildcards.
13850  * @completeWild will hold the resulting intersection.
13851  * Returns a positive error code on failure, -1 in case of an
13852  * internal error, 0 otherwise.
13853  */
13854 static int
xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,xmlSchemaWildcardPtr completeWild,xmlSchemaWildcardPtr curWild)13855 xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
13856 			    xmlSchemaWildcardPtr completeWild,
13857 			    xmlSchemaWildcardPtr curWild)
13858 {
13859     xmlSchemaWildcardNsPtr cur, curB, prev,  tmp;
13860 
13861     /*
13862     * 1 If O1 and O2 are the same value, then that value must be the
13863     * value.
13864     */
13865     if ((completeWild->any == curWild->any) &&
13866 	((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13867 	((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
13868 
13869 	if ((completeWild->negNsSet == NULL) ||
13870 	    (completeWild->negNsSet->value == curWild->negNsSet->value)) {
13871 
13872 	    if (completeWild->nsSet != NULL) {
13873 		int found = 0;
13874 
13875 		/*
13876 		* Check equality of sets.
13877 		*/
13878 		cur = completeWild->nsSet;
13879 		while (cur != NULL) {
13880 		    found = 0;
13881 		    curB = curWild->nsSet;
13882 		    while (curB != NULL) {
13883 			if (cur->value == curB->value) {
13884 			    found = 1;
13885 			    break;
13886 			}
13887 			curB = curB->next;
13888 		    }
13889 		    if (!found)
13890 			break;
13891 		    cur = cur->next;
13892 		}
13893 		if (found)
13894 		    return(0);
13895 	    } else
13896 		return(0);
13897 	}
13898     }
13899     /*
13900     * 2 If either O1 or O2 is any, then the other must be the value.
13901     */
13902     if ((completeWild->any != curWild->any) && (completeWild->any)) {
13903 	if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
13904 	    return(-1);
13905 	return(0);
13906     }
13907     /*
13908     * 3 If either O1 or O2 is a pair of not and a value (a namespace
13909     * name or `absent`) and the other is a set of (namespace names or
13910     * `absent`), then that set, minus the negated value if it was in
13911     * the set, minus `absent` if it was in the set, must be the value.
13912     */
13913     if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
13914 	((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
13915 	const xmlChar *neg;
13916 
13917 	if (completeWild->nsSet == NULL) {
13918 	    neg = completeWild->negNsSet->value;
13919 	    if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
13920 		return(-1);
13921 	} else
13922 	    neg = curWild->negNsSet->value;
13923 	/*
13924 	* Remove absent and negated.
13925 	*/
13926 	prev = NULL;
13927 	cur = completeWild->nsSet;
13928 	while (cur != NULL) {
13929 	    if (cur->value == NULL) {
13930 		if (prev == NULL)
13931 		    completeWild->nsSet = cur->next;
13932 		else
13933 		    prev->next = cur->next;
13934 		xmlFree(cur);
13935 		break;
13936 	    }
13937 	    prev = cur;
13938 	    cur = cur->next;
13939 	}
13940 	if (neg != NULL) {
13941 	    prev = NULL;
13942 	    cur = completeWild->nsSet;
13943 	    while (cur != NULL) {
13944 		if (cur->value == neg) {
13945 		    if (prev == NULL)
13946 			completeWild->nsSet = cur->next;
13947 		    else
13948 			prev->next = cur->next;
13949 		    xmlFree(cur);
13950 		    break;
13951 		}
13952 		prev = cur;
13953 		cur = cur->next;
13954 	    }
13955 	}
13956 
13957 	return(0);
13958     }
13959     /*
13960     * 4 If both O1 and O2 are sets of (namespace names or `absent`),
13961     * then the intersection of those sets must be the value.
13962     */
13963     if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
13964 	int found;
13965 
13966 	cur = completeWild->nsSet;
13967 	prev = NULL;
13968 	while (cur != NULL) {
13969 	    found = 0;
13970 	    curB = curWild->nsSet;
13971 	    while (curB != NULL) {
13972 		if (cur->value == curB->value) {
13973 		    found = 1;
13974 		    break;
13975 		}
13976 		curB = curB->next;
13977 	    }
13978 	    if (!found) {
13979 		if (prev == NULL)
13980 		    completeWild->nsSet = cur->next;
13981 		else
13982 		    prev->next = cur->next;
13983 		tmp = cur->next;
13984 		xmlFree(cur);
13985 		cur = tmp;
13986 		continue;
13987 	    }
13988 	    prev = cur;
13989 	    cur = cur->next;
13990 	}
13991 
13992 	return(0);
13993     }
13994     /* 5 If the two are negations of different namespace names,
13995     * then the intersection is not expressible
13996     */
13997     if ((completeWild->negNsSet != NULL) &&
13998 	(curWild->negNsSet != NULL) &&
13999 	(completeWild->negNsSet->value != curWild->negNsSet->value) &&
14000 	(completeWild->negNsSet->value != NULL) &&
14001 	(curWild->negNsSet->value != NULL)) {
14002 
14003 	xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
14004 	    "The intersection of the wilcard is not expressible.\n",
14005 	    NULL, NULL);
14006 	return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
14007     }
14008     /*
14009     * 6 If the one is a negation of a namespace name and the other
14010     * is a negation of `absent`, then the one which is the negation
14011     * of a namespace name must be the value.
14012     */
14013     if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
14014 	(completeWild->negNsSet->value != curWild->negNsSet->value) &&
14015 	(completeWild->negNsSet->value == NULL)) {
14016 	completeWild->negNsSet->value =  curWild->negNsSet->value;
14017     }
14018     return(0);
14019 }
14020 
14021 /**
14022  * xmlSchemaIsWildcardNsConstraintSubset:
14023  * @ctxt:  the schema parser context
14024  * @sub:  the first wildcard
14025  * @super: the second wildcard
14026  *
14027  * Schema Component Constraint: Wildcard Subset (cos-ns-subset)
14028  *
14029  * Returns 0 if the namespace constraint of @sub is an intensional
14030  * subset of @super, 1 otherwise.
14031  */
14032 static int
xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub,xmlSchemaWildcardPtr super)14033 xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub,
14034 			  xmlSchemaWildcardPtr super)
14035 {
14036     /*
14037     * 1 super must be any.
14038     */
14039     if (super->any)
14040 	return (0);
14041     /*
14042     * 2.1 sub must be a pair of not and a namespace name or `absent`.
14043     * 2.2 super must be a pair of not and the same value.
14044     */
14045     if ((sub->negNsSet != NULL) &&
14046 	(super->negNsSet != NULL) &&
14047 	(sub->negNsSet->value == super->negNsSet->value))
14048 	return (0);
14049     /*
14050     * 3.1 sub must be a set whose members are either namespace names or `absent`.
14051     */
14052     if (sub->nsSet != NULL) {
14053 	/*
14054 	* 3.2.1 super must be the same set or a superset thereof.
14055 	*/
14056 	if (super->nsSet != NULL) {
14057 	    xmlSchemaWildcardNsPtr cur, curB;
14058 	    int found = 0;
14059 
14060 	    cur = sub->nsSet;
14061 	    while (cur != NULL) {
14062 		found = 0;
14063 		curB = super->nsSet;
14064 		while (curB != NULL) {
14065 		    if (cur->value == curB->value) {
14066 			found = 1;
14067 			break;
14068 		    }
14069 		    curB = curB->next;
14070 		}
14071 		if (!found)
14072 		    return (1);
14073 		cur = cur->next;
14074 	    }
14075 	    if (found)
14076 		return (0);
14077 	} else if (super->negNsSet != NULL) {
14078 	    xmlSchemaWildcardNsPtr cur;
14079 	    /*
14080 	    * 3.2.2 super must be a pair of not and a namespace name or
14081 	    * `absent` and that value must not be in sub's set.
14082 	    */
14083 	    cur = sub->nsSet;
14084 	    while (cur != NULL) {
14085 		if (cur->value == super->negNsSet->value)
14086 		    return (1);
14087 		cur = cur->next;
14088 	    }
14089 	    return (0);
14090 	}
14091     }
14092     return (1);
14093 }
14094 
14095 static int
xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributeUsePtr attruse,int * fixed,const xmlChar ** value,xmlSchemaValPtr * val)14096 xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributeUsePtr attruse,
14097 				     int *fixed,
14098 				     const xmlChar **value,
14099 				     xmlSchemaValPtr *val)
14100 {
14101     *fixed = 0;
14102     *value = NULL;
14103     if (val != 0)
14104 	*val = NULL;
14105 
14106     if (attruse->defValue != NULL) {
14107 	*value = attruse->defValue;
14108 	if (val != NULL)
14109 	    *val = attruse->defVal;
14110 	if (attruse->flags & XML_SCHEMA_ATTR_USE_FIXED)
14111 	    *fixed = 1;
14112 	return(1);
14113     } else if ((attruse->attrDecl != NULL) &&
14114 	(attruse->attrDecl->defValue != NULL)) {
14115 	*value = attruse->attrDecl->defValue;
14116 	if (val != NULL)
14117 	    *val = attruse->attrDecl->defVal;
14118 	if (attruse->attrDecl->flags & XML_SCHEMAS_ATTR_FIXED)
14119 	    *fixed = 1;
14120 	return(1);
14121     }
14122     return(0);
14123 }
14124 /**
14125  * xmlSchemaCheckCVCWildcardNamespace:
14126  * @wild:  the wildcard
14127  * @ns:  the namespace
14128  *
14129  * Validation Rule: Wildcard allows Namespace Name
14130  * (cvc-wildcard-namespace)
14131  *
14132  * Returns 0 if the given namespace matches the wildcard,
14133  * 1 otherwise and -1 on API errors.
14134  */
14135 static int
xmlSchemaCheckCVCWildcardNamespace(xmlSchemaWildcardPtr wild,const xmlChar * ns)14136 xmlSchemaCheckCVCWildcardNamespace(xmlSchemaWildcardPtr wild,
14137 				   const xmlChar* ns)
14138 {
14139     if (wild == NULL)
14140 	return(-1);
14141 
14142     if (wild->any)
14143 	return(0);
14144     else if (wild->nsSet != NULL) {
14145 	xmlSchemaWildcardNsPtr cur;
14146 
14147 	cur = wild->nsSet;
14148 	while (cur != NULL) {
14149 	    if (xmlStrEqual(cur->value, ns))
14150 		return(0);
14151 	    cur = cur->next;
14152 	}
14153     } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
14154 	(!xmlStrEqual(wild->negNsSet->value, ns)))
14155 	return(0);
14156 
14157     return(1);
14158 }
14159 
14160 #define XML_SCHEMA_ACTION_DERIVE 0
14161 #define XML_SCHEMA_ACTION_REDEFINE 1
14162 
14163 #define WXS_ACTION_STR(a) \
14164 ((a) == XML_SCHEMA_ACTION_DERIVE) ? (const xmlChar *) "base" : (const xmlChar *) "redefined"
14165 
14166 /*
14167 * Schema Component Constraint:
14168 *   Derivation Valid (Restriction, Complex)
14169 *   derivation-ok-restriction (2) - (4)
14170 *
14171 * ATTENTION:
14172 * In XML Schema 1.1 this will be:
14173 * Validation Rule:
14174 *     Checking complex type subsumption (practicalSubsumption) (1, 2 and 3)
14175 *
14176 */
14177 static int
xmlSchemaCheckDerivationOKRestriction2to4(xmlSchemaParserCtxtPtr pctxt,int action,xmlSchemaBasicItemPtr item,xmlSchemaBasicItemPtr baseItem,xmlSchemaItemListPtr uses,xmlSchemaItemListPtr baseUses,xmlSchemaWildcardPtr wild,xmlSchemaWildcardPtr baseWild)14178 xmlSchemaCheckDerivationOKRestriction2to4(xmlSchemaParserCtxtPtr pctxt,
14179 				       int action,
14180 				       xmlSchemaBasicItemPtr item,
14181 				       xmlSchemaBasicItemPtr baseItem,
14182 				       xmlSchemaItemListPtr uses,
14183 				       xmlSchemaItemListPtr baseUses,
14184 				       xmlSchemaWildcardPtr wild,
14185 				       xmlSchemaWildcardPtr baseWild)
14186 {
14187     xmlSchemaAttributeUsePtr cur = NULL, bcur;
14188     int i, j, found; /* err = 0; */
14189     const xmlChar *bEffValue;
14190     int effFixed;
14191 
14192     if (uses != NULL) {
14193 	for (i = 0; i < uses->nbItems; i++) {
14194 	    cur = uses->items[i];
14195 	    found = 0;
14196 	    if (baseUses == NULL)
14197 		goto not_found;
14198 	    for (j = 0; j < baseUses->nbItems; j++) {
14199 		bcur = baseUses->items[j];
14200 		if ((WXS_ATTRUSE_DECL_NAME(cur) ==
14201 			WXS_ATTRUSE_DECL_NAME(bcur)) &&
14202 		    (WXS_ATTRUSE_DECL_TNS(cur) ==
14203 			WXS_ATTRUSE_DECL_TNS(bcur)))
14204 		{
14205 		    /*
14206 		    * (2.1) "If there is an attribute use in the {attribute
14207 		    * uses} of the {base type definition} (call this B) whose
14208 		    * {attribute declaration} has the same {name} and {target
14209 		    * namespace}, then  all of the following must be true:"
14210 		    */
14211 		    found = 1;
14212 
14213 		    if ((cur->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
14214 			(bcur->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED))
14215 		    {
14216 			xmlChar *str = NULL;
14217 			/*
14218 			* (2.1.1) "one of the following must be true:"
14219 			* (2.1.1.1) "B's {required} is false."
14220 			* (2.1.1.2) "R's {required} is true."
14221 			*/
14222 			xmlSchemaPAttrUseErr4(pctxt,
14223 			    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
14224 			    WXS_ITEM_NODE(item), item, cur,
14225 			    "The 'optional' attribute use is inconsistent "
14226 			    "with the corresponding 'required' attribute use of "
14227 			    "the %s %s",
14228 			    WXS_ACTION_STR(action),
14229 			    xmlSchemaGetComponentDesignation(&str, baseItem),
14230 			    NULL, NULL);
14231 			FREE_AND_NULL(str);
14232 			/* err = pctxt->err; */
14233 		    } else if (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
14234 			WXS_ATTRUSE_TYPEDEF(cur),
14235 			WXS_ATTRUSE_TYPEDEF(bcur), 0) != 0)
14236 		    {
14237 			xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
14238 
14239 			/*
14240 			* SPEC (2.1.2) "R's {attribute declaration}'s
14241 			* {type definition} must be validly derived from
14242 			* B's {type definition} given the empty set as
14243 			* defined in Type Derivation OK (Simple) ($3.14.6)."
14244 			*/
14245 			xmlSchemaPAttrUseErr4(pctxt,
14246 			    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_2,
14247 			    WXS_ITEM_NODE(item), item, cur,
14248 			    "The attribute declaration's %s "
14249 			    "is not validly derived from "
14250 			    "the corresponding %s of the "
14251 			    "attribute declaration in the %s %s",
14252 			    xmlSchemaGetComponentDesignation(&strA,
14253 				WXS_ATTRUSE_TYPEDEF(cur)),
14254 			    xmlSchemaGetComponentDesignation(&strB,
14255 				WXS_ATTRUSE_TYPEDEF(bcur)),
14256 			    WXS_ACTION_STR(action),
14257 			    xmlSchemaGetComponentDesignation(&strC, baseItem));
14258 			    /* xmlSchemaGetComponentDesignation(&str, baseItem), */
14259 			FREE_AND_NULL(strA);
14260 			FREE_AND_NULL(strB);
14261 			FREE_AND_NULL(strC);
14262 			/* err = pctxt->err; */
14263 		    } else {
14264 			/*
14265 			* 2.1.3 [Definition:]  Let the effective value
14266 			* constraint of an attribute use be its {value
14267 			* constraint}, if present, otherwise its {attribute
14268 			* declaration}'s {value constraint} .
14269 			*/
14270 			xmlSchemaGetEffectiveValueConstraint(bcur,
14271 			    &effFixed, &bEffValue, NULL);
14272 			/*
14273 			* 2.1.3 ... one of the following must be true
14274 			*
14275 			* 2.1.3.1 B's `effective value constraint` is
14276 			* `absent` or default.
14277 			*/
14278 			if ((bEffValue != NULL) &&
14279 			    (effFixed == 1)) {
14280 			    const xmlChar *rEffValue = NULL;
14281 
14282 			    xmlSchemaGetEffectiveValueConstraint(bcur,
14283 				&effFixed, &rEffValue, NULL);
14284 			    /*
14285 			    * 2.1.3.2 R's `effective value constraint` is
14286 			    * fixed with the same string as B's.
14287 			    * MAYBE TODO: Compare the computed values.
14288 			    *       Hmm, it says "same string" so
14289 			    *       string-equality might really be sufficient.
14290 			    */
14291 			    if ((effFixed == 0) ||
14292 				(! WXS_ARE_DEFAULT_STR_EQUAL(rEffValue, bEffValue)))
14293 			    {
14294 				xmlChar *str = NULL;
14295 
14296 				xmlSchemaPAttrUseErr4(pctxt,
14297 				    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
14298 				    WXS_ITEM_NODE(item), item, cur,
14299 				    "The effective value constraint of the "
14300 				    "attribute use is inconsistent with "
14301 				    "its correspondent in the %s %s",
14302 				    WXS_ACTION_STR(action),
14303 				    xmlSchemaGetComponentDesignation(&str,
14304 					baseItem),
14305 				    NULL, NULL);
14306 				FREE_AND_NULL(str);
14307 				/* err = pctxt->err; */
14308 			    }
14309 			}
14310 		    }
14311 		    break;
14312 		}
14313 	    }
14314 not_found:
14315 	    if (!found) {
14316 		/*
14317 		* (2.2) "otherwise the {base type definition} must have an
14318 		* {attribute wildcard} and the {target namespace} of the
14319 		* R's {attribute declaration} must be `valid` with respect
14320 		* to that wildcard, as defined in Wildcard allows Namespace
14321 		* Name ($3.10.4)."
14322 		*/
14323 		if ((baseWild == NULL) ||
14324 		    (xmlSchemaCheckCVCWildcardNamespace(baseWild,
14325 		    (WXS_ATTRUSE_DECL(cur))->targetNamespace) != 0))
14326 		{
14327 		    xmlChar *str = NULL;
14328 
14329 		    xmlSchemaPAttrUseErr4(pctxt,
14330 			XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
14331 			WXS_ITEM_NODE(item), item, cur,
14332 			"Neither a matching attribute use, "
14333 			"nor a matching wildcard exists in the %s %s",
14334 			WXS_ACTION_STR(action),
14335 			xmlSchemaGetComponentDesignation(&str, baseItem),
14336 			NULL, NULL);
14337 		    FREE_AND_NULL(str);
14338 		    /* err = pctxt->err; */
14339 		}
14340 	    }
14341 	}
14342     }
14343     /*
14344     * SPEC derivation-ok-restriction (3):
14345     * (3) "For each attribute use in the {attribute uses} of the {base type
14346     * definition} whose {required} is true, there must be an attribute
14347     * use with an {attribute declaration} with the same {name} and
14348     * {target namespace} as its {attribute declaration} in the {attribute
14349     * uses} of the complex type definition itself whose {required} is true.
14350     */
14351     if (baseUses != NULL) {
14352 	for (j = 0; j < baseUses->nbItems; j++) {
14353 	    bcur = baseUses->items[j];
14354 	    if (bcur->occurs != XML_SCHEMAS_ATTR_USE_REQUIRED)
14355 		continue;
14356 	    found = 0;
14357 	    if (uses != NULL) {
14358 		for (i = 0; i < uses->nbItems; i++) {
14359 		    cur = uses->items[i];
14360 		    if ((WXS_ATTRUSE_DECL_NAME(cur) ==
14361 			WXS_ATTRUSE_DECL_NAME(bcur)) &&
14362 			(WXS_ATTRUSE_DECL_TNS(cur) ==
14363 			WXS_ATTRUSE_DECL_TNS(bcur))) {
14364 			found = 1;
14365 			break;
14366 		    }
14367 		}
14368 	    }
14369 	    if (!found) {
14370 		xmlChar *strA = NULL, *strB = NULL;
14371 
14372 		xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14373 		    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
14374 		    NULL, item,
14375 		    "A matching attribute use for the "
14376 		    "'required' %s of the %s %s is missing",
14377 		    xmlSchemaGetComponentDesignation(&strA, bcur),
14378 		    WXS_ACTION_STR(action),
14379 		    xmlSchemaGetComponentDesignation(&strB, baseItem),
14380 		    NULL);
14381 		FREE_AND_NULL(strA);
14382 		FREE_AND_NULL(strB);
14383 	    }
14384 	}
14385     }
14386     /*
14387     * derivation-ok-restriction (4)
14388     */
14389     if (wild != NULL) {
14390 	/*
14391 	* (4) "If there is an {attribute wildcard}, all of the
14392 	* following must be true:"
14393 	*/
14394 	if (baseWild == NULL) {
14395 	    xmlChar *str = NULL;
14396 
14397 	    /*
14398 	    * (4.1) "The {base type definition} must also have one."
14399 	    */
14400 	    xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14401 		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
14402 		NULL, item,
14403 		"The %s has an attribute wildcard, "
14404 		"but the %s %s '%s' does not have one",
14405 		WXS_ITEM_TYPE_NAME(item),
14406 		WXS_ACTION_STR(action),
14407 		WXS_ITEM_TYPE_NAME(baseItem),
14408 		xmlSchemaGetComponentQName(&str, baseItem));
14409 	    FREE_AND_NULL(str);
14410 	    return(pctxt->err);
14411 	} else if ((baseWild->any == 0) &&
14412 		xmlSchemaCheckCOSNSSubset(wild, baseWild))
14413 	{
14414 	    xmlChar *str = NULL;
14415 	    /*
14416 	    * (4.2) "The complex type definition's {attribute wildcard}'s
14417 	    * {namespace constraint} must be a subset of the {base type
14418 	    * definition}'s {attribute wildcard}'s {namespace constraint},
14419 	    * as defined by Wildcard Subset ($3.10.6)."
14420 	    */
14421 	    xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14422 		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
14423 		NULL, item,
14424 		"The attribute wildcard is not a valid "
14425 		"subset of the wildcard in the %s %s '%s'",
14426 		WXS_ACTION_STR(action),
14427 		WXS_ITEM_TYPE_NAME(baseItem),
14428 		xmlSchemaGetComponentQName(&str, baseItem),
14429 		NULL);
14430 	    FREE_AND_NULL(str);
14431 	    return(pctxt->err);
14432 	}
14433 	/* 4.3 Unless the {base type definition} is the `ur-type
14434 	* definition`, the complex type definition's {attribute
14435 	* wildcard}'s {process contents} must be identical to or
14436 	* stronger than the {base type definition}'s {attribute
14437 	* wildcard}'s {process contents}, where strict is stronger
14438 	* than lax is stronger than skip.
14439 	*/
14440 	if ((! WXS_IS_ANYTYPE(baseItem)) &&
14441 	    (wild->processContents < baseWild->processContents)) {
14442 	    xmlChar *str = NULL;
14443 	    xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14444 		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
14445 		NULL, baseItem,
14446 		"The {process contents} of the attribute wildcard is "
14447 		"weaker than the one in the %s %s '%s'",
14448 		WXS_ACTION_STR(action),
14449 		WXS_ITEM_TYPE_NAME(baseItem),
14450 		xmlSchemaGetComponentQName(&str, baseItem),
14451 		NULL);
14452 	    FREE_AND_NULL(str)
14453 		return(pctxt->err);
14454 	}
14455     }
14456     return(0);
14457 }
14458 
14459 
14460 static int
14461 xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
14462 				  xmlSchemaBasicItemPtr item,
14463 				  xmlSchemaWildcardPtr *completeWild,
14464 				  xmlSchemaItemListPtr list,
14465 				  xmlSchemaItemListPtr prohibs);
14466 /**
14467  * xmlSchemaFixupTypeAttributeUses:
14468  * @ctxt:  the schema parser context
14469  * @type:  the complex type definition
14470  *
14471  *
14472  * Builds the wildcard and the attribute uses on the given complex type.
14473  * Returns -1 if an internal error occurs, 0 otherwise.
14474  *
14475  * ATTENTION TODO: Experimantally this uses pointer comparisons for
14476  * strings, so recheck this if we start to hardcode some schemata, since
14477  * they might not be in the same dict.
14478  * NOTE: It is allowed to "extend" the xs:anyType type.
14479  */
14480 static int
xmlSchemaFixupTypeAttributeUses(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)14481 xmlSchemaFixupTypeAttributeUses(xmlSchemaParserCtxtPtr pctxt,
14482 				  xmlSchemaTypePtr type)
14483 {
14484     xmlSchemaTypePtr baseType = NULL;
14485     xmlSchemaAttributeUsePtr use;
14486     xmlSchemaItemListPtr uses, baseUses, prohibs = NULL;
14487 
14488     if (type->baseType == NULL) {
14489 	PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14490 	    "no base type");
14491         return (-1);
14492     }
14493     baseType = type->baseType;
14494     if (WXS_IS_TYPE_NOT_FIXED(baseType))
14495 	if (xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt) == -1)
14496 	    return(-1);
14497 
14498     uses = type->attrUses;
14499     baseUses = baseType->attrUses;
14500     /*
14501     * Expand attribute group references. And build the 'complete'
14502     * wildcard, i.e. intersect multiple wildcards.
14503     * Move attribute prohibitions into a separate list.
14504     */
14505     if (uses != NULL) {
14506 	if (WXS_IS_RESTRICTION(type)) {
14507 	    /*
14508 	    * This one will transfer all attr. prohibitions
14509 	    * into pctxt->attrProhibs.
14510 	    */
14511 	    if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14512 		WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14513 		pctxt->attrProhibs) == -1)
14514 	    {
14515 		PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14516 		"failed to expand attributes");
14517 	    }
14518 	    if (pctxt->attrProhibs->nbItems != 0)
14519 		prohibs = pctxt->attrProhibs;
14520 	} else {
14521 	    if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14522 		WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14523 		NULL) == -1)
14524 	    {
14525 		PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14526 		"failed to expand attributes");
14527 	    }
14528 	}
14529     }
14530     /*
14531     * Inherit the attribute uses of the base type.
14532     */
14533     if (baseUses != NULL) {
14534 	int i, j;
14535 	xmlSchemaAttributeUseProhibPtr pro;
14536 
14537 	if (WXS_IS_RESTRICTION(type)) {
14538 	    int usesCount;
14539 	    xmlSchemaAttributeUsePtr tmp;
14540 
14541 	    if (uses != NULL)
14542 		usesCount = uses->nbItems;
14543 	    else
14544 		usesCount = 0;
14545 
14546 	    /* Restriction. */
14547 	    for (i = 0; i < baseUses->nbItems; i++) {
14548 		use = baseUses->items[i];
14549 		if (prohibs) {
14550 		    /*
14551 		    * Filter out prohibited uses.
14552 		    */
14553 		    for (j = 0; j < prohibs->nbItems; j++) {
14554 			pro = prohibs->items[j];
14555 			if ((WXS_ATTRUSE_DECL_NAME(use) == pro->name) &&
14556 			    (WXS_ATTRUSE_DECL_TNS(use) ==
14557 				pro->targetNamespace))
14558 			{
14559 			    goto inherit_next;
14560 			}
14561 		    }
14562 		}
14563 		if (usesCount) {
14564 		    /*
14565 		    * Filter out existing uses.
14566 		    */
14567 		    for (j = 0; j < usesCount; j++) {
14568 			tmp = uses->items[j];
14569 			if ((WXS_ATTRUSE_DECL_NAME(use) ==
14570 				WXS_ATTRUSE_DECL_NAME(tmp)) &&
14571 			    (WXS_ATTRUSE_DECL_TNS(use) ==
14572 				WXS_ATTRUSE_DECL_TNS(tmp)))
14573 			{
14574 			    goto inherit_next;
14575 			}
14576 		    }
14577 		}
14578 		if (uses == NULL) {
14579 		    type->attrUses = xmlSchemaItemListCreate();
14580 		    if (type->attrUses == NULL)
14581 			goto exit_failure;
14582 		    uses = type->attrUses;
14583 		}
14584 		xmlSchemaItemListAddSize(uses, 2, use);
14585 inherit_next: {}
14586 	    }
14587 	} else {
14588 	    /* Extension. */
14589 	    for (i = 0; i < baseUses->nbItems; i++) {
14590 		use = baseUses->items[i];
14591 		if (uses == NULL) {
14592 		    type->attrUses = xmlSchemaItemListCreate();
14593 		    if (type->attrUses == NULL)
14594 			goto exit_failure;
14595 		    uses = type->attrUses;
14596 		}
14597 		xmlSchemaItemListAddSize(uses, baseUses->nbItems, use);
14598 	    }
14599 	}
14600     }
14601     /*
14602     * Shrink attr. uses.
14603     */
14604     if (uses) {
14605 	if (uses->nbItems == 0) {
14606 	    xmlSchemaItemListFree(uses);
14607 	    type->attrUses = NULL;
14608 	}
14609 	/*
14610 	* TODO: We could shrink the size of the array
14611 	* to fit the actual number of items.
14612 	*/
14613     }
14614     /*
14615     * Compute the complete wildcard.
14616     */
14617     if (WXS_IS_EXTENSION(type)) {
14618 	if (baseType->attributeWildcard != NULL) {
14619 	    /*
14620 	    * (3.2.2.1) "If the `base wildcard` is non-`absent`, then
14621 	    * the appropriate case among the following:"
14622 	    */
14623 	    if (type->attributeWildcard != NULL) {
14624 		/*
14625 		* Union the complete wildcard with the base wildcard.
14626 		* SPEC {attribute wildcard}
14627 		* (3.2.2.1.2) "otherwise a wildcard whose {process contents}
14628 		* and {annotation} are those of the `complete wildcard`,
14629 		* and whose {namespace constraint} is the intensional union
14630 		* of the {namespace constraint} of the `complete wildcard`
14631 		* and of the `base wildcard`, as defined in Attribute
14632 		* Wildcard Union ($3.10.6)."
14633 		*/
14634 		if (xmlSchemaUnionWildcards(pctxt, type->attributeWildcard,
14635 		    baseType->attributeWildcard) == -1)
14636 		    goto exit_failure;
14637 	    } else {
14638 		/*
14639 		* (3.2.2.1.1) "If the `complete wildcard` is `absent`,
14640 		* then the `base wildcard`."
14641 		*/
14642 		type->attributeWildcard = baseType->attributeWildcard;
14643 	    }
14644 	} else {
14645 	    /*
14646 	    * (3.2.2.2) "otherwise (the `base wildcard` is `absent`) the
14647 	    * `complete wildcard`"
14648 	    * NOOP
14649 	    */
14650 	}
14651     } else {
14652 	/*
14653 	* SPEC {attribute wildcard}
14654 	* (3.1) "If the <restriction> alternative is chosen, then the
14655 	* `complete wildcard`;"
14656 	* NOOP
14657 	*/
14658     }
14659 
14660     return (0);
14661 
14662 exit_failure:
14663     return(-1);
14664 }
14665 
14666 /**
14667  * xmlSchemaTypeFinalContains:
14668  * @schema:  the schema
14669  * @type:  the type definition
14670  * @final: the final
14671  *
14672  * Evaluates if a type definition contains the given "final".
14673  * This does take "finalDefault" into account as well.
14674  *
14675  * Returns 1 if the type does containt the given "final",
14676  * 0 otherwise.
14677  */
14678 static int
xmlSchemaTypeFinalContains(xmlSchemaTypePtr type,int final)14679 xmlSchemaTypeFinalContains(xmlSchemaTypePtr type, int final)
14680 {
14681     if (type == NULL)
14682 	return (0);
14683     if (type->flags & final)
14684 	return (1);
14685     else
14686 	return (0);
14687 }
14688 
14689 /**
14690  * xmlSchemaGetUnionSimpleTypeMemberTypes:
14691  * @type:  the Union Simple Type
14692  *
14693  * Returns a list of member types of @type if existing,
14694  * returns NULL otherwise.
14695  */
14696 static xmlSchemaTypeLinkPtr
xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)14697 xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
14698 {
14699     while ((type != NULL) && (type->type == XML_SCHEMA_TYPE_SIMPLE)) {
14700 	if (type->memberTypes != NULL)
14701 	    return (type->memberTypes);
14702 	else
14703 	    type = type->baseType;
14704     }
14705     return (NULL);
14706 }
14707 
14708 /**
14709  * xmlSchemaGetParticleTotalRangeMin:
14710  * @particle: the particle
14711  *
14712  * Schema Component Constraint: Effective Total Range
14713  * (all and sequence) + (choice)
14714  *
14715  * Returns the minimun Effective Total Range.
14716  */
14717 static int
xmlSchemaGetParticleTotalRangeMin(xmlSchemaParticlePtr particle)14718 xmlSchemaGetParticleTotalRangeMin(xmlSchemaParticlePtr particle)
14719 {
14720     if ((particle->children == NULL) ||
14721 	(particle->minOccurs == 0))
14722 	return (0);
14723     if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14724 	int min = -1, cur;
14725 	xmlSchemaParticlePtr part =
14726 	    (xmlSchemaParticlePtr) particle->children->children;
14727 
14728 	if (part == NULL)
14729 	    return (0);
14730 	while (part != NULL) {
14731 	    if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14732 		(part->children->type == XML_SCHEMA_TYPE_ANY))
14733 		cur = part->minOccurs;
14734 	    else
14735 		cur = xmlSchemaGetParticleTotalRangeMin(part);
14736 	    if (cur == 0)
14737 		return (0);
14738 	    if ((min > cur) || (min == -1))
14739 		min = cur;
14740 	    part = (xmlSchemaParticlePtr) part->next;
14741 	}
14742 	return (particle->minOccurs * min);
14743     } else {
14744 	/* <all> and <sequence> */
14745 	int sum = 0;
14746 	xmlSchemaParticlePtr part =
14747 	    (xmlSchemaParticlePtr) particle->children->children;
14748 
14749 	if (part == NULL)
14750 	    return (0);
14751 	do {
14752 	    if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14753 		(part->children->type == XML_SCHEMA_TYPE_ANY))
14754 		sum += part->minOccurs;
14755 	    else
14756 		sum += xmlSchemaGetParticleTotalRangeMin(part);
14757 	    part = (xmlSchemaParticlePtr) part->next;
14758 	} while (part != NULL);
14759 	return (particle->minOccurs * sum);
14760     }
14761 }
14762 
14763 #if 0
14764 /**
14765  * xmlSchemaGetParticleTotalRangeMax:
14766  * @particle: the particle
14767  *
14768  * Schema Component Constraint: Effective Total Range
14769  * (all and sequence) + (choice)
14770  *
14771  * Returns the maximum Effective Total Range.
14772  */
14773 static int
14774 xmlSchemaGetParticleTotalRangeMax(xmlSchemaParticlePtr particle)
14775 {
14776     if ((particle->children == NULL) ||
14777 	(particle->children->children == NULL))
14778 	return (0);
14779     if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14780 	int max = -1, cur;
14781 	xmlSchemaParticlePtr part =
14782 	    (xmlSchemaParticlePtr) particle->children->children;
14783 
14784 	for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14785 	    if (part->children == NULL)
14786 		continue;
14787 	    if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14788 		(part->children->type == XML_SCHEMA_TYPE_ANY))
14789 		cur = part->maxOccurs;
14790 	    else
14791 		cur = xmlSchemaGetParticleTotalRangeMax(part);
14792 	    if (cur == UNBOUNDED)
14793 		return (UNBOUNDED);
14794 	    if ((max < cur) || (max == -1))
14795 		max = cur;
14796 	}
14797 	/* TODO: Handle overflows? */
14798 	return (particle->maxOccurs * max);
14799     } else {
14800 	/* <all> and <sequence> */
14801 	int sum = 0, cur;
14802 	xmlSchemaParticlePtr part =
14803 	    (xmlSchemaParticlePtr) particle->children->children;
14804 
14805 	for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14806 	    if (part->children == NULL)
14807 		continue;
14808 	    if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14809 		(part->children->type == XML_SCHEMA_TYPE_ANY))
14810 		cur = part->maxOccurs;
14811 	    else
14812 		cur = xmlSchemaGetParticleTotalRangeMax(part);
14813 	    if (cur == UNBOUNDED)
14814 		return (UNBOUNDED);
14815 	    if ((cur > 0) && (particle->maxOccurs == UNBOUNDED))
14816 		return (UNBOUNDED);
14817 	    sum += cur;
14818 	}
14819 	/* TODO: Handle overflows? */
14820 	return (particle->maxOccurs * sum);
14821     }
14822 }
14823 #endif
14824 
14825 /**
14826  * xmlSchemaIsParticleEmptiable:
14827  * @particle: the particle
14828  *
14829  * Schema Component Constraint: Particle Emptiable
14830  * Checks whether the given particle is emptiable.
14831  *
14832  * Returns 1 if emptiable, 0 otherwise.
14833  */
14834 static int
xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)14835 xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)
14836 {
14837     /*
14838     * SPEC (1) "Its {min occurs} is 0."
14839     */
14840     if ((particle == NULL) || (particle->minOccurs == 0) ||
14841 	(particle->children == NULL))
14842 	return (1);
14843     /*
14844     * SPEC (2) "Its {term} is a group and the minimum part of the
14845     * effective total range of that group, [...] is 0."
14846     */
14847     if (WXS_IS_MODEL_GROUP(particle->children)) {
14848 	if (xmlSchemaGetParticleTotalRangeMin(particle) == 0)
14849 	    return (1);
14850     }
14851     return (0);
14852 }
14853 
14854 /**
14855  * xmlSchemaCheckCOSSTDerivedOK:
14856  * @actxt: a context
14857  * @type:  the derived simple type definition
14858  * @baseType:  the base type definition
14859  * @subset: the subset of ('restriction', ect.)
14860  *
14861  * Schema Component Constraint:
14862  * Type Derivation OK (Simple) (cos-st-derived-OK)
14863  *
14864  * Checks wheter @type can be validly
14865  * derived from @baseType.
14866  *
14867  * Returns 0 on success, an positive error code otherwise.
14868  */
14869 static int
xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,xmlSchemaTypePtr type,xmlSchemaTypePtr baseType,int subset)14870 xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
14871 			     xmlSchemaTypePtr type,
14872 			     xmlSchemaTypePtr baseType,
14873 			     int subset)
14874 {
14875     /*
14876     * 1 They are the same type definition.
14877     * TODO: The identy check might have to be more complex than this.
14878     */
14879     if (type == baseType)
14880 	return (0);
14881     /*
14882     * 2.1 restriction is not in the subset, or in the {final}
14883     * of its own {base type definition};
14884     *
14885     * NOTE that this will be used also via "xsi:type".
14886     *
14887     * TODO: Revise this, it looks strange. How can the "type"
14888     * not be fixed or *in* fixing?
14889     */
14890     if (WXS_IS_TYPE_NOT_FIXED(type))
14891 	if (xmlSchemaTypeFixup(type, actxt) == -1)
14892 	    return(-1);
14893     if (WXS_IS_TYPE_NOT_FIXED(baseType))
14894 	if (xmlSchemaTypeFixup(baseType, actxt) == -1)
14895 	    return(-1);
14896     if ((subset & SUBSET_RESTRICTION) ||
14897 	(xmlSchemaTypeFinalContains(type->baseType,
14898 	    XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
14899 	return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
14900     }
14901     /* 2.2 */
14902     if (type->baseType == baseType) {
14903 	/*
14904 	* 2.2.1 D's `base type definition` is B.
14905 	*/
14906 	return (0);
14907     }
14908     /*
14909     * 2.2.2 D's `base type definition` is not the `ur-type definition`
14910     * and is validly derived from B given the subset, as defined by this
14911     * constraint.
14912     */
14913     if ((! WXS_IS_ANYTYPE(type->baseType)) &&
14914 	(xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
14915 	    baseType, subset) == 0)) {
14916 	return (0);
14917     }
14918     /*
14919     * 2.2.3 D's {variety} is list or union and B is the `simple ur-type
14920     * definition`.
14921     */
14922     if (WXS_IS_ANY_SIMPLE_TYPE(baseType) &&
14923 	(WXS_IS_LIST(type) || WXS_IS_UNION(type))) {
14924 	return (0);
14925     }
14926     /*
14927     * 2.2.4 B's {variety} is union and D is validly derived from a type
14928     * definition in B's {member type definitions} given the subset, as
14929     * defined by this constraint.
14930     *
14931     * NOTE: This seems not to involve built-in types, since there is no
14932     * built-in Union Simple Type.
14933     */
14934     if (WXS_IS_UNION(baseType)) {
14935 	xmlSchemaTypeLinkPtr cur;
14936 
14937 	cur = baseType->memberTypes;
14938 	while (cur != NULL) {
14939 	    if (WXS_IS_TYPE_NOT_FIXED(cur->type))
14940 		if (xmlSchemaTypeFixup(cur->type, actxt) == -1)
14941 		    return(-1);
14942 	    if (xmlSchemaCheckCOSSTDerivedOK(actxt,
14943 		    type, cur->type, subset) == 0)
14944 	    {
14945 		/*
14946 		* It just has to be validly derived from at least one
14947 		* member-type.
14948 		*/
14949 		return (0);
14950 	    }
14951 	    cur = cur->next;
14952 	}
14953     }
14954     return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
14955 }
14956 
14957 /**
14958  * xmlSchemaCheckTypeDefCircularInternal:
14959  * @pctxt:  the schema parser context
14960  * @ctxtType:  the type definition
14961  * @ancestor: an ancestor of @ctxtType
14962  *
14963  * Checks st-props-correct (2) + ct-props-correct (3).
14964  * Circular type definitions are not allowed.
14965  *
14966  * Returns XML_SCHEMAP_ST_PROPS_CORRECT_2 if the given type is
14967  * circular, 0 otherwise.
14968  */
14969 static int
xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr ctxtType,xmlSchemaTypePtr ancestor)14970 xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,
14971 			   xmlSchemaTypePtr ctxtType,
14972 			   xmlSchemaTypePtr ancestor)
14973 {
14974     int ret;
14975 
14976     if ((ancestor == NULL) || (ancestor->type == XML_SCHEMA_TYPE_BASIC))
14977 	return (0);
14978 
14979     if (ctxtType == ancestor) {
14980 	xmlSchemaPCustomErr(pctxt,
14981 	    XML_SCHEMAP_ST_PROPS_CORRECT_2,
14982 	    WXS_BASIC_CAST ctxtType, WXS_ITEM_NODE(ctxtType),
14983 	    "The definition is circular", NULL);
14984 	return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
14985     }
14986     if (ancestor->flags & XML_SCHEMAS_TYPE_MARKED) {
14987 	/*
14988 	* Avoid inifinite recursion on circular types not yet checked.
14989 	*/
14990 	return (0);
14991     }
14992     ancestor->flags |= XML_SCHEMAS_TYPE_MARKED;
14993     ret = xmlSchemaCheckTypeDefCircularInternal(pctxt, ctxtType,
14994 	ancestor->baseType);
14995     ancestor->flags ^= XML_SCHEMAS_TYPE_MARKED;
14996     return (ret);
14997 }
14998 
14999 /**
15000  * xmlSchemaCheckTypeDefCircular:
15001  * @item:  the complex/simple type definition
15002  * @ctxt:  the parser context
15003  * @name:  the name
15004  *
15005  * Checks for circular type definitions.
15006  */
15007 static void
xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,xmlSchemaParserCtxtPtr ctxt)15008 xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,
15009 			      xmlSchemaParserCtxtPtr ctxt)
15010 {
15011     if ((item == NULL) ||
15012 	(item->type == XML_SCHEMA_TYPE_BASIC) ||
15013 	(item->baseType == NULL))
15014 	return;
15015     xmlSchemaCheckTypeDefCircularInternal(ctxt, item,
15016 	item->baseType);
15017 }
15018 
15019 /*
15020 * Simple Type Definition Representation OK (src-simple-type) 4
15021 *
15022 * "4 Circular union type definition is disallowed. That is, if the
15023 * <union> alternative is chosen, there must not be any entries in the
15024 * memberTypes [attribute] at any depth which resolve to the component
15025 * corresponding to the <simpleType>."
15026 *
15027 * Note that this should work on the *representation* of a component,
15028 * thus assumes any union types in the member types not being yet
15029 * substituted. At this stage we need the variety of the types
15030 * to be already computed.
15031 */
15032 static int
xmlSchemaCheckUnionTypeDefCircularRecur(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr ctxType,xmlSchemaTypeLinkPtr members)15033 xmlSchemaCheckUnionTypeDefCircularRecur(xmlSchemaParserCtxtPtr pctxt,
15034 					xmlSchemaTypePtr ctxType,
15035 					xmlSchemaTypeLinkPtr members)
15036 {
15037     xmlSchemaTypeLinkPtr member;
15038     xmlSchemaTypePtr memberType;
15039 
15040     member = members;
15041     while (member != NULL) {
15042 	memberType = member->type;
15043 	while ((memberType != NULL) &&
15044 	    (memberType->type != XML_SCHEMA_TYPE_BASIC)) {
15045 	    if (memberType == ctxType) {
15046 		xmlSchemaPCustomErr(pctxt,
15047 		    XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
15048 		    WXS_BASIC_CAST ctxType, NULL,
15049 		    "The union type definition is circular", NULL);
15050 		return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
15051 	    }
15052 	    if ((WXS_IS_UNION(memberType)) &&
15053 		((memberType->flags & XML_SCHEMAS_TYPE_MARKED) == 0))
15054 	    {
15055 		int res;
15056 		memberType->flags |= XML_SCHEMAS_TYPE_MARKED;
15057 		res = xmlSchemaCheckUnionTypeDefCircularRecur(pctxt,
15058 		    ctxType,
15059 		    xmlSchemaGetUnionSimpleTypeMemberTypes(memberType));
15060 		memberType->flags ^= XML_SCHEMAS_TYPE_MARKED;
15061 		if (res != 0)
15062 		    return(res);
15063 	    }
15064 	    memberType = memberType->baseType;
15065 	}
15066 	member = member->next;
15067     }
15068     return(0);
15069 }
15070 
15071 static int
xmlSchemaCheckUnionTypeDefCircular(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)15072 xmlSchemaCheckUnionTypeDefCircular(xmlSchemaParserCtxtPtr pctxt,
15073 				   xmlSchemaTypePtr type)
15074 {
15075     if (! WXS_IS_UNION(type))
15076 	return(0);
15077     return(xmlSchemaCheckUnionTypeDefCircularRecur(pctxt, type,
15078 	type->memberTypes));
15079 }
15080 
15081 /**
15082  * xmlSchemaResolveTypeReferences:
15083  * @item:  the complex/simple type definition
15084  * @ctxt:  the parser context
15085  * @name:  the name
15086  *
15087  * Resolvese type definition references
15088  */
15089 static void
xmlSchemaResolveTypeReferences(xmlSchemaTypePtr typeDef,xmlSchemaParserCtxtPtr ctxt)15090 xmlSchemaResolveTypeReferences(xmlSchemaTypePtr typeDef,
15091 			 xmlSchemaParserCtxtPtr ctxt)
15092 {
15093     if (typeDef == NULL)
15094 	return;
15095 
15096     /*
15097     * Resolve the base type.
15098     */
15099     if (typeDef->baseType == NULL) {
15100 	typeDef->baseType = xmlSchemaGetType(ctxt->schema,
15101 	    typeDef->base, typeDef->baseNs);
15102 	if (typeDef->baseType == NULL) {
15103 	    xmlSchemaPResCompAttrErr(ctxt,
15104 		XML_SCHEMAP_SRC_RESOLVE,
15105 		WXS_BASIC_CAST typeDef, typeDef->node,
15106 		"base", typeDef->base, typeDef->baseNs,
15107 		XML_SCHEMA_TYPE_SIMPLE, NULL);
15108 	    return;
15109 	}
15110     }
15111     if (WXS_IS_SIMPLE(typeDef)) {
15112 	if (WXS_IS_UNION(typeDef)) {
15113 	    /*
15114 	    * Resolve the memberTypes.
15115 	    */
15116 	    xmlSchemaResolveUnionMemberTypes(ctxt, typeDef);
15117 	    return;
15118 	} else if (WXS_IS_LIST(typeDef)) {
15119 	    /*
15120 	    * Resolve the itemType.
15121 	    */
15122 	    if ((typeDef->subtypes == NULL) && (typeDef->base != NULL)) {
15123 
15124 		typeDef->subtypes = xmlSchemaGetType(ctxt->schema,
15125 		    typeDef->base, typeDef->baseNs);
15126 
15127 		if ((typeDef->subtypes == NULL) ||
15128 		    (! WXS_IS_SIMPLE(typeDef->subtypes)))
15129 		{
15130 		    typeDef->subtypes = NULL;
15131 		    xmlSchemaPResCompAttrErr(ctxt,
15132 			XML_SCHEMAP_SRC_RESOLVE,
15133 			WXS_BASIC_CAST typeDef, typeDef->node,
15134 			"itemType", typeDef->base, typeDef->baseNs,
15135 			XML_SCHEMA_TYPE_SIMPLE, NULL);
15136 		}
15137 	    }
15138 	    return;
15139 	}
15140     }
15141     /*
15142     * The ball of letters below means, that if we have a particle
15143     * which has a QName-helper component as its {term}, we want
15144     * to resolve it...
15145     */
15146     else if ((WXS_TYPE_CONTENTTYPE(typeDef) != NULL) &&
15147 	((WXS_TYPE_CONTENTTYPE(typeDef))->type ==
15148 	    XML_SCHEMA_TYPE_PARTICLE) &&
15149 	(WXS_TYPE_PARTICLE_TERM(typeDef) != NULL) &&
15150 	((WXS_TYPE_PARTICLE_TERM(typeDef))->type ==
15151 	    XML_SCHEMA_EXTRA_QNAMEREF))
15152     {
15153 	xmlSchemaQNameRefPtr ref =
15154 	    WXS_QNAME_CAST WXS_TYPE_PARTICLE_TERM(typeDef);
15155 	xmlSchemaModelGroupDefPtr groupDef;
15156 
15157 	/*
15158 	* URGENT TODO: Test this.
15159 	*/
15160 	WXS_TYPE_PARTICLE_TERM(typeDef) = NULL;
15161 	/*
15162 	* Resolve the MG definition reference.
15163 	*/
15164 	groupDef =
15165 	    WXS_MODEL_GROUPDEF_CAST xmlSchemaGetNamedComponent(ctxt->schema,
15166 		ref->itemType, ref->name, ref->targetNamespace);
15167 	if (groupDef == NULL) {
15168 	    xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
15169 		NULL, WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)),
15170 		"ref", ref->name, ref->targetNamespace, ref->itemType,
15171 		NULL);
15172 	    /* Remove the particle. */
15173 	    WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
15174 	} else if (WXS_MODELGROUPDEF_MODEL(groupDef) == NULL)
15175 	    /* Remove the particle. */
15176 	    WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
15177 	else {
15178 	    /*
15179 	    * Assign the MG definition's {model group} to the
15180 	    * particle's {term}.
15181 	    */
15182 	    WXS_TYPE_PARTICLE_TERM(typeDef) = WXS_MODELGROUPDEF_MODEL(groupDef);
15183 
15184 	    if (WXS_MODELGROUPDEF_MODEL(groupDef)->type == XML_SCHEMA_TYPE_ALL) {
15185 		/*
15186 		* SPEC cos-all-limited (1.2)
15187 		* "1.2 the {term} property of a particle with
15188 		* {max occurs}=1 which is part of a pair which constitutes
15189 		* the {content type} of a complex type definition."
15190 		*/
15191 		if ((WXS_TYPE_PARTICLE(typeDef))->maxOccurs != 1) {
15192 		    xmlSchemaCustomErr(ACTXT_CAST ctxt,
15193 			/* TODO: error code */
15194 			XML_SCHEMAP_COS_ALL_LIMITED,
15195 			WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)), NULL,
15196 			"The particle's {max occurs} must be 1, since the "
15197 			"reference resolves to an 'all' model group",
15198 			NULL, NULL);
15199 		}
15200 	    }
15201 	}
15202     }
15203 }
15204 
15205 
15206 
15207 /**
15208  * xmlSchemaCheckSTPropsCorrect:
15209  * @ctxt:  the schema parser context
15210  * @type:  the simple type definition
15211  *
15212  * Checks st-props-correct.
15213  *
15214  * Returns 0 if the properties are correct,
15215  * if not, a positive error code and -1 on internal
15216  * errors.
15217  */
15218 static int
xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,xmlSchemaTypePtr type)15219 xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
15220 			     xmlSchemaTypePtr type)
15221 {
15222     xmlSchemaTypePtr baseType = type->baseType;
15223     xmlChar *str = NULL;
15224 
15225     /* STATE: error funcs converted. */
15226     /*
15227     * Schema Component Constraint: Simple Type Definition Properties Correct
15228     *
15229     * NOTE: This is somehow redundant, since we actually built a simple type
15230     * to have all the needed information; this acts as an self test.
15231     */
15232     /* Base type: If the datatype has been `derived` by `restriction`
15233     * then the Simple Type Definition component from which it is `derived`,
15234     * otherwise the Simple Type Definition for anySimpleType ($4.1.6).
15235     */
15236     if (baseType == NULL) {
15237 	/*
15238 	* TODO: Think about: "modulo the impact of Missing
15239 	* Sub-components ($5.3)."
15240 	*/
15241 	xmlSchemaPCustomErr(ctxt,
15242 	    XML_SCHEMAP_ST_PROPS_CORRECT_1,
15243 	    WXS_BASIC_CAST type, NULL,
15244 	    "No base type existent", NULL);
15245 	return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15246 
15247     }
15248     if (! WXS_IS_SIMPLE(baseType)) {
15249 	xmlSchemaPCustomErr(ctxt,
15250 	    XML_SCHEMAP_ST_PROPS_CORRECT_1,
15251 	    WXS_BASIC_CAST type, NULL,
15252 	    "The base type '%s' is not a simple type",
15253 	    xmlSchemaGetComponentQName(&str, baseType));
15254 	FREE_AND_NULL(str)
15255 	return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15256     }
15257     if ((WXS_IS_LIST(type) || WXS_IS_UNION(type)) &&
15258 	(WXS_IS_RESTRICTION(type) == 0) &&
15259 	((! WXS_IS_ANY_SIMPLE_TYPE(baseType)) &&
15260          (baseType->type != XML_SCHEMA_TYPE_SIMPLE))) {
15261 	xmlSchemaPCustomErr(ctxt,
15262 	    XML_SCHEMAP_ST_PROPS_CORRECT_1,
15263 	    WXS_BASIC_CAST type, NULL,
15264 	    "A type, derived by list or union, must have "
15265 	    "the simple ur-type definition as base type, not '%s'",
15266 	    xmlSchemaGetComponentQName(&str, baseType));
15267 	FREE_AND_NULL(str)
15268 	return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15269     }
15270     /*
15271     * Variety: One of {atomic, list, union}.
15272     */
15273     if ((! WXS_IS_ATOMIC(type)) && (! WXS_IS_UNION(type)) &&
15274 	(! WXS_IS_LIST(type))) {
15275 	xmlSchemaPCustomErr(ctxt,
15276 	    XML_SCHEMAP_ST_PROPS_CORRECT_1,
15277 	    WXS_BASIC_CAST type, NULL,
15278 	    "The variety is absent", NULL);
15279 	return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15280     }
15281     /* TODO: Finish this. Hmm, is this finished? */
15282 
15283     /*
15284     * 3 The {final} of the {base type definition} must not contain restriction.
15285     */
15286     if (xmlSchemaTypeFinalContains(baseType,
15287 	XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15288 	xmlSchemaPCustomErr(ctxt,
15289 	    XML_SCHEMAP_ST_PROPS_CORRECT_3,
15290 	    WXS_BASIC_CAST type, NULL,
15291 	    "The 'final' of its base type '%s' must not contain "
15292 	    "'restriction'",
15293 	    xmlSchemaGetComponentQName(&str, baseType));
15294 	FREE_AND_NULL(str)
15295 	return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
15296     }
15297 
15298     /*
15299     * 2 All simple type definitions must be derived ultimately from the `simple
15300     * ur-type definition` (so circular definitions are disallowed). That is, it
15301     * must be possible to reach a built-in primitive datatype or the `simple
15302     * ur-type definition` by repeatedly following the {base type definition}.
15303     *
15304     * NOTE: this is done in xmlSchemaCheckTypeDefCircular().
15305     */
15306     return (0);
15307 }
15308 
15309 /**
15310  * xmlSchemaCheckCOSSTRestricts:
15311  * @ctxt:  the schema parser context
15312  * @type:  the simple type definition
15313  *
15314  * Schema Component Constraint:
15315  * Derivation Valid (Restriction, Simple) (cos-st-restricts)
15316 
15317  * Checks if the given @type (simpleType) is derived validly by restriction.
15318  * STATUS:
15319  *
15320  * Returns -1 on internal errors, 0 if the type is validly derived,
15321  * a positive error code otherwise.
15322  */
15323 static int
xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)15324 xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt,
15325 			     xmlSchemaTypePtr type)
15326 {
15327     xmlChar *str = NULL;
15328 
15329     if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
15330 	PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15331 	    "given type is not a user-derived simpleType");
15332 	return (-1);
15333     }
15334 
15335     if (WXS_IS_ATOMIC(type)) {
15336 	xmlSchemaTypePtr primitive;
15337 	/*
15338 	* 1.1 The {base type definition} must be an atomic simple
15339 	* type definition or a built-in primitive datatype.
15340 	*/
15341 	if (! WXS_IS_ATOMIC(type->baseType)) {
15342 	    xmlSchemaPCustomErr(pctxt,
15343 		XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
15344 		WXS_BASIC_CAST type, NULL,
15345 		"The base type '%s' is not an atomic simple type",
15346 		xmlSchemaGetComponentQName(&str, type->baseType));
15347 	    FREE_AND_NULL(str)
15348 	    return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
15349 	}
15350 	/* 1.2 The {final} of the {base type definition} must not contain
15351 	* restriction.
15352 	*/
15353 	/* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
15354 	if (xmlSchemaTypeFinalContains(type->baseType,
15355 	    XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15356 	    xmlSchemaPCustomErr(pctxt,
15357 		XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
15358 		WXS_BASIC_CAST type, NULL,
15359 		"The final of its base type '%s' must not contain 'restriction'",
15360 		xmlSchemaGetComponentQName(&str, type->baseType));
15361 	    FREE_AND_NULL(str)
15362 	    return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
15363 	}
15364 
15365 	/*
15366 	* 1.3.1 DF must be an allowed constraining facet for the {primitive
15367 	* type definition}, as specified in the appropriate subsection of 3.2
15368 	* Primitive datatypes.
15369 	*/
15370 	if (type->facets != NULL) {
15371 	    xmlSchemaFacetPtr facet;
15372 	    int ok = 1;
15373 
15374 	    primitive = xmlSchemaGetPrimitiveType(type);
15375 	    if (primitive == NULL) {
15376 		PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15377 		    "failed to get primitive type");
15378 		return (-1);
15379 	    }
15380 	    facet = type->facets;
15381 	    do {
15382 		if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
15383 		    ok = 0;
15384 		    xmlSchemaPIllegalFacetAtomicErr(pctxt,
15385 			XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
15386 			type, primitive, facet);
15387 		}
15388 		facet = facet->next;
15389 	    } while (facet != NULL);
15390 	    if (ok == 0)
15391 		return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
15392 	}
15393 	/*
15394 	* SPEC (1.3.2) "If there is a facet of the same kind in the {facets}
15395 	* of the {base type definition} (call this BF),then the DF's {value}
15396 	* must be a valid restriction of BF's {value} as defined in
15397 	* [XML Schemas: Datatypes]."
15398 	*
15399 	* NOTE (1.3.2) Facet derivation constraints are currently handled in
15400 	* xmlSchemaDeriveAndValidateFacets()
15401 	*/
15402     } else if (WXS_IS_LIST(type)) {
15403 	xmlSchemaTypePtr itemType = NULL;
15404 
15405 	itemType = type->subtypes;
15406 	if ((itemType == NULL) || (! WXS_IS_SIMPLE(itemType))) {
15407 	    PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15408 		"failed to evaluate the item type");
15409 	    return (-1);
15410 	}
15411 	if (WXS_IS_TYPE_NOT_FIXED(itemType))
15412 	    xmlSchemaTypeFixup(itemType, ACTXT_CAST pctxt);
15413 	/*
15414 	* 2.1 The {item type definition} must have a {variety} of atomic or
15415 	* union (in which case all the {member type definitions}
15416 	* must be atomic).
15417 	*/
15418 	if ((! WXS_IS_ATOMIC(itemType)) &&
15419 	    (! WXS_IS_UNION(itemType))) {
15420 	    xmlSchemaPCustomErr(pctxt,
15421 		XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
15422 		WXS_BASIC_CAST type, NULL,
15423 		"The item type '%s' does not have a variety of atomic or union",
15424 		xmlSchemaGetComponentQName(&str, itemType));
15425 	    FREE_AND_NULL(str)
15426 	    return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
15427 	} else if (WXS_IS_UNION(itemType)) {
15428 	    xmlSchemaTypeLinkPtr member;
15429 
15430 	    member = itemType->memberTypes;
15431 	    while (member != NULL) {
15432 		if (! WXS_IS_ATOMIC(member->type)) {
15433 		    xmlSchemaPCustomErr(pctxt,
15434 			XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
15435 			WXS_BASIC_CAST type, NULL,
15436 			"The item type is a union type, but the "
15437 			"member type '%s' of this item type is not atomic",
15438 			xmlSchemaGetComponentQName(&str, member->type));
15439 		    FREE_AND_NULL(str)
15440 		    return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
15441 		}
15442 		member = member->next;
15443 	    }
15444 	}
15445 
15446 	if (WXS_IS_ANY_SIMPLE_TYPE(type->baseType)) {
15447 	    xmlSchemaFacetPtr facet;
15448 	    /*
15449 	    * This is the case if we have: <simpleType><list ..
15450 	    */
15451 	    /*
15452 	    * 2.3.1
15453 	    * 2.3.1.1 The {final} of the {item type definition} must not
15454 	    * contain list.
15455 	    */
15456 	    if (xmlSchemaTypeFinalContains(itemType,
15457 		XML_SCHEMAS_TYPE_FINAL_LIST)) {
15458 		xmlSchemaPCustomErr(pctxt,
15459 		    XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
15460 		    WXS_BASIC_CAST type, NULL,
15461 		    "The final of its item type '%s' must not contain 'list'",
15462 		    xmlSchemaGetComponentQName(&str, itemType));
15463 		FREE_AND_NULL(str)
15464 		return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
15465 	    }
15466 	    /*
15467 	    * 2.3.1.2 The {facets} must only contain the whiteSpace
15468 	    * facet component.
15469 	    * OPTIMIZE TODO: the S4S already disallows any facet
15470 	    * to be specified.
15471 	    */
15472 	    if (type->facets != NULL) {
15473 		facet = type->facets;
15474 		do {
15475 		    if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
15476 			xmlSchemaPIllegalFacetListUnionErr(pctxt,
15477 			    XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
15478 			    type, facet);
15479 			return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
15480 		    }
15481 		    facet = facet->next;
15482 		} while (facet != NULL);
15483 	    }
15484 	    /*
15485 	    * MAYBE TODO: (Hmm, not really) Datatypes states:
15486 	    * A `list` datatype can be `derived` from an `atomic` datatype
15487 	    * whose `lexical space` allows space (such as string or anyURI)or
15488 	    * a `union` datatype any of whose {member type definitions}'s
15489 	    * `lexical space` allows space.
15490 	    */
15491 	} else {
15492 	    /*
15493 	    * This is the case if we have: <simpleType><restriction ...
15494 	    * I.e. the variety of "list" is inherited.
15495 	    */
15496 	    /*
15497 	    * 2.3.2
15498 	    * 2.3.2.1 The {base type definition} must have a {variety} of list.
15499 	    */
15500 	    if (! WXS_IS_LIST(type->baseType)) {
15501 		xmlSchemaPCustomErr(pctxt,
15502 		    XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
15503 		    WXS_BASIC_CAST type, NULL,
15504 		    "The base type '%s' must be a list type",
15505 		    xmlSchemaGetComponentQName(&str, type->baseType));
15506 		FREE_AND_NULL(str)
15507 		return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
15508 	    }
15509 	    /*
15510 	    * 2.3.2.2 The {final} of the {base type definition} must not
15511 	    * contain restriction.
15512 	    */
15513 	    if (xmlSchemaTypeFinalContains(type->baseType,
15514 		XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15515 		xmlSchemaPCustomErr(pctxt,
15516 		    XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
15517 		    WXS_BASIC_CAST type, NULL,
15518 		    "The 'final' of the base type '%s' must not contain 'restriction'",
15519 		    xmlSchemaGetComponentQName(&str, type->baseType));
15520 		FREE_AND_NULL(str)
15521 		return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
15522 	    }
15523 	    /*
15524 	    * 2.3.2.3 The {item type definition} must be validly derived
15525 	    * from the {base type definition}'s {item type definition} given
15526 	    * the empty set, as defined in Type Derivation OK (Simple) ($3.14.6).
15527 	    */
15528 	    {
15529 		xmlSchemaTypePtr baseItemType;
15530 
15531 		baseItemType = type->baseType->subtypes;
15532 		if ((baseItemType == NULL) || (! WXS_IS_SIMPLE(baseItemType))) {
15533 		    PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15534 			"failed to eval the item type of a base type");
15535 		    return (-1);
15536 		}
15537 		if ((itemType != baseItemType) &&
15538 		    (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt, itemType,
15539 			baseItemType, 0) != 0)) {
15540 		    xmlChar *strBIT = NULL, *strBT = NULL;
15541 		    xmlSchemaPCustomErrExt(pctxt,
15542 			XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
15543 			WXS_BASIC_CAST type, NULL,
15544 			"The item type '%s' is not validly derived from "
15545 			"the item type '%s' of the base type '%s'",
15546 			xmlSchemaGetComponentQName(&str, itemType),
15547 			xmlSchemaGetComponentQName(&strBIT, baseItemType),
15548 			xmlSchemaGetComponentQName(&strBT, type->baseType));
15549 
15550 		    FREE_AND_NULL(str)
15551 		    FREE_AND_NULL(strBIT)
15552 		    FREE_AND_NULL(strBT)
15553 		    return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
15554 		}
15555 	    }
15556 
15557 	    if (type->facets != NULL) {
15558 		xmlSchemaFacetPtr facet;
15559 		int ok = 1;
15560 		/*
15561 		* 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
15562 		* and enumeration facet components are allowed among the {facets}.
15563 		*/
15564 		facet = type->facets;
15565 		do {
15566 		    switch (facet->type) {
15567 			case XML_SCHEMA_FACET_LENGTH:
15568 			case XML_SCHEMA_FACET_MINLENGTH:
15569 			case XML_SCHEMA_FACET_MAXLENGTH:
15570 			case XML_SCHEMA_FACET_WHITESPACE:
15571 			    /*
15572 			    * TODO: 2.5.1.2 List datatypes
15573 			    * The value of `whiteSpace` is fixed to the value collapse.
15574 			    */
15575 			case XML_SCHEMA_FACET_PATTERN:
15576 			case XML_SCHEMA_FACET_ENUMERATION:
15577 			    break;
15578 			default: {
15579 			    xmlSchemaPIllegalFacetListUnionErr(pctxt,
15580 				XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
15581 				type, facet);
15582 			    /*
15583 			    * We could return, but it's nicer to report all
15584 			    * invalid facets.
15585 			    */
15586 			    ok = 0;
15587 			}
15588 		    }
15589 		    facet = facet->next;
15590 		} while (facet != NULL);
15591 		if (ok == 0)
15592 		    return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
15593 		/*
15594 		* SPEC (2.3.2.5) (same as 1.3.2)
15595 		*
15596 		* NOTE (2.3.2.5) This is currently done in
15597 		* xmlSchemaDeriveAndValidateFacets()
15598 		*/
15599 	    }
15600 	}
15601     } else if (WXS_IS_UNION(type)) {
15602 	/*
15603 	* 3.1 The {member type definitions} must all have {variety} of
15604 	* atomic or list.
15605 	*/
15606 	xmlSchemaTypeLinkPtr member;
15607 
15608 	member = type->memberTypes;
15609 	while (member != NULL) {
15610 	    if (WXS_IS_TYPE_NOT_FIXED(member->type))
15611 		xmlSchemaTypeFixup(member->type, ACTXT_CAST pctxt);
15612 
15613 	    if ((! WXS_IS_ATOMIC(member->type)) &&
15614 		(! WXS_IS_LIST(member->type))) {
15615 		xmlSchemaPCustomErr(pctxt,
15616 		    XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
15617 		    WXS_BASIC_CAST type, NULL,
15618 		    "The member type '%s' is neither an atomic, nor a list type",
15619 		    xmlSchemaGetComponentQName(&str, member->type));
15620 		FREE_AND_NULL(str)
15621 		return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
15622 	    }
15623 	    member = member->next;
15624 	}
15625 	/*
15626 	* 3.3.1 If the {base type definition} is the `simple ur-type
15627 	* definition`
15628 	*/
15629 	if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) {
15630 	    /*
15631 	    * 3.3.1.1 All of the {member type definitions} must have a
15632 	    * {final} which does not contain union.
15633 	    */
15634 	    member = type->memberTypes;
15635 	    while (member != NULL) {
15636 		if (xmlSchemaTypeFinalContains(member->type,
15637 		    XML_SCHEMAS_TYPE_FINAL_UNION)) {
15638 		    xmlSchemaPCustomErr(pctxt,
15639 			XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
15640 			WXS_BASIC_CAST type, NULL,
15641 			"The 'final' of member type '%s' contains 'union'",
15642 			xmlSchemaGetComponentQName(&str, member->type));
15643 		    FREE_AND_NULL(str)
15644 		    return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
15645 		}
15646 		member = member->next;
15647 	    }
15648 	    /*
15649 	    * 3.3.1.2 The {facets} must be empty.
15650 	    */
15651 	    if (type->facetSet != NULL) {
15652 		xmlSchemaPCustomErr(pctxt,
15653 		    XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
15654 		    WXS_BASIC_CAST type, NULL,
15655 		    "No facets allowed", NULL);
15656 		return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
15657 	    }
15658 	} else {
15659 	    /*
15660 	    * 3.3.2.1 The {base type definition} must have a {variety} of union.
15661 	    * I.e. the variety of "list" is inherited.
15662 	    */
15663 	    if (! WXS_IS_UNION(type->baseType)) {
15664 		xmlSchemaPCustomErr(pctxt,
15665 		    XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
15666 		    WXS_BASIC_CAST type, NULL,
15667 		    "The base type '%s' is not a union type",
15668 		    xmlSchemaGetComponentQName(&str, type->baseType));
15669 		FREE_AND_NULL(str)
15670 		return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
15671 	    }
15672 	    /*
15673 	    * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
15674 	    */
15675 	    if (xmlSchemaTypeFinalContains(type->baseType,
15676 		XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15677 		xmlSchemaPCustomErr(pctxt,
15678 		    XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
15679 		    WXS_BASIC_CAST type, NULL,
15680 		    "The 'final' of its base type '%s' must not contain 'restriction'",
15681 		    xmlSchemaGetComponentQName(&str, type->baseType));
15682 		FREE_AND_NULL(str)
15683 		return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
15684 	    }
15685 	    /*
15686 	    * 3.3.2.3 The {member type definitions}, in order, must be validly
15687 	    * derived from the corresponding type definitions in the {base
15688 	    * type definition}'s {member type definitions} given the empty set,
15689 	    * as defined in Type Derivation OK (Simple) ($3.14.6).
15690 	    */
15691 	    {
15692 		xmlSchemaTypeLinkPtr baseMember;
15693 
15694 		/*
15695 		* OPTIMIZE: if the type is restricting, it has no local defined
15696 		* member types and inherits the member types of the base type;
15697 		* thus a check for equality can be skipped.
15698 		*/
15699 		/*
15700 		* Even worse: I cannot see a scenario where a restricting
15701 		* union simple type can have other member types as the member
15702 		* types of it's base type. This check seems not necessary with
15703 		* respect to the derivation process in libxml2.
15704 		* But necessary if constructing types with an API.
15705 		*/
15706 		if (type->memberTypes != NULL) {
15707 		    member = type->memberTypes;
15708 		    baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
15709 		    if ((member == NULL) && (baseMember != NULL)) {
15710 			PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15711 			    "different number of member types in base");
15712 		    }
15713 		    while (member != NULL) {
15714 			if (baseMember == NULL) {
15715 			    PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15716 			    "different number of member types in base");
15717 			} else if ((member->type != baseMember->type) &&
15718 			    (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
15719 				member->type, baseMember->type, 0) != 0)) {
15720 			    xmlChar *strBMT = NULL, *strBT = NULL;
15721 
15722 			    xmlSchemaPCustomErrExt(pctxt,
15723 				XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
15724 				WXS_BASIC_CAST type, NULL,
15725 				"The member type %s is not validly "
15726 				"derived from its corresponding member "
15727 				"type %s of the base type %s",
15728 				xmlSchemaGetComponentQName(&str, member->type),
15729 				xmlSchemaGetComponentQName(&strBMT, baseMember->type),
15730 				xmlSchemaGetComponentQName(&strBT, type->baseType));
15731 			    FREE_AND_NULL(str)
15732 			    FREE_AND_NULL(strBMT)
15733 			    FREE_AND_NULL(strBT)
15734 			    return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
15735 			}
15736 			member = member->next;
15737                         if (baseMember != NULL)
15738                             baseMember = baseMember->next;
15739 		    }
15740 		}
15741 	    }
15742 	    /*
15743 	    * 3.3.2.4 Only pattern and enumeration facet components are
15744 	    * allowed among the {facets}.
15745 	    */
15746 	    if (type->facets != NULL) {
15747 		xmlSchemaFacetPtr facet;
15748 		int ok = 1;
15749 
15750 		facet = type->facets;
15751 		do {
15752 		    if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
15753 			(facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
15754 			xmlSchemaPIllegalFacetListUnionErr(pctxt,
15755 				XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
15756 				type, facet);
15757 			ok = 0;
15758 		    }
15759 		    facet = facet->next;
15760 		} while (facet != NULL);
15761 		if (ok == 0)
15762 		    return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
15763 
15764 	    }
15765 	    /*
15766 	    * SPEC (3.3.2.5) (same as 1.3.2)
15767 	    *
15768 	    * NOTE (3.3.2.5) This is currently done in
15769 	    * xmlSchemaDeriveAndValidateFacets()
15770 	    */
15771 	}
15772     }
15773 
15774     return (0);
15775 }
15776 
15777 /**
15778  * xmlSchemaCheckSRCSimpleType:
15779  * @ctxt:  the schema parser context
15780  * @type:  the simple type definition
15781  *
15782  * Checks crc-simple-type constraints.
15783  *
15784  * Returns 0 if the constraints are satisfied,
15785  * if not a positive error code and -1 on internal
15786  * errors.
15787  */
15788 #if 0
15789 static int
15790 xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
15791 			    xmlSchemaTypePtr type)
15792 {
15793     /*
15794     * src-simple-type.1 The corresponding simple type definition, if any,
15795     * must satisfy the conditions set out in Constraints on Simple Type
15796     * Definition Schema Components ($3.14.6).
15797     */
15798     if (WXS_IS_RESTRICTION(type)) {
15799 	/*
15800 	* src-simple-type.2 "If the <restriction> alternative is chosen,
15801 	* either it must have a base [attribute] or a <simpleType> among its
15802 	* [children], but not both."
15803 	* NOTE: This is checked in the parse function of <restriction>.
15804 	*/
15805 	/*
15806 	*
15807 	*/
15808     } else if (WXS_IS_LIST(type)) {
15809 	/* src-simple-type.3 "If the <list> alternative is chosen, either it must have
15810 	* an itemType [attribute] or a <simpleType> among its [children],
15811 	* but not both."
15812 	*
15813 	* NOTE: This is checked in the parse function of <list>.
15814 	*/
15815     } else if (WXS_IS_UNION(type)) {
15816 	/*
15817 	* src-simple-type.4 is checked in xmlSchemaCheckUnionTypeDefCircular().
15818 	*/
15819     }
15820     return (0);
15821 }
15822 #endif
15823 
15824 static int
xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)15825 xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
15826 {
15827    if (ctxt->vctxt == NULL) {
15828 	ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
15829 	if (ctxt->vctxt == NULL) {
15830 	    xmlSchemaPErr(ctxt, NULL,
15831 		XML_SCHEMAP_INTERNAL,
15832 		"Internal error: xmlSchemaCreateVCtxtOnPCtxt, "
15833 		"failed to create a temp. validation context.\n",
15834 		NULL, NULL);
15835 	    return (-1);
15836 	}
15837 	/* TODO: Pass user data. */
15838 	xmlSchemaSetValidErrors(ctxt->vctxt,
15839 	    ctxt->error, ctxt->warning, ctxt->errCtxt);
15840 	xmlSchemaSetValidStructuredErrors(ctxt->vctxt,
15841 	    ctxt->serror, ctxt->errCtxt);
15842     }
15843     return (0);
15844 }
15845 
15846 static int
15847 xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
15848 			     xmlNodePtr node,
15849 			     xmlSchemaTypePtr type,
15850 			     const xmlChar *value,
15851 			     xmlSchemaValPtr *retVal,
15852 			     int fireErrors,
15853 			     int normalize,
15854 			     int isNormalized);
15855 
15856 /**
15857  * xmlSchemaParseCheckCOSValidDefault:
15858  * @pctxt:  the schema parser context
15859  * @type:  the simple type definition
15860  * @value: the default value
15861  * @node: an optional node (the holder of the value)
15862  *
15863  * Schema Component Constraint: Element Default Valid (Immediate)
15864  * (cos-valid-default)
15865  * This will be used by the parser only. For the validator there's
15866  * an other version.
15867  *
15868  * Returns 0 if the constraints are satisfied,
15869  * if not, a positive error code and -1 on internal
15870  * errors.
15871  */
15872 static int
xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,xmlNodePtr node,xmlSchemaTypePtr type,const xmlChar * value,xmlSchemaValPtr * val)15873 xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
15874 				   xmlNodePtr node,
15875 				   xmlSchemaTypePtr type,
15876 				   const xmlChar *value,
15877 				   xmlSchemaValPtr *val)
15878 {
15879     int ret = 0;
15880 
15881     /*
15882     * cos-valid-default:
15883     * Schema Component Constraint: Element Default Valid (Immediate)
15884     * For a string to be a valid default with respect to a type
15885     * definition the appropriate case among the following must be true:
15886     */
15887     if WXS_IS_COMPLEX(type) {
15888 	/*
15889 	* Complex type.
15890 	*
15891 	* SPEC (2.1) "its {content type} must be a simple type definition
15892 	* or mixed."
15893 	* SPEC (2.2.2) "If the {content type} is mixed, then the {content
15894 	* type}'s particle must be `emptiable` as defined by
15895 	* Particle Emptiable ($3.9.6)."
15896 	*/
15897 	if ((! WXS_HAS_SIMPLE_CONTENT(type)) &&
15898 	    ((! WXS_HAS_MIXED_CONTENT(type)) || (! WXS_EMPTIABLE(type)))) {
15899 	    /* NOTE that this covers (2.2.2) as well. */
15900 	    xmlSchemaPCustomErr(pctxt,
15901 		XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
15902 		WXS_BASIC_CAST type, type->node,
15903 		"For a string to be a valid default, the type definition "
15904 		"must be a simple type or a complex type with mixed content "
15905 		"and a particle emptiable", NULL);
15906 	    return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
15907 	}
15908     }
15909     /*
15910     * 1 If the type definition is a simple type definition, then the string
15911     * must be `valid` with respect to that definition as defined by String
15912     * Valid ($3.14.4).
15913     *
15914     * AND
15915     *
15916     * 2.2.1 If the {content type} is a simple type definition, then the
15917     * string must be `valid` with respect to that simple type definition
15918     * as defined by String Valid ($3.14.4).
15919     */
15920     if (WXS_IS_SIMPLE(type))
15921 	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
15922 	    type, value, val, 1, 1, 0);
15923     else if (WXS_HAS_SIMPLE_CONTENT(type))
15924 	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
15925 	    type->contentTypeDef, value, val, 1, 1, 0);
15926     else
15927 	return (ret);
15928 
15929     if (ret < 0) {
15930 	PERROR_INT("xmlSchemaParseCheckCOSValidDefault",
15931 	    "calling xmlSchemaVCheckCVCSimpleType()");
15932     }
15933 
15934     return (ret);
15935 }
15936 
15937 /**
15938  * xmlSchemaCheckCTPropsCorrect:
15939  * @ctxt:  the schema parser context
15940  * @type:  the complex type definition
15941  *
15942  *.(4.6) Constraints on Complex Type Definition Schema Components
15943  * Schema Component Constraint:
15944  * Complex Type Definition Properties Correct (ct-props-correct)
15945  * STATUS: (seems) complete
15946  *
15947  * Returns 0 if the constraints are satisfied, a positive
15948  * error code if not and -1 if an internal error occurred.
15949  */
15950 static int
xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)15951 xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
15952 			     xmlSchemaTypePtr type)
15953 {
15954     /*
15955     * TODO: Correct the error code; XML_SCHEMAP_SRC_CT_1 is used temporarily.
15956     *
15957     * SPEC (1) "The values of the properties of a complex type definition must
15958     * be as described in the property tableau in The Complex Type Definition
15959     * Schema Component ($3.4.1), modulo the impact of Missing
15960     * Sub-components ($5.3)."
15961     */
15962     if ((type->baseType != NULL) &&
15963 	(WXS_IS_SIMPLE(type->baseType)) &&
15964 	(WXS_IS_EXTENSION(type) == 0)) {
15965 	/*
15966 	* SPEC (2) "If the {base type definition} is a simple type definition,
15967 	* the {derivation method} must be extension."
15968 	*/
15969 	xmlSchemaCustomErr(ACTXT_CAST pctxt,
15970 	    XML_SCHEMAP_SRC_CT_1,
15971 	    NULL, WXS_BASIC_CAST type,
15972 	    "If the base type is a simple type, the derivation method must be "
15973 	    "'extension'", NULL, NULL);
15974 	return (XML_SCHEMAP_SRC_CT_1);
15975     }
15976     /*
15977     * SPEC (3) "Circular definitions are disallowed, except for the `ur-type
15978     * definition`. That is, it must be possible to reach the `ur-type
15979     * definition` by repeatedly following the {base type definition}."
15980     *
15981     * NOTE (3) is done in xmlSchemaCheckTypeDefCircular().
15982     */
15983     /*
15984     * NOTE that (4) and (5) need the following:
15985     *   - attribute uses need to be already inherited (apply attr. prohibitions)
15986     *   - attribute group references need to be expanded already
15987     *   - simple types need to be typefixed already
15988     */
15989     if (type->attrUses &&
15990 	(((xmlSchemaItemListPtr) type->attrUses)->nbItems > 1))
15991     {
15992 	xmlSchemaItemListPtr uses = (xmlSchemaItemListPtr) type->attrUses;
15993 	xmlSchemaAttributeUsePtr use, tmp;
15994 	int i, j, hasId = 0;
15995 
15996 	for (i = uses->nbItems -1; i >= 0; i--) {
15997 	    use = uses->items[i];
15998 
15999 	    /*
16000 	    * SPEC ct-props-correct
16001 	    * (4) "Two distinct attribute declarations in the
16002 	    * {attribute uses} must not have identical {name}s and
16003 	    * {target namespace}s."
16004 	    */
16005 	    if (i > 0) {
16006 		for (j = i -1; j >= 0; j--) {
16007 		    tmp = uses->items[j];
16008 		    if ((WXS_ATTRUSE_DECL_NAME(use) ==
16009 			WXS_ATTRUSE_DECL_NAME(tmp)) &&
16010 			(WXS_ATTRUSE_DECL_TNS(use) ==
16011 			WXS_ATTRUSE_DECL_TNS(tmp)))
16012 		    {
16013 			xmlChar *str = NULL;
16014 
16015 			xmlSchemaCustomErr(ACTXT_CAST pctxt,
16016 			    XML_SCHEMAP_AG_PROPS_CORRECT,
16017 			    NULL, WXS_BASIC_CAST type,
16018 			    "Duplicate %s",
16019 			    xmlSchemaGetComponentDesignation(&str, use),
16020 			    NULL);
16021 			FREE_AND_NULL(str);
16022 			/*
16023 			* Remove the duplicate.
16024 			*/
16025 			if (xmlSchemaItemListRemove(uses, i) == -1)
16026 			    goto exit_failure;
16027 			goto next_use;
16028 		    }
16029 		}
16030 	    }
16031 	    /*
16032 	    * SPEC ct-props-correct
16033 	    * (5) "Two distinct attribute declarations in the
16034 	    * {attribute uses} must not have {type definition}s which
16035 	    * are or are derived from ID."
16036 	    */
16037 	    if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
16038 		if (xmlSchemaIsDerivedFromBuiltInType(
16039 		    WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
16040 		{
16041 		    if (hasId) {
16042 			xmlChar *str = NULL;
16043 
16044 			xmlSchemaCustomErr(ACTXT_CAST pctxt,
16045 			    XML_SCHEMAP_AG_PROPS_CORRECT,
16046 			    NULL, WXS_BASIC_CAST type,
16047 			    "There must not exist more than one attribute "
16048 			    "declaration of type 'xs:ID' "
16049 			    "(or derived from 'xs:ID'). The %s violates this "
16050 			    "constraint",
16051 			    xmlSchemaGetComponentDesignation(&str, use),
16052 			    NULL);
16053 			FREE_AND_NULL(str);
16054 			if (xmlSchemaItemListRemove(uses, i) == -1)
16055 			    goto exit_failure;
16056 		    }
16057 
16058 		    hasId = 1;
16059 		}
16060 	    }
16061 next_use: {}
16062 	}
16063     }
16064     return (0);
16065 exit_failure:
16066     return(-1);
16067 }
16068 
16069 static int
xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,xmlSchemaTypePtr typeB)16070 xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,
16071 		       xmlSchemaTypePtr typeB)
16072 {
16073     /*
16074     * TODO: This should implement component-identity
16075     * in the future.
16076     */
16077     if ((typeA == NULL) || (typeB == NULL))
16078 	return (0);
16079     return (typeA == typeB);
16080 }
16081 
16082 /**
16083  * xmlSchemaCheckCOSCTDerivedOK:
16084  * @ctxt:  the schema parser context
16085  * @type:  the to-be derived complex type definition
16086  * @baseType:  the base complex type definition
16087  * @set: the given set
16088  *
16089  * Schema Component Constraint:
16090  * Type Derivation OK (Complex) (cos-ct-derived-ok)
16091  *
16092  * STATUS: completed
16093  *
16094  * Returns 0 if the constraints are satisfied, or 1
16095  * if not.
16096  */
16097 static int
xmlSchemaCheckCOSCTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,xmlSchemaTypePtr type,xmlSchemaTypePtr baseType,int set)16098 xmlSchemaCheckCOSCTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
16099 			     xmlSchemaTypePtr type,
16100 			     xmlSchemaTypePtr baseType,
16101 			     int set)
16102 {
16103     int equal = xmlSchemaAreEqualTypes(type, baseType);
16104     /* TODO: Error codes. */
16105     /*
16106     * SPEC "For a complex type definition (call it D, for derived)
16107     * to be validly derived from a type definition (call this
16108     * B, for base) given a subset of {extension, restriction}
16109     * all of the following must be true:"
16110     */
16111     if (! equal) {
16112 	/*
16113 	* SPEC (1) "If B and D are not the same type definition, then the
16114 	* {derivation method} of D must not be in the subset."
16115 	*/
16116 	if (((set & SUBSET_EXTENSION) && (WXS_IS_EXTENSION(type))) ||
16117 	    ((set & SUBSET_RESTRICTION) && (WXS_IS_RESTRICTION(type))))
16118 	    return (1);
16119     } else {
16120 	/*
16121 	* SPEC (2.1) "B and D must be the same type definition."
16122 	*/
16123 	return (0);
16124     }
16125     /*
16126     * SPEC (2.2) "B must be D's {base type definition}."
16127     */
16128     if (type->baseType == baseType)
16129 	return (0);
16130     /*
16131     * SPEC (2.3.1) "D's {base type definition} must not be the `ur-type
16132     * definition`."
16133     */
16134     if (WXS_IS_ANYTYPE(type->baseType))
16135 	return (1);
16136 
16137     if (WXS_IS_COMPLEX(type->baseType)) {
16138 	/*
16139 	* SPEC (2.3.2.1) "If D's {base type definition} is complex, then it
16140 	* must be validly derived from B given the subset as defined by this
16141 	* constraint."
16142 	*/
16143 	return (xmlSchemaCheckCOSCTDerivedOK(actxt, type->baseType,
16144 	    baseType, set));
16145     } else {
16146 	/*
16147 	* SPEC (2.3.2.2) "If D's {base type definition} is simple, then it
16148 	* must be validly derived from B given the subset as defined in Type
16149 	* Derivation OK (Simple) ($3.14.6).
16150 	*/
16151 	return (xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
16152 	    baseType, set));
16153     }
16154 }
16155 
16156 /**
16157  * xmlSchemaCheckCOSDerivedOK:
16158  * @type:  the derived simple type definition
16159  * @baseType:  the base type definition
16160  *
16161  * Calls:
16162  * Type Derivation OK (Simple) AND Type Derivation OK (Complex)
16163  *
16164  * Checks wheter @type can be validly derived from @baseType.
16165  *
16166  * Returns 0 on success, an positive error code otherwise.
16167  */
16168 static int
xmlSchemaCheckCOSDerivedOK(xmlSchemaAbstractCtxtPtr actxt,xmlSchemaTypePtr type,xmlSchemaTypePtr baseType,int set)16169 xmlSchemaCheckCOSDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
16170 			   xmlSchemaTypePtr type,
16171 			   xmlSchemaTypePtr baseType,
16172 			   int set)
16173 {
16174     if (WXS_IS_SIMPLE(type))
16175 	return (xmlSchemaCheckCOSSTDerivedOK(actxt, type, baseType, set));
16176     else
16177 	return (xmlSchemaCheckCOSCTDerivedOK(actxt, type, baseType, set));
16178 }
16179 
16180 /**
16181  * xmlSchemaCheckCOSCTExtends:
16182  * @ctxt:  the schema parser context
16183  * @type:  the complex type definition
16184  *
16185  * (3.4.6) Constraints on Complex Type Definition Schema Components
16186  * Schema Component Constraint:
16187  * Derivation Valid (Extension) (cos-ct-extends)
16188  *
16189  * STATUS:
16190  *   missing:
16191  *     (1.5)
16192  *     (1.4.3.2.2.2) "Particle Valid (Extension)"
16193  *
16194  * Returns 0 if the constraints are satisfied, a positive
16195  * error code if not and -1 if an internal error occurred.
16196  */
16197 static int
xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,xmlSchemaTypePtr type)16198 xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
16199 			   xmlSchemaTypePtr type)
16200 {
16201     xmlSchemaTypePtr base = type->baseType;
16202     /*
16203     * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
16204     * temporarily only.
16205     */
16206     /*
16207     * SPEC (1) "If the {base type definition} is a complex type definition,
16208     * then all of the following must be true:"
16209     */
16210     if (WXS_IS_COMPLEX(base)) {
16211 	/*
16212 	* SPEC (1.1) "The {final} of the {base type definition} must not
16213 	* contain extension."
16214 	*/
16215 	if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16216 	    xmlSchemaPCustomErr(ctxt,
16217 		XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16218 		WXS_BASIC_CAST type, NULL,
16219 		"The 'final' of the base type definition "
16220 		"contains 'extension'", NULL);
16221 	    return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16222 	}
16223 
16224 	/*
16225 	* ATTENTION: The constrains (1.2) and (1.3) are not applied,
16226 	* since they are automatically satisfied through the
16227 	* inheriting mechanism.
16228 	* Note that even if redefining components, the inheriting mechanism
16229 	* is used.
16230 	*/
16231 #if 0
16232 	/*
16233 	* SPEC (1.2) "Its {attribute uses} must be a subset of the {attribute
16234 	* uses}
16235 	* of the complex type definition itself, that is, for every attribute
16236 	* use in the {attribute uses} of the {base type definition}, there
16237 	* must be an attribute use in the {attribute uses} of the complex
16238 	* type definition itself whose {attribute declaration} has the same
16239 	* {name}, {target namespace} and {type definition} as its attribute
16240 	* declaration"
16241 	*/
16242 	if (base->attrUses != NULL) {
16243 	    int i, j, found;
16244 	    xmlSchemaAttributeUsePtr use, buse;
16245 
16246 	    for (i = 0; i < (WXS_LIST_CAST base->attrUses)->nbItems; i ++) {
16247 		buse = (WXS_LIST_CAST base->attrUses)->items[i];
16248 		found = 0;
16249 		if (type->attrUses != NULL) {
16250 		    use = (WXS_LIST_CAST type->attrUses)->items[j];
16251 		    for (j = 0; j < (WXS_LIST_CAST type->attrUses)->nbItems; j ++)
16252 		    {
16253 			if ((WXS_ATTRUSE_DECL_NAME(use) ==
16254 				WXS_ATTRUSE_DECL_NAME(buse)) &&
16255 			    (WXS_ATTRUSE_DECL_TNS(use) ==
16256 				WXS_ATTRUSE_DECL_TNS(buse)) &&
16257 			    (WXS_ATTRUSE_TYPEDEF(use) ==
16258 				WXS_ATTRUSE_TYPEDEF(buse))
16259 			{
16260 			    found = 1;
16261 			    break;
16262 			}
16263 		    }
16264 		}
16265 		if (! found) {
16266 		    xmlChar *str = NULL;
16267 
16268 		    xmlSchemaCustomErr(ACTXT_CAST ctxt,
16269 			XML_SCHEMAP_COS_CT_EXTENDS_1_2,
16270 			NULL, WXS_BASIC_CAST type,
16271 			/*
16272 			* TODO: The report does not indicate that also the
16273 			* type needs to be the same.
16274 			*/
16275 			"This type is missing a matching correspondent "
16276 			"for its {base type}'s %s in its {attribute uses}",
16277 			xmlSchemaGetComponentDesignation(&str,
16278 			    buse->children),
16279 			NULL);
16280 		    FREE_AND_NULL(str)
16281 		}
16282 	    }
16283 	}
16284 	/*
16285 	* SPEC (1.3) "If it has an {attribute wildcard}, the complex type
16286 	* definition must also have one, and the base type definition's
16287 	* {attribute  wildcard}'s {namespace constraint} must be a subset
16288 	* of the complex  type definition's {attribute wildcard}'s {namespace
16289 	* constraint}, as defined by Wildcard Subset ($3.10.6)."
16290 	*/
16291 
16292 	/*
16293 	* MAYBE TODO: Enable if ever needed. But this will be needed only
16294 	* if created the type via a schema construction API.
16295 	*/
16296 	if (base->attributeWildcard != NULL) {
16297 	    if (type->attributeWilcard == NULL) {
16298 		xmlChar *str = NULL;
16299 
16300 		xmlSchemaCustomErr(ACTXT_CAST pctxt,
16301 		    XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16302 		    NULL, type,
16303 		    "The base %s has an attribute wildcard, "
16304 		    "but this type is missing an attribute wildcard",
16305 		    xmlSchemaGetComponentDesignation(&str, base));
16306 		FREE_AND_NULL(str)
16307 
16308 	    } else if (xmlSchemaCheckCOSNSSubset(
16309 		base->attributeWildcard, type->attributeWildcard))
16310 	    {
16311 		xmlChar *str = NULL;
16312 
16313 		xmlSchemaCustomErr(ACTXT_CAST pctxt,
16314 		    XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16315 		    NULL, type,
16316 		    "The attribute wildcard is not a valid "
16317 		    "superset of the one in the base %s",
16318 		    xmlSchemaGetComponentDesignation(&str, base));
16319 		FREE_AND_NULL(str)
16320 	    }
16321 	}
16322 #endif
16323 	/*
16324 	* SPEC (1.4) "One of the following must be true:"
16325 	*/
16326 	if ((type->contentTypeDef != NULL) &&
16327 	    (type->contentTypeDef == base->contentTypeDef)) {
16328 	    /*
16329 	    * SPEC (1.4.1) "The {content type} of the {base type definition}
16330 	    * and the {content type} of the complex type definition itself
16331 	    * must be the same simple type definition"
16332 	    * PASS
16333 	    */
16334 	} else if ((type->contentType == XML_SCHEMA_CONTENT_EMPTY) &&
16335 	    (base->contentType == XML_SCHEMA_CONTENT_EMPTY) ) {
16336 	    /*
16337 	    * SPEC (1.4.2) "The {content type} of both the {base type
16338 	    * definition} and the complex type definition itself must
16339 	    * be empty."
16340 	    * PASS
16341 	    */
16342 	} else {
16343 	    /*
16344 	    * SPEC (1.4.3) "All of the following must be true:"
16345 	    */
16346 	    if (type->subtypes == NULL) {
16347 		/*
16348 		* SPEC 1.4.3.1 The {content type} of the complex type
16349 		* definition itself must specify a particle.
16350 		*/
16351 		xmlSchemaPCustomErr(ctxt,
16352 		    XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16353 		    WXS_BASIC_CAST type, NULL,
16354 		    "The content type must specify a particle", NULL);
16355 		return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16356 	    }
16357 	    /*
16358 	    * SPEC (1.4.3.2) "One of the following must be true:"
16359 	    */
16360 	    if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16361 		/*
16362 		* SPEC (1.4.3.2.1) "The {content type} of the {base type
16363 		* definition} must be empty.
16364 		* PASS
16365 		*/
16366 	    } else {
16367 		/*
16368 		* SPEC (1.4.3.2.2) "All of the following must be true:"
16369 		*/
16370 		if ((type->contentType != base->contentType) ||
16371 		    ((type->contentType != XML_SCHEMA_CONTENT_MIXED) &&
16372 		    (type->contentType != XML_SCHEMA_CONTENT_ELEMENTS))) {
16373 		    /*
16374 		    * SPEC (1.4.3.2.2.1) "Both {content type}s must be mixed
16375 		    * or both must be element-only."
16376 		    */
16377 		    xmlSchemaPCustomErr(ctxt,
16378 			XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16379 			WXS_BASIC_CAST type, NULL,
16380 			"The content type of both, the type and its base "
16381 			"type, must either 'mixed' or 'element-only'", NULL);
16382 		    return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16383 		}
16384 		/*
16385 		* URGENT TODO SPEC (1.4.3.2.2.2) "The particle of the
16386 		* complex type definition must be a `valid extension`
16387 		* of the {base type definition}'s particle, as defined
16388 		* in Particle Valid (Extension) ($3.9.6)."
16389 		*
16390 		* NOTE that we won't check "Particle Valid (Extension)",
16391 		* since it is ensured by the derivation process in
16392 		* xmlSchemaTypeFixup(). We need to implement this when heading
16393 		* for a construction API
16394 		* TODO: !! This is needed to be checked if redefining a type !!
16395 		*/
16396 	    }
16397 	    /*
16398 	    * URGENT TODO (1.5)
16399 	    */
16400 	}
16401     } else {
16402 	/*
16403 	* SPEC (2) "If the {base type definition} is a simple type definition,
16404 	* then all of the following must be true:"
16405 	*/
16406 	if (type->contentTypeDef != base) {
16407 	    /*
16408 	    * SPEC (2.1) "The {content type} must be the same simple type
16409 	    * definition."
16410 	    */
16411 	    xmlSchemaPCustomErr(ctxt,
16412 		XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16413 		WXS_BASIC_CAST type, NULL,
16414 		"The content type must be the simple base type", NULL);
16415 	    return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16416 	}
16417 	if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16418 	    /*
16419 	    * SPEC (2.2) "The {final} of the {base type definition} must not
16420 	    * contain extension"
16421 	    * NOTE that this is the same as (1.1).
16422 	    */
16423 	    xmlSchemaPCustomErr(ctxt,
16424 		XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16425 		WXS_BASIC_CAST type, NULL,
16426 		"The 'final' of the base type definition "
16427 		"contains 'extension'", NULL);
16428 	    return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16429 	}
16430     }
16431     return (0);
16432 }
16433 
16434 /**
16435  * xmlSchemaCheckDerivationOKRestriction:
16436  * @ctxt:  the schema parser context
16437  * @type:  the complex type definition
16438  *
16439  * (3.4.6) Constraints on Complex Type Definition Schema Components
16440  * Schema Component Constraint:
16441  * Derivation Valid (Restriction, Complex) (derivation-ok-restriction)
16442  *
16443  * STATUS:
16444  *   missing:
16445  *     (5.4.2) ???
16446  *
16447  * ATTENTION:
16448  * In XML Schema 1.1 this will be:
16449  * Validation Rule: Checking complex type subsumption
16450  *
16451  * Returns 0 if the constraints are satisfied, a positive
16452  * error code if not and -1 if an internal error occurred.
16453  */
16454 static int
xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,xmlSchemaTypePtr type)16455 xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,
16456 				      xmlSchemaTypePtr type)
16457 {
16458     xmlSchemaTypePtr base;
16459 
16460     /*
16461     * TODO: Correct the error code; XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1 is used
16462     * temporarily only.
16463     */
16464     base = type->baseType;
16465     if (! WXS_IS_COMPLEX(base)) {
16466 	xmlSchemaCustomErr(ACTXT_CAST ctxt,
16467 	    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16468 	    type->node, WXS_BASIC_CAST type,
16469 	    "The base type must be a complex type", NULL, NULL);
16470 	return(ctxt->err);
16471     }
16472     if (base->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) {
16473 	/*
16474 	* SPEC (1) "The {base type definition} must be a complex type
16475 	* definition whose {final} does not contain restriction."
16476 	*/
16477 	xmlSchemaCustomErr(ACTXT_CAST ctxt,
16478 	    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16479 	    type->node, WXS_BASIC_CAST type,
16480 	    "The 'final' of the base type definition "
16481 	    "contains 'restriction'", NULL, NULL);
16482 	return (ctxt->err);
16483     }
16484     /*
16485     * SPEC (2), (3) and (4)
16486     * Those are handled in a separate function, since the
16487     * same constraints are needed for redefinition of
16488     * attribute groups as well.
16489     */
16490     if (xmlSchemaCheckDerivationOKRestriction2to4(ctxt,
16491 	XML_SCHEMA_ACTION_DERIVE,
16492 	WXS_BASIC_CAST type, WXS_BASIC_CAST base,
16493 	type->attrUses, base->attrUses,
16494 	type->attributeWildcard,
16495 	base->attributeWildcard) == -1)
16496     {
16497 	return(-1);
16498     }
16499     /*
16500     * SPEC (5) "One of the following must be true:"
16501     */
16502     if (base->builtInType == XML_SCHEMAS_ANYTYPE) {
16503 	/*
16504 	* SPEC (5.1) "The {base type definition} must be the
16505 	* `ur-type definition`."
16506 	* PASS
16507 	*/
16508     } else if ((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16509 	    (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16510 	/*
16511 	* SPEC (5.2.1) "The {content type} of the complex type definition
16512 	* must be a simple type definition"
16513 	*
16514 	* SPEC (5.2.2) "One of the following must be true:"
16515 	*/
16516 	if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16517 	    (base->contentType == XML_SCHEMA_CONTENT_BASIC))
16518 	{
16519 	    int err;
16520 	    /*
16521 	    * SPEC (5.2.2.1) "The {content type} of the {base type
16522 	    * definition} must be a simple type definition from which
16523 	    * the {content type} is validly derived given the empty
16524 	    * set as defined in Type Derivation OK (Simple) ($3.14.6)."
16525 	    *
16526 	    * ATTENTION TODO: This seems not needed if the type implicitely
16527 	    * derived from the base type.
16528 	    *
16529 	    */
16530 	    err = xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST ctxt,
16531 		type->contentTypeDef, base->contentTypeDef, 0);
16532 	    if (err != 0) {
16533 		xmlChar *strA = NULL, *strB = NULL;
16534 
16535 		if (err == -1)
16536 		    return(-1);
16537 		xmlSchemaCustomErr(ACTXT_CAST ctxt,
16538 		    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16539 		    NULL, WXS_BASIC_CAST type,
16540 		    "The {content type} %s is not validly derived from the "
16541 		    "base type's {content type} %s",
16542 		    xmlSchemaGetComponentDesignation(&strA,
16543 			type->contentTypeDef),
16544 		    xmlSchemaGetComponentDesignation(&strB,
16545 			base->contentTypeDef));
16546 		FREE_AND_NULL(strA);
16547 		FREE_AND_NULL(strB);
16548 		return(ctxt->err);
16549 	    }
16550 	} else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16551 	    (xmlSchemaIsParticleEmptiable(
16552 		(xmlSchemaParticlePtr) base->subtypes))) {
16553 	    /*
16554 	    * SPEC (5.2.2.2) "The {base type definition} must be mixed
16555 	    * and have a particle which is `emptiable` as defined in
16556 	    * Particle Emptiable ($3.9.6)."
16557 	    * PASS
16558 	    */
16559 	} else {
16560 	    xmlSchemaPCustomErr(ctxt,
16561 		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16562 		WXS_BASIC_CAST type, NULL,
16563 		"The content type of the base type must be either "
16564 		"a simple type or 'mixed' and an emptiable particle", NULL);
16565 	    return (ctxt->err);
16566 	}
16567     } else if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16568 	/*
16569 	* SPEC (5.3.1) "The {content type} of the complex type itself must
16570 	* be empty"
16571 	*/
16572 	if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16573 	    /*
16574 	    * SPEC (5.3.2.1) "The {content type} of the {base type
16575 	    * definition} must also be empty."
16576 	    * PASS
16577 	    */
16578 	} else if (((base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16579 	    (base->contentType == XML_SCHEMA_CONTENT_MIXED)) &&
16580 	    xmlSchemaIsParticleEmptiable(
16581 		(xmlSchemaParticlePtr) base->subtypes)) {
16582 	    /*
16583 	    * SPEC (5.3.2.2) "The {content type} of the {base type
16584 	    * definition} must be elementOnly or mixed and have a particle
16585 	    * which is `emptiable` as defined in Particle Emptiable ($3.9.6)."
16586 	    * PASS
16587 	    */
16588 	} else {
16589 	    xmlSchemaPCustomErr(ctxt,
16590 		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16591 		WXS_BASIC_CAST type, NULL,
16592 		"The content type of the base type must be either "
16593 		"empty or 'mixed' (or 'elements-only') and an emptiable "
16594 		"particle", NULL);
16595 	    return (ctxt->err);
16596 	}
16597     } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16598 	WXS_HAS_MIXED_CONTENT(type)) {
16599 	/*
16600 	* SPEC (5.4.1.1) "The {content type} of the complex type definition
16601 	* itself must be element-only"
16602 	*/
16603 	if (WXS_HAS_MIXED_CONTENT(type) && (! WXS_HAS_MIXED_CONTENT(base))) {
16604 	    /*
16605 	    * SPEC (5.4.1.2) "The {content type} of the complex type
16606 	    * definition itself and of the {base type definition} must be
16607 	    * mixed"
16608 	    */
16609 	    xmlSchemaPCustomErr(ctxt,
16610 		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16611 		WXS_BASIC_CAST type, NULL,
16612 		"If the content type is 'mixed', then the content type of the "
16613 		"base type must also be 'mixed'", NULL);
16614 	    return (ctxt->err);
16615 	}
16616 	/*
16617 	* SPEC (5.4.2) "The particle of the complex type definition itself
16618 	* must be a `valid restriction` of the particle of the {content
16619 	* type} of the {base type definition} as defined in Particle Valid
16620 	* (Restriction) ($3.9.6).
16621 	*
16622 	* URGENT TODO: (5.4.2)
16623 	*/
16624     } else {
16625 	xmlSchemaPCustomErr(ctxt,
16626 	    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16627 	    WXS_BASIC_CAST type, NULL,
16628 	    "The type is not a valid restriction of its base type", NULL);
16629 	return (ctxt->err);
16630     }
16631     return (0);
16632 }
16633 
16634 /**
16635  * xmlSchemaCheckCTComponent:
16636  * @ctxt:  the schema parser context
16637  * @type:  the complex type definition
16638  *
16639  * (3.4.6) Constraints on Complex Type Definition Schema Components
16640  *
16641  * Returns 0 if the constraints are satisfied, a positive
16642  * error code if not and -1 if an internal error occurred.
16643  */
16644 static int
xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,xmlSchemaTypePtr type)16645 xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,
16646 			  xmlSchemaTypePtr type)
16647 {
16648     int ret;
16649     /*
16650     * Complex Type Definition Properties Correct
16651     */
16652     ret = xmlSchemaCheckCTPropsCorrect(ctxt, type);
16653     if (ret != 0)
16654 	return (ret);
16655     if (WXS_IS_EXTENSION(type))
16656 	ret = xmlSchemaCheckCOSCTExtends(ctxt, type);
16657     else
16658 	ret = xmlSchemaCheckDerivationOKRestriction(ctxt, type);
16659     return (ret);
16660 }
16661 
16662 /**
16663  * xmlSchemaCheckSRCCT:
16664  * @ctxt:  the schema parser context
16665  * @type:  the complex type definition
16666  *
16667  * (3.4.3) Constraints on XML Representations of Complex Type Definitions:
16668  * Schema Representation Constraint:
16669  * Complex Type Definition Representation OK (src-ct)
16670  *
16671  * Returns 0 if the constraints are satisfied, a positive
16672  * error code if not and -1 if an internal error occurred.
16673  */
16674 static int
xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,xmlSchemaTypePtr type)16675 xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
16676 		    xmlSchemaTypePtr type)
16677 {
16678     xmlSchemaTypePtr base;
16679     int ret = 0;
16680 
16681     /*
16682     * TODO: Adjust the error codes here, as I used
16683     * XML_SCHEMAP_SRC_CT_1 only yet.
16684     */
16685     base = type->baseType;
16686     if (! WXS_HAS_SIMPLE_CONTENT(type)) {
16687 	/*
16688 	* 1 If the <complexContent> alternative is chosen, the type definition
16689 	* `resolved` to by the `actual value` of the base [attribute]
16690 	* must be a complex type definition;
16691 	*/
16692 	if (! WXS_IS_COMPLEX(base)) {
16693 	    xmlChar *str = NULL;
16694 	    xmlSchemaPCustomErr(ctxt,
16695 		XML_SCHEMAP_SRC_CT_1,
16696 		WXS_BASIC_CAST type, type->node,
16697 		"If using <complexContent>, the base type is expected to be "
16698 		"a complex type. The base type '%s' is a simple type",
16699 		xmlSchemaFormatQName(&str, base->targetNamespace,
16700 		base->name));
16701 	    FREE_AND_NULL(str)
16702 	    return (XML_SCHEMAP_SRC_CT_1);
16703 	}
16704     } else {
16705 	/*
16706 	* SPEC
16707 	* 2 If the <simpleContent> alternative is chosen, all of the
16708 	* following must be true:
16709 	* 2.1 The type definition `resolved` to by the `actual value` of the
16710 	* base [attribute] must be one of the following:
16711 	*/
16712 	if (WXS_IS_SIMPLE(base)) {
16713 	    if (WXS_IS_EXTENSION(type) == 0) {
16714 		xmlChar *str = NULL;
16715 		/*
16716 		* 2.1.3 only if the <extension> alternative is also
16717 		* chosen, a simple type definition.
16718 		*/
16719 		/* TODO: Change error code to ..._SRC_CT_2_1_3. */
16720 		xmlSchemaPCustomErr(ctxt,
16721 		    XML_SCHEMAP_SRC_CT_1,
16722 		    WXS_BASIC_CAST type, NULL,
16723 		    "If using <simpleContent> and <restriction>, the base "
16724 		    "type must be a complex type. The base type '%s' is "
16725 		    "a simple type",
16726 		    xmlSchemaFormatQName(&str, base->targetNamespace,
16727 			base->name));
16728 		FREE_AND_NULL(str)
16729 		return (XML_SCHEMAP_SRC_CT_1);
16730 	    }
16731 	} else {
16732 	    /* Base type is a complex type. */
16733 	    if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16734 		(base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16735 		/*
16736 		* 2.1.1 a complex type definition whose {content type} is a
16737 		* simple type definition;
16738 		* PASS
16739 		*/
16740 		if (base->contentTypeDef == NULL) {
16741 		    xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
16742 			WXS_BASIC_CAST type, NULL,
16743 			"Internal error: xmlSchemaCheckSRCCT, "
16744 			"'%s', base type has no content type",
16745 			type->name);
16746 		    return (-1);
16747 		}
16748 	    } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16749 		(WXS_IS_RESTRICTION(type))) {
16750 
16751 		/*
16752 		* 2.1.2 only if the <restriction> alternative is also
16753 		* chosen, a complex type definition whose {content type}
16754 		* is mixed and a particle emptiable.
16755 		*/
16756 		if (! xmlSchemaIsParticleEmptiable(
16757 		    (xmlSchemaParticlePtr) base->subtypes)) {
16758 		    ret = XML_SCHEMAP_SRC_CT_1;
16759 		} else
16760 		    /*
16761 		    * Attention: at this point the <simpleType> child is in
16762 		    * ->contentTypeDef (put there during parsing).
16763 		    */
16764 		    if (type->contentTypeDef == NULL) {
16765 		    xmlChar *str = NULL;
16766 		    /*
16767 		    * 2.2 If clause 2.1.2 above is satisfied, then there
16768 		    * must be a <simpleType> among the [children] of
16769 		    * <restriction>.
16770 		    */
16771 		    /* TODO: Change error code to ..._SRC_CT_2_2. */
16772 		    xmlSchemaPCustomErr(ctxt,
16773 			XML_SCHEMAP_SRC_CT_1,
16774 			WXS_BASIC_CAST type, NULL,
16775 			"A <simpleType> is expected among the children "
16776 			"of <restriction>, if <simpleContent> is used and "
16777 			"the base type '%s' is a complex type",
16778 			xmlSchemaFormatQName(&str, base->targetNamespace,
16779 			base->name));
16780 		    FREE_AND_NULL(str)
16781 		    return (XML_SCHEMAP_SRC_CT_1);
16782 		}
16783 	    } else {
16784 		ret = XML_SCHEMAP_SRC_CT_1;
16785 	    }
16786 	}
16787 	if (ret > 0) {
16788 	    xmlChar *str = NULL;
16789 	    if (WXS_IS_RESTRICTION(type)) {
16790 		xmlSchemaPCustomErr(ctxt,
16791 		    XML_SCHEMAP_SRC_CT_1,
16792 		    WXS_BASIC_CAST type, NULL,
16793 		    "If <simpleContent> and <restriction> is used, the "
16794 		    "base type must be a simple type or a complex type with "
16795 		    "mixed content and particle emptiable. The base type "
16796 		    "'%s' is none of those",
16797 		    xmlSchemaFormatQName(&str, base->targetNamespace,
16798 		    base->name));
16799 	    } else {
16800 		xmlSchemaPCustomErr(ctxt,
16801 		    XML_SCHEMAP_SRC_CT_1,
16802 		    WXS_BASIC_CAST type, NULL,
16803 		    "If <simpleContent> and <extension> is used, the "
16804 		    "base type must be a simple type. The base type '%s' "
16805 		    "is a complex type",
16806 		    xmlSchemaFormatQName(&str, base->targetNamespace,
16807 		    base->name));
16808 	    }
16809 	    FREE_AND_NULL(str)
16810 	}
16811     }
16812     /*
16813     * SPEC (3) "The corresponding complex type definition component must
16814     * satisfy the conditions set out in Constraints on Complex Type
16815     * Definition Schema Components ($3.4.6);"
16816     * NOTE (3) will be done in xmlSchemaTypeFixup().
16817     */
16818     /*
16819     * SPEC (4) If clause 2.2.1 or clause 2.2.2 in the correspondence specification
16820     * above for {attribute wildcard} is satisfied, the intensional
16821     * intersection must be expressible, as defined in Attribute Wildcard
16822     * Intersection ($3.10.6).
16823     * NOTE (4) is done in xmlSchemaFixupTypeAttributeUses().
16824     */
16825     return (ret);
16826 }
16827 
16828 #ifdef ENABLE_PARTICLE_RESTRICTION
16829 /**
16830  * xmlSchemaCheckParticleRangeOK:
16831  * @ctxt:  the schema parser context
16832  * @type:  the complex type definition
16833  *
16834  * (3.9.6) Constraints on Particle Schema Components
16835  * Schema Component Constraint:
16836  * Occurrence Range OK (range-ok)
16837  *
16838  * STATUS: complete
16839  *
16840  * Returns 0 if the constraints are satisfied, a positive
16841  * error code if not and -1 if an internal error occurred.
16842  */
16843 static int
xmlSchemaCheckParticleRangeOK(int rmin,int rmax,int bmin,int bmax)16844 xmlSchemaCheckParticleRangeOK(int rmin, int rmax,
16845 			      int bmin, int bmax)
16846 {
16847     if (rmin < bmin)
16848 	return (1);
16849     if ((bmax != UNBOUNDED) &&
16850 	(rmax > bmax))
16851 	return (1);
16852     return (0);
16853 }
16854 
16855 /**
16856  * xmlSchemaCheckRCaseNameAndTypeOK:
16857  * @ctxt:  the schema parser context
16858  * @r: the restricting element declaration particle
16859  * @b: the base element declaration particle
16860  *
16861  * (3.9.6) Constraints on Particle Schema Components
16862  * Schema Component Constraint:
16863  * Particle Restriction OK (Elt:Elt -- NameAndTypeOK)
16864  * (rcase-NameAndTypeOK)
16865  *
16866  * STATUS:
16867  *   MISSING (3.2.3)
16868  *   CLARIFY: (3.2.2)
16869  *
16870  * Returns 0 if the constraints are satisfied, a positive
16871  * error code if not and -1 if an internal error occurred.
16872  */
16873 static int
xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr r,xmlSchemaParticlePtr b)16874 xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,
16875 				 xmlSchemaParticlePtr r,
16876 				 xmlSchemaParticlePtr b)
16877 {
16878     xmlSchemaElementPtr elemR, elemB;
16879 
16880     /* TODO: Error codes (rcase-NameAndTypeOK). */
16881     elemR = (xmlSchemaElementPtr) r->children;
16882     elemB = (xmlSchemaElementPtr) b->children;
16883     /*
16884     * SPEC (1) "The declarations' {name}s and {target namespace}s are
16885     * the same."
16886     */
16887     if ((elemR != elemB) &&
16888 	((! xmlStrEqual(elemR->name, elemB->name)) ||
16889 	(! xmlStrEqual(elemR->targetNamespace, elemB->targetNamespace))))
16890 	return (1);
16891     /*
16892     * SPEC (2) "R's occurrence range is a valid restriction of B's
16893     * occurrence range as defined by Occurrence Range OK ($3.9.6)."
16894     */
16895     if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16896 	    b->minOccurs, b->maxOccurs) != 0)
16897 	return (1);
16898     /*
16899     * SPEC (3.1) "Both B's declaration's {scope} and R's declaration's
16900     * {scope} are global."
16901     */
16902     if (elemR == elemB)
16903 	return (0);
16904     /*
16905     * SPEC (3.2.1) "Either B's {nillable} is true or R's {nillable} is false."
16906     */
16907     if (((elemB->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) &&
16908 	(elemR->flags & XML_SCHEMAS_ELEM_NILLABLE))
16909 	 return (1);
16910     /*
16911     * SPEC (3.2.2) "either B's declaration's {value constraint} is absent,
16912     * or is not fixed, or R's declaration's {value constraint} is fixed
16913     * with the same value."
16914     */
16915     if ((elemB->value != NULL) && (elemB->flags & XML_SCHEMAS_ELEM_FIXED) &&
16916 	((elemR->value == NULL) ||
16917 	 ((elemR->flags & XML_SCHEMAS_ELEM_FIXED) == 0) ||
16918 	 /* TODO: Equality of the initial value or normalized or canonical? */
16919 	 (! xmlStrEqual(elemR->value, elemB->value))))
16920 	 return (1);
16921     /*
16922     * TODO: SPEC (3.2.3) "R's declaration's {identity-constraint
16923     * definitions} is a subset of B's declaration's {identity-constraint
16924     * definitions}, if any."
16925     */
16926     if (elemB->idcs != NULL) {
16927 	/* TODO */
16928     }
16929     /*
16930     * SPEC (3.2.4) "R's declaration's {disallowed substitutions} is a
16931     * superset of B's declaration's {disallowed substitutions}."
16932     */
16933     if (((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) &&
16934 	 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) == 0)) ||
16935 	((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) &&
16936 	 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) == 0)) ||
16937 	((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) &&
16938 	 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) == 0)))
16939 	 return (1);
16940     /*
16941     * SPEC (3.2.5) "R's {type definition} is validly derived given
16942     * {extension, list, union} from B's {type definition}"
16943     *
16944     * BADSPEC TODO: What's the point of adding "list" and "union" to the
16945     * set, if the corresponding constraints handle "restriction" and
16946     * "extension" only?
16947     *
16948     */
16949     {
16950 	int set = 0;
16951 
16952 	set |= SUBSET_EXTENSION;
16953 	set |= SUBSET_LIST;
16954 	set |= SUBSET_UNION;
16955 	if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST ctxt, elemR->subtypes,
16956 	    elemB->subtypes, set) != 0)
16957 	    return (1);
16958     }
16959     return (0);
16960 }
16961 
16962 /**
16963  * xmlSchemaCheckRCaseNSCompat:
16964  * @ctxt:  the schema parser context
16965  * @r: the restricting element declaration particle
16966  * @b: the base wildcard particle
16967  *
16968  * (3.9.6) Constraints on Particle Schema Components
16969  * Schema Component Constraint:
16970  * Particle Derivation OK (Elt:Any -- NSCompat)
16971  * (rcase-NSCompat)
16972  *
16973  * STATUS: complete
16974  *
16975  * Returns 0 if the constraints are satisfied, a positive
16976  * error code if not and -1 if an internal error occurred.
16977  */
16978 static int
xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr r,xmlSchemaParticlePtr b)16979 xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,
16980 			    xmlSchemaParticlePtr r,
16981 			    xmlSchemaParticlePtr b)
16982 {
16983     /* TODO:Error codes (rcase-NSCompat). */
16984     /*
16985     * SPEC "For an element declaration particle to be a `valid restriction`
16986     * of a wildcard particle all of the following must be true:"
16987     *
16988     * SPEC (1) "The element declaration's {target namespace} is `valid`
16989     * with respect to the wildcard's {namespace constraint} as defined by
16990     * Wildcard allows Namespace Name ($3.10.4)."
16991     */
16992     if (xmlSchemaCheckCVCWildcardNamespace((xmlSchemaWildcardPtr) b->children,
16993 	((xmlSchemaElementPtr) r->children)->targetNamespace) != 0)
16994 	return (1);
16995     /*
16996     * SPEC (2) "R's occurrence range is a valid restriction of B's
16997     * occurrence range as defined by Occurrence Range OK ($3.9.6)."
16998     */
16999     if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
17000 	    b->minOccurs, b->maxOccurs) != 0)
17001 	return (1);
17002 
17003     return (0);
17004 }
17005 
17006 /**
17007  * xmlSchemaCheckRCaseRecurseAsIfGroup:
17008  * @ctxt:  the schema parser context
17009  * @r: the restricting element declaration particle
17010  * @b: the base model group particle
17011  *
17012  * (3.9.6) Constraints on Particle Schema Components
17013  * Schema Component Constraint:
17014  * Particle Derivation OK (Elt:All/Choice/Sequence -- RecurseAsIfGroup)
17015  * (rcase-RecurseAsIfGroup)
17016  *
17017  * STATUS: TODO
17018  *
17019  * Returns 0 if the constraints are satisfied, a positive
17020  * error code if not and -1 if an internal error occurred.
17021  */
17022 static int
xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr r,xmlSchemaParticlePtr b)17023 xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,
17024 				    xmlSchemaParticlePtr r,
17025 				    xmlSchemaParticlePtr b)
17026 {
17027     /* TODO: Error codes (rcase-RecurseAsIfGroup). */
17028     TODO
17029     return (0);
17030 }
17031 
17032 /**
17033  * xmlSchemaCheckRCaseNSSubset:
17034  * @ctxt:  the schema parser context
17035  * @r: the restricting wildcard particle
17036  * @b: the base wildcard particle
17037  *
17038  * (3.9.6) Constraints on Particle Schema Components
17039  * Schema Component Constraint:
17040  * Particle Derivation OK (Any:Any -- NSSubset)
17041  * (rcase-NSSubset)
17042  *
17043  * STATUS: complete
17044  *
17045  * Returns 0 if the constraints are satisfied, a positive
17046  * error code if not and -1 if an internal error occurred.
17047  */
17048 static int
xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr r,xmlSchemaParticlePtr b,int isAnyTypeBase)17049 xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,
17050 				    xmlSchemaParticlePtr r,
17051 				    xmlSchemaParticlePtr b,
17052 				    int isAnyTypeBase)
17053 {
17054     /* TODO: Error codes (rcase-NSSubset). */
17055     /*
17056     * SPEC (1) "R's occurrence range is a valid restriction of B's
17057     * occurrence range as defined by Occurrence Range OK ($3.9.6)."
17058     */
17059     if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
17060 	    b->minOccurs, b->maxOccurs))
17061 	return (1);
17062     /*
17063     * SPEC (2) "R's {namespace constraint} must be an intensional subset
17064     * of B's {namespace constraint} as defined by Wildcard Subset ($3.10.6)."
17065     */
17066     if (xmlSchemaCheckCOSNSSubset((xmlSchemaWildcardPtr) r->children,
17067 	(xmlSchemaWildcardPtr) b->children))
17068 	return (1);
17069     /*
17070     * SPEC (3) "Unless B is the content model wildcard of the `ur-type
17071     * definition`, R's {process contents} must be identical to or stronger
17072     * than B's {process contents}, where strict is stronger than lax is
17073     * stronger than skip."
17074     */
17075     if (! isAnyTypeBase) {
17076 	if ( ((xmlSchemaWildcardPtr) r->children)->processContents <
17077 	    ((xmlSchemaWildcardPtr) b->children)->processContents)
17078 	    return (1);
17079     }
17080 
17081     return (0);
17082 }
17083 
17084 /**
17085  * xmlSchemaCheckCOSParticleRestrict:
17086  * @ctxt:  the schema parser context
17087  * @type:  the complex type definition
17088  *
17089  * (3.9.6) Constraints on Particle Schema Components
17090  * Schema Component Constraint:
17091  * Particle Valid (Restriction) (cos-particle-restrict)
17092  *
17093  * STATUS: TODO
17094  *
17095  * Returns 0 if the constraints are satisfied, a positive
17096  * error code if not and -1 if an internal error occurred.
17097  */
17098 static int
xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr r,xmlSchemaParticlePtr b)17099 xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,
17100 				  xmlSchemaParticlePtr r,
17101 				  xmlSchemaParticlePtr b)
17102 {
17103     int ret = 0;
17104 
17105     /*part = WXS_TYPE_PARTICLE(type);
17106     basePart = WXS_TYPE_PARTICLE(base);
17107     */
17108 
17109     TODO
17110 
17111     /*
17112     * SPEC (1) "They are the same particle."
17113     */
17114     if (r == b)
17115 	return (0);
17116 
17117 
17118     return (0);
17119 }
17120 
17121 #if 0
17122 /**
17123  * xmlSchemaCheckRCaseNSRecurseCheckCardinality:
17124  * @ctxt:  the schema parser context
17125  * @r: the model group particle
17126  * @b: the base wildcard particle
17127  *
17128  * (3.9.6) Constraints on Particle Schema Components
17129  * Schema Component Constraint:
17130  * Particle Derivation OK (All/Choice/Sequence:Any --
17131  *                         NSRecurseCheckCardinality)
17132  * (rcase-NSRecurseCheckCardinality)
17133  *
17134  * STATUS: TODO: subst-groups
17135  *
17136  * Returns 0 if the constraints are satisfied, a positive
17137  * error code if not and -1 if an internal error occurred.
17138  */
17139 static int
17140 xmlSchemaCheckRCaseNSRecurseCheckCardinality(xmlSchemaParserCtxtPtr ctxt,
17141 					     xmlSchemaParticlePtr r,
17142 					     xmlSchemaParticlePtr b)
17143 {
17144     xmlSchemaParticlePtr part;
17145     /* TODO: Error codes (rcase-NSRecurseCheckCardinality). */
17146     if ((r->children == NULL) || (r->children->children == NULL))
17147 	return (-1);
17148     /*
17149     * SPEC "For a group particle to be a `valid restriction` of a
17150     * wildcard particle..."
17151     *
17152     * SPEC (1) "Every member of the {particles} of the group is a `valid
17153     * restriction` of the wildcard as defined by
17154     * Particle Valid (Restriction) ($3.9.6)."
17155     */
17156     part = (xmlSchemaParticlePtr) r->children->children;
17157     do {
17158 	if (xmlSchemaCheckCOSParticleRestrict(ctxt, part, b))
17159 	    return (1);
17160 	part = (xmlSchemaParticlePtr) part->next;
17161     } while (part != NULL);
17162     /*
17163     * SPEC (2) "The effective total range of the group [...] is a
17164     * valid restriction of B's occurrence range as defined by
17165     * Occurrence Range OK ($3.9.6)."
17166     */
17167     if (xmlSchemaCheckParticleRangeOK(
17168 	    xmlSchemaGetParticleTotalRangeMin(r),
17169 	    xmlSchemaGetParticleTotalRangeMax(r),
17170 	    b->minOccurs, b->maxOccurs) != 0)
17171 	return (1);
17172     return (0);
17173 }
17174 #endif
17175 
17176 /**
17177  * xmlSchemaCheckRCaseRecurse:
17178  * @ctxt:  the schema parser context
17179  * @r: the <all> or <sequence> model group particle
17180  * @b: the base <all> or <sequence> model group particle
17181  *
17182  * (3.9.6) Constraints on Particle Schema Components
17183  * Schema Component Constraint:
17184  * Particle Derivation OK (All:All,Sequence:Sequence --
17185                            Recurse)
17186  * (rcase-Recurse)
17187  *
17188  * STATUS:  ?
17189  * TODO: subst-groups
17190  *
17191  * Returns 0 if the constraints are satisfied, a positive
17192  * error code if not and -1 if an internal error occurred.
17193  */
17194 static int
xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr r,xmlSchemaParticlePtr b)17195 xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,
17196 			   xmlSchemaParticlePtr r,
17197 			   xmlSchemaParticlePtr b)
17198 {
17199     /* xmlSchemaParticlePtr part; */
17200     /* TODO: Error codes (rcase-Recurse). */
17201     if ((r->children == NULL) || (b->children == NULL) ||
17202 	(r->children->type != b->children->type))
17203 	return (-1);
17204     /*
17205     * SPEC "For an all or sequence group particle to be a `valid
17206     * restriction` of another group particle with the same {compositor}..."
17207     *
17208     * SPEC (1) "R's occurrence range is a valid restriction of B's
17209     * occurrence range as defined by Occurrence Range OK ($3.9.6)."
17210     */
17211     if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
17212 	    b->minOccurs, b->maxOccurs))
17213 	return (1);
17214 
17215 
17216     return (0);
17217 }
17218 
17219 #endif
17220 
17221 #define FACET_RESTR_MUTUAL_ERR(fac1, fac2) \
17222     xmlSchemaPCustomErrExt(pctxt,      \
17223 	XML_SCHEMAP_INVALID_FACET_VALUE, \
17224 	WXS_BASIC_CAST fac1, fac1->node, \
17225 	"It is an error for both '%s' and '%s' to be specified on the "\
17226 	"same type definition", \
17227 	BAD_CAST xmlSchemaFacetTypeToString(fac1->type), \
17228 	BAD_CAST xmlSchemaFacetTypeToString(fac2->type), NULL);
17229 
17230 #define FACET_RESTR_ERR(fac1, msg) \
17231     xmlSchemaPCustomErr(pctxt,      \
17232 	XML_SCHEMAP_INVALID_FACET_VALUE, \
17233 	WXS_BASIC_CAST fac1, fac1->node, \
17234 	msg, NULL);
17235 
17236 #define FACET_RESTR_FIXED_ERR(fac) \
17237     xmlSchemaPCustomErr(pctxt, \
17238 	XML_SCHEMAP_INVALID_FACET_VALUE, \
17239 	WXS_BASIC_CAST fac, fac->node, \
17240 	"The base type's facet is 'fixed', thus the value must not " \
17241 	"differ", NULL);
17242 
17243 static void
xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,xmlSchemaFacetPtr facet1,xmlSchemaFacetPtr facet2,int lessGreater,int orEqual,int ofBase)17244 xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,
17245 			xmlSchemaFacetPtr facet1,
17246 			xmlSchemaFacetPtr facet2,
17247 			int lessGreater,
17248 			int orEqual,
17249 			int ofBase)
17250 {
17251     xmlChar *msg = NULL;
17252 
17253     msg = xmlStrdup(BAD_CAST "'");
17254     msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet1->type));
17255     msg = xmlStrcat(msg, BAD_CAST "' has to be");
17256     if (lessGreater == 0)
17257 	msg = xmlStrcat(msg, BAD_CAST " equal to");
17258     if (lessGreater == 1)
17259 	msg = xmlStrcat(msg, BAD_CAST " greater than");
17260     else
17261 	msg = xmlStrcat(msg, BAD_CAST " less than");
17262 
17263     if (orEqual)
17264 	msg = xmlStrcat(msg, BAD_CAST " or equal to");
17265     msg = xmlStrcat(msg, BAD_CAST " '");
17266     msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet2->type));
17267     if (ofBase)
17268 	msg = xmlStrcat(msg, BAD_CAST "' of the base type");
17269     else
17270 	msg = xmlStrcat(msg, BAD_CAST "'");
17271 
17272     xmlSchemaPCustomErr(pctxt,
17273 	XML_SCHEMAP_INVALID_FACET_VALUE,
17274 	WXS_BASIC_CAST facet1, NULL,
17275 	(const char *) msg, NULL);
17276 
17277     if (msg != NULL)
17278 	xmlFree(msg);
17279 }
17280 
17281 /*
17282 * xmlSchemaDeriveAndValidateFacets:
17283 *
17284 * Schema Component Constraint: Simple Type Restriction (Facets)
17285 * (st-restrict-facets)
17286 */
17287 static int
xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)17288 xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,
17289 				 xmlSchemaTypePtr type)
17290 {
17291     xmlSchemaTypePtr base = type->baseType;
17292     xmlSchemaFacetLinkPtr link, cur, last = NULL;
17293     xmlSchemaFacetPtr facet, bfacet,
17294 	flength = NULL, ftotdig = NULL, ffracdig = NULL,
17295 	fmaxlen = NULL, fminlen = NULL, /* facets of the current type */
17296 	fmininc = NULL, fmaxinc = NULL,
17297 	fminexc = NULL, fmaxexc = NULL,
17298 	bflength = NULL, bftotdig = NULL, bffracdig = NULL,
17299 	bfmaxlen = NULL, bfminlen = NULL, /* facets of the base type */
17300 	bfmininc = NULL, bfmaxinc = NULL,
17301 	bfminexc = NULL, bfmaxexc = NULL;
17302     int res; /* err = 0, fixedErr; */
17303 
17304     /*
17305     * SPEC st-restrict-facets 1:
17306     * "The {variety} of R is the same as that of B."
17307     */
17308     /*
17309     * SPEC st-restrict-facets 2:
17310     * "If {variety} is atomic, the {primitive type definition}
17311     * of R is the same as that of B."
17312     *
17313     * NOTE: we leave 1 & 2 out for now, since this will be
17314     * satisfied by the derivation process.
17315     * CONSTRUCTION TODO: Maybe needed if using a construction API.
17316     */
17317     /*
17318     * SPEC st-restrict-facets 3:
17319     * "The {facets} of R are the union of S and the {facets}
17320     * of B, eliminating duplicates. To eliminate duplicates,
17321     * when a facet of the same kind occurs in both S and the
17322     * {facets} of B, the one in the {facets} of B is not
17323     * included, with the exception of enumeration and pattern
17324     * facets, for which multiple occurrences with distinct values
17325     * are allowed."
17326     */
17327 
17328     if ((type->facetSet == NULL) && (base->facetSet == NULL))
17329 	return (0);
17330 
17331     last = type->facetSet;
17332     if (last != NULL)
17333 	while (last->next != NULL)
17334 	    last = last->next;
17335 
17336     for (cur = type->facetSet; cur != NULL; cur = cur->next) {
17337 	facet = cur->facet;
17338 	switch (facet->type) {
17339 	    case XML_SCHEMA_FACET_LENGTH:
17340 		flength = facet; break;
17341 	    case XML_SCHEMA_FACET_MINLENGTH:
17342 		fminlen = facet; break;
17343 	    case XML_SCHEMA_FACET_MININCLUSIVE:
17344 		fmininc = facet; break;
17345 	    case XML_SCHEMA_FACET_MINEXCLUSIVE:
17346 		fminexc = facet; break;
17347 	    case XML_SCHEMA_FACET_MAXLENGTH:
17348 		fmaxlen = facet; break;
17349 	    case XML_SCHEMA_FACET_MAXINCLUSIVE:
17350 		fmaxinc = facet; break;
17351 	    case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17352 		fmaxexc = facet; break;
17353 	    case XML_SCHEMA_FACET_TOTALDIGITS:
17354 		ftotdig = facet; break;
17355 	    case XML_SCHEMA_FACET_FRACTIONDIGITS:
17356 		ffracdig = facet; break;
17357 	    default:
17358 		break;
17359 	}
17360     }
17361     for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17362 	facet = cur->facet;
17363 	switch (facet->type) {
17364 	    case XML_SCHEMA_FACET_LENGTH:
17365 		bflength = facet; break;
17366 	    case XML_SCHEMA_FACET_MINLENGTH:
17367 		bfminlen = facet; break;
17368 	    case XML_SCHEMA_FACET_MININCLUSIVE:
17369 		bfmininc = facet; break;
17370 	    case XML_SCHEMA_FACET_MINEXCLUSIVE:
17371 		bfminexc = facet; break;
17372 	    case XML_SCHEMA_FACET_MAXLENGTH:
17373 		bfmaxlen = facet; break;
17374 	    case XML_SCHEMA_FACET_MAXINCLUSIVE:
17375 		bfmaxinc = facet; break;
17376 	    case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17377 		bfmaxexc = facet; break;
17378 	    case XML_SCHEMA_FACET_TOTALDIGITS:
17379 		bftotdig = facet; break;
17380 	    case XML_SCHEMA_FACET_FRACTIONDIGITS:
17381 		bffracdig = facet; break;
17382 	    default:
17383 		break;
17384 	}
17385     }
17386     /*
17387     * length and minLength or maxLength (2.2) + (3.2)
17388     */
17389     if (flength && (fminlen || fmaxlen)) {
17390 	FACET_RESTR_ERR(flength, "It is an error for both 'length' and "
17391 	    "either of 'minLength' or 'maxLength' to be specified on "
17392 	    "the same type definition")
17393     }
17394     /*
17395     * Mutual exclusions in the same derivation step.
17396     */
17397     if ((fmaxinc) && (fmaxexc)) {
17398 	/*
17399 	* SCC "maxInclusive and maxExclusive"
17400 	*/
17401 	FACET_RESTR_MUTUAL_ERR(fmaxinc, fmaxexc)
17402     }
17403     if ((fmininc) && (fminexc)) {
17404 	/*
17405 	* SCC "minInclusive and minExclusive"
17406 	*/
17407 	FACET_RESTR_MUTUAL_ERR(fmininc, fminexc)
17408     }
17409 
17410     if (flength && bflength) {
17411 	/*
17412 	* SCC "length valid restriction"
17413 	* The values have to be equal.
17414 	*/
17415 	res = xmlSchemaCompareValues(flength->val, bflength->val);
17416 	if (res == -2)
17417 	    goto internal_error;
17418 	if (res != 0)
17419 	    xmlSchemaDeriveFacetErr(pctxt, flength, bflength, 0, 0, 1);
17420 	if ((res != 0) && (bflength->fixed)) {
17421 	    FACET_RESTR_FIXED_ERR(flength)
17422 	}
17423 
17424     }
17425     if (fminlen && bfminlen) {
17426 	/*
17427 	* SCC "minLength valid restriction"
17428 	* minLength >= BASE minLength
17429 	*/
17430 	res = xmlSchemaCompareValues(fminlen->val, bfminlen->val);
17431 	if (res == -2)
17432 	    goto internal_error;
17433 	if (res == -1)
17434 	    xmlSchemaDeriveFacetErr(pctxt, fminlen, bfminlen, 1, 1, 1);
17435 	if ((res != 0) && (bfminlen->fixed)) {
17436 	    FACET_RESTR_FIXED_ERR(fminlen)
17437 	}
17438     }
17439     if (fmaxlen && bfmaxlen) {
17440 	/*
17441 	* SCC "maxLength valid restriction"
17442 	* maxLength <= BASE minLength
17443 	*/
17444 	res = xmlSchemaCompareValues(fmaxlen->val, bfmaxlen->val);
17445 	if (res == -2)
17446 	    goto internal_error;
17447 	if (res == 1)
17448 	    xmlSchemaDeriveFacetErr(pctxt, fmaxlen, bfmaxlen, -1, 1, 1);
17449 	if ((res != 0) && (bfmaxlen->fixed)) {
17450 	    FACET_RESTR_FIXED_ERR(fmaxlen)
17451 	}
17452     }
17453     /*
17454     * SCC "length and minLength or maxLength"
17455     */
17456     if (! flength)
17457 	flength = bflength;
17458     if (flength) {
17459 	if (! fminlen)
17460 	    fminlen = bfminlen;
17461 	if (fminlen) {
17462 	    /* (1.1) length >= minLength */
17463 	    res = xmlSchemaCompareValues(flength->val, fminlen->val);
17464 	    if (res == -2)
17465 		goto internal_error;
17466 	    if (res == -1)
17467 		xmlSchemaDeriveFacetErr(pctxt, flength, fminlen, 1, 1, 0);
17468 	}
17469 	if (! fmaxlen)
17470 	    fmaxlen = bfmaxlen;
17471 	if (fmaxlen) {
17472 	    /* (2.1) length <= maxLength */
17473 	    res = xmlSchemaCompareValues(flength->val, fmaxlen->val);
17474 	    if (res == -2)
17475 		goto internal_error;
17476 	    if (res == 1)
17477 		xmlSchemaDeriveFacetErr(pctxt, flength, fmaxlen, -1, 1, 0);
17478 	}
17479     }
17480     if (fmaxinc) {
17481 	/*
17482 	* "maxInclusive"
17483 	*/
17484 	if (fmininc) {
17485 	    /* SCC "maxInclusive >= minInclusive" */
17486 	    res = xmlSchemaCompareValues(fmaxinc->val, fmininc->val);
17487 	    if (res == -2)
17488 		goto internal_error;
17489 	    if (res == -1) {
17490 		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, fmininc, 1, 1, 0);
17491 	    }
17492 	}
17493 	/*
17494 	* SCC "maxInclusive valid restriction"
17495 	*/
17496 	if (bfmaxinc) {
17497 	    /* maxInclusive <= BASE maxInclusive */
17498 	    res = xmlSchemaCompareValues(fmaxinc->val, bfmaxinc->val);
17499 	    if (res == -2)
17500 		goto internal_error;
17501 	    if (res == 1)
17502 		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxinc, -1, 1, 1);
17503 	    if ((res != 0) && (bfmaxinc->fixed)) {
17504 		FACET_RESTR_FIXED_ERR(fmaxinc)
17505 	    }
17506 	}
17507 	if (bfmaxexc) {
17508 	    /* maxInclusive < BASE maxExclusive */
17509 	    res = xmlSchemaCompareValues(fmaxinc->val, bfmaxexc->val);
17510 	    if (res == -2)
17511 		goto internal_error;
17512 	    if (res != -1) {
17513 		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxexc, -1, 0, 1);
17514 	    }
17515 	}
17516 	if (bfmininc) {
17517 	    /* maxInclusive >= BASE minInclusive */
17518 	    res = xmlSchemaCompareValues(fmaxinc->val, bfmininc->val);
17519 	    if (res == -2)
17520 		goto internal_error;
17521 	    if (res == -1) {
17522 		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmininc, 1, 1, 1);
17523 	    }
17524 	}
17525 	if (bfminexc) {
17526 	    /* maxInclusive > BASE minExclusive */
17527 	    res = xmlSchemaCompareValues(fmaxinc->val, bfminexc->val);
17528 	    if (res == -2)
17529 		goto internal_error;
17530 	    if (res != 1) {
17531 		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfminexc, 1, 0, 1);
17532 	    }
17533 	}
17534     }
17535     if (fmaxexc) {
17536 	/*
17537 	* "maxExclusive >= minExclusive"
17538 	*/
17539 	if (fminexc) {
17540 	    res = xmlSchemaCompareValues(fmaxexc->val, fminexc->val);
17541 	    if (res == -2)
17542 		goto internal_error;
17543 	    if (res == -1) {
17544 		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, fminexc, 1, 1, 0);
17545 	    }
17546 	}
17547 	/*
17548 	* "maxExclusive valid restriction"
17549 	*/
17550 	if (bfmaxexc) {
17551 	    /* maxExclusive <= BASE maxExclusive */
17552 	    res = xmlSchemaCompareValues(fmaxexc->val, bfmaxexc->val);
17553 	    if (res == -2)
17554 		goto internal_error;
17555 	    if (res == 1) {
17556 		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxexc, -1, 1, 1);
17557 	    }
17558 	    if ((res != 0) && (bfmaxexc->fixed)) {
17559 		FACET_RESTR_FIXED_ERR(fmaxexc)
17560 	    }
17561 	}
17562 	if (bfmaxinc) {
17563 	    /* maxExclusive <= BASE maxInclusive */
17564 	    res = xmlSchemaCompareValues(fmaxexc->val, bfmaxinc->val);
17565 	    if (res == -2)
17566 		goto internal_error;
17567 	    if (res == 1) {
17568 		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxinc, -1, 1, 1);
17569 	    }
17570 	}
17571 	if (bfmininc) {
17572 	    /* maxExclusive > BASE minInclusive */
17573 	    res = xmlSchemaCompareValues(fmaxexc->val, bfmininc->val);
17574 	    if (res == -2)
17575 		goto internal_error;
17576 	    if (res != 1) {
17577 		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmininc, 1, 0, 1);
17578 	    }
17579 	}
17580 	if (bfminexc) {
17581 	    /* maxExclusive > BASE minExclusive */
17582 	    res = xmlSchemaCompareValues(fmaxexc->val, bfminexc->val);
17583 	    if (res == -2)
17584 		goto internal_error;
17585 	    if (res != 1) {
17586 		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfminexc, 1, 0, 1);
17587 	    }
17588 	}
17589     }
17590     if (fminexc) {
17591 	/*
17592 	* "minExclusive < maxInclusive"
17593 	*/
17594 	if (fmaxinc) {
17595 	    res = xmlSchemaCompareValues(fminexc->val, fmaxinc->val);
17596 	    if (res == -2)
17597 		goto internal_error;
17598 	    if (res != -1) {
17599 		xmlSchemaDeriveFacetErr(pctxt, fminexc, fmaxinc, -1, 0, 0);
17600 	    }
17601 	}
17602 	/*
17603 	* "minExclusive valid restriction"
17604 	*/
17605 	if (bfminexc) {
17606 	    /* minExclusive >= BASE minExclusive */
17607 	    res = xmlSchemaCompareValues(fminexc->val, bfminexc->val);
17608 	    if (res == -2)
17609 		goto internal_error;
17610 	    if (res == -1) {
17611 		xmlSchemaDeriveFacetErr(pctxt, fminexc, bfminexc, 1, 1, 1);
17612 	    }
17613 	    if ((res != 0) && (bfminexc->fixed)) {
17614 		FACET_RESTR_FIXED_ERR(fminexc)
17615 	    }
17616 	}
17617 	if (bfmaxinc) {
17618 	    /* minExclusive <= BASE maxInclusive */
17619 	    res = xmlSchemaCompareValues(fminexc->val, bfmaxinc->val);
17620 	    if (res == -2)
17621 		goto internal_error;
17622 	    if (res == 1) {
17623 		xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxinc, -1, 1, 1);
17624 	    }
17625 	}
17626 	if (bfmininc) {
17627 	    /* minExclusive >= BASE minInclusive */
17628 	    res = xmlSchemaCompareValues(fminexc->val, bfmininc->val);
17629 	    if (res == -2)
17630 		goto internal_error;
17631 	    if (res == -1) {
17632 		xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmininc, 1, 1, 1);
17633 	    }
17634 	}
17635 	if (bfmaxexc) {
17636 	    /* minExclusive < BASE maxExclusive */
17637 	    res = xmlSchemaCompareValues(fminexc->val, bfmaxexc->val);
17638 	    if (res == -2)
17639 		goto internal_error;
17640 	    if (res != -1) {
17641 		xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxexc, -1, 0, 1);
17642 	    }
17643 	}
17644     }
17645     if (fmininc) {
17646 	/*
17647 	* "minInclusive < maxExclusive"
17648 	*/
17649 	if (fmaxexc) {
17650 	    res = xmlSchemaCompareValues(fmininc->val, fmaxexc->val);
17651 	    if (res == -2)
17652 		goto internal_error;
17653 	    if (res != -1) {
17654 		xmlSchemaDeriveFacetErr(pctxt, fmininc, fmaxexc, -1, 0, 0);
17655 	    }
17656 	}
17657 	/*
17658 	* "minExclusive valid restriction"
17659 	*/
17660 	if (bfmininc) {
17661 	    /* minInclusive >= BASE minInclusive */
17662 	    res = xmlSchemaCompareValues(fmininc->val, bfmininc->val);
17663 	    if (res == -2)
17664 		goto internal_error;
17665 	    if (res == -1) {
17666 		xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmininc, 1, 1, 1);
17667 	    }
17668 	    if ((res != 0) && (bfmininc->fixed)) {
17669 		FACET_RESTR_FIXED_ERR(fmininc)
17670 	    }
17671 	}
17672 	if (bfmaxinc) {
17673 	    /* minInclusive <= BASE maxInclusive */
17674 	    res = xmlSchemaCompareValues(fmininc->val, bfmaxinc->val);
17675 	    if (res == -2)
17676 		goto internal_error;
17677 	    if (res == 1) {
17678 		xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxinc, -1, 1, 1);
17679 	    }
17680 	}
17681 	if (bfminexc) {
17682 	    /* minInclusive > BASE minExclusive */
17683 	    res = xmlSchemaCompareValues(fmininc->val, bfminexc->val);
17684 	    if (res == -2)
17685 		goto internal_error;
17686 	    if (res != 1)
17687 		xmlSchemaDeriveFacetErr(pctxt, fmininc, bfminexc, 1, 0, 1);
17688 	}
17689 	if (bfmaxexc) {
17690 	    /* minInclusive < BASE maxExclusive */
17691 	    res = xmlSchemaCompareValues(fmininc->val, bfmaxexc->val);
17692 	    if (res == -2)
17693 		goto internal_error;
17694 	    if (res != -1)
17695 		xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxexc, -1, 0, 1);
17696 	}
17697     }
17698     if (ftotdig && bftotdig) {
17699 	/*
17700 	* SCC " totalDigits valid restriction"
17701 	* totalDigits <= BASE totalDigits
17702 	*/
17703 	res = xmlSchemaCompareValues(ftotdig->val, bftotdig->val);
17704 	if (res == -2)
17705 	    goto internal_error;
17706 	if (res == 1)
17707 	    xmlSchemaDeriveFacetErr(pctxt, ftotdig, bftotdig,
17708 	    -1, 1, 1);
17709 	if ((res != 0) && (bftotdig->fixed)) {
17710 	    FACET_RESTR_FIXED_ERR(ftotdig)
17711 	}
17712     }
17713     if (ffracdig && bffracdig) {
17714 	/*
17715 	* SCC  "fractionDigits valid restriction"
17716 	* fractionDigits <= BASE fractionDigits
17717 	*/
17718 	res = xmlSchemaCompareValues(ffracdig->val, bffracdig->val);
17719 	if (res == -2)
17720 	    goto internal_error;
17721 	if (res == 1)
17722 	    xmlSchemaDeriveFacetErr(pctxt, ffracdig, bffracdig,
17723 	    -1, 1, 1);
17724 	if ((res != 0) && (bffracdig->fixed)) {
17725 	    FACET_RESTR_FIXED_ERR(ffracdig)
17726 	}
17727     }
17728     /*
17729     * SCC "fractionDigits less than or equal to totalDigits"
17730     */
17731     if (! ftotdig)
17732 	ftotdig = bftotdig;
17733     if (! ffracdig)
17734 	ffracdig = bffracdig;
17735     if (ftotdig && ffracdig) {
17736 	res = xmlSchemaCompareValues(ffracdig->val, ftotdig->val);
17737 	if (res == -2)
17738 	    goto internal_error;
17739 	if (res == 1)
17740 	    xmlSchemaDeriveFacetErr(pctxt, ffracdig, ftotdig,
17741 		-1, 1, 0);
17742     }
17743     /*
17744     * *Enumerations* won' be added here, since only the first set
17745     * of enumerations in the ancestor-or-self axis is used
17746     * for validation, plus we need to use the base type of those
17747     * enumerations for whitespace.
17748     *
17749     * *Patterns*: won't be add here, since they are ORed at
17750     * type level and ANDed at ancestor level. This will
17751     * happed during validation by walking the base axis
17752     * of the type.
17753     */
17754     for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17755 	bfacet = cur->facet;
17756 	/*
17757 	* Special handling of enumerations and patterns.
17758 	* TODO: hmm, they should not appear in the set, so remove this.
17759 	*/
17760 	if ((bfacet->type == XML_SCHEMA_FACET_PATTERN) ||
17761 	    (bfacet->type == XML_SCHEMA_FACET_ENUMERATION))
17762 	    continue;
17763 	/*
17764 	* Search for a duplicate facet in the current type.
17765 	*/
17766 	link = type->facetSet;
17767 	/* err = 0; */
17768 	/* fixedErr = 0; */
17769 	while (link != NULL) {
17770 	    facet = link->facet;
17771 	    if (facet->type == bfacet->type) {
17772 		switch (facet->type) {
17773 		    case XML_SCHEMA_FACET_WHITESPACE:
17774 			/*
17775 			* The whitespace must be stronger.
17776 			*/
17777 			if (facet->whitespace < bfacet->whitespace) {
17778 			    FACET_RESTR_ERR(facet,
17779 				"The 'whitespace' value has to be equal to "
17780 				"or stronger than the 'whitespace' value of "
17781 				"the base type")
17782 			}
17783 			if ((bfacet->fixed) &&
17784 			    (facet->whitespace != bfacet->whitespace)) {
17785 			    FACET_RESTR_FIXED_ERR(facet)
17786 			}
17787 			break;
17788 		    default:
17789 			break;
17790 		}
17791 		/* Duplicate found. */
17792 		break;
17793 	    }
17794 	    link = link->next;
17795 	}
17796 	/*
17797 	* If no duplicate was found: add the base types's facet
17798 	* to the set.
17799 	*/
17800 	if (link == NULL) {
17801 	    link = (xmlSchemaFacetLinkPtr)
17802 		xmlMalloc(sizeof(xmlSchemaFacetLink));
17803 	    if (link == NULL) {
17804 		xmlSchemaPErrMemory(pctxt,
17805 		    "deriving facets, creating a facet link", NULL);
17806 		return (-1);
17807 	    }
17808 	    link->facet = cur->facet;
17809 	    link->next = NULL;
17810 	    if (last == NULL)
17811 		type->facetSet = link;
17812 	    else
17813 		last->next = link;
17814 	    last = link;
17815 	}
17816 
17817     }
17818 
17819     return (0);
17820 internal_error:
17821     PERROR_INT("xmlSchemaDeriveAndValidateFacets",
17822 	"an error occurred");
17823     return (-1);
17824 }
17825 
17826 static int
xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)17827 xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,
17828 					     xmlSchemaTypePtr type)
17829 {
17830     xmlSchemaTypeLinkPtr link, lastLink, prevLink, subLink, newLink;
17831     /*
17832     * The actual value is then formed by replacing any union type
17833     * definition in the `explicit members` with the members of their
17834     * {member type definitions}, in order.
17835     *
17836     * TODO: There's a bug entry at
17837     * "http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0287.html"
17838     * which indicates that we'll keep the union types the future.
17839     */
17840     link = type->memberTypes;
17841     while (link != NULL) {
17842 
17843 	if (WXS_IS_TYPE_NOT_FIXED(link->type))
17844 	    xmlSchemaTypeFixup(link->type, ACTXT_CAST pctxt);
17845 
17846 	if (WXS_IS_UNION(link->type)) {
17847 	    subLink = xmlSchemaGetUnionSimpleTypeMemberTypes(link->type);
17848 	    if (subLink != NULL) {
17849 		link->type = subLink->type;
17850 		if (subLink->next != NULL) {
17851 		    lastLink = link->next;
17852 		    subLink = subLink->next;
17853 		    prevLink = link;
17854 		    while (subLink != NULL) {
17855 			newLink = (xmlSchemaTypeLinkPtr)
17856 			    xmlMalloc(sizeof(xmlSchemaTypeLink));
17857 			if (newLink == NULL) {
17858 			    xmlSchemaPErrMemory(pctxt, "allocating a type link",
17859 				NULL);
17860 			    return (-1);
17861 			}
17862 			newLink->type = subLink->type;
17863 			prevLink->next = newLink;
17864 			prevLink = newLink;
17865 			newLink->next = lastLink;
17866 
17867 			subLink = subLink->next;
17868 		    }
17869 		}
17870 	    }
17871 	}
17872 	link = link->next;
17873     }
17874     return (0);
17875 }
17876 
17877 static void
xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type)17878 xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type)
17879 {
17880     int has = 0, needVal = 0, normVal = 0;
17881 
17882     has	= (type->baseType->flags & XML_SCHEMAS_TYPE_HAS_FACETS) ? 1 : 0;
17883     if (has) {
17884 	needVal = (type->baseType->flags &
17885 	    XML_SCHEMAS_TYPE_FACETSNEEDVALUE) ? 1 : 0;
17886 	normVal = (type->baseType->flags &
17887 	    XML_SCHEMAS_TYPE_NORMVALUENEEDED) ? 1 : 0;
17888     }
17889     if (type->facets != NULL) {
17890 	xmlSchemaFacetPtr fac;
17891 
17892 	for (fac = type->facets; fac != NULL; fac = fac->next) {
17893 	    switch (fac->type) {
17894 		case XML_SCHEMA_FACET_WHITESPACE:
17895 		    break;
17896 		case XML_SCHEMA_FACET_PATTERN:
17897 		    normVal = 1;
17898 		    has = 1;
17899 		    break;
17900 		case XML_SCHEMA_FACET_ENUMERATION:
17901 		    needVal = 1;
17902 		    normVal = 1;
17903 		    has = 1;
17904 		    break;
17905 		default:
17906 		    has = 1;
17907 		    break;
17908 	    }
17909 	}
17910     }
17911     if (normVal)
17912 	type->flags |= XML_SCHEMAS_TYPE_NORMVALUENEEDED;
17913     if (needVal)
17914 	type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17915     if (has)
17916 	type->flags |= XML_SCHEMAS_TYPE_HAS_FACETS;
17917 
17918     if (has && (! needVal) && WXS_IS_ATOMIC(type)) {
17919 	xmlSchemaTypePtr prim = xmlSchemaGetPrimitiveType(type);
17920 	/*
17921 	* OPTIMIZE VAL TODO: Some facets need a computed value.
17922 	*/
17923 	if ((prim->builtInType != XML_SCHEMAS_ANYSIMPLETYPE) &&
17924 	    (prim->builtInType != XML_SCHEMAS_STRING)) {
17925 	    type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17926 	}
17927     }
17928 }
17929 
17930 static int
xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type)17931 xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type)
17932 {
17933 
17934 
17935     /*
17936     * Evaluate the whitespace-facet value.
17937     */
17938     if (WXS_IS_LIST(type)) {
17939 	type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17940 	return (0);
17941     } else if (WXS_IS_UNION(type))
17942 	return (0);
17943 
17944     if (type->facetSet != NULL) {
17945 	xmlSchemaFacetLinkPtr lin;
17946 
17947 	for (lin = type->facetSet; lin != NULL; lin = lin->next) {
17948 	    if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
17949 		switch (lin->facet->whitespace) {
17950 		case XML_SCHEMAS_FACET_PRESERVE:
17951 		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
17952 		    break;
17953 		case XML_SCHEMAS_FACET_REPLACE:
17954 		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
17955 		    break;
17956 		case XML_SCHEMAS_FACET_COLLAPSE:
17957 		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17958 		    break;
17959 		default:
17960 		    return (-1);
17961 		}
17962 		return (0);
17963 	    }
17964 	}
17965     }
17966     /*
17967     * For all `atomic` datatypes other than string (and types `derived`
17968     * by `restriction` from it) the value of whiteSpace is fixed to
17969     * collapse
17970     */
17971     {
17972 	xmlSchemaTypePtr anc;
17973 
17974 	for (anc = type->baseType; anc != NULL &&
17975 		anc->builtInType != XML_SCHEMAS_ANYTYPE;
17976 		anc = anc->baseType) {
17977 
17978 	    if (anc->type == XML_SCHEMA_TYPE_BASIC) {
17979 		if (anc->builtInType == XML_SCHEMAS_NORMSTRING) {
17980 		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
17981 
17982 		} else if ((anc->builtInType == XML_SCHEMAS_STRING) ||
17983 		    (anc->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)) {
17984 		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
17985 
17986 		} else
17987 		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17988 		break;
17989 	    }
17990 	}
17991     }
17992     return (0);
17993 }
17994 
17995 static int
xmlSchemaFixupSimpleTypeStageOne(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)17996 xmlSchemaFixupSimpleTypeStageOne(xmlSchemaParserCtxtPtr pctxt,
17997 			  xmlSchemaTypePtr type)
17998 {
17999     if (type->type != XML_SCHEMA_TYPE_SIMPLE)
18000 	return(0);
18001     if (! WXS_IS_TYPE_NOT_FIXED_1(type))
18002 	return(0);
18003     type->flags |= XML_SCHEMAS_TYPE_FIXUP_1;
18004 
18005     if (WXS_IS_LIST(type)) {
18006 	/*
18007 	* Corresponds to <simpleType><list>...
18008 	*/
18009 	if (type->subtypes == NULL) {
18010 	    /*
18011 	    * This one is really needed, so get out.
18012 	    */
18013 	    PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
18014 		"list type has no item-type assigned");
18015 	    return(-1);
18016 	}
18017     } else if (WXS_IS_UNION(type)) {
18018 	/*
18019 	* Corresponds to <simpleType><union>...
18020 	*/
18021 	if (type->memberTypes == NULL) {
18022 	    /*
18023 	    * This one is really needed, so get out.
18024 	    */
18025 	    PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
18026 		"union type has no member-types assigned");
18027 	    return(-1);
18028 	}
18029     } else {
18030 	/*
18031 	* Corresponds to <simpleType><restriction>...
18032 	*/
18033 	if (type->baseType == NULL) {
18034 	    PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
18035 		"type has no base-type assigned");
18036 	    return(-1);
18037 	}
18038 	if (WXS_IS_TYPE_NOT_FIXED_1(type->baseType))
18039 	    if (xmlSchemaFixupSimpleTypeStageOne(pctxt, type->baseType) == -1)
18040 		return(-1);
18041 	/*
18042 	* Variety
18043 	* If the <restriction> alternative is chosen, then the
18044 	* {variety} of the {base type definition}.
18045 	*/
18046 	if (WXS_IS_ATOMIC(type->baseType))
18047 	    type->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
18048 	else if (WXS_IS_LIST(type->baseType)) {
18049 	    type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
18050 	    /*
18051 	    * Inherit the itemType.
18052 	    */
18053 	    type->subtypes = type->baseType->subtypes;
18054 	} else if (WXS_IS_UNION(type->baseType)) {
18055 	    type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
18056 	    /*
18057 	    * NOTE that we won't assign the memberTypes of the base,
18058 	    * since this will make trouble when freeing them; we will
18059 	    * use a lookup function to access them instead.
18060 	    */
18061 	}
18062     }
18063     return(0);
18064 }
18065 
18066 #ifdef DEBUG_TYPE
18067 static void
xmlSchemaDebugFixedType(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)18068 xmlSchemaDebugFixedType(xmlSchemaParserCtxtPtr pctxt,
18069 		       xmlSchemaTypePtr type)
18070 {
18071     if (type->node != NULL) {
18072         xmlGenericError(xmlGenericErrorContext,
18073                         "Type of %s : %s:%d :", name,
18074                         type->node->doc->URL,
18075                         xmlGetLineNo(type->node));
18076     } else {
18077         xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
18078     }
18079     if ((WXS_IS_SIMPLE(type)) || (WXS_IS_COMPLEX(type))) {
18080 	switch (type->contentType) {
18081 	    case XML_SCHEMA_CONTENT_SIMPLE:
18082 		xmlGenericError(xmlGenericErrorContext, "simple\n");
18083 		break;
18084 	    case XML_SCHEMA_CONTENT_ELEMENTS:
18085 		xmlGenericError(xmlGenericErrorContext, "elements\n");
18086 		break;
18087 	    case XML_SCHEMA_CONTENT_UNKNOWN:
18088 		xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
18089 		break;
18090 	    case XML_SCHEMA_CONTENT_EMPTY:
18091 		xmlGenericError(xmlGenericErrorContext, "empty\n");
18092 		break;
18093 	    case XML_SCHEMA_CONTENT_MIXED:
18094 		if (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr)
18095 		    type->subtypes))
18096 		    xmlGenericError(xmlGenericErrorContext,
18097 			"mixed as emptiable particle\n");
18098 		else
18099 		    xmlGenericError(xmlGenericErrorContext, "mixed\n");
18100 		break;
18101 		/* Removed, since not used. */
18102 		/*
18103 		case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
18104 		xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
18105 		break;
18106 		*/
18107 	    case XML_SCHEMA_CONTENT_BASIC:
18108 		xmlGenericError(xmlGenericErrorContext, "basic\n");
18109 		break;
18110 	    default:
18111 		xmlGenericError(xmlGenericErrorContext,
18112 		    "not registered !!!\n");
18113 		break;
18114 	}
18115     }
18116 }
18117 #endif
18118 
18119 /*
18120 * 3.14.6 Constraints on Simple Type Definition Schema Components
18121 */
18122 static int
xmlSchemaFixupSimpleTypeStageTwo(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)18123 xmlSchemaFixupSimpleTypeStageTwo(xmlSchemaParserCtxtPtr pctxt,
18124 				 xmlSchemaTypePtr type)
18125 {
18126     int res, olderrs = pctxt->nberrors;
18127 
18128     if (type->type != XML_SCHEMA_TYPE_SIMPLE)
18129 	return(-1);
18130 
18131     if (! WXS_IS_TYPE_NOT_FIXED(type))
18132 	return(0);
18133 
18134     type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
18135     type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
18136 
18137     if (type->baseType == NULL) {
18138 	PERROR_INT("xmlSchemaFixupSimpleTypeStageTwo",
18139 	    "missing baseType");
18140 	goto exit_failure;
18141     }
18142     if (WXS_IS_TYPE_NOT_FIXED(type->baseType))
18143 	xmlSchemaTypeFixup(type->baseType, ACTXT_CAST pctxt);
18144     /*
18145     * If a member type of a union is a union itself, we need to substitute
18146     * that member type for its member types.
18147     * NOTE that this might change in WXS 1.1; i.e. we will keep the union
18148     * types in WXS 1.1.
18149     */
18150     if ((type->memberTypes != NULL) &&
18151 	(xmlSchemaFinishMemberTypeDefinitionsProperty(pctxt, type) == -1))
18152 	return(-1);
18153     /*
18154     * SPEC src-simple-type 1
18155     * "The corresponding simple type definition, if any, must satisfy
18156     * the conditions set out in Constraints on Simple Type Definition
18157     * Schema Components ($3.14.6)."
18158     */
18159     /*
18160     * Schema Component Constraint: Simple Type Definition Properties Correct
18161     * (st-props-correct)
18162     */
18163     res = xmlSchemaCheckSTPropsCorrect(pctxt, type);
18164     HFAILURE HERROR
18165     /*
18166     * Schema Component Constraint: Derivation Valid (Restriction, Simple)
18167     * (cos-st-restricts)
18168     */
18169     res = xmlSchemaCheckCOSSTRestricts(pctxt, type);
18170     HFAILURE HERROR
18171     /*
18172     * TODO: Removed the error report, since it got annoying to get an
18173     * extra error report, if anything failed until now.
18174     * Enable this if needed.
18175     *
18176     * xmlSchemaPErr(ctxt, type->node,
18177     *    XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
18178     *    "Simple type '%s' does not satisfy the constraints "
18179     *    "on simple type definitions.\n",
18180     *    type->name, NULL);
18181     */
18182     /*
18183     * Schema Component Constraint: Simple Type Restriction (Facets)
18184     * (st-restrict-facets)
18185     */
18186     res = xmlSchemaCheckFacetValues(type, pctxt);
18187     HFAILURE HERROR
18188     if ((type->facetSet != NULL) ||
18189 	(type->baseType->facetSet != NULL)) {
18190 	res = xmlSchemaDeriveAndValidateFacets(pctxt, type);
18191 	HFAILURE HERROR
18192     }
18193     /*
18194     * Whitespace value.
18195     */
18196     res = xmlSchemaTypeFixupWhitespace(type);
18197     HFAILURE HERROR
18198     xmlSchemaTypeFixupOptimFacets(type);
18199 
18200 exit_error:
18201 #ifdef DEBUG_TYPE
18202     xmlSchemaDebugFixedType(pctxt, type);
18203 #endif
18204     if (olderrs != pctxt->nberrors)
18205 	return(pctxt->err);
18206     return(0);
18207 
18208 exit_failure:
18209 #ifdef DEBUG_TYPE
18210     xmlSchemaDebugFixedType(pctxt, type);
18211 #endif
18212     return(-1);
18213 }
18214 
18215 static int
xmlSchemaFixupComplexType(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)18216 xmlSchemaFixupComplexType(xmlSchemaParserCtxtPtr pctxt,
18217 			  xmlSchemaTypePtr type)
18218 {
18219     int res = 0, olderrs = pctxt->nberrors;
18220     xmlSchemaTypePtr baseType = type->baseType;
18221 
18222     if (! WXS_IS_TYPE_NOT_FIXED(type))
18223 	return(0);
18224     type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
18225     if (baseType == NULL) {
18226 	PERROR_INT("xmlSchemaFixupComplexType",
18227 	    "missing baseType");
18228 	goto exit_failure;
18229     }
18230     /*
18231     * Fixup the base type.
18232     */
18233     if (WXS_IS_TYPE_NOT_FIXED(baseType))
18234 	xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt);
18235     if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) {
18236 	/*
18237 	* Skip fixup if the base type is invalid.
18238 	* TODO: Generate a warning!
18239 	*/
18240 	return(0);
18241     }
18242     /*
18243     * This basically checks if the base type can be derived.
18244     */
18245     res = xmlSchemaCheckSRCCT(pctxt, type);
18246     HFAILURE HERROR
18247     /*
18248     * Fixup the content type.
18249     */
18250     if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) {
18251 	/*
18252 	* Corresponds to <complexType><simpleContent>...
18253 	*/
18254 	if ((WXS_IS_COMPLEX(baseType)) &&
18255 	    (baseType->contentTypeDef != NULL) &&
18256 	    (WXS_IS_RESTRICTION(type))) {
18257 	    xmlSchemaTypePtr contentBase, content;
18258 #ifdef ENABLE_NAMED_LOCALS
18259 	    char buf[30];
18260 	    const xmlChar *tmpname;
18261 #endif
18262 	    /*
18263 	    * SPEC (1) If <restriction> + base type is <complexType>,
18264 	    * "whose own {content type} is a simple type..."
18265 	    */
18266 	    if (type->contentTypeDef != NULL) {
18267 		/*
18268 		* SPEC (1.1) "the simple type definition corresponding to the
18269 		* <simpleType> among the [children] of <restriction> if there
18270 		* is one;"
18271 		* Note that this "<simpleType> among the [children]" was put
18272 		* into ->contentTypeDef during parsing.
18273 		*/
18274 		contentBase = type->contentTypeDef;
18275 		type->contentTypeDef = NULL;
18276 	    } else {
18277 		/*
18278 		* (1.2) "...otherwise (<restriction> has no <simpleType>
18279 		* among its [children]), the simple type definition which
18280 		* is the {content type} of the ... base type."
18281 		*/
18282 		contentBase = baseType->contentTypeDef;
18283 	    }
18284 	    /*
18285 	    * SPEC
18286 	    * "... a simple type definition which restricts the simple
18287 	    * type definition identified in clause 1.1 or clause 1.2
18288 	    * with a set of facet components"
18289 	    *
18290 	    * Create the anonymous simple type, which will be the content
18291 	    * type of the complex type.
18292 	    */
18293 #ifdef ENABLE_NAMED_LOCALS
18294 	    snprintf(buf, 29, "#scST%d", ++(pctxt->counter));
18295 	    tmpname = xmlDictLookup(pctxt->dict, BAD_CAST buf, -1);
18296 	    content = xmlSchemaAddType(pctxt, pctxt->schema,
18297 		XML_SCHEMA_TYPE_SIMPLE, tmpname, type->targetNamespace,
18298 		type->node, 0);
18299 #else
18300 	    content = xmlSchemaAddType(pctxt, pctxt->schema,
18301 		XML_SCHEMA_TYPE_SIMPLE, NULL, type->targetNamespace,
18302 		type->node, 0);
18303 #endif
18304 	    if (content == NULL)
18305 		goto exit_failure;
18306 	    /*
18307 	    * We will use the same node as for the <complexType>
18308 	    * to have it somehow anchored in the schema doc.
18309 	    */
18310 	    content->type = XML_SCHEMA_TYPE_SIMPLE;
18311 	    content->baseType = contentBase;
18312 	    /*
18313 	    * Move the facets, previously anchored on the
18314 	    * complexType during parsing.
18315 	    */
18316 	    content->facets = type->facets;
18317 	    type->facets = NULL;
18318 	    content->facetSet = type->facetSet;
18319 	    type->facetSet = NULL;
18320 
18321 	    type->contentTypeDef = content;
18322 	    if (WXS_IS_TYPE_NOT_FIXED(contentBase))
18323 		xmlSchemaTypeFixup(contentBase, ACTXT_CAST pctxt);
18324 	    /*
18325 	    * Fixup the newly created type. We don't need to check
18326 	    * for circularity here.
18327 	    */
18328 	    res = xmlSchemaFixupSimpleTypeStageOne(pctxt, content);
18329 	    HFAILURE HERROR
18330 	    res = xmlSchemaFixupSimpleTypeStageTwo(pctxt, content);
18331 	    HFAILURE HERROR
18332 
18333 	} else if ((WXS_IS_COMPLEX(baseType)) &&
18334 	    (baseType->contentType == XML_SCHEMA_CONTENT_MIXED) &&
18335 	    (WXS_IS_RESTRICTION(type))) {
18336 	    /*
18337 	    * SPEC (2) If <restriction> + base is a mixed <complexType> with
18338 	    * an emptiable particle, then a simple type definition which
18339 	    * restricts the <restriction>'s <simpleType> child.
18340 	    */
18341 	    if ((type->contentTypeDef == NULL) ||
18342 		(type->contentTypeDef->baseType == NULL)) {
18343 		/*
18344 		* TODO: Check if this ever happens.
18345 		*/
18346 		xmlSchemaPCustomErr(pctxt,
18347 		    XML_SCHEMAP_INTERNAL,
18348 		    WXS_BASIC_CAST type, NULL,
18349 		    "Internal error: xmlSchemaTypeFixup, "
18350 		    "complex type '%s': the <simpleContent><restriction> "
18351 		    "is missing a <simpleType> child, but was not catched "
18352 		    "by xmlSchemaCheckSRCCT()", type->name);
18353 		goto exit_failure;
18354 	    }
18355 	} else if ((WXS_IS_COMPLEX(baseType)) && WXS_IS_EXTENSION(type)) {
18356 	    /*
18357 	    * SPEC (3) If <extension> + base is <complexType> with
18358 	    * <simpleType> content, "...then the {content type} of that
18359 	    * complex type definition"
18360 	    */
18361 	    if (baseType->contentTypeDef == NULL) {
18362 		/*
18363 		* TODO: Check if this ever happens. xmlSchemaCheckSRCCT
18364 		* should have catched this already.
18365 		*/
18366 		xmlSchemaPCustomErr(pctxt,
18367 		    XML_SCHEMAP_INTERNAL,
18368 		    WXS_BASIC_CAST type, NULL,
18369 		    "Internal error: xmlSchemaTypeFixup, "
18370 		    "complex type '%s': the <extension>ed base type is "
18371 		    "a complex type with no simple content type",
18372 		    type->name);
18373 		goto exit_failure;
18374 	    }
18375 	    type->contentTypeDef = baseType->contentTypeDef;
18376 	} else if ((WXS_IS_SIMPLE(baseType)) && WXS_IS_EXTENSION(type)) {
18377 	    /*
18378 	    * SPEC (4) <extension> + base is <simpleType>
18379 	    * "... then that simple type definition"
18380 	    */
18381 	    type->contentTypeDef = baseType;
18382 	} else {
18383 	    /*
18384 	    * TODO: Check if this ever happens.
18385 	    */
18386 	    xmlSchemaPCustomErr(pctxt,
18387 		XML_SCHEMAP_INTERNAL,
18388 		WXS_BASIC_CAST type, NULL,
18389 		"Internal error: xmlSchemaTypeFixup, "
18390 		"complex type '%s' with <simpleContent>: unhandled "
18391 		"derivation case", type->name);
18392 	    goto exit_failure;
18393 	}
18394     } else {
18395 	int dummySequence = 0;
18396 	xmlSchemaParticlePtr particle =
18397 	    (xmlSchemaParticlePtr) type->subtypes;
18398 	/*
18399 	* Corresponds to <complexType><complexContent>...
18400 	*
18401 	* NOTE that the effective mixed was already set during parsing of
18402 	* <complexType> and <complexContent>; its flag value is
18403 	* XML_SCHEMAS_TYPE_MIXED.
18404 	*
18405 	* Compute the "effective content":
18406 	* (2.1.1) + (2.1.2) + (2.1.3)
18407 	*/
18408 	if ((particle == NULL) ||
18409 	    ((particle->type == XML_SCHEMA_TYPE_PARTICLE) &&
18410 	    ((particle->children->type == XML_SCHEMA_TYPE_ALL) ||
18411 	    (particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) ||
18412 	    ((particle->children->type == XML_SCHEMA_TYPE_CHOICE) &&
18413 	    (particle->minOccurs == 0))) &&
18414 	    ( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) {
18415 	    if (type->flags & XML_SCHEMAS_TYPE_MIXED) {
18416 		/*
18417 		* SPEC (2.1.4) "If the `effective mixed` is true, then
18418 		* a particle whose properties are as follows:..."
18419 		*
18420 		* Empty sequence model group with
18421 		* minOccurs/maxOccurs = 1 (i.e. a "particle emptiable").
18422 		* NOTE that we sill assign it the <complexType> node to
18423 		* somehow anchor it in the doc.
18424 		*/
18425 		if ((particle == NULL) ||
18426 		    (particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) {
18427 		    /*
18428 		    * Create the particle.
18429 		    */
18430 		    particle = xmlSchemaAddParticle(pctxt,
18431 			type->node, 1, 1);
18432 		    if (particle == NULL)
18433 			goto exit_failure;
18434 		    /*
18435 		    * Create the model group.
18436 		    */ /* URGENT TODO: avoid adding to pending items. */
18437 		    particle->children = (xmlSchemaTreeItemPtr)
18438 			xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18439 			XML_SCHEMA_TYPE_SEQUENCE, type->node);
18440 		    if (particle->children == NULL)
18441 			goto exit_failure;
18442 
18443 		    type->subtypes = (xmlSchemaTypePtr) particle;
18444 		}
18445 		dummySequence = 1;
18446 		type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18447 	    } else {
18448 		/*
18449 		* SPEC (2.1.5) "otherwise empty"
18450 		*/
18451 		type->contentType = XML_SCHEMA_CONTENT_EMPTY;
18452 	    }
18453 	} else {
18454 	    /*
18455 	    * SPEC (2.2) "otherwise the particle corresponding to the
18456 	    * <all>, <choice>, <group> or <sequence> among the
18457 	    * [children]."
18458 	    */
18459 	    type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18460 	}
18461 	/*
18462 	* Compute the "content type".
18463 	*/
18464 	if (WXS_IS_RESTRICTION(type)) {
18465 	    /*
18466 	    * SPEC (3.1) "If <restriction>..."
18467 	    * (3.1.1) + (3.1.2) */
18468 	    if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) {
18469 		if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18470 		    type->contentType = XML_SCHEMA_CONTENT_MIXED;
18471 	    }
18472 	} else {
18473 	    /*
18474 	    * SPEC (3.2) "If <extension>..."
18475 	    */
18476 	    if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18477 		/*
18478 		* SPEC (3.2.1)
18479 		* "If the `effective content` is empty, then the
18480 		*  {content type} of the [...] base ..."
18481 		*/
18482 		type->contentType = baseType->contentType;
18483 		type->subtypes = baseType->subtypes;
18484 		/*
18485 		* Fixes bug #347316:
18486 		* This is the case when the base type has a simple
18487 		* type definition as content.
18488 		*/
18489 		type->contentTypeDef = baseType->contentTypeDef;
18490 		/*
18491 		* NOTE that the effective mixed is ignored here.
18492 		*/
18493 	    } else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18494 		/*
18495 		* SPEC (3.2.2)
18496 		*/
18497 		if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18498 		    type->contentType = XML_SCHEMA_CONTENT_MIXED;
18499 	    } else {
18500 		/*
18501 		* SPEC (3.2.3)
18502 		*/
18503 		if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18504 		    type->contentType = XML_SCHEMA_CONTENT_MIXED;
18505 		    /*
18506 		    * "A model group whose {compositor} is sequence and whose
18507 		    * {particles} are..."
18508 		    */
18509 		if ((WXS_TYPE_PARTICLE(type) != NULL) &&
18510 		    (WXS_TYPE_PARTICLE_TERM(type) != NULL) &&
18511 		    ((WXS_TYPE_PARTICLE_TERM(type))->type ==
18512 			XML_SCHEMA_TYPE_ALL))
18513 		{
18514 		    /*
18515 		    * SPEC cos-all-limited (1)
18516 		    */
18517 		    xmlSchemaCustomErr(ACTXT_CAST pctxt,
18518 			/* TODO: error code */
18519 			XML_SCHEMAP_COS_ALL_LIMITED,
18520 			WXS_ITEM_NODE(type), NULL,
18521 			"The type has an 'all' model group in its "
18522 			"{content type} and thus cannot be derived from "
18523 			"a non-empty type, since this would produce a "
18524 			"'sequence' model group containing the 'all' "
18525 			"model group; 'all' model groups are not "
18526 			"allowed to appear inside other model groups",
18527 			NULL, NULL);
18528 
18529 		} else if ((WXS_TYPE_PARTICLE(baseType) != NULL) &&
18530 		    (WXS_TYPE_PARTICLE_TERM(baseType) != NULL) &&
18531 		    ((WXS_TYPE_PARTICLE_TERM(baseType))->type ==
18532 			XML_SCHEMA_TYPE_ALL))
18533 		{
18534 		    /*
18535 		    * SPEC cos-all-limited (1)
18536 		    */
18537 		    xmlSchemaCustomErr(ACTXT_CAST pctxt,
18538 			/* TODO: error code */
18539 			XML_SCHEMAP_COS_ALL_LIMITED,
18540 			WXS_ITEM_NODE(type), NULL,
18541 			"A type cannot be derived by extension from a type "
18542 			"which has an 'all' model group in its "
18543 			"{content type}, since this would produce a "
18544 			"'sequence' model group containing the 'all' "
18545 			"model group; 'all' model groups are not "
18546 			"allowed to appear inside other model groups",
18547 			NULL, NULL);
18548 
18549 		} else if (! dummySequence) {
18550 		    xmlSchemaTreeItemPtr effectiveContent =
18551 			(xmlSchemaTreeItemPtr) type->subtypes;
18552 		    /*
18553 		    * Create the particle.
18554 		    */
18555 		    particle = xmlSchemaAddParticle(pctxt,
18556 			type->node, 1, 1);
18557 		    if (particle == NULL)
18558 			goto exit_failure;
18559 		    /*
18560 		    * Create the "sequence" model group.
18561 		    */
18562 		    particle->children = (xmlSchemaTreeItemPtr)
18563 			xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18564 			XML_SCHEMA_TYPE_SEQUENCE, type->node);
18565 		    if (particle->children == NULL)
18566 			goto exit_failure;
18567 		    WXS_TYPE_CONTENTTYPE(type) = (xmlSchemaTypePtr) particle;
18568 		    /*
18569 		    * SPEC "the particle of the {content type} of
18570 		    * the ... base ..."
18571 		    * Create a duplicate of the base type's particle
18572 		    * and assign its "term" to it.
18573 		    */
18574 		    particle->children->children =
18575 			(xmlSchemaTreeItemPtr) xmlSchemaAddParticle(pctxt,
18576 			type->node,
18577 			((xmlSchemaParticlePtr) baseType->subtypes)->minOccurs,
18578 			((xmlSchemaParticlePtr) baseType->subtypes)->maxOccurs);
18579 		    if (particle->children->children == NULL)
18580 			goto exit_failure;
18581 		    particle = (xmlSchemaParticlePtr)
18582 			particle->children->children;
18583 		    particle->children =
18584 			((xmlSchemaParticlePtr) baseType->subtypes)->children;
18585 		    /*
18586 		    * SPEC "followed by the `effective content`."
18587 		    */
18588 		    particle->next = effectiveContent;
18589 		    /*
18590 		    * This all will result in:
18591 		    * new-particle
18592 		    *   --> new-sequence(
18593 		    *         new-particle
18594 		    *           --> base-model,
18595 		    *         this-particle
18596 		    *	        --> this-model
18597 		    *	    )
18598 		    */
18599 		} else {
18600 		    /*
18601 		    * This is the case when there is already an empty
18602 		    * <sequence> with minOccurs==maxOccurs==1.
18603 		    * Just add the base types's content type.
18604 		    * NOTE that, although we miss to add an intermediate
18605 		    * <sequence>, this should produce no difference to
18606 		    * neither the regex compilation of the content model,
18607 		    * nor to the complex type contraints.
18608 		    */
18609 		    particle->children->children =
18610 			(xmlSchemaTreeItemPtr) baseType->subtypes;
18611 		}
18612 	    }
18613 	}
18614     }
18615     /*
18616     * Now fixup attribute uses:
18617     *   - expand attr. group references
18618     *     - intersect attribute wildcards
18619     *   - inherit attribute uses of the base type
18620     *   - inherit or union attr. wildcards if extending
18621     *   - apply attr. use prohibitions if restricting
18622     */
18623     res = xmlSchemaFixupTypeAttributeUses(pctxt, type);
18624     HFAILURE HERROR
18625     /*
18626     * Apply the complex type component constraints; this will not
18627     * check attributes, since this is done in
18628     * xmlSchemaFixupTypeAttributeUses().
18629     */
18630     res = xmlSchemaCheckCTComponent(pctxt, type);
18631     HFAILURE HERROR
18632 
18633 #ifdef DEBUG_TYPE
18634     xmlSchemaDebugFixedType(pctxt, type);
18635 #endif
18636     if (olderrs != pctxt->nberrors)
18637 	return(pctxt->err);
18638     else
18639 	return(0);
18640 
18641 exit_error:
18642     type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18643 #ifdef DEBUG_TYPE
18644     xmlSchemaDebugFixedType(pctxt, type);
18645 #endif
18646     return(pctxt->err);
18647 
18648 exit_failure:
18649     type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18650 #ifdef DEBUG_TYPE
18651     xmlSchemaDebugFixedType(pctxt, type);
18652 #endif
18653     return(-1);
18654 }
18655 
18656 
18657 /**
18658  * xmlSchemaTypeFixup:
18659  * @typeDecl:  the schema type definition
18660  * @ctxt:  the schema parser context
18661  *
18662  * Fixes the content model of the type.
18663  * URGENT TODO: We need an int result!
18664  */
18665 static int
xmlSchemaTypeFixup(xmlSchemaTypePtr type,xmlSchemaAbstractCtxtPtr actxt)18666 xmlSchemaTypeFixup(xmlSchemaTypePtr type,
18667                    xmlSchemaAbstractCtxtPtr actxt)
18668 {
18669     if (type == NULL)
18670         return(0);
18671     if (actxt->type != XML_SCHEMA_CTXT_PARSER) {
18672 	AERROR_INT("xmlSchemaTypeFixup",
18673 	    "this function needs a parser context");
18674 	return(-1);
18675     }
18676     if (! WXS_IS_TYPE_NOT_FIXED(type))
18677 	return(0);
18678     if (type->type == XML_SCHEMA_TYPE_COMPLEX)
18679 	return(xmlSchemaFixupComplexType(PCTXT_CAST actxt, type));
18680     else if (type->type == XML_SCHEMA_TYPE_SIMPLE)
18681 	return(xmlSchemaFixupSimpleTypeStageTwo(PCTXT_CAST actxt, type));
18682     return(0);
18683 }
18684 
18685 /**
18686  * xmlSchemaCheckFacet:
18687  * @facet:  the facet
18688  * @typeDecl:  the schema type definition
18689  * @pctxt:  the schema parser context or NULL
18690  * @name: the optional name of the type
18691  *
18692  * Checks and computes the values of facets.
18693  *
18694  * Returns 0 if valid, a positive error code if not valid and
18695  *         -1 in case of an internal or API error.
18696  */
18697 int
xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,xmlSchemaTypePtr typeDecl,xmlSchemaParserCtxtPtr pctxt,const xmlChar * name ATTRIBUTE_UNUSED)18698 xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
18699                     xmlSchemaTypePtr typeDecl,
18700                     xmlSchemaParserCtxtPtr pctxt,
18701 		    const xmlChar * name ATTRIBUTE_UNUSED)
18702 {
18703     int ret = 0, ctxtGiven;
18704 
18705     if ((facet == NULL) || (typeDecl == NULL))
18706         return(-1);
18707     /*
18708     * TODO: will the parser context be given if used from
18709     * the relaxNG module?
18710     */
18711     if (pctxt == NULL)
18712 	ctxtGiven = 0;
18713     else
18714 	ctxtGiven = 1;
18715 
18716     switch (facet->type) {
18717         case XML_SCHEMA_FACET_MININCLUSIVE:
18718         case XML_SCHEMA_FACET_MINEXCLUSIVE:
18719         case XML_SCHEMA_FACET_MAXINCLUSIVE:
18720         case XML_SCHEMA_FACET_MAXEXCLUSIVE:
18721 	case XML_SCHEMA_FACET_ENUMERATION: {
18722                 /*
18723                  * Okay we need to validate the value
18724                  * at that point.
18725                  */
18726 		xmlSchemaTypePtr base;
18727 
18728 		/* 4.3.5.5 Constraints on enumeration Schema Components
18729 		* Schema Component Constraint: enumeration valid restriction
18730 		* It is an `error` if any member of {value} is not in the
18731 		* `value space` of {base type definition}.
18732 		*
18733 		* minInclusive, maxInclusive, minExclusive, maxExclusive:
18734 		* The value `must` be in the
18735 		* `value space` of the `base type`.
18736 		*/
18737 		/*
18738 		* This function is intended to deliver a compiled value
18739 		* on the facet. In this implementation of XML Schemata the
18740 		* type holding a facet, won't be a built-in type.
18741 		* Thus to ensure that other API
18742 		* calls (relaxng) do work, if the given type is a built-in
18743 		* type, we will assume that the given built-in type *is
18744 		* already* the base type.
18745 		*/
18746 		if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
18747 		    base = typeDecl->baseType;
18748 		    if (base == NULL) {
18749 			PERROR_INT("xmlSchemaCheckFacet",
18750 			    "a type user derived type has no base type");
18751 			return (-1);
18752 		    }
18753 		} else
18754 		    base = typeDecl;
18755 
18756 		if (! ctxtGiven) {
18757 		    /*
18758 		    * A context is needed if called from RelaxNG.
18759 		    */
18760 		    pctxt = xmlSchemaNewParserCtxt("*");
18761 		    if (pctxt == NULL)
18762 			return (-1);
18763 		}
18764 		/*
18765 		* NOTE: This call does not check the content nodes,
18766 		* since they are not available:
18767 		* facet->node is just the node holding the facet
18768 		* definition, *not* the attribute holding the *value*
18769 		* of the facet.
18770 		*/
18771 		ret = xmlSchemaVCheckCVCSimpleType(
18772 		    ACTXT_CAST pctxt, facet->node, base,
18773 		    facet->value, &(facet->val), 1, 1, 0);
18774                 if (ret != 0) {
18775 		    if (ret < 0) {
18776 			/* No error message for RelaxNG. */
18777 			if (ctxtGiven) {
18778 			    xmlSchemaCustomErr(ACTXT_CAST pctxt,
18779 				XML_SCHEMAP_INTERNAL, facet->node, NULL,
18780 				"Internal error: xmlSchemaCheckFacet, "
18781 				"failed to validate the value '%s' of the "
18782 				"facet '%s' against the base type",
18783 				facet->value, xmlSchemaFacetTypeToString(facet->type));
18784 			}
18785 			goto internal_error;
18786 		    }
18787 		    ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18788 		    /* No error message for RelaxNG. */
18789 		    if (ctxtGiven) {
18790 			xmlChar *str = NULL;
18791 
18792 			xmlSchemaCustomErr(ACTXT_CAST pctxt,
18793 			    ret, facet->node, WXS_BASIC_CAST facet,
18794 			    "The value '%s' of the facet does not validate "
18795 			    "against the base type '%s'",
18796 			    facet->value,
18797 			    xmlSchemaFormatQName(&str,
18798 				base->targetNamespace, base->name));
18799 			FREE_AND_NULL(str);
18800 		    }
18801 		    goto exit;
18802                 } else if (facet->val == NULL) {
18803 		    if (ctxtGiven) {
18804 			PERROR_INT("xmlSchemaCheckFacet",
18805 			    "value was not computed");
18806 		    }
18807 		    TODO
18808 		}
18809                 break;
18810             }
18811         case XML_SCHEMA_FACET_PATTERN:
18812             facet->regexp = xmlRegexpCompile(facet->value);
18813             if (facet->regexp == NULL) {
18814 		ret = XML_SCHEMAP_REGEXP_INVALID;
18815 		/* No error message for RelaxNG. */
18816 		if (ctxtGiven) {
18817 		    xmlSchemaCustomErr(ACTXT_CAST pctxt,
18818 			ret, facet->node, WXS_BASIC_CAST typeDecl,
18819 			"The value '%s' of the facet 'pattern' is not a "
18820 			"valid regular expression",
18821 			facet->value, NULL);
18822 		}
18823             }
18824             break;
18825         case XML_SCHEMA_FACET_TOTALDIGITS:
18826         case XML_SCHEMA_FACET_FRACTIONDIGITS:
18827         case XML_SCHEMA_FACET_LENGTH:
18828         case XML_SCHEMA_FACET_MAXLENGTH:
18829         case XML_SCHEMA_FACET_MINLENGTH:
18830 
18831 	    if (facet->type == XML_SCHEMA_FACET_TOTALDIGITS) {
18832 		ret = xmlSchemaValidatePredefinedType(
18833 		    xmlSchemaGetBuiltInType(XML_SCHEMAS_PINTEGER),
18834 		    facet->value, &(facet->val));
18835 	    } else {
18836 		ret = xmlSchemaValidatePredefinedType(
18837 		    xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER),
18838 		    facet->value, &(facet->val));
18839 	    }
18840 	    if (ret != 0) {
18841 		if (ret < 0) {
18842 		    /* No error message for RelaxNG. */
18843 		    if (ctxtGiven) {
18844 			PERROR_INT("xmlSchemaCheckFacet",
18845 			    "validating facet value");
18846 		    }
18847 		    goto internal_error;
18848 		}
18849 		ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18850 		/* No error message for RelaxNG. */
18851 		if (ctxtGiven) {
18852 		    /* error code */
18853 		    xmlSchemaCustomErr4(ACTXT_CAST pctxt,
18854 			ret, facet->node, WXS_BASIC_CAST typeDecl,
18855 			"The value '%s' of the facet '%s' is not a valid '%s'",
18856 			facet->value,
18857 			xmlSchemaFacetTypeToString(facet->type),
18858 			(facet->type != XML_SCHEMA_FACET_TOTALDIGITS) ?
18859 			    BAD_CAST "nonNegativeInteger" :
18860 			    BAD_CAST "positiveInteger",
18861 			NULL);
18862 		}
18863 	    }
18864 	    break;
18865 
18866         case XML_SCHEMA_FACET_WHITESPACE:{
18867                 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
18868                     facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
18869                 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
18870                     facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
18871                 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
18872                     facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
18873                 } else {
18874 		    ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18875                     /* No error message for RelaxNG. */
18876 		    if (ctxtGiven) {
18877 			/* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */
18878 			xmlSchemaCustomErr(ACTXT_CAST pctxt,
18879 			    ret, facet->node, WXS_BASIC_CAST typeDecl,
18880 			    "The value '%s' of the facet 'whitespace' is not "
18881 			    "valid", facet->value, NULL);
18882                     }
18883                 }
18884             }
18885         default:
18886             break;
18887     }
18888 exit:
18889     if ((! ctxtGiven) && (pctxt != NULL))
18890 	xmlSchemaFreeParserCtxt(pctxt);
18891     return (ret);
18892 internal_error:
18893     if ((! ctxtGiven) && (pctxt != NULL))
18894 	xmlSchemaFreeParserCtxt(pctxt);
18895     return (-1);
18896 }
18897 
18898 /**
18899  * xmlSchemaCheckFacetValues:
18900  * @typeDecl:  the schema type definition
18901  * @ctxt:  the schema parser context
18902  *
18903  * Checks the default values types, especially for facets
18904  */
18905 static int
xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,xmlSchemaParserCtxtPtr pctxt)18906 xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
18907 			  xmlSchemaParserCtxtPtr pctxt)
18908 {
18909     int res, olderrs = pctxt->nberrors;
18910     const xmlChar *name = typeDecl->name;
18911     /*
18912     * NOTE: It is intended to use the facets list, instead
18913     * of facetSet.
18914     */
18915     if (typeDecl->facets != NULL) {
18916 	xmlSchemaFacetPtr facet = typeDecl->facets;
18917 
18918 	/*
18919 	* Temporarily assign the "schema" to the validation context
18920 	* of the parser context. This is needed for NOTATION validation.
18921 	*/
18922 	if (pctxt->vctxt == NULL) {
18923 	    if (xmlSchemaCreateVCtxtOnPCtxt(pctxt) == -1)
18924 		return(-1);
18925 	}
18926 	pctxt->vctxt->schema = pctxt->schema;
18927 	while (facet != NULL) {
18928 	    res = xmlSchemaCheckFacet(facet, typeDecl, pctxt, name);
18929 	    HFAILURE
18930 	    facet = facet->next;
18931 	}
18932 	pctxt->vctxt->schema = NULL;
18933     }
18934     if (olderrs != pctxt->nberrors)
18935 	return(pctxt->err);
18936     return(0);
18937 exit_failure:
18938     return(-1);
18939 }
18940 
18941 /**
18942  * xmlSchemaGetCircModelGrDefRef:
18943  * @ctxtMGroup: the searched model group
18944  * @selfMGroup: the second searched model group
18945  * @particle: the first particle
18946  *
18947  * This one is intended to be used by
18948  * xmlSchemaCheckGroupDefCircular only.
18949  *
18950  * Returns the particle with the circular model group definition reference,
18951  * otherwise NULL.
18952  */
18953 static xmlSchemaTreeItemPtr
xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,xmlSchemaTreeItemPtr particle)18954 xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,
18955 			      xmlSchemaTreeItemPtr particle)
18956 {
18957     xmlSchemaTreeItemPtr circ = NULL;
18958     xmlSchemaTreeItemPtr term;
18959     xmlSchemaModelGroupDefPtr gdef;
18960 
18961     for (; particle != NULL; particle = particle->next) {
18962 	term = particle->children;
18963 	if (term == NULL)
18964 	    continue;
18965 	switch (term->type) {
18966 	    case XML_SCHEMA_TYPE_GROUP:
18967 		gdef = (xmlSchemaModelGroupDefPtr) term;
18968 		if (gdef == groupDef)
18969 		    return (particle);
18970 		/*
18971 		* Mark this model group definition to avoid infinite
18972 		* recursion on circular references not yet examined.
18973 		*/
18974 		if (gdef->flags & XML_SCHEMA_MODEL_GROUP_DEF_MARKED)
18975 		    continue;
18976 		if (gdef->children != NULL) {
18977 		    gdef->flags |= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18978 		    circ = xmlSchemaGetCircModelGrDefRef(groupDef,
18979 			gdef->children->children);
18980 		    gdef->flags ^= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18981 		    if (circ != NULL)
18982 			return (circ);
18983 		}
18984 		break;
18985 	    case XML_SCHEMA_TYPE_SEQUENCE:
18986 	    case XML_SCHEMA_TYPE_CHOICE:
18987 	    case XML_SCHEMA_TYPE_ALL:
18988 		circ = xmlSchemaGetCircModelGrDefRef(groupDef, term->children);
18989 		if (circ != NULL)
18990 		    return (circ);
18991 		break;
18992 	    default:
18993 		break;
18994 	}
18995     }
18996     return (NULL);
18997 }
18998 
18999 /**
19000  * xmlSchemaCheckGroupDefCircular:
19001  * @item:  the model group definition
19002  * @ctxt:  the parser context
19003  * @name:  the name
19004  *
19005  * Checks for circular references to model group definitions.
19006  */
19007 static void
xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,xmlSchemaParserCtxtPtr ctxt)19008 xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,
19009 			       xmlSchemaParserCtxtPtr ctxt)
19010 {
19011     /*
19012     * Schema Component Constraint: Model Group Correct
19013     * 2 Circular groups are disallowed. That is, within the {particles}
19014     * of a group there must not be at any depth a particle whose {term}
19015     * is the group itself.
19016     */
19017     if ((item == NULL) ||
19018 	(item->type != XML_SCHEMA_TYPE_GROUP) ||
19019 	(item->children == NULL))
19020 	return;
19021     {
19022 	xmlSchemaTreeItemPtr circ;
19023 
19024 	circ = xmlSchemaGetCircModelGrDefRef(item, item->children->children);
19025 	if (circ != NULL) {
19026 	    xmlChar *str = NULL;
19027 	    /*
19028 	    * TODO: The error report is not adequate: this constraint
19029 	    * is defined for model groups but not definitions, but since
19030 	    * there cannot be any circular model groups without a model group
19031 	    * definition (if not using a construction API), we check those
19032 	    * defintions only.
19033 	    */
19034 	    xmlSchemaPCustomErr(ctxt,
19035 		XML_SCHEMAP_MG_PROPS_CORRECT_2,
19036 		NULL, WXS_ITEM_NODE(circ),
19037 		"Circular reference to the model group definition '%s' "
19038 		"defined", xmlSchemaFormatQName(&str,
19039 		    item->targetNamespace, item->name));
19040 	    FREE_AND_NULL(str)
19041 	    /*
19042 	    * NOTE: We will cut the reference to avoid further
19043 	    * confusion of the processor. This is a fatal error.
19044 	    */
19045 	    circ->children = NULL;
19046 	}
19047     }
19048 }
19049 
19050 /**
19051  * xmlSchemaModelGroupToModelGroupDefFixup:
19052  * @ctxt:  the parser context
19053  * @mg:  the model group
19054  *
19055  * Assigns the model group of model group definitions to the "term"
19056  * of the referencing particle.
19057  * In xmlSchemaResolveModelGroupParticleReferences the model group
19058  * definitions were assigned to the "term", since needed for the
19059  * circularity check.
19060  *
19061  * Schema Component Constraint:
19062  *     All Group Limited (cos-all-limited) (1.2)
19063  */
19064 static void
xmlSchemaModelGroupToModelGroupDefFixup(xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,xmlSchemaModelGroupPtr mg)19065 xmlSchemaModelGroupToModelGroupDefFixup(
19066     xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
19067     xmlSchemaModelGroupPtr mg)
19068 {
19069     xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
19070 
19071     while (particle != NULL) {
19072 	if ((WXS_PARTICLE_TERM(particle) == NULL) ||
19073 	    ((WXS_PARTICLE_TERM(particle))->type !=
19074 		XML_SCHEMA_TYPE_GROUP))
19075 	{
19076 	    particle = WXS_PTC_CAST particle->next;
19077 	    continue;
19078 	}
19079 	if (WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle)) == NULL) {
19080 	    /*
19081 	    * TODO: Remove the particle.
19082 	    */
19083 	    WXS_PARTICLE_TERM(particle) = NULL;
19084 	    particle = WXS_PTC_CAST particle->next;
19085 	    continue;
19086 	}
19087 	/*
19088 	* Assign the model group to the {term} of the particle.
19089 	*/
19090 	WXS_PARTICLE_TERM(particle) =
19091 	    WXS_TREE_CAST WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle));
19092 
19093 	particle = WXS_PTC_CAST particle->next;
19094     }
19095 }
19096 
19097 /**
19098  * xmlSchemaCheckAttrGroupCircularRecur:
19099  * @ctxtGr: the searched attribute group
19100  * @attr: the current attribute list to be processed
19101  *
19102  * This one is intended to be used by
19103  * xmlSchemaCheckAttrGroupCircular only.
19104  *
19105  * Returns the circular attribute grou reference, otherwise NULL.
19106  */
19107 static xmlSchemaQNameRefPtr
xmlSchemaCheckAttrGroupCircularRecur(xmlSchemaAttributeGroupPtr ctxtGr,xmlSchemaItemListPtr list)19108 xmlSchemaCheckAttrGroupCircularRecur(xmlSchemaAttributeGroupPtr ctxtGr,
19109 				     xmlSchemaItemListPtr list)
19110 {
19111     xmlSchemaAttributeGroupPtr gr;
19112     xmlSchemaQNameRefPtr ref, circ;
19113     int i;
19114     /*
19115     * We will search for an attribute group reference which
19116     * references the context attribute group.
19117     */
19118     for (i = 0; i < list->nbItems; i++) {
19119 	ref = list->items[i];
19120 	if ((ref->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
19121 	    (ref->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
19122 	    (ref->item != NULL))
19123 	{
19124 	    gr = WXS_ATTR_GROUP_CAST ref->item;
19125 	    if (gr == ctxtGr)
19126 		return(ref);
19127 	    if (gr->flags & XML_SCHEMAS_ATTRGROUP_MARKED)
19128 		continue;
19129 	    /*
19130 	    * Mark as visited to avoid infinite recursion on
19131 	    * circular references not yet examined.
19132 	    */
19133 	    if ((gr->attrUses) &&
19134 		(gr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS))
19135 	    {
19136 		gr->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
19137 		circ = xmlSchemaCheckAttrGroupCircularRecur(ctxtGr,
19138 		    (xmlSchemaItemListPtr) gr->attrUses);
19139 		gr->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
19140 		if (circ != NULL)
19141 		    return (circ);
19142 	    }
19143 
19144 	}
19145     }
19146     return (NULL);
19147 }
19148 
19149 /**
19150  * xmlSchemaCheckAttrGroupCircular:
19151  * attrGr:  the attribute group definition
19152  * @ctxt:  the parser context
19153  * @name:  the name
19154  *
19155  * Checks for circular references of attribute groups.
19156  */
19157 static int
xmlSchemaCheckAttrGroupCircular(xmlSchemaAttributeGroupPtr attrGr,xmlSchemaParserCtxtPtr ctxt)19158 xmlSchemaCheckAttrGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
19159 				xmlSchemaParserCtxtPtr ctxt)
19160 {
19161     /*
19162     * Schema Representation Constraint:
19163     * Attribute Group Definition Representation OK
19164     * 3 Circular group reference is disallowed outside <redefine>.
19165     * That is, unless this element information item's parent is
19166     * <redefine>, then among the [children], if any, there must
19167     * not be an <attributeGroup> with ref [attribute] which resolves
19168     * to the component corresponding to this <attributeGroup>. Indirect
19169     * circularity is also ruled out. That is, when QName resolution
19170     * (Schema Document) ($3.15.3) is applied to a `QName` arising from
19171     * any <attributeGroup>s with a ref [attribute] among the [children],
19172     * it must not be the case that a `QName` is encountered at any depth
19173     * which resolves to the component corresponding to this <attributeGroup>.
19174     */
19175     if (attrGr->attrUses == NULL)
19176 	return(0);
19177     else if ((attrGr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS) == 0)
19178 	return(0);
19179     else {
19180 	xmlSchemaQNameRefPtr circ;
19181 
19182 	circ = xmlSchemaCheckAttrGroupCircularRecur(attrGr,
19183 	    (xmlSchemaItemListPtr) attrGr->attrUses);
19184 	if (circ != NULL) {
19185 	    xmlChar *str = NULL;
19186 	    /*
19187 	    * TODO: Report the referenced attr group as QName.
19188 	    */
19189 	    xmlSchemaPCustomErr(ctxt,
19190 		XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
19191 		NULL, WXS_ITEM_NODE(WXS_BASIC_CAST circ),
19192 		"Circular reference to the attribute group '%s' "
19193 		"defined", xmlSchemaGetComponentQName(&str, attrGr));
19194 	    FREE_AND_NULL(str);
19195 	    /*
19196 	    * NOTE: We will cut the reference to avoid further
19197 	    * confusion of the processor.
19198 	    * BADSPEC TODO: The spec should define how to process in this case.
19199 	    */
19200 	    circ->item = NULL;
19201 	    return(ctxt->err);
19202 	}
19203     }
19204     return(0);
19205 }
19206 
19207 static int
19208 xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19209 				  xmlSchemaAttributeGroupPtr attrGr);
19210 
19211 /**
19212  * xmlSchemaExpandAttributeGroupRefs:
19213  * @pctxt: the parser context
19214  * @node: the node of the component holding the attribute uses
19215  * @completeWild: the intersected wildcard to be returned
19216  * @list: the attribute uses
19217  *
19218  * Substitutes contained attribute group references
19219  * for their attribute uses. Wilcards are intersected.
19220  * Attribute use prohibitions are removed from the list
19221  * and returned via the @prohibs list.
19222  * Pointlessness of attr. prohibs, if a matching attr. decl
19223  * is existent a well, are checked.
19224  */
19225 static int
xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,xmlSchemaBasicItemPtr item,xmlSchemaWildcardPtr * completeWild,xmlSchemaItemListPtr list,xmlSchemaItemListPtr prohibs)19226 xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
19227 				  xmlSchemaBasicItemPtr item,
19228 				  xmlSchemaWildcardPtr *completeWild,
19229 				  xmlSchemaItemListPtr list,
19230 				  xmlSchemaItemListPtr prohibs)
19231 {
19232     xmlSchemaAttributeGroupPtr gr;
19233     xmlSchemaAttributeUsePtr use;
19234     xmlSchemaItemListPtr sublist;
19235     int i, j;
19236     int created = (*completeWild == NULL) ? 0 : 1;
19237 
19238     if (prohibs)
19239 	prohibs->nbItems = 0;
19240 
19241     for (i = 0; i < list->nbItems; i++) {
19242 	use = list->items[i];
19243 
19244 	if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
19245 	    if (prohibs == NULL) {
19246 		PERROR_INT("xmlSchemaExpandAttributeGroupRefs",
19247 		    "unexpected attr prohibition found");
19248 		return(-1);
19249 	    }
19250 	    /*
19251 	    * Remove from attribute uses.
19252 	    */
19253 	    if (xmlSchemaItemListRemove(list, i) == -1)
19254 		return(-1);
19255 	    i--;
19256 	    /*
19257 	    * Note that duplicate prohibitions were already
19258 	    * handled at parsing time.
19259 	    */
19260 	    /*
19261 	    * Add to list of prohibitions.
19262 	    */
19263 	    xmlSchemaItemListAddSize(prohibs, 2, use);
19264 	    continue;
19265 	}
19266 	if ((use->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
19267 	    ((WXS_QNAME_CAST use)->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP))
19268 	{
19269 	    if ((WXS_QNAME_CAST use)->item == NULL)
19270 		return(-1);
19271 	    gr = WXS_ATTR_GROUP_CAST (WXS_QNAME_CAST use)->item;
19272 	    /*
19273 	    * Expand the referenced attr. group.
19274 	    * TODO: remove this, this is done in a previous step, so
19275 	    * already done here.
19276 	    */
19277 	    if ((gr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
19278 		if (xmlSchemaAttributeGroupExpandRefs(pctxt, gr) == -1)
19279 		    return(-1);
19280 	    }
19281 	    /*
19282 	    * Build the 'complete' wildcard; i.e. intersect multiple
19283 	    * wildcards.
19284 	    */
19285 	    if (gr->attributeWildcard != NULL) {
19286 		if (*completeWild == NULL) {
19287 		    *completeWild = gr->attributeWildcard;
19288 		} else {
19289 		    if (! created) {
19290 			xmlSchemaWildcardPtr tmpWild;
19291 
19292 			 /*
19293 			* Copy the first encountered wildcard as context,
19294 			* except for the annotation.
19295 			*
19296 			* Although the complete wildcard might not correspond
19297 			* to any node in the schema, we will anchor it on
19298 			* the node of the owner component.
19299 			*/
19300 			tmpWild =  xmlSchemaAddWildcard(pctxt, pctxt->schema,
19301 			    XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
19302 			    WXS_ITEM_NODE(item));
19303 			if (tmpWild == NULL)
19304 			    return(-1);
19305 			if (xmlSchemaCloneWildcardNsConstraints(pctxt,
19306 			    tmpWild, *completeWild) == -1)
19307 			    return (-1);
19308 			tmpWild->processContents = (*completeWild)->processContents;
19309 			*completeWild = tmpWild;
19310 			created = 1;
19311 		    }
19312 
19313 		    if (xmlSchemaIntersectWildcards(pctxt, *completeWild,
19314 			gr->attributeWildcard) == -1)
19315 			return(-1);
19316 		}
19317 	    }
19318 	    /*
19319 	    * Just remove the reference if the referenced group does not
19320 	    * contain any attribute uses.
19321 	    */
19322 	    sublist = ((xmlSchemaItemListPtr) gr->attrUses);
19323 	    if ((sublist == NULL) || sublist->nbItems == 0) {
19324 		if (xmlSchemaItemListRemove(list, i) == -1)
19325 		    return(-1);
19326 		i--;
19327 		continue;
19328 	    }
19329 	    /*
19330 	    * Add the attribute uses.
19331 	    */
19332 	    list->items[i] = sublist->items[0];
19333 	    if (sublist->nbItems != 1) {
19334 		for (j = 1; j < sublist->nbItems; j++) {
19335 		    i++;
19336 		    if (xmlSchemaItemListInsert(list,
19337 			    sublist->items[j], i) == -1)
19338 			return(-1);
19339 		}
19340 	    }
19341 	}
19342 
19343     }
19344     /*
19345     * Handle pointless prohibitions of declared attributes.
19346     */
19347     if (prohibs && (prohibs->nbItems != 0) && (list->nbItems != 0)) {
19348 	xmlSchemaAttributeUseProhibPtr prohib;
19349 
19350 	for (i = prohibs->nbItems -1; i >= 0; i--) {
19351 	    prohib = prohibs->items[i];
19352 	    for (j = 0; j < list->nbItems; j++) {
19353 		use = list->items[j];
19354 
19355 		if ((prohib->name == WXS_ATTRUSE_DECL_NAME(use)) &&
19356 		    (prohib->targetNamespace == WXS_ATTRUSE_DECL_TNS(use)))
19357 		{
19358 		    xmlChar *str = NULL;
19359 
19360 		    xmlSchemaCustomWarning(ACTXT_CAST pctxt,
19361 			XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
19362 			prohib->node, NULL,
19363 			"Skipping pointless attribute use prohibition "
19364 			"'%s', since a corresponding attribute use "
19365 			"exists already in the type definition",
19366 			xmlSchemaFormatQName(&str,
19367 			    prohib->targetNamespace, prohib->name),
19368 			NULL, NULL);
19369 		    FREE_AND_NULL(str);
19370 		    /*
19371 		    * Remove the prohibition.
19372 		    */
19373 		    if (xmlSchemaItemListRemove(prohibs, i) == -1)
19374 			return(-1);
19375 		    break;
19376 		}
19377 	    }
19378 	}
19379     }
19380     return(0);
19381 }
19382 
19383 /**
19384  * xmlSchemaAttributeGroupExpandRefs:
19385  * @pctxt:  the parser context
19386  * @attrGr:  the attribute group definition
19387  *
19388  * Computation of:
19389  * {attribute uses} property
19390  * {attribute wildcard} property
19391  *
19392  * Substitutes contained attribute group references
19393  * for their attribute uses. Wilcards are intersected.
19394  */
19395 static int
xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,xmlSchemaAttributeGroupPtr attrGr)19396 xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19397 				  xmlSchemaAttributeGroupPtr attrGr)
19398 {
19399     if ((attrGr->attrUses == NULL) ||
19400 	(attrGr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED))
19401 	return(0);
19402 
19403     attrGr->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
19404     if (xmlSchemaExpandAttributeGroupRefs(pctxt, WXS_BASIC_CAST attrGr,
19405 	&(attrGr->attributeWildcard), attrGr->attrUses, NULL) == -1)
19406 	return(-1);
19407     return(0);
19408 }
19409 
19410 /**
19411  * xmlSchemaAttributeGroupExpandRefs:
19412  * @pctxt:  the parser context
19413  * @attrGr:  the attribute group definition
19414  *
19415  * Substitutes contained attribute group references
19416  * for their attribute uses. Wilcards are intersected.
19417  *
19418  * Schema Component Constraint:
19419  *    Attribute Group Definition Properties Correct (ag-props-correct)
19420  */
19421 static int
xmlSchemaCheckAGPropsCorrect(xmlSchemaParserCtxtPtr pctxt,xmlSchemaAttributeGroupPtr attrGr)19422 xmlSchemaCheckAGPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19423 				  xmlSchemaAttributeGroupPtr attrGr)
19424 {
19425     /*
19426     * SPEC ag-props-correct
19427     * (1) "The values of the properties of an attribute group definition
19428     * must be as described in the property tableau in The Attribute
19429     * Group Definition Schema Component ($3.6.1), modulo the impact of
19430     * Missing Sub-components ($5.3);"
19431     */
19432 
19433     if ((attrGr->attrUses != NULL) &&
19434 	(WXS_LIST_CAST attrGr->attrUses)->nbItems > 1)
19435     {
19436 	xmlSchemaItemListPtr uses = WXS_LIST_CAST attrGr->attrUses;
19437 	xmlSchemaAttributeUsePtr use, tmp;
19438 	int i, j, hasId = 0;
19439 
19440 	for (i = uses->nbItems -1; i >= 0; i--) {
19441 	    use = uses->items[i];
19442 	    /*
19443 	    * SPEC ag-props-correct
19444 	    * (2) "Two distinct members of the {attribute uses} must not have
19445 	    * {attribute declaration}s both of whose {name}s match and whose
19446 	    * {target namespace}s are identical."
19447 	    */
19448 	    if (i > 0) {
19449 		for (j = i -1; j >= 0; j--) {
19450 		    tmp = uses->items[j];
19451 		    if ((WXS_ATTRUSE_DECL_NAME(use) ==
19452 			WXS_ATTRUSE_DECL_NAME(tmp)) &&
19453 			(WXS_ATTRUSE_DECL_TNS(use) ==
19454 			WXS_ATTRUSE_DECL_TNS(tmp)))
19455 		    {
19456 			xmlChar *str = NULL;
19457 
19458 			xmlSchemaCustomErr(ACTXT_CAST pctxt,
19459 			    XML_SCHEMAP_AG_PROPS_CORRECT,
19460 			    attrGr->node, WXS_BASIC_CAST attrGr,
19461 			    "Duplicate %s",
19462 			    xmlSchemaGetComponentDesignation(&str, use),
19463 			    NULL);
19464 			FREE_AND_NULL(str);
19465 			/*
19466 			* Remove the duplicate.
19467 			*/
19468 			if (xmlSchemaItemListRemove(uses, i) == -1)
19469 			    return(-1);
19470 			goto next_use;
19471 		    }
19472 		}
19473 	    }
19474 	    /*
19475 	    * SPEC ag-props-correct
19476 	    * (3) "Two distinct members of the {attribute uses} must not have
19477 	    * {attribute declaration}s both of whose {type definition}s are or
19478 	    * are derived from ID."
19479 	    * TODO: Does 'derived' include member-types of unions?
19480 	    */
19481 	    if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
19482 		if (xmlSchemaIsDerivedFromBuiltInType(
19483 		    WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
19484 		{
19485 		    if (hasId) {
19486 			xmlChar *str = NULL;
19487 
19488 			xmlSchemaCustomErr(ACTXT_CAST pctxt,
19489 			    XML_SCHEMAP_AG_PROPS_CORRECT,
19490 			    attrGr->node, WXS_BASIC_CAST attrGr,
19491 			    "There must not exist more than one attribute "
19492 			    "declaration of type 'xs:ID' "
19493 			    "(or derived from 'xs:ID'). The %s violates this "
19494 			    "constraint",
19495 			    xmlSchemaGetComponentDesignation(&str, use),
19496 			    NULL);
19497 			FREE_AND_NULL(str);
19498 			if (xmlSchemaItemListRemove(uses, i) == -1)
19499 			    return(-1);
19500 		    }
19501 		    hasId = 1;
19502 		}
19503 	    }
19504 next_use: {}
19505 	}
19506     }
19507     return(0);
19508 }
19509 
19510 /**
19511  * xmlSchemaResolveAttrGroupReferences:
19512  * @attrgrpDecl:  the schema attribute definition
19513  * @ctxt:  the schema parser context
19514  * @name:  the attribute name
19515  *
19516  * Resolves references to attribute group definitions.
19517  */
19518 static int
xmlSchemaResolveAttrGroupReferences(xmlSchemaQNameRefPtr ref,xmlSchemaParserCtxtPtr ctxt)19519 xmlSchemaResolveAttrGroupReferences(xmlSchemaQNameRefPtr ref,
19520 				    xmlSchemaParserCtxtPtr ctxt)
19521 {
19522     xmlSchemaAttributeGroupPtr group;
19523 
19524     if (ref->item != NULL)
19525         return(0);
19526     group = xmlSchemaGetAttributeGroup(ctxt->schema,
19527 	ref->name,
19528 	ref->targetNamespace);
19529     if (group == NULL) {
19530 	xmlSchemaPResCompAttrErr(ctxt,
19531 	    XML_SCHEMAP_SRC_RESOLVE,
19532 	    NULL, ref->node,
19533 	    "ref", ref->name, ref->targetNamespace,
19534 	    ref->itemType, NULL);
19535 	return(ctxt->err);
19536     }
19537     ref->item = WXS_BASIC_CAST group;
19538     return(0);
19539 }
19540 
19541 /**
19542  * xmlSchemaCheckAttrPropsCorrect:
19543  * @item:  an schema attribute declaration/use
19544  * @ctxt:  a schema parser context
19545  * @name:  the name of the attribute
19546  *
19547  *
19548  * Schema Component Constraint:
19549  *    Attribute Declaration Properties Correct (a-props-correct)
19550  *
19551  * Validates the value constraints of an attribute declaration/use.
19552  * NOTE that this needs the simle type definitions to be already
19553  *   builded and checked.
19554  */
19555 static int
xmlSchemaCheckAttrPropsCorrect(xmlSchemaParserCtxtPtr pctxt,xmlSchemaAttributePtr attr)19556 xmlSchemaCheckAttrPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19557 			       xmlSchemaAttributePtr attr)
19558 {
19559 
19560     /*
19561     * SPEC a-props-correct (1)
19562     * "The values of the properties of an attribute declaration must
19563     * be as described in the property tableau in The Attribute
19564     * Declaration Schema Component ($3.2.1), modulo the impact of
19565     * Missing Sub-components ($5.3)."
19566     */
19567 
19568     if (WXS_ATTR_TYPEDEF(attr) == NULL)
19569 	return(0);
19570 
19571     if (attr->defValue != NULL) {
19572 	int ret;
19573 
19574 	/*
19575 	* SPEC a-props-correct (3)
19576 	* "If the {type definition} is or is derived from ID then there
19577 	* must not be a {value constraint}."
19578 	*/
19579 	if (xmlSchemaIsDerivedFromBuiltInType(
19580 	    WXS_ATTR_TYPEDEF(attr), XML_SCHEMAS_ID))
19581 	{
19582 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
19583 		XML_SCHEMAP_A_PROPS_CORRECT_3,
19584 		NULL, WXS_BASIC_CAST attr,
19585 		"Value constraints are not allowed if the type definition "
19586 		"is or is derived from xs:ID",
19587 		NULL, NULL);
19588 	    return(pctxt->err);
19589 	}
19590 	/*
19591 	* SPEC a-props-correct (2)
19592 	* "if there is a {value constraint}, the canonical lexical
19593 	* representation of its value must be `valid` with respect
19594 	* to the {type definition} as defined in String Valid ($3.14.4)."
19595 	* TODO: Don't care about the *canonical* stuff here, this requirement
19596 	* will be removed in WXS 1.1 anyway.
19597 	*/
19598 	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt,
19599 	    attr->node, WXS_ATTR_TYPEDEF(attr),
19600 	    attr->defValue, &(attr->defVal),
19601 	    1, 1, 0);
19602 	if (ret != 0) {
19603 	    if (ret < 0) {
19604 		PERROR_INT("xmlSchemaCheckAttrPropsCorrect",
19605 		    "calling xmlSchemaVCheckCVCSimpleType()");
19606 		return(-1);
19607 	    }
19608 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
19609 		XML_SCHEMAP_A_PROPS_CORRECT_2,
19610 		NULL, WXS_BASIC_CAST attr,
19611 		"The value of the value constraint is not valid",
19612 		NULL, NULL);
19613 	    return(pctxt->err);
19614 	}
19615     }
19616 
19617     return(0);
19618 }
19619 
19620 static xmlSchemaElementPtr
xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,xmlSchemaElementPtr ancestor)19621 xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,
19622 				 xmlSchemaElementPtr ancestor)
19623 {
19624     xmlSchemaElementPtr ret;
19625 
19626     if (WXS_SUBST_HEAD(ancestor) == NULL)
19627 	return (NULL);
19628     if (WXS_SUBST_HEAD(ancestor) == elemDecl)
19629 	return (ancestor);
19630 
19631     if (WXS_SUBST_HEAD(ancestor)->flags & XML_SCHEMAS_ELEM_CIRCULAR)
19632 	return (NULL);
19633     WXS_SUBST_HEAD(ancestor)->flags |= XML_SCHEMAS_ELEM_CIRCULAR;
19634     ret = xmlSchemaCheckSubstGroupCircular(elemDecl,
19635 	WXS_SUBST_HEAD(ancestor));
19636     WXS_SUBST_HEAD(ancestor)->flags ^= XML_SCHEMAS_ELEM_CIRCULAR;
19637 
19638     return (ret);
19639 }
19640 
19641 /**
19642  * xmlSchemaCheckElemPropsCorrect:
19643  * @ctxt:  a schema parser context
19644  * @decl: the element declaration
19645  * @name:  the name of the attribute
19646  *
19647  * Schema Component Constraint:
19648  * Element Declaration Properties Correct (e-props-correct)
19649  *
19650  * STATUS:
19651  *   missing: (6)
19652  */
19653 static int
xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,xmlSchemaElementPtr elemDecl)19654 xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19655 			       xmlSchemaElementPtr elemDecl)
19656 {
19657     int ret = 0;
19658     xmlSchemaTypePtr typeDef = WXS_ELEM_TYPEDEF(elemDecl);
19659     /*
19660     * SPEC (1) "The values of the properties of an element declaration
19661     * must be as described in the property tableau in The Element
19662     * Declaration Schema Component ($3.3.1), modulo the impact of Missing
19663     * Sub-components ($5.3)."
19664     */
19665     if (WXS_SUBST_HEAD(elemDecl) != NULL) {
19666 	xmlSchemaElementPtr head = WXS_SUBST_HEAD(elemDecl), circ;
19667 
19668 	xmlSchemaCheckElementDeclComponent(head, pctxt);
19669 	/*
19670 	* SPEC (3) "If there is a non-`absent` {substitution group
19671 	* affiliation}, then {scope} must be global."
19672 	*/
19673 	if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
19674 	    xmlSchemaPCustomErr(pctxt,
19675 		XML_SCHEMAP_E_PROPS_CORRECT_3,
19676 		WXS_BASIC_CAST elemDecl, NULL,
19677 		"Only global element declarations can have a "
19678 		"substitution group affiliation", NULL);
19679 	    ret = XML_SCHEMAP_E_PROPS_CORRECT_3;
19680 	}
19681 	/*
19682 	* TODO: SPEC (6) "Circular substitution groups are disallowed.
19683 	* That is, it must not be possible to return to an element declaration
19684 	* by repeatedly following the {substitution group affiliation}
19685 	* property."
19686 	*/
19687 	if (head == elemDecl)
19688 	    circ = head;
19689 	else if (WXS_SUBST_HEAD(head) != NULL)
19690 	    circ = xmlSchemaCheckSubstGroupCircular(head, head);
19691 	else
19692 	    circ = NULL;
19693 	if (circ != NULL) {
19694 	    xmlChar *strA = NULL, *strB = NULL;
19695 
19696 	    xmlSchemaPCustomErrExt(pctxt,
19697 		XML_SCHEMAP_E_PROPS_CORRECT_6,
19698 		WXS_BASIC_CAST circ, NULL,
19699 		"The element declaration '%s' defines a circular "
19700 		"substitution group to element declaration '%s'",
19701 		xmlSchemaGetComponentQName(&strA, circ),
19702 		xmlSchemaGetComponentQName(&strB, head),
19703 		NULL);
19704 	    FREE_AND_NULL(strA)
19705 	    FREE_AND_NULL(strB)
19706 	    ret = XML_SCHEMAP_E_PROPS_CORRECT_6;
19707 	}
19708 	/*
19709 	* SPEC (4) "If there is a {substitution group affiliation},
19710 	* the {type definition}
19711 	* of the element declaration must be validly derived from the {type
19712 	* definition} of the {substitution group affiliation}, given the value
19713 	* of the {substitution group exclusions} of the {substitution group
19714 	* affiliation}, as defined in Type Derivation OK (Complex) ($3.4.6)
19715 	* (if the {type definition} is complex) or as defined in
19716 	* Type Derivation OK (Simple) ($3.14.6) (if the {type definition} is
19717 	* simple)."
19718 	*
19719 	* NOTE: {substitution group exclusions} means the values of the
19720 	* attribute "final".
19721 	*/
19722 
19723 	if (typeDef != WXS_ELEM_TYPEDEF(WXS_SUBST_HEAD(elemDecl))) {
19724 	    int set = 0;
19725 
19726 	    if (head->flags & XML_SCHEMAS_ELEM_FINAL_EXTENSION)
19727 		set |= SUBSET_EXTENSION;
19728 	    if (head->flags & XML_SCHEMAS_ELEM_FINAL_RESTRICTION)
19729 		set |= SUBSET_RESTRICTION;
19730 
19731 	    if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST pctxt, typeDef,
19732 		WXS_ELEM_TYPEDEF(head), set) != 0) {
19733 		xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
19734 
19735 		ret = XML_SCHEMAP_E_PROPS_CORRECT_4;
19736 		xmlSchemaPCustomErrExt(pctxt,
19737 		    XML_SCHEMAP_E_PROPS_CORRECT_4,
19738 		    WXS_BASIC_CAST elemDecl, NULL,
19739 		    "The type definition '%s' was "
19740 		    "either rejected by the substitution group "
19741 		    "affiliation '%s', or not validly derived from its type "
19742 		    "definition '%s'",
19743 		    xmlSchemaGetComponentQName(&strA, typeDef),
19744 		    xmlSchemaGetComponentQName(&strB, head),
19745 		    xmlSchemaGetComponentQName(&strC, WXS_ELEM_TYPEDEF(head)));
19746 		FREE_AND_NULL(strA)
19747 		FREE_AND_NULL(strB)
19748 		FREE_AND_NULL(strC)
19749 	    }
19750 	}
19751     }
19752     /*
19753     * SPEC (5) "If the {type definition} or {type definition}'s
19754     * {content type}
19755     * is or is derived from ID then there must not be a {value constraint}.
19756     * Note: The use of ID as a type definition for elements goes beyond
19757     * XML 1.0, and should be avoided if backwards compatibility is desired"
19758     */
19759     if ((elemDecl->value != NULL) &&
19760 	((WXS_IS_SIMPLE(typeDef) &&
19761 	  xmlSchemaIsDerivedFromBuiltInType(typeDef, XML_SCHEMAS_ID)) ||
19762 	 (WXS_IS_COMPLEX(typeDef) &&
19763 	  WXS_HAS_SIMPLE_CONTENT(typeDef) &&
19764 	  xmlSchemaIsDerivedFromBuiltInType(typeDef->contentTypeDef,
19765 	    XML_SCHEMAS_ID)))) {
19766 
19767 	ret = XML_SCHEMAP_E_PROPS_CORRECT_5;
19768 	xmlSchemaPCustomErr(pctxt,
19769 	    XML_SCHEMAP_E_PROPS_CORRECT_5,
19770 	    WXS_BASIC_CAST elemDecl, NULL,
19771 	    "The type definition (or type definition's content type) is or "
19772 	    "is derived from ID; value constraints are not allowed in "
19773 	    "conjunction with such a type definition", NULL);
19774     } else if (elemDecl->value != NULL) {
19775 	int vcret;
19776 	xmlNodePtr node = NULL;
19777 
19778 	/*
19779 	* SPEC (2) "If there is a {value constraint}, the canonical lexical
19780 	* representation of its value must be `valid` with respect to the
19781 	* {type definition} as defined in Element Default Valid (Immediate)
19782 	* ($3.3.6)."
19783 	*/
19784 	if (typeDef == NULL) {
19785 	    xmlSchemaPErr(pctxt, elemDecl->node,
19786 		XML_SCHEMAP_INTERNAL,
19787 		"Internal error: xmlSchemaCheckElemPropsCorrect, "
19788 		"type is missing... skipping validation of "
19789 		"the value constraint", NULL, NULL);
19790 	    return (-1);
19791 	}
19792 	if (elemDecl->node != NULL) {
19793 	    if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
19794 		node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19795 		    BAD_CAST "fixed");
19796 	    else
19797 		node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19798 		    BAD_CAST "default");
19799 	}
19800 	vcret = xmlSchemaParseCheckCOSValidDefault(pctxt, node,
19801 	    typeDef, elemDecl->value, &(elemDecl->defVal));
19802 	if (vcret != 0) {
19803 	    if (vcret < 0) {
19804 		PERROR_INT("xmlSchemaElemCheckValConstr",
19805 		    "failed to validate the value constraint of an "
19806 		    "element declaration");
19807 		return (-1);
19808 	    }
19809 	    return (vcret);
19810 	}
19811     }
19812 
19813     return (ret);
19814 }
19815 
19816 /**
19817  * xmlSchemaCheckElemSubstGroup:
19818  * @ctxt:  a schema parser context
19819  * @decl: the element declaration
19820  * @name:  the name of the attribute
19821  *
19822  * Schema Component Constraint:
19823  * Substitution Group (cos-equiv-class)
19824  *
19825  * In Libxml2 the subst. groups will be precomputed, in terms of that
19826  * a list will be built for each subst. group head, holding all direct
19827  * referents to this head.
19828  * NOTE that this function needs:
19829  *   1. circular subst. groups to be checked beforehand
19830  *   2. the declaration's type to be derived from the head's type
19831  *
19832  * STATUS:
19833  *
19834  */
19835 static void
xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,xmlSchemaElementPtr elemDecl)19836 xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,
19837 			     xmlSchemaElementPtr elemDecl)
19838 {
19839     if ((WXS_SUBST_HEAD(elemDecl) == NULL) ||
19840 	/* SPEC (1) "Its {abstract} is false." */
19841 	(elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT))
19842 	return;
19843     {
19844 	xmlSchemaElementPtr head;
19845 	xmlSchemaTypePtr headType, type;
19846 	int set, methSet;
19847 	/*
19848 	* SPEC (2) "It is validly substitutable for HEAD subject to HEAD's
19849 	* {disallowed substitutions} as the blocking constraint, as defined in
19850 	* Substitution Group OK (Transitive) ($3.3.6)."
19851 	*/
19852 	for (head = WXS_SUBST_HEAD(elemDecl); head != NULL;
19853 	    head = WXS_SUBST_HEAD(head)) {
19854 	    set = 0;
19855 	    methSet = 0;
19856 	    /*
19857 	    * The blocking constraints.
19858 	    */
19859 	    if (head->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION)
19860 		continue;
19861 	    headType = head->subtypes;
19862 	    type = elemDecl->subtypes;
19863 	    if (headType == type)
19864 		goto add_member;
19865 	    if (head->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION)
19866 		set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19867 	    if (head->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION)
19868 		set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19869 	    /*
19870 	    * SPEC: Substitution Group OK (Transitive) (2.3)
19871 	    * "The set of all {derivation method}s involved in the
19872 	    * derivation of D's {type definition} from C's {type definition}
19873 	    * does not intersect with the union of the blocking constraint,
19874 	    * C's {prohibited substitutions} (if C is complex, otherwise the
19875 	    * empty set) and the {prohibited substitutions} (respectively the
19876 	    * empty set) of any intermediate {type definition}s in the
19877 	    * derivation of D's {type definition} from C's {type definition}."
19878 	    */
19879 	    /*
19880 	    * OPTIMIZE TODO: Optimize this a bit, since, if traversing the
19881 	    * subst.head axis, the methSet does not need to be computed for
19882 	    * the full depth over and over.
19883 	    */
19884 	    /*
19885 	    * The set of all {derivation method}s involved in the derivation
19886 	    */
19887 	    while ((type != NULL) && (type != headType)) {
19888 		if ((WXS_IS_EXTENSION(type)) &&
19889 		    ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19890 		    methSet |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19891 
19892 		if (WXS_IS_RESTRICTION(type) &&
19893 		    ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19894 		    methSet |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19895 
19896 		type = type->baseType;
19897 	    }
19898 	    /*
19899 	    * The {prohibited substitutions} of all intermediate types +
19900 	    * the head's type.
19901 	    */
19902 	    type = elemDecl->subtypes->baseType;
19903 	    while (type != NULL) {
19904 		if (WXS_IS_COMPLEX(type)) {
19905 		    if ((type->flags &
19906 			    XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19907 			((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) == 0))
19908 		    set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19909 		    if ((type->flags &
19910 			    XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19911 			((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19912 		    set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19913 		} else
19914 		    break;
19915 		if (type == headType)
19916 		    break;
19917 		type = type->baseType;
19918 	    }
19919 	    if ((set != 0) &&
19920 		(((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19921 		(methSet & XML_SCHEMAS_TYPE_BLOCK_EXTENSION)) ||
19922 		((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19923 		(methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION)))) {
19924 		continue;
19925 	    }
19926 add_member:
19927 	    xmlSchemaAddElementSubstitutionMember(ctxt, head, elemDecl);
19928 	    if ((head->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) == 0)
19929 		head->flags |= XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD;
19930 	}
19931     }
19932 }
19933 
19934 #ifdef WXS_ELEM_DECL_CONS_ENABLED /* enable when finished */
19935 /**
19936  * xmlSchemaCheckElementDeclComponent
19937  * @pctxt: the schema parser context
19938  * @ctxtComponent: the context component (an element declaration)
19939  * @ctxtParticle: the first particle of the context component
19940  * @searchParticle: the element declaration particle to be analysed
19941  *
19942  * Schema Component Constraint: Element Declarations Consistent
19943  */
19944 static int
xmlSchemaCheckElementDeclConsistent(xmlSchemaParserCtxtPtr pctxt,xmlSchemaBasicItemPtr ctxtComponent,xmlSchemaParticlePtr ctxtParticle,xmlSchemaParticlePtr searchParticle,xmlSchemaParticlePtr curParticle,int search)19945 xmlSchemaCheckElementDeclConsistent(xmlSchemaParserCtxtPtr pctxt,
19946 				    xmlSchemaBasicItemPtr ctxtComponent,
19947 				    xmlSchemaParticlePtr ctxtParticle,
19948 				    xmlSchemaParticlePtr searchParticle,
19949 				    xmlSchemaParticlePtr curParticle,
19950 				    int search)
19951 {
19952     return(0);
19953 
19954     int ret = 0;
19955     xmlSchemaParticlePtr cur = curParticle;
19956     if (curParticle == NULL) {
19957 	return(0);
19958     }
19959     if (WXS_PARTICLE_TERM(curParticle) == NULL) {
19960 	/*
19961 	* Just return in this case. A missing "term" of the particle
19962 	* might arise due to an invalid "term" component.
19963 	*/
19964 	return(0);
19965     }
19966     while (cur != NULL) {
19967 	switch (WXS_PARTICLE_TERM(cur)->type) {
19968 	    case XML_SCHEMA_TYPE_ANY:
19969 		break;
19970 	    case XML_SCHEMA_TYPE_ELEMENT:
19971 		if (search == 0) {
19972 		    ret = xmlSchemaCheckElementDeclConsistent(pctxt,
19973 			ctxtComponent, ctxtParticle, cur, ctxtParticle, 1);
19974 		    if (ret != 0)
19975 			return(ret);
19976 		} else {
19977 		    xmlSchemaElementPtr elem =
19978 			WXS_ELEM_CAST(WXS_PARTICLE_TERM(cur));
19979 		    /*
19980 		    * SPEC Element Declarations Consistent:
19981 		    * "If the {particles} contains, either directly,
19982 		    * indirectly (that is, within the {particles} of a
19983 		    * contained model group, recursively) or `implicitly`
19984 		    * two or more element declaration particles with
19985 		    * the same {name} and {target namespace}, then
19986 		    * all their type definitions must be the same
19987 		    * top-level definition [...]"
19988 		    */
19989 		    if (xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->name,
19990 			    WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->name) &&
19991 			xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamespace,
19992 			    WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->targetNamespace))
19993 		    {
19994 			xmlChar *strA = NULL, *strB = NULL;
19995 
19996 			xmlSchemaCustomErr(ACTXT_CAST pctxt,
19997 			    /* TODO: error code */
19998 			    XML_SCHEMAP_COS_NONAMBIG,
19999 			    WXS_ITEM_NODE(cur), NULL,
20000 			    "In the content model of %s, there are multiple "
20001 			    "element declarations for '%s' with different "
20002 			    "type definitions",
20003 			    xmlSchemaGetComponentDesignation(&strA,
20004 				ctxtComponent),
20005 			    xmlSchemaFormatQName(&strB,
20006 				WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamespace,
20007 				WXS_PARTICLE_TERM_AS_ELEM(cur)->name));
20008 			FREE_AND_NULL(strA);
20009 			FREE_AND_NULL(strB);
20010 			return(XML_SCHEMAP_COS_NONAMBIG);
20011 		    }
20012 		}
20013 		break;
20014 	    case XML_SCHEMA_TYPE_SEQUENCE: {
20015 		break;
20016 		}
20017 	    case XML_SCHEMA_TYPE_CHOICE:{
20018 		/*
20019 		xmlSchemaTreeItemPtr sub;
20020 
20021 		sub = WXS_PARTICLE_TERM(particle)->children;  (xmlSchemaParticlePtr)
20022 		while (sub != NULL) {
20023 		    ret = xmlSchemaCheckElementDeclConsistent(pctxt, ctxtComponent,
20024 			ctxtParticle, ctxtElem);
20025 		    if (ret != 0)
20026 			return(ret);
20027 		    sub = sub->next;
20028 		}
20029 		*/
20030 		break;
20031 		}
20032 	    case XML_SCHEMA_TYPE_ALL:
20033 		break;
20034 	    case XML_SCHEMA_TYPE_GROUP:
20035 		break;
20036 	    default:
20037 		xmlSchemaInternalErr2(ACTXT_CAST pctxt,
20038 		    "xmlSchemaCheckElementDeclConsistent",
20039 		    "found unexpected term of type '%s' in content model",
20040 		    WXS_ITEM_TYPE_NAME(WXS_PARTICLE_TERM(cur)), NULL);
20041 		return(-1);
20042 	}
20043 	cur = (xmlSchemaParticlePtr) cur->next;
20044     }
20045 
20046 exit:
20047     return(ret);
20048 }
20049 #endif
20050 
20051 /**
20052  * xmlSchemaCheckElementDeclComponent
20053  * @item:  an schema element declaration/particle
20054  * @ctxt:  a schema parser context
20055  * @name:  the name of the attribute
20056  *
20057  * Validates the value constraints of an element declaration.
20058  * Adds substitution group members.
20059  */
20060 static void
xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,xmlSchemaParserCtxtPtr ctxt)20061 xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
20062 				   xmlSchemaParserCtxtPtr ctxt)
20063 {
20064     if (elemDecl == NULL)
20065 	return;
20066     if (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED)
20067 	return;
20068     elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_CHECKED;
20069     if (xmlSchemaCheckElemPropsCorrect(ctxt, elemDecl) == 0) {
20070 	/*
20071 	* Adds substitution group members.
20072 	*/
20073 	xmlSchemaCheckElemSubstGroup(ctxt, elemDecl);
20074     }
20075 }
20076 
20077 /**
20078  * xmlSchemaResolveModelGroupParticleReferences:
20079  * @particle:  a particle component
20080  * @ctxt:  a parser context
20081  *
20082  * Resolves references of a model group's {particles} to
20083  * model group definitions and to element declarations.
20084  */
20085 static void
xmlSchemaResolveModelGroupParticleReferences(xmlSchemaParserCtxtPtr ctxt,xmlSchemaModelGroupPtr mg)20086 xmlSchemaResolveModelGroupParticleReferences(
20087     xmlSchemaParserCtxtPtr ctxt,
20088     xmlSchemaModelGroupPtr mg)
20089 {
20090     xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
20091     xmlSchemaQNameRefPtr ref;
20092     xmlSchemaBasicItemPtr refItem;
20093 
20094     /*
20095     * URGENT TODO: Test this.
20096     */
20097     while (particle != NULL) {
20098 	if ((WXS_PARTICLE_TERM(particle) == NULL) ||
20099 	    ((WXS_PARTICLE_TERM(particle))->type !=
20100 		XML_SCHEMA_EXTRA_QNAMEREF))
20101 	{
20102 	    goto next_particle;
20103 	}
20104 	ref = WXS_QNAME_CAST WXS_PARTICLE_TERM(particle);
20105 	/*
20106 	* Resolve the reference.
20107 	* NULL the {term} by default.
20108 	*/
20109 	particle->children = NULL;
20110 
20111 	refItem = xmlSchemaGetNamedComponent(ctxt->schema,
20112 	    ref->itemType, ref->name, ref->targetNamespace);
20113 	if (refItem == NULL) {
20114 	    xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
20115 		NULL, WXS_ITEM_NODE(particle), "ref", ref->name,
20116 		ref->targetNamespace, ref->itemType, NULL);
20117 	    /* TODO: remove the particle. */
20118 	    goto next_particle;
20119 	}
20120 	if (refItem->type == XML_SCHEMA_TYPE_GROUP) {
20121 	    if (WXS_MODELGROUPDEF_MODEL(refItem) == NULL)
20122 		/* TODO: remove the particle. */
20123 		goto next_particle;
20124 	    /*
20125 	    * NOTE that we will assign the model group definition
20126 	    * itself to the "term" of the particle. This will ease
20127 	    * the check for circular model group definitions. After
20128 	    * that the "term" will be assigned the model group of the
20129 	    * model group definition.
20130 	    */
20131 	    if ((WXS_MODELGROUPDEF_MODEL(refItem))->type ==
20132 		    XML_SCHEMA_TYPE_ALL) {
20133 		/*
20134 		* SPEC cos-all-limited (1)
20135 		* SPEC cos-all-limited (1.2)
20136 		* "It appears only as the value of one or both of the
20137 		* following properties:"
20138 		* (1.1) "the {model group} property of a model group
20139 		*        definition."
20140 		* (1.2) "the {term} property of a particle [... of] the "
20141 		* {content type} of a complex type definition."
20142 		*/
20143 		xmlSchemaCustomErr(ACTXT_CAST ctxt,
20144 		    /* TODO: error code */
20145 		    XML_SCHEMAP_COS_ALL_LIMITED,
20146 		    WXS_ITEM_NODE(particle), NULL,
20147 		    "A model group definition is referenced, but "
20148 		    "it contains an 'all' model group, which "
20149 		    "cannot be contained by model groups",
20150 		    NULL, NULL);
20151 		/* TODO: remove the particle. */
20152 		goto next_particle;
20153 	    }
20154 	    particle->children = (xmlSchemaTreeItemPtr) refItem;
20155 	} else {
20156 	    /*
20157 	    * TODO: Are referenced element declarations the only
20158 	    * other components we expect here?
20159 	    */
20160 	    particle->children = (xmlSchemaTreeItemPtr) refItem;
20161 	}
20162 next_particle:
20163 	particle = WXS_PTC_CAST particle->next;
20164     }
20165 }
20166 
20167 static int
xmlSchemaAreValuesEqual(xmlSchemaValPtr x,xmlSchemaValPtr y)20168 xmlSchemaAreValuesEqual(xmlSchemaValPtr x,
20169 		       xmlSchemaValPtr y)
20170 {
20171     xmlSchemaTypePtr tx, ty, ptx, pty;
20172     int ret;
20173 
20174     while (x != NULL) {
20175 	/* Same types. */
20176 	tx = xmlSchemaGetBuiltInType(xmlSchemaGetValType(x));
20177 	ty = xmlSchemaGetBuiltInType(xmlSchemaGetValType(y));
20178 	ptx = xmlSchemaGetPrimitiveType(tx);
20179 	pty = xmlSchemaGetPrimitiveType(ty);
20180 	/*
20181 	* (1) if a datatype T' is `derived` by `restriction` from an
20182 	* atomic datatype T then the `value space` of T' is a subset of
20183 	* the `value space` of T. */
20184 	/*
20185 	* (2) if datatypes T' and T'' are `derived` by `restriction`
20186 	* from a common atomic ancestor T then the `value space`s of T'
20187 	* and T'' may overlap.
20188 	*/
20189 	if (ptx != pty)
20190 	    return(0);
20191 	/*
20192 	* We assume computed values to be normalized, so do a fast
20193 	* string comparison for string based types.
20194 	*/
20195 	if ((ptx->builtInType == XML_SCHEMAS_STRING) ||
20196 	    WXS_IS_ANY_SIMPLE_TYPE(ptx)) {
20197 	    if (! xmlStrEqual(
20198 		xmlSchemaValueGetAsString(x),
20199 		xmlSchemaValueGetAsString(y)))
20200 		return (0);
20201 	} else {
20202 	    ret = xmlSchemaCompareValuesWhtsp(
20203 		x, XML_SCHEMA_WHITESPACE_PRESERVE,
20204 		y, XML_SCHEMA_WHITESPACE_PRESERVE);
20205 	    if (ret == -2)
20206 		return(-1);
20207 	    if (ret != 0)
20208 		return(0);
20209 	}
20210 	/*
20211 	* Lists.
20212 	*/
20213 	x = xmlSchemaValueGetNext(x);
20214 	if (x != NULL) {
20215 	    y = xmlSchemaValueGetNext(y);
20216 	    if (y == NULL)
20217 		return (0);
20218 	} else if (xmlSchemaValueGetNext(y) != NULL)
20219 	    return (0);
20220 	else
20221 	    return (1);
20222     }
20223     return (0);
20224 }
20225 
20226 /**
20227  * xmlSchemaResolveAttrUseReferences:
20228  * @item:  an attribute use
20229  * @ctxt:  a parser context
20230  *
20231  * Resolves the referenced attribute declaration.
20232  */
20233 static int
xmlSchemaResolveAttrUseReferences(xmlSchemaAttributeUsePtr ause,xmlSchemaParserCtxtPtr ctxt)20234 xmlSchemaResolveAttrUseReferences(xmlSchemaAttributeUsePtr ause,
20235 				  xmlSchemaParserCtxtPtr ctxt)
20236 {
20237     if ((ctxt == NULL) || (ause == NULL))
20238 	return(-1);
20239     if ((ause->attrDecl == NULL) ||
20240 	(ause->attrDecl->type != XML_SCHEMA_EXTRA_QNAMEREF))
20241 	return(0);
20242 
20243     {
20244 	xmlSchemaQNameRefPtr ref = WXS_QNAME_CAST ause->attrDecl;
20245 
20246 	/*
20247 	* TODO: Evaluate, what errors could occur if the declaration is not
20248 	* found.
20249 	*/
20250 	ause->attrDecl = xmlSchemaGetAttributeDecl(ctxt->schema,
20251 	    ref->name, ref->targetNamespace);
20252         if (ause->attrDecl == NULL) {
20253 	    xmlSchemaPResCompAttrErr(ctxt,
20254 		XML_SCHEMAP_SRC_RESOLVE,
20255 		WXS_BASIC_CAST ause, ause->node,
20256 		"ref", ref->name, ref->targetNamespace,
20257 		XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20258             return(ctxt->err);;
20259         }
20260     }
20261     return(0);
20262 }
20263 
20264 /**
20265  * xmlSchemaCheckAttrUsePropsCorrect:
20266  * @ctxt:  a parser context
20267  * @use:  an attribute use
20268  *
20269  * Schema Component Constraint:
20270  * Attribute Use Correct (au-props-correct)
20271  *
20272  */
20273 static int
xmlSchemaCheckAttrUsePropsCorrect(xmlSchemaParserCtxtPtr ctxt,xmlSchemaAttributeUsePtr use)20274 xmlSchemaCheckAttrUsePropsCorrect(xmlSchemaParserCtxtPtr ctxt,
20275 			     xmlSchemaAttributeUsePtr use)
20276 {
20277     if ((ctxt == NULL) || (use == NULL))
20278 	return(-1);
20279     if ((use->defValue == NULL) || (WXS_ATTRUSE_DECL(use) == NULL) ||
20280 	((WXS_ATTRUSE_DECL(use))->type != XML_SCHEMA_TYPE_ATTRIBUTE))
20281 	return(0);
20282 
20283     /*
20284     * SPEC au-props-correct (1)
20285     * "The values of the properties of an attribute use must be as
20286     * described in the property tableau in The Attribute Use Schema
20287     * Component ($3.5.1), modulo the impact of Missing
20288     * Sub-components ($5.3)."
20289     */
20290 
20291     if (((WXS_ATTRUSE_DECL(use))->defValue != NULL) &&
20292 	((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMAS_ATTR_FIXED) &&
20293         ((use->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20294     {
20295 	xmlSchemaPCustomErr(ctxt,
20296 	    XML_SCHEMAP_AU_PROPS_CORRECT_2,
20297 	    WXS_BASIC_CAST use, NULL,
20298 	    "The attribute declaration has a 'fixed' value constraint "
20299 	    ", thus the attribute use must also have a 'fixed' value "
20300 	    "constraint",
20301 	    NULL);
20302 	return(ctxt->err);
20303     }
20304     /*
20305     * Compute and check the value constraint's value.
20306     */
20307     if ((use->defVal != NULL) && (WXS_ATTRUSE_TYPEDEF(use) != NULL)) {
20308 	int ret;
20309 	/*
20310 	* TODO: The spec seems to be missing a check of the
20311 	* value constraint of the attribute use. We will do it here.
20312 	*/
20313 	/*
20314 	* SPEC a-props-correct (3)
20315 	*/
20316 	if (xmlSchemaIsDerivedFromBuiltInType(
20317 	    WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
20318 	{
20319 	    xmlSchemaCustomErr(ACTXT_CAST ctxt,
20320 		XML_SCHEMAP_AU_PROPS_CORRECT,
20321 		NULL, WXS_BASIC_CAST use,
20322 		"Value constraints are not allowed if the type definition "
20323 		"is or is derived from xs:ID",
20324 		NULL, NULL);
20325 	    return(ctxt->err);
20326 	}
20327 
20328 	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST ctxt,
20329 	    use->node, WXS_ATTRUSE_TYPEDEF(use),
20330 	    use->defValue, &(use->defVal),
20331 	    1, 1, 0);
20332 	if (ret != 0) {
20333 	    if (ret < 0) {
20334 		PERROR_INT2("xmlSchemaCheckAttrUsePropsCorrect",
20335 		    "calling xmlSchemaVCheckCVCSimpleType()");
20336 		return(-1);
20337 	    }
20338 	    xmlSchemaCustomErr(ACTXT_CAST ctxt,
20339 		XML_SCHEMAP_AU_PROPS_CORRECT,
20340 		NULL, WXS_BASIC_CAST use,
20341 		"The value of the value constraint is not valid",
20342 		NULL, NULL);
20343 	    return(ctxt->err);
20344 	}
20345     }
20346     /*
20347     * SPEC au-props-correct (2)
20348     * "If the {attribute declaration} has a fixed
20349     * {value constraint}, then if the attribute use itself has a
20350     * {value constraint}, it must also be fixed and its value must match
20351     * that of the {attribute declaration}'s {value constraint}."
20352     */
20353     if (((WXS_ATTRUSE_DECL(use))->defVal != NULL) &&
20354 	(((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20355     {
20356 	if (! xmlSchemaAreValuesEqual(use->defVal,
20357 		(WXS_ATTRUSE_DECL(use))->defVal))
20358 	{
20359 	    xmlSchemaPCustomErr(ctxt,
20360 		XML_SCHEMAP_AU_PROPS_CORRECT_2,
20361 		WXS_BASIC_CAST use, NULL,
20362 		"The 'fixed' value constraint of the attribute use "
20363 		"must match the attribute declaration's value "
20364 		"constraint '%s'",
20365 		(WXS_ATTRUSE_DECL(use))->defValue);
20366 	}
20367 	return(ctxt->err);
20368     }
20369     return(0);
20370 }
20371 
20372 
20373 
20374 
20375 /**
20376  * xmlSchemaResolveAttrTypeReferences:
20377  * @item:  an attribute declaration
20378  * @ctxt:  a parser context
20379  *
20380  * Resolves the referenced type definition component.
20381  */
20382 static int
xmlSchemaResolveAttrTypeReferences(xmlSchemaAttributePtr item,xmlSchemaParserCtxtPtr ctxt)20383 xmlSchemaResolveAttrTypeReferences(xmlSchemaAttributePtr item,
20384 				   xmlSchemaParserCtxtPtr ctxt)
20385 {
20386     /*
20387     * The simple type definition corresponding to the <simpleType> element
20388     * information item in the [children], if present, otherwise the simple
20389     * type definition `resolved` to by the `actual value` of the type
20390     * [attribute], if present, otherwise the `simple ur-type definition`.
20391     */
20392     if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
20393 	return(0);
20394     item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
20395     if (item->subtypes != NULL)
20396         return(0);
20397     if (item->typeName != NULL) {
20398         xmlSchemaTypePtr type;
20399 
20400 	type = xmlSchemaGetType(ctxt->schema, item->typeName,
20401 	    item->typeNs);
20402 	if ((type == NULL) || (! WXS_IS_SIMPLE(type))) {
20403 	    xmlSchemaPResCompAttrErr(ctxt,
20404 		XML_SCHEMAP_SRC_RESOLVE,
20405 		WXS_BASIC_CAST item, item->node,
20406 		"type", item->typeName, item->typeNs,
20407 		XML_SCHEMA_TYPE_SIMPLE, NULL);
20408 	    return(ctxt->err);
20409 	} else
20410 	    item->subtypes = type;
20411 
20412     } else {
20413 	/*
20414 	* The type defaults to the xs:anySimpleType.
20415 	*/
20416 	item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
20417     }
20418     return(0);
20419 }
20420 
20421 /**
20422  * xmlSchemaResolveIDCKeyReferences:
20423  * @idc:  the identity-constraint definition
20424  * @ctxt:  the schema parser context
20425  * @name:  the attribute name
20426  *
20427  * Resolve keyRef references to key/unique IDCs.
20428  * Schema Component Constraint:
20429  *   Identity-constraint Definition Properties Correct (c-props-correct)
20430  */
20431 static int
xmlSchemaResolveIDCKeyReferences(xmlSchemaIDCPtr idc,xmlSchemaParserCtxtPtr pctxt)20432 xmlSchemaResolveIDCKeyReferences(xmlSchemaIDCPtr idc,
20433 			  xmlSchemaParserCtxtPtr pctxt)
20434 {
20435     if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
20436         return(0);
20437     if (idc->ref->name != NULL) {
20438 	idc->ref->item = (xmlSchemaBasicItemPtr)
20439 	    xmlSchemaGetIDC(pctxt->schema, idc->ref->name,
20440 		idc->ref->targetNamespace);
20441         if (idc->ref->item == NULL) {
20442 	    /*
20443 	    * TODO: It is actually not an error to fail to resolve
20444 	    * at this stage. BUT we need to be that strict!
20445 	    */
20446 	    xmlSchemaPResCompAttrErr(pctxt,
20447 		XML_SCHEMAP_SRC_RESOLVE,
20448 		WXS_BASIC_CAST idc, idc->node,
20449 		"refer", idc->ref->name,
20450 		idc->ref->targetNamespace,
20451 		XML_SCHEMA_TYPE_IDC_KEY, NULL);
20452             return(pctxt->err);
20453 	} else if (idc->ref->item->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
20454 	    /*
20455 	    * SPEC c-props-correct (1)
20456 	    */
20457 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
20458 		XML_SCHEMAP_C_PROPS_CORRECT,
20459 		NULL, WXS_BASIC_CAST idc,
20460 		"The keyref references a keyref",
20461 		NULL, NULL);
20462 	    idc->ref->item = NULL;
20463 	    return(pctxt->err);
20464 	} else {
20465 	    if (idc->nbFields !=
20466 		((xmlSchemaIDCPtr) idc->ref->item)->nbFields) {
20467 		xmlChar *str = NULL;
20468 		xmlSchemaIDCPtr refer;
20469 
20470 		refer = (xmlSchemaIDCPtr) idc->ref->item;
20471 		/*
20472 		* SPEC c-props-correct(2)
20473 		* "If the {identity-constraint category} is keyref,
20474 		* the cardinality of the {fields} must equal that of
20475 		* the {fields} of the {referenced key}.
20476 		*/
20477 		xmlSchemaCustomErr(ACTXT_CAST pctxt,
20478 		    XML_SCHEMAP_C_PROPS_CORRECT,
20479 		    NULL, WXS_BASIC_CAST idc,
20480 		    "The cardinality of the keyref differs from the "
20481 		    "cardinality of the referenced key/unique '%s'",
20482 		    xmlSchemaFormatQName(&str, refer->targetNamespace,
20483 			refer->name),
20484 		    NULL);
20485 		FREE_AND_NULL(str)
20486 		return(pctxt->err);
20487 	    }
20488 	}
20489     }
20490     return(0);
20491 }
20492 
20493 static int
xmlSchemaResolveAttrUseProhibReferences(xmlSchemaAttributeUseProhibPtr prohib,xmlSchemaParserCtxtPtr pctxt)20494 xmlSchemaResolveAttrUseProhibReferences(xmlSchemaAttributeUseProhibPtr prohib,
20495 				       xmlSchemaParserCtxtPtr pctxt)
20496 {
20497     if (xmlSchemaGetAttributeDecl(pctxt->schema, prohib->name,
20498 	prohib->targetNamespace) == NULL) {
20499 
20500 	xmlSchemaPResCompAttrErr(pctxt,
20501 	    XML_SCHEMAP_SRC_RESOLVE,
20502 	    NULL, prohib->node,
20503 	    "ref", prohib->name, prohib->targetNamespace,
20504 	    XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20505 	return(XML_SCHEMAP_SRC_RESOLVE);
20506     }
20507     return(0);
20508 }
20509 
20510 #define WXS_REDEFINED_TYPE(c) \
20511 (((xmlSchemaTypePtr) item)->flags & XML_SCHEMAS_TYPE_REDEFINED)
20512 
20513 #define WXS_REDEFINED_MODEL_GROUP_DEF(c) \
20514 (((xmlSchemaModelGroupDefPtr) item)->flags & XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20515 
20516 #define WXS_REDEFINED_ATTR_GROUP(c) \
20517 (((xmlSchemaAttributeGroupPtr) item)->flags & XML_SCHEMAS_ATTRGROUP_REDEFINED)
20518 
20519 static int
xmlSchemaCheckSRCRedefineFirst(xmlSchemaParserCtxtPtr pctxt)20520 xmlSchemaCheckSRCRedefineFirst(xmlSchemaParserCtxtPtr pctxt)
20521 {
20522     int err = 0;
20523     xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20524     xmlSchemaBasicItemPtr prev, item;
20525     int wasRedefined;
20526 
20527     if (redef == NULL)
20528 	return(0);
20529 
20530     do {
20531 	item = redef->item;
20532 	/*
20533 	* First try to locate the redefined component in the
20534 	* schema graph starting with the redefined schema.
20535 	* NOTE: According to this schema bug entry:
20536 	*   http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005OctDec/0019.html
20537 	*   it's not clear if the referenced component needs to originate
20538 	*   from the <redefine>d schema _document_ or the schema; the latter
20539 	*   would include all imported and included sub-schemas of the
20540 	*   <redefine>d schema. Currenlty we latter approach is used.
20541 	*   SUPPLEMENT: It seems that the WG moves towards the latter
20542 	*   approach, so we are doing it right.
20543 	*
20544 	*/
20545 	prev = xmlSchemaFindRedefCompInGraph(
20546 	    redef->targetBucket, item->type,
20547 	    redef->refName, redef->refTargetNs);
20548 	if (prev == NULL) {
20549 	    xmlChar *str = NULL;
20550 	    xmlNodePtr node;
20551 
20552 	    /*
20553 	    * SPEC src-redefine:
20554 	    * (6.2.1) "The `actual value` of its own name attribute plus
20555 	    * target namespace must successfully `resolve` to a model
20556 	    * group definition in I."
20557 	    * (7.2.1) "The `actual value` of its own name attribute plus
20558 	    * target namespace must successfully `resolve` to an attribute
20559 	    * group definition in I."
20560 
20561 	    *
20562 	    * Note that, if we are redefining with the use of references
20563 	    * to components, the spec assumes the src-resolve to be used;
20564 	    * but this won't assure that we search only *inside* the
20565 	    * redefined schema.
20566 	    */
20567 	    if (redef->reference)
20568 		node = WXS_ITEM_NODE(redef->reference);
20569 	    else
20570 		node = WXS_ITEM_NODE(item);
20571 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
20572 		/*
20573 		* TODO: error code.
20574 		* Probably XML_SCHEMAP_SRC_RESOLVE, if this is using the
20575 		* reference kind.
20576 		*/
20577 		XML_SCHEMAP_SRC_REDEFINE, node, NULL,
20578 		"The %s '%s' to be redefined could not be found in "
20579 		"the redefined schema",
20580 		WXS_ITEM_TYPE_NAME(item),
20581 		xmlSchemaFormatQName(&str, redef->refTargetNs,
20582 		    redef->refName));
20583 	    FREE_AND_NULL(str);
20584 	    err = pctxt->err;
20585 	    redef = redef->next;
20586 	    continue;
20587 	}
20588 	/*
20589 	* TODO: Obtaining and setting the redefinition state is really
20590 	* clumsy.
20591 	*/
20592 	wasRedefined = 0;
20593 	switch (item->type) {
20594 	    case XML_SCHEMA_TYPE_COMPLEX:
20595 	    case XML_SCHEMA_TYPE_SIMPLE:
20596 		if ((WXS_TYPE_CAST prev)->flags &
20597 		    XML_SCHEMAS_TYPE_REDEFINED)
20598 		{
20599 		    wasRedefined = 1;
20600 		    break;
20601 		}
20602 		/* Mark it as redefined. */
20603 		(WXS_TYPE_CAST prev)->flags |= XML_SCHEMAS_TYPE_REDEFINED;
20604 		/*
20605 		* Assign the redefined type to the
20606 		* base type of the redefining type.
20607 		* TODO: How
20608 		*/
20609 		((xmlSchemaTypePtr) item)->baseType =
20610 		    (xmlSchemaTypePtr) prev;
20611 		break;
20612 	    case XML_SCHEMA_TYPE_GROUP:
20613 		if ((WXS_MODEL_GROUPDEF_CAST prev)->flags &
20614 		    XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20615 		{
20616 		    wasRedefined = 1;
20617 		    break;
20618 		}
20619 		/* Mark it as redefined. */
20620 		(WXS_MODEL_GROUPDEF_CAST prev)->flags |=
20621 		    XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED;
20622 		if (redef->reference != NULL) {
20623 		    /*
20624 		    * Overwrite the QName-reference with the
20625 		    * referenced model group def.
20626 		    */
20627 		    (WXS_PTC_CAST redef->reference)->children =
20628 			WXS_TREE_CAST prev;
20629 		}
20630 		redef->target = prev;
20631 		break;
20632 	    case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20633 		if ((WXS_ATTR_GROUP_CAST prev)->flags &
20634 		    XML_SCHEMAS_ATTRGROUP_REDEFINED)
20635 		{
20636 		    wasRedefined = 1;
20637 		    break;
20638 		}
20639 		(WXS_ATTR_GROUP_CAST prev)->flags |=
20640 		    XML_SCHEMAS_ATTRGROUP_REDEFINED;
20641 		if (redef->reference != NULL) {
20642 		    /*
20643 		    * Assign the redefined attribute group to the
20644 		    * QName-reference component.
20645 		    * This is the easy case, since we will just
20646 		    * expand the redefined group.
20647 		    */
20648 		    (WXS_QNAME_CAST redef->reference)->item = prev;
20649 		    redef->target = NULL;
20650 		} else {
20651 		    /*
20652 		    * This is the complicated case: we need
20653 		    * to apply src-redefine (7.2.2) at a later
20654 		    * stage, i.e. when attribute group references
20655 		    * have beed expanded and simple types have
20656 		    * beed fixed.
20657 		    */
20658 		    redef->target = prev;
20659 		}
20660 		break;
20661 	    default:
20662 		PERROR_INT("xmlSchemaResolveRedefReferences",
20663 		    "Unexpected redefined component type");
20664 		return(-1);
20665 	}
20666 	if (wasRedefined) {
20667 	    xmlChar *str = NULL;
20668 	    xmlNodePtr node;
20669 
20670 	    if (redef->reference)
20671 		node = WXS_ITEM_NODE(redef->reference);
20672 	    else
20673 		node = WXS_ITEM_NODE(redef->item);
20674 
20675 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
20676 		/* TODO: error code. */
20677 		XML_SCHEMAP_SRC_REDEFINE,
20678 		node, NULL,
20679 		"The referenced %s was already redefined. Multiple "
20680 		"redefinition of the same component is not supported",
20681 		xmlSchemaGetComponentDesignation(&str, prev),
20682 		NULL);
20683 	    FREE_AND_NULL(str)
20684 	    err = pctxt->err;
20685 	    redef = redef->next;
20686 	    continue;
20687 	}
20688 	redef = redef->next;
20689     } while (redef != NULL);
20690 
20691     return(err);
20692 }
20693 
20694 static int
xmlSchemaCheckSRCRedefineSecond(xmlSchemaParserCtxtPtr pctxt)20695 xmlSchemaCheckSRCRedefineSecond(xmlSchemaParserCtxtPtr pctxt)
20696 {
20697     int err = 0;
20698     xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20699     xmlSchemaBasicItemPtr item;
20700 
20701     if (redef == NULL)
20702 	return(0);
20703 
20704     do {
20705 	if (redef->target == NULL) {
20706 	    redef = redef->next;
20707 	    continue;
20708 	}
20709 	item = redef->item;
20710 
20711 	switch (item->type) {
20712 	    case XML_SCHEMA_TYPE_SIMPLE:
20713 	    case XML_SCHEMA_TYPE_COMPLEX:
20714 		/*
20715 		* Since the spec wants the {name} of the redefined
20716 		* type to be 'absent', we'll NULL it.
20717 		*/
20718 		(WXS_TYPE_CAST redef->target)->name = NULL;
20719 
20720 		/*
20721 		* TODO: Seems like there's nothing more to do. The normal
20722 		* inheritance mechanism is used. But not 100% sure.
20723 		*/
20724 		break;
20725 	    case XML_SCHEMA_TYPE_GROUP:
20726 		/*
20727 		* URGENT TODO:
20728 		* SPEC src-redefine:
20729 		* (6.2.2) "The {model group} of the model group definition
20730 		* which corresponds to it per XML Representation of Model
20731 		* Group Definition Schema Components ($3.7.2) must be a
20732 		* `valid restriction` of the {model group} of that model
20733 		* group definition in I, as defined in Particle Valid
20734 		* (Restriction) ($3.9.6)."
20735 		*/
20736 		break;
20737 	    case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20738 		/*
20739 		* SPEC src-redefine:
20740 		* (7.2.2) "The {attribute uses} and {attribute wildcard} of
20741 		* the attribute group definition which corresponds to it
20742 		* per XML Representation of Attribute Group Definition Schema
20743 		* Components ($3.6.2) must be `valid restrictions` of the
20744 		* {attribute uses} and {attribute wildcard} of that attribute
20745 		* group definition in I, as defined in clause 2, clause 3 and
20746 		* clause 4 of Derivation Valid (Restriction, Complex)
20747 		* ($3.4.6) (where references to the base type definition are
20748 		* understood as references to the attribute group definition
20749 		* in I)."
20750 		*/
20751 		err = xmlSchemaCheckDerivationOKRestriction2to4(pctxt,
20752 		    XML_SCHEMA_ACTION_REDEFINE,
20753 		    item, redef->target,
20754 		    (WXS_ATTR_GROUP_CAST item)->attrUses,
20755 		    (WXS_ATTR_GROUP_CAST redef->target)->attrUses,
20756 		    (WXS_ATTR_GROUP_CAST item)->attributeWildcard,
20757 		    (WXS_ATTR_GROUP_CAST redef->target)->attributeWildcard);
20758 		if (err == -1)
20759 		    return(-1);
20760 		break;
20761 	    default:
20762 		break;
20763 	}
20764 	redef = redef->next;
20765     } while (redef != NULL);
20766     return(0);
20767 }
20768 
20769 
20770 static int
xmlSchemaAddComponents(xmlSchemaParserCtxtPtr pctxt,xmlSchemaBucketPtr bucket)20771 xmlSchemaAddComponents(xmlSchemaParserCtxtPtr pctxt,
20772 		       xmlSchemaBucketPtr bucket)
20773 {
20774     xmlSchemaBasicItemPtr item;
20775     int err;
20776     xmlHashTablePtr *table;
20777     const xmlChar *name;
20778     int i;
20779 
20780 #define WXS_GET_GLOBAL_HASH(c, slot) { \
20781     if (WXS_IS_BUCKET_IMPMAIN((c)->type)) \
20782 	table = &(WXS_IMPBUCKET((c))->schema->slot); \
20783     else \
20784 	table = &(WXS_INCBUCKET((c))->ownerImport->schema->slot); }
20785 
20786     /*
20787     * Add global components to the schema's hash tables.
20788     * This is the place where duplicate components will be
20789     * detected.
20790     * TODO: I think normally we should support imports of the
20791     *   same namespace from multiple locations. We don't do currently,
20792     *   but if we do then according to:
20793     *   http://www.w3.org/Bugs/Public/show_bug.cgi?id=2224
20794     *   we would need, if imported directly, to import redefined
20795     *   components as well to be able to catch clashing components.
20796     *   (I hope I'll still know what this means after some months :-()
20797     */
20798     if (bucket == NULL)
20799 	return(-1);
20800     if (bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED)
20801 	return(0);
20802     bucket->flags |= XML_SCHEMA_BUCKET_COMPS_ADDED;
20803 
20804     for (i = 0; i < bucket->globals->nbItems; i++) {
20805 	item = bucket->globals->items[i];
20806 	table = NULL;
20807 	switch (item->type) {
20808 	    case XML_SCHEMA_TYPE_COMPLEX:
20809 	    case XML_SCHEMA_TYPE_SIMPLE:
20810 		if (WXS_REDEFINED_TYPE(item))
20811 		    continue;
20812 		name = (WXS_TYPE_CAST item)->name;
20813 		WXS_GET_GLOBAL_HASH(bucket, typeDecl)
20814 		break;
20815 	    case XML_SCHEMA_TYPE_ELEMENT:
20816 		name = (WXS_ELEM_CAST item)->name;
20817 		WXS_GET_GLOBAL_HASH(bucket, elemDecl)
20818 		break;
20819 	    case XML_SCHEMA_TYPE_ATTRIBUTE:
20820 		name = (WXS_ATTR_CAST item)->name;
20821 		WXS_GET_GLOBAL_HASH(bucket, attrDecl)
20822 		break;
20823 	    case XML_SCHEMA_TYPE_GROUP:
20824 		if (WXS_REDEFINED_MODEL_GROUP_DEF(item))
20825 		    continue;
20826 		name = (WXS_MODEL_GROUPDEF_CAST item)->name;
20827 		WXS_GET_GLOBAL_HASH(bucket, groupDecl)
20828 		break;
20829 	    case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20830 		if (WXS_REDEFINED_ATTR_GROUP(item))
20831 		    continue;
20832 		name = (WXS_ATTR_GROUP_CAST item)->name;
20833 		WXS_GET_GLOBAL_HASH(bucket, attrgrpDecl)
20834 		break;
20835 	    case XML_SCHEMA_TYPE_IDC_KEY:
20836 	    case XML_SCHEMA_TYPE_IDC_UNIQUE:
20837 	    case XML_SCHEMA_TYPE_IDC_KEYREF:
20838 		name = (WXS_IDC_CAST item)->name;
20839 		WXS_GET_GLOBAL_HASH(bucket, idcDef)
20840 		break;
20841 	    case XML_SCHEMA_TYPE_NOTATION:
20842 		name = ((xmlSchemaNotationPtr) item)->name;
20843 		WXS_GET_GLOBAL_HASH(bucket, notaDecl)
20844 		break;
20845 	    default:
20846 		PERROR_INT("xmlSchemaAddComponents",
20847 		    "Unexpected global component type");
20848 		continue;
20849 	}
20850 	if (*table == NULL) {
20851 	    *table = xmlHashCreateDict(10, pctxt->dict);
20852 	    if (*table == NULL) {
20853 		PERROR_INT("xmlSchemaAddComponents",
20854 		    "failed to create a component hash table");
20855 		return(-1);
20856 	    }
20857 	}
20858 	err = xmlHashAddEntry(*table, name, item);
20859 	if (err != 0) {
20860 	    xmlChar *str = NULL;
20861 
20862 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
20863 		XML_SCHEMAP_REDEFINED_TYPE,
20864 		WXS_ITEM_NODE(item),
20865 		WXS_BASIC_CAST item,
20866 		"A global %s '%s' does already exist",
20867 		WXS_ITEM_TYPE_NAME(item),
20868 		xmlSchemaGetComponentQName(&str, item));
20869 	    FREE_AND_NULL(str);
20870 	}
20871     }
20872     /*
20873     * Process imported/included schemas.
20874     */
20875     if (bucket->relations != NULL) {
20876 	xmlSchemaSchemaRelationPtr rel = bucket->relations;
20877 	do {
20878 	    if ((rel->bucket != NULL) &&
20879 		((rel->bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED) == 0)) {
20880 		if (xmlSchemaAddComponents(pctxt, rel->bucket) == -1)
20881 		    return(-1);
20882 	    }
20883 	    rel = rel->next;
20884 	} while (rel != NULL);
20885     }
20886     return(0);
20887 }
20888 
20889 static int
xmlSchemaFixupComponents(xmlSchemaParserCtxtPtr pctxt,xmlSchemaBucketPtr rootBucket)20890 xmlSchemaFixupComponents(xmlSchemaParserCtxtPtr pctxt,
20891 			 xmlSchemaBucketPtr rootBucket)
20892 {
20893     xmlSchemaConstructionCtxtPtr con = pctxt->constructor;
20894     xmlSchemaTreeItemPtr item, *items;
20895     int nbItems, i, ret = 0;
20896     xmlSchemaBucketPtr oldbucket = con->bucket;
20897     xmlSchemaElementPtr elemDecl;
20898 
20899 #define FIXHFAILURE if (pctxt->err == XML_SCHEMAP_INTERNAL) goto exit_failure;
20900 
20901     if ((con->pending == NULL) ||
20902 	(con->pending->nbItems == 0))
20903 	return(0);
20904 
20905     /*
20906     * Since xmlSchemaFixupComplexType() will create new particles
20907     * (local components), and those particle components need a bucket
20908     * on the constructor, we'll assure here that the constructor has
20909     * a bucket.
20910     * TODO: Think about storing locals _only_ on the main bucket.
20911     */
20912     if (con->bucket == NULL)
20913 	con->bucket = rootBucket;
20914 
20915     /* TODO:
20916     * SPEC (src-redefine):
20917     * (6.2) "If it has no such self-reference, then all of the
20918     * following must be true:"
20919 
20920     * (6.2.2) The {model group} of the model group definition which
20921     * corresponds to it per XML Representation of Model Group
20922     * Definition Schema Components ($3.7.2) must be a `valid
20923     * restriction` of the {model group} of that model group definition
20924     * in I, as defined in Particle Valid (Restriction) ($3.9.6)."
20925     */
20926     xmlSchemaCheckSRCRedefineFirst(pctxt);
20927 
20928     /*
20929     * Add global components to the schemata's hash tables.
20930     */
20931     xmlSchemaAddComponents(pctxt, rootBucket);
20932 
20933     pctxt->ctxtType = NULL;
20934     items = (xmlSchemaTreeItemPtr *) con->pending->items;
20935     nbItems = con->pending->nbItems;
20936     /*
20937     * Now that we have parsed *all* the schema document(s) and converted
20938     * them to schema components, we can resolve references, apply component
20939     * constraints, create the FSA from the content model, etc.
20940     */
20941     /*
20942     * Resolve references of..
20943     *
20944     * 1. element declarations:
20945     *   - the type definition
20946     *   - the substitution group affiliation
20947     * 2. simple/complex types:
20948     *   - the base type definition
20949     *   - the memberTypes of union types
20950     *   - the itemType of list types
20951     * 3. attributes declarations and attribute uses:
20952     *   - the type definition
20953     *   - if an attribute use, then the attribute declaration
20954     * 4. attribute group references:
20955     *   - the attribute group definition
20956     * 5. particles:
20957     *   - the term of the particle (e.g. a model group)
20958     * 6. IDC key-references:
20959     *   - the referenced IDC 'key' or 'unique' definition
20960     * 7. Attribute prohibitions which had a "ref" attribute.
20961     */
20962     for (i = 0; i < nbItems; i++) {
20963 	item = items[i];
20964 	switch (item->type) {
20965 	    case XML_SCHEMA_TYPE_ELEMENT:
20966 		xmlSchemaResolveElementReferences(
20967 		    (xmlSchemaElementPtr) item, pctxt);
20968 		FIXHFAILURE;
20969 		break;
20970 	    case XML_SCHEMA_TYPE_COMPLEX:
20971 	    case XML_SCHEMA_TYPE_SIMPLE:
20972 		xmlSchemaResolveTypeReferences(
20973 		    (xmlSchemaTypePtr) item, pctxt);
20974 		FIXHFAILURE;
20975 		break;
20976 	    case XML_SCHEMA_TYPE_ATTRIBUTE:
20977 		xmlSchemaResolveAttrTypeReferences(
20978 		    (xmlSchemaAttributePtr) item, pctxt);
20979 		FIXHFAILURE;
20980 		break;
20981 	    case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
20982 		xmlSchemaResolveAttrUseReferences(
20983 		    (xmlSchemaAttributeUsePtr) item, pctxt);
20984 		FIXHFAILURE;
20985 		break;
20986 	    case XML_SCHEMA_EXTRA_QNAMEREF:
20987 		if ((WXS_QNAME_CAST item)->itemType ==
20988 		    XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
20989 		{
20990 		    xmlSchemaResolveAttrGroupReferences(
20991 			WXS_QNAME_CAST item, pctxt);
20992 		}
20993 		FIXHFAILURE;
20994 		break;
20995 	    case XML_SCHEMA_TYPE_SEQUENCE:
20996 	    case XML_SCHEMA_TYPE_CHOICE:
20997 	    case XML_SCHEMA_TYPE_ALL:
20998 		xmlSchemaResolveModelGroupParticleReferences(pctxt,
20999 		    WXS_MODEL_GROUP_CAST item);
21000 		FIXHFAILURE;
21001 		break;
21002 	    case XML_SCHEMA_TYPE_IDC_KEY:
21003 	    case XML_SCHEMA_TYPE_IDC_UNIQUE:
21004 	    case XML_SCHEMA_TYPE_IDC_KEYREF:
21005 		xmlSchemaResolveIDCKeyReferences(
21006 		    (xmlSchemaIDCPtr) item, pctxt);
21007 		FIXHFAILURE;
21008 		break;
21009 	    case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
21010 		/*
21011 		* Handle attribue prohibition which had a
21012 		* "ref" attribute.
21013 		*/
21014 		xmlSchemaResolveAttrUseProhibReferences(
21015 		    WXS_ATTR_PROHIB_CAST item, pctxt);
21016 		FIXHFAILURE;
21017 		break;
21018 	    default:
21019 		break;
21020 	}
21021     }
21022     if (pctxt->nberrors != 0)
21023 	goto exit_error;
21024 
21025     /*
21026     * Now that all references are resolved we
21027     * can check for circularity of...
21028     * 1. the base axis of type definitions
21029     * 2. nested model group definitions
21030     * 3. nested attribute group definitions
21031     * TODO: check for circual substitution groups.
21032     */
21033     for (i = 0; i < nbItems; i++) {
21034 	item = items[i];
21035 	/*
21036 	* Let's better stop on the first error here.
21037 	*/
21038 	switch (item->type) {
21039 	    case XML_SCHEMA_TYPE_COMPLEX:
21040 	    case XML_SCHEMA_TYPE_SIMPLE:
21041 		xmlSchemaCheckTypeDefCircular(
21042 		    (xmlSchemaTypePtr) item, pctxt);
21043 		FIXHFAILURE;
21044 		if (pctxt->nberrors != 0)
21045 		    goto exit_error;
21046 		break;
21047 	    case XML_SCHEMA_TYPE_GROUP:
21048 		xmlSchemaCheckGroupDefCircular(
21049 		    (xmlSchemaModelGroupDefPtr) item, pctxt);
21050 		FIXHFAILURE;
21051 		if (pctxt->nberrors != 0)
21052 		    goto exit_error;
21053 		break;
21054 	    case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
21055 		xmlSchemaCheckAttrGroupCircular(
21056 		    (xmlSchemaAttributeGroupPtr) item, pctxt);
21057 		FIXHFAILURE;
21058 		if (pctxt->nberrors != 0)
21059 		    goto exit_error;
21060 		break;
21061 	    default:
21062 		break;
21063 	}
21064     }
21065     if (pctxt->nberrors != 0)
21066 	goto exit_error;
21067     /*
21068     * Model group definition references:
21069     * Such a reference is reflected by a particle at the component
21070     * level. Until now the 'term' of such particles pointed
21071     * to the model group definition; this was done, in order to
21072     * ease circularity checks. Now we need to set the 'term' of
21073     * such particles to the model group of the model group definition.
21074     */
21075     for (i = 0; i < nbItems; i++) {
21076 	item = items[i];
21077 	switch (item->type) {
21078 	    case XML_SCHEMA_TYPE_SEQUENCE:
21079 	    case XML_SCHEMA_TYPE_CHOICE:
21080 		xmlSchemaModelGroupToModelGroupDefFixup(pctxt,
21081 		    WXS_MODEL_GROUP_CAST item);
21082 		break;
21083 	    default:
21084 		break;
21085 	}
21086     }
21087     if (pctxt->nberrors != 0)
21088 	goto exit_error;
21089     /*
21090     * Expand attribute group references of attribute group definitions.
21091     */
21092     for (i = 0; i < nbItems; i++) {
21093 	item = items[i];
21094 	switch (item->type) {
21095             case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
21096 		if ((! WXS_ATTR_GROUP_EXPANDED(item)) &&
21097 		    WXS_ATTR_GROUP_HAS_REFS(item))
21098 		{
21099 		    xmlSchemaAttributeGroupExpandRefs(pctxt,
21100 			WXS_ATTR_GROUP_CAST item);
21101 		    FIXHFAILURE;
21102 		}
21103 		break;
21104 	    default:
21105 		break;
21106 	}
21107     }
21108     if (pctxt->nberrors != 0)
21109 	goto exit_error;
21110     /*
21111     * First compute the variety of simple types. This is needed as
21112     * a seperate step, since otherwise we won't be able to detect
21113     * circular union types in all cases.
21114     */
21115     for (i = 0; i < nbItems; i++) {
21116 	item = items[i];
21117 	switch (item->type) {
21118             case XML_SCHEMA_TYPE_SIMPLE:
21119 		if (WXS_IS_TYPE_NOT_FIXED_1((xmlSchemaTypePtr) item)) {
21120 		    xmlSchemaFixupSimpleTypeStageOne(pctxt,
21121 			(xmlSchemaTypePtr) item);
21122 		    FIXHFAILURE;
21123 		}
21124 		break;
21125 	    default:
21126 		break;
21127 	}
21128     }
21129     if (pctxt->nberrors != 0)
21130 	goto exit_error;
21131     /*
21132     * Detect circular union types. Note that this needs the variety to
21133     * be already computed.
21134     */
21135     for (i = 0; i < nbItems; i++) {
21136 	item = items[i];
21137 	switch (item->type) {
21138             case XML_SCHEMA_TYPE_SIMPLE:
21139 		if (((xmlSchemaTypePtr) item)->memberTypes != NULL) {
21140 		    xmlSchemaCheckUnionTypeDefCircular(pctxt,
21141 			(xmlSchemaTypePtr) item);
21142 		    FIXHFAILURE;
21143 		}
21144 		break;
21145 	    default:
21146 		break;
21147 	}
21148     }
21149     if (pctxt->nberrors != 0)
21150 	goto exit_error;
21151 
21152     /*
21153     * Do the complete type fixup for simple types.
21154     */
21155     for (i = 0; i < nbItems; i++) {
21156 	item = items[i];
21157 	switch (item->type) {
21158             case XML_SCHEMA_TYPE_SIMPLE:
21159 		if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
21160 		    xmlSchemaFixupSimpleTypeStageTwo(pctxt, WXS_TYPE_CAST item);
21161 		    FIXHFAILURE;
21162 		}
21163 		break;
21164 	    default:
21165 		break;
21166 	}
21167     }
21168     if (pctxt->nberrors != 0)
21169 	goto exit_error;
21170     /*
21171     * At this point we need build and check all simple types.
21172     */
21173     /*
21174     * Apply contraints for attribute declarations.
21175     */
21176     for (i = 0; i < nbItems; i++) {
21177 	item = items[i];
21178 	switch (item->type) {
21179 	    case XML_SCHEMA_TYPE_ATTRIBUTE:
21180 		xmlSchemaCheckAttrPropsCorrect(pctxt, WXS_ATTR_CAST item);
21181 		FIXHFAILURE;
21182 		break;
21183 	    default:
21184 		break;
21185 	}
21186     }
21187     if (pctxt->nberrors != 0)
21188 	goto exit_error;
21189     /*
21190     * Apply constraints for attribute uses.
21191     */
21192     for (i = 0; i < nbItems; i++) {
21193 	item = items[i];
21194 	switch (item->type) {
21195 	    case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
21196 		if (((xmlSchemaAttributeUsePtr)item)->defValue != NULL) {
21197 		    xmlSchemaCheckAttrUsePropsCorrect(pctxt,
21198 			WXS_ATTR_USE_CAST item);
21199 		    FIXHFAILURE;
21200 		}
21201 		break;
21202 	    default:
21203 		break;
21204 	}
21205     }
21206     if (pctxt->nberrors != 0)
21207 	goto exit_error;
21208 
21209     /*
21210     * Apply constraints for attribute group definitions.
21211     */
21212     for (i = 0; i < nbItems; i++) {
21213 	item = items[i];
21214 	switch (item->type) {
21215 	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
21216 	    if (( (WXS_ATTR_GROUP_CAST item)->attrUses != NULL) &&
21217 		( (WXS_LIST_CAST (WXS_ATTR_GROUP_CAST item)->attrUses)->nbItems > 1))
21218 	    {
21219 		xmlSchemaCheckAGPropsCorrect(pctxt, WXS_ATTR_GROUP_CAST item);
21220 		FIXHFAILURE;
21221 	    }
21222 	    break;
21223 	default:
21224 	    break;
21225 	}
21226     }
21227     if (pctxt->nberrors != 0)
21228 	goto exit_error;
21229 
21230     /*
21231     * Apply constraints for redefinitions.
21232     */
21233     if (WXS_CONSTRUCTOR(pctxt)->redefs != NULL)
21234 	xmlSchemaCheckSRCRedefineSecond(pctxt);
21235     if (pctxt->nberrors != 0)
21236 	goto exit_error;
21237 
21238     /*
21239     * Complex types are builded and checked.
21240     */
21241     for (i = 0; i < nbItems; i++) {
21242 	item = con->pending->items[i];
21243 	switch (item->type) {
21244 	    case XML_SCHEMA_TYPE_COMPLEX:
21245 		if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
21246 		    xmlSchemaFixupComplexType(pctxt, WXS_TYPE_CAST item);
21247 		    FIXHFAILURE;
21248 		}
21249 		break;
21250 	    default:
21251 		break;
21252 	}
21253     }
21254     if (pctxt->nberrors != 0)
21255 	goto exit_error;
21256 
21257     /*
21258     * The list could have changed, since xmlSchemaFixupComplexType()
21259     * will create particles and model groups in some cases.
21260     */
21261     items = (xmlSchemaTreeItemPtr *) con->pending->items;
21262     nbItems = con->pending->nbItems;
21263 
21264     /*
21265     * Apply some constraints for element declarations.
21266     */
21267     for (i = 0; i < nbItems; i++) {
21268 	item = items[i];
21269 	switch (item->type) {
21270 	    case XML_SCHEMA_TYPE_ELEMENT:
21271 		elemDecl = (xmlSchemaElementPtr) item;
21272 
21273 		if ((elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED) == 0)
21274 		{
21275 		    xmlSchemaCheckElementDeclComponent(
21276 			(xmlSchemaElementPtr) elemDecl, pctxt);
21277 		    FIXHFAILURE;
21278 		}
21279 
21280 #ifdef WXS_ELEM_DECL_CONS_ENABLED
21281 		/*
21282 		* Schema Component Constraint: Element Declarations Consistent
21283 		* Apply this constraint to local types of element declarations.
21284 		*/
21285 		if ((WXS_ELEM_TYPEDEF(elemDecl) != NULL) &&
21286 		    (WXS_IS_COMPLEX(WXS_ELEM_TYPEDEF(elemDecl))) &&
21287 		    (WXS_TYPE_IS_LOCAL(WXS_ELEM_TYPEDEF(elemDecl))))
21288 		{
21289 		    xmlSchemaCheckElementDeclConsistent(pctxt,
21290 			WXS_BASIC_CAST elemDecl,
21291 			WXS_TYPE_PARTICLE(WXS_ELEM_TYPEDEF(elemDecl)),
21292 			NULL, NULL, 0);
21293 		}
21294 #endif
21295 		break;
21296 	    default:
21297 		break;
21298 	}
21299     }
21300     if (pctxt->nberrors != 0)
21301 	goto exit_error;
21302 
21303     /*
21304     * Finally we can build the automaton from the content model of
21305     * complex types.
21306     */
21307 
21308     for (i = 0; i < nbItems; i++) {
21309 	item = items[i];
21310 	switch (item->type) {
21311 	    case XML_SCHEMA_TYPE_COMPLEX:
21312 		xmlSchemaBuildContentModel((xmlSchemaTypePtr) item, pctxt);
21313 		/* FIXHFAILURE; */
21314 		break;
21315 	    default:
21316 		break;
21317 	}
21318     }
21319     if (pctxt->nberrors != 0)
21320 	goto exit_error;
21321     /*
21322     * URGENT TODO: cos-element-consistent
21323     */
21324     goto exit;
21325 
21326 exit_error:
21327     ret = pctxt->err;
21328     goto exit;
21329 
21330 exit_failure:
21331     ret = -1;
21332 
21333 exit:
21334     /*
21335     * Reset the constructor. This is needed for XSI acquisition, since
21336     * those items will be processed over and over again for every XSI
21337     * if not cleared here.
21338     */
21339     con->bucket = oldbucket;
21340     con->pending->nbItems = 0;
21341     if (con->substGroups != NULL) {
21342 	xmlHashFree(con->substGroups, xmlSchemaSubstGroupFreeEntry);
21343 	con->substGroups = NULL;
21344     }
21345     if (con->redefs != NULL) {
21346 	xmlSchemaRedefListFree(con->redefs);
21347 	con->redefs = NULL;
21348     }
21349     return(ret);
21350 }
21351 /**
21352  * xmlSchemaParse:
21353  * @ctxt:  a schema validation context
21354  *
21355  * parse a schema definition resource and build an internal
21356  * XML Shema struture which can be used to validate instances.
21357  *
21358  * Returns the internal XML Schema structure built from the resource or
21359  *         NULL in case of error
21360  */
21361 xmlSchemaPtr
xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)21362 xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
21363 {
21364     xmlSchemaPtr mainSchema = NULL;
21365     xmlSchemaBucketPtr bucket = NULL;
21366     int res;
21367 
21368     /*
21369     * This one is used if the schema to be parsed was specified via
21370     * the API; i.e. not automatically by the validated instance document.
21371     */
21372 
21373     xmlSchemaInitTypes();
21374 
21375     if (ctxt == NULL)
21376         return (NULL);
21377 
21378     /* TODO: Init the context. Is this all we need?*/
21379     ctxt->nberrors = 0;
21380     ctxt->err = 0;
21381     ctxt->counter = 0;
21382 
21383     /* Create the *main* schema. */
21384     mainSchema = xmlSchemaNewSchema(ctxt);
21385     if (mainSchema == NULL)
21386 	goto exit_failure;
21387     /*
21388     * Create the schema constructor.
21389     */
21390     if (ctxt->constructor == NULL) {
21391 	ctxt->constructor = xmlSchemaConstructionCtxtCreate(ctxt->dict);
21392 	if (ctxt->constructor == NULL)
21393 	    return(NULL);
21394 	/* Take ownership of the constructor to be able to free it. */
21395 	ctxt->ownsConstructor = 1;
21396     }
21397     ctxt->constructor->mainSchema = mainSchema;
21398     /*
21399     * Locate and add the schema document.
21400     */
21401     res = xmlSchemaAddSchemaDoc(ctxt, XML_SCHEMA_SCHEMA_MAIN,
21402 	ctxt->URL, ctxt->doc, ctxt->buffer, ctxt->size, NULL,
21403 	NULL, NULL, &bucket);
21404     if (res == -1)
21405 	goto exit_failure;
21406     if (res != 0)
21407 	goto exit;
21408 
21409     if (bucket == NULL) {
21410 	/* TODO: Error code, actually we failed to *locate* the schema. */
21411 	if (ctxt->URL)
21412 	    xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21413 		NULL, NULL,
21414 		"Failed to locate the main schema resource at '%s'",
21415 		ctxt->URL, NULL);
21416 	else
21417 	    xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21418 		NULL, NULL,
21419 		"Failed to locate the main schema resource",
21420 		    NULL, NULL);
21421 	goto exit;
21422     }
21423     /* Then do the parsing for good. */
21424     if (xmlSchemaParseNewDocWithContext(ctxt, mainSchema, bucket) == -1)
21425 	goto exit_failure;
21426     if (ctxt->nberrors != 0)
21427 	goto exit;
21428 
21429     mainSchema->doc = bucket->doc;
21430     mainSchema->preserve = ctxt->preserve;
21431 
21432     ctxt->schema = mainSchema;
21433 
21434     if (xmlSchemaFixupComponents(ctxt, WXS_CONSTRUCTOR(ctxt)->mainBucket) == -1)
21435 	goto exit_failure;
21436 
21437     /*
21438     * TODO: This is not nice, since we cannot distinguish from the
21439     * result if there was an internal error or not.
21440     */
21441 exit:
21442     if (ctxt->nberrors != 0) {
21443 	if (mainSchema) {
21444 	    xmlSchemaFree(mainSchema);
21445 	    mainSchema = NULL;
21446 	}
21447 	if (ctxt->constructor) {
21448 	    xmlSchemaConstructionCtxtFree(ctxt->constructor);
21449 	    ctxt->constructor = NULL;
21450 	    ctxt->ownsConstructor = 0;
21451 	}
21452     }
21453     ctxt->schema = NULL;
21454     return(mainSchema);
21455 exit_failure:
21456     /*
21457     * Quite verbose, but should catch internal errors, which were
21458     * not communitated.
21459     */
21460     if (mainSchema) {
21461         xmlSchemaFree(mainSchema);
21462 	mainSchema = NULL;
21463     }
21464     if (ctxt->constructor) {
21465 	xmlSchemaConstructionCtxtFree(ctxt->constructor);
21466 	ctxt->constructor = NULL;
21467 	ctxt->ownsConstructor = 0;
21468     }
21469     PERROR_INT2("xmlSchemaParse",
21470 	"An internal error occurred");
21471     ctxt->schema = NULL;
21472     return(NULL);
21473 }
21474 
21475 /**
21476  * xmlSchemaSetParserErrors:
21477  * @ctxt:  a schema validation context
21478  * @err:  the error callback
21479  * @warn:  the warning callback
21480  * @ctx:  contextual data for the callbacks
21481  *
21482  * Set the callback functions used to handle errors for a validation context
21483  */
21484 void
xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,xmlSchemaValidityErrorFunc err,xmlSchemaValidityWarningFunc warn,void * ctx)21485 xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
21486                          xmlSchemaValidityErrorFunc err,
21487                          xmlSchemaValidityWarningFunc warn, void *ctx)
21488 {
21489     if (ctxt == NULL)
21490         return;
21491     ctxt->error = err;
21492     ctxt->warning = warn;
21493     ctxt->errCtxt = ctx;
21494     if (ctxt->vctxt != NULL)
21495 	xmlSchemaSetValidErrors(ctxt->vctxt, err, warn, ctx);
21496 }
21497 
21498 /**
21499  * xmlSchemaSetParserStructuredErrors:
21500  * @ctxt:  a schema parser context
21501  * @serror:  the structured error function
21502  * @ctx: the functions context
21503  *
21504  * Set the structured error callback
21505  */
21506 void
xmlSchemaSetParserStructuredErrors(xmlSchemaParserCtxtPtr ctxt,xmlStructuredErrorFunc serror,void * ctx)21507 xmlSchemaSetParserStructuredErrors(xmlSchemaParserCtxtPtr ctxt,
21508 				   xmlStructuredErrorFunc serror,
21509 				   void *ctx)
21510 {
21511     if (ctxt == NULL)
21512 	return;
21513     ctxt->serror = serror;
21514     ctxt->errCtxt = ctx;
21515     if (ctxt->vctxt != NULL)
21516 	xmlSchemaSetValidStructuredErrors(ctxt->vctxt, serror, ctx);
21517 }
21518 
21519 /**
21520  * xmlSchemaGetParserErrors:
21521  * @ctxt:  a XMl-Schema parser context
21522  * @err: the error callback result
21523  * @warn: the warning callback result
21524  * @ctx: contextual data for the callbacks result
21525  *
21526  * Get the callback information used to handle errors for a parser context
21527  *
21528  * Returns -1 in case of failure, 0 otherwise
21529  */
21530 int
xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,xmlSchemaValidityErrorFunc * err,xmlSchemaValidityWarningFunc * warn,void ** ctx)21531 xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
21532 			 xmlSchemaValidityErrorFunc * err,
21533 			 xmlSchemaValidityWarningFunc * warn, void **ctx)
21534 {
21535 	if (ctxt == NULL)
21536 		return(-1);
21537 	if (err != NULL)
21538 		*err = ctxt->error;
21539 	if (warn != NULL)
21540 		*warn = ctxt->warning;
21541 	if (ctx != NULL)
21542 		*ctx = ctxt->errCtxt;
21543 	return(0);
21544 }
21545 
21546 /**
21547  * xmlSchemaFacetTypeToString:
21548  * @type:  the facet type
21549  *
21550  * Convert the xmlSchemaTypeType to a char string.
21551  *
21552  * Returns the char string representation of the facet type if the
21553  *     type is a facet and an "Internal Error" string otherwise.
21554  */
21555 static const xmlChar *
xmlSchemaFacetTypeToString(xmlSchemaTypeType type)21556 xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
21557 {
21558     switch (type) {
21559         case XML_SCHEMA_FACET_PATTERN:
21560             return (BAD_CAST "pattern");
21561         case XML_SCHEMA_FACET_MAXEXCLUSIVE:
21562             return (BAD_CAST "maxExclusive");
21563         case XML_SCHEMA_FACET_MAXINCLUSIVE:
21564             return (BAD_CAST "maxInclusive");
21565         case XML_SCHEMA_FACET_MINEXCLUSIVE:
21566             return (BAD_CAST "minExclusive");
21567         case XML_SCHEMA_FACET_MININCLUSIVE:
21568             return (BAD_CAST "minInclusive");
21569         case XML_SCHEMA_FACET_WHITESPACE:
21570             return (BAD_CAST "whiteSpace");
21571         case XML_SCHEMA_FACET_ENUMERATION:
21572             return (BAD_CAST "enumeration");
21573         case XML_SCHEMA_FACET_LENGTH:
21574             return (BAD_CAST "length");
21575         case XML_SCHEMA_FACET_MAXLENGTH:
21576             return (BAD_CAST "maxLength");
21577         case XML_SCHEMA_FACET_MINLENGTH:
21578             return (BAD_CAST "minLength");
21579         case XML_SCHEMA_FACET_TOTALDIGITS:
21580             return (BAD_CAST "totalDigits");
21581         case XML_SCHEMA_FACET_FRACTIONDIGITS:
21582             return (BAD_CAST "fractionDigits");
21583         default:
21584             break;
21585     }
21586     return (BAD_CAST "Internal Error");
21587 }
21588 
21589 static xmlSchemaWhitespaceValueType
xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)21590 xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
21591 {
21592     /*
21593     * The normalization type can be changed only for types which are derived
21594     * from xsd:string.
21595     */
21596     if (type->type == XML_SCHEMA_TYPE_BASIC) {
21597 	/*
21598 	* Note that we assume a whitespace of preserve for anySimpleType.
21599 	*/
21600 	if ((type->builtInType == XML_SCHEMAS_STRING) ||
21601 	    (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
21602 	    return(XML_SCHEMA_WHITESPACE_PRESERVE);
21603 	else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
21604 	    return(XML_SCHEMA_WHITESPACE_REPLACE);
21605 	else {
21606 	    /*
21607 	    * For all `atomic` datatypes other than string (and types `derived`
21608 	    * by `restriction` from it) the value of whiteSpace is fixed to
21609 	    * collapse
21610 	    * Note that this includes built-in list datatypes.
21611 	    */
21612 	    return(XML_SCHEMA_WHITESPACE_COLLAPSE);
21613 	}
21614     } else if (WXS_IS_LIST(type)) {
21615 	/*
21616 	* For list types the facet "whiteSpace" is fixed to "collapse".
21617 	*/
21618 	return (XML_SCHEMA_WHITESPACE_COLLAPSE);
21619     } else if (WXS_IS_UNION(type)) {
21620 	return (XML_SCHEMA_WHITESPACE_UNKNOWN);
21621     } else if (WXS_IS_ATOMIC(type)) {
21622 	if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE)
21623 	    return (XML_SCHEMA_WHITESPACE_PRESERVE);
21624 	else if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_REPLACE)
21625 	    return (XML_SCHEMA_WHITESPACE_REPLACE);
21626 	else
21627 	    return (XML_SCHEMA_WHITESPACE_COLLAPSE);
21628     }
21629     return (-1);
21630 }
21631 
21632 /************************************************************************
21633  *									*
21634  *			Simple type validation				*
21635  *									*
21636  ************************************************************************/
21637 
21638 
21639 /************************************************************************
21640  *									*
21641  *			DOM Validation code				*
21642  *									*
21643  ************************************************************************/
21644 
21645 /**
21646  * xmlSchemaAssembleByLocation:
21647  * @pctxt:  a schema parser context
21648  * @vctxt:  a schema validation context
21649  * @schema: the existing schema
21650  * @node: the node that fired the assembling
21651  * @nsName: the namespace name of the new schema
21652  * @location: the location of the schema
21653  *
21654  * Expands an existing schema by an additional schema.
21655  *
21656  * Returns 0 if the new schema is correct, a positive error code
21657  * number otherwise and -1 in case of an internal or API error.
21658  */
21659 static int
xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,xmlSchemaPtr schema,xmlNodePtr node,const xmlChar * nsName,const xmlChar * location)21660 xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
21661 			    xmlSchemaPtr schema,
21662 			    xmlNodePtr node,
21663 			    const xmlChar *nsName,
21664 			    const xmlChar *location)
21665 {
21666     int ret = 0;
21667     xmlSchemaParserCtxtPtr pctxt;
21668     xmlSchemaBucketPtr bucket = NULL;
21669 
21670     if ((vctxt == NULL) || (schema == NULL))
21671 	return (-1);
21672 
21673     if (vctxt->pctxt == NULL) {
21674 	VERROR_INT("xmlSchemaAssembleByLocation",
21675 	    "no parser context available");
21676 	return(-1);
21677     }
21678     pctxt = vctxt->pctxt;
21679     if (pctxt->constructor == NULL) {
21680 	PERROR_INT("xmlSchemaAssembleByLocation",
21681 	    "no constructor");
21682 	return(-1);
21683     }
21684     /*
21685     * Acquire the schema document.
21686     */
21687     location = xmlSchemaBuildAbsoluteURI(pctxt->dict,
21688 	location, node);
21689     /*
21690     * Note that we pass XML_SCHEMA_SCHEMA_IMPORT here;
21691     * the process will automatically change this to
21692     * XML_SCHEMA_SCHEMA_MAIN if it is the first schema document.
21693     */
21694     ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
21695 	location, NULL, NULL, 0, node, NULL, nsName,
21696 	&bucket);
21697     if (ret != 0)
21698 	return(ret);
21699     if (bucket == NULL) {
21700 	/*
21701 	* Generate a warning that the document could not be located.
21702 	*/
21703 	xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC,
21704 	    node, NULL,
21705 	    "The document at location '%s' could not be acquired",
21706 	    location, NULL, NULL);
21707 	return(ret);
21708     }
21709     /*
21710     * The first located schema will be handled as if all other
21711     * schemas imported by XSI were imported by this first schema.
21712     */
21713     if ((bucket != NULL) &&
21714 	(WXS_CONSTRUCTOR(pctxt)->bucket == NULL))
21715 	WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
21716     /*
21717     * TODO: Is this handled like an import? I.e. is it not an error
21718     * if the schema cannot be located?
21719     */
21720     if ((bucket == NULL) || (! CAN_PARSE_SCHEMA(bucket)))
21721 	return(0);
21722     /*
21723     * We will reuse the parser context for every schema imported
21724     * directly via XSI. So reset the context.
21725     */
21726     pctxt->nberrors = 0;
21727     pctxt->err = 0;
21728     pctxt->doc = bucket->doc;
21729 
21730     ret = xmlSchemaParseNewDocWithContext(pctxt, schema, bucket);
21731     if (ret == -1) {
21732 	pctxt->doc = NULL;
21733 	goto exit_failure;
21734     }
21735     /* Paranoid error channelling. */
21736     if ((ret == 0) && (pctxt->nberrors != 0))
21737 	ret = pctxt->err;
21738     if (pctxt->nberrors == 0) {
21739 	/*
21740 	* Only bother to fixup pending components, if there was
21741 	* no error yet.
21742 	* For every XSI acquired schema (and its sub-schemata) we will
21743 	* fixup the components.
21744 	*/
21745 	xmlSchemaFixupComponents(pctxt, bucket);
21746 	ret = pctxt->err;
21747 	/*
21748 	* Not nice, but we need somehow to channel the schema parser
21749 	* error to the validation context.
21750 	*/
21751 	if ((ret != 0) && (vctxt->err == 0))
21752 	    vctxt->err = ret;
21753 	vctxt->nberrors += pctxt->nberrors;
21754     } else {
21755 	/* Add to validation error sum. */
21756 	vctxt->nberrors += pctxt->nberrors;
21757     }
21758     pctxt->doc = NULL;
21759     return(ret);
21760 exit_failure:
21761     pctxt->doc = NULL;
21762     return (-1);
21763 }
21764 
21765 static xmlSchemaAttrInfoPtr
xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,int metaType)21766 xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,
21767 			 int metaType)
21768 {
21769     if (vctxt->nbAttrInfos == 0)
21770 	return (NULL);
21771     {
21772 	int i;
21773 	xmlSchemaAttrInfoPtr iattr;
21774 
21775 	for (i = 0; i < vctxt->nbAttrInfos; i++) {
21776 	    iattr = vctxt->attrInfos[i];
21777 	    if (iattr->metaType == metaType)
21778 		return (iattr);
21779 	}
21780 
21781     }
21782     return (NULL);
21783 }
21784 
21785 /**
21786  * xmlSchemaAssembleByXSI:
21787  * @vctxt:  a schema validation context
21788  *
21789  * Expands an existing schema by an additional schema using
21790  * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
21791  * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
21792  * must be set to 1.
21793  *
21794  * Returns 0 if the new schema is correct, a positive error code
21795  * number otherwise and -1 in case of an internal or API error.
21796  */
21797 static int
xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)21798 xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)
21799 {
21800     const xmlChar *cur, *end;
21801     const xmlChar *nsname = NULL, *location;
21802     int count = 0;
21803     int ret = 0;
21804     xmlSchemaAttrInfoPtr iattr;
21805 
21806     /*
21807     * Parse the value; we will assume an even number of values
21808     * to be given (this is how Xerces and XSV work).
21809     *
21810     * URGENT TODO: !! This needs to work for both
21811     * @noNamespaceSchemaLocation AND @schemaLocation on the same
21812     * element !!
21813     */
21814     iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21815 	XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC);
21816     if (iattr == NULL)
21817 	iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21818 	XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC);
21819     if (iattr == NULL)
21820 	return (0);
21821     cur = iattr->value;
21822     do {
21823 	/*
21824 	* TODO: Move the string parsing mechanism away from here.
21825 	*/
21826 	if (iattr->metaType == XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC) {
21827 	    /*
21828 	    * Get the namespace name.
21829 	    */
21830 	    while (IS_BLANK_CH(*cur))
21831 		cur++;
21832 	    end = cur;
21833 	    while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21834 		end++;
21835 	    if (end == cur)
21836 		break;
21837 	    count++; /* TODO: Don't use the schema's dict. */
21838 	    nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
21839 	    cur = end;
21840 	}
21841 	/*
21842 	* Get the URI.
21843 	*/
21844 	while (IS_BLANK_CH(*cur))
21845 	    cur++;
21846 	end = cur;
21847 	while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21848 	    end++;
21849 	if (end == cur) {
21850 	    if (iattr->metaType ==
21851 		XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC)
21852 	    {
21853 		/*
21854 		* If using @schemaLocation then tuples are expected.
21855 		* I.e. the namespace name *and* the document's URI.
21856 		*/
21857 		xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC,
21858 		    iattr->node, NULL,
21859 		    "The value must consist of tuples: the target namespace "
21860 		    "name and the document's URI", NULL, NULL, NULL);
21861 	    }
21862 	    break;
21863 	}
21864 	count++; /* TODO: Don't use the schema's dict. */
21865 	location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
21866 	cur = end;
21867 	ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
21868 	    iattr->node, nsname, location);
21869 	if (ret == -1) {
21870 	    VERROR_INT("xmlSchemaAssembleByXSI",
21871 		"assembling schemata");
21872 	    return (-1);
21873 	}
21874     } while (*cur != 0);
21875     return (ret);
21876 }
21877 
21878 static const xmlChar *
xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,const xmlChar * prefix)21879 xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,
21880 			 const xmlChar *prefix)
21881 {
21882     if (vctxt->sax != NULL) {
21883 	int i, j;
21884 	xmlSchemaNodeInfoPtr inode;
21885 
21886 	for (i = vctxt->depth; i >= 0; i--) {
21887 	    if (vctxt->elemInfos[i]->nbNsBindings != 0) {
21888 		inode = vctxt->elemInfos[i];
21889 		for (j = 0; j < inode->nbNsBindings * 2; j += 2) {
21890 		    if (((prefix == NULL) &&
21891 			    (inode->nsBindings[j] == NULL)) ||
21892 			((prefix != NULL) && xmlStrEqual(prefix,
21893 			    inode->nsBindings[j]))) {
21894 
21895 			/*
21896 			* Note that the namespace bindings are already
21897 			* in a string dict.
21898 			*/
21899 			return (inode->nsBindings[j+1]);
21900 		    }
21901 		}
21902 	    }
21903 	}
21904 	return (NULL);
21905 #ifdef LIBXML_READER_ENABLED
21906     } else if (vctxt->reader != NULL) {
21907 	xmlChar *nsName;
21908 
21909 	nsName = xmlTextReaderLookupNamespace(vctxt->reader, prefix);
21910 	if (nsName != NULL) {
21911 	    const xmlChar *ret;
21912 
21913 	    ret = xmlDictLookup(vctxt->dict, nsName, -1);
21914 	    xmlFree(nsName);
21915 	    return (ret);
21916 	} else
21917 	    return (NULL);
21918 #endif
21919     } else {
21920 	xmlNsPtr ns;
21921 
21922 	if ((vctxt->inode->node == NULL) ||
21923 	    (vctxt->inode->node->doc == NULL)) {
21924 	    VERROR_INT("xmlSchemaLookupNamespace",
21925 		"no node or node's doc avaliable");
21926 	    return (NULL);
21927 	}
21928 	ns = xmlSearchNs(vctxt->inode->node->doc,
21929 	    vctxt->inode->node, prefix);
21930 	if (ns != NULL)
21931 	    return (ns->href);
21932 	return (NULL);
21933     }
21934 }
21935 
21936 /*
21937 * This one works on the schema of the validation context.
21938 */
21939 static int
xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,xmlSchemaPtr schema,xmlNodePtr node,const xmlChar * value,xmlSchemaValPtr * val,int valNeeded)21940 xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
21941 			  xmlSchemaPtr schema,
21942 			  xmlNodePtr node,
21943 			  const xmlChar *value,
21944 			  xmlSchemaValPtr *val,
21945 			  int valNeeded)
21946 {
21947     int ret;
21948 
21949     if (vctxt && (vctxt->schema == NULL)) {
21950 	VERROR_INT("xmlSchemaValidateNotation",
21951 	    "a schema is needed on the validation context");
21952 	return (-1);
21953     }
21954     ret = xmlValidateQName(value, 1);
21955     if (ret != 0)
21956 	return (ret);
21957     {
21958 	xmlChar *localName = NULL;
21959 	xmlChar *prefix = NULL;
21960 
21961 	localName = xmlSplitQName2(value, &prefix);
21962 	if (prefix != NULL) {
21963 	    const xmlChar *nsName = NULL;
21964 
21965 	    if (vctxt != NULL)
21966 		nsName = xmlSchemaLookupNamespace(vctxt, BAD_CAST prefix);
21967 	    else if (node != NULL) {
21968 		xmlNsPtr ns = xmlSearchNs(node->doc, node, prefix);
21969 		if (ns != NULL)
21970 		    nsName = ns->href;
21971 	    } else {
21972 		xmlFree(prefix);
21973 		xmlFree(localName);
21974 		return (1);
21975 	    }
21976 	    if (nsName == NULL) {
21977 		xmlFree(prefix);
21978 		xmlFree(localName);
21979 		return (1);
21980 	    }
21981 	    if (xmlSchemaGetNotation(schema, localName, nsName) != NULL) {
21982 		if ((valNeeded) && (val != NULL)) {
21983 		    (*val) = xmlSchemaNewNOTATIONValue(xmlStrdup(localName),
21984 						       xmlStrdup(nsName));
21985 		    if (*val == NULL)
21986 			ret = -1;
21987 		}
21988 	    } else
21989 		ret = 1;
21990 	    xmlFree(prefix);
21991 	    xmlFree(localName);
21992 	} else {
21993 	    if (xmlSchemaGetNotation(schema, value, NULL) != NULL) {
21994 		if (valNeeded && (val != NULL)) {
21995 		    (*val) = xmlSchemaNewNOTATIONValue(
21996 			BAD_CAST xmlStrdup(value), NULL);
21997 		    if (*val == NULL)
21998 			ret = -1;
21999 		}
22000 	    } else
22001 		return (1);
22002 	}
22003     }
22004     return (ret);
22005 }
22006 
22007 static int
xmlSchemaVAddNodeQName(xmlSchemaValidCtxtPtr vctxt,const xmlChar * lname,const xmlChar * nsname)22008 xmlSchemaVAddNodeQName(xmlSchemaValidCtxtPtr vctxt,
22009 		       const xmlChar* lname,
22010 		       const xmlChar* nsname)
22011 {
22012     int i;
22013 
22014     lname = xmlDictLookup(vctxt->dict, lname, -1);
22015     if (lname == NULL)
22016 	return(-1);
22017     if (nsname != NULL) {
22018 	nsname = xmlDictLookup(vctxt->dict, nsname, -1);
22019 	if (nsname == NULL)
22020 	    return(-1);
22021     }
22022     for (i = 0; i < vctxt->nodeQNames->nbItems; i += 2) {
22023 	if ((vctxt->nodeQNames->items [i] == lname) &&
22024 	    (vctxt->nodeQNames->items[i +1] == nsname))
22025 	    /* Already there */
22026 	    return(i);
22027     }
22028     /* Add new entry. */
22029     i = vctxt->nodeQNames->nbItems;
22030     xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) lname);
22031     xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) nsname);
22032     return(i);
22033 }
22034 
22035 /************************************************************************
22036  *									*
22037  *  Validation of identity-constraints (IDC)                            *
22038  *									*
22039  ************************************************************************/
22040 
22041 /**
22042  * xmlSchemaAugmentIDC:
22043  * @idcDef: the IDC definition
22044  *
22045  * Creates an augmented IDC definition item.
22046  *
22047  * Returns the item, or NULL on internal errors.
22048  */
22049 static void
xmlSchemaAugmentIDC(void * payload,void * data,const xmlChar * name ATTRIBUTE_UNUSED)22050 xmlSchemaAugmentIDC(void *payload, void *data,
22051                     const xmlChar *name ATTRIBUTE_UNUSED)
22052 {
22053     xmlSchemaIDCPtr idcDef = (xmlSchemaIDCPtr) payload;
22054     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) data;
22055     xmlSchemaIDCAugPtr aidc;
22056 
22057     aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
22058     if (aidc == NULL) {
22059 	xmlSchemaVErrMemory(vctxt,
22060 	    "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
22061 	    NULL);
22062 	return;
22063     }
22064     aidc->keyrefDepth = -1;
22065     aidc->def = idcDef;
22066     aidc->next = NULL;
22067     if (vctxt->aidcs == NULL)
22068 	vctxt->aidcs = aidc;
22069     else {
22070 	aidc->next = vctxt->aidcs;
22071 	vctxt->aidcs = aidc;
22072     }
22073     /*
22074     * Save if we have keyrefs at all.
22075     */
22076     if ((vctxt->hasKeyrefs == 0) &&
22077 	(idcDef->type == XML_SCHEMA_TYPE_IDC_KEYREF))
22078 	vctxt->hasKeyrefs = 1;
22079 }
22080 
22081 /**
22082  * xmlSchemaAugmentImportedIDC:
22083  * @imported: the imported schema
22084  *
22085  * Creates an augmented IDC definition for the imported schema.
22086  */
22087 static void
xmlSchemaAugmentImportedIDC(void * payload,void * data,const xmlChar * name ATTRIBUTE_UNUSED)22088 xmlSchemaAugmentImportedIDC(void *payload, void *data,
22089                             const xmlChar *name ATTRIBUTE_UNUSED) {
22090     xmlSchemaImportPtr imported = (xmlSchemaImportPtr) payload;
22091     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) data;
22092     if (imported->schema->idcDef != NULL) {
22093 	    xmlHashScan(imported->schema->idcDef, xmlSchemaAugmentIDC, vctxt);
22094     }
22095 }
22096 
22097 /**
22098  * xmlSchemaIDCNewBinding:
22099  * @idcDef: the IDC definition of this binding
22100  *
22101  * Creates a new IDC binding.
22102  *
22103  * Returns the new IDC binding, NULL on internal errors.
22104  */
22105 static xmlSchemaPSVIIDCBindingPtr
xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)22106 xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
22107 {
22108     xmlSchemaPSVIIDCBindingPtr ret;
22109 
22110     ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
22111 	    sizeof(xmlSchemaPSVIIDCBinding));
22112     if (ret == NULL) {
22113 	xmlSchemaVErrMemory(NULL,
22114 	    "allocating a PSVI IDC binding item", NULL);
22115 	return (NULL);
22116     }
22117     memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
22118     ret->definition = idcDef;
22119     return (ret);
22120 }
22121 
22122 /**
22123  * xmlSchemaIDCStoreNodeTableItem:
22124  * @vctxt: the WXS validation context
22125  * @item: the IDC node table item
22126  *
22127  * The validation context is used to store IDC node table items.
22128  * They are stored to avoid copying them if IDC node-tables are merged
22129  * with corresponding parent IDC node-tables (bubbling).
22130  *
22131  * Returns 0 if succeeded, -1 on internal errors.
22132  */
22133 static int
xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,xmlSchemaPSVIIDCNodePtr item)22134 xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
22135 			       xmlSchemaPSVIIDCNodePtr item)
22136 {
22137     /*
22138     * Add to gobal list.
22139     */
22140     if (vctxt->idcNodes == NULL) {
22141 	vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
22142 	    xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
22143 	if (vctxt->idcNodes == NULL) {
22144 	    xmlSchemaVErrMemory(vctxt,
22145 		"allocating the IDC node table item list", NULL);
22146 	    return (-1);
22147 	}
22148 	vctxt->sizeIdcNodes = 20;
22149     } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
22150 	vctxt->sizeIdcNodes *= 2;
22151 	vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
22152 	    xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
22153 	    sizeof(xmlSchemaPSVIIDCNodePtr));
22154 	if (vctxt->idcNodes == NULL) {
22155 	    xmlSchemaVErrMemory(vctxt,
22156 		"re-allocating the IDC node table item list", NULL);
22157 	    return (-1);
22158 	}
22159     }
22160     vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
22161 
22162     return (0);
22163 }
22164 
22165 /**
22166  * xmlSchemaIDCStoreKey:
22167  * @vctxt: the WXS validation context
22168  * @item: the IDC key
22169  *
22170  * The validation context is used to store an IDC key.
22171  *
22172  * Returns 0 if succeeded, -1 on internal errors.
22173  */
22174 static int
xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,xmlSchemaPSVIIDCKeyPtr key)22175 xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
22176 		     xmlSchemaPSVIIDCKeyPtr key)
22177 {
22178     /*
22179     * Add to gobal list.
22180     */
22181     if (vctxt->idcKeys == NULL) {
22182 	vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
22183 	    xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
22184 	if (vctxt->idcKeys == NULL) {
22185 	    xmlSchemaVErrMemory(vctxt,
22186 		"allocating the IDC key storage list", NULL);
22187 	    return (-1);
22188 	}
22189 	vctxt->sizeIdcKeys = 40;
22190     } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
22191 	vctxt->sizeIdcKeys *= 2;
22192 	vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
22193 	    xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
22194 	    sizeof(xmlSchemaPSVIIDCKeyPtr));
22195 	if (vctxt->idcKeys == NULL) {
22196 	    xmlSchemaVErrMemory(vctxt,
22197 		"re-allocating the IDC key storage list", NULL);
22198 	    return (-1);
22199 	}
22200     }
22201     vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
22202 
22203     return (0);
22204 }
22205 
22206 /**
22207  * xmlSchemaIDCAppendNodeTableItem:
22208  * @bind: the IDC binding
22209  * @ntItem: the node-table item
22210  *
22211  * Appends the IDC node-table item to the binding.
22212  *
22213  * Returns 0 on success and -1 on internal errors.
22214  */
22215 static int
xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,xmlSchemaPSVIIDCNodePtr ntItem)22216 xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
22217 				xmlSchemaPSVIIDCNodePtr ntItem)
22218 {
22219     if (bind->nodeTable == NULL) {
22220 	bind->sizeNodes = 10;
22221 	bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
22222 	    xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
22223 	if (bind->nodeTable == NULL) {
22224 	    xmlSchemaVErrMemory(NULL,
22225 		"allocating an array of IDC node-table items", NULL);
22226 	    return(-1);
22227 	}
22228     } else if (bind->sizeNodes <= bind->nbNodes) {
22229 	bind->sizeNodes *= 2;
22230 	bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
22231 	    xmlRealloc(bind->nodeTable, bind->sizeNodes *
22232 		sizeof(xmlSchemaPSVIIDCNodePtr));
22233 	if (bind->nodeTable == NULL) {
22234 	    xmlSchemaVErrMemory(NULL,
22235 		"re-allocating an array of IDC node-table items", NULL);
22236 	    return(-1);
22237 	}
22238     }
22239     bind->nodeTable[bind->nbNodes++] = ntItem;
22240     return(0);
22241 }
22242 
22243 /**
22244  * xmlSchemaIDCAcquireBinding:
22245  * @vctxt: the WXS validation context
22246  * @matcher: the IDC matcher
22247  *
22248  * Looks up an PSVI IDC binding, for the IDC definition and
22249  * of the given matcher. If none found, a new one is created
22250  * and added to the IDC table.
22251  *
22252  * Returns an IDC binding or NULL on internal errors.
22253  */
22254 static xmlSchemaPSVIIDCBindingPtr
xmlSchemaIDCAcquireBinding(xmlSchemaValidCtxtPtr vctxt,xmlSchemaIDCMatcherPtr matcher)22255 xmlSchemaIDCAcquireBinding(xmlSchemaValidCtxtPtr vctxt,
22256 			  xmlSchemaIDCMatcherPtr matcher)
22257 {
22258     xmlSchemaNodeInfoPtr ielem;
22259 
22260     ielem = vctxt->elemInfos[matcher->depth];
22261 
22262     if (ielem->idcTable == NULL) {
22263 	ielem->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
22264 	if (ielem->idcTable == NULL)
22265 	    return (NULL);
22266 	return(ielem->idcTable);
22267     } else {
22268 	xmlSchemaPSVIIDCBindingPtr bind = NULL;
22269 
22270 	bind = ielem->idcTable;
22271 	do {
22272 	    if (bind->definition == matcher->aidc->def)
22273 		return(bind);
22274 	    if (bind->next == NULL) {
22275 		bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
22276 		if (bind->next == NULL)
22277 		    return (NULL);
22278 		return(bind->next);
22279 	    }
22280 	    bind = bind->next;
22281 	} while (bind != NULL);
22282     }
22283     return (NULL);
22284 }
22285 
22286 static xmlSchemaItemListPtr
xmlSchemaIDCAcquireTargetList(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,xmlSchemaIDCMatcherPtr matcher)22287 xmlSchemaIDCAcquireTargetList(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
22288 			     xmlSchemaIDCMatcherPtr matcher)
22289 {
22290     if (matcher->targets == NULL)
22291 	matcher->targets = xmlSchemaItemListCreate();
22292     return(matcher->targets);
22293 }
22294 
22295 /**
22296  * xmlSchemaIDCFreeKey:
22297  * @key: the IDC key
22298  *
22299  * Frees an IDC key together with its compiled value.
22300  */
22301 static void
xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)22302 xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
22303 {
22304     if (key->val != NULL)
22305 	xmlSchemaFreeValue(key->val);
22306     xmlFree(key);
22307 }
22308 
22309 /**
22310  * xmlSchemaIDCFreeBinding:
22311  *
22312  * Frees an IDC binding. Note that the node table-items
22313  * are not freed.
22314  */
22315 static void
xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)22316 xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
22317 {
22318     if (bind->nodeTable != NULL)
22319 	xmlFree(bind->nodeTable);
22320     if (bind->dupls != NULL)
22321 	xmlSchemaItemListFree(bind->dupls);
22322     xmlFree(bind);
22323 }
22324 
22325 /**
22326  * xmlSchemaIDCFreeIDCTable:
22327  * @bind: the first IDC binding in the list
22328  *
22329  * Frees an IDC table, i.e. all the IDC bindings in the list.
22330  */
22331 static void
xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)22332 xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
22333 {
22334     xmlSchemaPSVIIDCBindingPtr prev;
22335 
22336     while (bind != NULL) {
22337 	prev = bind;
22338 	bind = bind->next;
22339 	xmlSchemaIDCFreeBinding(prev);
22340     }
22341 }
22342 
22343 /**
22344  * xmlSchemaIDCFreeMatcherList:
22345  * @matcher: the first IDC matcher in the list
22346  *
22347  * Frees a list of IDC matchers.
22348  */
22349 static void
xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)22350 xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
22351 {
22352     xmlSchemaIDCMatcherPtr next;
22353 
22354     while (matcher != NULL) {
22355 	next = matcher->next;
22356 	if (matcher->keySeqs != NULL) {
22357 	    int i;
22358 	    for (i = 0; i < matcher->sizeKeySeqs; i++)
22359 		if (matcher->keySeqs[i] != NULL)
22360 		    xmlFree(matcher->keySeqs[i]);
22361 	    xmlFree(matcher->keySeqs);
22362 	}
22363 	if (matcher->targets != NULL) {
22364 	    if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
22365 		int i;
22366 		xmlSchemaPSVIIDCNodePtr idcNode;
22367 		/*
22368 		* Node-table items for keyrefs are not stored globally
22369 		* to the validation context, since they are not bubbled.
22370 		* We need to free them here.
22371 		*/
22372 		for (i = 0; i < matcher->targets->nbItems; i++) {
22373 		    idcNode =
22374 			(xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
22375 		    xmlFree(idcNode->keys);
22376 		    xmlFree(idcNode);
22377 		}
22378 	    }
22379 	    xmlSchemaItemListFree(matcher->targets);
22380 	}
22381 	xmlFree(matcher);
22382 	matcher = next;
22383     }
22384 }
22385 
22386 /**
22387  * xmlSchemaIDCReleaseMatcherList:
22388  * @vctxt: the WXS validation context
22389  * @matcher: the first IDC matcher in the list
22390  *
22391  * Caches a list of IDC matchers for reuse.
22392  */
22393 static void
xmlSchemaIDCReleaseMatcherList(xmlSchemaValidCtxtPtr vctxt,xmlSchemaIDCMatcherPtr matcher)22394 xmlSchemaIDCReleaseMatcherList(xmlSchemaValidCtxtPtr vctxt,
22395 			       xmlSchemaIDCMatcherPtr matcher)
22396 {
22397     xmlSchemaIDCMatcherPtr next;
22398 
22399     while (matcher != NULL) {
22400 	next = matcher->next;
22401 	if (matcher->keySeqs != NULL) {
22402 	    int i;
22403 	    /*
22404 	    * Don't free the array, but only the content.
22405 	    */
22406 	    for (i = 0; i < matcher->sizeKeySeqs; i++)
22407 		if (matcher->keySeqs[i] != NULL) {
22408 		    xmlFree(matcher->keySeqs[i]);
22409 		    matcher->keySeqs[i] = NULL;
22410 		}
22411 	}
22412 	if (matcher->targets) {
22413 	    if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
22414 		int i;
22415 		xmlSchemaPSVIIDCNodePtr idcNode;
22416 		/*
22417 		* Node-table items for keyrefs are not stored globally
22418 		* to the validation context, since they are not bubbled.
22419 		* We need to free them here.
22420 		*/
22421 		for (i = 0; i < matcher->targets->nbItems; i++) {
22422 		    idcNode =
22423 			(xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
22424 		    xmlFree(idcNode->keys);
22425 		    xmlFree(idcNode);
22426 		}
22427 	    }
22428 	    xmlSchemaItemListFree(matcher->targets);
22429 	    matcher->targets = NULL;
22430 	}
22431 	matcher->next = NULL;
22432 	/*
22433 	* Cache the matcher.
22434 	*/
22435 	if (vctxt->idcMatcherCache != NULL)
22436 	    matcher->nextCached = vctxt->idcMatcherCache;
22437 	vctxt->idcMatcherCache = matcher;
22438 
22439 	matcher = next;
22440     }
22441 }
22442 
22443 /**
22444  * xmlSchemaIDCAddStateObject:
22445  * @vctxt: the WXS validation context
22446  * @matcher: the IDC matcher
22447  * @sel: the XPath information
22448  * @parent: the parent "selector" state object if any
22449  * @type: "selector" or "field"
22450  *
22451  * Creates/reuses and activates state objects for the given
22452  * XPath information; if the XPath expression consists of unions,
22453  * multiple state objects are created for every unioned expression.
22454  *
22455  * Returns 0 on success and -1 on internal errors.
22456  */
22457 static int
xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,xmlSchemaIDCMatcherPtr matcher,xmlSchemaIDCSelectPtr sel,int type)22458 xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
22459 			xmlSchemaIDCMatcherPtr matcher,
22460 			xmlSchemaIDCSelectPtr sel,
22461 			int type)
22462 {
22463     xmlSchemaIDCStateObjPtr sto;
22464 
22465     /*
22466     * Reuse the state objects from the pool.
22467     */
22468     if (vctxt->xpathStatePool != NULL) {
22469 	sto = vctxt->xpathStatePool;
22470 	vctxt->xpathStatePool = sto->next;
22471 	sto->next = NULL;
22472     } else {
22473 	/*
22474 	* Create a new state object.
22475 	*/
22476 	sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
22477 	if (sto == NULL) {
22478 	    xmlSchemaVErrMemory(NULL,
22479 		"allocating an IDC state object", NULL);
22480 	    return (-1);
22481 	}
22482 	memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
22483     }
22484     /*
22485     * Add to global list.
22486     */
22487     if (vctxt->xpathStates != NULL)
22488 	sto->next = vctxt->xpathStates;
22489     vctxt->xpathStates = sto;
22490 
22491     /*
22492     * Free the old xpath validation context.
22493     */
22494     if (sto->xpathCtxt != NULL)
22495 	xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
22496 
22497     /*
22498     * Create a new XPath (pattern) validation context.
22499     */
22500     sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
22501 	(xmlPatternPtr) sel->xpathComp);
22502     if (sto->xpathCtxt == NULL) {
22503 	VERROR_INT("xmlSchemaIDCAddStateObject",
22504 	    "failed to create an XPath validation context");
22505 	return (-1);
22506     }
22507     sto->type = type;
22508     sto->depth = vctxt->depth;
22509     sto->matcher = matcher;
22510     sto->sel = sel;
22511     sto->nbHistory = 0;
22512 
22513 #ifdef DEBUG_IDC
22514     xmlGenericError(xmlGenericErrorContext, "IDC:   STO push '%s'\n",
22515 	sto->sel->xpath);
22516 #endif
22517     return (0);
22518 }
22519 
22520 /**
22521  * xmlSchemaXPathEvaluate:
22522  * @vctxt: the WXS validation context
22523  * @nodeType: the nodeType of the current node
22524  *
22525  * Evaluates all active XPath state objects.
22526  *
22527  * Returns the number of IC "field" state objects which resolved to
22528  * this node, 0 if none resolved and -1 on internal errors.
22529  */
22530 static int
xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,xmlElementType nodeType)22531 xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
22532 		       xmlElementType nodeType)
22533 {
22534     xmlSchemaIDCStateObjPtr sto, head = NULL, first;
22535     int res, resolved = 0, depth = vctxt->depth;
22536 
22537     if (vctxt->xpathStates == NULL)
22538 	return (0);
22539 
22540     if (nodeType == XML_ATTRIBUTE_NODE)
22541 	depth++;
22542 #ifdef DEBUG_IDC
22543     {
22544 	xmlChar *str = NULL;
22545 	xmlGenericError(xmlGenericErrorContext,
22546 	    "IDC: EVAL on %s, depth %d, type %d\n",
22547 	    xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22548 		vctxt->inode->localName), depth, nodeType);
22549 	FREE_AND_NULL(str)
22550     }
22551 #endif
22552     /*
22553     * Process all active XPath state objects.
22554     */
22555     first = vctxt->xpathStates;
22556     sto = first;
22557     while (sto != head) {
22558 #ifdef DEBUG_IDC
22559 	if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
22560 	    xmlGenericError(xmlGenericErrorContext, "IDC:   ['%s'] selector '%s'\n",
22561 		sto->matcher->aidc->def->name, sto->sel->xpath);
22562 	else
22563 	    xmlGenericError(xmlGenericErrorContext, "IDC:   ['%s'] field '%s'\n",
22564 		sto->matcher->aidc->def->name, sto->sel->xpath);
22565 #endif
22566 	if (nodeType == XML_ELEMENT_NODE)
22567 	    res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
22568 		vctxt->inode->localName, vctxt->inode->nsName);
22569 	else
22570 	    res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
22571 		vctxt->inode->localName, vctxt->inode->nsName);
22572 
22573 	if (res == -1) {
22574 	    VERROR_INT("xmlSchemaXPathEvaluate",
22575 		"calling xmlStreamPush()");
22576 	    return (-1);
22577 	}
22578 	if (res == 0)
22579 	    goto next_sto;
22580 	/*
22581 	* Full match.
22582 	*/
22583 #ifdef DEBUG_IDC
22584 	xmlGenericError(xmlGenericErrorContext, "IDC:     "
22585 	    "MATCH\n");
22586 #endif
22587 	/*
22588 	* Register a match in the state object history.
22589 	*/
22590 	if (sto->history == NULL) {
22591 	    sto->history = (int *) xmlMalloc(5 * sizeof(int));
22592 	    if (sto->history == NULL) {
22593 		xmlSchemaVErrMemory(NULL,
22594 		    "allocating the state object history", NULL);
22595 		return(-1);
22596 	    }
22597 	    sto->sizeHistory = 5;
22598 	} else if (sto->sizeHistory <= sto->nbHistory) {
22599 	    sto->sizeHistory *= 2;
22600 	    sto->history = (int *) xmlRealloc(sto->history,
22601 		sto->sizeHistory * sizeof(int));
22602 	    if (sto->history == NULL) {
22603 		xmlSchemaVErrMemory(NULL,
22604 		    "re-allocating the state object history", NULL);
22605 		return(-1);
22606 	    }
22607 	}
22608 	sto->history[sto->nbHistory++] = depth;
22609 
22610 #ifdef DEBUG_IDC
22611 	xmlGenericError(xmlGenericErrorContext, "IDC:       push match '%d'\n",
22612 	    vctxt->depth);
22613 #endif
22614 
22615 	if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
22616 	    xmlSchemaIDCSelectPtr sel;
22617 	    /*
22618 	    * Activate state objects for the IDC fields of
22619 	    * the IDC selector.
22620 	    */
22621 #ifdef DEBUG_IDC
22622 	    xmlGenericError(xmlGenericErrorContext, "IDC:     "
22623 		"activating field states\n");
22624 #endif
22625 	    sel = sto->matcher->aidc->def->fields;
22626 	    while (sel != NULL) {
22627 		if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
22628 		    sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
22629 		    return (-1);
22630 		sel = sel->next;
22631 	    }
22632 	} else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22633 	    /*
22634 	    * An IDC key node was found by the IDC field.
22635 	    */
22636 #ifdef DEBUG_IDC
22637 	    xmlGenericError(xmlGenericErrorContext,
22638 		"IDC:     key found\n");
22639 #endif
22640 	    /*
22641 	    * Notify that the character value of this node is
22642 	    * needed.
22643 	    */
22644 	    if (resolved == 0) {
22645 		if ((vctxt->inode->flags &
22646 		    XML_SCHEMA_NODE_INFO_VALUE_NEEDED) == 0)
22647 		vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
22648 	    }
22649 	    resolved++;
22650 	}
22651 next_sto:
22652 	if (sto->next == NULL) {
22653 	    /*
22654 	    * Evaluate field state objects created on this node as well.
22655 	    */
22656 	    head = first;
22657 	    sto = vctxt->xpathStates;
22658 	} else
22659 	    sto = sto->next;
22660     }
22661     return (resolved);
22662 }
22663 
22664 static const xmlChar *
xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,xmlChar ** buf,xmlSchemaPSVIIDCKeyPtr * seq,int count)22665 xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,
22666 			      xmlChar **buf,
22667 			      xmlSchemaPSVIIDCKeyPtr *seq,
22668 			      int count)
22669 {
22670     int i, res;
22671     xmlChar *value = NULL;
22672 
22673     *buf = xmlStrdup(BAD_CAST "[");
22674     for (i = 0; i < count; i++) {
22675 	*buf = xmlStrcat(*buf, BAD_CAST "'");
22676 	res = xmlSchemaGetCanonValueWhtspExt(seq[i]->val,
22677 	    xmlSchemaGetWhiteSpaceFacetValue(seq[i]->type),
22678 	    &value);
22679 	if (res == 0)
22680 	    *buf = xmlStrcat(*buf, BAD_CAST value);
22681 	else {
22682 	    VERROR_INT("xmlSchemaFormatIDCKeySequence",
22683 		"failed to compute a canonical value");
22684 	    *buf = xmlStrcat(*buf, BAD_CAST "???");
22685 	}
22686 	if (i < count -1)
22687 	    *buf = xmlStrcat(*buf, BAD_CAST "', ");
22688 	else
22689 	    *buf = xmlStrcat(*buf, BAD_CAST "'");
22690 	if (value != NULL) {
22691 	    xmlFree(value);
22692 	    value = NULL;
22693 	}
22694     }
22695     *buf = xmlStrcat(*buf, BAD_CAST "]");
22696 
22697     return (BAD_CAST *buf);
22698 }
22699 
22700 /**
22701  * xmlSchemaXPathPop:
22702  * @vctxt: the WXS validation context
22703  *
22704  * Pops all XPath states.
22705  *
22706  * Returns 0 on success and -1 on internal errors.
22707  */
22708 static int
xmlSchemaXPathPop(xmlSchemaValidCtxtPtr vctxt)22709 xmlSchemaXPathPop(xmlSchemaValidCtxtPtr vctxt)
22710 {
22711     xmlSchemaIDCStateObjPtr sto;
22712     int res;
22713 
22714     if (vctxt->xpathStates == NULL)
22715 	return(0);
22716     sto = vctxt->xpathStates;
22717     do {
22718 	res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22719 	if (res == -1)
22720 	    return (-1);
22721 	sto = sto->next;
22722     } while (sto != NULL);
22723     return(0);
22724 }
22725 
22726 /**
22727  * xmlSchemaXPathProcessHistory:
22728  * @vctxt: the WXS validation context
22729  * @type: the simple/complex type of the current node if any at all
22730  * @val: the precompiled value
22731  *
22732  * Processes and pops the history items of the IDC state objects.
22733  * IDC key-sequences are validated/created on IDC bindings.
22734  *
22735  * Returns 0 on success and -1 on internal errors.
22736  */
22737 static int
xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,int depth)22738 xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
22739 			     int depth)
22740 {
22741     xmlSchemaIDCStateObjPtr sto, nextsto;
22742     int res, matchDepth;
22743     xmlSchemaPSVIIDCKeyPtr key = NULL;
22744     xmlSchemaTypePtr type = vctxt->inode->typeDef, simpleType = NULL;
22745 
22746     if (vctxt->xpathStates == NULL)
22747 	return (0);
22748     sto = vctxt->xpathStates;
22749 
22750 #ifdef DEBUG_IDC
22751     {
22752 	xmlChar *str = NULL;
22753 	xmlGenericError(xmlGenericErrorContext,
22754 	    "IDC: BACK on %s, depth %d\n",
22755 	    xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22756 		vctxt->inode->localName), vctxt->depth);
22757 	FREE_AND_NULL(str)
22758     }
22759 #endif
22760     /*
22761     * Evaluate the state objects.
22762     */
22763     while (sto != NULL) {
22764 	res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22765 	if (res == -1) {
22766 	    VERROR_INT("xmlSchemaXPathProcessHistory",
22767 		"calling xmlStreamPop()");
22768 	    return (-1);
22769 	}
22770 #ifdef DEBUG_IDC
22771 	xmlGenericError(xmlGenericErrorContext, "IDC:   stream pop '%s'\n",
22772 	    sto->sel->xpath);
22773 #endif
22774 	if (sto->nbHistory == 0)
22775 	    goto deregister_check;
22776 
22777 	matchDepth = sto->history[sto->nbHistory -1];
22778 
22779 	/*
22780 	* Only matches at the current depth are of interest.
22781 	*/
22782 	if (matchDepth != depth) {
22783 	    sto = sto->next;
22784 	    continue;
22785 	}
22786 	if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22787 	    /*
22788 	    * NOTE: According to
22789 	    *   http://www.w3.org/Bugs/Public/show_bug.cgi?id=2198
22790 	    *   ... the simple-content of complex types is also allowed.
22791 	    */
22792 
22793 	    if (WXS_IS_COMPLEX(type)) {
22794 		if (WXS_HAS_SIMPLE_CONTENT(type)) {
22795 		    /*
22796 		    * Sanity check for complex types with simple content.
22797 		    */
22798 		    simpleType = type->contentTypeDef;
22799 		    if (simpleType == NULL) {
22800 			VERROR_INT("xmlSchemaXPathProcessHistory",
22801 			    "field resolves to a CT with simple content "
22802 			    "but the CT is missing the ST definition");
22803 			return (-1);
22804 		    }
22805 		} else
22806 		    simpleType = NULL;
22807 	    } else
22808 		simpleType = type;
22809 	    if (simpleType == NULL) {
22810 		xmlChar *str = NULL;
22811 
22812 		/*
22813 		* Not qualified if the field resolves to a node of non
22814 		* simple type.
22815 		*/
22816 		xmlSchemaCustomErr(ACTXT_CAST vctxt,
22817 		    XML_SCHEMAV_CVC_IDC, NULL,
22818 		    WXS_BASIC_CAST sto->matcher->aidc->def,
22819 		    "The XPath '%s' of a field of %s does evaluate to a node of "
22820 		    "non-simple type",
22821 		    sto->sel->xpath,
22822 		    xmlSchemaGetIDCDesignation(&str, sto->matcher->aidc->def));
22823 		FREE_AND_NULL(str);
22824 		sto->nbHistory--;
22825 		goto deregister_check;
22826 	    }
22827 
22828 	    if ((key == NULL) && (vctxt->inode->val == NULL)) {
22829 		/*
22830 		* Failed to provide the normalized value; maybe
22831 		* the value was invalid.
22832 		*/
22833 		VERROR(XML_SCHEMAV_CVC_IDC,
22834 		    WXS_BASIC_CAST sto->matcher->aidc->def,
22835 		    "Warning: No precomputed value available, the value "
22836 		    "was either invalid or something strange happend");
22837 		sto->nbHistory--;
22838 		goto deregister_check;
22839 	    } else {
22840 		xmlSchemaIDCMatcherPtr matcher = sto->matcher;
22841 		xmlSchemaPSVIIDCKeyPtr *keySeq;
22842 		int pos, idx;
22843 
22844 		/*
22845 		* The key will be anchored on the matcher's list of
22846 		* key-sequences. The position in this list is determined
22847 		* by the target node's depth relative to the matcher's
22848 		* depth of creation (i.e. the depth of the scope element).
22849 		*
22850 		* Element        Depth    Pos   List-entries
22851 		* <scope>          0              NULL
22852 		*   <bar>          1              NULL
22853 		*     <target/>    2       2      target
22854 		*   <bar>
22855                 * </scope>
22856 		*
22857 		* The size of the list is only dependant on the depth of
22858 		* the tree.
22859 		* An entry will be NULLed in selector_leave, i.e. when
22860 		* we hit the target's
22861 		*/
22862 		pos = sto->depth - matcher->depth;
22863 		idx = sto->sel->index;
22864 
22865 		/*
22866 		* Create/grow the array of key-sequences.
22867 		*/
22868 		if (matcher->keySeqs == NULL) {
22869 		    if (pos > 9)
22870 			matcher->sizeKeySeqs = pos * 2;
22871 		    else
22872 			matcher->sizeKeySeqs = 10;
22873 		    matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22874 			xmlMalloc(matcher->sizeKeySeqs *
22875 			sizeof(xmlSchemaPSVIIDCKeyPtr *));
22876 		    if (matcher->keySeqs == NULL) {
22877 			xmlSchemaVErrMemory(NULL,
22878 			    "allocating an array of key-sequences",
22879 			    NULL);
22880 			return(-1);
22881 		    }
22882 		    memset(matcher->keySeqs, 0,
22883 			matcher->sizeKeySeqs *
22884 			sizeof(xmlSchemaPSVIIDCKeyPtr *));
22885 		} else if (pos >= matcher->sizeKeySeqs) {
22886 		    int i = matcher->sizeKeySeqs;
22887 
22888 		    matcher->sizeKeySeqs *= 2;
22889 		    matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22890 			xmlRealloc(matcher->keySeqs,
22891 			matcher->sizeKeySeqs *
22892 			sizeof(xmlSchemaPSVIIDCKeyPtr *));
22893 		    if (matcher->keySeqs == NULL) {
22894 			xmlSchemaVErrMemory(NULL,
22895 			    "reallocating an array of key-sequences",
22896 			    NULL);
22897 			return (-1);
22898 		    }
22899 		    /*
22900 		    * The array needs to be NULLed.
22901 		    * TODO: Use memset?
22902 		    */
22903 		    for (; i < matcher->sizeKeySeqs; i++)
22904 			matcher->keySeqs[i] = NULL;
22905 		}
22906 
22907 		/*
22908 		* Get/create the key-sequence.
22909 		*/
22910 		keySeq = matcher->keySeqs[pos];
22911 		if (keySeq == NULL) {
22912 		    goto create_sequence;
22913 		} else if (keySeq[idx] != NULL) {
22914 		    xmlChar *str = NULL;
22915 		    /*
22916 		    * cvc-identity-constraint:
22917 		    * 3 For each node in the `target node set` all
22918 		    * of the {fields}, with that node as the context
22919 		    * node, evaluate to either an empty node-set or
22920 		    * a node-set with exactly one member, which must
22921 		    * have a simple type.
22922 		    *
22923 		    * The key was already set; report an error.
22924 		    */
22925 		    xmlSchemaCustomErr(ACTXT_CAST vctxt,
22926 			XML_SCHEMAV_CVC_IDC, NULL,
22927 			WXS_BASIC_CAST matcher->aidc->def,
22928 			"The XPath '%s' of a field of %s evaluates to a "
22929 			"node-set with more than one member",
22930 			sto->sel->xpath,
22931 			xmlSchemaGetIDCDesignation(&str, matcher->aidc->def));
22932 		    FREE_AND_NULL(str);
22933 		    sto->nbHistory--;
22934 		    goto deregister_check;
22935 		} else
22936 		    goto create_key;
22937 
22938 create_sequence:
22939 		/*
22940 		* Create a key-sequence.
22941 		*/
22942 		keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
22943 		    matcher->aidc->def->nbFields *
22944 		    sizeof(xmlSchemaPSVIIDCKeyPtr));
22945 		if (keySeq == NULL) {
22946 		    xmlSchemaVErrMemory(NULL,
22947 			"allocating an IDC key-sequence", NULL);
22948 		    return(-1);
22949 		}
22950 		memset(keySeq, 0, matcher->aidc->def->nbFields *
22951 		    sizeof(xmlSchemaPSVIIDCKeyPtr));
22952 		matcher->keySeqs[pos] = keySeq;
22953 create_key:
22954 		/*
22955 		* Create a key once per node only.
22956 		*/
22957 		if (key == NULL) {
22958 		    key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
22959 			sizeof(xmlSchemaPSVIIDCKey));
22960 		    if (key == NULL) {
22961 			xmlSchemaVErrMemory(NULL,
22962 			    "allocating a IDC key", NULL);
22963 			xmlFree(keySeq);
22964 			matcher->keySeqs[pos] = NULL;
22965 			return(-1);
22966 		    }
22967 		    /*
22968 		    * Consume the compiled value.
22969 		    */
22970 		    key->type = simpleType;
22971 		    key->val = vctxt->inode->val;
22972 		    vctxt->inode->val = NULL;
22973 		    /*
22974 		    * Store the key in a global list.
22975 		    */
22976 		    if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
22977 			xmlSchemaIDCFreeKey(key);
22978 			return (-1);
22979 		    }
22980 		}
22981 		keySeq[idx] = key;
22982 	    }
22983 	} else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
22984 
22985 	    xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
22986 	    /* xmlSchemaPSVIIDCBindingPtr bind; */
22987 	    xmlSchemaPSVIIDCNodePtr ntItem;
22988 	    xmlSchemaIDCMatcherPtr matcher;
22989 	    xmlSchemaIDCPtr idc;
22990 	    xmlSchemaItemListPtr targets;
22991 	    int pos, i, j, nbKeys;
22992 	    /*
22993 	    * Here we have the following scenario:
22994 	    * An IDC 'selector' state object resolved to a target node,
22995 	    * during the time this target node was in the
22996 	    * ancestor-or-self axis, the 'field' state object(s) looked
22997 	    * out for matching nodes to create a key-sequence for this
22998 	    * target node. Now we are back to this target node and need
22999 	    * to put the key-sequence, together with the target node
23000 	    * itself, into the node-table of the corresponding IDC
23001 	    * binding.
23002 	    */
23003 	    matcher = sto->matcher;
23004 	    idc = matcher->aidc->def;
23005 	    nbKeys = idc->nbFields;
23006 	    pos = depth - matcher->depth;
23007 	    /*
23008 	    * Check if the matcher has any key-sequences at all, plus
23009 	    * if it has a key-sequence for the current target node.
23010 	    */
23011 	    if ((matcher->keySeqs == NULL) ||
23012 		(matcher->sizeKeySeqs <= pos)) {
23013 		if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
23014 		    goto selector_key_error;
23015 		else
23016 		    goto selector_leave;
23017 	    }
23018 
23019 	    keySeq = &(matcher->keySeqs[pos]);
23020 	    if (*keySeq == NULL) {
23021 		if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
23022 		    goto selector_key_error;
23023 		else
23024 		    goto selector_leave;
23025 	    }
23026 
23027 	    for (i = 0; i < nbKeys; i++) {
23028 		if ((*keySeq)[i] == NULL) {
23029 		    /*
23030 		    * Not qualified, if not all fields did resolve.
23031 		    */
23032 		    if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
23033 			/*
23034 			* All fields of a "key" IDC must resolve.
23035 			*/
23036 			goto selector_key_error;
23037 		    }
23038 		    goto selector_leave;
23039 		}
23040 	    }
23041 	    /*
23042 	    * All fields did resolve.
23043 	    */
23044 
23045 	    /*
23046 	    * 4.1 If the {identity-constraint category} is unique(/key),
23047 	    * then no two members of the `qualified node set` have
23048 	    * `key-sequences` whose members are pairwise equal, as
23049 	    * defined by Equal in [XML Schemas: Datatypes].
23050 	    *
23051 	    * Get the IDC binding from the matcher and check for
23052 	    * duplicate key-sequences.
23053 	    */
23054 #if 0
23055 	    bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
23056 #endif
23057 	    targets = xmlSchemaIDCAcquireTargetList(vctxt, matcher);
23058 	    if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
23059 		(targets->nbItems != 0)) {
23060 		xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
23061 
23062 		i = 0;
23063 		res = 0;
23064 		/*
23065 		* Compare the key-sequences, key by key.
23066 		*/
23067 		do {
23068 		    bkeySeq =
23069 			((xmlSchemaPSVIIDCNodePtr) targets->items[i])->keys;
23070 		    for (j = 0; j < nbKeys; j++) {
23071 			ckey = (*keySeq)[j];
23072 			bkey = bkeySeq[j];
23073 			res = xmlSchemaAreValuesEqual(ckey->val, bkey->val);
23074 			if (res == -1) {
23075 			    return (-1);
23076 			} else if (res == 0) {
23077 			    /*
23078 			    * One of the keys differs, so the key-sequence
23079 			    * won't be equal; get out.
23080 			    */
23081 			    break;
23082 			}
23083 		    }
23084 		    if (res == 1) {
23085 			/*
23086 			* Duplicate key-sequence found.
23087 			*/
23088 			break;
23089 		    }
23090 		    i++;
23091 		} while (i < targets->nbItems);
23092 		if (i != targets->nbItems) {
23093 		    xmlChar *str = NULL, *strB = NULL;
23094 		    /*
23095 		    * TODO: Try to report the key-sequence.
23096 		    */
23097 		    xmlSchemaCustomErr(ACTXT_CAST vctxt,
23098 			XML_SCHEMAV_CVC_IDC, NULL,
23099 			WXS_BASIC_CAST idc,
23100 			"Duplicate key-sequence %s in %s",
23101 			xmlSchemaFormatIDCKeySequence(vctxt, &str,
23102 			    (*keySeq), nbKeys),
23103 			xmlSchemaGetIDCDesignation(&strB, idc));
23104 		    FREE_AND_NULL(str);
23105 		    FREE_AND_NULL(strB);
23106 		    goto selector_leave;
23107 		}
23108 	    }
23109 	    /*
23110 	    * Add a node-table item to the IDC binding.
23111 	    */
23112 	    ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
23113 		sizeof(xmlSchemaPSVIIDCNode));
23114 	    if (ntItem == NULL) {
23115 		xmlSchemaVErrMemory(NULL,
23116 		    "allocating an IDC node-table item", NULL);
23117 		xmlFree(*keySeq);
23118 		*keySeq = NULL;
23119 		return(-1);
23120 	    }
23121 	    memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
23122 
23123 	    /*
23124 	    * Store the node-table item in a global list.
23125 	    */
23126 	    if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
23127 		if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
23128 		    xmlFree(ntItem);
23129 		    xmlFree(*keySeq);
23130 		    *keySeq = NULL;
23131 		    return (-1);
23132 		}
23133 		ntItem->nodeQNameID = -1;
23134 	    } else {
23135 		/*
23136 		* Save a cached QName for this node on the IDC node, to be
23137 		* able to report it, even if the node is not saved.
23138 		*/
23139 		ntItem->nodeQNameID = xmlSchemaVAddNodeQName(vctxt,
23140 		    vctxt->inode->localName, vctxt->inode->nsName);
23141 		if (ntItem->nodeQNameID == -1) {
23142 		    xmlFree(ntItem);
23143 		    xmlFree(*keySeq);
23144 		    *keySeq = NULL;
23145 		    return (-1);
23146 		}
23147 	    }
23148 	    /*
23149 	    * Init the node-table item: Save the node, position and
23150 	    * consume the key-sequence.
23151 	    */
23152 	    ntItem->node = vctxt->node;
23153 	    ntItem->nodeLine = vctxt->inode->nodeLine;
23154 	    ntItem->keys = *keySeq;
23155 	    *keySeq = NULL;
23156 #if 0
23157 	    if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1)
23158 #endif
23159 	    if (xmlSchemaItemListAdd(targets, ntItem) == -1) {
23160 		if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
23161 		    /*
23162 		    * Free the item, since keyref items won't be
23163 		    * put on a global list.
23164 		    */
23165 		    xmlFree(ntItem->keys);
23166 		    xmlFree(ntItem);
23167 		}
23168 		return (-1);
23169 	    }
23170 
23171 	    goto selector_leave;
23172 selector_key_error:
23173 	    {
23174 		xmlChar *str = NULL;
23175 		/*
23176 		* 4.2.1 (KEY) The `target node set` and the
23177 		* `qualified node set` are equal, that is, every
23178 		* member of the `target node set` is also a member
23179 		* of the `qualified node set` and vice versa.
23180 		*/
23181 		xmlSchemaCustomErr(ACTXT_CAST vctxt,
23182 		    XML_SCHEMAV_CVC_IDC, NULL,
23183 		    WXS_BASIC_CAST idc,
23184 		    "Not all fields of %s evaluate to a node",
23185 		    xmlSchemaGetIDCDesignation(&str, idc), NULL);
23186 		FREE_AND_NULL(str);
23187 	    }
23188 selector_leave:
23189 	    /*
23190 	    * Free the key-sequence if not added to the IDC table.
23191 	    */
23192 	    if ((keySeq != NULL) && (*keySeq != NULL)) {
23193 		xmlFree(*keySeq);
23194 		*keySeq = NULL;
23195 	    }
23196 	} /* if selector */
23197 
23198 	sto->nbHistory--;
23199 
23200 deregister_check:
23201 	/*
23202 	* Deregister state objects if they reach the depth of creation.
23203 	*/
23204 	if ((sto->nbHistory == 0) && (sto->depth == depth)) {
23205 #ifdef DEBUG_IDC
23206 	    xmlGenericError(xmlGenericErrorContext, "IDC:   STO pop '%s'\n",
23207 		sto->sel->xpath);
23208 #endif
23209 	    if (vctxt->xpathStates != sto) {
23210 		VERROR_INT("xmlSchemaXPathProcessHistory",
23211 		    "The state object to be removed is not the first "
23212 		    "in the list");
23213 	    }
23214 	    nextsto = sto->next;
23215 	    /*
23216 	    * Unlink from the list of active XPath state objects.
23217 	    */
23218 	    vctxt->xpathStates = sto->next;
23219 	    sto->next = vctxt->xpathStatePool;
23220 	    /*
23221 	    * Link it to the pool of reusable state objects.
23222 	    */
23223 	    vctxt->xpathStatePool = sto;
23224 	    sto = nextsto;
23225 	} else
23226 	    sto = sto->next;
23227     } /* while (sto != NULL) */
23228     return (0);
23229 }
23230 
23231 /**
23232  * xmlSchemaIDCRegisterMatchers:
23233  * @vctxt: the WXS validation context
23234  * @elemDecl: the element declaration
23235  *
23236  * Creates helper objects to evaluate IDC selectors/fields
23237  * successively.
23238  *
23239  * Returns 0 if OK and -1 on internal errors.
23240  */
23241 static int
xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,xmlSchemaElementPtr elemDecl)23242 xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
23243 			     xmlSchemaElementPtr elemDecl)
23244 {
23245     xmlSchemaIDCMatcherPtr matcher, last = NULL;
23246     xmlSchemaIDCPtr idc, refIdc;
23247     xmlSchemaIDCAugPtr aidc;
23248 
23249     idc = (xmlSchemaIDCPtr) elemDecl->idcs;
23250     if (idc == NULL)
23251 	return (0);
23252 
23253 #ifdef DEBUG_IDC
23254     {
23255 	xmlChar *str = NULL;
23256 	xmlGenericError(xmlGenericErrorContext,
23257 	    "IDC: REGISTER on %s, depth %d\n",
23258 	    (char *) xmlSchemaFormatQName(&str, vctxt->inode->nsName,
23259 		vctxt->inode->localName), vctxt->depth);
23260 	FREE_AND_NULL(str)
23261     }
23262 #endif
23263     if (vctxt->inode->idcMatchers != NULL) {
23264 	VERROR_INT("xmlSchemaIDCRegisterMatchers",
23265 	    "The chain of IDC matchers is expected to be empty");
23266 	return (-1);
23267     }
23268     do {
23269 	if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
23270 	    /*
23271 	    * Since IDCs bubbles are expensive we need to know the
23272 	    * depth at which the bubbles should stop; this will be
23273 	    * the depth of the top-most keyref IDC. If no keyref
23274 	    * references a key/unique IDC, the keyrefDepth will
23275 	    * be -1, indicating that no bubbles are needed.
23276 	    */
23277 	    refIdc = (xmlSchemaIDCPtr) idc->ref->item;
23278 	    if (refIdc != NULL) {
23279 		/*
23280 		* Remember that we have keyrefs on this node.
23281 		*/
23282 		vctxt->inode->hasKeyrefs = 1;
23283 		/*
23284 		* Lookup the referenced augmented IDC info.
23285 		*/
23286 		aidc = vctxt->aidcs;
23287 		while (aidc != NULL) {
23288 		    if (aidc->def == refIdc)
23289 			break;
23290 		    aidc = aidc->next;
23291 		}
23292 		if (aidc == NULL) {
23293 		    VERROR_INT("xmlSchemaIDCRegisterMatchers",
23294 			"Could not find an augmented IDC item for an IDC "
23295 			"definition");
23296 		    return (-1);
23297 		}
23298 		if ((aidc->keyrefDepth == -1) ||
23299 		    (vctxt->depth < aidc->keyrefDepth))
23300 		    aidc->keyrefDepth = vctxt->depth;
23301 	    }
23302 	}
23303 	/*
23304 	* Lookup the augmented IDC item for the IDC definition.
23305 	*/
23306 	aidc = vctxt->aidcs;
23307 	while (aidc != NULL) {
23308 	    if (aidc->def == idc)
23309 		break;
23310 	    aidc = aidc->next;
23311 	}
23312 	if (aidc == NULL) {
23313 	    VERROR_INT("xmlSchemaIDCRegisterMatchers",
23314 		"Could not find an augmented IDC item for an IDC definition");
23315 	    return (-1);
23316 	}
23317 	/*
23318 	* Create an IDC matcher for every IDC definition.
23319 	*/
23320 	if (vctxt->idcMatcherCache != NULL) {
23321 	    /*
23322 	    * Reuse a cached matcher.
23323 	    */
23324 	    matcher = vctxt->idcMatcherCache;
23325 	    vctxt->idcMatcherCache = matcher->nextCached;
23326 	    matcher->nextCached = NULL;
23327 	} else {
23328 	    matcher = (xmlSchemaIDCMatcherPtr)
23329 		xmlMalloc(sizeof(xmlSchemaIDCMatcher));
23330 	    if (matcher == NULL) {
23331 		xmlSchemaVErrMemory(vctxt,
23332 		    "allocating an IDC matcher", NULL);
23333 		return (-1);
23334 	    }
23335 	    memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
23336 	}
23337 	if (last == NULL)
23338 	    vctxt->inode->idcMatchers = matcher;
23339 	else
23340 	    last->next = matcher;
23341 	last = matcher;
23342 
23343 	matcher->type = IDC_MATCHER;
23344 	matcher->depth = vctxt->depth;
23345 	matcher->aidc = aidc;
23346 	matcher->idcType = aidc->def->type;
23347 #ifdef DEBUG_IDC
23348 	xmlGenericError(xmlGenericErrorContext, "IDC:   register matcher\n");
23349 #endif
23350 	/*
23351 	* Init the automaton state object.
23352 	*/
23353 	if (xmlSchemaIDCAddStateObject(vctxt, matcher,
23354 	    idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
23355 	    return (-1);
23356 
23357 	idc = idc->next;
23358     } while (idc != NULL);
23359     return (0);
23360 }
23361 
23362 static int
xmlSchemaIDCFillNodeTables(xmlSchemaValidCtxtPtr vctxt,xmlSchemaNodeInfoPtr ielem)23363 xmlSchemaIDCFillNodeTables(xmlSchemaValidCtxtPtr vctxt,
23364 			   xmlSchemaNodeInfoPtr ielem)
23365 {
23366     xmlSchemaPSVIIDCBindingPtr bind;
23367     int res, i, j, k, nbTargets, nbFields, nbDupls, nbNodeTable;
23368     xmlSchemaPSVIIDCKeyPtr *keys, *ntkeys;
23369     xmlSchemaPSVIIDCNodePtr *targets, *dupls;
23370 
23371     xmlSchemaIDCMatcherPtr matcher = ielem->idcMatchers;
23372     /* vctxt->createIDCNodeTables */
23373     while (matcher != NULL) {
23374 	/*
23375 	* Skip keyref IDCs and empty IDC target-lists.
23376 	*/
23377 	if ((matcher->aidc->def->type == XML_SCHEMA_TYPE_IDC_KEYREF) ||
23378 	    WXS_ILIST_IS_EMPTY(matcher->targets))
23379 	{
23380 	    matcher = matcher->next;
23381 	    continue;
23382 	}
23383 	/*
23384 	* If we _want_ the IDC node-table to be created in any case
23385 	* then do so. Otherwise create them only if keyrefs need them.
23386 	*/
23387 	if ((! vctxt->createIDCNodeTables) &&
23388 	    ((matcher->aidc->keyrefDepth == -1) ||
23389 	     (matcher->aidc->keyrefDepth > vctxt->depth)))
23390 	{
23391 	    matcher = matcher->next;
23392 	    continue;
23393 	}
23394 	/*
23395 	* Get/create the IDC binding on this element for the IDC definition.
23396 	*/
23397 	bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
23398 
23399 	if (! WXS_ILIST_IS_EMPTY(bind->dupls)) {
23400 	    dupls = (xmlSchemaPSVIIDCNodePtr *) bind->dupls->items;
23401 	    nbDupls = bind->dupls->nbItems;
23402 	} else {
23403 	    dupls = NULL;
23404 	    nbDupls = 0;
23405 	}
23406 	if (bind->nodeTable != NULL) {
23407 	    nbNodeTable = bind->nbNodes;
23408 	} else {
23409 	    nbNodeTable = 0;
23410 	}
23411 
23412 	if ((nbNodeTable == 0) && (nbDupls == 0)) {
23413 	    /*
23414 	    * Transfer all IDC target-nodes to the IDC node-table.
23415 	    */
23416 	    bind->nodeTable =
23417 		(xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
23418 	    bind->sizeNodes = matcher->targets->sizeItems;
23419 	    bind->nbNodes = matcher->targets->nbItems;
23420 
23421 	    matcher->targets->items = NULL;
23422 	    matcher->targets->sizeItems = 0;
23423 	    matcher->targets->nbItems = 0;
23424 	} else {
23425 	    /*
23426 	    * Compare the key-sequences and add to the IDC node-table.
23427 	    */
23428 	    nbTargets = matcher->targets->nbItems;
23429 	    targets = (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
23430 	    nbFields = matcher->aidc->def->nbFields;
23431 	    i = 0;
23432 	    do {
23433 		keys = targets[i]->keys;
23434 		if (nbDupls) {
23435 		    /*
23436 		    * Search in already found duplicates first.
23437 		    */
23438 		    j = 0;
23439 		    do {
23440 			if (nbFields == 1) {
23441 			    res = xmlSchemaAreValuesEqual(keys[0]->val,
23442 				dupls[j]->keys[0]->val);
23443 			    if (res == -1)
23444 				goto internal_error;
23445 			    if (res == 1) {
23446 				/*
23447 				* Equal key-sequence.
23448 				*/
23449 				goto next_target;
23450 			    }
23451 			} else {
23452 			    res = 0;
23453 			    ntkeys = dupls[j]->keys;
23454 			    for (k = 0; k < nbFields; k++) {
23455 				res = xmlSchemaAreValuesEqual(keys[k]->val,
23456 				    ntkeys[k]->val);
23457 				if (res == -1)
23458 				    goto internal_error;
23459 				if (res == 0) {
23460 				    /*
23461 				    * One of the keys differs.
23462 				    */
23463 				    break;
23464 				}
23465 			    }
23466 			    if (res == 1) {
23467 				/*
23468 				* Equal key-sequence found.
23469 				*/
23470 				goto next_target;
23471 			    }
23472 			}
23473 			j++;
23474 		    } while (j < nbDupls);
23475 		}
23476 		if (nbNodeTable) {
23477 		    j = 0;
23478 		    do {
23479 			if (nbFields == 1) {
23480 			    res = xmlSchemaAreValuesEqual(keys[0]->val,
23481 				bind->nodeTable[j]->keys[0]->val);
23482 			    if (res == -1)
23483 				goto internal_error;
23484 			    if (res == 0) {
23485 				/*
23486 				* The key-sequence differs.
23487 				*/
23488 				goto next_node_table_entry;
23489 			    }
23490 			} else {
23491 			    res = 0;
23492 			    ntkeys = bind->nodeTable[j]->keys;
23493 			    for (k = 0; k < nbFields; k++) {
23494 				res = xmlSchemaAreValuesEqual(keys[k]->val,
23495 				    ntkeys[k]->val);
23496 				if (res == -1)
23497 				    goto internal_error;
23498 				if (res == 0) {
23499 				    /*
23500 				    * One of the keys differs.
23501 				    */
23502 				    goto next_node_table_entry;
23503 				}
23504 			    }
23505 			}
23506 			/*
23507 			* Add the duplicate to the list of duplicates.
23508 			*/
23509 			if (bind->dupls == NULL) {
23510 			    bind->dupls = xmlSchemaItemListCreate();
23511 			    if (bind->dupls == NULL)
23512 				goto internal_error;
23513 			}
23514 			if (xmlSchemaItemListAdd(bind->dupls, bind->nodeTable[j]) == -1)
23515 			    goto internal_error;
23516 			/*
23517 			* Remove the duplicate entry from the IDC node-table.
23518 			*/
23519 			bind->nodeTable[j] = bind->nodeTable[bind->nbNodes -1];
23520 			bind->nbNodes--;
23521 
23522 			goto next_target;
23523 
23524 next_node_table_entry:
23525 			j++;
23526 		    } while (j < nbNodeTable);
23527 		}
23528 		/*
23529 		* If everything is fine, then add the IDC target-node to
23530 		* the IDC node-table.
23531 		*/
23532 		if (xmlSchemaIDCAppendNodeTableItem(bind, targets[i]) == -1)
23533 		    goto internal_error;
23534 
23535 next_target:
23536 		i++;
23537 	    } while (i < nbTargets);
23538 	}
23539 	matcher = matcher->next;
23540     }
23541     return(0);
23542 
23543 internal_error:
23544     return(-1);
23545 }
23546 
23547 /**
23548  * xmlSchemaBubbleIDCNodeTables:
23549  * @depth: the current tree depth
23550  *
23551  * Merges IDC bindings of an element at @depth into the corresponding IDC
23552  * bindings of its parent element. If a duplicate note-table entry is found,
23553  * both, the parent node-table entry and child entry are discarded from the
23554  * node-table of the parent.
23555  *
23556  * Returns 0 if OK and -1 on internal errors.
23557  */
23558 static int
xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)23559 xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
23560 {
23561     xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
23562     xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL; /* parent IDC bindings. */
23563     xmlSchemaPSVIIDCNodePtr node, parNode = NULL, *dupls, *parNodes; /* node-table entries. */
23564     xmlSchemaIDCAugPtr aidc;
23565     int i, j, k, ret = 0, nbFields, oldNum, oldDupls;
23566 
23567     bind = vctxt->inode->idcTable;
23568     if (bind == NULL) {
23569 	/* Fine, no table, no bubbles. */
23570 	return (0);
23571     }
23572 
23573     parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
23574     /*
23575     * Walk all bindings; create new or add to existing bindings.
23576     * Remove duplicate key-sequences.
23577     */
23578     while (bind != NULL) {
23579 
23580 	if ((bind->nbNodes == 0) && WXS_ILIST_IS_EMPTY(bind->dupls))
23581 	    goto next_binding;
23582 	/*
23583 	* Check if the key/unique IDC table needs to be bubbled.
23584 	*/
23585 	if (! vctxt->createIDCNodeTables) {
23586 	    aidc = vctxt->aidcs;
23587 	    do {
23588 		if (aidc->def == bind->definition) {
23589 		    if ((aidc->keyrefDepth == -1) ||
23590 			(aidc->keyrefDepth >= vctxt->depth)) {
23591 			goto next_binding;
23592 		    }
23593 		    break;
23594 		}
23595 		aidc = aidc->next;
23596 	    } while (aidc != NULL);
23597 	}
23598 
23599 	if (parTable != NULL)
23600 	    parBind = *parTable;
23601 	/*
23602 	* Search a matching parent binding for the
23603 	* IDC definition.
23604 	*/
23605 	while (parBind != NULL) {
23606 	    if (parBind->definition == bind->definition)
23607 		break;
23608 	    parBind = parBind->next;
23609 	}
23610 
23611 	if (parBind != NULL) {
23612 	    /*
23613 	    * Compare every node-table entry of the child node,
23614 	    * i.e. the key-sequence within, ...
23615 	    */
23616 	    oldNum = parBind->nbNodes; /* Skip newly added items. */
23617 
23618 	    if (! WXS_ILIST_IS_EMPTY(parBind->dupls)) {
23619 		oldDupls = parBind->dupls->nbItems;
23620 		dupls = (xmlSchemaPSVIIDCNodePtr *) parBind->dupls->items;
23621 	    } else {
23622 		dupls = NULL;
23623 		oldDupls = 0;
23624 	    }
23625 
23626 	    parNodes = parBind->nodeTable;
23627 	    nbFields = bind->definition->nbFields;
23628 
23629 	    for (i = 0; i < bind->nbNodes; i++) {
23630 		node = bind->nodeTable[i];
23631 		if (node == NULL)
23632 		    continue;
23633 		/*
23634 		* ...with every key-sequence of the parent node, already
23635 		* evaluated to be a duplicate key-sequence.
23636 		*/
23637 		if (oldDupls) {
23638 		    j = 0;
23639 		    while (j < oldDupls) {
23640 			if (nbFields == 1) {
23641 			    ret = xmlSchemaAreValuesEqual(
23642 				node->keys[0]->val,
23643 				dupls[j]->keys[0]->val);
23644 			    if (ret == -1)
23645 				goto internal_error;
23646 			    if (ret == 0) {
23647 				j++;
23648 				continue;
23649 			    }
23650 			} else {
23651 			    parNode = dupls[j];
23652 			    for (k = 0; k < nbFields; k++) {
23653 				ret = xmlSchemaAreValuesEqual(
23654 				    node->keys[k]->val,
23655 				    parNode->keys[k]->val);
23656 				if (ret == -1)
23657 				    goto internal_error;
23658 				if (ret == 0)
23659 				    break;
23660 			    }
23661 			}
23662 			if (ret == 1)
23663 			    /* Duplicate found. */
23664 			    break;
23665 			j++;
23666 		    }
23667 		    if (j != oldDupls) {
23668 			/* Duplicate found. Skip this entry. */
23669 			continue;
23670 		    }
23671 		}
23672 		/*
23673 		* ... and with every key-sequence of the parent node.
23674 		*/
23675 		if (oldNum) {
23676 		    j = 0;
23677 		    while (j < oldNum) {
23678 			parNode = parNodes[j];
23679 			if (nbFields == 1) {
23680 			    ret = xmlSchemaAreValuesEqual(
23681 				node->keys[0]->val,
23682 				parNode->keys[0]->val);
23683 			    if (ret == -1)
23684 				goto internal_error;
23685 			    if (ret == 0) {
23686 				j++;
23687 				continue;
23688 			    }
23689 			} else {
23690 			    for (k = 0; k < nbFields; k++) {
23691 				ret = xmlSchemaAreValuesEqual(
23692 				    node->keys[k]->val,
23693 				    parNode->keys[k]->val);
23694 				if (ret == -1)
23695 				    goto internal_error;
23696 				if (ret == 0)
23697 				    break;
23698 			    }
23699 			}
23700 			if (ret == 1)
23701 			    /* Duplicate found. */
23702 			    break;
23703 			j++;
23704 		    }
23705 		    if (j != oldNum) {
23706 			/*
23707 			* Handle duplicates. Move the duplicate in
23708 			* the parent's node-table to the list of
23709 			* duplicates.
23710 			*/
23711 			oldNum--;
23712 			parBind->nbNodes--;
23713 			/*
23714 			* Move last old item to pos of duplicate.
23715 			*/
23716 			parNodes[j] = parNodes[oldNum];
23717 
23718 			if (parBind->nbNodes != oldNum) {
23719 			    /*
23720 			    * If new items exist, move last new item to
23721 			    * last of old items.
23722 			    */
23723 			    parNodes[oldNum] =
23724 				parNodes[parBind->nbNodes];
23725 			}
23726 			if (parBind->dupls == NULL) {
23727 			    parBind->dupls = xmlSchemaItemListCreate();
23728 			    if (parBind->dupls == NULL)
23729 				goto internal_error;
23730 			}
23731 			xmlSchemaItemListAdd(parBind->dupls, parNode);
23732 		    } else {
23733 			/*
23734 			* Add the node-table entry (node and key-sequence) of
23735 			* the child node to the node table of the parent node.
23736 			*/
23737 			if (parBind->nodeTable == NULL) {
23738 			    parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23739 				xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
23740 			    if (parBind->nodeTable == NULL) {
23741 				xmlSchemaVErrMemory(NULL,
23742 				    "allocating IDC list of node-table items", NULL);
23743 				goto internal_error;
23744 			    }
23745 			    parBind->sizeNodes = 1;
23746 			} else if (parBind->nbNodes >= parBind->sizeNodes) {
23747 			    parBind->sizeNodes *= 2;
23748 			    parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23749 				xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
23750 				sizeof(xmlSchemaPSVIIDCNodePtr));
23751 			    if (parBind->nodeTable == NULL) {
23752 				xmlSchemaVErrMemory(NULL,
23753 				    "re-allocating IDC list of node-table items", NULL);
23754 				goto internal_error;
23755 			    }
23756 			}
23757 			parNodes = parBind->nodeTable;
23758 			/*
23759 			* Append the new node-table entry to the 'new node-table
23760 			* entries' section.
23761 			*/
23762 			parNodes[parBind->nbNodes++] = node;
23763 		    }
23764 
23765 		}
23766 
23767 	    }
23768 	} else {
23769 	    /*
23770 	    * No binding for the IDC was found: create a new one and
23771 	    * copy all node-tables.
23772 	    */
23773 	    parBind = xmlSchemaIDCNewBinding(bind->definition);
23774 	    if (parBind == NULL)
23775 		goto internal_error;
23776 
23777 	    /*
23778 	    * TODO: Hmm, how to optimize the initial number of
23779 	    * allocated entries?
23780 	    */
23781 	    if (bind->nbNodes != 0) {
23782 		/*
23783 		* Add all IDC node-table entries.
23784 		*/
23785 		if (! vctxt->psviExposeIDCNodeTables) {
23786 		    /*
23787 		    * Just move the entries.
23788 		    * NOTE: this is quite save here, since
23789 		    * all the keyref lookups have already been
23790 		    * performed.
23791 		    */
23792 		    parBind->nodeTable = bind->nodeTable;
23793 		    bind->nodeTable = NULL;
23794 		    parBind->sizeNodes = bind->sizeNodes;
23795 		    bind->sizeNodes = 0;
23796 		    parBind->nbNodes = bind->nbNodes;
23797 		    bind->nbNodes = 0;
23798 		} else {
23799 		    /*
23800 		    * Copy the entries.
23801 		    */
23802 		    parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23803 			xmlMalloc(bind->nbNodes *
23804 			sizeof(xmlSchemaPSVIIDCNodePtr));
23805 		    if (parBind->nodeTable == NULL) {
23806 			xmlSchemaVErrMemory(NULL,
23807 			    "allocating an array of IDC node-table "
23808 			    "items", NULL);
23809 			xmlSchemaIDCFreeBinding(parBind);
23810 			goto internal_error;
23811 		    }
23812 		    parBind->sizeNodes = bind->nbNodes;
23813 		    parBind->nbNodes = bind->nbNodes;
23814 		    memcpy(parBind->nodeTable, bind->nodeTable,
23815 			bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
23816 		}
23817 	    }
23818 	    if (bind->dupls) {
23819 		/*
23820 		* Move the duplicates.
23821 		*/
23822 		if (parBind->dupls != NULL)
23823 		    xmlSchemaItemListFree(parBind->dupls);
23824 		parBind->dupls = bind->dupls;
23825 		bind->dupls = NULL;
23826 	    }
23827             if (parTable != NULL) {
23828                 if (*parTable == NULL)
23829                     *parTable = parBind;
23830                 else {
23831                     parBind->next = *parTable;
23832                     *parTable = parBind;
23833                 }
23834             }
23835 	}
23836 
23837 next_binding:
23838 	bind = bind->next;
23839     }
23840     return (0);
23841 
23842 internal_error:
23843     return(-1);
23844 }
23845 
23846 /**
23847  * xmlSchemaCheckCVCIDCKeyRef:
23848  * @vctxt: the WXS validation context
23849  * @elemDecl: the element declaration
23850  *
23851  * Check the cvc-idc-keyref constraints.
23852  */
23853 static int
xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)23854 xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
23855 {
23856     xmlSchemaIDCMatcherPtr matcher;
23857     xmlSchemaPSVIIDCBindingPtr bind;
23858 
23859     matcher = vctxt->inode->idcMatchers;
23860     /*
23861     * Find a keyref.
23862     */
23863     while (matcher != NULL) {
23864 	if ((matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) &&
23865 	    matcher->targets &&
23866 	    matcher->targets->nbItems)
23867 	{
23868 	    int i, j, k, res, nbFields, hasDupls;
23869 	    xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
23870 	    xmlSchemaPSVIIDCNodePtr refNode = NULL;
23871 
23872 	    nbFields = matcher->aidc->def->nbFields;
23873 
23874 	    /*
23875 	    * Find the IDC node-table for the referenced IDC key/unique.
23876 	    */
23877 	    bind = vctxt->inode->idcTable;
23878 	    while (bind != NULL) {
23879 		if ((xmlSchemaIDCPtr) matcher->aidc->def->ref->item ==
23880 		    bind->definition)
23881 		    break;
23882 		bind = bind->next;
23883 	    }
23884 	    hasDupls = (bind && bind->dupls && bind->dupls->nbItems) ? 1 : 0;
23885 	    /*
23886 	    * Search for a matching key-sequences.
23887 	    */
23888 	    for (i = 0; i < matcher->targets->nbItems; i++) {
23889 		res = 0;
23890 		refNode = matcher->targets->items[i];
23891 		if (bind != NULL) {
23892 		    refKeys = refNode->keys;
23893 		    for (j = 0; j < bind->nbNodes; j++) {
23894 			keys = bind->nodeTable[j]->keys;
23895 			for (k = 0; k < nbFields; k++) {
23896 			    res = xmlSchemaAreValuesEqual(keys[k]->val,
23897 				refKeys[k]->val);
23898 			    if (res == 0)
23899 				break;
23900 			    else if (res == -1) {
23901 				return (-1);
23902 			    }
23903 			}
23904 			if (res == 1) {
23905 			    /*
23906 			    * Match found.
23907 			    */
23908 			    break;
23909 			}
23910 		    }
23911 		    if ((res == 0) && hasDupls) {
23912 			/*
23913 			* Search in duplicates
23914 			*/
23915 			for (j = 0; j < bind->dupls->nbItems; j++) {
23916 			    keys = ((xmlSchemaPSVIIDCNodePtr)
23917 				bind->dupls->items[j])->keys;
23918 			    for (k = 0; k < nbFields; k++) {
23919 				res = xmlSchemaAreValuesEqual(keys[k]->val,
23920 				    refKeys[k]->val);
23921 				if (res == 0)
23922 				    break;
23923 				else if (res == -1) {
23924 				    return (-1);
23925 				}
23926 			    }
23927 			    if (res == 1) {
23928 				/*
23929 				* Match in duplicates found.
23930 				*/
23931 				xmlChar *str = NULL, *strB = NULL;
23932 				xmlSchemaKeyrefErr(vctxt,
23933 				    XML_SCHEMAV_CVC_IDC, refNode,
23934 				    (xmlSchemaTypePtr) matcher->aidc->def,
23935 				    "More than one match found for "
23936 				    "key-sequence %s of keyref '%s'",
23937 				    xmlSchemaFormatIDCKeySequence(vctxt, &str,
23938 					refNode->keys, nbFields),
23939 				    xmlSchemaGetComponentQName(&strB,
23940 					matcher->aidc->def));
23941 				FREE_AND_NULL(str);
23942 				FREE_AND_NULL(strB);
23943 				break;
23944 			    }
23945 			}
23946 		    }
23947 		}
23948 
23949 		if (res == 0) {
23950 		    xmlChar *str = NULL, *strB = NULL;
23951 		    xmlSchemaKeyrefErr(vctxt,
23952 			XML_SCHEMAV_CVC_IDC, refNode,
23953 			(xmlSchemaTypePtr) matcher->aidc->def,
23954 			"No match found for key-sequence %s of keyref '%s'",
23955 			xmlSchemaFormatIDCKeySequence(vctxt, &str,
23956 			    refNode->keys, nbFields),
23957 			xmlSchemaGetComponentQName(&strB, matcher->aidc->def));
23958 		    FREE_AND_NULL(str);
23959 		    FREE_AND_NULL(strB);
23960 		}
23961 	    }
23962 	}
23963 	matcher = matcher->next;
23964     }
23965     /* TODO: Return an error if any error encountered. */
23966     return (0);
23967 }
23968 
23969 /************************************************************************
23970  *									*
23971  *			XML Reader validation code                      *
23972  *									*
23973  ************************************************************************/
23974 
23975 static xmlSchemaAttrInfoPtr
xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)23976 xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)
23977 {
23978     xmlSchemaAttrInfoPtr iattr;
23979     /*
23980     * Grow/create list of attribute infos.
23981     */
23982     if (vctxt->attrInfos == NULL) {
23983 	vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
23984 	    xmlMalloc(sizeof(xmlSchemaAttrInfoPtr));
23985 	vctxt->sizeAttrInfos = 1;
23986 	if (vctxt->attrInfos == NULL) {
23987 	    xmlSchemaVErrMemory(vctxt,
23988 		"allocating attribute info list", NULL);
23989 	    return (NULL);
23990 	}
23991     } else if (vctxt->sizeAttrInfos <= vctxt->nbAttrInfos) {
23992 	vctxt->sizeAttrInfos++;
23993 	vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
23994 	    xmlRealloc(vctxt->attrInfos,
23995 		vctxt->sizeAttrInfos * sizeof(xmlSchemaAttrInfoPtr));
23996 	if (vctxt->attrInfos == NULL) {
23997 	    xmlSchemaVErrMemory(vctxt,
23998 		"re-allocating attribute info list", NULL);
23999 	    return (NULL);
24000 	}
24001     } else {
24002 	iattr = vctxt->attrInfos[vctxt->nbAttrInfos++];
24003 	if (iattr->localName != NULL) {
24004 	    VERROR_INT("xmlSchemaGetFreshAttrInfo",
24005 		"attr info not cleared");
24006 	    return (NULL);
24007 	}
24008 	iattr->nodeType = XML_ATTRIBUTE_NODE;
24009 	return (iattr);
24010     }
24011     /*
24012     * Create an attribute info.
24013     */
24014     iattr = (xmlSchemaAttrInfoPtr)
24015 	xmlMalloc(sizeof(xmlSchemaAttrInfo));
24016     if (iattr == NULL) {
24017 	xmlSchemaVErrMemory(vctxt, "creating new attribute info", NULL);
24018 	return (NULL);
24019     }
24020     memset(iattr, 0, sizeof(xmlSchemaAttrInfo));
24021     iattr->nodeType = XML_ATTRIBUTE_NODE;
24022     vctxt->attrInfos[vctxt->nbAttrInfos++] = iattr;
24023 
24024     return (iattr);
24025 }
24026 
24027 static int
xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,xmlNodePtr attrNode,int nodeLine,const xmlChar * localName,const xmlChar * nsName,int ownedNames,xmlChar * value,int ownedValue)24028 xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,
24029 			xmlNodePtr attrNode,
24030 			int nodeLine,
24031 			const xmlChar *localName,
24032 			const xmlChar *nsName,
24033 			int ownedNames,
24034 			xmlChar *value,
24035 			int ownedValue)
24036 {
24037     xmlSchemaAttrInfoPtr attr;
24038 
24039     attr = xmlSchemaGetFreshAttrInfo(vctxt);
24040     if (attr == NULL) {
24041 	VERROR_INT("xmlSchemaPushAttribute",
24042 	    "calling xmlSchemaGetFreshAttrInfo()");
24043 	return (-1);
24044     }
24045     attr->node = attrNode;
24046     attr->nodeLine = nodeLine;
24047     attr->state = XML_SCHEMAS_ATTR_UNKNOWN;
24048     attr->localName = localName;
24049     attr->nsName = nsName;
24050     if (ownedNames)
24051 	attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
24052     /*
24053     * Evaluate if it's an XSI attribute.
24054     */
24055     if (nsName != NULL) {
24056 	if (xmlStrEqual(localName, BAD_CAST "nil")) {
24057 	    if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
24058 		attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NIL;
24059 	    }
24060 	} else if (xmlStrEqual(localName, BAD_CAST "type")) {
24061 	    if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
24062 		attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_TYPE;
24063 	    }
24064 	} else if (xmlStrEqual(localName, BAD_CAST "schemaLocation")) {
24065 	    if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
24066 		attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC;
24067 	    }
24068 	} else if (xmlStrEqual(localName, BAD_CAST "noNamespaceSchemaLocation")) {
24069 	    if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
24070 		attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC;
24071 	    }
24072 	} else if (xmlStrEqual(attr->nsName, xmlNamespaceNs)) {
24073 	    attr->metaType = XML_SCHEMA_ATTR_INFO_META_XMLNS;
24074 	}
24075     }
24076     attr->value = value;
24077     if (ownedValue)
24078 	attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
24079     if (attr->metaType != 0)
24080 	attr->state = XML_SCHEMAS_ATTR_META;
24081     return (0);
24082 }
24083 
24084 /**
24085  * xmlSchemaClearElemInfo:
24086  * @vctxt: the WXS validation context
24087  * @ielem: the element information item
24088  */
24089 static void
xmlSchemaClearElemInfo(xmlSchemaValidCtxtPtr vctxt,xmlSchemaNodeInfoPtr ielem)24090 xmlSchemaClearElemInfo(xmlSchemaValidCtxtPtr vctxt,
24091 		       xmlSchemaNodeInfoPtr ielem)
24092 {
24093     ielem->hasKeyrefs = 0;
24094     ielem->appliedXPath = 0;
24095     if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
24096 	FREE_AND_NULL(ielem->localName);
24097 	FREE_AND_NULL(ielem->nsName);
24098     } else {
24099 	ielem->localName = NULL;
24100 	ielem->nsName = NULL;
24101     }
24102     if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
24103 	FREE_AND_NULL(ielem->value);
24104     } else {
24105 	ielem->value = NULL;
24106     }
24107     if (ielem->val != NULL) {
24108 	/*
24109 	* PSVI TODO: Be careful not to free it when the value is
24110 	* exposed via PSVI.
24111 	*/
24112 	xmlSchemaFreeValue(ielem->val);
24113 	ielem->val = NULL;
24114     }
24115     if (ielem->idcMatchers != NULL) {
24116 	/*
24117 	* REVISIT OPTIMIZE TODO: Use a pool of IDC matchers.
24118 	*   Does it work?
24119 	*/
24120 	xmlSchemaIDCReleaseMatcherList(vctxt, ielem->idcMatchers);
24121 #if 0
24122 	xmlSchemaIDCFreeMatcherList(ielem->idcMatchers);
24123 #endif
24124 	ielem->idcMatchers = NULL;
24125     }
24126     if (ielem->idcTable != NULL) {
24127 	/*
24128 	* OPTIMIZE TODO: Use a pool of IDC tables??.
24129 	*/
24130 	xmlSchemaIDCFreeIDCTable(ielem->idcTable);
24131 	ielem->idcTable = NULL;
24132     }
24133     if (ielem->regexCtxt != NULL) {
24134 	xmlRegFreeExecCtxt(ielem->regexCtxt);
24135 	ielem->regexCtxt = NULL;
24136     }
24137     if (ielem->nsBindings != NULL) {
24138 	xmlFree((xmlChar **)ielem->nsBindings);
24139 	ielem->nsBindings = NULL;
24140 	ielem->nbNsBindings = 0;
24141 	ielem->sizeNsBindings = 0;
24142     }
24143 }
24144 
24145 /**
24146  * xmlSchemaGetFreshElemInfo:
24147  * @vctxt: the schema validation context
24148  *
24149  * Creates/reuses and initializes the element info item for
24150  * the currect tree depth.
24151  *
24152  * Returns the element info item or NULL on API or internal errors.
24153  */
24154 static xmlSchemaNodeInfoPtr
xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)24155 xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)
24156 {
24157     xmlSchemaNodeInfoPtr info = NULL;
24158 
24159     if (vctxt->depth > vctxt->sizeElemInfos) {
24160 	VERROR_INT("xmlSchemaGetFreshElemInfo",
24161 	    "inconsistent depth encountered");
24162 	return (NULL);
24163     }
24164     if (vctxt->elemInfos == NULL) {
24165 	vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
24166 	    xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
24167 	if (vctxt->elemInfos == NULL) {
24168 	    xmlSchemaVErrMemory(vctxt,
24169 		"allocating the element info array", NULL);
24170 	    return (NULL);
24171 	}
24172 	memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
24173 	vctxt->sizeElemInfos = 10;
24174     } else if (vctxt->sizeElemInfos <= vctxt->depth) {
24175 	int i = vctxt->sizeElemInfos;
24176 
24177 	vctxt->sizeElemInfos *= 2;
24178 	vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
24179 	    xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
24180 	    sizeof(xmlSchemaNodeInfoPtr));
24181 	if (vctxt->elemInfos == NULL) {
24182 	    xmlSchemaVErrMemory(vctxt,
24183 		"re-allocating the element info array", NULL);
24184 	    return (NULL);
24185 	}
24186 	/*
24187 	* We need the new memory to be NULLed.
24188 	* TODO: Use memset instead?
24189 	*/
24190 	for (; i < vctxt->sizeElemInfos; i++)
24191 	    vctxt->elemInfos[i] = NULL;
24192     } else
24193 	info = vctxt->elemInfos[vctxt->depth];
24194 
24195     if (info == NULL) {
24196 	info = (xmlSchemaNodeInfoPtr)
24197 	    xmlMalloc(sizeof(xmlSchemaNodeInfo));
24198 	if (info == NULL) {
24199 	    xmlSchemaVErrMemory(vctxt,
24200 		"allocating an element info", NULL);
24201 	    return (NULL);
24202 	}
24203 	vctxt->elemInfos[vctxt->depth] = info;
24204     } else {
24205 	if (info->localName != NULL) {
24206 	    VERROR_INT("xmlSchemaGetFreshElemInfo",
24207 		"elem info has not been cleared");
24208 	    return (NULL);
24209 	}
24210     }
24211     memset(info, 0, sizeof(xmlSchemaNodeInfo));
24212     info->nodeType = XML_ELEMENT_NODE;
24213     info->depth = vctxt->depth;
24214 
24215     return (info);
24216 }
24217 
24218 #define ACTIVATE_ATTRIBUTE(item) vctxt->inode = (xmlSchemaNodeInfoPtr) item;
24219 #define ACTIVATE_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth];
24220 #define ACTIVATE_PARENT_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth -1];
24221 
24222 static int
xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,xmlNodePtr node,xmlSchemaTypePtr type,xmlSchemaValType valType,const xmlChar * value,xmlSchemaValPtr val,unsigned long length,int fireErrors)24223 xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,
24224 			xmlNodePtr node,
24225 			xmlSchemaTypePtr type,
24226 			xmlSchemaValType valType,
24227 			const xmlChar * value,
24228 			xmlSchemaValPtr val,
24229 			unsigned long length,
24230 			int fireErrors)
24231 {
24232     int ret, error = 0;
24233 
24234     xmlSchemaTypePtr tmpType;
24235     xmlSchemaFacetLinkPtr facetLink;
24236     xmlSchemaFacetPtr facet;
24237     unsigned long len = 0;
24238     xmlSchemaWhitespaceValueType ws;
24239 
24240     /*
24241     * In Libxml2, derived built-in types have currently no explicit facets.
24242     */
24243     if (type->type == XML_SCHEMA_TYPE_BASIC)
24244 	return (0);
24245 
24246     /*
24247     * NOTE: Do not jump away, if the facetSet of the given type is
24248     * empty: until now, "pattern" and "enumeration" facets of the
24249     * *base types* need to be checked as well.
24250     */
24251     if (type->facetSet == NULL)
24252 	goto pattern_and_enum;
24253 
24254     if (! WXS_IS_ATOMIC(type)) {
24255 	if (WXS_IS_LIST(type))
24256 	    goto WXS_IS_LIST;
24257 	else
24258 	    goto pattern_and_enum;
24259     }
24260 
24261     /*
24262     * Whitespace handling is only of importance for string-based
24263     * types.
24264     */
24265     tmpType = xmlSchemaGetPrimitiveType(type);
24266     if ((tmpType->builtInType == XML_SCHEMAS_STRING) ||
24267 	WXS_IS_ANY_SIMPLE_TYPE(tmpType)) {
24268 	ws = xmlSchemaGetWhiteSpaceFacetValue(type);
24269     } else
24270 	ws = XML_SCHEMA_WHITESPACE_COLLAPSE;
24271 
24272     /*
24273     * If the value was not computed (for string or
24274     * anySimpleType based types), then use the provided
24275     * type.
24276     */
24277     if (val != NULL)
24278 	valType = xmlSchemaGetValType(val);
24279 
24280     ret = 0;
24281     for (facetLink = type->facetSet; facetLink != NULL;
24282 	facetLink = facetLink->next) {
24283 	/*
24284 	* Skip the pattern "whiteSpace": it is used to
24285 	* format the character content beforehand.
24286 	*/
24287 	switch (facetLink->facet->type) {
24288 	    case XML_SCHEMA_FACET_WHITESPACE:
24289 	    case XML_SCHEMA_FACET_PATTERN:
24290 	    case XML_SCHEMA_FACET_ENUMERATION:
24291 		continue;
24292 	    case XML_SCHEMA_FACET_LENGTH:
24293 	    case XML_SCHEMA_FACET_MINLENGTH:
24294 	    case XML_SCHEMA_FACET_MAXLENGTH:
24295 		ret = xmlSchemaValidateLengthFacetWhtsp(facetLink->facet,
24296 		    valType, value, val, &len, ws);
24297 		break;
24298 	    default:
24299 		ret = xmlSchemaValidateFacetWhtsp(facetLink->facet, ws,
24300 		    valType, value, val, ws);
24301 		break;
24302 	}
24303 	if (ret < 0) {
24304 	    AERROR_INT("xmlSchemaValidateFacets",
24305 		"validating against a atomic type facet");
24306 	    return (-1);
24307 	} else if (ret > 0) {
24308 	    if (fireErrors)
24309 		xmlSchemaFacetErr(actxt, ret, node,
24310 		value, len, type, facetLink->facet, NULL, NULL, NULL);
24311 	    else
24312 		return (ret);
24313 	    if (error == 0)
24314 		error = ret;
24315 	}
24316 	ret = 0;
24317     }
24318 
24319 WXS_IS_LIST:
24320     if (! WXS_IS_LIST(type))
24321 	goto pattern_and_enum;
24322     /*
24323     * "length", "minLength" and "maxLength" of list types.
24324     */
24325     ret = 0;
24326     for (facetLink = type->facetSet; facetLink != NULL;
24327 	facetLink = facetLink->next) {
24328 
24329 	switch (facetLink->facet->type) {
24330 	    case XML_SCHEMA_FACET_LENGTH:
24331 	    case XML_SCHEMA_FACET_MINLENGTH:
24332 	    case XML_SCHEMA_FACET_MAXLENGTH:
24333 		ret = xmlSchemaValidateListSimpleTypeFacet(facetLink->facet,
24334 		    value, length, NULL);
24335 		break;
24336 	    default:
24337 		continue;
24338 	}
24339 	if (ret < 0) {
24340 	    AERROR_INT("xmlSchemaValidateFacets",
24341 		"validating against a list type facet");
24342 	    return (-1);
24343 	} else if (ret > 0) {
24344 	    if (fireErrors)
24345 		xmlSchemaFacetErr(actxt, ret, node,
24346 		value, length, type, facetLink->facet, NULL, NULL, NULL);
24347 	    else
24348 		return (ret);
24349 	    if (error == 0)
24350 		error = ret;
24351 	}
24352 	ret = 0;
24353     }
24354 
24355 pattern_and_enum:
24356     if (error >= 0) {
24357 	int found = 0;
24358 	/*
24359 	* Process enumerations. Facet values are in the value space
24360 	* of the defining type's base type. This seems to be a bug in the
24361 	* XML Schema 1.0 spec. Use the whitespace type of the base type.
24362 	* Only the first set of enumerations in the ancestor-or-self axis
24363 	* is used for validation.
24364 	*/
24365 	ret = 0;
24366 	tmpType = type;
24367 	do {
24368 	    for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
24369 		if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
24370 		    continue;
24371 		found = 1;
24372 		ret = xmlSchemaAreValuesEqual(facet->val, val);
24373 		if (ret == 1)
24374 		    break;
24375 		else if (ret < 0) {
24376 		    AERROR_INT("xmlSchemaValidateFacets",
24377 			"validating against an enumeration facet");
24378 		    return (-1);
24379 		}
24380 	    }
24381 	    if (ret != 0)
24382 		break;
24383 	    /*
24384 	    * Break on the first set of enumerations. Any additional
24385 	    *  enumerations which might be existent on the ancestors
24386 	    *  of the current type are restricted by this set; thus
24387 	    *  *must* *not* be taken into account.
24388 	    */
24389 	    if (found)
24390 		break;
24391 	    tmpType = tmpType->baseType;
24392 	} while ((tmpType != NULL) &&
24393 	    (tmpType->type != XML_SCHEMA_TYPE_BASIC));
24394 	if (found && (ret == 0)) {
24395 	    ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
24396 	    if (fireErrors) {
24397 		xmlSchemaFacetErr(actxt, ret, node,
24398 		    value, 0, type, NULL, NULL, NULL, NULL);
24399 	    } else
24400 		return (ret);
24401 	    if (error == 0)
24402 		error = ret;
24403 	}
24404     }
24405 
24406     if (error >= 0) {
24407 	int found;
24408 	/*
24409 	* Process patters. Pattern facets are ORed at type level
24410 	* and ANDed if derived. Walk the base type axis.
24411 	*/
24412 	tmpType = type;
24413 	facet = NULL;
24414 	do {
24415 	    found = 0;
24416 	    for (facetLink = tmpType->facetSet; facetLink != NULL;
24417 		facetLink = facetLink->next) {
24418 		if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
24419 		    continue;
24420 		found = 1;
24421 		/*
24422 		* NOTE that for patterns, @value needs to be the
24423 		* normalized vaule.
24424 		*/
24425 		ret = xmlRegexpExec(facetLink->facet->regexp, value);
24426 		if (ret == 1)
24427 		    break;
24428 		else if (ret < 0) {
24429 		    AERROR_INT("xmlSchemaValidateFacets",
24430 			"validating against a pattern facet");
24431 		    return (-1);
24432 		} else {
24433 		    /*
24434 		    * Save the last non-validating facet.
24435 		    */
24436 		    facet = facetLink->facet;
24437 		}
24438 	    }
24439 	    if (found && (ret != 1)) {
24440 		ret = XML_SCHEMAV_CVC_PATTERN_VALID;
24441 		if (fireErrors) {
24442 		    xmlSchemaFacetErr(actxt, ret, node,
24443 			value, 0, type, facet, NULL, NULL, NULL);
24444 		} else
24445 		    return (ret);
24446 		if (error == 0)
24447 		    error = ret;
24448 		break;
24449 	    }
24450 	    tmpType = tmpType->baseType;
24451 	} while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
24452     }
24453 
24454     return (error);
24455 }
24456 
24457 static xmlChar *
xmlSchemaNormalizeValue(xmlSchemaTypePtr type,const xmlChar * value)24458 xmlSchemaNormalizeValue(xmlSchemaTypePtr type,
24459 			const xmlChar *value)
24460 {
24461     switch (xmlSchemaGetWhiteSpaceFacetValue(type)) {
24462 	case XML_SCHEMA_WHITESPACE_COLLAPSE:
24463 	    return (xmlSchemaCollapseString(value));
24464 	case XML_SCHEMA_WHITESPACE_REPLACE:
24465 	    return (xmlSchemaWhiteSpaceReplace(value));
24466 	default:
24467 	    return (NULL);
24468     }
24469 }
24470 
24471 static int
xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt,const xmlChar * value,xmlSchemaValPtr * val,int valNeeded)24472 xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt,
24473 		       const xmlChar *value,
24474 		       xmlSchemaValPtr *val,
24475 		       int valNeeded)
24476 {
24477     int ret;
24478     const xmlChar *nsName;
24479     xmlChar *local, *prefix = NULL;
24480 
24481     ret = xmlValidateQName(value, 1);
24482     if (ret != 0) {
24483 	if (ret == -1) {
24484 	    VERROR_INT("xmlSchemaValidateQName",
24485 		"calling xmlValidateQName()");
24486 	    return (-1);
24487 	}
24488 	return( XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
24489     }
24490     /*
24491     * NOTE: xmlSplitQName2 will always return a duplicated
24492     * strings.
24493     */
24494     local = xmlSplitQName2(value, &prefix);
24495     if (local == NULL)
24496 	local = xmlStrdup(value);
24497     /*
24498     * OPTIMIZE TODO: Use flags for:
24499     *  - is there any namespace binding?
24500     *  - is there a default namespace?
24501     */
24502     nsName = xmlSchemaLookupNamespace(vctxt, prefix);
24503 
24504     if (prefix != NULL) {
24505 	xmlFree(prefix);
24506 	/*
24507 	* A namespace must be found if the prefix is
24508 	* NOT NULL.
24509 	*/
24510 	if (nsName == NULL) {
24511 	    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24512 	    xmlSchemaCustomErr(ACTXT_CAST vctxt, ret, NULL,
24513 		WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24514 		"The QName value '%s' has no "
24515 		"corresponding namespace declaration in "
24516 		"scope", value, NULL);
24517 	    if (local != NULL)
24518 		xmlFree(local);
24519 	    return (ret);
24520 	}
24521     }
24522     if (valNeeded && val) {
24523 	if (nsName != NULL)
24524 	    *val = xmlSchemaNewQNameValue(
24525 		BAD_CAST xmlStrdup(nsName), BAD_CAST local);
24526 	else
24527 	    *val = xmlSchemaNewQNameValue(NULL,
24528 		BAD_CAST local);
24529     } else
24530 	xmlFree(local);
24531     return (0);
24532 }
24533 
24534 /*
24535 * cvc-simple-type
24536 */
24537 static int
xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,xmlNodePtr node,xmlSchemaTypePtr type,const xmlChar * value,xmlSchemaValPtr * retVal,int fireErrors,int normalize,int isNormalized)24538 xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
24539 			     xmlNodePtr node,
24540 			     xmlSchemaTypePtr type,
24541 			     const xmlChar *value,
24542 			     xmlSchemaValPtr *retVal,
24543 			     int fireErrors,
24544 			     int normalize,
24545 			     int isNormalized)
24546 {
24547     int ret = 0, valNeeded = (retVal) ? 1 : 0;
24548     xmlSchemaValPtr val = NULL;
24549     /* xmlSchemaWhitespaceValueType ws; */
24550     xmlChar *normValue = NULL;
24551 
24552 #define NORMALIZE(atype) \
24553     if ((! isNormalized) && \
24554     (normalize || (type->flags & XML_SCHEMAS_TYPE_NORMVALUENEEDED))) { \
24555 	normValue = xmlSchemaNormalizeValue(atype, value); \
24556 	if (normValue != NULL) \
24557 	    value = normValue; \
24558 	isNormalized = 1; \
24559     }
24560 
24561     if ((retVal != NULL) && (*retVal != NULL)) {
24562 	xmlSchemaFreeValue(*retVal);
24563 	*retVal = NULL;
24564     }
24565     /*
24566     * 3.14.4 Simple Type Definition Validation Rules
24567     * Validation Rule: String Valid
24568     */
24569     /*
24570     * 1 It is schema-valid with respect to that definition as defined
24571     * by Datatype Valid in [XML Schemas: Datatypes].
24572     */
24573     /*
24574     * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
24575     * the empty set, as defined in Type Derivation OK (Simple) ($3.14.6), then
24576     * the string must be a `declared entity name`.
24577     */
24578     /*
24579     * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
24580     * given the empty set, as defined in Type Derivation OK (Simple) ($3.14.6),
24581     * then every whitespace-delimited substring of the string must be a `declared
24582     * entity name`.
24583     */
24584     /*
24585     * 2.3 otherwise no further condition applies.
24586     */
24587     if ((! valNeeded) && (type->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
24588 	valNeeded = 1;
24589     if (value == NULL)
24590 	value = BAD_CAST "";
24591     if (WXS_IS_ANY_SIMPLE_TYPE(type) || WXS_IS_ATOMIC(type)) {
24592 	xmlSchemaTypePtr biType; /* The built-in type. */
24593 	/*
24594 	* SPEC (1.2.1) "if {variety} is `atomic` then the string must `match`
24595 	* a literal in the `lexical space` of {base type definition}"
24596 	*/
24597 	/*
24598 	* Whitespace-normalize.
24599 	*/
24600 	NORMALIZE(type);
24601 	if (type->type != XML_SCHEMA_TYPE_BASIC) {
24602 	    /*
24603 	    * Get the built-in type.
24604 	    */
24605 	    biType = type->baseType;
24606 	    while ((biType != NULL) &&
24607 		(biType->type != XML_SCHEMA_TYPE_BASIC))
24608 		biType = biType->baseType;
24609 
24610 	    if (biType == NULL) {
24611 		AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24612 		    "could not get the built-in type");
24613 		goto internal_error;
24614 	    }
24615 	} else
24616 	    biType = type;
24617 	/*
24618 	* NOTATIONs need to be processed here, since they need
24619 	* to lookup in the hashtable of NOTATION declarations of the schema.
24620 	*/
24621 	if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
24622 	    switch (biType->builtInType) {
24623 		case XML_SCHEMAS_NOTATION:
24624 		    ret = xmlSchemaValidateNotation(
24625 			(xmlSchemaValidCtxtPtr) actxt,
24626 			((xmlSchemaValidCtxtPtr) actxt)->schema,
24627 			NULL, value, &val, valNeeded);
24628 		    break;
24629 		case XML_SCHEMAS_QNAME:
24630 		    ret = xmlSchemaValidateQName((xmlSchemaValidCtxtPtr) actxt,
24631 			value, &val, valNeeded);
24632 		    break;
24633 		default:
24634 		    /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
24635 		    if (valNeeded)
24636 			ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24637 			    value, &val, node);
24638 		    else
24639 			ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24640 			    value, NULL, node);
24641 		    break;
24642 	    }
24643 	} else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
24644 	    switch (biType->builtInType) {
24645 		case XML_SCHEMAS_NOTATION:
24646 		    ret = xmlSchemaValidateNotation(NULL,
24647 			((xmlSchemaParserCtxtPtr) actxt)->schema, node,
24648 			value, &val, valNeeded);
24649 		    break;
24650 		default:
24651 		    /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
24652 		    if (valNeeded)
24653 			ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24654 			    value, &val, node);
24655 		    else
24656 			ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24657 			    value, NULL, node);
24658 		    break;
24659 	    }
24660 	} else {
24661 	    /*
24662 	    * Validation via a public API is not implemented yet.
24663 	    */
24664 	    TODO
24665 	    goto internal_error;
24666 	}
24667 	if (ret != 0) {
24668 	    if (ret < 0) {
24669 		AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24670 		    "validating against a built-in type");
24671 		goto internal_error;
24672 	    }
24673 	    if (WXS_IS_LIST(type))
24674 		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24675 	    else
24676 		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24677 	}
24678 	if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24679 	    /*
24680 	    * Check facets.
24681 	    */
24682 	    ret = xmlSchemaValidateFacets(actxt, node, type,
24683 		(xmlSchemaValType) biType->builtInType, value, val,
24684 		0, fireErrors);
24685 	    if (ret != 0) {
24686 		if (ret < 0) {
24687 		    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24688 			"validating facets of atomic simple type");
24689 		    goto internal_error;
24690 		}
24691 		if (WXS_IS_LIST(type))
24692 		    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24693 		else
24694 		    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24695 	    }
24696 	}
24697 	if (fireErrors && (ret > 0))
24698 	    xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24699     } else if (WXS_IS_LIST(type)) {
24700 
24701 	xmlSchemaTypePtr itemType;
24702 	const xmlChar *cur, *end;
24703 	xmlChar *tmpValue = NULL;
24704 	unsigned long len = 0;
24705 	xmlSchemaValPtr prevVal = NULL, curVal = NULL;
24706 	/* 1.2.2 if {variety} is `list` then the string must be a sequence
24707 	* of white space separated tokens, each of which `match`es a literal
24708 	* in the `lexical space` of {item type definition}
24709 	*/
24710 	/*
24711 	* Note that XML_SCHEMAS_TYPE_NORMVALUENEEDED will be set if
24712 	* the list type has an enum or pattern facet.
24713 	*/
24714 	NORMALIZE(type);
24715 	/*
24716 	* VAL TODO: Optimize validation of empty values.
24717 	* VAL TODO: We do not have computed values for lists.
24718 	*/
24719 	itemType = WXS_LIST_ITEMTYPE(type);
24720 	cur = value;
24721 	do {
24722 	    while (IS_BLANK_CH(*cur))
24723 		cur++;
24724 	    end = cur;
24725 	    while ((*end != 0) && (!(IS_BLANK_CH(*end))))
24726 		end++;
24727 	    if (end == cur)
24728 		break;
24729 	    tmpValue = xmlStrndup(cur, end - cur);
24730 	    len++;
24731 
24732 	    if (valNeeded)
24733 		ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24734 		    tmpValue, &curVal, fireErrors, 0, 1);
24735 	    else
24736 		ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24737 		    tmpValue, NULL, fireErrors, 0, 1);
24738 	    FREE_AND_NULL(tmpValue);
24739 	    if (curVal != NULL) {
24740 		/*
24741 		* Add to list of computed values.
24742 		*/
24743 		if (val == NULL)
24744 		    val = curVal;
24745 		else
24746 		    xmlSchemaValueAppend(prevVal, curVal);
24747 		prevVal = curVal;
24748 		curVal = NULL;
24749 	    }
24750 	    if (ret != 0) {
24751 		if (ret < 0) {
24752 		    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24753 			"validating an item of list simple type");
24754 		    goto internal_error;
24755 		}
24756 		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24757 		break;
24758 	    }
24759 	    cur = end;
24760 	} while (*cur != 0);
24761 	FREE_AND_NULL(tmpValue);
24762 	if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24763 	    /*
24764 	    * Apply facets (pattern, enumeration).
24765 	    */
24766 	    ret = xmlSchemaValidateFacets(actxt, node, type,
24767 		XML_SCHEMAS_UNKNOWN, value, val,
24768 		len, fireErrors);
24769 	    if (ret != 0) {
24770 		if (ret < 0) {
24771 		    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24772 			"validating facets of list simple type");
24773 		    goto internal_error;
24774 		}
24775 		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24776 	    }
24777 	}
24778 	if (fireErrors && (ret > 0)) {
24779 	    /*
24780 	    * Report the normalized value.
24781 	    */
24782 	    normalize = 1;
24783 	    NORMALIZE(type);
24784 	    xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24785 	}
24786     } else if (WXS_IS_UNION(type)) {
24787 	xmlSchemaTypeLinkPtr memberLink;
24788 	/*
24789 	* TODO: For all datatypes `derived` by `union`  whiteSpace does
24790 	* not apply directly; however, the normalization behavior of `union`
24791 	* types is controlled by the value of whiteSpace on that one of the
24792 	* `memberTypes` against which the `union` is successfully validated.
24793 	*
24794 	* This means that the value is normalized by the first validating
24795 	* member type, then the facets of the union type are applied. This
24796 	* needs changing of the value!
24797 	*/
24798 
24799 	/*
24800 	* 1.2.3 if {variety} is `union` then the string must `match` a
24801 	* literal in the `lexical space` of at least one member of
24802 	* {member type definitions}
24803 	*/
24804 	memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
24805 	if (memberLink == NULL) {
24806 	    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24807 		"union simple type has no member types");
24808 	    goto internal_error;
24809 	}
24810 	/*
24811 	* Always normalize union type values, since we currently
24812 	* cannot store the whitespace information with the value
24813 	* itself; otherwise a later value-comparison would be
24814 	* not possible.
24815 	*/
24816 	while (memberLink != NULL) {
24817 	    if (valNeeded)
24818 		ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24819 		    memberLink->type, value, &val, 0, 1, 0);
24820 	    else
24821 		ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24822 		    memberLink->type, value, NULL, 0, 1, 0);
24823 	    if (ret <= 0)
24824 		break;
24825 	    memberLink = memberLink->next;
24826 	}
24827 	if (ret != 0) {
24828 	    if (ret < 0) {
24829 		AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24830 		    "validating members of union simple type");
24831 		goto internal_error;
24832 	    }
24833 	    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
24834 	}
24835 	/*
24836 	* Apply facets (pattern, enumeration).
24837 	*/
24838 	if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24839 	    /*
24840 	    * The normalization behavior of `union` types is controlled by
24841 	    * the value of whiteSpace on that one of the `memberTypes`
24842 	    * against which the `union` is successfully validated.
24843 	    */
24844 	    NORMALIZE(memberLink->type);
24845 	    ret = xmlSchemaValidateFacets(actxt, node, type,
24846 		XML_SCHEMAS_UNKNOWN, value, val,
24847 		0, fireErrors);
24848 	    if (ret != 0) {
24849 		if (ret < 0) {
24850 		    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24851 			"validating facets of union simple type");
24852 		    goto internal_error;
24853 		}
24854 		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
24855 	    }
24856 	}
24857 	if (fireErrors && (ret > 0))
24858 	    xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24859     }
24860 
24861     if (normValue != NULL)
24862 	xmlFree(normValue);
24863     if (ret == 0) {
24864 	if (retVal != NULL)
24865 	    *retVal = val;
24866 	else if (val != NULL)
24867 	    xmlSchemaFreeValue(val);
24868     } else if (val != NULL)
24869 	xmlSchemaFreeValue(val);
24870     return (ret);
24871 internal_error:
24872     if (normValue != NULL)
24873 	xmlFree(normValue);
24874     if (val != NULL)
24875 	xmlSchemaFreeValue(val);
24876     return (-1);
24877 }
24878 
24879 static int
xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt,const xmlChar * value,const xmlChar ** nsName,const xmlChar ** localName)24880 xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt,
24881 			   const xmlChar *value,
24882 			   const xmlChar **nsName,
24883 			   const xmlChar **localName)
24884 {
24885     int ret = 0;
24886 
24887     if ((nsName == NULL) || (localName == NULL))
24888 	return (-1);
24889     *nsName = NULL;
24890     *localName = NULL;
24891 
24892     ret = xmlValidateQName(value, 1);
24893     if (ret == -1)
24894 	return (-1);
24895     if (ret > 0) {
24896 	xmlSchemaSimpleTypeErr(ACTXT_CAST vctxt,
24897 	    XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
24898 	    value, xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), 1);
24899 	return (1);
24900     }
24901     {
24902 	xmlChar *local = NULL;
24903 	xmlChar *prefix;
24904 
24905 	/*
24906 	* NOTE: xmlSplitQName2 will return a duplicated
24907 	* string.
24908 	*/
24909 	local = xmlSplitQName2(value, &prefix);
24910 	if (local == NULL)
24911 	    *localName = xmlDictLookup(vctxt->dict, value, -1);
24912 	else {
24913 	    *localName = xmlDictLookup(vctxt->dict, local, -1);
24914 	    xmlFree(local);
24915 	}
24916 
24917 	*nsName = xmlSchemaLookupNamespace(vctxt, prefix);
24918 
24919 	if (prefix != NULL) {
24920 	    xmlFree(prefix);
24921 	    /*
24922 	    * A namespace must be found if the prefix is NOT NULL.
24923 	    */
24924 	    if (*nsName == NULL) {
24925 		xmlSchemaCustomErr(ACTXT_CAST vctxt,
24926 		    XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
24927 		    WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24928 		    "The QName value '%s' has no "
24929 		    "corresponding namespace declaration in scope",
24930 		    value, NULL);
24931 		return (2);
24932 	    }
24933 	}
24934     }
24935     return (0);
24936 }
24937 
24938 static int
xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,xmlSchemaAttrInfoPtr iattr,xmlSchemaTypePtr * localType,xmlSchemaElementPtr elemDecl)24939 xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,
24940 			xmlSchemaAttrInfoPtr iattr,
24941 			xmlSchemaTypePtr *localType,
24942 			xmlSchemaElementPtr elemDecl)
24943 {
24944     int ret = 0;
24945     /*
24946     * cvc-elt (3.3.4) : (4)
24947     * AND
24948     * Schema-Validity Assessment (Element) (cvc-assess-elt)
24949     *   (1.2.1.2.1) - (1.2.1.2.4)
24950     * Handle 'xsi:type'.
24951     */
24952     if (localType == NULL)
24953 	return (-1);
24954     *localType = NULL;
24955     if (iattr == NULL)
24956 	return (0);
24957     else {
24958 	const xmlChar *nsName = NULL, *local = NULL;
24959 	/*
24960 	* TODO: We should report a *warning* that the type was overriden
24961 	* by the instance.
24962 	*/
24963 	ACTIVATE_ATTRIBUTE(iattr);
24964 	/*
24965 	* (cvc-elt) (3.3.4) : (4.1)
24966 	* (cvc-assess-elt) (1.2.1.2.2)
24967 	*/
24968 	ret = xmlSchemaVExpandQName(vctxt, iattr->value,
24969 	    &nsName, &local);
24970 	if (ret != 0) {
24971 	    if (ret < 0) {
24972 		VERROR_INT("xmlSchemaValidateElementByDeclaration",
24973 		    "calling xmlSchemaQNameExpand() to validate the "
24974 		    "attribute 'xsi:type'");
24975 		goto internal_error;
24976 	    }
24977 	    goto exit;
24978 	}
24979 	/*
24980 	* (cvc-elt) (3.3.4) : (4.2)
24981 	* (cvc-assess-elt) (1.2.1.2.3)
24982 	*/
24983 	*localType = xmlSchemaGetType(vctxt->schema, local, nsName);
24984 	if (*localType == NULL) {
24985 	    xmlChar *str = NULL;
24986 
24987 	    xmlSchemaCustomErr(ACTXT_CAST vctxt,
24988 		XML_SCHEMAV_CVC_ELT_4_2, NULL,
24989 		WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24990 		"The QName value '%s' of the xsi:type attribute does not "
24991 		"resolve to a type definition",
24992 		xmlSchemaFormatQName(&str, nsName, local), NULL);
24993 	    FREE_AND_NULL(str);
24994 	    ret = vctxt->err;
24995 	    goto exit;
24996 	}
24997 	if (elemDecl != NULL) {
24998 	    int set = 0;
24999 
25000 	    /*
25001 	    * SPEC cvc-elt (3.3.4) : (4.3) (Type Derivation OK)
25002 	    * "The `local type definition` must be validly
25003 	    * derived from the {type definition} given the union of
25004 	    * the {disallowed substitutions} and the {type definition}'s
25005 	    * {prohibited substitutions}, as defined in
25006 	    * Type Derivation OK (Complex) ($3.4.6)
25007 	    * (if it is a complex type definition),
25008 	    * or given {disallowed substitutions} as defined in Type
25009 	    * Derivation OK (Simple) ($3.14.6) (if it is a simple type
25010 	    * definition)."
25011 	    *
25012 	    * {disallowed substitutions}: the "block" on the element decl.
25013 	    * {prohibited substitutions}: the "block" on the type def.
25014 	    */
25015 	    /*
25016 	    * OPTIMIZE TODO: We could map types already evaluated
25017 	    * to be validly derived from other types to avoid checking
25018 	    * this over and over for the same types.
25019 	    */
25020 	    if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) ||
25021 		(elemDecl->subtypes->flags &
25022 		    XML_SCHEMAS_TYPE_BLOCK_EXTENSION))
25023 		set |= SUBSET_EXTENSION;
25024 
25025 	    if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) ||
25026 		(elemDecl->subtypes->flags &
25027 		    XML_SCHEMAS_TYPE_BLOCK_RESTRICTION))
25028 		set |= SUBSET_RESTRICTION;
25029 
25030 	    /*
25031 	    * REMOVED and CHANGED since this produced a parser context
25032 	    * which adds to the string dict of the schema. So this would
25033 	    * change the schema and we don't want this. We don't need
25034 	    * the parser context anymore.
25035 	    *
25036 	    * if ((vctxt->pctxt == NULL) &&
25037 	    *	(xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
25038 	    *	    return (-1);
25039 	    */
25040 
25041 	    if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST vctxt, *localType,
25042 		elemDecl->subtypes, set) != 0) {
25043 		xmlChar *str = NULL;
25044 
25045 		xmlSchemaCustomErr(ACTXT_CAST vctxt,
25046 		    XML_SCHEMAV_CVC_ELT_4_3, NULL, NULL,
25047 		    "The type definition '%s', specified by xsi:type, is "
25048 		    "blocked or not validly derived from the type definition "
25049 		    "of the element declaration",
25050 		    xmlSchemaFormatQName(&str,
25051 			(*localType)->targetNamespace,
25052 			(*localType)->name),
25053 		    NULL);
25054 		FREE_AND_NULL(str);
25055 		ret = vctxt->err;
25056 		*localType = NULL;
25057 	    }
25058 	}
25059     }
25060 exit:
25061     ACTIVATE_ELEM;
25062     return (ret);
25063 internal_error:
25064     ACTIVATE_ELEM;
25065     return (-1);
25066 }
25067 
25068 static int
xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt)25069 xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt)
25070 {
25071     xmlSchemaElementPtr elemDecl = vctxt->inode->decl;
25072     xmlSchemaTypePtr actualType;
25073 
25074     /*
25075     * cvc-elt (3.3.4) : 1
25076     */
25077     if (elemDecl == NULL) {
25078 	VERROR(XML_SCHEMAV_CVC_ELT_1, NULL,
25079 	    "No matching declaration available");
25080         return (vctxt->err);
25081     }
25082     actualType = WXS_ELEM_TYPEDEF(elemDecl);
25083     /*
25084     * cvc-elt (3.3.4) : 2
25085     */
25086     if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
25087 	VERROR(XML_SCHEMAV_CVC_ELT_2, NULL,
25088 	    "The element declaration is abstract");
25089         return (vctxt->err);
25090     }
25091     if (actualType == NULL) {
25092 	VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
25093 	    "The type definition is absent");
25094 	return (XML_SCHEMAV_CVC_TYPE_1);
25095     }
25096     if (vctxt->nbAttrInfos != 0) {
25097 	int ret;
25098 	xmlSchemaAttrInfoPtr iattr;
25099 	/*
25100 	* cvc-elt (3.3.4) : 3
25101 	* Handle 'xsi:nil'.
25102 	*/
25103 	iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25104 	    XML_SCHEMA_ATTR_INFO_META_XSI_NIL);
25105 	if (iattr) {
25106 	    ACTIVATE_ATTRIBUTE(iattr);
25107 	    /*
25108 	    * Validate the value.
25109 	    */
25110 	    ret = xmlSchemaVCheckCVCSimpleType(
25111 		ACTXT_CAST vctxt, NULL,
25112 		xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
25113 		iattr->value, &(iattr->val), 1, 0, 0);
25114 	    ACTIVATE_ELEM;
25115 	    if (ret < 0) {
25116 		VERROR_INT("xmlSchemaValidateElemDecl",
25117 		    "calling xmlSchemaVCheckCVCSimpleType() to "
25118 		    "validate the attribute 'xsi:nil'");
25119 		return (-1);
25120 	    }
25121 	    if (ret == 0) {
25122 		if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
25123 		    /*
25124 		    * cvc-elt (3.3.4) : 3.1
25125 		    */
25126 		    VERROR(XML_SCHEMAV_CVC_ELT_3_1, NULL,
25127 			"The element is not 'nillable'");
25128 		    /* Does not return an error on purpose. */
25129 		} else {
25130 		    if (xmlSchemaValueGetAsBoolean(iattr->val)) {
25131 			/*
25132 			* cvc-elt (3.3.4) : 3.2.2
25133 			*/
25134 			if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
25135 			    (elemDecl->value != NULL)) {
25136 			    VERROR(XML_SCHEMAV_CVC_ELT_3_2_2, NULL,
25137 				"The element cannot be 'nilled' because "
25138 				"there is a fixed value constraint defined "
25139 				"for it");
25140 			     /* Does not return an error on purpose. */
25141 			} else
25142 			    vctxt->inode->flags |=
25143 				XML_SCHEMA_ELEM_INFO_NILLED;
25144 		    }
25145 		}
25146 	    }
25147 	}
25148 	/*
25149 	* cvc-elt (3.3.4) : 4
25150 	* Handle 'xsi:type'.
25151 	*/
25152 	iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25153 	    XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
25154 	if (iattr) {
25155 	    xmlSchemaTypePtr localType = NULL;
25156 
25157 	    ret = xmlSchemaProcessXSIType(vctxt, iattr, &localType,
25158 		elemDecl);
25159 	    if (ret != 0) {
25160 		if (ret == -1) {
25161 		    VERROR_INT("xmlSchemaValidateElemDecl",
25162 			"calling xmlSchemaProcessXSIType() to "
25163 			"process the attribute 'xsi:type'");
25164 		    return (-1);
25165 		}
25166 		/* Does not return an error on purpose. */
25167 	    }
25168 	    if (localType != NULL) {
25169 		vctxt->inode->flags |= XML_SCHEMA_ELEM_INFO_LOCAL_TYPE;
25170 		actualType = localType;
25171 	    }
25172 	}
25173     }
25174     /*
25175     * IDC: Register identity-constraint XPath matchers.
25176     */
25177     if ((elemDecl->idcs != NULL) &&
25178 	(xmlSchemaIDCRegisterMatchers(vctxt, elemDecl) == -1))
25179 	    return (-1);
25180     /*
25181     * No actual type definition.
25182     */
25183     if (actualType == NULL) {
25184 	VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
25185 	    "The type definition is absent");
25186 	return (XML_SCHEMAV_CVC_TYPE_1);
25187     }
25188     /*
25189     * Remember the actual type definition.
25190     */
25191     vctxt->inode->typeDef = actualType;
25192 
25193     return (0);
25194 }
25195 
25196 static int
xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt)25197 xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt)
25198 {
25199     xmlSchemaAttrInfoPtr iattr;
25200     int ret = 0, i;
25201 
25202     /*
25203     * SPEC cvc-type (3.1.1)
25204     * "The attributes of must be empty, excepting those whose namespace
25205     * name is identical to http://www.w3.org/2001/XMLSchema-instance and
25206     * whose local name is one of type, nil, schemaLocation or
25207     * noNamespaceSchemaLocation."
25208     */
25209     if (vctxt->nbAttrInfos == 0)
25210 	return (0);
25211     for (i = 0; i < vctxt->nbAttrInfos; i++) {
25212 	iattr = vctxt->attrInfos[i];
25213 	if (! iattr->metaType) {
25214 	    ACTIVATE_ATTRIBUTE(iattr)
25215 	    xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25216 		XML_SCHEMAV_CVC_TYPE_3_1_1, iattr, NULL);
25217 	    ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
25218         }
25219     }
25220     ACTIVATE_ELEM
25221     return (ret);
25222 }
25223 
25224 /*
25225 * Cleanup currently used attribute infos.
25226 */
25227 static void
xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)25228 xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)
25229 {
25230     int i;
25231     xmlSchemaAttrInfoPtr attr;
25232 
25233     if (vctxt->nbAttrInfos == 0)
25234 	return;
25235     for (i = 0; i < vctxt->nbAttrInfos; i++) {
25236 	attr = vctxt->attrInfos[i];
25237 	if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
25238 	    if (attr->localName != NULL)
25239 		xmlFree((xmlChar *) attr->localName);
25240 	    if (attr->nsName != NULL)
25241 		xmlFree((xmlChar *) attr->nsName);
25242 	}
25243 	if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
25244 	    if (attr->value != NULL)
25245 		xmlFree((xmlChar *) attr->value);
25246 	}
25247 	if (attr->val != NULL) {
25248 	    xmlSchemaFreeValue(attr->val);
25249 	    attr->val = NULL;
25250 	}
25251 	memset(attr, 0, sizeof(xmlSchemaAttrInfo));
25252     }
25253     vctxt->nbAttrInfos = 0;
25254 }
25255 
25256 /*
25257 * 3.4.4 Complex Type Definition Validation Rules
25258 *   Element Locally Valid (Complex Type) (cvc-complex-type)
25259 * 3.2.4 Attribute Declaration Validation Rules
25260 *   Validation Rule: Attribute Locally Valid (cvc-attribute)
25261 *   Attribute Locally Valid (Use) (cvc-au)
25262 *
25263 * Only "assessed" attribute information items will be visible to
25264 * IDCs. I.e. not "lax" (without declaration) and "skip" wild attributes.
25265 */
25266 static int
xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)25267 xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)
25268 {
25269     xmlSchemaTypePtr type = vctxt->inode->typeDef;
25270     xmlSchemaItemListPtr attrUseList;
25271     xmlSchemaAttributeUsePtr attrUse = NULL;
25272     xmlSchemaAttributePtr attrDecl = NULL;
25273     xmlSchemaAttrInfoPtr iattr, tmpiattr;
25274     int i, j, found, nbAttrs, nbUses;
25275     int xpathRes = 0, res, wildIDs = 0, fixed;
25276     xmlNodePtr defAttrOwnerElem = NULL;
25277 
25278     /*
25279     * SPEC (cvc-attribute)
25280     * (1) "The declaration must not be `absent` (see Missing
25281     * Sub-components ($5.3) for how this can fail to be
25282     * the case)."
25283     * (2) "Its {type definition} must not be absent."
25284     *
25285     * NOTE (1) + (2): This is not handled here, since we currently do not
25286     * allow validation against schemas which have missing sub-components.
25287     *
25288     * SPEC (cvc-complex-type)
25289     * (3) "For each attribute information item in the element information
25290     * item's [attributes] excepting those whose [namespace name] is
25291     * identical to http://www.w3.org/2001/XMLSchema-instance and whose
25292     * [local name] is one of type, nil, schemaLocation or
25293     * noNamespaceSchemaLocation, the appropriate case among the following
25294     * must be true:
25295     *
25296     */
25297     attrUseList = (xmlSchemaItemListPtr) type->attrUses;
25298     /*
25299     * @nbAttrs is the number of attributes present in the instance.
25300     */
25301     nbAttrs = vctxt->nbAttrInfos;
25302     if (attrUseList != NULL)
25303 	nbUses = attrUseList->nbItems;
25304     else
25305 	nbUses = 0;
25306     for (i = 0; i < nbUses; i++) {
25307         found = 0;
25308 	attrUse = attrUseList->items[i];
25309 	attrDecl = WXS_ATTRUSE_DECL(attrUse);
25310         for (j = 0; j < nbAttrs; j++) {
25311 	    iattr = vctxt->attrInfos[j];
25312 	    /*
25313 	    * SPEC (cvc-complex-type) (3)
25314 	    * Skip meta attributes.
25315 	    */
25316 	    if (iattr->metaType)
25317 		continue;
25318 	    if (iattr->localName[0] != attrDecl->name[0])
25319 		continue;
25320 	    if (!xmlStrEqual(iattr->localName, attrDecl->name))
25321 		continue;
25322 	    if (!xmlStrEqual(iattr->nsName, attrDecl->targetNamespace))
25323 		continue;
25324 	    found = 1;
25325 	    /*
25326 	    * SPEC (cvc-complex-type)
25327 	    * (3.1) "If there is among the {attribute uses} an attribute
25328 	    * use with an {attribute declaration} whose {name} matches
25329 	    * the attribute information item's [local name] and whose
25330 	    * {target namespace} is identical to the attribute information
25331 	    * item's [namespace name] (where an `absent` {target namespace}
25332 	    * is taken to be identical to a [namespace name] with no value),
25333 	    * then the attribute information must be `valid` with respect
25334 	    * to that attribute use as per Attribute Locally Valid (Use)
25335 	    * ($3.5.4). In this case the {attribute declaration} of that
25336 	    * attribute use is the `context-determined declaration` for the
25337 	    * attribute information item with respect to Schema-Validity
25338 	    * Assessment (Attribute) ($3.2.4) and
25339 	    * Assessment Outcome (Attribute) ($3.2.5).
25340 	    */
25341 	    iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
25342 	    iattr->use = attrUse;
25343 	    /*
25344 	    * Context-determined declaration.
25345 	    */
25346 	    iattr->decl = attrDecl;
25347 	    iattr->typeDef = attrDecl->subtypes;
25348 	    break;
25349 	}
25350 
25351 	if (found)
25352 	    continue;
25353 
25354 	if (attrUse->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
25355 	    /*
25356 	    * Handle non-existent, required attributes.
25357 	    *
25358 	    * SPEC (cvc-complex-type)
25359 	    * (4) "The {attribute declaration} of each attribute use in
25360 	    * the {attribute uses} whose {required} is true matches one
25361 	    * of the attribute information items in the element information
25362 	    * item's [attributes] as per clause 3.1 above."
25363 	    */
25364 	    tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
25365 	    if (tmpiattr == NULL) {
25366 		VERROR_INT(
25367 		    "xmlSchemaVAttributesComplex",
25368 		    "calling xmlSchemaGetFreshAttrInfo()");
25369 		return (-1);
25370 	    }
25371 	    tmpiattr->state = XML_SCHEMAS_ATTR_ERR_MISSING;
25372 	    tmpiattr->use = attrUse;
25373 	    tmpiattr->decl = attrDecl;
25374 	} else if ((attrUse->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
25375 	    ((attrUse->defValue != NULL) ||
25376 	     (attrDecl->defValue != NULL))) {
25377 	    /*
25378 	    * Handle non-existent, optional, default/fixed attributes.
25379 	    */
25380 	    tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
25381 	    if (tmpiattr == NULL) {
25382 		VERROR_INT(
25383 		    "xmlSchemaVAttributesComplex",
25384 		    "calling xmlSchemaGetFreshAttrInfo()");
25385 		return (-1);
25386 	    }
25387 	    tmpiattr->state = XML_SCHEMAS_ATTR_DEFAULT;
25388 	    tmpiattr->use = attrUse;
25389 	    tmpiattr->decl = attrDecl;
25390 	    tmpiattr->typeDef = attrDecl->subtypes;
25391 	    tmpiattr->localName = attrDecl->name;
25392 	    tmpiattr->nsName = attrDecl->targetNamespace;
25393 	}
25394     }
25395 
25396     if (vctxt->nbAttrInfos == 0)
25397 	return (0);
25398     /*
25399     * Validate against the wildcard.
25400     */
25401     if (type->attributeWildcard != NULL) {
25402 	/*
25403 	* SPEC (cvc-complex-type)
25404 	* (3.2.1) "There must be an {attribute wildcard}."
25405 	*/
25406 	for (i = 0; i < nbAttrs; i++) {
25407 	    iattr = vctxt->attrInfos[i];
25408 	    /*
25409 	    * SPEC (cvc-complex-type) (3)
25410 	    * Skip meta attributes.
25411 	    */
25412 	    if (iattr->state != XML_SCHEMAS_ATTR_UNKNOWN)
25413 		continue;
25414 	    /*
25415 	    * SPEC (cvc-complex-type)
25416 	    * (3.2.2) "The attribute information item must be `valid` with
25417 	    * respect to it as defined in Item Valid (Wildcard) ($3.10.4)."
25418 	    *
25419 	    * SPEC Item Valid (Wildcard) (cvc-wildcard)
25420 	    * "... its [namespace name] must be `valid` with respect to
25421 	    * the wildcard constraint, as defined in Wildcard allows
25422 	    * Namespace Name ($3.10.4)."
25423 	    */
25424 	    if (xmlSchemaCheckCVCWildcardNamespace(type->attributeWildcard,
25425 		    iattr->nsName) == 0) {
25426 		/*
25427 		* Handle processContents.
25428 		*
25429 		* SPEC (cvc-wildcard):
25430 		* processContents | context-determined declaration:
25431 		* "strict"          "mustFind"
25432 		* "lax"             "none"
25433 		* "skip"            "skip"
25434 		*/
25435 		if (type->attributeWildcard->processContents ==
25436 		    XML_SCHEMAS_ANY_SKIP) {
25437 		     /*
25438 		    * context-determined declaration = "skip"
25439 		    *
25440 		    * SPEC PSVI Assessment Outcome (Attribute)
25441 		    * [validity] = "notKnown"
25442 		    * [validation attempted] = "none"
25443 		    */
25444 		    iattr->state = XML_SCHEMAS_ATTR_WILD_SKIP;
25445 		    continue;
25446 		}
25447 		/*
25448 		* Find an attribute declaration.
25449 		*/
25450 		iattr->decl = xmlSchemaGetAttributeDecl(vctxt->schema,
25451 		    iattr->localName, iattr->nsName);
25452 		if (iattr->decl != NULL) {
25453 		    iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
25454 		    /*
25455 		    * SPEC (cvc-complex-type)
25456 		    * (5) "Let [Definition:]  the wild IDs be the set of
25457 		    * all attribute information item to which clause 3.2
25458 		    * applied and whose `validation` resulted in a
25459 		    * `context-determined declaration` of mustFind or no
25460 		    * `context-determined declaration` at all, and whose
25461 		    * [local name] and [namespace name] resolve (as
25462 		    * defined by QName resolution (Instance) ($3.15.4)) to
25463 		    * an attribute declaration whose {type definition} is
25464 		    * or is derived from ID. Then all of the following
25465 		    * must be true:"
25466 		    */
25467 		    iattr->typeDef = WXS_ATTR_TYPEDEF(iattr->decl);
25468 		    if (xmlSchemaIsDerivedFromBuiltInType(
25469 			iattr->typeDef, XML_SCHEMAS_ID)) {
25470 			/*
25471 			* SPEC (5.1) "There must be no more than one
25472 			* item in `wild IDs`."
25473 			*/
25474 			if (wildIDs != 0) {
25475 			    /* VAL TODO */
25476 			    iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID;
25477 			    TODO
25478 			    continue;
25479 			}
25480 			wildIDs++;
25481 			/*
25482 			* SPEC (cvc-complex-type)
25483 			* (5.2) "If `wild IDs` is non-empty, there must not
25484 			* be any attribute uses among the {attribute uses}
25485 			* whose {attribute declaration}'s {type definition}
25486 			* is or is derived from ID."
25487 			*/
25488                         if (attrUseList != NULL) {
25489                             for (j = 0; j < attrUseList->nbItems; j++) {
25490                                 if (xmlSchemaIsDerivedFromBuiltInType(
25491                                     WXS_ATTRUSE_TYPEDEF(attrUseList->items[j]),
25492                                     XML_SCHEMAS_ID)) {
25493                                     /* URGENT VAL TODO: implement */
25494                             iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID;
25495                                     TODO
25496                                     break;
25497                                 }
25498                             }
25499                         }
25500 		    }
25501 		} else if (type->attributeWildcard->processContents ==
25502 		    XML_SCHEMAS_ANY_LAX) {
25503 		    iattr->state = XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL;
25504 		    /*
25505 		    * SPEC PSVI Assessment Outcome (Attribute)
25506 		    * [validity] = "notKnown"
25507 		    * [validation attempted] = "none"
25508 		    */
25509 		} else {
25510 		    iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL;
25511 		}
25512 	    }
25513 	}
25514     }
25515 
25516     if (vctxt->nbAttrInfos == 0)
25517 	return (0);
25518 
25519     /*
25520     * Get the owner element; needed for creation of default attributes.
25521     * This fixes bug #341337, reported by David Grohmann.
25522     */
25523     if (vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
25524 	xmlSchemaNodeInfoPtr ielem = vctxt->elemInfos[vctxt->depth];
25525 	if (ielem && ielem->node && ielem->node->doc)
25526 	    defAttrOwnerElem = ielem->node;
25527     }
25528     /*
25529     * Validate values, create default attributes, evaluate IDCs.
25530     */
25531     for (i = 0; i < vctxt->nbAttrInfos; i++) {
25532 	iattr = vctxt->attrInfos[i];
25533 	/*
25534 	* VAL TODO: Note that we won't try to resolve IDCs to
25535 	* "lax" and "skip" validated attributes. Check what to
25536 	* do in this case.
25537 	*/
25538 	if ((iattr->state != XML_SCHEMAS_ATTR_ASSESSED) &&
25539 	    (iattr->state != XML_SCHEMAS_ATTR_DEFAULT))
25540 	    continue;
25541 	/*
25542 	* VAL TODO: What to do if the type definition is missing?
25543 	*/
25544 	if (iattr->typeDef == NULL) {
25545 	    iattr->state = XML_SCHEMAS_ATTR_ERR_NO_TYPE;
25546 	    continue;
25547 	}
25548 
25549 	ACTIVATE_ATTRIBUTE(iattr);
25550 	fixed = 0;
25551 	xpathRes = 0;
25552 
25553 	if (vctxt->xpathStates != NULL) {
25554 	    /*
25555 	    * Evaluate IDCs.
25556 	    */
25557 	    xpathRes = xmlSchemaXPathEvaluate(vctxt,
25558 		XML_ATTRIBUTE_NODE);
25559 	    if (xpathRes == -1) {
25560 		VERROR_INT("xmlSchemaVAttributesComplex",
25561 		    "calling xmlSchemaXPathEvaluate()");
25562 		goto internal_error;
25563 	    }
25564 	}
25565 
25566 	if (iattr->state == XML_SCHEMAS_ATTR_DEFAULT) {
25567 	    /*
25568 	    * Default/fixed attributes.
25569 	    * We need the value only if we need to resolve IDCs or
25570 	    * will create default attributes.
25571 	    */
25572 	    if ((xpathRes) || (defAttrOwnerElem)) {
25573 		if (iattr->use->defValue != NULL) {
25574 		    iattr->value = (xmlChar *) iattr->use->defValue;
25575 		    iattr->val = iattr->use->defVal;
25576 		} else {
25577 		    iattr->value = (xmlChar *) iattr->decl->defValue;
25578 		    iattr->val = iattr->decl->defVal;
25579 		}
25580 		/*
25581 		* IDCs will consume the precomputed default value,
25582 		* so we need to clone it.
25583 		*/
25584 		if (iattr->val == NULL) {
25585 		    VERROR_INT("xmlSchemaVAttributesComplex",
25586 			"default/fixed value on an attribute use was "
25587 			"not precomputed");
25588 		    goto internal_error;
25589 		}
25590 		iattr->val = xmlSchemaCopyValue(iattr->val);
25591 		if (iattr->val == NULL) {
25592 		    VERROR_INT("xmlSchemaVAttributesComplex",
25593 			"calling xmlSchemaCopyValue()");
25594 		    goto internal_error;
25595 		}
25596 	    }
25597 	    /*
25598 	    * PSVI: Add the default attribute to the current element.
25599 	    * VAL TODO: Should we use the *normalized* value? This currently
25600 	    *   uses the *initial* value.
25601 	    */
25602 
25603 	    if (defAttrOwnerElem) {
25604 		xmlChar *normValue;
25605 		const xmlChar *value;
25606 
25607 		value = iattr->value;
25608 		/*
25609 		* Normalize the value.
25610 		*/
25611 		normValue = xmlSchemaNormalizeValue(iattr->typeDef,
25612 		    iattr->value);
25613 		if (normValue != NULL)
25614 		    value = BAD_CAST normValue;
25615 
25616 		if (iattr->nsName == NULL) {
25617 		    if (xmlNewProp(defAttrOwnerElem,
25618 			iattr->localName, value) == NULL) {
25619 			VERROR_INT("xmlSchemaVAttributesComplex",
25620 			    "calling xmlNewProp()");
25621 			if (normValue != NULL)
25622 			    xmlFree(normValue);
25623 			goto internal_error;
25624 		    }
25625 		} else {
25626 		    xmlNsPtr ns;
25627 
25628 		    ns = xmlSearchNsByHref(defAttrOwnerElem->doc,
25629 			defAttrOwnerElem, iattr->nsName);
25630 		    if (ns == NULL) {
25631 			xmlChar prefix[12];
25632 			int counter = 0;
25633 
25634 			/*
25635 			* Create a namespace declaration on the validation
25636 			* root node if no namespace declaration is in scope.
25637 			*/
25638 			do {
25639 			    snprintf((char *) prefix, 12, "p%d", counter++);
25640 			    ns = xmlSearchNs(defAttrOwnerElem->doc,
25641 				defAttrOwnerElem, BAD_CAST prefix);
25642 			    if (counter > 1000) {
25643 				VERROR_INT(
25644 				    "xmlSchemaVAttributesComplex",
25645 				    "could not compute a ns prefix for a "
25646 				    "default/fixed attribute");
25647 				if (normValue != NULL)
25648 				    xmlFree(normValue);
25649 				goto internal_error;
25650 			    }
25651 			} while (ns != NULL);
25652 			ns = xmlNewNs(vctxt->validationRoot,
25653 			    iattr->nsName, BAD_CAST prefix);
25654 		    }
25655 		    /*
25656 		    * TODO:
25657 		    * http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0406.html
25658 		    * If we have QNames: do we need to ensure there's a
25659 		    * prefix defined for the QName?
25660 		    */
25661 		    xmlNewNsProp(defAttrOwnerElem, ns, iattr->localName, value);
25662 		}
25663 		if (normValue != NULL)
25664 		    xmlFree(normValue);
25665 	    }
25666 	    /*
25667 	    * Go directly to IDC evaluation.
25668 	    */
25669 	    goto eval_idcs;
25670 	}
25671 	/*
25672 	* Validate the value.
25673 	*/
25674 	if (vctxt->value != NULL) {
25675 	    /*
25676 	    * Free last computed value; just for safety reasons.
25677 	    */
25678 	    xmlSchemaFreeValue(vctxt->value);
25679 	    vctxt->value = NULL;
25680 	}
25681 	/*
25682 	* Note that the attribute *use* can be unavailable, if
25683 	* the attribute was a wild attribute.
25684 	*/
25685 	if ((iattr->decl->flags & XML_SCHEMAS_ATTR_FIXED) ||
25686 	    ((iattr->use != NULL) &&
25687 	     (iattr->use->flags & XML_SCHEMAS_ATTR_FIXED)))
25688 	    fixed = 1;
25689 	else
25690 	    fixed = 0;
25691 	/*
25692 	* SPEC (cvc-attribute)
25693 	* (3) "The item's `normalized value` must be locally `valid`
25694 	* with respect to that {type definition} as per
25695 	* String Valid ($3.14.4)."
25696 	*
25697 	* VAL TODO: Do we already have the
25698 	* "normalized attribute value" here?
25699 	*/
25700 	if (xpathRes || fixed) {
25701 	    iattr->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
25702 	    /*
25703 	    * Request a computed value.
25704 	    */
25705 	    res = xmlSchemaVCheckCVCSimpleType(
25706 		ACTXT_CAST vctxt,
25707 		iattr->node, iattr->typeDef, iattr->value, &(iattr->val),
25708 		1, 1, 0);
25709 	} else {
25710 	    res = xmlSchemaVCheckCVCSimpleType(
25711 		ACTXT_CAST vctxt,
25712 		iattr->node, iattr->typeDef, iattr->value, NULL,
25713 		1, 0, 0);
25714 	}
25715 
25716 	if (res != 0) {
25717 	    if (res == -1) {
25718 		VERROR_INT("xmlSchemaVAttributesComplex",
25719 		    "calling xmlSchemaStreamValidateSimpleTypeValue()");
25720 		goto internal_error;
25721 	    }
25722 	    iattr->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
25723 	    /*
25724 	    * SPEC PSVI Assessment Outcome (Attribute)
25725 	    * [validity] = "invalid"
25726 	    */
25727 	    goto eval_idcs;
25728 	}
25729 
25730 	if (fixed) {
25731 	    /*
25732 	    * SPEC Attribute Locally Valid (Use) (cvc-au)
25733 	    * "For an attribute information item to be `valid`
25734 	    * with respect to an attribute use its *normalized*
25735 	    * value must match the *canonical* lexical
25736 	    * representation of the attribute use's {value
25737 	    * constraint}value, if it is present and fixed."
25738 	    *
25739 	    * VAL TODO: The requirement for the *canonical* value
25740 	    * will be removed in XML Schema 1.1.
25741 	    */
25742 	    /*
25743 	    * SPEC Attribute Locally Valid (cvc-attribute)
25744 	    * (4) "The item's *actual* value must match the *value* of
25745 	    * the {value constraint}, if it is present and fixed."
25746 	    */
25747 	    if (iattr->val == NULL) {
25748 		/* VAL TODO: A value was not precomputed. */
25749 		TODO
25750 		goto eval_idcs;
25751 	    }
25752 	    if ((iattr->use != NULL) &&
25753 		(iattr->use->defValue != NULL)) {
25754 		if (iattr->use->defVal == NULL) {
25755 		    /* VAL TODO: A default value was not precomputed. */
25756 		    TODO
25757 		    goto eval_idcs;
25758 		}
25759 		iattr->vcValue = iattr->use->defValue;
25760 		/*
25761 		if (xmlSchemaCompareValuesWhtsp(attr->val,
25762 		    (xmlSchemaWhitespaceValueType) ws,
25763 		    attr->use->defVal,
25764 		    (xmlSchemaWhitespaceValueType) ws) != 0) {
25765 		*/
25766 		if (! xmlSchemaAreValuesEqual(iattr->val, iattr->use->defVal))
25767 		    iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
25768 	    } else {
25769 		if (iattr->decl->defVal == NULL) {
25770 		    /* VAL TODO: A default value was not precomputed. */
25771 		    TODO
25772 		    goto eval_idcs;
25773 		}
25774 		iattr->vcValue = iattr->decl->defValue;
25775 		/*
25776 		if (xmlSchemaCompareValuesWhtsp(attr->val,
25777 		    (xmlSchemaWhitespaceValueType) ws,
25778 		    attrDecl->defVal,
25779 		    (xmlSchemaWhitespaceValueType) ws) != 0) {
25780 		*/
25781 		if (! xmlSchemaAreValuesEqual(iattr->val, iattr->decl->defVal))
25782 		    iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
25783 	    }
25784 	    /*
25785 	    * [validity] = "valid"
25786 	    */
25787 	}
25788 eval_idcs:
25789 	/*
25790 	* Evaluate IDCs.
25791 	*/
25792 	if (xpathRes) {
25793 	    if (xmlSchemaXPathProcessHistory(vctxt,
25794 		vctxt->depth +1) == -1) {
25795 		VERROR_INT("xmlSchemaVAttributesComplex",
25796 		    "calling xmlSchemaXPathEvaluate()");
25797 		goto internal_error;
25798 	    }
25799 	} else if (vctxt->xpathStates != NULL)
25800 	    xmlSchemaXPathPop(vctxt);
25801     }
25802 
25803     /*
25804     * Report errors.
25805     */
25806     for (i = 0; i < vctxt->nbAttrInfos; i++) {
25807 	iattr = vctxt->attrInfos[i];
25808 	if ((iattr->state == XML_SCHEMAS_ATTR_META) ||
25809 	    (iattr->state == XML_SCHEMAS_ATTR_ASSESSED) ||
25810 	    (iattr->state == XML_SCHEMAS_ATTR_WILD_SKIP) ||
25811 	    (iattr->state == XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL))
25812 	    continue;
25813 	ACTIVATE_ATTRIBUTE(iattr);
25814 	switch (iattr->state) {
25815 	    case XML_SCHEMAS_ATTR_ERR_MISSING: {
25816 		    xmlChar *str = NULL;
25817 		    ACTIVATE_ELEM;
25818 		    xmlSchemaCustomErr(ACTXT_CAST vctxt,
25819 			XML_SCHEMAV_CVC_COMPLEX_TYPE_4, NULL, NULL,
25820 			"The attribute '%s' is required but missing",
25821 			xmlSchemaFormatQName(&str,
25822 			    iattr->decl->targetNamespace,
25823 			    iattr->decl->name),
25824 			NULL);
25825 		    FREE_AND_NULL(str)
25826 		    break;
25827 		}
25828 	    case XML_SCHEMAS_ATTR_ERR_NO_TYPE:
25829 		VERROR(XML_SCHEMAV_CVC_ATTRIBUTE_2, NULL,
25830 		    "The type definition is absent");
25831 		break;
25832 	    case XML_SCHEMAS_ATTR_ERR_FIXED_VALUE:
25833 		xmlSchemaCustomErr(ACTXT_CAST vctxt,
25834 		    XML_SCHEMAV_CVC_AU, NULL, NULL,
25835 		    "The value '%s' does not match the fixed "
25836 		    "value constraint '%s'",
25837 		    iattr->value, iattr->vcValue);
25838 		break;
25839 	    case XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL:
25840 		VERROR(XML_SCHEMAV_CVC_WILDCARD, NULL,
25841 		    "No matching global attribute declaration available, but "
25842 		    "demanded by the strict wildcard");
25843 		break;
25844 	    case XML_SCHEMAS_ATTR_UNKNOWN:
25845 		if (iattr->metaType)
25846 		    break;
25847 		/*
25848 		* MAYBE VAL TODO: One might report different error messages
25849 		* for the following errors.
25850 		*/
25851 		if (type->attributeWildcard == NULL) {
25852 		    xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25853 			XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, iattr, NULL);
25854 		} else {
25855 		    xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25856 			XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, iattr, NULL);
25857 		}
25858 		break;
25859 	    default:
25860 		break;
25861 	}
25862     }
25863 
25864     ACTIVATE_ELEM;
25865     return (0);
25866 internal_error:
25867     ACTIVATE_ELEM;
25868     return (-1);
25869 }
25870 
25871 static int
xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt,int * skip)25872 xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt,
25873 			      int *skip)
25874 {
25875     xmlSchemaWildcardPtr wild = (xmlSchemaWildcardPtr) vctxt->inode->decl;
25876     /*
25877     * The namespace of the element was already identified to be
25878     * matching the wildcard.
25879     */
25880     if ((skip == NULL) || (wild == NULL) ||
25881 	(wild->type != XML_SCHEMA_TYPE_ANY)) {
25882 	VERROR_INT("xmlSchemaValidateElemWildcard",
25883 	    "bad arguments");
25884 	return (-1);
25885     }
25886     *skip = 0;
25887     if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
25888 	/*
25889 	* URGENT VAL TODO: Either we need to position the stream to the
25890 	* next sibling, or walk the whole subtree.
25891 	*/
25892 	*skip = 1;
25893 	return (0);
25894     }
25895     {
25896 	xmlSchemaElementPtr decl = NULL;
25897 
25898 	decl = xmlSchemaGetElem(vctxt->schema,
25899 	    vctxt->inode->localName, vctxt->inode->nsName);
25900 	if (decl != NULL) {
25901 	    vctxt->inode->decl = decl;
25902 	    return (0);
25903 	}
25904     }
25905     if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
25906 	/* VAL TODO: Change to proper error code. */
25907 	VERROR(XML_SCHEMAV_CVC_ELT_1, NULL, /* WXS_BASIC_CAST wild */
25908 	    "No matching global element declaration available, but "
25909 	    "demanded by the strict wildcard");
25910 	return (vctxt->err);
25911     }
25912     if (vctxt->nbAttrInfos != 0) {
25913 	xmlSchemaAttrInfoPtr iattr;
25914 	/*
25915 	* SPEC Validation Rule: Schema-Validity Assessment (Element)
25916 	* (1.2.1.2.1) - (1.2.1.2.3 )
25917 	*
25918 	* Use the xsi:type attribute for the type definition.
25919 	*/
25920 	iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25921 	    XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
25922 	if (iattr != NULL) {
25923 	    if (xmlSchemaProcessXSIType(vctxt, iattr,
25924 		&(vctxt->inode->typeDef), NULL) == -1) {
25925 		VERROR_INT("xmlSchemaValidateElemWildcard",
25926 		    "calling xmlSchemaProcessXSIType() to "
25927 		    "process the attribute 'xsi:nil'");
25928 		return (-1);
25929 	    }
25930 	    /*
25931 	    * Don't return an error on purpose.
25932 	    */
25933 	    return (0);
25934 	}
25935     }
25936     /*
25937     * SPEC Validation Rule: Schema-Validity Assessment (Element)
25938     *
25939     * Fallback to "anyType".
25940     */
25941     vctxt->inode->typeDef =
25942 	xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
25943     return (0);
25944 }
25945 
25946 /*
25947 * xmlSchemaCheckCOSValidDefault:
25948 *
25949 * This will be called if: not nilled, no content and a default/fixed
25950 * value is provided.
25951 */
25952 
25953 static int
xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt,const xmlChar * value,xmlSchemaValPtr * val)25954 xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt,
25955 			      const xmlChar *value,
25956 			      xmlSchemaValPtr *val)
25957 {
25958     int ret = 0;
25959     xmlSchemaNodeInfoPtr inode = vctxt->inode;
25960 
25961     /*
25962     * cos-valid-default:
25963     * Schema Component Constraint: Element Default Valid (Immediate)
25964     * For a string to be a valid default with respect to a type
25965     * definition the appropriate case among the following must be true:
25966     */
25967     if WXS_IS_COMPLEX(inode->typeDef) {
25968 	/*
25969 	* Complex type.
25970 	*
25971 	* SPEC (2.1) "its {content type} must be a simple type definition
25972 	* or mixed."
25973 	* SPEC (2.2.2) "If the {content type} is mixed, then the {content
25974 	* type}'s particle must be `emptiable` as defined by
25975 	* Particle Emptiable ($3.9.6)."
25976 	*/
25977 	if ((! WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) &&
25978 	    ((! WXS_HAS_MIXED_CONTENT(inode->typeDef)) ||
25979 	     (! WXS_EMPTIABLE(inode->typeDef)))) {
25980 	    ret = XML_SCHEMAP_COS_VALID_DEFAULT_2_1;
25981 	    /* NOTE that this covers (2.2.2) as well. */
25982 	    VERROR(ret, NULL,
25983 		"For a string to be a valid default, the type definition "
25984 		"must be a simple type or a complex type with simple content "
25985 		"or mixed content and a particle emptiable");
25986 	    return(ret);
25987 	}
25988     }
25989     /*
25990     * 1 If the type definition is a simple type definition, then the string
25991     * must be `valid` with respect to that definition as defined by String
25992     * Valid ($3.14.4).
25993     *
25994     * AND
25995     *
25996     * 2.2.1 If the {content type} is a simple type definition, then the
25997     * string must be `valid` with respect to that simple type definition
25998     * as defined by String Valid ($3.14.4).
25999     */
26000     if (WXS_IS_SIMPLE(inode->typeDef)) {
26001 
26002 	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
26003 	    NULL, inode->typeDef, value, val, 1, 1, 0);
26004 
26005     } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26006 
26007 	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
26008 	    NULL, inode->typeDef->contentTypeDef, value, val, 1, 1, 0);
26009     }
26010     if (ret < 0) {
26011 	VERROR_INT("xmlSchemaCheckCOSValidDefault",
26012 	    "calling xmlSchemaVCheckCVCSimpleType()");
26013     }
26014     return (ret);
26015 }
26016 
26017 static void
xmlSchemaVContentModelCallback(xmlRegExecCtxtPtr exec ATTRIBUTE_UNUSED,const xmlChar * name ATTRIBUTE_UNUSED,void * transdata,void * inputdata)26018 xmlSchemaVContentModelCallback(xmlRegExecCtxtPtr exec ATTRIBUTE_UNUSED,
26019 			       const xmlChar * name ATTRIBUTE_UNUSED,
26020 			       void *transdata, void *inputdata)
26021 {
26022     xmlSchemaElementPtr item = (xmlSchemaElementPtr) transdata;
26023     xmlSchemaNodeInfoPtr inode = (xmlSchemaNodeInfoPtr) inputdata;
26024     inode->decl = item;
26025 #ifdef DEBUG_CONTENT
26026     {
26027 	xmlChar *str = NULL;
26028 
26029 	if (item->type == XML_SCHEMA_TYPE_ELEMENT) {
26030 	    xmlGenericError(xmlGenericErrorContext,
26031 		"AUTOMATON callback for '%s' [declaration]\n",
26032 		xmlSchemaFormatQName(&str,
26033 		inode->localName, inode->nsName));
26034 	} else {
26035 	    xmlGenericError(xmlGenericErrorContext,
26036 		    "AUTOMATON callback for '%s' [wildcard]\n",
26037 		    xmlSchemaFormatQName(&str,
26038 		    inode->localName, inode->nsName));
26039 
26040 	}
26041 	FREE_AND_NULL(str)
26042     }
26043 #endif
26044 }
26045 
26046 static int
xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt)26047 xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt)
26048 {
26049     vctxt->inode = xmlSchemaGetFreshElemInfo(vctxt);
26050     if (vctxt->inode == NULL) {
26051 	VERROR_INT("xmlSchemaValidatorPushElem",
26052 	    "calling xmlSchemaGetFreshElemInfo()");
26053 	return (-1);
26054     }
26055     vctxt->nbAttrInfos = 0;
26056     return (0);
26057 }
26058 
26059 static int
xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt,xmlSchemaNodeInfoPtr inode,xmlSchemaTypePtr type,const xmlChar * value)26060 xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt,
26061 			     xmlSchemaNodeInfoPtr inode,
26062 			     xmlSchemaTypePtr type,
26063 			     const xmlChar *value)
26064 {
26065     if (inode->flags & XML_SCHEMA_NODE_INFO_VALUE_NEEDED)
26066 	return (xmlSchemaVCheckCVCSimpleType(
26067 	    ACTXT_CAST vctxt, NULL,
26068 	    type, value, &(inode->val), 1, 1, 0));
26069     else
26070 	return (xmlSchemaVCheckCVCSimpleType(
26071 	    ACTXT_CAST vctxt, NULL,
26072 	    type, value, NULL, 1, 0, 0));
26073 }
26074 
26075 
26076 
26077 /*
26078 * Process END of element.
26079 */
26080 static int
xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)26081 xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)
26082 {
26083     int ret = 0;
26084     xmlSchemaNodeInfoPtr inode = vctxt->inode;
26085 
26086     if (vctxt->nbAttrInfos != 0)
26087 	xmlSchemaClearAttrInfos(vctxt);
26088     if (inode->flags & XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED) {
26089 	/*
26090 	* This element was not expected;
26091 	* we will not validate child elements of broken parents.
26092 	* Skip validation of all content of the parent.
26093 	*/
26094 	vctxt->skipDepth = vctxt->depth -1;
26095 	goto end_elem;
26096     }
26097     if ((inode->typeDef == NULL) ||
26098 	(inode->flags & XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE)) {
26099 	/*
26100 	* 1. the type definition might be missing if the element was
26101 	*    error prone
26102 	* 2. it might be abstract.
26103 	*/
26104 	goto end_elem;
26105     }
26106     /*
26107     * Check the content model.
26108     */
26109     if ((inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) ||
26110 	(inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)) {
26111 
26112 	/*
26113 	* Workaround for "anyType".
26114 	*/
26115 	if (inode->typeDef->builtInType == XML_SCHEMAS_ANYTYPE)
26116 	    goto character_content;
26117 
26118 	if ((inode->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0) {
26119 	    xmlChar *values[10];
26120 	    int terminal, nbval = 10, nbneg;
26121 
26122 	    if (inode->regexCtxt == NULL) {
26123 		/*
26124 		* Create the regex context.
26125 		*/
26126 		inode->regexCtxt =
26127 		    xmlRegNewExecCtxt(inode->typeDef->contModel,
26128 		    xmlSchemaVContentModelCallback, vctxt);
26129 		if (inode->regexCtxt == NULL) {
26130 		    VERROR_INT("xmlSchemaValidatorPopElem",
26131 			"failed to create a regex context");
26132 		    goto internal_error;
26133 		}
26134 #ifdef DEBUG_AUTOMATA
26135 		xmlGenericError(xmlGenericErrorContext,
26136 		    "AUTOMATON create on '%s'\n", inode->localName);
26137 #endif
26138 	    }
26139 
26140 	    /*
26141 	     * Do not check further content if the node has been nilled
26142 	     */
26143 	    if (INODE_NILLED(inode)) {
26144 		ret = 0;
26145 #ifdef DEBUG_AUTOMATA
26146 		xmlGenericError(xmlGenericErrorContext,
26147 		    "AUTOMATON succeeded on nilled '%s'\n",
26148 		    inode->localName);
26149 #endif
26150                 goto skip_nilled;
26151 	    }
26152 
26153 	    /*
26154 	    * Get hold of the still expected content, since a further
26155 	    * call to xmlRegExecPushString() will lose this information.
26156 	    */
26157 	    xmlRegExecNextValues(inode->regexCtxt,
26158 		&nbval, &nbneg, &values[0], &terminal);
26159 	    ret = xmlRegExecPushString(inode->regexCtxt, NULL, NULL);
26160 	    if ((ret<0) || ((ret==0) && (!INODE_NILLED(inode)))) {
26161 		/*
26162 		* Still missing something.
26163 		*/
26164 		ret = 1;
26165 		inode->flags |=
26166 		    XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
26167 		xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
26168 		    XML_SCHEMAV_ELEMENT_CONTENT, NULL, NULL,
26169 		    "Missing child element(s)",
26170 		    nbval, nbneg, values);
26171 #ifdef DEBUG_AUTOMATA
26172 		xmlGenericError(xmlGenericErrorContext,
26173 		    "AUTOMATON missing ERROR on '%s'\n",
26174 		    inode->localName);
26175 #endif
26176 	    } else {
26177 		/*
26178 		* Content model is satisfied.
26179 		*/
26180 		ret = 0;
26181 #ifdef DEBUG_AUTOMATA
26182 		xmlGenericError(xmlGenericErrorContext,
26183 		    "AUTOMATON succeeded on '%s'\n",
26184 		    inode->localName);
26185 #endif
26186 	    }
26187 
26188 	}
26189     }
26190 
26191 skip_nilled:
26192 
26193     if (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)
26194 	goto end_elem;
26195 
26196 character_content:
26197 
26198     if (vctxt->value != NULL) {
26199 	xmlSchemaFreeValue(vctxt->value);
26200 	vctxt->value = NULL;
26201     }
26202     /*
26203     * Check character content.
26204     */
26205     if (inode->decl == NULL) {
26206 	/*
26207 	* Speedup if no declaration exists.
26208 	*/
26209 	if (WXS_IS_SIMPLE(inode->typeDef)) {
26210 	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26211 		inode, inode->typeDef, inode->value);
26212 	} else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26213 	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26214 		inode, inode->typeDef->contentTypeDef,
26215 		inode->value);
26216 	}
26217 	if (ret < 0) {
26218 	    VERROR_INT("xmlSchemaValidatorPopElem",
26219 		"calling xmlSchemaVCheckCVCSimpleType()");
26220 	    goto internal_error;
26221 	}
26222 	goto end_elem;
26223     }
26224     /*
26225     * cvc-elt (3.3.4) : 5
26226     * The appropriate case among the following must be true:
26227     */
26228     /*
26229     * cvc-elt (3.3.4) : 5.1
26230     * If the declaration has a {value constraint},
26231     * the item has neither element nor character [children] and
26232     * clause 3.2 has not applied, then all of the following must be true:
26233     */
26234     if ((inode->decl->value != NULL) &&
26235 	(inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) &&
26236 	(! INODE_NILLED(inode))) {
26237 	/*
26238 	* cvc-elt (3.3.4) : 5.1.1
26239 	* If the `actual type definition` is a `local type definition`
26240 	* then the canonical lexical representation of the {value constraint}
26241 	* value must be a valid default for the `actual type definition` as
26242 	* defined in Element Default Valid (Immediate) ($3.3.6).
26243 	*/
26244 	/*
26245 	* NOTE: 'local' above means types acquired by xsi:type.
26246 	* NOTE: Although the *canonical* value is stated, it is not
26247 	* relevant if canonical or not. Additionally XML Schema 1.1
26248 	* will removed this requirement as well.
26249 	*/
26250 	if (inode->flags & XML_SCHEMA_ELEM_INFO_LOCAL_TYPE) {
26251 
26252 	    ret = xmlSchemaCheckCOSValidDefault(vctxt,
26253 		inode->decl->value, &(inode->val));
26254 	    if (ret != 0) {
26255 		if (ret < 0) {
26256 		    VERROR_INT("xmlSchemaValidatorPopElem",
26257 			"calling xmlSchemaCheckCOSValidDefault()");
26258 		    goto internal_error;
26259 		}
26260 		goto end_elem;
26261 	    }
26262 	    /*
26263 	    * Stop here, to avoid redundant validation of the value
26264 	    * (see following).
26265 	    */
26266 	    goto default_psvi;
26267 	}
26268 	/*
26269 	* cvc-elt (3.3.4) : 5.1.2
26270 	* The element information item with the canonical lexical
26271 	* representation of the {value constraint} value used as its
26272 	* `normalized value` must be `valid` with respect to the
26273 	* `actual type definition` as defined by Element Locally Valid (Type)
26274 	* ($3.3.4).
26275 	*/
26276 	if (WXS_IS_SIMPLE(inode->typeDef)) {
26277 	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26278 		inode, inode->typeDef, inode->decl->value);
26279 	} else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26280 	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26281 		inode, inode->typeDef->contentTypeDef,
26282 		inode->decl->value);
26283 	}
26284 	if (ret != 0) {
26285 	    if (ret < 0) {
26286 		VERROR_INT("xmlSchemaValidatorPopElem",
26287 		    "calling xmlSchemaVCheckCVCSimpleType()");
26288 		goto internal_error;
26289 	    }
26290 	    goto end_elem;
26291 	}
26292 
26293 default_psvi:
26294 	/*
26295 	* PSVI: Create a text node on the instance element.
26296 	*/
26297 	if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
26298 	    (inode->node != NULL)) {
26299 	    xmlNodePtr textChild;
26300 	    xmlChar *normValue;
26301 	    /*
26302 	    * VAL TODO: Normalize the value.
26303 	    */
26304 	    normValue = xmlSchemaNormalizeValue(inode->typeDef,
26305 		inode->decl->value);
26306 	    if (normValue != NULL) {
26307 		textChild = xmlNewText(BAD_CAST normValue);
26308 		xmlFree(normValue);
26309 	    } else
26310 		textChild = xmlNewText(inode->decl->value);
26311 	    if (textChild == NULL) {
26312 		VERROR_INT("xmlSchemaValidatorPopElem",
26313 		    "calling xmlNewText()");
26314 		goto internal_error;
26315 	    } else
26316 		xmlAddChild(inode->node, textChild);
26317 	}
26318 
26319     } else if (! INODE_NILLED(inode)) {
26320 	/*
26321 	* 5.2.1 The element information item must be `valid` with respect
26322 	* to the `actual type definition` as defined by Element Locally
26323 	* Valid (Type) ($3.3.4).
26324 	*/
26325 	if (WXS_IS_SIMPLE(inode->typeDef)) {
26326 	     /*
26327 	    * SPEC (cvc-type) (3.1)
26328 	    * "If the type definition is a simple type definition, ..."
26329 	    * (3.1.3) "If clause 3.2 of Element Locally Valid
26330 	    * (Element) ($3.3.4) did not apply, then the `normalized value`
26331 	    * must be `valid` with respect to the type definition as defined
26332 	    * by String Valid ($3.14.4).
26333 	    */
26334 	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26335 		    inode, inode->typeDef, inode->value);
26336 	} else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26337 	    /*
26338 	    * SPEC (cvc-type) (3.2) "If the type definition is a complex type
26339 	    * definition, then the element information item must be
26340 	    * `valid` with respect to the type definition as per
26341 	    * Element Locally Valid (Complex Type) ($3.4.4);"
26342 	    *
26343 	    * SPEC (cvc-complex-type) (2.2)
26344 	    * "If the {content type} is a simple type definition, ...
26345 	    * the `normalized value` of the element information item is
26346 	    * `valid` with respect to that simple type definition as
26347 	    * defined by String Valid ($3.14.4)."
26348 	    */
26349 	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26350 		inode, inode->typeDef->contentTypeDef, inode->value);
26351 	}
26352 	if (ret != 0) {
26353 	    if (ret < 0) {
26354 		VERROR_INT("xmlSchemaValidatorPopElem",
26355 		    "calling xmlSchemaVCheckCVCSimpleType()");
26356 		goto internal_error;
26357 	    }
26358 	    goto end_elem;
26359 	}
26360 	/*
26361 	* 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
26362 	* not applied, all of the following must be true:
26363 	*/
26364 	if ((inode->decl->value != NULL) &&
26365 	    (inode->decl->flags & XML_SCHEMAS_ELEM_FIXED)) {
26366 
26367 	    /*
26368 	    * TODO: We will need a computed value, when comparison is
26369 	    * done on computed values.
26370 	    */
26371 	    /*
26372 	    * 5.2.2.1 The element information item must have no element
26373 	    * information item [children].
26374 	    */
26375 	    if (inode->flags &
26376 		    XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT) {
26377 		ret = XML_SCHEMAV_CVC_ELT_5_2_2_1;
26378 		VERROR(ret, NULL,
26379 		    "The content must not containt element nodes since "
26380 		    "there is a fixed value constraint");
26381 		goto end_elem;
26382 	    } else {
26383 		/*
26384 		* 5.2.2.2 The appropriate case among the following must
26385 		* be true:
26386 		*/
26387 		if (WXS_HAS_MIXED_CONTENT(inode->typeDef)) {
26388 		    /*
26389 		    * 5.2.2.2.1 If the {content type} of the `actual type
26390 		    * definition` is mixed, then the *initial value* of the
26391 		    * item must match the canonical lexical representation
26392 		    * of the {value constraint} value.
26393 		    *
26394 		    * ... the *initial value* of an element information
26395 		    * item is the string composed of, in order, the
26396 		    * [character code] of each character information item in
26397 		    * the [children] of that element information item.
26398 		    */
26399 		    if (! xmlStrEqual(inode->value, inode->decl->value)){
26400 			/*
26401 			* VAL TODO: Report invalid & expected values as well.
26402 			* VAL TODO: Implement the canonical stuff.
26403 			*/
26404 			ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_1;
26405 			xmlSchemaCustomErr(ACTXT_CAST vctxt,
26406 			    ret, NULL, NULL,
26407 			    "The initial value '%s' does not match the fixed "
26408 			    "value constraint '%s'",
26409 			    inode->value, inode->decl->value);
26410 			goto end_elem;
26411 		    }
26412 		} else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26413 		    /*
26414 		    * 5.2.2.2.2 If the {content type} of the `actual type
26415 		    * definition` is a simple type definition, then the
26416 		    * *actual value* of the item must match the canonical
26417 		    * lexical representation of the {value constraint} value.
26418 		    */
26419 		    /*
26420 		    * VAL TODO: *actual value* is the normalized value, impl.
26421 		    *           this.
26422 		    * VAL TODO: Report invalid & expected values as well.
26423 		    * VAL TODO: Implement a comparison with the computed values.
26424 		    */
26425 		    if (! xmlStrEqual(inode->value,
26426 			    inode->decl->value)) {
26427 			ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_2;
26428 			xmlSchemaCustomErr(ACTXT_CAST vctxt,
26429 			    ret, NULL, NULL,
26430 			    "The actual value '%s' does not match the fixed "
26431 			    "value constraint '%s'",
26432 			    inode->value,
26433 			    inode->decl->value);
26434 			goto end_elem;
26435 		    }
26436 		}
26437 	    }
26438 	}
26439     }
26440 
26441 end_elem:
26442     if (vctxt->depth < 0) {
26443 	/* TODO: raise error? */
26444 	return (0);
26445     }
26446     if (vctxt->depth == vctxt->skipDepth)
26447 	vctxt->skipDepth = -1;
26448     /*
26449     * Evaluate the history of XPath state objects.
26450     */
26451     if (inode->appliedXPath &&
26452 	(xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1))
26453 	goto internal_error;
26454     /*
26455     * MAYBE TODO:
26456     * SPEC (6) "The element information item must be `valid` with
26457     * respect to each of the {identity-constraint definitions} as per
26458     * Identity-constraint Satisfied ($3.11.4)."
26459     */
26460     /*
26461     * PSVI TODO: If we expose IDC node-tables via PSVI then the tables
26462     *   need to be built in any case.
26463     *   We will currently build IDC node-tables and bubble them only if
26464     *   keyrefs do exist.
26465     */
26466 
26467     /*
26468     * Add the current IDC target-nodes to the IDC node-tables.
26469     */
26470     if ((inode->idcMatchers != NULL) &&
26471 	(vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
26472     {
26473 	if (xmlSchemaIDCFillNodeTables(vctxt, inode) == -1)
26474 	    goto internal_error;
26475     }
26476     /*
26477     * Validate IDC keyrefs.
26478     */
26479     if (vctxt->inode->hasKeyrefs)
26480 	if (xmlSchemaCheckCVCIDCKeyRef(vctxt) == -1)
26481 	    goto internal_error;
26482     /*
26483     * Merge/free the IDC table.
26484     */
26485     if (inode->idcTable != NULL) {
26486 #ifdef DEBUG_IDC_NODE_TABLE
26487 	xmlSchemaDebugDumpIDCTable(stdout,
26488 	    inode->nsName,
26489 	    inode->localName,
26490 	    inode->idcTable);
26491 #endif
26492 	if ((vctxt->depth > 0) &&
26493 	    (vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
26494 	{
26495 	    /*
26496 	    * Merge the IDC node table with the table of the parent node.
26497 	    */
26498 	    if (xmlSchemaBubbleIDCNodeTables(vctxt) == -1)
26499 		goto internal_error;
26500 	}
26501     }
26502     /*
26503     * Clear the current ielem.
26504     * VAL TODO: Don't free the PSVI IDC tables if they are
26505     * requested for the PSVI.
26506     */
26507     xmlSchemaClearElemInfo(vctxt, inode);
26508     /*
26509     * Skip further processing if we are on the validation root.
26510     */
26511     if (vctxt->depth == 0) {
26512 	vctxt->depth--;
26513 	vctxt->inode = NULL;
26514 	return (0);
26515     }
26516     /*
26517     * Reset the keyrefDepth if needed.
26518     */
26519     if (vctxt->aidcs != NULL) {
26520 	xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
26521 	do {
26522 	    if (aidc->keyrefDepth == vctxt->depth) {
26523 		/*
26524 		* A 'keyrefDepth' of a key/unique IDC matches the current
26525 		* depth, this means that we are leaving the scope of the
26526 		* top-most keyref IDC which refers to this IDC.
26527 		*/
26528 		aidc->keyrefDepth = -1;
26529 	    }
26530 	    aidc = aidc->next;
26531 	} while (aidc != NULL);
26532     }
26533     vctxt->depth--;
26534     vctxt->inode = vctxt->elemInfos[vctxt->depth];
26535     /*
26536     * VAL TODO: 7 If the element information item is the `validation root`, it must be
26537     * `valid` per Validation Root Valid (ID/IDREF) ($3.3.4).
26538     */
26539     return (ret);
26540 
26541 internal_error:
26542     vctxt->err = -1;
26543     return (-1);
26544 }
26545 
26546 /*
26547 * 3.4.4 Complex Type Definition Validation Rules
26548 * Validation Rule: Element Locally Valid (Complex Type) (cvc-complex-type)
26549 */
26550 static int
xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)26551 xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)
26552 {
26553     xmlSchemaNodeInfoPtr pielem;
26554     xmlSchemaTypePtr ptype;
26555     int ret = 0;
26556 
26557     if (vctxt->depth <= 0) {
26558 	VERROR_INT("xmlSchemaValidateChildElem",
26559 	    "not intended for the validation root");
26560 	return (-1);
26561     }
26562     pielem = vctxt->elemInfos[vctxt->depth -1];
26563     if (pielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26564 	pielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
26565     /*
26566     * Handle 'nilled' elements.
26567     */
26568     if (INODE_NILLED(pielem)) {
26569 	/*
26570 	* SPEC (cvc-elt) (3.3.4) : (3.2.1)
26571 	*/
26572 	ACTIVATE_PARENT_ELEM;
26573 	ret = XML_SCHEMAV_CVC_ELT_3_2_1;
26574 	VERROR(ret, NULL,
26575 	    "Neither character nor element content is allowed, "
26576 	    "because the element was 'nilled'");
26577 	ACTIVATE_ELEM;
26578 	goto unexpected_elem;
26579     }
26580 
26581     ptype = pielem->typeDef;
26582 
26583     if (ptype->builtInType == XML_SCHEMAS_ANYTYPE) {
26584 	/*
26585 	* Workaround for "anyType": we have currently no content model
26586 	* assigned for "anyType", so handle it explicitely.
26587 	* "anyType" has an unbounded, lax "any" wildcard.
26588 	*/
26589 	vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26590 	    vctxt->inode->localName,
26591 	    vctxt->inode->nsName);
26592 
26593 	if (vctxt->inode->decl == NULL) {
26594 	    xmlSchemaAttrInfoPtr iattr;
26595 	    /*
26596 	    * Process "xsi:type".
26597 	    * SPEC (cvc-assess-elt) (1.2.1.2.1) - (1.2.1.2.3)
26598 	    */
26599 	    iattr = xmlSchemaGetMetaAttrInfo(vctxt,
26600 		XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
26601 	    if (iattr != NULL) {
26602 		ret = xmlSchemaProcessXSIType(vctxt, iattr,
26603 		    &(vctxt->inode->typeDef), NULL);
26604 		if (ret != 0) {
26605 		    if (ret == -1) {
26606 			VERROR_INT("xmlSchemaValidateChildElem",
26607 			    "calling xmlSchemaProcessXSIType() to "
26608 			    "process the attribute 'xsi:nil'");
26609 			return (-1);
26610 		    }
26611 		    return (ret);
26612 		}
26613 	    } else {
26614 		 /*
26615 		 * Fallback to "anyType".
26616 		 *
26617 		 * SPEC (cvc-assess-elt)
26618 		 * "If the item cannot be `strictly assessed`, [...]
26619 		 * an element information item's schema validity may be laxly
26620 		 * assessed if its `context-determined declaration` is not
26621 		 * skip by `validating` with respect to the `ur-type
26622 		 * definition` as per Element Locally Valid (Type) ($3.3.4)."
26623 		*/
26624 		vctxt->inode->typeDef =
26625 		    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
26626 	    }
26627 	}
26628 	return (0);
26629     }
26630 
26631     switch (ptype->contentType) {
26632 	case XML_SCHEMA_CONTENT_EMPTY:
26633 	    /*
26634 	    * SPEC (2.1) "If the {content type} is empty, then the
26635 	    * element information item has no character or element
26636 	    * information item [children]."
26637 	    */
26638 	    ACTIVATE_PARENT_ELEM
26639 	    ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1;
26640 	    VERROR(ret, NULL,
26641 		"Element content is not allowed, "
26642 		"because the content type is empty");
26643 	    ACTIVATE_ELEM
26644 	    goto unexpected_elem;
26645 	    break;
26646 
26647 	case XML_SCHEMA_CONTENT_MIXED:
26648         case XML_SCHEMA_CONTENT_ELEMENTS: {
26649 	    xmlRegExecCtxtPtr regexCtxt;
26650 	    xmlChar *values[10];
26651 	    int terminal, nbval = 10, nbneg;
26652 
26653 	    /* VAL TODO: Optimized "anyType" validation.*/
26654 
26655 	    if (ptype->contModel == NULL) {
26656 		VERROR_INT("xmlSchemaValidateChildElem",
26657 		    "type has elem content but no content model");
26658 		return (-1);
26659 	    }
26660 	    /*
26661 	    * Safety belf for evaluation if the cont. model was already
26662 	    * examined to be invalid.
26663 	    */
26664 	    if (pielem->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) {
26665 		VERROR_INT("xmlSchemaValidateChildElem",
26666 		    "validating elem, but elem content is already invalid");
26667 		return (-1);
26668 	    }
26669 
26670 	    regexCtxt = pielem->regexCtxt;
26671 	    if (regexCtxt == NULL) {
26672 		/*
26673 		* Create the regex context.
26674 		*/
26675 		regexCtxt = xmlRegNewExecCtxt(ptype->contModel,
26676 		    xmlSchemaVContentModelCallback, vctxt);
26677 		if (regexCtxt == NULL) {
26678 		    VERROR_INT("xmlSchemaValidateChildElem",
26679 			"failed to create a regex context");
26680 		    return (-1);
26681 		}
26682 		pielem->regexCtxt = regexCtxt;
26683 #ifdef DEBUG_AUTOMATA
26684 		xmlGenericError(xmlGenericErrorContext, "AUTOMATA create on '%s'\n",
26685 		    pielem->localName);
26686 #endif
26687 	    }
26688 
26689 	    /*
26690 	    * SPEC (2.4) "If the {content type} is element-only or mixed,
26691 	    * then the sequence of the element information item's
26692 	    * element information item [children], if any, taken in
26693 	    * order, is `valid` with respect to the {content type}'s
26694 	    * particle, as defined in Element Sequence Locally Valid
26695 	    * (Particle) ($3.9.4)."
26696 	    */
26697 	    ret = xmlRegExecPushString2(regexCtxt,
26698 		vctxt->inode->localName,
26699 		vctxt->inode->nsName,
26700 		vctxt->inode);
26701 #ifdef DEBUG_AUTOMATA
26702 	    if (ret < 0)
26703 		xmlGenericError(xmlGenericErrorContext,
26704 		"AUTOMATON push ERROR for '%s' on '%s'\n",
26705 		vctxt->inode->localName, pielem->localName);
26706 	    else
26707 		xmlGenericError(xmlGenericErrorContext,
26708 		"AUTOMATON push OK for '%s' on '%s'\n",
26709 		vctxt->inode->localName, pielem->localName);
26710 #endif
26711 	    if (vctxt->err == XML_SCHEMAV_INTERNAL) {
26712 		VERROR_INT("xmlSchemaValidateChildElem",
26713 		    "calling xmlRegExecPushString2()");
26714 		return (-1);
26715 	    }
26716 	    if (ret < 0) {
26717 		xmlRegExecErrInfo(regexCtxt, NULL, &nbval, &nbneg,
26718 		    &values[0], &terminal);
26719 		xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
26720 		    XML_SCHEMAV_ELEMENT_CONTENT, NULL,NULL,
26721 		    "This element is not expected",
26722 		    nbval, nbneg, values);
26723 		ret = vctxt->err;
26724 		goto unexpected_elem;
26725 	    } else
26726 		ret = 0;
26727 	}
26728 	    break;
26729 	case XML_SCHEMA_CONTENT_SIMPLE:
26730 	case XML_SCHEMA_CONTENT_BASIC:
26731 	    ACTIVATE_PARENT_ELEM
26732 	    if (WXS_IS_COMPLEX(ptype)) {
26733 		/*
26734 		* SPEC (cvc-complex-type) (2.2)
26735 		* "If the {content type} is a simple type definition, then
26736 		* the element information item has no element information
26737 		* item [children], ..."
26738 		*/
26739 		ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
26740 		VERROR(ret, NULL, "Element content is not allowed, "
26741 		    "because the content type is a simple type definition");
26742 	    } else {
26743 		/*
26744 		* SPEC (cvc-type) (3.1.2) "The element information item must
26745 		* have no element information item [children]."
26746 		*/
26747 		ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
26748 		VERROR(ret, NULL, "Element content is not allowed, "
26749 		    "because the type definition is simple");
26750 	    }
26751 	    ACTIVATE_ELEM
26752 	    ret = vctxt->err;
26753 	    goto unexpected_elem;
26754 	    break;
26755 
26756 	default:
26757 	    break;
26758     }
26759     return (ret);
26760 unexpected_elem:
26761     /*
26762     * Pop this element and set the skipDepth to skip
26763     * all further content of the parent element.
26764     */
26765     vctxt->skipDepth = vctxt->depth;
26766     vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
26767     pielem->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
26768     return (ret);
26769 }
26770 
26771 #define XML_SCHEMA_PUSH_TEXT_PERSIST 1
26772 #define XML_SCHEMA_PUSH_TEXT_CREATED 2
26773 #define XML_SCHEMA_PUSH_TEXT_VOLATILE 3
26774 
26775 static int
xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,int nodeType,const xmlChar * value,int len,int mode,int * consumed)26776 xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,
26777 		  int nodeType, const xmlChar *value, int len,
26778 		  int mode, int *consumed)
26779 {
26780     /*
26781     * Unfortunately we have to duplicate the text sometimes.
26782     * OPTIMIZE: Maybe we could skip it, if:
26783     *   1. content type is simple
26784     *   2. whitespace is "collapse"
26785     *   3. it consists of whitespace only
26786     *
26787     * Process character content.
26788     */
26789     if (consumed != NULL)
26790 	*consumed = 0;
26791     if (INODE_NILLED(vctxt->inode)) {
26792 	/*
26793 	* SPEC cvc-elt (3.3.4 - 3.2.1)
26794 	* "The element information item must have no character or
26795 	* element information item [children]."
26796 	*/
26797 	VERROR(XML_SCHEMAV_CVC_ELT_3_2_1, NULL,
26798 	    "Neither character nor element content is allowed "
26799 	    "because the element is 'nilled'");
26800 	return (vctxt->err);
26801     }
26802     /*
26803     * SPEC (2.1) "If the {content type} is empty, then the
26804     * element information item has no character or element
26805     * information item [children]."
26806     */
26807     if (vctxt->inode->typeDef->contentType ==
26808 	    XML_SCHEMA_CONTENT_EMPTY) {
26809 	VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1, NULL,
26810 	    "Character content is not allowed, "
26811 	    "because the content type is empty");
26812 	return (vctxt->err);
26813     }
26814 
26815     if (vctxt->inode->typeDef->contentType ==
26816 	    XML_SCHEMA_CONTENT_ELEMENTS) {
26817 	if ((nodeType != XML_TEXT_NODE) ||
26818 	    (! xmlSchemaIsBlank((xmlChar *) value, len))) {
26819 	    /*
26820 	    * SPEC cvc-complex-type (2.3)
26821 	    * "If the {content type} is element-only, then the
26822 	    * element information item has no character information
26823 	    * item [children] other than those whose [character
26824 	    * code] is defined as a white space in [XML 1.0 (Second
26825 	    * Edition)]."
26826 	    */
26827 	    VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3, NULL,
26828 		"Character content other than whitespace is not allowed "
26829 		"because the content type is 'element-only'");
26830 	    return (vctxt->err);
26831 	}
26832 	return (0);
26833     }
26834 
26835     if ((value == NULL) || (value[0] == 0))
26836 	return (0);
26837     /*
26838     * Save the value.
26839     * NOTE that even if the content type is *mixed*, we need the
26840     * *initial value* for default/fixed value constraints.
26841     */
26842     if ((vctxt->inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) &&
26843 	((vctxt->inode->decl == NULL) ||
26844 	(vctxt->inode->decl->value == NULL)))
26845 	return (0);
26846 
26847     if (vctxt->inode->value == NULL) {
26848 	/*
26849 	* Set the value.
26850 	*/
26851 	switch (mode) {
26852 	    case XML_SCHEMA_PUSH_TEXT_PERSIST:
26853 		/*
26854 		* When working on a tree.
26855 		*/
26856 		vctxt->inode->value = value;
26857 		break;
26858 	    case XML_SCHEMA_PUSH_TEXT_CREATED:
26859 		/*
26860 		* When working with the reader.
26861 		* The value will be freed by the element info.
26862 		*/
26863 		vctxt->inode->value = value;
26864 		if (consumed != NULL)
26865 		    *consumed = 1;
26866 		vctxt->inode->flags |=
26867 		    XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26868 		break;
26869 	    case XML_SCHEMA_PUSH_TEXT_VOLATILE:
26870 		/*
26871 		* When working with SAX.
26872 		* The value will be freed by the element info.
26873 		*/
26874 		if (len != -1)
26875 		    vctxt->inode->value = BAD_CAST xmlStrndup(value, len);
26876 		else
26877 		    vctxt->inode->value = BAD_CAST xmlStrdup(value);
26878 		vctxt->inode->flags |=
26879 		    XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26880 		break;
26881 	    default:
26882 		break;
26883 	}
26884     } else {
26885 	if (len < 0)
26886 	    len = xmlStrlen(value);
26887 	/*
26888 	* Concat the value.
26889 	*/
26890 	if (vctxt->inode->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
26891 	    vctxt->inode->value = BAD_CAST xmlStrncat(
26892 		(xmlChar *) vctxt->inode->value, value, len);
26893 	} else {
26894 	    vctxt->inode->value =
26895 		BAD_CAST xmlStrncatNew(vctxt->inode->value, value, len);
26896 	    vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26897 	}
26898     }
26899 
26900     return (0);
26901 }
26902 
26903 static int
xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt)26904 xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt)
26905 {
26906     int ret = 0;
26907 
26908     if ((vctxt->skipDepth != -1) &&
26909 	(vctxt->depth >= vctxt->skipDepth)) {
26910 	VERROR_INT("xmlSchemaValidateElem",
26911 	    "in skip-state");
26912 	goto internal_error;
26913     }
26914     if (vctxt->xsiAssemble) {
26915 	/*
26916 	* We will stop validation if there was an error during
26917 	* dynamic schema construction.
26918 	* Note that we simply set @skipDepth to 0, this could
26919 	* mean that a streaming document via SAX would be
26920 	* still read to the end but it won't be validated any more.
26921 	* TODO: If we are sure how to stop the validation at once
26922 	*   for all input scenarios, then this should be changed to
26923 	*   instantly stop the validation.
26924 	*/
26925 	ret = xmlSchemaAssembleByXSI(vctxt);
26926 	if (ret != 0) {
26927 	    if (ret == -1)
26928 		goto internal_error;
26929 	    vctxt->skipDepth = 0;
26930 	    return(ret);
26931 	}
26932         /*
26933          * Augment the IDC definitions for the main schema and all imported ones
26934          * NOTE: main schema is the first in the imported list
26935          */
26936         xmlHashScan(vctxt->schema->schemasImports, xmlSchemaAugmentImportedIDC,
26937                     vctxt);
26938     }
26939     if (vctxt->depth > 0) {
26940 	/*
26941 	* Validate this element against the content model
26942 	* of the parent.
26943 	*/
26944 	ret = xmlSchemaValidateChildElem(vctxt);
26945 	if (ret != 0) {
26946 	    if (ret < 0) {
26947 		VERROR_INT("xmlSchemaValidateElem",
26948 		    "calling xmlSchemaStreamValidateChildElement()");
26949 		goto internal_error;
26950 	    }
26951 	    goto exit;
26952 	}
26953 	if (vctxt->depth == vctxt->skipDepth)
26954 	    goto exit;
26955 	if ((vctxt->inode->decl == NULL) &&
26956 	    (vctxt->inode->typeDef == NULL)) {
26957 	    VERROR_INT("xmlSchemaValidateElem",
26958 		"the child element was valid but neither the "
26959 		"declaration nor the type was set");
26960 	    goto internal_error;
26961 	}
26962     } else {
26963 	/*
26964 	* Get the declaration of the validation root.
26965 	*/
26966 	vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26967 	    vctxt->inode->localName,
26968 	    vctxt->inode->nsName);
26969 	if (vctxt->inode->decl == NULL) {
26970 	    ret = XML_SCHEMAV_CVC_ELT_1;
26971 	    VERROR(ret, NULL,
26972 		"No matching global declaration available "
26973 		"for the validation root");
26974 	    goto exit;
26975 	}
26976     }
26977 
26978     if (vctxt->inode->decl == NULL)
26979 	goto type_validation;
26980 
26981     if (vctxt->inode->decl->type == XML_SCHEMA_TYPE_ANY) {
26982 	int skip;
26983 	/*
26984 	* Wildcards.
26985 	*/
26986 	ret = xmlSchemaValidateElemWildcard(vctxt, &skip);
26987 	if (ret != 0) {
26988 	    if (ret < 0) {
26989 		VERROR_INT("xmlSchemaValidateElem",
26990 		    "calling xmlSchemaValidateElemWildcard()");
26991 		goto internal_error;
26992 	    }
26993 	    goto exit;
26994 	}
26995 	if (skip) {
26996 	    vctxt->skipDepth = vctxt->depth;
26997 	    goto exit;
26998 	}
26999 	/*
27000 	* The declaration might be set by the wildcard validation,
27001 	* when the processContents is "lax" or "strict".
27002 	*/
27003 	if (vctxt->inode->decl->type != XML_SCHEMA_TYPE_ELEMENT) {
27004 	    /*
27005 	    * Clear the "decl" field to not confuse further processing.
27006 	    */
27007 	    vctxt->inode->decl = NULL;
27008 	    goto type_validation;
27009 	}
27010     }
27011     /*
27012     * Validate against the declaration.
27013     */
27014     ret = xmlSchemaValidateElemDecl(vctxt);
27015     if (ret != 0) {
27016 	if (ret < 0) {
27017 	    VERROR_INT("xmlSchemaValidateElem",
27018 		"calling xmlSchemaValidateElemDecl()");
27019 	    goto internal_error;
27020 	}
27021 	goto exit;
27022     }
27023     /*
27024     * Validate against the type definition.
27025     */
27026 type_validation:
27027 
27028     if (vctxt->inode->typeDef == NULL) {
27029 	vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
27030 	ret = XML_SCHEMAV_CVC_TYPE_1;
27031 	VERROR(ret, NULL,
27032 	    "The type definition is absent");
27033 	goto exit;
27034     }
27035     if (vctxt->inode->typeDef->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
27036 	vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
27037 	ret = XML_SCHEMAV_CVC_TYPE_2;
27038 	    VERROR(ret, NULL,
27039 	    "The type definition is abstract");
27040 	goto exit;
27041     }
27042     /*
27043     * Evaluate IDCs. Do it here, since new IDC matchers are registered
27044     * during validation against the declaration. This must be done
27045     * _before_ attribute validation.
27046     */
27047     if (vctxt->xpathStates != NULL) {
27048 	ret = xmlSchemaXPathEvaluate(vctxt, XML_ELEMENT_NODE);
27049 	vctxt->inode->appliedXPath = 1;
27050 	if (ret == -1) {
27051 	    VERROR_INT("xmlSchemaValidateElem",
27052 		"calling xmlSchemaXPathEvaluate()");
27053 	    goto internal_error;
27054 	}
27055     }
27056     /*
27057     * Validate attributes.
27058     */
27059     if (WXS_IS_COMPLEX(vctxt->inode->typeDef)) {
27060 	if ((vctxt->nbAttrInfos != 0) ||
27061 	    (vctxt->inode->typeDef->attrUses != NULL)) {
27062 
27063 	    ret = xmlSchemaVAttributesComplex(vctxt);
27064 	}
27065     } else if (vctxt->nbAttrInfos != 0) {
27066 
27067 	ret = xmlSchemaVAttributesSimple(vctxt);
27068     }
27069     /*
27070     * Clear registered attributes.
27071     */
27072     if (vctxt->nbAttrInfos != 0)
27073 	xmlSchemaClearAttrInfos(vctxt);
27074     if (ret == -1) {
27075 	VERROR_INT("xmlSchemaValidateElem",
27076 	    "calling attributes validation");
27077 	goto internal_error;
27078     }
27079     /*
27080     * Don't return an error if attributes are invalid on purpose.
27081     */
27082     ret = 0;
27083 
27084 exit:
27085     if (ret != 0)
27086 	vctxt->skipDepth = vctxt->depth;
27087     return (ret);
27088 internal_error:
27089     return (-1);
27090 }
27091 
27092 #ifdef XML_SCHEMA_READER_ENABLED
27093 static int
xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt)27094 xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt)
27095 {
27096     const int WHTSP = 13, SIGN_WHTSP = 14, END_ELEM = 15;
27097     int depth, nodeType, ret = 0, consumed;
27098     xmlSchemaNodeInfoPtr ielem;
27099 
27100     vctxt->depth = -1;
27101     ret = xmlTextReaderRead(vctxt->reader);
27102     /*
27103     * Move to the document element.
27104     */
27105     while (ret == 1) {
27106 	nodeType = xmlTextReaderNodeType(vctxt->reader);
27107 	if (nodeType == XML_ELEMENT_NODE)
27108 	    goto root_found;
27109 	ret = xmlTextReaderRead(vctxt->reader);
27110     }
27111     goto exit;
27112 
27113 root_found:
27114 
27115     do {
27116 	depth = xmlTextReaderDepth(vctxt->reader);
27117 	nodeType = xmlTextReaderNodeType(vctxt->reader);
27118 
27119 	if (nodeType == XML_ELEMENT_NODE) {
27120 
27121 	    vctxt->depth++;
27122 	    if (xmlSchemaValidatorPushElem(vctxt) == -1) {
27123 		VERROR_INT("xmlSchemaVReaderWalk",
27124 		    "calling xmlSchemaValidatorPushElem()");
27125 		goto internal_error;
27126 	    }
27127 	    ielem = vctxt->inode;
27128 	    ielem->localName = xmlTextReaderLocalName(vctxt->reader);
27129 	    ielem->nsName = xmlTextReaderNamespaceUri(vctxt->reader);
27130 	    ielem->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
27131 	    /*
27132 	    * Is the element empty?
27133 	    */
27134 	    ret = xmlTextReaderIsEmptyElement(vctxt->reader);
27135 	    if (ret == -1) {
27136 		VERROR_INT("xmlSchemaVReaderWalk",
27137 		    "calling xmlTextReaderIsEmptyElement()");
27138 		goto internal_error;
27139 	    }
27140 	    if (ret) {
27141 		ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27142 	    }
27143 	    /*
27144 	    * Register attributes.
27145 	    */
27146 	    vctxt->nbAttrInfos = 0;
27147 	    ret = xmlTextReaderMoveToFirstAttribute(vctxt->reader);
27148 	    if (ret == -1) {
27149 		VERROR_INT("xmlSchemaVReaderWalk",
27150 		    "calling xmlTextReaderMoveToFirstAttribute()");
27151 		goto internal_error;
27152 	    }
27153 	    if (ret == 1) {
27154 		do {
27155 		    /*
27156 		    * VAL TODO: How do we know that the reader works on a
27157 		    * node tree, to be able to pass a node here?
27158 		    */
27159 		    if (xmlSchemaValidatorPushAttribute(vctxt, NULL,
27160 			(const xmlChar *) xmlTextReaderLocalName(vctxt->reader),
27161 			xmlTextReaderNamespaceUri(vctxt->reader), 1,
27162 			xmlTextReaderValue(vctxt->reader), 1) == -1) {
27163 
27164 			VERROR_INT("xmlSchemaVReaderWalk",
27165 			    "calling xmlSchemaValidatorPushAttribute()");
27166 			goto internal_error;
27167 		    }
27168 		    ret = xmlTextReaderMoveToNextAttribute(vctxt->reader);
27169 		    if (ret == -1) {
27170 			VERROR_INT("xmlSchemaVReaderWalk",
27171 			    "calling xmlTextReaderMoveToFirstAttribute()");
27172 			goto internal_error;
27173 		    }
27174 		} while (ret == 1);
27175 		/*
27176 		* Back to element position.
27177 		*/
27178 		ret = xmlTextReaderMoveToElement(vctxt->reader);
27179 		if (ret == -1) {
27180 		    VERROR_INT("xmlSchemaVReaderWalk",
27181 			"calling xmlTextReaderMoveToElement()");
27182 		    goto internal_error;
27183 		}
27184 	    }
27185 	    /*
27186 	    * Validate the element.
27187 	    */
27188 	    ret= xmlSchemaValidateElem(vctxt);
27189 	    if (ret != 0) {
27190 		if (ret == -1) {
27191 		    VERROR_INT("xmlSchemaVReaderWalk",
27192 			"calling xmlSchemaValidateElem()");
27193 		    goto internal_error;
27194 		}
27195 		goto exit;
27196 	    }
27197 	    if (vctxt->depth == vctxt->skipDepth) {
27198 		int curDepth;
27199 		/*
27200 		* Skip all content.
27201 		*/
27202 		if ((ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) == 0) {
27203 		    ret = xmlTextReaderRead(vctxt->reader);
27204 		    curDepth = xmlTextReaderDepth(vctxt->reader);
27205 		    while ((ret == 1) && (curDepth != depth)) {
27206 			ret = xmlTextReaderRead(vctxt->reader);
27207 			curDepth = xmlTextReaderDepth(vctxt->reader);
27208 		    }
27209 		    if (ret < 0) {
27210 			/*
27211 			* VAL TODO: A reader error occurred; what to do here?
27212 			*/
27213 			ret = 1;
27214 			goto exit;
27215 		    }
27216 		}
27217 		goto leave_elem;
27218 	    }
27219 	    /*
27220 	    * READER VAL TODO: Is an END_ELEM really never called
27221 	    * if the elem is empty?
27222 	    */
27223 	    if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27224 		goto leave_elem;
27225 	} else if (nodeType == END_ELEM) {
27226 	    /*
27227 	    * Process END of element.
27228 	    */
27229 leave_elem:
27230 	    ret = xmlSchemaValidatorPopElem(vctxt);
27231 	    if (ret != 0) {
27232 		if (ret < 0) {
27233 		    VERROR_INT("xmlSchemaVReaderWalk",
27234 			"calling xmlSchemaValidatorPopElem()");
27235 		    goto internal_error;
27236 		}
27237 		goto exit;
27238 	    }
27239 	    if (vctxt->depth >= 0)
27240 		ielem = vctxt->inode;
27241 	    else
27242 		ielem = NULL;
27243 	} else if ((nodeType == XML_TEXT_NODE) ||
27244 	    (nodeType == XML_CDATA_SECTION_NODE) ||
27245 	    (nodeType == WHTSP) ||
27246 	    (nodeType == SIGN_WHTSP)) {
27247 	    /*
27248 	    * Process character content.
27249 	    */
27250 	    xmlChar *value;
27251 
27252 	    if ((nodeType == WHTSP) || (nodeType == SIGN_WHTSP))
27253 		nodeType = XML_TEXT_NODE;
27254 
27255 	    value = xmlTextReaderValue(vctxt->reader);
27256 	    ret = xmlSchemaVPushText(vctxt, nodeType, BAD_CAST value,
27257 		-1, XML_SCHEMA_PUSH_TEXT_CREATED, &consumed);
27258 	    if (! consumed)
27259 		xmlFree(value);
27260 	    if (ret == -1) {
27261 		VERROR_INT("xmlSchemaVReaderWalk",
27262 		    "calling xmlSchemaVPushText()");
27263 		goto internal_error;
27264 	    }
27265 	} else if ((nodeType == XML_ENTITY_NODE) ||
27266 	    (nodeType == XML_ENTITY_REF_NODE)) {
27267 	    /*
27268 	    * VAL TODO: What to do with entities?
27269 	    */
27270 	    TODO
27271 	}
27272 	/*
27273 	* Read next node.
27274 	*/
27275 	ret = xmlTextReaderRead(vctxt->reader);
27276     } while (ret == 1);
27277 
27278 exit:
27279     return (ret);
27280 internal_error:
27281     return (-1);
27282 }
27283 #endif
27284 
27285 /************************************************************************
27286  *									*
27287  *			SAX validation handlers				*
27288  *									*
27289  ************************************************************************/
27290 
27291 /*
27292 * Process text content.
27293 */
27294 static void
xmlSchemaSAXHandleText(void * ctx,const xmlChar * ch,int len)27295 xmlSchemaSAXHandleText(void *ctx,
27296 		       const xmlChar * ch,
27297 		       int len)
27298 {
27299     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27300 
27301     if (vctxt->depth < 0)
27302 	return;
27303     if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27304 	return;
27305     if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27306 	vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27307     if (xmlSchemaVPushText(vctxt, XML_TEXT_NODE, ch, len,
27308 	XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
27309 	VERROR_INT("xmlSchemaSAXHandleCDataSection",
27310 	    "calling xmlSchemaVPushText()");
27311 	vctxt->err = -1;
27312 	xmlStopParser(vctxt->parserCtxt);
27313     }
27314 }
27315 
27316 /*
27317 * Process CDATA content.
27318 */
27319 static void
xmlSchemaSAXHandleCDataSection(void * ctx,const xmlChar * ch,int len)27320 xmlSchemaSAXHandleCDataSection(void *ctx,
27321 			     const xmlChar * ch,
27322 			     int len)
27323 {
27324     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27325 
27326     if (vctxt->depth < 0)
27327 	return;
27328     if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27329 	return;
27330     if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27331 	vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27332     if (xmlSchemaVPushText(vctxt, XML_CDATA_SECTION_NODE, ch, len,
27333 	XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
27334 	VERROR_INT("xmlSchemaSAXHandleCDataSection",
27335 	    "calling xmlSchemaVPushText()");
27336 	vctxt->err = -1;
27337 	xmlStopParser(vctxt->parserCtxt);
27338     }
27339 }
27340 
27341 static void
xmlSchemaSAXHandleReference(void * ctx ATTRIBUTE_UNUSED,const xmlChar * name ATTRIBUTE_UNUSED)27342 xmlSchemaSAXHandleReference(void *ctx ATTRIBUTE_UNUSED,
27343 			    const xmlChar * name ATTRIBUTE_UNUSED)
27344 {
27345     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27346 
27347     if (vctxt->depth < 0)
27348 	return;
27349     if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27350 	return;
27351     /* SAX VAL TODO: What to do here? */
27352     TODO
27353 }
27354 
27355 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)27356 xmlSchemaSAXHandleStartElementNs(void *ctx,
27357 				 const xmlChar * localname,
27358 				 const xmlChar * prefix ATTRIBUTE_UNUSED,
27359 				 const xmlChar * URI,
27360 				 int nb_namespaces,
27361 				 const xmlChar ** namespaces,
27362 				 int nb_attributes,
27363 				 int nb_defaulted ATTRIBUTE_UNUSED,
27364 				 const xmlChar ** attributes)
27365 {
27366     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27367     int ret;
27368     xmlSchemaNodeInfoPtr ielem;
27369     int i, j;
27370 
27371     /*
27372     * SAX VAL TODO: What to do with nb_defaulted?
27373     */
27374     /*
27375     * Skip elements if inside a "skip" wildcard or invalid.
27376     */
27377     vctxt->depth++;
27378     if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27379 	return;
27380     /*
27381     * Push the element.
27382     */
27383     if (xmlSchemaValidatorPushElem(vctxt) == -1) {
27384 	VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27385 	    "calling xmlSchemaValidatorPushElem()");
27386 	goto internal_error;
27387     }
27388     ielem = vctxt->inode;
27389     /*
27390     * TODO: Is this OK?
27391     */
27392     ielem->nodeLine = xmlSAX2GetLineNumber(vctxt->parserCtxt);
27393     ielem->localName = localname;
27394     ielem->nsName = URI;
27395     ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27396     /*
27397     * Register namespaces on the elem info.
27398     */
27399     if (nb_namespaces != 0) {
27400 	/*
27401 	* Although the parser builds its own namespace list,
27402 	* we have no access to it, so we'll use an own one.
27403 	*/
27404         for (i = 0, j = 0; i < nb_namespaces; i++, j += 2) {
27405 	    /*
27406 	    * Store prefix and namespace name.
27407 	    */
27408 	    if (ielem->nsBindings == NULL) {
27409 		ielem->nsBindings =
27410 		    (const xmlChar **) xmlMalloc(10 *
27411 			sizeof(const xmlChar *));
27412 		if (ielem->nsBindings == NULL) {
27413 		    xmlSchemaVErrMemory(vctxt,
27414 			"allocating namespace bindings for SAX validation",
27415 			NULL);
27416 		    goto internal_error;
27417 		}
27418 		ielem->nbNsBindings = 0;
27419 		ielem->sizeNsBindings = 5;
27420 	    } else if (ielem->sizeNsBindings <= ielem->nbNsBindings) {
27421 		ielem->sizeNsBindings *= 2;
27422 		ielem->nsBindings =
27423 		    (const xmlChar **) xmlRealloc(
27424 			(void *) ielem->nsBindings,
27425 			ielem->sizeNsBindings * 2 * sizeof(const xmlChar *));
27426 		if (ielem->nsBindings == NULL) {
27427 		    xmlSchemaVErrMemory(vctxt,
27428 			"re-allocating namespace bindings for SAX validation",
27429 			NULL);
27430 		    goto internal_error;
27431 		}
27432 	    }
27433 
27434 	    ielem->nsBindings[ielem->nbNsBindings * 2] = namespaces[j];
27435 	    if (namespaces[j+1][0] == 0) {
27436 		/*
27437 		* Handle xmlns="".
27438 		*/
27439 		ielem->nsBindings[ielem->nbNsBindings * 2 + 1] = NULL;
27440 	    } else
27441 		ielem->nsBindings[ielem->nbNsBindings * 2 + 1] =
27442 		    namespaces[j+1];
27443 	    ielem->nbNsBindings++;
27444 	}
27445     }
27446     /*
27447     * Register attributes.
27448     * SAX VAL TODO: We are not adding namespace declaration
27449     * attributes yet.
27450     */
27451     if (nb_attributes != 0) {
27452 	int valueLen, k, l;
27453 	xmlChar *value;
27454 
27455         for (j = 0, i = 0; i < nb_attributes; i++, j += 5) {
27456 	    /*
27457 	    * Duplicate the value, changing any &#38; to a literal ampersand.
27458 	    *
27459 	    * libxml2 differs from normal SAX here in that it escapes all ampersands
27460 	    * as &#38; instead of delivering the raw converted string. Changing the
27461 	    * behavior at this point would break applications that use this API, so
27462 	    * we are forced to work around it.
27463 	    */
27464 	    valueLen = attributes[j+4] - attributes[j+3];
27465 	    value = xmlMallocAtomic(valueLen + 1);
27466 	    if (value == NULL) {
27467 		xmlSchemaVErrMemory(vctxt,
27468 		    "allocating string for decoded attribute",
27469 		    NULL);
27470 		goto internal_error;
27471 	    }
27472 	    for (k = 0, l = 0; k < valueLen; l++) {
27473 		if (k < valueLen - 4 &&
27474 		    attributes[j+3][k+0] == '&' &&
27475 		    attributes[j+3][k+1] == '#' &&
27476 		    attributes[j+3][k+2] == '3' &&
27477 		    attributes[j+3][k+3] == '8' &&
27478 		    attributes[j+3][k+4] == ';') {
27479 		    value[l] = '&';
27480 		    k += 5;
27481 		} else {
27482 		    value[l] = attributes[j+3][k];
27483 		    k++;
27484 		}
27485 	    }
27486 	    value[l] = '\0';
27487 	    /*
27488 	    * TODO: Set the node line.
27489 	    */
27490 	    ret = xmlSchemaValidatorPushAttribute(vctxt,
27491 		NULL, ielem->nodeLine, attributes[j], attributes[j+2], 0,
27492 		value, 1);
27493 	    if (ret == -1) {
27494 		VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27495 		    "calling xmlSchemaValidatorPushAttribute()");
27496 		goto internal_error;
27497 	    }
27498 	}
27499     }
27500     /*
27501     * Validate the element.
27502     */
27503     ret = xmlSchemaValidateElem(vctxt);
27504     if (ret != 0) {
27505 	if (ret == -1) {
27506 	    VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27507 		"calling xmlSchemaValidateElem()");
27508 	    goto internal_error;
27509 	}
27510 	goto exit;
27511     }
27512 
27513 exit:
27514     return;
27515 internal_error:
27516     vctxt->err = -1;
27517     xmlStopParser(vctxt->parserCtxt);
27518     return;
27519 }
27520 
27521 static void
xmlSchemaSAXHandleEndElementNs(void * ctx,const xmlChar * localname ATTRIBUTE_UNUSED,const xmlChar * prefix ATTRIBUTE_UNUSED,const xmlChar * URI ATTRIBUTE_UNUSED)27522 xmlSchemaSAXHandleEndElementNs(void *ctx,
27523 			       const xmlChar * localname ATTRIBUTE_UNUSED,
27524 			       const xmlChar * prefix ATTRIBUTE_UNUSED,
27525 			       const xmlChar * URI ATTRIBUTE_UNUSED)
27526 {
27527     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27528     int res;
27529 
27530     /*
27531     * Skip elements if inside a "skip" wildcard or if invalid.
27532     */
27533     if (vctxt->skipDepth != -1) {
27534 	if (vctxt->depth > vctxt->skipDepth) {
27535 	    vctxt->depth--;
27536 	    return;
27537 	} else
27538 	    vctxt->skipDepth = -1;
27539     }
27540     /*
27541     * SAX VAL TODO: Just a temporary check.
27542     */
27543     if ((!xmlStrEqual(vctxt->inode->localName, localname)) ||
27544 	(!xmlStrEqual(vctxt->inode->nsName, URI))) {
27545 	VERROR_INT("xmlSchemaSAXHandleEndElementNs",
27546 	    "elem pop mismatch");
27547     }
27548     res = xmlSchemaValidatorPopElem(vctxt);
27549     if (res != 0) {
27550 	if (res < 0) {
27551 	    VERROR_INT("xmlSchemaSAXHandleEndElementNs",
27552 		"calling xmlSchemaValidatorPopElem()");
27553 	    goto internal_error;
27554 	}
27555 	goto exit;
27556     }
27557 exit:
27558     return;
27559 internal_error:
27560     vctxt->err = -1;
27561     xmlStopParser(vctxt->parserCtxt);
27562     return;
27563 }
27564 
27565 /************************************************************************
27566  *									*
27567  *			Validation interfaces				*
27568  *									*
27569  ************************************************************************/
27570 
27571 /**
27572  * xmlSchemaNewValidCtxt:
27573  * @schema:  a precompiled XML Schemas
27574  *
27575  * Create an XML Schemas validation context based on the given schema.
27576  *
27577  * Returns the validation context or NULL in case of error
27578  */
27579 xmlSchemaValidCtxtPtr
xmlSchemaNewValidCtxt(xmlSchemaPtr schema)27580 xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
27581 {
27582     xmlSchemaValidCtxtPtr ret;
27583 
27584     ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
27585     if (ret == NULL) {
27586         xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
27587         return (NULL);
27588     }
27589     memset(ret, 0, sizeof(xmlSchemaValidCtxt));
27590     ret->type = XML_SCHEMA_CTXT_VALIDATOR;
27591     ret->dict = xmlDictCreate();
27592     ret->nodeQNames = xmlSchemaItemListCreate();
27593     ret->schema = schema;
27594     return (ret);
27595 }
27596 
27597 /**
27598  * xmlSchemaValidateSetFilename:
27599  * @vctxt: the schema validation context
27600  * @filename: the file name
27601  *
27602  * Workaround to provide file error reporting information when this is
27603  * not provided by current APIs
27604  */
27605 void
xmlSchemaValidateSetFilename(xmlSchemaValidCtxtPtr vctxt,const char * filename)27606 xmlSchemaValidateSetFilename(xmlSchemaValidCtxtPtr vctxt, const char *filename) {
27607     if (vctxt == NULL)
27608         return;
27609     if (vctxt->filename != NULL)
27610         xmlFree(vctxt->filename);
27611     if (filename != NULL)
27612         vctxt->filename = (char *) xmlStrdup((const xmlChar *) filename);
27613     else
27614         vctxt->filename = NULL;
27615 }
27616 
27617 /**
27618  * xmlSchemaClearValidCtxt:
27619  * @vctxt: the schema validation context
27620  *
27621  * Free the resources associated to the schema validation context;
27622  * leaves some fields alive intended for reuse of the context.
27623  */
27624 static void
xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)27625 xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
27626 {
27627     if (vctxt == NULL)
27628         return;
27629 
27630     /*
27631     * TODO: Should we clear the flags?
27632     *   Might be problematic if one reuses the context
27633     *   and assumes that the options remain the same.
27634     */
27635     vctxt->flags = 0;
27636     vctxt->validationRoot = NULL;
27637     vctxt->doc = NULL;
27638 #ifdef LIBXML_READER_ENABLED
27639     vctxt->reader = NULL;
27640 #endif
27641     vctxt->hasKeyrefs = 0;
27642 
27643     if (vctxt->value != NULL) {
27644         xmlSchemaFreeValue(vctxt->value);
27645 	vctxt->value = NULL;
27646     }
27647     /*
27648     * Augmented IDC information.
27649     */
27650     if (vctxt->aidcs != NULL) {
27651 	xmlSchemaIDCAugPtr cur = vctxt->aidcs, next;
27652 	do {
27653 	    next = cur->next;
27654 	    xmlFree(cur);
27655 	    cur = next;
27656 	} while (cur != NULL);
27657 	vctxt->aidcs = NULL;
27658     }
27659     if (vctxt->idcMatcherCache != NULL) {
27660 	xmlSchemaIDCMatcherPtr matcher = vctxt->idcMatcherCache, tmp;
27661 
27662 	while (matcher) {
27663 	    tmp = matcher;
27664 	    matcher = matcher->nextCached;
27665 	    xmlSchemaIDCFreeMatcherList(tmp);
27666 	}
27667 	vctxt->idcMatcherCache = NULL;
27668     }
27669 
27670 
27671     if (vctxt->idcNodes != NULL) {
27672 	int i;
27673 	xmlSchemaPSVIIDCNodePtr item;
27674 
27675 	for (i = 0; i < vctxt->nbIdcNodes; i++) {
27676 	    item = vctxt->idcNodes[i];
27677 	    xmlFree(item->keys);
27678 	    xmlFree(item);
27679 	}
27680 	xmlFree(vctxt->idcNodes);
27681 	vctxt->idcNodes = NULL;
27682 	vctxt->nbIdcNodes = 0;
27683 	vctxt->sizeIdcNodes = 0;
27684     }
27685 
27686     if (vctxt->idcKeys != NULL) {
27687 	int i;
27688 	for (i = 0; i < vctxt->nbIdcKeys; i++)
27689 	    xmlSchemaIDCFreeKey(vctxt->idcKeys[i]);
27690 	xmlFree(vctxt->idcKeys);
27691 	vctxt->idcKeys = NULL;
27692 	vctxt->nbIdcKeys = 0;
27693 	vctxt->sizeIdcKeys = 0;
27694     }
27695 
27696     /*
27697     * Note that we won't delete the XPath state pool here.
27698     */
27699     if (vctxt->xpathStates != NULL) {
27700 	xmlSchemaFreeIDCStateObjList(vctxt->xpathStates);
27701 	vctxt->xpathStates = NULL;
27702     }
27703     /*
27704     * Attribute info.
27705     */
27706     if (vctxt->nbAttrInfos != 0) {
27707 	xmlSchemaClearAttrInfos(vctxt);
27708     }
27709     /*
27710     * Element info.
27711     */
27712     if (vctxt->elemInfos != NULL) {
27713 	int i;
27714 	xmlSchemaNodeInfoPtr ei;
27715 
27716 	for (i = 0; i < vctxt->sizeElemInfos; i++) {
27717 	    ei = vctxt->elemInfos[i];
27718 	    if (ei == NULL)
27719 		break;
27720 	    xmlSchemaClearElemInfo(vctxt, ei);
27721 	}
27722     }
27723     xmlSchemaItemListClear(vctxt->nodeQNames);
27724     /* Recreate the dict. */
27725     xmlDictFree(vctxt->dict);
27726     /*
27727     * TODO: Is is save to recreate it? Do we have a scenario
27728     * where the user provides the dict?
27729     */
27730     vctxt->dict = xmlDictCreate();
27731 
27732     if (vctxt->filename != NULL) {
27733         xmlFree(vctxt->filename);
27734 	vctxt->filename = NULL;
27735     }
27736 }
27737 
27738 /**
27739  * xmlSchemaFreeValidCtxt:
27740  * @ctxt:  the schema validation context
27741  *
27742  * Free the resources associated to the schema validation context
27743  */
27744 void
xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)27745 xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
27746 {
27747     if (ctxt == NULL)
27748         return;
27749     if (ctxt->value != NULL)
27750         xmlSchemaFreeValue(ctxt->value);
27751     if (ctxt->pctxt != NULL)
27752 	xmlSchemaFreeParserCtxt(ctxt->pctxt);
27753     if (ctxt->idcNodes != NULL) {
27754 	int i;
27755 	xmlSchemaPSVIIDCNodePtr item;
27756 
27757 	for (i = 0; i < ctxt->nbIdcNodes; i++) {
27758 	    item = ctxt->idcNodes[i];
27759 	    xmlFree(item->keys);
27760 	    xmlFree(item);
27761 	}
27762 	xmlFree(ctxt->idcNodes);
27763     }
27764     if (ctxt->idcKeys != NULL) {
27765 	int i;
27766 	for (i = 0; i < ctxt->nbIdcKeys; i++)
27767 	    xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
27768 	xmlFree(ctxt->idcKeys);
27769     }
27770 
27771     if (ctxt->xpathStates != NULL) {
27772 	xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
27773 	ctxt->xpathStates = NULL;
27774     }
27775     if (ctxt->xpathStatePool != NULL) {
27776 	xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
27777 	ctxt->xpathStatePool = NULL;
27778     }
27779 
27780     /*
27781     * Augmented IDC information.
27782     */
27783     if (ctxt->aidcs != NULL) {
27784 	xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
27785 	do {
27786 	    next = cur->next;
27787 	    xmlFree(cur);
27788 	    cur = next;
27789 	} while (cur != NULL);
27790     }
27791     if (ctxt->attrInfos != NULL) {
27792 	int i;
27793 	xmlSchemaAttrInfoPtr attr;
27794 
27795 	/* Just a paranoid call to the cleanup. */
27796 	if (ctxt->nbAttrInfos != 0)
27797 	    xmlSchemaClearAttrInfos(ctxt);
27798 	for (i = 0; i < ctxt->sizeAttrInfos; i++) {
27799 	    attr = ctxt->attrInfos[i];
27800 	    xmlFree(attr);
27801 	}
27802 	xmlFree(ctxt->attrInfos);
27803     }
27804     if (ctxt->elemInfos != NULL) {
27805 	int i;
27806 	xmlSchemaNodeInfoPtr ei;
27807 
27808 	for (i = 0; i < ctxt->sizeElemInfos; i++) {
27809 	    ei = ctxt->elemInfos[i];
27810 	    if (ei == NULL)
27811 		break;
27812 	    xmlSchemaClearElemInfo(ctxt, ei);
27813 	    xmlFree(ei);
27814 	}
27815 	xmlFree(ctxt->elemInfos);
27816     }
27817     if (ctxt->nodeQNames != NULL)
27818 	xmlSchemaItemListFree(ctxt->nodeQNames);
27819     if (ctxt->dict != NULL)
27820 	xmlDictFree(ctxt->dict);
27821     if (ctxt->filename != NULL)
27822 	xmlFree(ctxt->filename);
27823     xmlFree(ctxt);
27824 }
27825 
27826 /**
27827  * xmlSchemaIsValid:
27828  * @ctxt: the schema validation context
27829  *
27830  * Check if any error was detected during validation.
27831  *
27832  * Returns 1 if valid so far, 0 if errors were detected, and -1 in case
27833  *         of internal error.
27834  */
27835 int
xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt)27836 xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt)
27837 {
27838     if (ctxt == NULL)
27839         return(-1);
27840     return(ctxt->err == 0);
27841 }
27842 
27843 /**
27844  * xmlSchemaSetValidErrors:
27845  * @ctxt:  a schema validation context
27846  * @err:  the error function
27847  * @warn: the warning function
27848  * @ctx: the functions context
27849  *
27850  * Set the error and warning callback informations
27851  */
27852 void
xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,xmlSchemaValidityErrorFunc err,xmlSchemaValidityWarningFunc warn,void * ctx)27853 xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
27854                         xmlSchemaValidityErrorFunc err,
27855                         xmlSchemaValidityWarningFunc warn, void *ctx)
27856 {
27857     if (ctxt == NULL)
27858         return;
27859     ctxt->error = err;
27860     ctxt->warning = warn;
27861     ctxt->errCtxt = ctx;
27862     if (ctxt->pctxt != NULL)
27863 	xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
27864 }
27865 
27866 /**
27867  * xmlSchemaSetValidStructuredErrors:
27868  * @ctxt:  a schema validation context
27869  * @serror:  the structured error function
27870  * @ctx: the functions context
27871  *
27872  * Set the structured error callback
27873  */
27874 void
xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt,xmlStructuredErrorFunc serror,void * ctx)27875 xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt,
27876 				  xmlStructuredErrorFunc serror, void *ctx)
27877 {
27878     if (ctxt == NULL)
27879         return;
27880     ctxt->serror = serror;
27881     ctxt->error = NULL;
27882     ctxt->warning = NULL;
27883     ctxt->errCtxt = ctx;
27884     if (ctxt->pctxt != NULL)
27885 	xmlSchemaSetParserStructuredErrors(ctxt->pctxt, serror, ctx);
27886 }
27887 
27888 /**
27889  * xmlSchemaGetValidErrors:
27890  * @ctxt: a XML-Schema validation context
27891  * @err: the error function result
27892  * @warn: the warning function result
27893  * @ctx: the functions context result
27894  *
27895  * Get the error and warning callback informations
27896  *
27897  * Returns -1 in case of error and 0 otherwise
27898  */
27899 int
xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,xmlSchemaValidityErrorFunc * err,xmlSchemaValidityWarningFunc * warn,void ** ctx)27900 xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
27901 			xmlSchemaValidityErrorFunc * err,
27902 			xmlSchemaValidityWarningFunc * warn, void **ctx)
27903 {
27904 	if (ctxt == NULL)
27905 		return (-1);
27906 	if (err != NULL)
27907 		*err = ctxt->error;
27908 	if (warn != NULL)
27909 		*warn = ctxt->warning;
27910 	if (ctx != NULL)
27911 		*ctx = ctxt->errCtxt;
27912 	return (0);
27913 }
27914 
27915 
27916 /**
27917  * xmlSchemaSetValidOptions:
27918  * @ctxt:	a schema validation context
27919  * @options: a combination of xmlSchemaValidOption
27920  *
27921  * Sets the options to be used during the validation.
27922  *
27923  * Returns 0 in case of success, -1 in case of an
27924  * API error.
27925  */
27926 int
xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,int options)27927 xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
27928 			 int options)
27929 
27930 {
27931     int i;
27932 
27933     if (ctxt == NULL)
27934 	return (-1);
27935     /*
27936     * WARNING: Change the start value if adding to the
27937     * xmlSchemaValidOption.
27938     * TODO: Is there an other, more easy to maintain,
27939     * way?
27940     */
27941     for (i = 1; i < (int) sizeof(int) * 8; i++) {
27942         if (options & 1<<i)
27943 	    return (-1);
27944     }
27945     ctxt->options = options;
27946     return (0);
27947 }
27948 
27949 /**
27950  * xmlSchemaValidCtxtGetOptions:
27951  * @ctxt: a schema validation context
27952  *
27953  * Get the validation context options.
27954  *
27955  * Returns the option combination or -1 on error.
27956  */
27957 int
xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)27958 xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
27959 
27960 {
27961     if (ctxt == NULL)
27962 	return (-1);
27963     else
27964 	return (ctxt->options);
27965 }
27966 
27967 static int
xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)27968 xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)
27969 {
27970     xmlAttrPtr attr;
27971     int ret = 0;
27972     xmlSchemaNodeInfoPtr ielem = NULL;
27973     xmlNodePtr node, valRoot;
27974     const xmlChar *nsName;
27975 
27976     /* DOC VAL TODO: Move this to the start function. */
27977     if (vctxt->validationRoot != NULL)
27978         valRoot = vctxt->validationRoot;
27979     else
27980 	valRoot = xmlDocGetRootElement(vctxt->doc);
27981     if (valRoot == NULL) {
27982 	/* VAL TODO: Error code? */
27983 	VERROR(1, NULL, "The document has no document element");
27984 	return (1);
27985     }
27986     vctxt->depth = -1;
27987     vctxt->validationRoot = valRoot;
27988     node = valRoot;
27989     while (node != NULL) {
27990 	if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27991 	    goto next_sibling;
27992 	if (node->type == XML_ELEMENT_NODE) {
27993 
27994 	    /*
27995 	    * Init the node-info.
27996 	    */
27997 	    vctxt->depth++;
27998 	    if (xmlSchemaValidatorPushElem(vctxt) == -1)
27999 		goto internal_error;
28000 	    ielem = vctxt->inode;
28001 	    ielem->node = node;
28002 	    ielem->nodeLine = node->line;
28003 	    ielem->localName = node->name;
28004 	    if (node->ns != NULL)
28005 		ielem->nsName = node->ns->href;
28006 	    ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
28007 	    /*
28008 	    * Register attributes.
28009 	    * DOC VAL TODO: We do not register namespace declaration
28010 	    * attributes yet.
28011 	    */
28012 	    vctxt->nbAttrInfos = 0;
28013 	    if (node->properties != NULL) {
28014 		attr = node->properties;
28015 		do {
28016 		    if (attr->ns != NULL)
28017 			nsName = attr->ns->href;
28018 		    else
28019 			nsName = NULL;
28020 		    ret = xmlSchemaValidatorPushAttribute(vctxt,
28021 			(xmlNodePtr) attr,
28022 			/*
28023 			* Note that we give it the line number of the
28024 			* parent element.
28025 			*/
28026 			ielem->nodeLine,
28027 			attr->name, nsName, 0,
28028 			xmlNodeListGetString(attr->doc, attr->children, 1), 1);
28029 		    if (ret == -1) {
28030 			VERROR_INT("xmlSchemaDocWalk",
28031 			    "calling xmlSchemaValidatorPushAttribute()");
28032 			goto internal_error;
28033 		    }
28034 		    attr = attr->next;
28035 		} while (attr);
28036 	    }
28037 	    /*
28038 	    * Validate the element.
28039 	    */
28040 	    ret = xmlSchemaValidateElem(vctxt);
28041 	    if (ret != 0) {
28042 		if (ret == -1) {
28043 		    VERROR_INT("xmlSchemaDocWalk",
28044 			"calling xmlSchemaValidateElem()");
28045 		    goto internal_error;
28046 		}
28047 		/*
28048 		* Don't stop validation; just skip the content
28049 		* of this element.
28050 		*/
28051 		goto leave_node;
28052 	    }
28053 	    if ((vctxt->skipDepth != -1) &&
28054 		(vctxt->depth >= vctxt->skipDepth))
28055 		goto leave_node;
28056 	} else if ((node->type == XML_TEXT_NODE) ||
28057 	    (node->type == XML_CDATA_SECTION_NODE)) {
28058 	    /*
28059 	    * Process character content.
28060 	    */
28061 	    if ((ielem != NULL) && (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY))
28062 		ielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
28063 	    ret = xmlSchemaVPushText(vctxt, node->type, node->content,
28064 		-1, XML_SCHEMA_PUSH_TEXT_PERSIST, NULL);
28065 	    if (ret < 0) {
28066 		VERROR_INT("xmlSchemaVDocWalk",
28067 		    "calling xmlSchemaVPushText()");
28068 		goto internal_error;
28069 	    }
28070 	    /*
28071 	    * DOC VAL TODO: Should we skip further validation of the
28072 	    * element content here?
28073 	    */
28074 	} else if ((node->type == XML_ENTITY_NODE) ||
28075 	    (node->type == XML_ENTITY_REF_NODE)) {
28076 	    /*
28077 	    * DOC VAL TODO: What to do with entities?
28078 	    */
28079 	    VERROR_INT("xmlSchemaVDocWalk",
28080 		"there is at least one entity reference in the node-tree "
28081 		"currently being validated. Processing of entities with "
28082 		"this XML Schema processor is not supported (yet). Please "
28083 		"substitute entities before validation.");
28084 	    goto internal_error;
28085 	} else {
28086 	    goto leave_node;
28087 	    /*
28088 	    * DOC VAL TODO: XInclude nodes, etc.
28089 	    */
28090 	}
28091 	/*
28092 	* Walk the doc.
28093 	*/
28094 	if (node->children != NULL) {
28095 	    node = node->children;
28096 	    continue;
28097 	}
28098 leave_node:
28099 	if (node->type == XML_ELEMENT_NODE) {
28100 	    /*
28101 	    * Leaving the scope of an element.
28102 	    */
28103 	    if (node != vctxt->inode->node) {
28104 		VERROR_INT("xmlSchemaVDocWalk",
28105 		    "element position mismatch");
28106 		goto internal_error;
28107 	    }
28108 	    ret = xmlSchemaValidatorPopElem(vctxt);
28109 	    if (ret != 0) {
28110 		if (ret < 0) {
28111 		    VERROR_INT("xmlSchemaVDocWalk",
28112 			"calling xmlSchemaValidatorPopElem()");
28113 		    goto internal_error;
28114 		}
28115 	    }
28116 	    if (node == valRoot)
28117 		goto exit;
28118 	}
28119 next_sibling:
28120 	if (node->next != NULL)
28121 	    node = node->next;
28122 	else {
28123 	    node = node->parent;
28124 	    goto leave_node;
28125 	}
28126     }
28127 
28128 exit:
28129     return (ret);
28130 internal_error:
28131     return (-1);
28132 }
28133 
28134 static int
xmlSchemaPreRun(xmlSchemaValidCtxtPtr vctxt)28135 xmlSchemaPreRun(xmlSchemaValidCtxtPtr vctxt) {
28136     /*
28137     * Some initialization.
28138     */
28139     vctxt->err = 0;
28140     vctxt->nberrors = 0;
28141     vctxt->depth = -1;
28142     vctxt->skipDepth = -1;
28143     vctxt->xsiAssemble = 0;
28144     vctxt->hasKeyrefs = 0;
28145 #ifdef ENABLE_IDC_NODE_TABLES_TEST
28146     vctxt->createIDCNodeTables = 1;
28147 #else
28148     vctxt->createIDCNodeTables = 0;
28149 #endif
28150     /*
28151     * Create a schema + parser if necessary.
28152     */
28153     if (vctxt->schema == NULL) {
28154 	xmlSchemaParserCtxtPtr pctxt;
28155 
28156 	vctxt->xsiAssemble = 1;
28157 	/*
28158 	* If not schema was given then we will create a schema
28159 	* dynamically using XSI schema locations.
28160 	*
28161 	* Create the schema parser context.
28162 	*/
28163 	if ((vctxt->pctxt == NULL) &&
28164 	   (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
28165 	   return (-1);
28166 	pctxt = vctxt->pctxt;
28167 	pctxt->xsiAssemble = 1;
28168 	/*
28169 	* Create the schema.
28170 	*/
28171 	vctxt->schema = xmlSchemaNewSchema(pctxt);
28172 	if (vctxt->schema == NULL)
28173 	    return (-1);
28174 	/*
28175 	* Create the schema construction context.
28176 	*/
28177 	pctxt->constructor = xmlSchemaConstructionCtxtCreate(pctxt->dict);
28178 	if (pctxt->constructor == NULL)
28179 	    return(-1);
28180 	pctxt->constructor->mainSchema = vctxt->schema;
28181 	/*
28182 	* Take ownership of the constructor to be able to free it.
28183 	*/
28184 	pctxt->ownsConstructor = 1;
28185     }
28186     /*
28187     * Augment the IDC definitions for the main schema and all imported ones
28188     * NOTE: main schema if the first in the imported list
28189     */
28190     xmlHashScan(vctxt->schema->schemasImports, xmlSchemaAugmentImportedIDC,
28191                 vctxt);
28192 
28193     return(0);
28194 }
28195 
28196 static void
xmlSchemaPostRun(xmlSchemaValidCtxtPtr vctxt)28197 xmlSchemaPostRun(xmlSchemaValidCtxtPtr vctxt) {
28198     if (vctxt->xsiAssemble) {
28199 	if (vctxt->schema != NULL) {
28200 	    xmlSchemaFree(vctxt->schema);
28201 	    vctxt->schema = NULL;
28202 	}
28203     }
28204     xmlSchemaClearValidCtxt(vctxt);
28205 }
28206 
28207 static int
xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt)28208 xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt)
28209 {
28210     int ret = 0;
28211 
28212     if (xmlSchemaPreRun(vctxt) < 0)
28213         return(-1);
28214 
28215     if (vctxt->doc != NULL) {
28216 	/*
28217 	 * Tree validation.
28218 	 */
28219 	ret = xmlSchemaVDocWalk(vctxt);
28220 #ifdef LIBXML_READER_ENABLED
28221     } else if (vctxt->reader != NULL) {
28222 	/*
28223 	 * XML Reader validation.
28224 	 */
28225 #ifdef XML_SCHEMA_READER_ENABLED
28226 	ret = xmlSchemaVReaderWalk(vctxt);
28227 #endif
28228 #endif
28229     } else if ((vctxt->sax != NULL) && (vctxt->parserCtxt != NULL)) {
28230 	/*
28231 	 * SAX validation.
28232 	 */
28233 	ret = xmlParseDocument(vctxt->parserCtxt);
28234     } else {
28235 	VERROR_INT("xmlSchemaVStart",
28236 	    "no instance to validate");
28237 	ret = -1;
28238     }
28239 
28240     xmlSchemaPostRun(vctxt);
28241     if (ret == 0)
28242 	ret = vctxt->err;
28243     return (ret);
28244 }
28245 
28246 /**
28247  * xmlSchemaValidateOneElement:
28248  * @ctxt:  a schema validation context
28249  * @elem:  an element node
28250  *
28251  * Validate a branch of a tree, starting with the given @elem.
28252  *
28253  * Returns 0 if the element and its subtree is valid, a positive error
28254  * code number otherwise and -1 in case of an internal or API error.
28255  */
28256 int
xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt,xmlNodePtr elem)28257 xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
28258 {
28259     if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
28260 	return (-1);
28261 
28262     if (ctxt->schema == NULL)
28263 	return (-1);
28264 
28265     ctxt->doc = elem->doc;
28266     ctxt->node = elem;
28267     ctxt->validationRoot = elem;
28268     return(xmlSchemaVStart(ctxt));
28269 }
28270 
28271 /**
28272  * xmlSchemaValidateDoc:
28273  * @ctxt:  a schema validation context
28274  * @doc:  a parsed document tree
28275  *
28276  * Validate a document tree in memory.
28277  *
28278  * Returns 0 if the document is schemas valid, a positive error code
28279  *     number otherwise and -1 in case of internal or API error.
28280  */
28281 int
xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt,xmlDocPtr doc)28282 xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
28283 {
28284     if ((ctxt == NULL) || (doc == NULL))
28285         return (-1);
28286 
28287     ctxt->doc = doc;
28288     ctxt->node = xmlDocGetRootElement(doc);
28289     if (ctxt->node == NULL) {
28290         xmlSchemaCustomErr(ACTXT_CAST ctxt,
28291 	    XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
28292 	    (xmlNodePtr) doc, NULL,
28293 	    "The document has no document element", NULL, NULL);
28294         return (ctxt->err);
28295     }
28296     ctxt->validationRoot = ctxt->node;
28297     return (xmlSchemaVStart(ctxt));
28298 }
28299 
28300 
28301 /************************************************************************
28302  *									*
28303  *		Function and data for SAX streaming API			*
28304  *									*
28305  ************************************************************************/
28306 typedef struct _xmlSchemaSplitSAXData xmlSchemaSplitSAXData;
28307 typedef xmlSchemaSplitSAXData *xmlSchemaSplitSAXDataPtr;
28308 
28309 struct _xmlSchemaSplitSAXData {
28310     xmlSAXHandlerPtr      user_sax;
28311     void                 *user_data;
28312     xmlSchemaValidCtxtPtr ctxt;
28313     xmlSAXHandlerPtr      schemas_sax;
28314 };
28315 
28316 #define XML_SAX_PLUG_MAGIC 0xdc43ba21
28317 
28318 struct _xmlSchemaSAXPlug {
28319     unsigned int magic;
28320 
28321     /* the original callbacks informations */
28322     xmlSAXHandlerPtr     *user_sax_ptr;
28323     xmlSAXHandlerPtr      user_sax;
28324     void                **user_data_ptr;
28325     void                 *user_data;
28326 
28327     /* the block plugged back and validation informations */
28328     xmlSAXHandler         schemas_sax;
28329     xmlSchemaValidCtxtPtr ctxt;
28330 };
28331 
28332 /* All those functions just bounces to the user provided SAX handlers */
28333 static void
internalSubsetSplit(void * ctx,const xmlChar * name,const xmlChar * ExternalID,const xmlChar * SystemID)28334 internalSubsetSplit(void *ctx, const xmlChar *name,
28335 	       const xmlChar *ExternalID, const xmlChar *SystemID)
28336 {
28337     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28338     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28339         (ctxt->user_sax->internalSubset != NULL))
28340 	ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
28341 	                               SystemID);
28342 }
28343 
28344 static int
isStandaloneSplit(void * ctx)28345 isStandaloneSplit(void *ctx)
28346 {
28347     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28348     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28349         (ctxt->user_sax->isStandalone != NULL))
28350 	return(ctxt->user_sax->isStandalone(ctxt->user_data));
28351     return(0);
28352 }
28353 
28354 static int
hasInternalSubsetSplit(void * ctx)28355 hasInternalSubsetSplit(void *ctx)
28356 {
28357     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28358     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28359         (ctxt->user_sax->hasInternalSubset != NULL))
28360 	return(ctxt->user_sax->hasInternalSubset(ctxt->user_data));
28361     return(0);
28362 }
28363 
28364 static int
hasExternalSubsetSplit(void * ctx)28365 hasExternalSubsetSplit(void *ctx)
28366 {
28367     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28368     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28369         (ctxt->user_sax->hasExternalSubset != NULL))
28370 	return(ctxt->user_sax->hasExternalSubset(ctxt->user_data));
28371     return(0);
28372 }
28373 
28374 static void
externalSubsetSplit(void * ctx,const xmlChar * name,const xmlChar * ExternalID,const xmlChar * SystemID)28375 externalSubsetSplit(void *ctx, const xmlChar *name,
28376 	       const xmlChar *ExternalID, const xmlChar *SystemID)
28377 {
28378     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28379     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28380         (ctxt->user_sax->externalSubset != NULL))
28381 	ctxt->user_sax->externalSubset(ctxt->user_data, name, ExternalID,
28382 	                               SystemID);
28383 }
28384 
28385 static xmlParserInputPtr
resolveEntitySplit(void * ctx,const xmlChar * publicId,const xmlChar * systemId)28386 resolveEntitySplit(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
28387 {
28388     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28389     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28390         (ctxt->user_sax->resolveEntity != NULL))
28391 	return(ctxt->user_sax->resolveEntity(ctxt->user_data, publicId,
28392 	                                     systemId));
28393     return(NULL);
28394 }
28395 
28396 static xmlEntityPtr
getEntitySplit(void * ctx,const xmlChar * name)28397 getEntitySplit(void *ctx, const xmlChar *name)
28398 {
28399     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28400     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28401         (ctxt->user_sax->getEntity != NULL))
28402 	return(ctxt->user_sax->getEntity(ctxt->user_data, name));
28403     return(NULL);
28404 }
28405 
28406 static xmlEntityPtr
getParameterEntitySplit(void * ctx,const xmlChar * name)28407 getParameterEntitySplit(void *ctx, const xmlChar *name)
28408 {
28409     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28410     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28411         (ctxt->user_sax->getParameterEntity != NULL))
28412 	return(ctxt->user_sax->getParameterEntity(ctxt->user_data, name));
28413     return(NULL);
28414 }
28415 
28416 
28417 static void
entityDeclSplit(void * ctx,const xmlChar * name,int type,const xmlChar * publicId,const xmlChar * systemId,xmlChar * content)28418 entityDeclSplit(void *ctx, const xmlChar *name, int type,
28419           const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
28420 {
28421     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28422     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28423         (ctxt->user_sax->entityDecl != NULL))
28424 	ctxt->user_sax->entityDecl(ctxt->user_data, name, type, publicId,
28425 	                           systemId, content);
28426 }
28427 
28428 static void
attributeDeclSplit(void * ctx,const xmlChar * elem,const xmlChar * name,int type,int def,const xmlChar * defaultValue,xmlEnumerationPtr tree)28429 attributeDeclSplit(void *ctx, const xmlChar * elem,
28430                    const xmlChar * name, int type, int def,
28431                    const xmlChar * defaultValue, xmlEnumerationPtr tree)
28432 {
28433     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28434     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28435         (ctxt->user_sax->attributeDecl != NULL)) {
28436 	ctxt->user_sax->attributeDecl(ctxt->user_data, elem, name, type,
28437 	                              def, defaultValue, tree);
28438     } else {
28439 	xmlFreeEnumeration(tree);
28440     }
28441 }
28442 
28443 static void
elementDeclSplit(void * ctx,const xmlChar * name,int type,xmlElementContentPtr content)28444 elementDeclSplit(void *ctx, const xmlChar *name, int type,
28445 	    xmlElementContentPtr content)
28446 {
28447     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28448     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28449         (ctxt->user_sax->elementDecl != NULL))
28450 	ctxt->user_sax->elementDecl(ctxt->user_data, name, type, content);
28451 }
28452 
28453 static void
notationDeclSplit(void * ctx,const xmlChar * name,const xmlChar * publicId,const xmlChar * systemId)28454 notationDeclSplit(void *ctx, const xmlChar *name,
28455 	     const xmlChar *publicId, const xmlChar *systemId)
28456 {
28457     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28458     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28459         (ctxt->user_sax->notationDecl != NULL))
28460 	ctxt->user_sax->notationDecl(ctxt->user_data, name, publicId,
28461 	                             systemId);
28462 }
28463 
28464 static void
unparsedEntityDeclSplit(void * ctx,const xmlChar * name,const xmlChar * publicId,const xmlChar * systemId,const xmlChar * notationName)28465 unparsedEntityDeclSplit(void *ctx, const xmlChar *name,
28466 		   const xmlChar *publicId, const xmlChar *systemId,
28467 		   const xmlChar *notationName)
28468 {
28469     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28470     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28471         (ctxt->user_sax->unparsedEntityDecl != NULL))
28472 	ctxt->user_sax->unparsedEntityDecl(ctxt->user_data, name, publicId,
28473 	                                   systemId, notationName);
28474 }
28475 
28476 static void
setDocumentLocatorSplit(void * ctx,xmlSAXLocatorPtr loc)28477 setDocumentLocatorSplit(void *ctx, xmlSAXLocatorPtr loc)
28478 {
28479     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28480     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28481         (ctxt->user_sax->setDocumentLocator != NULL))
28482 	ctxt->user_sax->setDocumentLocator(ctxt->user_data, loc);
28483 }
28484 
28485 static void
startDocumentSplit(void * ctx)28486 startDocumentSplit(void *ctx)
28487 {
28488     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28489     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28490         (ctxt->user_sax->startDocument != NULL))
28491 	ctxt->user_sax->startDocument(ctxt->user_data);
28492 }
28493 
28494 static void
endDocumentSplit(void * ctx)28495 endDocumentSplit(void *ctx)
28496 {
28497     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28498     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28499         (ctxt->user_sax->endDocument != NULL))
28500 	ctxt->user_sax->endDocument(ctxt->user_data);
28501 }
28502 
28503 static void
processingInstructionSplit(void * ctx,const xmlChar * target,const xmlChar * data)28504 processingInstructionSplit(void *ctx, const xmlChar *target,
28505                       const xmlChar *data)
28506 {
28507     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28508     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28509         (ctxt->user_sax->processingInstruction != NULL))
28510 	ctxt->user_sax->processingInstruction(ctxt->user_data, target, data);
28511 }
28512 
28513 static void
commentSplit(void * ctx,const xmlChar * value)28514 commentSplit(void *ctx, const xmlChar *value)
28515 {
28516     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28517     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28518         (ctxt->user_sax->comment != NULL))
28519 	ctxt->user_sax->comment(ctxt->user_data, value);
28520 }
28521 
28522 /*
28523  * Varargs error callbacks to the user application, harder ...
28524  */
28525 
28526 static void XMLCDECL
warningSplit(void * ctx,const char * msg ATTRIBUTE_UNUSED,...)28527 warningSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28528     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28529     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28530         (ctxt->user_sax->warning != NULL)) {
28531 	TODO
28532     }
28533 }
28534 static void XMLCDECL
errorSplit(void * ctx,const char * msg ATTRIBUTE_UNUSED,...)28535 errorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28536     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28537     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28538         (ctxt->user_sax->error != NULL)) {
28539 	TODO
28540     }
28541 }
28542 static void XMLCDECL
fatalErrorSplit(void * ctx,const char * msg ATTRIBUTE_UNUSED,...)28543 fatalErrorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28544     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28545     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28546         (ctxt->user_sax->fatalError != NULL)) {
28547 	TODO
28548     }
28549 }
28550 
28551 /*
28552  * Those are function where both the user handler and the schemas handler
28553  * need to be called.
28554  */
28555 static void
charactersSplit(void * ctx,const xmlChar * ch,int len)28556 charactersSplit(void *ctx, const xmlChar *ch, int len)
28557 {
28558     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28559     if (ctxt == NULL)
28560         return;
28561     if ((ctxt->user_sax != NULL) && (ctxt->user_sax->characters != NULL))
28562 	ctxt->user_sax->characters(ctxt->user_data, ch, len);
28563     if (ctxt->ctxt != NULL)
28564 	xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
28565 }
28566 
28567 static void
ignorableWhitespaceSplit(void * ctx,const xmlChar * ch,int len)28568 ignorableWhitespaceSplit(void *ctx, const xmlChar *ch, int len)
28569 {
28570     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28571     if (ctxt == NULL)
28572         return;
28573     if ((ctxt->user_sax != NULL) &&
28574         (ctxt->user_sax->ignorableWhitespace != NULL))
28575 	ctxt->user_sax->ignorableWhitespace(ctxt->user_data, ch, len);
28576     if (ctxt->ctxt != NULL)
28577 	xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
28578 }
28579 
28580 static void
cdataBlockSplit(void * ctx,const xmlChar * value,int len)28581 cdataBlockSplit(void *ctx, const xmlChar *value, int len)
28582 {
28583     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28584     if (ctxt == NULL)
28585         return;
28586     if ((ctxt->user_sax != NULL) &&
28587         (ctxt->user_sax->cdataBlock != NULL))
28588 	ctxt->user_sax->cdataBlock(ctxt->user_data, value, len);
28589     if (ctxt->ctxt != NULL)
28590 	xmlSchemaSAXHandleCDataSection(ctxt->ctxt, value, len);
28591 }
28592 
28593 static void
referenceSplit(void * ctx,const xmlChar * name)28594 referenceSplit(void *ctx, const xmlChar *name)
28595 {
28596     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28597     if (ctxt == NULL)
28598         return;
28599     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28600         (ctxt->user_sax->reference != NULL))
28601 	ctxt->user_sax->reference(ctxt->user_data, name);
28602     if (ctxt->ctxt != NULL)
28603         xmlSchemaSAXHandleReference(ctxt->user_data, name);
28604 }
28605 
28606 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)28607 startElementNsSplit(void *ctx, const xmlChar * localname,
28608 		    const xmlChar * prefix, const xmlChar * URI,
28609 		    int nb_namespaces, const xmlChar ** namespaces,
28610 		    int nb_attributes, int nb_defaulted,
28611 		    const xmlChar ** attributes) {
28612     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28613     if (ctxt == NULL)
28614         return;
28615     if ((ctxt->user_sax != NULL) &&
28616         (ctxt->user_sax->startElementNs != NULL))
28617 	ctxt->user_sax->startElementNs(ctxt->user_data, localname, prefix,
28618 	                               URI, nb_namespaces, namespaces,
28619 				       nb_attributes, nb_defaulted,
28620 				       attributes);
28621     if (ctxt->ctxt != NULL)
28622 	xmlSchemaSAXHandleStartElementNs(ctxt->ctxt, localname, prefix,
28623 	                                 URI, nb_namespaces, namespaces,
28624 					 nb_attributes, nb_defaulted,
28625 					 attributes);
28626 }
28627 
28628 static void
endElementNsSplit(void * ctx,const xmlChar * localname,const xmlChar * prefix,const xmlChar * URI)28629 endElementNsSplit(void *ctx, const xmlChar * localname,
28630 		    const xmlChar * prefix, const xmlChar * URI) {
28631     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28632     if (ctxt == NULL)
28633         return;
28634     if ((ctxt->user_sax != NULL) &&
28635         (ctxt->user_sax->endElementNs != NULL))
28636 	ctxt->user_sax->endElementNs(ctxt->user_data, localname, prefix, URI);
28637     if (ctxt->ctxt != NULL)
28638 	xmlSchemaSAXHandleEndElementNs(ctxt->ctxt, localname, prefix, URI);
28639 }
28640 
28641 /**
28642  * xmlSchemaSAXPlug:
28643  * @ctxt:  a schema validation context
28644  * @sax:  a pointer to the original xmlSAXHandlerPtr
28645  * @user_data:  a pointer to the original SAX user data pointer
28646  *
28647  * Plug a SAX based validation layer in a SAX parsing event flow.
28648  * The original @saxptr and @dataptr data are replaced by new pointers
28649  * but the calls to the original will be maintained.
28650  *
28651  * Returns a pointer to a data structure needed to unplug the validation layer
28652  *         or NULL in case of errors.
28653  */
28654 xmlSchemaSAXPlugPtr
xmlSchemaSAXPlug(xmlSchemaValidCtxtPtr ctxt,xmlSAXHandlerPtr * sax,void ** user_data)28655 xmlSchemaSAXPlug(xmlSchemaValidCtxtPtr ctxt,
28656 		 xmlSAXHandlerPtr *sax, void **user_data)
28657 {
28658     xmlSchemaSAXPlugPtr ret;
28659     xmlSAXHandlerPtr old_sax;
28660 
28661     if ((ctxt == NULL) || (sax == NULL) || (user_data == NULL))
28662         return(NULL);
28663 
28664     /*
28665      * We only allow to plug into SAX2 event streams
28666      */
28667     old_sax = *sax;
28668     if ((old_sax != NULL) && (old_sax->initialized != XML_SAX2_MAGIC))
28669         return(NULL);
28670     if ((old_sax != NULL) &&
28671         (old_sax->startElementNs == NULL) && (old_sax->endElementNs == NULL) &&
28672         ((old_sax->startElement != NULL) || (old_sax->endElement != NULL)))
28673         return(NULL);
28674 
28675     /*
28676      * everything seems right allocate the local data needed for that layer
28677      */
28678     ret = (xmlSchemaSAXPlugPtr) xmlMalloc(sizeof(xmlSchemaSAXPlugStruct));
28679     if (ret == NULL) {
28680         return(NULL);
28681     }
28682     memset(ret, 0, sizeof(xmlSchemaSAXPlugStruct));
28683     ret->magic = XML_SAX_PLUG_MAGIC;
28684     ret->schemas_sax.initialized = XML_SAX2_MAGIC;
28685     ret->ctxt = ctxt;
28686     ret->user_sax_ptr = sax;
28687     ret->user_sax = old_sax;
28688     if (old_sax == NULL) {
28689         /*
28690 	 * go direct, no need for the split block and functions.
28691 	 */
28692 	ret->schemas_sax.startElementNs = xmlSchemaSAXHandleStartElementNs;
28693 	ret->schemas_sax.endElementNs = xmlSchemaSAXHandleEndElementNs;
28694 	/*
28695 	 * Note that we use the same text-function for both, to prevent
28696 	 * the parser from testing for ignorable whitespace.
28697 	 */
28698 	ret->schemas_sax.ignorableWhitespace = xmlSchemaSAXHandleText;
28699 	ret->schemas_sax.characters = xmlSchemaSAXHandleText;
28700 
28701 	ret->schemas_sax.cdataBlock = xmlSchemaSAXHandleCDataSection;
28702 	ret->schemas_sax.reference = xmlSchemaSAXHandleReference;
28703 
28704 	ret->user_data = ctxt;
28705 	*user_data = ctxt;
28706     } else {
28707        /*
28708         * for each callback unused by Schemas initialize it to the Split
28709 	* routine only if non NULL in the user block, this can speed up
28710 	* things at the SAX level.
28711 	*/
28712         if (old_sax->internalSubset != NULL)
28713             ret->schemas_sax.internalSubset = internalSubsetSplit;
28714         if (old_sax->isStandalone != NULL)
28715             ret->schemas_sax.isStandalone = isStandaloneSplit;
28716         if (old_sax->hasInternalSubset != NULL)
28717             ret->schemas_sax.hasInternalSubset = hasInternalSubsetSplit;
28718         if (old_sax->hasExternalSubset != NULL)
28719             ret->schemas_sax.hasExternalSubset = hasExternalSubsetSplit;
28720         if (old_sax->resolveEntity != NULL)
28721             ret->schemas_sax.resolveEntity = resolveEntitySplit;
28722         if (old_sax->getEntity != NULL)
28723             ret->schemas_sax.getEntity = getEntitySplit;
28724         if (old_sax->entityDecl != NULL)
28725             ret->schemas_sax.entityDecl = entityDeclSplit;
28726         if (old_sax->notationDecl != NULL)
28727             ret->schemas_sax.notationDecl = notationDeclSplit;
28728         if (old_sax->attributeDecl != NULL)
28729             ret->schemas_sax.attributeDecl = attributeDeclSplit;
28730         if (old_sax->elementDecl != NULL)
28731             ret->schemas_sax.elementDecl = elementDeclSplit;
28732         if (old_sax->unparsedEntityDecl != NULL)
28733             ret->schemas_sax.unparsedEntityDecl = unparsedEntityDeclSplit;
28734         if (old_sax->setDocumentLocator != NULL)
28735             ret->schemas_sax.setDocumentLocator = setDocumentLocatorSplit;
28736         if (old_sax->startDocument != NULL)
28737             ret->schemas_sax.startDocument = startDocumentSplit;
28738         if (old_sax->endDocument != NULL)
28739             ret->schemas_sax.endDocument = endDocumentSplit;
28740         if (old_sax->processingInstruction != NULL)
28741             ret->schemas_sax.processingInstruction = processingInstructionSplit;
28742         if (old_sax->comment != NULL)
28743             ret->schemas_sax.comment = commentSplit;
28744         if (old_sax->warning != NULL)
28745             ret->schemas_sax.warning = warningSplit;
28746         if (old_sax->error != NULL)
28747             ret->schemas_sax.error = errorSplit;
28748         if (old_sax->fatalError != NULL)
28749             ret->schemas_sax.fatalError = fatalErrorSplit;
28750         if (old_sax->getParameterEntity != NULL)
28751             ret->schemas_sax.getParameterEntity = getParameterEntitySplit;
28752         if (old_sax->externalSubset != NULL)
28753             ret->schemas_sax.externalSubset = externalSubsetSplit;
28754 
28755 	/*
28756 	 * the 6 schemas callback have to go to the splitter functions
28757 	 * Note that we use the same text-function for ignorableWhitespace
28758 	 * if possible, to prevent the parser from testing for ignorable
28759 	 * whitespace.
28760 	 */
28761         ret->schemas_sax.characters = charactersSplit;
28762 	if ((old_sax->ignorableWhitespace != NULL) &&
28763 	    (old_sax->ignorableWhitespace != old_sax->characters))
28764 	    ret->schemas_sax.ignorableWhitespace = ignorableWhitespaceSplit;
28765 	else
28766 	    ret->schemas_sax.ignorableWhitespace = charactersSplit;
28767         ret->schemas_sax.cdataBlock = cdataBlockSplit;
28768         ret->schemas_sax.reference = referenceSplit;
28769         ret->schemas_sax.startElementNs = startElementNsSplit;
28770         ret->schemas_sax.endElementNs = endElementNsSplit;
28771 
28772 	ret->user_data_ptr = user_data;
28773 	ret->user_data = *user_data;
28774 	*user_data = ret;
28775     }
28776 
28777     /*
28778      * plug the pointers back.
28779      */
28780     *sax = &(ret->schemas_sax);
28781     ctxt->sax = *sax;
28782     ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28783     xmlSchemaPreRun(ctxt);
28784     return(ret);
28785 }
28786 
28787 /**
28788  * xmlSchemaSAXUnplug:
28789  * @plug:  a data structure returned by xmlSchemaSAXPlug
28790  *
28791  * Unplug a SAX based validation layer in a SAX parsing event flow.
28792  * The original pointers used in the call are restored.
28793  *
28794  * Returns 0 in case of success and -1 in case of failure.
28795  */
28796 int
xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug)28797 xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug)
28798 {
28799     xmlSAXHandlerPtr *sax;
28800     void **user_data;
28801 
28802     if ((plug == NULL) || (plug->magic != XML_SAX_PLUG_MAGIC))
28803         return(-1);
28804     plug->magic = 0;
28805 
28806     xmlSchemaPostRun(plug->ctxt);
28807     /* restore the data */
28808     sax = plug->user_sax_ptr;
28809     *sax = plug->user_sax;
28810     if (plug->user_sax != NULL) {
28811 	user_data = plug->user_data_ptr;
28812 	*user_data = plug->user_data;
28813     }
28814 
28815     /* free and return */
28816     xmlFree(plug);
28817     return(0);
28818 }
28819 
28820 /**
28821  * xmlSchemaValidateSetLocator:
28822  * @vctxt: a schema validation context
28823  * @f: the locator function pointer
28824  * @ctxt: the locator context
28825  *
28826  * Allows to set a locator function to the validation context,
28827  * which will be used to provide file and line information since
28828  * those are not provided as part of the SAX validation flow
28829  * Setting @f to NULL disable the locator.
28830  */
28831 
28832 void
xmlSchemaValidateSetLocator(xmlSchemaValidCtxtPtr vctxt,xmlSchemaValidityLocatorFunc f,void * ctxt)28833 xmlSchemaValidateSetLocator(xmlSchemaValidCtxtPtr vctxt,
28834                             xmlSchemaValidityLocatorFunc f,
28835 			    void *ctxt)
28836 {
28837     if (vctxt == NULL) return;
28838     vctxt->locFunc = f;
28839     vctxt->locCtxt = ctxt;
28840 }
28841 
28842 /**
28843  * xmlSchemaValidateStreamLocator:
28844  * @ctx: the xmlTextReaderPtr used
28845  * @file: returned file information
28846  * @line: returned line information
28847  *
28848  * Internal locator function for the readers
28849  *
28850  * Returns 0 in case the Schema validation could be (des)activated and
28851  *         -1 in case of error.
28852  */
28853 static int
xmlSchemaValidateStreamLocator(void * ctx,const char ** file,unsigned long * line)28854 xmlSchemaValidateStreamLocator(void *ctx, const char **file,
28855                                unsigned long *line) {
28856     xmlParserCtxtPtr ctxt;
28857 
28858     if ((ctx == NULL) || ((file == NULL) && (line == NULL)))
28859         return(-1);
28860 
28861     if (file != NULL)
28862         *file = NULL;
28863     if (line != NULL)
28864         *line = 0;
28865 
28866     ctxt = (xmlParserCtxtPtr) ctx;
28867     if (ctxt->input != NULL) {
28868        if (file != NULL)
28869            *file = ctxt->input->filename;
28870        if (line != NULL)
28871            *line = ctxt->input->line;
28872        return(0);
28873     }
28874     return(-1);
28875 }
28876 
28877 /**
28878  * xmlSchemaValidateStream:
28879  * @ctxt:  a schema validation context
28880  * @input:  the input to use for reading the data
28881  * @enc:  an optional encoding information
28882  * @sax:  a SAX handler for the resulting events
28883  * @user_data:  the context to provide to the SAX handler.
28884  *
28885  * Validate an input based on a flow of SAX event from the parser
28886  * and forward the events to the @sax handler with the provided @user_data
28887  * the user provided @sax handler must be a SAX2 one.
28888  *
28889  * Returns 0 if the document is schemas valid, a positive error code
28890  *     number otherwise and -1 in case of internal or API error.
28891  */
28892 int
xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,xmlParserInputBufferPtr input,xmlCharEncoding enc,xmlSAXHandlerPtr sax,void * user_data)28893 xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
28894                         xmlParserInputBufferPtr input, xmlCharEncoding enc,
28895                         xmlSAXHandlerPtr sax, void *user_data)
28896 {
28897     xmlSchemaSAXPlugPtr plug = NULL;
28898     xmlSAXHandlerPtr old_sax = NULL;
28899     xmlParserCtxtPtr pctxt = NULL;
28900     xmlParserInputPtr inputStream = NULL;
28901     int ret;
28902 
28903     if ((ctxt == NULL) || (input == NULL))
28904         return (-1);
28905 
28906     /*
28907      * prepare the parser
28908      */
28909     pctxt = xmlNewParserCtxt();
28910     if (pctxt == NULL)
28911         return (-1);
28912     old_sax = pctxt->sax;
28913     pctxt->sax = sax;
28914     pctxt->userData = user_data;
28915 #if 0
28916     if (options)
28917         xmlCtxtUseOptions(pctxt, options);
28918 #endif
28919     pctxt->linenumbers = 1;
28920     xmlSchemaValidateSetLocator(ctxt, xmlSchemaValidateStreamLocator, pctxt);
28921 
28922     inputStream = xmlNewIOInputStream(pctxt, input, enc);;
28923     if (inputStream == NULL) {
28924         ret = -1;
28925 	goto done;
28926     }
28927     inputPush(pctxt, inputStream);
28928     ctxt->parserCtxt = pctxt;
28929     ctxt->input = input;
28930 
28931     /*
28932      * Plug the validation and launch the parsing
28933      */
28934     plug = xmlSchemaSAXPlug(ctxt, &(pctxt->sax), &(pctxt->userData));
28935     if (plug == NULL) {
28936         ret = -1;
28937 	goto done;
28938     }
28939     ctxt->input = input;
28940     ctxt->enc = enc;
28941     ctxt->sax = pctxt->sax;
28942     ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28943     ret = xmlSchemaVStart(ctxt);
28944 
28945     if ((ret == 0) && (! ctxt->parserCtxt->wellFormed)) {
28946 	ret = ctxt->parserCtxt->errNo;
28947 	if (ret == 0)
28948 	    ret = 1;
28949     }
28950 
28951 done:
28952     ctxt->parserCtxt = NULL;
28953     ctxt->sax = NULL;
28954     ctxt->input = NULL;
28955     if (plug != NULL) {
28956         xmlSchemaSAXUnplug(plug);
28957     }
28958     /* cleanup */
28959     if (pctxt != NULL) {
28960 	pctxt->sax = old_sax;
28961 	xmlFreeParserCtxt(pctxt);
28962     }
28963     return (ret);
28964 }
28965 
28966 /**
28967  * xmlSchemaValidateFile:
28968  * @ctxt: a schema validation context
28969  * @filename: the URI of the instance
28970  * @options: a future set of options, currently unused
28971  *
28972  * Do a schemas validation of the given resource, it will use the
28973  * SAX streamable validation internally.
28974  *
28975  * Returns 0 if the document is valid, a positive error code
28976  *     number otherwise and -1 in case of an internal or API error.
28977  */
28978 int
xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt,const char * filename,int options ATTRIBUTE_UNUSED)28979 xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt,
28980                       const char * filename,
28981 		      int options ATTRIBUTE_UNUSED)
28982 {
28983     int ret;
28984     xmlParserInputBufferPtr input;
28985 
28986     if ((ctxt == NULL) || (filename == NULL))
28987         return (-1);
28988 
28989     input = xmlParserInputBufferCreateFilename(filename,
28990 	XML_CHAR_ENCODING_NONE);
28991     if (input == NULL)
28992 	return (-1);
28993     ret = xmlSchemaValidateStream(ctxt, input, XML_CHAR_ENCODING_NONE,
28994 	NULL, NULL);
28995     return (ret);
28996 }
28997 
28998 /**
28999  * xmlSchemaValidCtxtGetParserCtxt:
29000  * @ctxt: a schema validation context
29001  *
29002  * allow access to the parser context of the schema validation context
29003  *
29004  * Returns the parser context of the schema validation context or NULL
29005  *         in case of error.
29006  */
29007 xmlParserCtxtPtr
xmlSchemaValidCtxtGetParserCtxt(xmlSchemaValidCtxtPtr ctxt)29008 xmlSchemaValidCtxtGetParserCtxt(xmlSchemaValidCtxtPtr ctxt)
29009 {
29010     if (ctxt == NULL)
29011         return(NULL);
29012     return (ctxt->parserCtxt);
29013 }
29014 
29015 #define bottom_xmlschemas
29016 #include "elfgcchack.h"
29017 #endif /* LIBXML_SCHEMAS_ENABLED */
29018