xref: /aosp_15_r20/external/libxml2/xmlschemastypes.c (revision 7c5688314b92172186c154356a6374bf7684c3ca)
1 /*
2  * schemastypes.c : implementation of the XML Schema Datatypes
3  *             definition and validity checking
4  *
5  * See Copyright for the status of this software.
6  *
7  * Daniel Veillard <[email protected]>
8  */
9 
10 /* To avoid EBCDIC trouble when parsing on zOS */
11 #if defined(__MVS__)
12 #pragma convert("ISO8859-1")
13 #endif
14 
15 #define IN_LIBXML
16 #include "libxml.h"
17 
18 #ifdef LIBXML_SCHEMAS_ENABLED
19 
20 #include <stdlib.h>
21 #include <string.h>
22 #include <math.h>
23 #include <float.h>
24 
25 #include <libxml/xmlmemory.h>
26 #include <libxml/parser.h>
27 #include <libxml/parserInternals.h>
28 #include <libxml/hash.h>
29 #include <libxml/xpath.h>
30 #include <libxml/uri.h>
31 #include <string.h>
32 
33 #include <libxml/xmlschemas.h>
34 #include <libxml/schemasInternals.h>
35 #include <libxml/xmlschemastypes.h>
36 
37 #include "private/error.h"
38 
39 #ifndef isnan
40   #define isnan(x) (!((x) == (x)))
41 #endif
42 
43 #define XML_SCHEMAS_NAMESPACE_NAME \
44     (const xmlChar *)"http://www.w3.org/2001/XMLSchema"
45 
46 #define IS_WSP_REPLACE_CH(c)	((((c) == 0x9) || ((c) == 0xa)) || \
47 				 ((c) == 0xd))
48 
49 #define IS_WSP_SPACE_CH(c)	((c) == 0x20)
50 
51 #define IS_WSP_BLANK_CH(c) IS_BLANK_CH(c)
52 
53 /* Date value */
54 typedef struct _xmlSchemaValDate xmlSchemaValDate;
55 typedef xmlSchemaValDate *xmlSchemaValDatePtr;
56 struct _xmlSchemaValDate {
57     long		year;
58     unsigned int	mon	:4;	/* 1 <=  mon    <= 12   */
59     unsigned int	day	:5;	/* 1 <=  day    <= 31   */
60     unsigned int	hour	:5;	/* 0 <=  hour   <= 24   */
61     unsigned int	min	:6;	/* 0 <=  min    <= 59	*/
62     double		sec;
63     unsigned int	tz_flag	:1;	/* is tzo explicitly set? */
64     signed int		tzo	:12;	/* -1440 <= tzo <= 1440;
65 					   currently only -840 to +840 are needed */
66 };
67 
68 /* Duration value */
69 typedef struct _xmlSchemaValDuration xmlSchemaValDuration;
70 typedef xmlSchemaValDuration *xmlSchemaValDurationPtr;
71 struct _xmlSchemaValDuration {
72     long	        mon;		/* mon stores years also */
73     long	day;
74     double		sec;            /* sec stores min and hour also */
75 };
76 
77 typedef struct _xmlSchemaValDecimal xmlSchemaValDecimal;
78 typedef xmlSchemaValDecimal *xmlSchemaValDecimalPtr;
79 struct _xmlSchemaValDecimal
80 {
81 	xmlChar *str;
82 	unsigned integralPlaces;
83 	unsigned fractionalPlaces;
84 };
85 
86 typedef struct _xmlSchemaValQName xmlSchemaValQName;
87 typedef xmlSchemaValQName *xmlSchemaValQNamePtr;
88 struct _xmlSchemaValQName {
89     xmlChar *name;
90     xmlChar *uri;
91 };
92 
93 typedef struct _xmlSchemaValHex xmlSchemaValHex;
94 typedef xmlSchemaValHex *xmlSchemaValHexPtr;
95 struct _xmlSchemaValHex {
96     xmlChar     *str;
97     unsigned int total;
98 };
99 
100 typedef struct _xmlSchemaValBase64 xmlSchemaValBase64;
101 typedef xmlSchemaValBase64 *xmlSchemaValBase64Ptr;
102 struct _xmlSchemaValBase64 {
103     xmlChar     *str;
104     unsigned int total;
105 };
106 
107 struct _xmlSchemaVal {
108     xmlSchemaValType type;
109     struct _xmlSchemaVal *next;
110     union {
111 	xmlSchemaValDecimal     decimal;
112         xmlSchemaValDate        date;
113         xmlSchemaValDuration    dur;
114 	xmlSchemaValQName	qname;
115 	xmlSchemaValHex		hex;
116 	xmlSchemaValBase64	base64;
117 	float			f;
118 	double			d;
119 	int			b;
120 	xmlChar                *str;
121     } value;
122 };
123 
124 static int xmlSchemaTypesInitialized = 0;
125 
126 static double xmlSchemaNAN = 0.0;
127 static double xmlSchemaPINF = 0.0;
128 static double xmlSchemaNINF = 0.0;
129 
130 static xmlHashTablePtr xmlSchemaTypesBank = NULL;
131 
132 /*
133  * Basic types
134  */
135 static xmlSchemaTypePtr xmlSchemaTypeStringDef = NULL;
136 static xmlSchemaTypePtr xmlSchemaTypeAnyTypeDef = NULL;
137 static xmlSchemaTypePtr xmlSchemaTypeAnySimpleTypeDef = NULL;
138 static xmlSchemaTypePtr xmlSchemaTypeDecimalDef = NULL;
139 static xmlSchemaTypePtr xmlSchemaTypeDatetimeDef = NULL;
140 static xmlSchemaTypePtr xmlSchemaTypeDateDef = NULL;
141 static xmlSchemaTypePtr xmlSchemaTypeTimeDef = NULL;
142 static xmlSchemaTypePtr xmlSchemaTypeGYearDef = NULL;
143 static xmlSchemaTypePtr xmlSchemaTypeGYearMonthDef = NULL;
144 static xmlSchemaTypePtr xmlSchemaTypeGDayDef = NULL;
145 static xmlSchemaTypePtr xmlSchemaTypeGMonthDayDef = NULL;
146 static xmlSchemaTypePtr xmlSchemaTypeGMonthDef = NULL;
147 static xmlSchemaTypePtr xmlSchemaTypeDurationDef = NULL;
148 static xmlSchemaTypePtr xmlSchemaTypeFloatDef = NULL;
149 static xmlSchemaTypePtr xmlSchemaTypeBooleanDef = NULL;
150 static xmlSchemaTypePtr xmlSchemaTypeDoubleDef = NULL;
151 static xmlSchemaTypePtr xmlSchemaTypeHexBinaryDef = NULL;
152 static xmlSchemaTypePtr xmlSchemaTypeBase64BinaryDef = NULL;
153 static xmlSchemaTypePtr xmlSchemaTypeAnyURIDef = NULL;
154 
155 /*
156  * Derived types
157  */
158 static xmlSchemaTypePtr xmlSchemaTypePositiveIntegerDef = NULL;
159 static xmlSchemaTypePtr xmlSchemaTypeNonPositiveIntegerDef = NULL;
160 static xmlSchemaTypePtr xmlSchemaTypeNegativeIntegerDef = NULL;
161 static xmlSchemaTypePtr xmlSchemaTypeNonNegativeIntegerDef = NULL;
162 static xmlSchemaTypePtr xmlSchemaTypeIntegerDef = NULL;
163 static xmlSchemaTypePtr xmlSchemaTypeLongDef = NULL;
164 static xmlSchemaTypePtr xmlSchemaTypeIntDef = NULL;
165 static xmlSchemaTypePtr xmlSchemaTypeShortDef = NULL;
166 static xmlSchemaTypePtr xmlSchemaTypeByteDef = NULL;
167 static xmlSchemaTypePtr xmlSchemaTypeUnsignedLongDef = NULL;
168 static xmlSchemaTypePtr xmlSchemaTypeUnsignedIntDef = NULL;
169 static xmlSchemaTypePtr xmlSchemaTypeUnsignedShortDef = NULL;
170 static xmlSchemaTypePtr xmlSchemaTypeUnsignedByteDef = NULL;
171 static xmlSchemaTypePtr xmlSchemaTypeNormStringDef = NULL;
172 static xmlSchemaTypePtr xmlSchemaTypeTokenDef = NULL;
173 static xmlSchemaTypePtr xmlSchemaTypeLanguageDef = NULL;
174 static xmlSchemaTypePtr xmlSchemaTypeNameDef = NULL;
175 static xmlSchemaTypePtr xmlSchemaTypeQNameDef = NULL;
176 static xmlSchemaTypePtr xmlSchemaTypeNCNameDef = NULL;
177 static xmlSchemaTypePtr xmlSchemaTypeIdDef = NULL;
178 static xmlSchemaTypePtr xmlSchemaTypeIdrefDef = NULL;
179 static xmlSchemaTypePtr xmlSchemaTypeIdrefsDef = NULL;
180 static xmlSchemaTypePtr xmlSchemaTypeEntityDef = NULL;
181 static xmlSchemaTypePtr xmlSchemaTypeEntitiesDef = NULL;
182 static xmlSchemaTypePtr xmlSchemaTypeNotationDef = NULL;
183 static xmlSchemaTypePtr xmlSchemaTypeNmtokenDef = NULL;
184 static xmlSchemaTypePtr xmlSchemaTypeNmtokensDef = NULL;
185 
186 /************************************************************************
187  *									*
188  *			Datatype error handlers				*
189  *									*
190  ************************************************************************/
191 /**
192  * xmlSchemaTypeErrMemory:
193  * @extra:  extra information
194  *
195  * Handle an out of memory condition
196  */
197 static void
xmlSchemaTypeErrMemory(void)198 xmlSchemaTypeErrMemory(void)
199 {
200     xmlRaiseMemoryError(NULL, NULL, NULL, XML_FROM_DATATYPE, NULL);
201 }
202 
203 /************************************************************************
204  *									*
205  *			Base types support				*
206  *									*
207  ************************************************************************/
208 
209 /**
210  * xmlSchemaNewValue:
211  * @type:  the value type
212  *
213  * Allocate a new simple type value
214  *
215  * Returns a pointer to the new value or NULL in case of error
216  */
217 static xmlSchemaValPtr
xmlSchemaNewValue(xmlSchemaValType type)218 xmlSchemaNewValue(xmlSchemaValType type) {
219     xmlSchemaValPtr value;
220 
221     value = (xmlSchemaValPtr) xmlMalloc(sizeof(xmlSchemaVal));
222     if (value == NULL) {
223 	return(NULL);
224     }
225     memset(value, 0, sizeof(xmlSchemaVal));
226     value->type = type;
227     return(value);
228 }
229 
230 static xmlSchemaFacetPtr
xmlSchemaNewMinLengthFacet(int value)231 xmlSchemaNewMinLengthFacet(int value)
232 {
233     xmlSchemaFacetPtr ret;
234     size_t bufsize;
235     xmlSchemaValDecimal *decimal;
236 
237     ret = xmlSchemaNewFacet();
238     if (ret == NULL) {
239         return(NULL);
240     }
241     ret->type = XML_SCHEMA_FACET_MINLENGTH;
242     ret->val = xmlSchemaNewValue(XML_SCHEMAS_NNINTEGER);
243     if (ret->val == NULL) {
244         xmlFree(ret);
245         return(NULL);
246     }
247     bufsize = snprintf(NULL, 0, "%+d.0", value) + 1;
248     decimal = &ret->val->value.decimal;
249     decimal->str = xmlMalloc(bufsize);
250     if (decimal->str == NULL)
251     {
252         xmlSchemaFreeFacet(ret);
253         return NULL;
254     }
255     snprintf((char *)decimal->str, bufsize, "%+d.0", value);
256     decimal->integralPlaces = bufsize - 4;
257     decimal->fractionalPlaces = 1;
258     return (ret);
259 }
260 
261 /*
262  * xmlSchemaInitBasicType:
263  * @name:  the type name
264  * @type:  the value type associated
265  *
266  * Initialize one primitive built-in type
267  */
268 static xmlSchemaTypePtr
xmlSchemaInitBasicType(const char * name,xmlSchemaValType type,xmlSchemaTypePtr baseType)269 xmlSchemaInitBasicType(const char *name, xmlSchemaValType type,
270 		       xmlSchemaTypePtr baseType) {
271     xmlSchemaTypePtr ret;
272 
273     ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
274     if (ret == NULL) {
275         xmlSchemaTypeErrMemory();
276 	return(NULL);
277     }
278     memset(ret, 0, sizeof(xmlSchemaType));
279     ret->name = (const xmlChar *)name;
280     ret->targetNamespace = XML_SCHEMAS_NAMESPACE_NAME;
281     ret->type = XML_SCHEMA_TYPE_BASIC;
282     ret->baseType = baseType;
283     ret->contentType = XML_SCHEMA_CONTENT_BASIC;
284     /*
285     * Primitive types.
286     */
287     switch (type) {
288 	case XML_SCHEMAS_STRING:
289 	case XML_SCHEMAS_DECIMAL:
290 	case XML_SCHEMAS_DATE:
291 	case XML_SCHEMAS_DATETIME:
292 	case XML_SCHEMAS_TIME:
293 	case XML_SCHEMAS_GYEAR:
294 	case XML_SCHEMAS_GYEARMONTH:
295 	case XML_SCHEMAS_GMONTH:
296 	case XML_SCHEMAS_GMONTHDAY:
297 	case XML_SCHEMAS_GDAY:
298 	case XML_SCHEMAS_DURATION:
299 	case XML_SCHEMAS_FLOAT:
300 	case XML_SCHEMAS_DOUBLE:
301 	case XML_SCHEMAS_BOOLEAN:
302 	case XML_SCHEMAS_ANYURI:
303 	case XML_SCHEMAS_HEXBINARY:
304 	case XML_SCHEMAS_BASE64BINARY:
305 	case XML_SCHEMAS_QNAME:
306 	case XML_SCHEMAS_NOTATION:
307 	    ret->flags |= XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE;
308 	    break;
309 	default:
310 	    break;
311     }
312     /*
313     * Set variety.
314     */
315     switch (type) {
316 	case XML_SCHEMAS_ANYTYPE:
317 	case XML_SCHEMAS_ANYSIMPLETYPE:
318 	    break;
319 	case XML_SCHEMAS_IDREFS:
320 	case XML_SCHEMAS_NMTOKENS:
321 	case XML_SCHEMAS_ENTITIES:
322 	    ret->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
323 	    ret->facets = xmlSchemaNewMinLengthFacet(1);
324 	    ret->flags |= XML_SCHEMAS_TYPE_HAS_FACETS;
325 	    break;
326 	default:
327 	    ret->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
328 	    break;
329     }
330     xmlHashAddEntry2(xmlSchemaTypesBank, ret->name,
331 	             XML_SCHEMAS_NAMESPACE_NAME, ret);
332     ret->builtInType = type;
333     return(ret);
334 }
335 
336 static const xmlChar *
xmlSchemaValDecimalGetFractionalPart(const xmlSchemaValDecimal * decimal)337 xmlSchemaValDecimalGetFractionalPart(const xmlSchemaValDecimal *decimal)
338 {
339     /* 2 = sign+dot */
340     return decimal->str+2+decimal->integralPlaces;
341 }
342 
343 static int
xmlSchemaValDecimalIsInteger(const xmlSchemaValDecimal * decimal)344 xmlSchemaValDecimalIsInteger(const xmlSchemaValDecimal *decimal)
345 {
346     return decimal->fractionalPlaces == 1 && xmlSchemaValDecimalGetFractionalPart(decimal)[0] == '0';
347 }
348 
349 static unsigned long
xmlSchemaValDecimalGetSignificantDigitCount(const xmlSchemaValDecimal * decimal)350 xmlSchemaValDecimalGetSignificantDigitCount(const xmlSchemaValDecimal *decimal)
351 {
352 	unsigned fractionalPlaces = xmlSchemaValDecimalIsInteger(decimal) ? 0 : decimal->fractionalPlaces;
353 	unsigned integralPlaces = decimal->integralPlaces;
354 	if(integralPlaces == 1 && decimal->str[1] == '0')
355 	{
356 		integralPlaces = 0;
357 	}
358 	if(integralPlaces+fractionalPlaces == 0)
359 	{
360 		/* 0, but that's still 1 significant digit */
361 		return 1;
362 	}
363 	return integralPlaces+fractionalPlaces;
364 }
365 
366 /**
367  * @brief Compares two decimals
368  *
369  * @param lhs
370  * @param rhs
371  * @return positive value if lhs > rhs, negative if lhs < rhs, or 0 if lhs == rhs
372  */
xmlSchemaValDecimalCompare(const xmlSchemaValDecimal * lhs,const xmlSchemaValDecimal * rhs)373 static int xmlSchemaValDecimalCompare(const xmlSchemaValDecimal *lhs, const xmlSchemaValDecimal *rhs)
374 {
375     int sign = 1;
376     /* may be +0 and -0 for some reason, handle */
377     if(strcmp((const char*)lhs->str+1, "0.0") == 0 &&
378         strcmp((const char*)rhs->str+1, "0.0") == 0)
379     {
380         return 0;
381     }
382     /* first take care of sign */
383     if(lhs->str[0] != rhs->str[0])
384     {
385         /* ASCII- > ASCII+ */
386         return rhs->str[0]-lhs->str[0];
387     }
388     /* signs are equal, but if negative the comparison must be reversed */
389     if(lhs->str[0] == '-')
390     {
391         sign = -1;
392     }
393     /* internal representation never contains leading zeroes, longer decimal representation = larger number */
394     if(lhs->integralPlaces != rhs->integralPlaces)
395     {
396         return ((int)lhs->integralPlaces-(int)rhs->integralPlaces)*sign;
397     }
398     /* same length, only digits => lexicographical sorting == numerical sorting.
399        If integral parts are equal it will compare compare fractional parts. Again, lexicographical is good enough,
400        length doesn't matter. We'll be starting from 0.1, always comparing like to like, and NULL < '0'
401        If one is shorter and is equal until end, it must be smaller, since there are no trailing zeroes
402        and the longer number must therefore have at least one non-zero digit after the other has ended.
403        +1 to skip the sign
404     */
405     return strcmp((const char*)lhs->str+1, (const char*)rhs->str+1)*sign;
406 }
407 
xmlSchemaValDecimalCompareWithInteger(const xmlSchemaValDecimal * lhs,long rhs)408 static int xmlSchemaValDecimalCompareWithInteger(const xmlSchemaValDecimal *lhs, long rhs)
409 {
410     /* can handle integers up to 128 bits, should be good for a while */
411     char buf[43];
412     xmlSchemaValDecimal tmpVal;
413     /* 3 = sign+dot+0+NULL */
414     tmpVal.integralPlaces = snprintf(buf, sizeof(buf), "%+ld.0", rhs)-3;
415     tmpVal.str = (xmlChar*)buf;
416     tmpVal.fractionalPlaces = 1;
417     return xmlSchemaValDecimalCompare(lhs, &tmpVal);
418 }
419 
420 /*
421 * WARNING: Those type reside normally in xmlschemas.c but are
422 * redefined here locally in oder of being able to use them for xs:anyType-
423 * TODO: Remove those definition if we move the types to a header file.
424 * TODO: Always keep those structs up-to-date with the originals.
425 */
426 #define UNBOUNDED (1 << 30)
427 
428 typedef struct _xmlSchemaTreeItem xmlSchemaTreeItem;
429 typedef xmlSchemaTreeItem *xmlSchemaTreeItemPtr;
430 struct _xmlSchemaTreeItem {
431     xmlSchemaTypeType type;
432     xmlSchemaAnnotPtr annot;
433     xmlSchemaTreeItemPtr next;
434     xmlSchemaTreeItemPtr children;
435 };
436 
437 typedef struct _xmlSchemaParticle xmlSchemaParticle;
438 typedef xmlSchemaParticle *xmlSchemaParticlePtr;
439 struct _xmlSchemaParticle {
440     xmlSchemaTypeType type;
441     xmlSchemaAnnotPtr annot;
442     xmlSchemaTreeItemPtr next;
443     xmlSchemaTreeItemPtr children;
444     int minOccurs;
445     int maxOccurs;
446     xmlNodePtr node;
447 };
448 
449 typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
450 typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
451 struct _xmlSchemaModelGroup {
452     xmlSchemaTypeType type;
453     xmlSchemaAnnotPtr annot;
454     xmlSchemaTreeItemPtr next;
455     xmlSchemaTreeItemPtr children;
456     xmlNodePtr node;
457 };
458 
459 static xmlSchemaParticlePtr
xmlSchemaAddParticle(void)460 xmlSchemaAddParticle(void)
461 {
462     xmlSchemaParticlePtr ret = NULL;
463 
464     ret = (xmlSchemaParticlePtr)
465 	xmlMalloc(sizeof(xmlSchemaParticle));
466     if (ret == NULL) {
467 	xmlSchemaTypeErrMemory();
468 	return (NULL);
469     }
470     memset(ret, 0, sizeof(xmlSchemaParticle));
471     ret->type = XML_SCHEMA_TYPE_PARTICLE;
472     ret->minOccurs = 1;
473     ret->maxOccurs = 1;
474     return (ret);
475 }
476 
477 static void
xmlSchemaFreeTypeEntry(void * type,const xmlChar * name ATTRIBUTE_UNUSED)478 xmlSchemaFreeTypeEntry(void *type, const xmlChar *name ATTRIBUTE_UNUSED) {
479     xmlSchemaFreeType((xmlSchemaTypePtr) type);
480 }
481 
482 /**
483  * xmlSchemaCleanupTypesInternal:
484  *
485  * Cleanup the default XML Schemas type library
486  */
487 static void
xmlSchemaCleanupTypesInternal(void)488 xmlSchemaCleanupTypesInternal(void) {
489     xmlSchemaParticlePtr particle;
490 
491     /*
492     * Free xs:anyType.
493     */
494     if (xmlSchemaTypeAnyTypeDef != NULL) {
495         /* Attribute wildcard. */
496         xmlSchemaFreeWildcard(xmlSchemaTypeAnyTypeDef->attributeWildcard);
497         /* Content type. */
498         particle = (xmlSchemaParticlePtr) xmlSchemaTypeAnyTypeDef->subtypes;
499         /* Wildcard. */
500         xmlSchemaFreeWildcard((xmlSchemaWildcardPtr)
501             particle->children->children->children);
502         xmlFree((xmlSchemaParticlePtr) particle->children->children);
503         /* Sequence model group. */
504         xmlFree((xmlSchemaModelGroupPtr) particle->children);
505         xmlFree((xmlSchemaParticlePtr) particle);
506         xmlSchemaTypeAnyTypeDef->subtypes = NULL;
507         xmlSchemaTypeAnyTypeDef = NULL;
508     }
509 
510     xmlHashFree(xmlSchemaTypesBank, xmlSchemaFreeTypeEntry);
511     xmlSchemaTypesBank = NULL;
512     /* Note that the xmlSchemaType*Def pointers aren't set to NULL. */
513 }
514 
515 /*
516  * xmlSchemaInitTypes:
517  *
518  * Initialize the default XML Schemas type library
519  *
520  * Returns 0 on success, -1 on error.
521  */
522 int
xmlSchemaInitTypes(void)523 xmlSchemaInitTypes(void)
524 {
525     if (xmlSchemaTypesInitialized != 0)
526         return (0);
527 
528 #if defined(NAN) && defined(INFINITY)
529     xmlSchemaNAN = NAN;
530     xmlSchemaPINF = INFINITY;
531     xmlSchemaNINF = -INFINITY;
532 #else
533     /* MSVC doesn't allow division by zero in constant expressions. */
534     double zero = 0.0;
535     xmlSchemaNAN = 0.0 / zero;
536     xmlSchemaPINF = 1.0 / zero;
537     xmlSchemaNINF = -xmlSchemaPINF;
538 #endif
539 
540     xmlSchemaTypesBank = xmlHashCreate(40);
541     if (xmlSchemaTypesBank == NULL) {
542 	xmlSchemaTypeErrMemory();
543         goto error;
544     }
545 
546     /*
547     * 3.4.7 Built-in Complex Type Definition
548     */
549     xmlSchemaTypeAnyTypeDef = xmlSchemaInitBasicType("anyType",
550                                                      XML_SCHEMAS_ANYTYPE,
551 						     NULL);
552     if (xmlSchemaTypeAnyTypeDef == NULL)
553         goto error;
554     xmlSchemaTypeAnyTypeDef->baseType = xmlSchemaTypeAnyTypeDef;
555     xmlSchemaTypeAnyTypeDef->contentType = XML_SCHEMA_CONTENT_MIXED;
556     /*
557     * Init the content type.
558     */
559     xmlSchemaTypeAnyTypeDef->contentType = XML_SCHEMA_CONTENT_MIXED;
560     {
561 	xmlSchemaParticlePtr particle;
562 	xmlSchemaModelGroupPtr sequence;
563 	xmlSchemaWildcardPtr wild;
564 	/* First particle. */
565 	particle = xmlSchemaAddParticle();
566 	if (particle == NULL)
567 	    goto error;
568 	xmlSchemaTypeAnyTypeDef->subtypes = (xmlSchemaTypePtr) particle;
569 	/* Sequence model group. */
570 	sequence = (xmlSchemaModelGroupPtr)
571 	    xmlMalloc(sizeof(xmlSchemaModelGroup));
572 	if (sequence == NULL) {
573 	    xmlSchemaTypeErrMemory();
574 	    goto error;
575 	}
576 	memset(sequence, 0, sizeof(xmlSchemaModelGroup));
577 	sequence->type = XML_SCHEMA_TYPE_SEQUENCE;
578 	particle->children = (xmlSchemaTreeItemPtr) sequence;
579 	/* Second particle. */
580 	particle = xmlSchemaAddParticle();
581 	if (particle == NULL)
582 	    goto error;
583 	particle->minOccurs = 0;
584 	particle->maxOccurs = UNBOUNDED;
585 	sequence->children = (xmlSchemaTreeItemPtr) particle;
586 	/* The wildcard */
587 	wild = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
588 	if (wild == NULL) {
589 	    xmlSchemaTypeErrMemory();
590 	    goto error;
591 	}
592 	memset(wild, 0, sizeof(xmlSchemaWildcard));
593 	wild->type = XML_SCHEMA_TYPE_ANY;
594 	wild->any = 1;
595 	wild->processContents = XML_SCHEMAS_ANY_LAX;
596 	particle->children = (xmlSchemaTreeItemPtr) wild;
597 	/*
598 	* Create the attribute wildcard.
599 	*/
600 	wild = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
601 	if (wild == NULL) {
602 	    xmlSchemaTypeErrMemory();
603 	    goto error;
604 	}
605 	memset(wild, 0, sizeof(xmlSchemaWildcard));
606 	wild->any = 1;
607 	wild->processContents = XML_SCHEMAS_ANY_LAX;
608 	xmlSchemaTypeAnyTypeDef->attributeWildcard = wild;
609     }
610     xmlSchemaTypeAnySimpleTypeDef = xmlSchemaInitBasicType("anySimpleType",
611                                                            XML_SCHEMAS_ANYSIMPLETYPE,
612 							   xmlSchemaTypeAnyTypeDef);
613     if (xmlSchemaTypeAnySimpleTypeDef == NULL)
614         goto error;
615     /*
616     * primitive datatypes
617     */
618     xmlSchemaTypeStringDef = xmlSchemaInitBasicType("string",
619                                                     XML_SCHEMAS_STRING,
620 						    xmlSchemaTypeAnySimpleTypeDef);
621     if (xmlSchemaTypeStringDef == NULL)
622         goto error;
623     xmlSchemaTypeDecimalDef = xmlSchemaInitBasicType("decimal",
624                                                      XML_SCHEMAS_DECIMAL,
625 						     xmlSchemaTypeAnySimpleTypeDef);
626     if (xmlSchemaTypeDecimalDef == NULL)
627         goto error;
628     xmlSchemaTypeDateDef = xmlSchemaInitBasicType("date",
629                                                   XML_SCHEMAS_DATE,
630 						  xmlSchemaTypeAnySimpleTypeDef);
631     if (xmlSchemaTypeDateDef == NULL)
632         goto error;
633     xmlSchemaTypeDatetimeDef = xmlSchemaInitBasicType("dateTime",
634                                                       XML_SCHEMAS_DATETIME,
635 						      xmlSchemaTypeAnySimpleTypeDef);
636     if (xmlSchemaTypeDatetimeDef == NULL)
637         goto error;
638     xmlSchemaTypeTimeDef = xmlSchemaInitBasicType("time",
639                                                   XML_SCHEMAS_TIME,
640 						  xmlSchemaTypeAnySimpleTypeDef);
641     if (xmlSchemaTypeTimeDef == NULL)
642         goto error;
643     xmlSchemaTypeGYearDef = xmlSchemaInitBasicType("gYear",
644                                                    XML_SCHEMAS_GYEAR,
645 						   xmlSchemaTypeAnySimpleTypeDef);
646     if (xmlSchemaTypeGYearDef == NULL)
647         goto error;
648     xmlSchemaTypeGYearMonthDef = xmlSchemaInitBasicType("gYearMonth",
649                                                         XML_SCHEMAS_GYEARMONTH,
650 							xmlSchemaTypeAnySimpleTypeDef);
651     if (xmlSchemaTypeGYearMonthDef == NULL)
652         goto error;
653     xmlSchemaTypeGMonthDef = xmlSchemaInitBasicType("gMonth",
654                                                     XML_SCHEMAS_GMONTH,
655 						    xmlSchemaTypeAnySimpleTypeDef);
656     if (xmlSchemaTypeGMonthDef == NULL)
657         goto error;
658     xmlSchemaTypeGMonthDayDef = xmlSchemaInitBasicType("gMonthDay",
659                                                        XML_SCHEMAS_GMONTHDAY,
660 						       xmlSchemaTypeAnySimpleTypeDef);
661     if (xmlSchemaTypeGMonthDayDef == NULL)
662         goto error;
663     xmlSchemaTypeGDayDef = xmlSchemaInitBasicType("gDay",
664                                                   XML_SCHEMAS_GDAY,
665 						  xmlSchemaTypeAnySimpleTypeDef);
666     if (xmlSchemaTypeGDayDef == NULL)
667         goto error;
668     xmlSchemaTypeDurationDef = xmlSchemaInitBasicType("duration",
669                                                       XML_SCHEMAS_DURATION,
670 						      xmlSchemaTypeAnySimpleTypeDef);
671     if (xmlSchemaTypeDurationDef == NULL)
672         goto error;
673     xmlSchemaTypeFloatDef = xmlSchemaInitBasicType("float",
674                                                    XML_SCHEMAS_FLOAT,
675 						   xmlSchemaTypeAnySimpleTypeDef);
676     if (xmlSchemaTypeFloatDef == NULL)
677         goto error;
678     xmlSchemaTypeDoubleDef = xmlSchemaInitBasicType("double",
679                                                     XML_SCHEMAS_DOUBLE,
680 						    xmlSchemaTypeAnySimpleTypeDef);
681     if (xmlSchemaTypeDoubleDef == NULL)
682         goto error;
683     xmlSchemaTypeBooleanDef = xmlSchemaInitBasicType("boolean",
684                                                      XML_SCHEMAS_BOOLEAN,
685 						     xmlSchemaTypeAnySimpleTypeDef);
686     if (xmlSchemaTypeBooleanDef == NULL)
687         goto error;
688     xmlSchemaTypeAnyURIDef = xmlSchemaInitBasicType("anyURI",
689                                                     XML_SCHEMAS_ANYURI,
690 						    xmlSchemaTypeAnySimpleTypeDef);
691     if (xmlSchemaTypeAnyURIDef == NULL)
692         goto error;
693     xmlSchemaTypeHexBinaryDef = xmlSchemaInitBasicType("hexBinary",
694                                                      XML_SCHEMAS_HEXBINARY,
695 						     xmlSchemaTypeAnySimpleTypeDef);
696     if (xmlSchemaTypeHexBinaryDef == NULL)
697         goto error;
698     xmlSchemaTypeBase64BinaryDef
699         = xmlSchemaInitBasicType("base64Binary", XML_SCHEMAS_BASE64BINARY,
700 	xmlSchemaTypeAnySimpleTypeDef);
701     if (xmlSchemaTypeBase64BinaryDef == NULL)
702         goto error;
703     xmlSchemaTypeNotationDef = xmlSchemaInitBasicType("NOTATION",
704                                                     XML_SCHEMAS_NOTATION,
705 						    xmlSchemaTypeAnySimpleTypeDef);
706     if (xmlSchemaTypeNotationDef == NULL)
707         goto error;
708     xmlSchemaTypeQNameDef = xmlSchemaInitBasicType("QName",
709                                                    XML_SCHEMAS_QNAME,
710 						   xmlSchemaTypeAnySimpleTypeDef);
711     if (xmlSchemaTypeQNameDef == NULL)
712         goto error;
713 
714     /*
715      * derived datatypes
716      */
717     xmlSchemaTypeIntegerDef = xmlSchemaInitBasicType("integer",
718                                                      XML_SCHEMAS_INTEGER,
719 						     xmlSchemaTypeDecimalDef);
720     if (xmlSchemaTypeIntegerDef == NULL)
721         goto error;
722     xmlSchemaTypeNonPositiveIntegerDef =
723         xmlSchemaInitBasicType("nonPositiveInteger",
724                                XML_SCHEMAS_NPINTEGER,
725 			       xmlSchemaTypeIntegerDef);
726     if (xmlSchemaTypeNonPositiveIntegerDef == NULL)
727         goto error;
728     xmlSchemaTypeNegativeIntegerDef =
729         xmlSchemaInitBasicType("negativeInteger", XML_SCHEMAS_NINTEGER,
730 	xmlSchemaTypeNonPositiveIntegerDef);
731     if (xmlSchemaTypeNegativeIntegerDef == NULL)
732         goto error;
733     xmlSchemaTypeLongDef =
734         xmlSchemaInitBasicType("long", XML_SCHEMAS_LONG,
735 	xmlSchemaTypeIntegerDef);
736     if (xmlSchemaTypeLongDef == NULL)
737         goto error;
738     xmlSchemaTypeIntDef = xmlSchemaInitBasicType("int", XML_SCHEMAS_INT,
739 	xmlSchemaTypeLongDef);
740     if (xmlSchemaTypeIntDef == NULL)
741         goto error;
742     xmlSchemaTypeShortDef = xmlSchemaInitBasicType("short",
743                                                    XML_SCHEMAS_SHORT,
744 						   xmlSchemaTypeIntDef);
745     if (xmlSchemaTypeShortDef == NULL)
746         goto error;
747     xmlSchemaTypeByteDef = xmlSchemaInitBasicType("byte",
748                                                   XML_SCHEMAS_BYTE,
749 						  xmlSchemaTypeShortDef);
750     if (xmlSchemaTypeByteDef == NULL)
751         goto error;
752     xmlSchemaTypeNonNegativeIntegerDef =
753         xmlSchemaInitBasicType("nonNegativeInteger",
754                                XML_SCHEMAS_NNINTEGER,
755 			       xmlSchemaTypeIntegerDef);
756     if (xmlSchemaTypeNonNegativeIntegerDef == NULL)
757         goto error;
758     xmlSchemaTypeUnsignedLongDef =
759         xmlSchemaInitBasicType("unsignedLong", XML_SCHEMAS_ULONG,
760 	xmlSchemaTypeNonNegativeIntegerDef);
761     if (xmlSchemaTypeUnsignedLongDef == NULL)
762         goto error;
763     xmlSchemaTypeUnsignedIntDef =
764         xmlSchemaInitBasicType("unsignedInt", XML_SCHEMAS_UINT,
765 	xmlSchemaTypeUnsignedLongDef);
766     if (xmlSchemaTypeUnsignedIntDef == NULL)
767         goto error;
768     xmlSchemaTypeUnsignedShortDef =
769         xmlSchemaInitBasicType("unsignedShort", XML_SCHEMAS_USHORT,
770 	xmlSchemaTypeUnsignedIntDef);
771     if (xmlSchemaTypeUnsignedShortDef == NULL)
772         goto error;
773     xmlSchemaTypeUnsignedByteDef =
774         xmlSchemaInitBasicType("unsignedByte", XML_SCHEMAS_UBYTE,
775 	xmlSchemaTypeUnsignedShortDef);
776     if (xmlSchemaTypeUnsignedByteDef == NULL)
777         goto error;
778     xmlSchemaTypePositiveIntegerDef =
779         xmlSchemaInitBasicType("positiveInteger", XML_SCHEMAS_PINTEGER,
780 	xmlSchemaTypeNonNegativeIntegerDef);
781     if (xmlSchemaTypePositiveIntegerDef == NULL)
782         goto error;
783     xmlSchemaTypeNormStringDef = xmlSchemaInitBasicType("normalizedString",
784                                                         XML_SCHEMAS_NORMSTRING,
785 							xmlSchemaTypeStringDef);
786     if (xmlSchemaTypeNormStringDef == NULL)
787         goto error;
788     xmlSchemaTypeTokenDef = xmlSchemaInitBasicType("token",
789                                                    XML_SCHEMAS_TOKEN,
790 						   xmlSchemaTypeNormStringDef);
791     if (xmlSchemaTypeTokenDef == NULL)
792         goto error;
793     xmlSchemaTypeLanguageDef = xmlSchemaInitBasicType("language",
794                                                       XML_SCHEMAS_LANGUAGE,
795 						      xmlSchemaTypeTokenDef);
796     if (xmlSchemaTypeLanguageDef == NULL)
797         goto error;
798     xmlSchemaTypeNameDef = xmlSchemaInitBasicType("Name",
799                                                   XML_SCHEMAS_NAME,
800 						  xmlSchemaTypeTokenDef);
801     if (xmlSchemaTypeNameDef == NULL)
802         goto error;
803     xmlSchemaTypeNmtokenDef = xmlSchemaInitBasicType("NMTOKEN",
804                                                      XML_SCHEMAS_NMTOKEN,
805 						     xmlSchemaTypeTokenDef);
806     if (xmlSchemaTypeNmtokenDef == NULL)
807         goto error;
808     xmlSchemaTypeNCNameDef = xmlSchemaInitBasicType("NCName",
809                                                     XML_SCHEMAS_NCNAME,
810 						    xmlSchemaTypeNameDef);
811     if (xmlSchemaTypeNCNameDef == NULL)
812         goto error;
813     xmlSchemaTypeIdDef = xmlSchemaInitBasicType("ID", XML_SCHEMAS_ID,
814 						    xmlSchemaTypeNCNameDef);
815     if (xmlSchemaTypeIdDef == NULL)
816         goto error;
817     xmlSchemaTypeIdrefDef = xmlSchemaInitBasicType("IDREF",
818                                                    XML_SCHEMAS_IDREF,
819 						   xmlSchemaTypeNCNameDef);
820     if (xmlSchemaTypeIdrefDef == NULL)
821         goto error;
822     xmlSchemaTypeEntityDef = xmlSchemaInitBasicType("ENTITY",
823                                                     XML_SCHEMAS_ENTITY,
824 						    xmlSchemaTypeNCNameDef);
825     if (xmlSchemaTypeEntityDef == NULL)
826         goto error;
827     /*
828     * Derived list types.
829     */
830     /* ENTITIES */
831     xmlSchemaTypeEntitiesDef = xmlSchemaInitBasicType("ENTITIES",
832                                                       XML_SCHEMAS_ENTITIES,
833 						      xmlSchemaTypeAnySimpleTypeDef);
834     if (xmlSchemaTypeEntitiesDef == NULL)
835         goto error;
836     xmlSchemaTypeEntitiesDef->subtypes = xmlSchemaTypeEntityDef;
837     /* IDREFS */
838     xmlSchemaTypeIdrefsDef = xmlSchemaInitBasicType("IDREFS",
839                                                     XML_SCHEMAS_IDREFS,
840 						    xmlSchemaTypeAnySimpleTypeDef);
841     if (xmlSchemaTypeIdrefsDef == NULL)
842         goto error;
843     xmlSchemaTypeIdrefsDef->subtypes = xmlSchemaTypeIdrefDef;
844 
845     /* NMTOKENS */
846     xmlSchemaTypeNmtokensDef = xmlSchemaInitBasicType("NMTOKENS",
847                                                       XML_SCHEMAS_NMTOKENS,
848 						      xmlSchemaTypeAnySimpleTypeDef);
849     if (xmlSchemaTypeNmtokensDef == NULL)
850         goto error;
851     xmlSchemaTypeNmtokensDef->subtypes = xmlSchemaTypeNmtokenDef;
852 
853     xmlSchemaTypesInitialized = 1;
854     return (0);
855 
856 error:
857     xmlSchemaCleanupTypesInternal();
858     return (-1);
859 }
860 
861 /**
862  * xmlSchemaCleanupTypes:
863  *
864  * DEPRECATED: This function will be made private. Call xmlCleanupParser
865  * to free global state but see the warnings there. xmlCleanupParser
866  * should be only called once at program exit. In most cases, you don't
867  * have to call cleanup functions at all.
868  *
869  * Cleanup the default XML Schemas type library
870  */
871 void
xmlSchemaCleanupTypes(void)872 xmlSchemaCleanupTypes(void) {
873     if (xmlSchemaTypesInitialized != 0) {
874         xmlSchemaCleanupTypesInternal();
875         xmlSchemaTypesInitialized = 0;
876     }
877 }
878 
879 /**
880  * xmlSchemaIsBuiltInTypeFacet:
881  * @type: the built-in type
882  * @facetType:  the facet type
883  *
884  * Evaluates if a specific facet can be
885  * used in conjunction with a type.
886  *
887  * Returns 1 if the facet can be used with the given built-in type,
888  * 0 otherwise and -1 in case the type is not a built-in type.
889  */
890 int
xmlSchemaIsBuiltInTypeFacet(xmlSchemaTypePtr type,int facetType)891 xmlSchemaIsBuiltInTypeFacet(xmlSchemaTypePtr type, int facetType)
892 {
893     if (type == NULL)
894 	return (-1);
895     if (type->type != XML_SCHEMA_TYPE_BASIC)
896 	return (-1);
897     switch (type->builtInType) {
898 	case XML_SCHEMAS_BOOLEAN:
899 	    if ((facetType == XML_SCHEMA_FACET_PATTERN) ||
900 		(facetType == XML_SCHEMA_FACET_WHITESPACE))
901 		return (1);
902 	    else
903 		return (0);
904 	case XML_SCHEMAS_STRING:
905 	case XML_SCHEMAS_NOTATION:
906 	case XML_SCHEMAS_QNAME:
907 	case XML_SCHEMAS_ANYURI:
908 	case XML_SCHEMAS_BASE64BINARY:
909 	case XML_SCHEMAS_HEXBINARY:
910 	    if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
911 		(facetType == XML_SCHEMA_FACET_MINLENGTH) ||
912 		(facetType == XML_SCHEMA_FACET_MAXLENGTH) ||
913 		(facetType == XML_SCHEMA_FACET_PATTERN) ||
914 		(facetType == XML_SCHEMA_FACET_ENUMERATION) ||
915 		(facetType == XML_SCHEMA_FACET_WHITESPACE))
916 		return (1);
917 	    else
918 		return (0);
919 	case XML_SCHEMAS_DECIMAL:
920 	    if ((facetType == XML_SCHEMA_FACET_TOTALDIGITS) ||
921 		(facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) ||
922 		(facetType == XML_SCHEMA_FACET_PATTERN) ||
923 		(facetType == XML_SCHEMA_FACET_WHITESPACE) ||
924 		(facetType == XML_SCHEMA_FACET_ENUMERATION) ||
925 		(facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) ||
926 		(facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) ||
927 		(facetType == XML_SCHEMA_FACET_MININCLUSIVE) ||
928 		(facetType == XML_SCHEMA_FACET_MINEXCLUSIVE))
929 		return (1);
930 	    else
931 		return (0);
932 	case XML_SCHEMAS_TIME:
933 	case XML_SCHEMAS_GDAY:
934 	case XML_SCHEMAS_GMONTH:
935 	case XML_SCHEMAS_GMONTHDAY:
936 	case XML_SCHEMAS_GYEAR:
937 	case XML_SCHEMAS_GYEARMONTH:
938 	case XML_SCHEMAS_DATE:
939 	case XML_SCHEMAS_DATETIME:
940 	case XML_SCHEMAS_DURATION:
941 	case XML_SCHEMAS_FLOAT:
942 	case XML_SCHEMAS_DOUBLE:
943 	    if ((facetType == XML_SCHEMA_FACET_PATTERN) ||
944 		(facetType == XML_SCHEMA_FACET_ENUMERATION) ||
945 		(facetType == XML_SCHEMA_FACET_WHITESPACE) ||
946 		(facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) ||
947 		(facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) ||
948 		(facetType == XML_SCHEMA_FACET_MININCLUSIVE) ||
949 		(facetType == XML_SCHEMA_FACET_MINEXCLUSIVE))
950 		return (1);
951 	    else
952 		return (0);
953 	default:
954 	    break;
955     }
956     return (0);
957 }
958 
959 /**
960  * xmlSchemaGetBuiltInType:
961  * @type:  the type of the built in type
962  *
963  * Gives you the type struct for a built-in
964  * type by its type id.
965  *
966  * Returns the type if found, NULL otherwise.
967  */
968 xmlSchemaTypePtr
xmlSchemaGetBuiltInType(xmlSchemaValType type)969 xmlSchemaGetBuiltInType(xmlSchemaValType type)
970 {
971     if ((xmlSchemaTypesInitialized == 0) &&
972 	(xmlSchemaInitTypes() < 0))
973         return (NULL);
974     switch (type) {
975 
976 	case XML_SCHEMAS_ANYSIMPLETYPE:
977 	    return (xmlSchemaTypeAnySimpleTypeDef);
978 	case XML_SCHEMAS_STRING:
979 	    return (xmlSchemaTypeStringDef);
980 	case XML_SCHEMAS_NORMSTRING:
981 	    return (xmlSchemaTypeNormStringDef);
982 	case XML_SCHEMAS_DECIMAL:
983 	    return (xmlSchemaTypeDecimalDef);
984 	case XML_SCHEMAS_TIME:
985 	    return (xmlSchemaTypeTimeDef);
986 	case XML_SCHEMAS_GDAY:
987 	    return (xmlSchemaTypeGDayDef);
988 	case XML_SCHEMAS_GMONTH:
989 	    return (xmlSchemaTypeGMonthDef);
990 	case XML_SCHEMAS_GMONTHDAY:
991 	    return (xmlSchemaTypeGMonthDayDef);
992 	case XML_SCHEMAS_GYEAR:
993 	    return (xmlSchemaTypeGYearDef);
994 	case XML_SCHEMAS_GYEARMONTH:
995 	    return (xmlSchemaTypeGYearMonthDef);
996 	case XML_SCHEMAS_DATE:
997 	    return (xmlSchemaTypeDateDef);
998 	case XML_SCHEMAS_DATETIME:
999 	    return (xmlSchemaTypeDatetimeDef);
1000 	case XML_SCHEMAS_DURATION:
1001 	    return (xmlSchemaTypeDurationDef);
1002 	case XML_SCHEMAS_FLOAT:
1003 	    return (xmlSchemaTypeFloatDef);
1004 	case XML_SCHEMAS_DOUBLE:
1005 	    return (xmlSchemaTypeDoubleDef);
1006 	case XML_SCHEMAS_BOOLEAN:
1007 	    return (xmlSchemaTypeBooleanDef);
1008 	case XML_SCHEMAS_TOKEN:
1009 	    return (xmlSchemaTypeTokenDef);
1010 	case XML_SCHEMAS_LANGUAGE:
1011 	    return (xmlSchemaTypeLanguageDef);
1012 	case XML_SCHEMAS_NMTOKEN:
1013 	    return (xmlSchemaTypeNmtokenDef);
1014 	case XML_SCHEMAS_NMTOKENS:
1015 	    return (xmlSchemaTypeNmtokensDef);
1016 	case XML_SCHEMAS_NAME:
1017 	    return (xmlSchemaTypeNameDef);
1018 	case XML_SCHEMAS_QNAME:
1019 	    return (xmlSchemaTypeQNameDef);
1020 	case XML_SCHEMAS_NCNAME:
1021 	    return (xmlSchemaTypeNCNameDef);
1022 	case XML_SCHEMAS_ID:
1023 	    return (xmlSchemaTypeIdDef);
1024 	case XML_SCHEMAS_IDREF:
1025 	    return (xmlSchemaTypeIdrefDef);
1026 	case XML_SCHEMAS_IDREFS:
1027 	    return (xmlSchemaTypeIdrefsDef);
1028 	case XML_SCHEMAS_ENTITY:
1029 	    return (xmlSchemaTypeEntityDef);
1030 	case XML_SCHEMAS_ENTITIES:
1031 	    return (xmlSchemaTypeEntitiesDef);
1032 	case XML_SCHEMAS_NOTATION:
1033 	    return (xmlSchemaTypeNotationDef);
1034 	case XML_SCHEMAS_ANYURI:
1035 	    return (xmlSchemaTypeAnyURIDef);
1036 	case XML_SCHEMAS_INTEGER:
1037 	    return (xmlSchemaTypeIntegerDef);
1038 	case XML_SCHEMAS_NPINTEGER:
1039 	    return (xmlSchemaTypeNonPositiveIntegerDef);
1040 	case XML_SCHEMAS_NINTEGER:
1041 	    return (xmlSchemaTypeNegativeIntegerDef);
1042 	case XML_SCHEMAS_NNINTEGER:
1043 	    return (xmlSchemaTypeNonNegativeIntegerDef);
1044 	case XML_SCHEMAS_PINTEGER:
1045 	    return (xmlSchemaTypePositiveIntegerDef);
1046 	case XML_SCHEMAS_INT:
1047 	    return (xmlSchemaTypeIntDef);
1048 	case XML_SCHEMAS_UINT:
1049 	    return (xmlSchemaTypeUnsignedIntDef);
1050 	case XML_SCHEMAS_LONG:
1051 	    return (xmlSchemaTypeLongDef);
1052 	case XML_SCHEMAS_ULONG:
1053 	    return (xmlSchemaTypeUnsignedLongDef);
1054 	case XML_SCHEMAS_SHORT:
1055 	    return (xmlSchemaTypeShortDef);
1056 	case XML_SCHEMAS_USHORT:
1057 	    return (xmlSchemaTypeUnsignedShortDef);
1058 	case XML_SCHEMAS_BYTE:
1059 	    return (xmlSchemaTypeByteDef);
1060 	case XML_SCHEMAS_UBYTE:
1061 	    return (xmlSchemaTypeUnsignedByteDef);
1062 	case XML_SCHEMAS_HEXBINARY:
1063 	    return (xmlSchemaTypeHexBinaryDef);
1064 	case XML_SCHEMAS_BASE64BINARY:
1065 	    return (xmlSchemaTypeBase64BinaryDef);
1066 	case XML_SCHEMAS_ANYTYPE:
1067 	    return (xmlSchemaTypeAnyTypeDef);
1068 	default:
1069 	    return (NULL);
1070     }
1071 }
1072 
1073 /**
1074  * xmlSchemaValueAppend:
1075  * @prev: the value
1076  * @cur: the value to be appended
1077  *
1078  * Appends a next sibling to a list of computed values.
1079  *
1080  * Returns 0 if succeeded and -1 on API errors.
1081  */
1082 int
xmlSchemaValueAppend(xmlSchemaValPtr prev,xmlSchemaValPtr cur)1083 xmlSchemaValueAppend(xmlSchemaValPtr prev, xmlSchemaValPtr cur) {
1084 
1085     if ((prev == NULL) || (cur == NULL))
1086 	return (-1);
1087     prev->next = cur;
1088     return (0);
1089 }
1090 
1091 /**
1092  * xmlSchemaValueGetNext:
1093  * @cur: the value
1094  *
1095  * Accessor for the next sibling of a list of computed values.
1096  *
1097  * Returns the next value or NULL if there was none, or on
1098  *         API errors.
1099  */
1100 xmlSchemaValPtr
xmlSchemaValueGetNext(xmlSchemaValPtr cur)1101 xmlSchemaValueGetNext(xmlSchemaValPtr cur) {
1102 
1103     if (cur == NULL)
1104 	return (NULL);
1105     return (cur->next);
1106 }
1107 
1108 /**
1109  * xmlSchemaValueGetAsString:
1110  * @val: the value
1111  *
1112  * Accessor for the string value of a computed value.
1113  *
1114  * Returns the string value or NULL if there was none, or on
1115  *         API errors.
1116  */
1117 const xmlChar *
xmlSchemaValueGetAsString(xmlSchemaValPtr val)1118 xmlSchemaValueGetAsString(xmlSchemaValPtr val)
1119 {
1120     if (val == NULL)
1121 	return (NULL);
1122     switch (val->type) {
1123 	case XML_SCHEMAS_STRING:
1124 	case XML_SCHEMAS_NORMSTRING:
1125 	case XML_SCHEMAS_ANYSIMPLETYPE:
1126 	case XML_SCHEMAS_TOKEN:
1127         case XML_SCHEMAS_LANGUAGE:
1128         case XML_SCHEMAS_NMTOKEN:
1129         case XML_SCHEMAS_NAME:
1130         case XML_SCHEMAS_NCNAME:
1131         case XML_SCHEMAS_ID:
1132         case XML_SCHEMAS_IDREF:
1133         case XML_SCHEMAS_ENTITY:
1134         case XML_SCHEMAS_ANYURI:
1135 	    return (BAD_CAST val->value.str);
1136 	default:
1137 	    break;
1138     }
1139     return (NULL);
1140 }
1141 
1142 /**
1143  * xmlSchemaValueGetAsBoolean:
1144  * @val: the value
1145  *
1146  * Accessor for the boolean value of a computed value.
1147  *
1148  * Returns 1 if true and 0 if false, or in case of an error. Hmm.
1149  */
1150 int
xmlSchemaValueGetAsBoolean(xmlSchemaValPtr val)1151 xmlSchemaValueGetAsBoolean(xmlSchemaValPtr val)
1152 {
1153     if ((val == NULL) || (val->type != XML_SCHEMAS_BOOLEAN))
1154 	return (0);
1155     return (val->value.b);
1156 }
1157 
1158 /**
1159  * xmlSchemaNewStringValue:
1160  * @type:  the value type
1161  * @value:  the value
1162  *
1163  * Allocate a new simple type value. The type can be
1164  * of XML_SCHEMAS_STRING.
1165  * WARNING: This one is intended to be expanded for other
1166  * string based types. We need this for anySimpleType as well.
1167  * The given value is consumed and freed with the struct.
1168  *
1169  * Returns a pointer to the new value or NULL in case of error
1170  */
1171 xmlSchemaValPtr
xmlSchemaNewStringValue(xmlSchemaValType type,const xmlChar * value)1172 xmlSchemaNewStringValue(xmlSchemaValType type,
1173 			const xmlChar *value)
1174 {
1175     xmlSchemaValPtr val;
1176 
1177     if (type != XML_SCHEMAS_STRING)
1178 	return(NULL);
1179     val = (xmlSchemaValPtr) xmlMalloc(sizeof(xmlSchemaVal));
1180     if (val == NULL) {
1181 	return(NULL);
1182     }
1183     memset(val, 0, sizeof(xmlSchemaVal));
1184     val->type = type;
1185     val->value.str = (xmlChar *) value;
1186     return(val);
1187 }
1188 
1189 /**
1190  * xmlSchemaNewNOTATIONValue:
1191  * @name:  the notation name
1192  * @ns: the notation namespace name or NULL
1193  *
1194  * Allocate a new NOTATION value.
1195  * The given values are consumed and freed with the struct.
1196  *
1197  * Returns a pointer to the new value or NULL in case of error
1198  */
1199 xmlSchemaValPtr
xmlSchemaNewNOTATIONValue(const xmlChar * name,const xmlChar * ns)1200 xmlSchemaNewNOTATIONValue(const xmlChar *name,
1201 			  const xmlChar *ns)
1202 {
1203     xmlSchemaValPtr val;
1204 
1205     val = xmlSchemaNewValue(XML_SCHEMAS_NOTATION);
1206     if (val == NULL)
1207 	return (NULL);
1208 
1209     val->value.qname.name = (xmlChar *)name;
1210     if (ns != NULL)
1211 	val->value.qname.uri = (xmlChar *)ns;
1212     return(val);
1213 }
1214 
1215 /**
1216  * xmlSchemaNewQNameValue:
1217  * @namespaceName: the namespace name
1218  * @localName: the local name
1219  *
1220  * Allocate a new QName value.
1221  * The given values are consumed and freed with the struct.
1222  *
1223  * Returns a pointer to the new value or NULL in case of an error.
1224  */
1225 xmlSchemaValPtr
xmlSchemaNewQNameValue(const xmlChar * namespaceName,const xmlChar * localName)1226 xmlSchemaNewQNameValue(const xmlChar *namespaceName,
1227 		       const xmlChar *localName)
1228 {
1229     xmlSchemaValPtr val;
1230 
1231     val = xmlSchemaNewValue(XML_SCHEMAS_QNAME);
1232     if (val == NULL)
1233 	return (NULL);
1234 
1235     val->value.qname.name = (xmlChar *) localName;
1236     val->value.qname.uri = (xmlChar *) namespaceName;
1237     return(val);
1238 }
1239 
1240 /**
1241  * xmlSchemaFreeValue:
1242  * @value:  the value to free
1243  *
1244  * Cleanup the default XML Schemas type library
1245  */
1246 void
xmlSchemaFreeValue(xmlSchemaValPtr value)1247 xmlSchemaFreeValue(xmlSchemaValPtr value) {
1248     xmlSchemaValPtr prev;
1249 
1250     while (value != NULL) {
1251 	switch (value->type) {
1252 	    case XML_SCHEMAS_STRING:
1253 	    case XML_SCHEMAS_NORMSTRING:
1254 	    case XML_SCHEMAS_TOKEN:
1255 	    case XML_SCHEMAS_LANGUAGE:
1256 	    case XML_SCHEMAS_NMTOKEN:
1257 	    case XML_SCHEMAS_NMTOKENS:
1258 	    case XML_SCHEMAS_NAME:
1259 	    case XML_SCHEMAS_NCNAME:
1260 	    case XML_SCHEMAS_ID:
1261 	    case XML_SCHEMAS_IDREF:
1262 	    case XML_SCHEMAS_IDREFS:
1263 	    case XML_SCHEMAS_ENTITY:
1264 	    case XML_SCHEMAS_ENTITIES:
1265 	    case XML_SCHEMAS_ANYURI:
1266 	    case XML_SCHEMAS_ANYSIMPLETYPE:
1267 		if (value->value.str != NULL)
1268 		    xmlFree(value->value.str);
1269 		break;
1270 	    case XML_SCHEMAS_NOTATION:
1271 	    case XML_SCHEMAS_QNAME:
1272 		if (value->value.qname.uri != NULL)
1273 		    xmlFree(value->value.qname.uri);
1274 		if (value->value.qname.name != NULL)
1275 		    xmlFree(value->value.qname.name);
1276 		break;
1277 	    case XML_SCHEMAS_HEXBINARY:
1278 		if (value->value.hex.str != NULL)
1279 		    xmlFree(value->value.hex.str);
1280 		break;
1281 	    case XML_SCHEMAS_BASE64BINARY:
1282 		if (value->value.base64.str != NULL)
1283 		    xmlFree(value->value.base64.str);
1284 		break;
1285 	    case XML_SCHEMAS_DECIMAL:
1286 	    case XML_SCHEMAS_INTEGER:
1287 	    case XML_SCHEMAS_NNINTEGER:
1288 	    case XML_SCHEMAS_PINTEGER:
1289 	    case XML_SCHEMAS_NPINTEGER:
1290 	    case XML_SCHEMAS_NINTEGER:
1291 	    case XML_SCHEMAS_INT:
1292 	    case XML_SCHEMAS_UINT:
1293 	    case XML_SCHEMAS_LONG:
1294 	    case XML_SCHEMAS_ULONG:
1295 	    case XML_SCHEMAS_SHORT:
1296 	    case XML_SCHEMAS_USHORT:
1297 	    case XML_SCHEMAS_BYTE:
1298 	    case XML_SCHEMAS_UBYTE:
1299 		if (value->value.decimal.str != NULL)
1300 		    xmlFree(value->value.decimal.str);
1301 		break;
1302 	    default:
1303 		break;
1304 	}
1305 	prev = value;
1306 	value = value->next;
1307 	xmlFree(prev);
1308     }
1309 }
1310 
1311 /**
1312  * xmlSchemaGetPredefinedType:
1313  * @name: the type name
1314  * @ns:  the URI of the namespace usually "http://www.w3.org/2001/XMLSchema"
1315  *
1316  * Lookup a type in the default XML Schemas type library
1317  *
1318  * Returns the type if found, NULL otherwise
1319  */
1320 xmlSchemaTypePtr
xmlSchemaGetPredefinedType(const xmlChar * name,const xmlChar * ns)1321 xmlSchemaGetPredefinedType(const xmlChar *name, const xmlChar *ns) {
1322     if ((xmlSchemaTypesInitialized == 0) &&
1323 	(xmlSchemaInitTypes() < 0))
1324         return (NULL);
1325     if (name == NULL)
1326 	return(NULL);
1327     return((xmlSchemaTypePtr) xmlHashLookup2(xmlSchemaTypesBank, name, ns));
1328 }
1329 
1330 /**
1331  * xmlSchemaGetBuiltInListSimpleTypeItemType:
1332  * @type: the built-in simple type.
1333  *
1334  * Lookup function
1335  *
1336  * Returns the item type of @type as defined by the built-in datatype
1337  * hierarchy of XML Schema Part 2: Datatypes, or NULL in case of an error.
1338  */
1339 xmlSchemaTypePtr
xmlSchemaGetBuiltInListSimpleTypeItemType(xmlSchemaTypePtr type)1340 xmlSchemaGetBuiltInListSimpleTypeItemType(xmlSchemaTypePtr type)
1341 {
1342     if ((type == NULL) || (type->type != XML_SCHEMA_TYPE_BASIC))
1343 	return (NULL);
1344     switch (type->builtInType) {
1345 	case XML_SCHEMAS_NMTOKENS:
1346 	    return (xmlSchemaTypeNmtokenDef );
1347 	case XML_SCHEMAS_IDREFS:
1348 	    return (xmlSchemaTypeIdrefDef);
1349 	case XML_SCHEMAS_ENTITIES:
1350 	    return (xmlSchemaTypeEntityDef);
1351 	default:
1352 	    return (NULL);
1353     }
1354 }
1355 
1356 /****************************************************************
1357  *								*
1358  *		Convenience macros and functions		*
1359  *								*
1360  ****************************************************************/
1361 
1362 #define IS_TZO_CHAR(c)						\
1363 	((c == 0) || (c == 'Z') || (c == '+') || (c == '-'))
1364 
1365 #define VALID_YEAR(yr)          (yr != 0)
1366 #define VALID_MONTH(mon)        ((mon >= 1) && (mon <= 12))
1367 /* VALID_DAY should only be used when month is unknown */
1368 #define VALID_DAY(day)          ((day >= 1) && (day <= 31))
1369 #define VALID_HOUR(hr)          ((hr >= 0) && (hr <= 23))
1370 #define VALID_MIN(min)          ((min >= 0) && (min <= 59))
1371 #define VALID_SEC(sec)          ((sec >= 0) && (sec < 60))
1372 #define VALID_TZO(tzo)          ((tzo >= -840) && (tzo <= 840))
1373 #define IS_LEAP(y)						\
1374 	(((y % 4 == 0) && (y % 100 != 0)) || (y % 400 == 0))
1375 
1376 static const unsigned int daysInMonth[12] =
1377 	{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
1378 static const unsigned int daysInMonthLeap[12] =
1379 	{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
1380 
1381 #define MAX_DAYINMONTH(yr,mon)                                  \
1382         (IS_LEAP(yr) ? daysInMonthLeap[mon - 1] : daysInMonth[mon - 1])
1383 
1384 #define VALID_MDAY(dt)						\
1385 	(IS_LEAP(dt->year) ?				        \
1386 	    (dt->day <= daysInMonthLeap[dt->mon - 1]) :	        \
1387 	    (dt->day <= daysInMonth[dt->mon - 1]))
1388 
1389 #define VALID_DATE(dt)						\
1390 	(VALID_YEAR(dt->year) && VALID_MONTH(dt->mon) && VALID_MDAY(dt))
1391 
1392 #define VALID_END_OF_DAY(dt)					\
1393 	((dt)->hour == 24 && (dt)->min == 0 && (dt)->sec == 0)
1394 
1395 #define VALID_TIME(dt)						\
1396 	(((VALID_HOUR((int)dt->hour) && VALID_MIN((int)dt->min) &&	\
1397 	  VALID_SEC(dt->sec)) || VALID_END_OF_DAY(dt)) &&	\
1398 	 VALID_TZO(dt->tzo))
1399 
1400 #define VALID_DATETIME(dt)					\
1401 	(VALID_DATE(dt) && VALID_TIME(dt))
1402 
1403 #define SECS_PER_MIN            60
1404 #define MINS_PER_HOUR           60
1405 #define HOURS_PER_DAY           24
1406 #define SECS_PER_HOUR           (MINS_PER_HOUR * SECS_PER_MIN)
1407 #define SECS_PER_DAY            (HOURS_PER_DAY * SECS_PER_HOUR)
1408 #define MINS_PER_DAY            (HOURS_PER_DAY * MINS_PER_HOUR)
1409 
1410 static const long dayInYearByMonth[12] =
1411 	{ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
1412 static const long dayInLeapYearByMonth[12] =
1413 	{ 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 };
1414 
1415 #define DAY_IN_YEAR(day, month, year)				\
1416         ((IS_LEAP(year) ?					\
1417                 dayInLeapYearByMonth[month - 1] :		\
1418                 dayInYearByMonth[month - 1]) + day)
1419 
1420 /**
1421  * _xmlSchemaParseGYear:
1422  * @dt:  pointer to a date structure
1423  * @str: pointer to the string to analyze
1424  *
1425  * Parses a xs:gYear without time zone and fills in the appropriate
1426  * field of the @dt structure. @str is updated to point just after the
1427  * xs:gYear. It is supposed that @dt->year is big enough to contain
1428  * the year.
1429  *
1430  * Returns 0 or the error code
1431  */
1432 static int
_xmlSchemaParseGYear(xmlSchemaValDatePtr dt,const xmlChar ** str)1433 _xmlSchemaParseGYear (xmlSchemaValDatePtr dt, const xmlChar **str) {
1434     const xmlChar *cur = *str, *firstChar;
1435     int isneg = 0, digcnt = 0;
1436 
1437     if (((*cur < '0') || (*cur > '9')) &&
1438 	(*cur != '-') && (*cur != '+'))
1439 	return -1;
1440 
1441     if (*cur == '-') {
1442 	isneg = 1;
1443 	cur++;
1444     }
1445 
1446     firstChar = cur;
1447 
1448     while ((*cur >= '0') && (*cur <= '9')) {
1449         int digit = *cur - '0';
1450 
1451         if (dt->year > LONG_MAX / 10)
1452             return 2;
1453 	dt->year *= 10;
1454         if (dt->year > LONG_MAX - digit)
1455             return 2;
1456         dt->year += digit;
1457 	cur++;
1458 	digcnt++;
1459     }
1460 
1461     /* year must be at least 4 digits (CCYY); over 4
1462      * digits cannot have a leading zero. */
1463     if ((digcnt < 4) || ((digcnt > 4) && (*firstChar == '0')))
1464 	return 1;
1465 
1466     if (isneg)
1467 	dt->year = - dt->year;
1468 
1469     if (!VALID_YEAR(dt->year))
1470 	return 2;
1471 
1472     *str = cur;
1473     return 0;
1474 }
1475 
1476 /**
1477  * PARSE_2_DIGITS:
1478  * @num:  the integer to fill in
1479  * @cur:  an #xmlChar *
1480  * @invalid: an integer
1481  *
1482  * Parses a 2-digits integer and updates @num with the value. @cur is
1483  * updated to point just after the integer.
1484  * In case of error, @invalid is set to %TRUE, values of @num and
1485  * @cur are undefined.
1486  */
1487 #define PARSE_2_DIGITS(num, cur, invalid)			\
1488 	if ((cur[0] < '0') || (cur[0] > '9') ||			\
1489 	    (cur[1] < '0') || (cur[1] > '9'))			\
1490 	    invalid = 1;					\
1491 	else							\
1492 	    num = (cur[0] - '0') * 10 + (cur[1] - '0');		\
1493 	cur += 2;
1494 
1495 /**
1496  * PARSE_FLOAT:
1497  * @num:  the double to fill in
1498  * @cur:  an #xmlChar *
1499  * @invalid: an integer
1500  *
1501  * Parses a float and updates @num with the value. @cur is
1502  * updated to point just after the float. The float must have a
1503  * 2-digits integer part and may or may not have a decimal part.
1504  * In case of error, @invalid is set to %TRUE, values of @num and
1505  * @cur are undefined.
1506  */
1507 #define PARSE_FLOAT(num, cur, invalid)				\
1508 	PARSE_2_DIGITS(num, cur, invalid);			\
1509 	if (!invalid && (*cur == '.')) {			\
1510 	    double mult = 1;				        \
1511 	    cur++;						\
1512 	    if ((*cur < '0') || (*cur > '9'))			\
1513 		invalid = 1;					\
1514 	    while ((*cur >= '0') && (*cur <= '9')) {		\
1515 		mult /= 10;					\
1516 		num += (*cur - '0') * mult;			\
1517 		cur++;						\
1518 	    }							\
1519 	}
1520 
1521 /**
1522  * _xmlSchemaParseGMonth:
1523  * @dt:  pointer to a date structure
1524  * @str: pointer to the string to analyze
1525  *
1526  * Parses a xs:gMonth without time zone and fills in the appropriate
1527  * field of the @dt structure. @str is updated to point just after the
1528  * xs:gMonth.
1529  *
1530  * Returns 0 or the error code
1531  */
1532 static int
_xmlSchemaParseGMonth(xmlSchemaValDatePtr dt,const xmlChar ** str)1533 _xmlSchemaParseGMonth (xmlSchemaValDatePtr dt, const xmlChar **str) {
1534     const xmlChar *cur = *str;
1535     int ret = 0;
1536     unsigned int value = 0;
1537 
1538     PARSE_2_DIGITS(value, cur, ret);
1539     if (ret != 0)
1540 	return ret;
1541 
1542     if (!VALID_MONTH(value))
1543 	return 2;
1544 
1545     dt->mon = value;
1546 
1547     *str = cur;
1548     return 0;
1549 }
1550 
1551 /**
1552  * _xmlSchemaParseGDay:
1553  * @dt:  pointer to a date structure
1554  * @str: pointer to the string to analyze
1555  *
1556  * Parses a xs:gDay without time zone and fills in the appropriate
1557  * field of the @dt structure. @str is updated to point just after the
1558  * xs:gDay.
1559  *
1560  * Returns 0 or the error code
1561  */
1562 static int
_xmlSchemaParseGDay(xmlSchemaValDatePtr dt,const xmlChar ** str)1563 _xmlSchemaParseGDay (xmlSchemaValDatePtr dt, const xmlChar **str) {
1564     const xmlChar *cur = *str;
1565     int ret = 0;
1566     unsigned int value = 0;
1567 
1568     PARSE_2_DIGITS(value, cur, ret);
1569     if (ret != 0)
1570 	return ret;
1571 
1572     if (!VALID_DAY(value))
1573 	return 2;
1574 
1575     dt->day = value;
1576     *str = cur;
1577     return 0;
1578 }
1579 
1580 /**
1581  * _xmlSchemaParseTime:
1582  * @dt:  pointer to a date structure
1583  * @str: pointer to the string to analyze
1584  *
1585  * Parses a xs:time without time zone and fills in the appropriate
1586  * fields of the @dt structure. @str is updated to point just after the
1587  * xs:time.
1588  * In case of error, values of @dt fields are undefined.
1589  *
1590  * Returns 0 or the error code
1591  */
1592 static int
_xmlSchemaParseTime(xmlSchemaValDatePtr dt,const xmlChar ** str)1593 _xmlSchemaParseTime (xmlSchemaValDatePtr dt, const xmlChar **str) {
1594     const xmlChar *cur = *str;
1595     int ret = 0;
1596     int value = 0;
1597 
1598     PARSE_2_DIGITS(value, cur, ret);
1599     if (ret != 0)
1600 	return ret;
1601     if (*cur != ':')
1602 	return 1;
1603     if (!VALID_HOUR(value) && value != 24 /* Allow end-of-day hour */)
1604 	return 2;
1605     cur++;
1606 
1607     /* the ':' insures this string is xs:time */
1608     dt->hour = value;
1609 
1610     PARSE_2_DIGITS(value, cur, ret);
1611     if (ret != 0)
1612 	return ret;
1613     if (!VALID_MIN(value))
1614 	return 2;
1615     dt->min = value;
1616 
1617     if (*cur != ':')
1618 	return 1;
1619     cur++;
1620 
1621     PARSE_FLOAT(dt->sec, cur, ret);
1622     if (ret != 0)
1623 	return ret;
1624 
1625     if (!VALID_TIME(dt))
1626 	return 2;
1627 
1628     *str = cur;
1629     return 0;
1630 }
1631 
1632 /**
1633  * _xmlSchemaParseTimeZone:
1634  * @dt:  pointer to a date structure
1635  * @str: pointer to the string to analyze
1636  *
1637  * Parses a time zone without time zone and fills in the appropriate
1638  * field of the @dt structure. @str is updated to point just after the
1639  * time zone.
1640  *
1641  * Returns 0 or the error code
1642  */
1643 static int
_xmlSchemaParseTimeZone(xmlSchemaValDatePtr dt,const xmlChar ** str)1644 _xmlSchemaParseTimeZone (xmlSchemaValDatePtr dt, const xmlChar **str) {
1645     const xmlChar *cur;
1646     int ret = 0;
1647 
1648     if (str == NULL)
1649 	return -1;
1650     cur = *str;
1651 
1652     switch (*cur) {
1653     case 0:
1654 	dt->tz_flag = 0;
1655 	dt->tzo = 0;
1656 	break;
1657 
1658     case 'Z':
1659 	dt->tz_flag = 1;
1660 	dt->tzo = 0;
1661 	cur++;
1662 	break;
1663 
1664     case '+':
1665     case '-': {
1666 	int isneg = 0, tmp = 0;
1667 	isneg = (*cur == '-');
1668 
1669 	cur++;
1670 
1671 	PARSE_2_DIGITS(tmp, cur, ret);
1672 	if (ret != 0)
1673 	    return ret;
1674 	if (!VALID_HOUR(tmp))
1675 	    return 2;
1676 
1677 	if (*cur != ':')
1678 	    return 1;
1679 	cur++;
1680 
1681 	dt->tzo = tmp * 60;
1682 
1683 	PARSE_2_DIGITS(tmp, cur, ret);
1684 	if (ret != 0)
1685 	    return ret;
1686 	if (!VALID_MIN(tmp))
1687 	    return 2;
1688 
1689 	dt->tzo += tmp;
1690 	if (isneg)
1691 	    dt->tzo = - dt->tzo;
1692 
1693 	if (!VALID_TZO(dt->tzo))
1694 	    return 2;
1695 
1696 	dt->tz_flag = 1;
1697 	break;
1698       }
1699     default:
1700 	return 1;
1701     }
1702 
1703     *str = cur;
1704     return 0;
1705 }
1706 
1707 /**
1708  * _xmlSchemaBase64Decode:
1709  * @ch: a character
1710  *
1711  * Converts a base64 encoded character to its base 64 value.
1712  *
1713  * Returns 0-63 (value), 64 (pad), or -1 (not recognized)
1714  */
1715 static int
_xmlSchemaBase64Decode(const xmlChar ch)1716 _xmlSchemaBase64Decode (const xmlChar ch) {
1717     if (('A' <= ch) && (ch <= 'Z')) return ch - 'A';
1718     if (('a' <= ch) && (ch <= 'z')) return ch - 'a' + 26;
1719     if (('0' <= ch) && (ch <= '9')) return ch - '0' + 52;
1720     if ('+' == ch) return 62;
1721     if ('/' == ch) return 63;
1722     if ('=' == ch) return 64;
1723     return -1;
1724 }
1725 
1726 /****************************************************************
1727  *								*
1728  *	XML Schema Dates/Times Datatypes Handling		*
1729  *								*
1730  ****************************************************************/
1731 
1732 /**
1733  * PARSE_DIGITS:
1734  * @num:  the integer to fill in
1735  * @cur:  an #xmlChar *
1736  * @num_type: an integer flag
1737  *
1738  * Parses a digits integer and updates @num with the value. @cur is
1739  * updated to point just after the integer.
1740  * In case of error, @num_type is set to -1, values of @num and
1741  * @cur are undefined.
1742  */
1743 #define PARSE_DIGITS(num, cur, num_type)	                \
1744 	if ((*cur < '0') || (*cur > '9'))			\
1745 	    num_type = -1;					\
1746         else                                                    \
1747 	    while ((*cur >= '0') && (*cur <= '9')) {		\
1748 	        num = num * 10 + (*cur - '0');		        \
1749 	        cur++;                                          \
1750             }
1751 
1752 /**
1753  * PARSE_NUM:
1754  * @num:  the double to fill in
1755  * @cur:  an #xmlChar *
1756  * @num_type: an integer flag
1757  *
1758  * Parses a float or integer and updates @num with the value. @cur is
1759  * updated to point just after the number. If the number is a float,
1760  * then it must have an integer part and a decimal part; @num_type will
1761  * be set to 1. If there is no decimal part, @num_type is set to zero.
1762  * In case of error, @num_type is set to -1, values of @num and
1763  * @cur are undefined.
1764  */
1765 #define PARSE_NUM(num, cur, num_type)				\
1766         num = 0;                                                \
1767 	PARSE_DIGITS(num, cur, num_type);	                \
1768 	if (!num_type && (*cur == '.')) {			\
1769 	    double mult = 1;				        \
1770 	    cur++;						\
1771 	    if ((*cur < '0') || (*cur > '9'))			\
1772 		num_type = -1;					\
1773             else                                                \
1774                 num_type = 1;                                   \
1775 	    while ((*cur >= '0') && (*cur <= '9')) {		\
1776 		mult /= 10;					\
1777 		num += (*cur - '0') * mult;			\
1778 		cur++;						\
1779 	    }							\
1780 	}
1781 
1782 /**
1783  * xmlSchemaValidateDates:
1784  * @type: the expected type or XML_SCHEMAS_UNKNOWN
1785  * @dateTime:  string to analyze
1786  * @val:  the return computed value
1787  *
1788  * Check that @dateTime conforms to the lexical space of one of the date types.
1789  * if true a value is computed and returned in @val.
1790  *
1791  * Returns 0 if this validates, a positive error code number otherwise
1792  *         and -1 in case of internal or API error.
1793  */
1794 static int
xmlSchemaValidateDates(xmlSchemaValType type,const xmlChar * dateTime,xmlSchemaValPtr * val,int collapse)1795 xmlSchemaValidateDates (xmlSchemaValType type,
1796 	                const xmlChar *dateTime, xmlSchemaValPtr *val,
1797 			int collapse) {
1798     xmlSchemaValPtr dt;
1799     int ret;
1800     const xmlChar *cur = dateTime;
1801 
1802 #define RETURN_TYPE_IF_VALID(t)					\
1803     if (IS_TZO_CHAR(*cur)) {					\
1804 	ret = _xmlSchemaParseTimeZone(&(dt->value.date), &cur);	\
1805 	if (ret == 0) {						\
1806 	    if (*cur != 0)					\
1807 		goto error;					\
1808 	    dt->type = t;					\
1809 	    goto done;						\
1810 	}							\
1811     }
1812 
1813     if (dateTime == NULL)
1814 	return -1;
1815 
1816     if (collapse)
1817 	while IS_WSP_BLANK_CH(*cur) cur++;
1818 
1819     if ((*cur != '-') && (*cur < '0') && (*cur > '9'))
1820 	return 1;
1821 
1822     dt = xmlSchemaNewValue(XML_SCHEMAS_UNKNOWN);
1823     if (dt == NULL)
1824 	return -1;
1825 
1826     if ((cur[0] == '-') && (cur[1] == '-')) {
1827 	/*
1828 	 * It's an incomplete date (xs:gMonthDay, xs:gMonth or
1829 	 * xs:gDay)
1830 	 */
1831 	cur += 2;
1832 
1833 	/* is it an xs:gDay? */
1834 	if (*cur == '-') {
1835 	    if (type == XML_SCHEMAS_GMONTH)
1836 		goto error;
1837 	  ++cur;
1838 	    ret = _xmlSchemaParseGDay(&(dt->value.date), &cur);
1839 	    if (ret != 0)
1840 		goto error;
1841 
1842 	    RETURN_TYPE_IF_VALID(XML_SCHEMAS_GDAY);
1843 
1844 	    goto error;
1845 	}
1846 
1847 	/*
1848 	 * it should be an xs:gMonthDay or xs:gMonth
1849 	 */
1850 	ret = _xmlSchemaParseGMonth(&(dt->value.date), &cur);
1851 	if (ret != 0)
1852 	    goto error;
1853 
1854         /*
1855          * a '-' char could indicate this type is xs:gMonthDay or
1856          * a negative time zone offset. Check for xs:gMonthDay first.
1857          * Also the first three char's of a negative tzo (-MM:SS) can
1858          * appear to be a valid day; so even if the day portion
1859          * of the xs:gMonthDay verifies, we must insure it was not
1860          * a tzo.
1861          */
1862         if (*cur == '-') {
1863             const xmlChar *rewnd = cur;
1864             cur++;
1865 
1866 	    ret = _xmlSchemaParseGDay(&(dt->value.date), &cur);
1867             if ((ret == 0) && ((*cur == 0) || (*cur != ':'))) {
1868 
1869                 /*
1870                  * we can use the VALID_MDAY macro to validate the month
1871                  * and day because the leap year test will flag year zero
1872                  * as a leap year (even though zero is an invalid year).
1873 		 * FUTURE TODO: Zero will become valid in XML Schema 1.1
1874 		 * probably.
1875                  */
1876                 if (VALID_MDAY((&(dt->value.date)))) {
1877 
1878 	            RETURN_TYPE_IF_VALID(XML_SCHEMAS_GMONTHDAY);
1879 
1880                     goto error;
1881                 }
1882             }
1883 
1884             /*
1885              * not xs:gMonthDay so rewind and check if just xs:gMonth
1886              * with an optional time zone.
1887              */
1888             cur = rewnd;
1889         }
1890 
1891 	RETURN_TYPE_IF_VALID(XML_SCHEMAS_GMONTH);
1892 
1893 	goto error;
1894     }
1895 
1896     /*
1897      * It's a right-truncated date or an xs:time.
1898      * Try to parse an xs:time then fallback on right-truncated dates.
1899      */
1900     if ((*cur >= '0') && (*cur <= '9')) {
1901 	ret = _xmlSchemaParseTime(&(dt->value.date), &cur);
1902 	if (ret == 0) {
1903 	    /* it's an xs:time */
1904 	    RETURN_TYPE_IF_VALID(XML_SCHEMAS_TIME);
1905 	}
1906     }
1907 
1908     /* fallback on date parsing */
1909     cur = dateTime;
1910 
1911     ret = _xmlSchemaParseGYear(&(dt->value.date), &cur);
1912     if (ret != 0)
1913 	goto error;
1914 
1915     /* is it an xs:gYear? */
1916     RETURN_TYPE_IF_VALID(XML_SCHEMAS_GYEAR);
1917 
1918     if (*cur != '-')
1919 	goto error;
1920     cur++;
1921 
1922     ret = _xmlSchemaParseGMonth(&(dt->value.date), &cur);
1923     if (ret != 0)
1924 	goto error;
1925 
1926     /* is it an xs:gYearMonth? */
1927     RETURN_TYPE_IF_VALID(XML_SCHEMAS_GYEARMONTH);
1928 
1929     if (*cur != '-')
1930 	goto error;
1931     cur++;
1932 
1933     ret = _xmlSchemaParseGDay(&(dt->value.date), &cur);
1934     if ((ret != 0) || !VALID_DATE((&(dt->value.date))))
1935 	goto error;
1936 
1937     /* is it an xs:date? */
1938     RETURN_TYPE_IF_VALID(XML_SCHEMAS_DATE);
1939 
1940     if (*cur != 'T')
1941 	goto error;
1942     cur++;
1943 
1944     /* it should be an xs:dateTime */
1945     ret = _xmlSchemaParseTime(&(dt->value.date), &cur);
1946     if (ret != 0)
1947 	goto error;
1948 
1949     ret = _xmlSchemaParseTimeZone(&(dt->value.date), &cur);
1950     if (collapse)
1951 	while IS_WSP_BLANK_CH(*cur) cur++;
1952     if ((ret != 0) || (*cur != 0) || (!(VALID_DATETIME((&(dt->value.date))))))
1953 	goto error;
1954 
1955 
1956     dt->type = XML_SCHEMAS_DATETIME;
1957 
1958 done:
1959 #if 1
1960     if ((type != XML_SCHEMAS_UNKNOWN) && (type != dt->type))
1961         goto error;
1962 #else
1963     /*
1964      * insure the parsed type is equal to or less significant (right
1965      * truncated) than the desired type.
1966      */
1967     if ((type != XML_SCHEMAS_UNKNOWN) && (type != dt->type)) {
1968 
1969         /* time only matches time */
1970         if ((type == XML_SCHEMAS_TIME) && (dt->type == XML_SCHEMAS_TIME))
1971             goto error;
1972 
1973         if ((type == XML_SCHEMAS_DATETIME) &&
1974             ((dt->type != XML_SCHEMAS_DATE) ||
1975              (dt->type != XML_SCHEMAS_GYEARMONTH) ||
1976              (dt->type != XML_SCHEMAS_GYEAR)))
1977             goto error;
1978 
1979         if ((type == XML_SCHEMAS_DATE) &&
1980             ((dt->type != XML_SCHEMAS_GYEAR) ||
1981              (dt->type != XML_SCHEMAS_GYEARMONTH)))
1982             goto error;
1983 
1984         if ((type == XML_SCHEMAS_GYEARMONTH) && (dt->type != XML_SCHEMAS_GYEAR))
1985             goto error;
1986 
1987         if ((type == XML_SCHEMAS_GMONTHDAY) && (dt->type != XML_SCHEMAS_GMONTH))
1988             goto error;
1989     }
1990 #endif
1991 
1992     if (val != NULL)
1993         *val = dt;
1994     else
1995 	xmlSchemaFreeValue(dt);
1996 
1997     return 0;
1998 
1999 error:
2000     if (dt != NULL)
2001 	xmlSchemaFreeValue(dt);
2002     return 1;
2003 }
2004 
2005 /**
2006  * xmlSchemaValidateDuration:
2007  * @type: the predefined type
2008  * @duration:  string to analyze
2009  * @val:  the return computed value
2010  *
2011  * Check that @duration conforms to the lexical space of the duration type.
2012  * if true a value is computed and returned in @val.
2013  *
2014  * Returns 0 if this validates, a positive error code number otherwise
2015  *         and -1 in case of internal or API error.
2016  */
2017 static int
xmlSchemaValidateDuration(xmlSchemaTypePtr type ATTRIBUTE_UNUSED,const xmlChar * duration,xmlSchemaValPtr * val,int collapse)2018 xmlSchemaValidateDuration (xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2019 	                   const xmlChar *duration, xmlSchemaValPtr *val,
2020 			   int collapse) {
2021     const xmlChar  *cur = duration;
2022     xmlSchemaValPtr dur;
2023     int isneg = 0;
2024     unsigned int seq = 0;
2025     long days, secs = 0;
2026     double sec_frac = 0.0;
2027 
2028     if (duration == NULL)
2029 	return -1;
2030 
2031     if (collapse)
2032 	while IS_WSP_BLANK_CH(*cur) cur++;
2033 
2034     if (*cur == '-') {
2035         isneg = 1;
2036         cur++;
2037     }
2038 
2039     /* duration must start with 'P' (after sign) */
2040     if (*cur++ != 'P')
2041 	return 1;
2042 
2043     if (*cur == 0)
2044 	return 1;
2045 
2046     dur = xmlSchemaNewValue(XML_SCHEMAS_DURATION);
2047     if (dur == NULL)
2048 	return -1;
2049 
2050     while (*cur != 0) {
2051         long           num = 0;
2052         size_t         has_digits = 0;
2053         int            has_frac = 0;
2054         const xmlChar  desig[] = {'Y', 'M', 'D', 'H', 'M', 'S'};
2055 
2056         /* input string should be empty or invalid date/time item */
2057         if (seq >= sizeof(desig))
2058             goto error;
2059 
2060         /* T designator must be present for time items */
2061         if (*cur == 'T') {
2062             if (seq > 3)
2063                 goto error;
2064             cur++;
2065             seq = 3;
2066         } else if (seq == 3)
2067             goto error;
2068 
2069         /* Parse integral part. */
2070         while (*cur >= '0' && *cur <= '9') {
2071             long digit = *cur - '0';
2072 
2073             if (num > LONG_MAX / 10)
2074                 goto error;
2075             num *= 10;
2076             if (num > LONG_MAX - digit)
2077                 goto error;
2078             num += digit;
2079 
2080             has_digits = 1;
2081             cur++;
2082         }
2083 
2084         if (*cur == '.') {
2085             /* Parse fractional part. */
2086             double mult = 1.0;
2087             cur++;
2088             has_frac = 1;
2089             while (*cur >= '0' && *cur <= '9') {
2090                 mult /= 10.0;
2091                 sec_frac += (*cur - '0') * mult;
2092                 has_digits = 1;
2093                 cur++;
2094             }
2095         }
2096 
2097         while (*cur != desig[seq]) {
2098             seq++;
2099             /* No T designator or invalid char. */
2100             if (seq == 3 || seq == sizeof(desig))
2101                 goto error;
2102         }
2103 	cur++;
2104 
2105         if (!has_digits || (has_frac && (seq != 5)))
2106             goto error;
2107 
2108         switch (seq) {
2109             case 0:
2110                 /* Year */
2111                 if (num > LONG_MAX / 12)
2112                     goto error;
2113                 dur->value.dur.mon = num * 12;
2114                 break;
2115             case 1:
2116                 /* Month */
2117                 if (dur->value.dur.mon > LONG_MAX - num)
2118                     goto error;
2119                 dur->value.dur.mon += num;
2120                 break;
2121             case 2:
2122                 /* Day */
2123                 dur->value.dur.day = num;
2124                 break;
2125             case 3:
2126                 /* Hour */
2127                 days = num / HOURS_PER_DAY;
2128                 if (dur->value.dur.day > LONG_MAX - days)
2129                     goto error;
2130                 dur->value.dur.day += days;
2131                 secs = (num % HOURS_PER_DAY) * SECS_PER_HOUR;
2132                 break;
2133             case 4:
2134                 /* Minute */
2135                 days = num / MINS_PER_DAY;
2136                 if (dur->value.dur.day > LONG_MAX - days)
2137                     goto error;
2138                 dur->value.dur.day += days;
2139                 secs += (num % MINS_PER_DAY) * SECS_PER_MIN;
2140                 break;
2141             case 5:
2142                 /* Second */
2143                 days = num / SECS_PER_DAY;
2144                 if (dur->value.dur.day > LONG_MAX - days)
2145                     goto error;
2146                 dur->value.dur.day += days;
2147                 secs += num % SECS_PER_DAY;
2148                 break;
2149         }
2150 
2151         seq++;
2152     }
2153 
2154     days = secs / SECS_PER_DAY;
2155     if (dur->value.dur.day > LONG_MAX - days)
2156         goto error;
2157     dur->value.dur.day += days;
2158     dur->value.dur.sec = (secs % SECS_PER_DAY) + sec_frac;
2159 
2160     if (isneg) {
2161         dur->value.dur.mon = -dur->value.dur.mon;
2162         dur->value.dur.day = -dur->value.dur.day;
2163         dur->value.dur.sec = -dur->value.dur.sec;
2164     }
2165 
2166     if (val != NULL)
2167         *val = dur;
2168     else
2169 	xmlSchemaFreeValue(dur);
2170 
2171     return 0;
2172 
2173 error:
2174     if (dur != NULL)
2175 	xmlSchemaFreeValue(dur);
2176     return 1;
2177 }
2178 
2179 /**
2180  * xmlSchemaStrip:
2181  * @value: a value
2182  *
2183  * Removes the leading and ending spaces of a string
2184  *
2185  * Returns the new string or NULL if no change was required.
2186  */
2187 static xmlChar *
xmlSchemaStrip(const xmlChar * value)2188 xmlSchemaStrip(const xmlChar *value) {
2189     const xmlChar *start = value, *end, *f;
2190 
2191     if (value == NULL) return(NULL);
2192     while ((*start != 0) && (IS_BLANK_CH(*start))) start++;
2193     end = start;
2194     while (*end != 0) end++;
2195     f = end;
2196     end--;
2197     while ((end > start) && (IS_BLANK_CH(*end))) end--;
2198     end++;
2199     if ((start == value) && (f == end)) return(NULL);
2200     return(xmlStrndup(start, end - start));
2201 }
2202 
2203 /**
2204  * xmlSchemaWhiteSpaceReplace:
2205  * @value: a value
2206  *
2207  * Replaces 0xd, 0x9 and 0xa with a space.
2208  *
2209  * Returns the new string or NULL if no change was required.
2210  */
2211 xmlChar *
xmlSchemaWhiteSpaceReplace(const xmlChar * value)2212 xmlSchemaWhiteSpaceReplace(const xmlChar *value) {
2213     const xmlChar *cur = value;
2214     xmlChar *ret = NULL, *mcur;
2215 
2216     if (value == NULL)
2217 	return(NULL);
2218 
2219     while ((*cur != 0) &&
2220 	(((*cur) != 0xd) && ((*cur) != 0x9) && ((*cur) != 0xa))) {
2221 	cur++;
2222     }
2223     if (*cur == 0)
2224 	return (NULL);
2225     ret = xmlStrdup(value);
2226     /* TODO FIXME: I guess gcc will bark at this. */
2227     mcur = (xmlChar *)  (ret + (cur - value));
2228     do {
2229 	if ( ((*mcur) == 0xd) || ((*mcur) == 0x9) || ((*mcur) == 0xa) )
2230 	    *mcur = ' ';
2231 	mcur++;
2232     } while (*mcur != 0);
2233     return(ret);
2234 }
2235 
2236 /**
2237  * xmlSchemaCollapseString:
2238  * @value: a value
2239  *
2240  * Removes and normalize white spaces in the string
2241  *
2242  * Returns the new string or NULL if no change was required.
2243  */
2244 xmlChar *
xmlSchemaCollapseString(const xmlChar * value)2245 xmlSchemaCollapseString(const xmlChar *value) {
2246     const xmlChar *start = value, *end, *f;
2247     xmlChar *g;
2248     int col = 0;
2249 
2250     if (value == NULL) return(NULL);
2251     while ((*start != 0) && (IS_BLANK_CH(*start))) start++;
2252     end = start;
2253     while (*end != 0) {
2254 	if ((*end == ' ') && (IS_BLANK_CH(end[1]))) {
2255 	    col = end - start;
2256 	    break;
2257 	} else if ((*end == 0xa) || (*end == 0x9) || (*end == 0xd)) {
2258 	    col = end - start;
2259 	    break;
2260 	}
2261 	end++;
2262     }
2263     if (col == 0) {
2264 	f = end;
2265 	end--;
2266 	while ((end > start) && (IS_BLANK_CH(*end))) end--;
2267 	end++;
2268 	if ((start == value) && (f == end)) return(NULL);
2269 	return(xmlStrndup(start, end - start));
2270     }
2271     start = xmlStrdup(start);
2272     if (start == NULL) return(NULL);
2273     g = (xmlChar *) (start + col);
2274     end = g;
2275     while (*end != 0) {
2276 	if (IS_BLANK_CH(*end)) {
2277 	    end++;
2278 	    while (IS_BLANK_CH(*end)) end++;
2279 	    if (*end != 0)
2280 		*g++ = ' ';
2281 	} else
2282 	    *g++ = *end++;
2283     }
2284     *g = 0;
2285     return((xmlChar *) start);
2286 }
2287 
2288 /**
2289  * xmlSchemaValAtomicListNode:
2290  * @type: the predefined atomic type for a token in the list
2291  * @value: the list value to check
2292  * @ret:  the return computed value
2293  * @node:  the node containing the value
2294  *
2295  * Check that a value conforms to the lexical space of the predefined
2296  * list type. if true a value is computed and returned in @ret.
2297  *
2298  * Returns the number of items if this validates, a negative error code
2299  *         number otherwise
2300  */
2301 static int
xmlSchemaValAtomicListNode(xmlSchemaTypePtr type,const xmlChar * value,xmlSchemaValPtr * ret,xmlNodePtr node)2302 xmlSchemaValAtomicListNode(xmlSchemaTypePtr type, const xmlChar *value,
2303 	                   xmlSchemaValPtr *ret, xmlNodePtr node) {
2304     xmlChar *val, *cur, *endval;
2305     int nb_values = 0;
2306     int tmp = 0;
2307 
2308     if (value == NULL) {
2309 	return(-1);
2310     }
2311     val = xmlStrdup(value);
2312     if (val == NULL) {
2313 	return(-1);
2314     }
2315     if (ret != NULL) {
2316         *ret = NULL;
2317     }
2318     cur = val;
2319     /*
2320      * Split the list
2321      */
2322     while (IS_BLANK_CH(*cur)) *cur++ = 0;
2323     while (*cur != 0) {
2324 	if (IS_BLANK_CH(*cur)) {
2325 	    *cur = 0;
2326 	    cur++;
2327 	    while (IS_BLANK_CH(*cur)) *cur++ = 0;
2328 	} else {
2329 	    nb_values++;
2330 	    cur++;
2331 	    while ((*cur != 0) && (!IS_BLANK_CH(*cur))) cur++;
2332 	}
2333     }
2334     if (nb_values == 0) {
2335 	xmlFree(val);
2336 	return(nb_values);
2337     }
2338     endval = cur;
2339     cur = val;
2340     while ((*cur == 0) && (cur != endval)) cur++;
2341     while (cur != endval) {
2342 	tmp = xmlSchemaValPredefTypeNode(type, cur, NULL, node);
2343 	if (tmp != 0)
2344 	    break;
2345 	while (*cur != 0) cur++;
2346 	while ((*cur == 0) && (cur != endval)) cur++;
2347     }
2348     /* TODO what return value ? c.f. bug #158628
2349     if (ret != NULL) {
2350 	TODO
2351     } */
2352     xmlFree(val);
2353     if (tmp == 0)
2354 	return(nb_values);
2355     return(-1);
2356 }
2357 
2358 /**
2359  * xmlSchemaParseUInt:
2360  * @str: pointer to the string R/W
2361  * @val: pointer to the resulting decimal
2362  *
2363  * Parse an unsigned long into a decimal.
2364  *
2365  * Returns the number of significant digits in the number or
2366  * -1 if overflow of the capacity and -2 if it's not a number.
2367  */
xmlSchemaParseUInt(const xmlChar ** str,xmlSchemaValDecimalPtr val)2368 static int xmlSchemaParseUInt(const xmlChar **str, xmlSchemaValDecimalPtr val) {
2369 	const xmlChar *tmp, *cur = *str;
2370 	int ret = 0, i = 0;
2371 
2372     if (!((*cur >= '0') && (*cur <= '9')))
2373         return(-2);
2374 
2375     while (*cur == '0') {        /* ignore leading zeroes */
2376         cur++;
2377     }
2378     /* back up in case there is nothing after the leading zeroes */
2379     if(!(*cur >= '0' && *cur <= '9'))
2380     {
2381         --cur;
2382     }
2383     tmp = cur;
2384     while ((*tmp != 0) && (*tmp >= '0') && (*tmp <= '9')) {
2385         i++;tmp++;ret++;
2386     }
2387     if (val->integralPlaces + val->fractionalPlaces < (unsigned)i + 1)
2388     {
2389         if (val->str != NULL)
2390         {
2391             xmlFree(val->str);
2392         }
2393         /*  sign, dot, fractional 0 and NULL terminator */
2394         val->str = xmlMalloc(i + 4);
2395     }
2396     val->fractionalPlaces = 1;
2397     val->integralPlaces = i;
2398     snprintf((char *)val->str, i + 4, "+%.*s.0", i, cur);
2399 
2400     *str = tmp;
2401     return(ret);
2402 }
2403 
2404 /*
2405  * xmlSchemaCheckLanguageType
2406  * @value: the value to check
2407  *
2408  * Check that a value conforms to the lexical space of the language datatype.
2409  * Must conform to [a-zA-Z]{1,8}(-[a-zA-Z0-9]{1,8})*
2410  *
2411  * Returns 1 if this validates, 0 otherwise.
2412  */
2413 static int
xmlSchemaCheckLanguageType(const xmlChar * value)2414 xmlSchemaCheckLanguageType(const xmlChar* value) {
2415     int first = 1, len = 0;
2416     const xmlChar* cur = value;
2417 
2418     if (value == NULL)
2419         return (0);
2420 
2421     while (cur[0] != 0) {
2422         if (!( ((cur[0] >= 'a') && (cur[0] <= 'z')) || ((cur[0] >= 'A') && (cur[0] <= 'Z'))
2423             || (cur[0] == '-')
2424             || ((first == 0) && (xmlIsDigit_ch(cur[0]))) ))
2425             return (0);
2426         if (cur[0] == '-') {
2427             if ((len < 1) || (len > 8))
2428                 return (0);
2429             len = 0;
2430             first = 0;
2431         }
2432         else
2433             len++;
2434         cur++;
2435     }
2436     if ((len < 1) || (len > 8))
2437         return (0);
2438 
2439     return (1);
2440 }
2441 
2442 /**
2443  * xmlSchemaValAtomicType:
2444  * @type: the predefined type
2445  * @value: the value to check
2446  * @val:  the return computed value
2447  * @node:  the node containing the value
2448  * flags:  flags to control the validation
2449  *
2450  * Check that a value conforms to the lexical space of the atomic type.
2451  * if true a value is computed and returned in @val.
2452  * This checks the value space for list types as well (IDREFS, NMTOKENS).
2453  *
2454  * Returns 0 if this validates, a positive error code number otherwise
2455  *         and -1 in case of internal or API error.
2456  */
2457 static int
xmlSchemaValAtomicType(xmlSchemaTypePtr type,const xmlChar * value,xmlSchemaValPtr * val,xmlNodePtr node,int flags,xmlSchemaWhitespaceValueType ws,int normOnTheFly,int applyNorm,int createStringValue)2458 xmlSchemaValAtomicType(xmlSchemaTypePtr type, const xmlChar * value,
2459                        xmlSchemaValPtr * val, xmlNodePtr node, int flags,
2460 		       xmlSchemaWhitespaceValueType ws,
2461 		       int normOnTheFly, int applyNorm, int createStringValue)
2462 {
2463     xmlSchemaValPtr v;
2464     xmlChar *norm = NULL;
2465     int ret = 0;
2466 
2467     if ((xmlSchemaTypesInitialized == 0) &&
2468 	(xmlSchemaInitTypes() < 0))
2469         return (-1);
2470     if (type == NULL)
2471         return (-1);
2472 
2473     /*
2474      * validating a non existent text node is similar to validating
2475      * an empty one.
2476      */
2477     if (value == NULL)
2478         value = BAD_CAST "";
2479 
2480     if (val != NULL)
2481         *val = NULL;
2482     if ((flags == 0) && (value != NULL)) {
2483 
2484         if ((type->builtInType != XML_SCHEMAS_STRING) &&
2485 	  (type->builtInType != XML_SCHEMAS_ANYTYPE) &&
2486 	  (type->builtInType != XML_SCHEMAS_ANYSIMPLETYPE)) {
2487 	    if (type->builtInType == XML_SCHEMAS_NORMSTRING)
2488 		norm = xmlSchemaWhiteSpaceReplace(value);
2489             else
2490 		norm = xmlSchemaCollapseString(value);
2491             if (norm != NULL)
2492                 value = norm;
2493         }
2494     }
2495 
2496     switch (type->builtInType) {
2497         case XML_SCHEMAS_UNKNOWN:
2498             goto error;
2499 	case XML_SCHEMAS_ANYTYPE:
2500 	case XML_SCHEMAS_ANYSIMPLETYPE:
2501 	    if ((createStringValue) && (val != NULL)) {
2502 		v = xmlSchemaNewValue(XML_SCHEMAS_ANYSIMPLETYPE);
2503 		if (v != NULL) {
2504 		    v->value.str = xmlStrdup(value);
2505 		    *val = v;
2506 		} else {
2507 		    goto error;
2508 		}
2509 	    }
2510 	    goto return0;
2511         case XML_SCHEMAS_STRING:
2512 	    if (! normOnTheFly) {
2513 		const xmlChar *cur = value;
2514 
2515 		if (ws == XML_SCHEMA_WHITESPACE_REPLACE) {
2516 		    while (*cur != 0) {
2517 			if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) {
2518 			    goto return1;
2519 			} else {
2520 			    cur++;
2521 			}
2522 		    }
2523 		} else if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE) {
2524 		    while (*cur != 0) {
2525 			if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) {
2526 			    goto return1;
2527 			} else if IS_WSP_SPACE_CH(*cur) {
2528 			    cur++;
2529 			    if IS_WSP_SPACE_CH(*cur)
2530 				goto return1;
2531 			} else {
2532 			    cur++;
2533 			}
2534 		    }
2535 		}
2536 	    }
2537 	    if (createStringValue && (val != NULL)) {
2538 		if (applyNorm) {
2539 		    if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
2540 			norm = xmlSchemaCollapseString(value);
2541 		    else if (ws == XML_SCHEMA_WHITESPACE_REPLACE)
2542 			norm = xmlSchemaWhiteSpaceReplace(value);
2543 		    if (norm != NULL)
2544 			value = norm;
2545 		}
2546 		v = xmlSchemaNewValue(XML_SCHEMAS_STRING);
2547 		if (v != NULL) {
2548 		    v->value.str = xmlStrdup(value);
2549 		    *val = v;
2550 		} else {
2551 		    goto error;
2552 		}
2553 	    }
2554             goto return0;
2555         case XML_SCHEMAS_NORMSTRING:{
2556 		if (normOnTheFly) {
2557 		    if (applyNorm) {
2558 			if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
2559 			    norm = xmlSchemaCollapseString(value);
2560 			else
2561 			    norm = xmlSchemaWhiteSpaceReplace(value);
2562 			if (norm != NULL)
2563 			    value = norm;
2564 		    }
2565 		} else {
2566 		    const xmlChar *cur = value;
2567 		    while (*cur != 0) {
2568 			if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) {
2569 			    goto return1;
2570 			} else {
2571 			    cur++;
2572 			}
2573 		    }
2574 		}
2575                 if (val != NULL) {
2576                     v = xmlSchemaNewValue(XML_SCHEMAS_NORMSTRING);
2577                     if (v != NULL) {
2578                         v->value.str = xmlStrdup(value);
2579                         *val = v;
2580                     } else {
2581                         goto error;
2582                     }
2583                 }
2584                 goto return0;
2585             }
2586         case XML_SCHEMAS_DECIMAL:{
2587                 const xmlChar *cur = value;
2588                 const xmlChar *numStart, *numEnd;
2589                 xmlSchemaValDecimal decimal;
2590                 xmlChar sign;
2591 
2592                 memset(&decimal, 0, sizeof(decimal));
2593 
2594                 if ((cur == NULL) || (*cur == 0))
2595                     goto return1;
2596 
2597 		/*
2598 		* xs:decimal has a whitespace-facet value of 'collapse'.
2599 		*/
2600 		if (normOnTheFly)
2601 		    while IS_WSP_BLANK_CH(*cur) cur++;
2602 
2603 		/*
2604 		* First we handle an optional sign.
2605 		*/
2606                 sign = '+';
2607                 if (*cur == '-') {
2608                     sign = '-';
2609                     cur++;
2610 		} else if (*cur == '+')
2611                     cur++;
2612 		/*
2613 		* Disallow: "", "-", "- "
2614 		*/
2615 		if (*cur == 0)
2616 		    goto return1;
2617 
2618 		/*
2619 		* Skip leading zeroes.
2620 		*/
2621 		while (*cur == '0') {
2622 		    cur++;
2623 		}
2624 
2625                 numStart = cur;
2626 
2627                 while ((*cur >= '0') && (*cur <= '9')) {
2628                     ++cur;
2629                     ++decimal.integralPlaces;
2630                 }
2631                 if (*cur == '.') {
2632                     ++cur;
2633                 }
2634                 while ((*cur >= '0') && (*cur <= '9')) {
2635                     ++cur;
2636                     ++decimal.fractionalPlaces;
2637                 }
2638 
2639                 /*  disallow "." */
2640                 if (
2641                     decimal.fractionalPlaces == 0 && decimal.integralPlaces == 0
2642                     && (numStart == value || numStart[-1] != '0')
2643                 ) {
2644                     goto return1;
2645                 }
2646 
2647                 numEnd = cur;
2648 
2649                 /*  find if there are trailing FRACTIONAL zeroes, and deal with them if necessary */
2650                 while (numEnd > numStart && decimal.fractionalPlaces && numEnd[-1] == '0') {
2651                     --numEnd;
2652                     --decimal.fractionalPlaces;
2653                 }
2654 
2655 		if (normOnTheFly)
2656 		    while IS_WSP_BLANK_CH(*cur) cur++;
2657 		if (*cur != 0)
2658 		    goto return1; /* error if any extraneous chars */
2659                 if (val != NULL) {
2660                     v = xmlSchemaNewValue(XML_SCHEMAS_DECIMAL);
2661                     if (v != NULL) {
2662                         /*  create a standardized representation */
2663                         size_t bufsize;
2664                         const char *integralStart = (const char *)numStart;
2665                         const char *fractionalStart = (const char *)numEnd - decimal.fractionalPlaces;
2666                         if (decimal.integralPlaces == 0)
2667                         {
2668                             integralStart = "0";
2669                             decimal.integralPlaces = 1;
2670                         }
2671                         if (decimal.fractionalPlaces == 0)
2672                         {
2673                             fractionalStart = "0";
2674                             decimal.fractionalPlaces = 1;
2675                         }
2676                         /*  3 = sign, dot, NULL terminator */
2677                         bufsize = decimal.integralPlaces + decimal.fractionalPlaces + 3;
2678                         decimal.str = xmlMalloc(bufsize);
2679                         if (!decimal.str)
2680                         {
2681                             goto error;
2682                         }
2683                         snprintf((char *)decimal.str, bufsize, "%c%.*s.%.*s", sign, decimal.integralPlaces, integralStart,
2684                                 decimal.fractionalPlaces, fractionalStart);
2685                         v->value.decimal = decimal;
2686                         *val = v;
2687                     }
2688                     else
2689                     {
2690                         goto error;
2691                     }
2692                 }
2693                 goto return0;
2694             }
2695         case XML_SCHEMAS_TIME:
2696         case XML_SCHEMAS_GDAY:
2697         case XML_SCHEMAS_GMONTH:
2698         case XML_SCHEMAS_GMONTHDAY:
2699         case XML_SCHEMAS_GYEAR:
2700         case XML_SCHEMAS_GYEARMONTH:
2701         case XML_SCHEMAS_DATE:
2702         case XML_SCHEMAS_DATETIME:
2703             ret = xmlSchemaValidateDates(type->builtInType, value, val,
2704 		normOnTheFly);
2705             break;
2706         case XML_SCHEMAS_DURATION:
2707             ret = xmlSchemaValidateDuration(type, value, val,
2708 		normOnTheFly);
2709             break;
2710         case XML_SCHEMAS_FLOAT:
2711         case XML_SCHEMAS_DOUBLE: {
2712                 const xmlChar *cur = value;
2713                 int neg = 0;
2714                 int digits_before = 0;
2715                 int digits_after = 0;
2716 
2717 		if (normOnTheFly)
2718 		    while IS_WSP_BLANK_CH(*cur) cur++;
2719 
2720                 if ((cur[0] == 'N') && (cur[1] == 'a') && (cur[2] == 'N')) {
2721                     cur += 3;
2722                     if (*cur != 0)
2723                         goto return1;
2724                     if (val != NULL) {
2725                         if (type == xmlSchemaTypeFloatDef) {
2726                             v = xmlSchemaNewValue(XML_SCHEMAS_FLOAT);
2727                             if (v != NULL) {
2728                                 v->value.f = (float) xmlSchemaNAN;
2729                             } else {
2730                                 xmlSchemaFreeValue(v);
2731                                 goto error;
2732                             }
2733                         } else {
2734                             v = xmlSchemaNewValue(XML_SCHEMAS_DOUBLE);
2735                             if (v != NULL) {
2736                                 v->value.d = xmlSchemaNAN;
2737                             } else {
2738                                 xmlSchemaFreeValue(v);
2739                                 goto error;
2740                             }
2741                         }
2742                         *val = v;
2743                     }
2744                     goto return0;
2745                 }
2746                 if (*cur == '-') {
2747                     neg = 1;
2748                     cur++;
2749                 }
2750                 if ((cur[0] == 'I') && (cur[1] == 'N') && (cur[2] == 'F')) {
2751                     cur += 3;
2752                     if (*cur != 0)
2753                         goto return1;
2754                     if (val != NULL) {
2755                         if (type == xmlSchemaTypeFloatDef) {
2756                             v = xmlSchemaNewValue(XML_SCHEMAS_FLOAT);
2757                             if (v != NULL) {
2758                                 if (neg)
2759                                     v->value.f = (float) xmlSchemaNINF;
2760                                 else
2761                                     v->value.f = (float) xmlSchemaPINF;
2762                             } else {
2763                                 xmlSchemaFreeValue(v);
2764                                 goto error;
2765                             }
2766                         } else {
2767                             v = xmlSchemaNewValue(XML_SCHEMAS_DOUBLE);
2768                             if (v != NULL) {
2769                                 if (neg)
2770                                     v->value.d = xmlSchemaNINF;
2771                                 else
2772                                     v->value.d = xmlSchemaPINF;
2773                             } else {
2774                                 xmlSchemaFreeValue(v);
2775                                 goto error;
2776                             }
2777                         }
2778                         *val = v;
2779                     }
2780                     goto return0;
2781                 }
2782                 if ((neg == 0) && (*cur == '+'))
2783                     cur++;
2784                 if ((cur[0] == 0) || (cur[0] == '+') || (cur[0] == '-'))
2785                     goto return1;
2786                 while ((*cur >= '0') && (*cur <= '9')) {
2787                     cur++;
2788                     digits_before++;
2789                 }
2790                 if (*cur == '.') {
2791                     cur++;
2792                     while ((*cur >= '0') && (*cur <= '9')) {
2793                         cur++;
2794                         digits_after++;
2795                     }
2796                 }
2797                 if ((digits_before == 0) && (digits_after == 0))
2798                     goto return1;
2799                 if ((*cur == 'e') || (*cur == 'E')) {
2800                     cur++;
2801                     if ((*cur == '-') || (*cur == '+'))
2802                         cur++;
2803                     while ((*cur >= '0') && (*cur <= '9'))
2804                         cur++;
2805                 }
2806 		if (normOnTheFly)
2807 		    while IS_WSP_BLANK_CH(*cur) cur++;
2808 
2809                 if (*cur != 0)
2810                     goto return1;
2811                 if (val != NULL) {
2812                     if (type == xmlSchemaTypeFloatDef) {
2813                         v = xmlSchemaNewValue(XML_SCHEMAS_FLOAT);
2814                         if (v != NULL) {
2815 			    /*
2816 			    * TODO: sscanf seems not to give the correct
2817 			    * value for extremely high/low values.
2818 			    * E.g. "1E-149" results in zero.
2819 			    */
2820                             if (sscanf((const char *) value, "%f",
2821                                  &(v->value.f)) == 1) {
2822                                 *val = v;
2823                             } else {
2824                                 xmlSchemaFreeValue(v);
2825                                 goto return1;
2826                             }
2827                         } else {
2828                             goto error;
2829                         }
2830                     } else {
2831                         v = xmlSchemaNewValue(XML_SCHEMAS_DOUBLE);
2832                         if (v != NULL) {
2833 			    /*
2834 			    * TODO: sscanf seems not to give the correct
2835 			    * value for extremely high/low values.
2836 			    */
2837                             if (sscanf((const char *) value, "%lf",
2838                                  &(v->value.d)) == 1) {
2839                                 *val = v;
2840                             } else {
2841                                 xmlSchemaFreeValue(v);
2842                                 goto return1;
2843                             }
2844                         } else {
2845                             goto error;
2846                         }
2847                     }
2848                 }
2849                 goto return0;
2850             }
2851         case XML_SCHEMAS_BOOLEAN:{
2852                 const xmlChar *cur = value;
2853 
2854 		if (normOnTheFly) {
2855 		    while IS_WSP_BLANK_CH(*cur) cur++;
2856 		    if (*cur == '0') {
2857 			ret = 0;
2858 			cur++;
2859 		    } else if (*cur == '1') {
2860 			ret = 1;
2861 			cur++;
2862 		    } else if (*cur == 't') {
2863 			cur++;
2864 			if ((*cur++ == 'r') && (*cur++ == 'u') &&
2865 			    (*cur++ == 'e')) {
2866 			    ret = 1;
2867 			} else
2868 			    goto return1;
2869 		    } else if (*cur == 'f') {
2870 			cur++;
2871 			if ((*cur++ == 'a') && (*cur++ == 'l') &&
2872 			    (*cur++ == 's') && (*cur++ == 'e')) {
2873 			    ret = 0;
2874 			} else
2875 			    goto return1;
2876 		    } else
2877 			goto return1;
2878 		    if (*cur != 0) {
2879 			while IS_WSP_BLANK_CH(*cur) cur++;
2880 			if (*cur != 0)
2881 			    goto return1;
2882 		    }
2883 		} else {
2884 		    if ((cur[0] == '0') && (cur[1] == 0))
2885 			ret = 0;
2886 		    else if ((cur[0] == '1') && (cur[1] == 0))
2887 			ret = 1;
2888 		    else if ((cur[0] == 't') && (cur[1] == 'r')
2889 			&& (cur[2] == 'u') && (cur[3] == 'e')
2890 			&& (cur[4] == 0))
2891 			ret = 1;
2892 		    else if ((cur[0] == 'f') && (cur[1] == 'a')
2893 			&& (cur[2] == 'l') && (cur[3] == 's')
2894 			&& (cur[4] == 'e') && (cur[5] == 0))
2895 			ret = 0;
2896 		    else
2897 			goto return1;
2898 		}
2899                 if (val != NULL) {
2900                     v = xmlSchemaNewValue(XML_SCHEMAS_BOOLEAN);
2901                     if (v != NULL) {
2902                         v->value.b = ret;
2903                         *val = v;
2904                     } else {
2905                         goto error;
2906                     }
2907                 }
2908                 goto return0;
2909             }
2910         case XML_SCHEMAS_TOKEN:{
2911                 const xmlChar *cur = value;
2912 
2913 		if (! normOnTheFly) {
2914 		    while (*cur != 0) {
2915 			if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) {
2916 			    goto return1;
2917 			} else if (*cur == ' ') {
2918 			    cur++;
2919 			    if (*cur == 0)
2920 				goto return1;
2921 			    if (*cur == ' ')
2922 				goto return1;
2923 			} else {
2924 			    cur++;
2925 			}
2926 		    }
2927 		}
2928                 if (val != NULL) {
2929                     v = xmlSchemaNewValue(XML_SCHEMAS_TOKEN);
2930                     if (v != NULL) {
2931                         v->value.str = xmlStrdup(value);
2932                         *val = v;
2933                     } else {
2934                         goto error;
2935                     }
2936                 }
2937                 goto return0;
2938             }
2939         case XML_SCHEMAS_LANGUAGE:
2940 	    if ((norm == NULL) && (normOnTheFly)) {
2941 		norm = xmlSchemaCollapseString(value);
2942 		if (norm != NULL)
2943 		    value = norm;
2944 	    }
2945 
2946             if (xmlSchemaCheckLanguageType(value) == 1) {
2947                 if (val != NULL) {
2948                     v = xmlSchemaNewValue(XML_SCHEMAS_LANGUAGE);
2949                     if (v != NULL) {
2950                         v->value.str = xmlStrdup(value);
2951                         *val = v;
2952                     } else {
2953                         goto error;
2954                     }
2955                 }
2956                 goto return0;
2957             }
2958             goto return1;
2959         case XML_SCHEMAS_NMTOKEN:
2960             if (xmlValidateNMToken(value, 1) == 0) {
2961                 if (val != NULL) {
2962                     v = xmlSchemaNewValue(XML_SCHEMAS_NMTOKEN);
2963                     if (v != NULL) {
2964                         v->value.str = xmlStrdup(value);
2965                         *val = v;
2966                     } else {
2967                         goto error;
2968                     }
2969                 }
2970                 goto return0;
2971             }
2972             goto return1;
2973         case XML_SCHEMAS_NMTOKENS:
2974             ret = xmlSchemaValAtomicListNode(xmlSchemaTypeNmtokenDef,
2975                                              value, val, node);
2976             if (ret > 0)
2977                 ret = 0;
2978             else
2979                 ret = 1;
2980             goto done;
2981         case XML_SCHEMAS_NAME:
2982             ret = xmlValidateName(value, 1);
2983             if ((ret == 0) && (val != NULL) && (value != NULL)) {
2984 		v = xmlSchemaNewValue(XML_SCHEMAS_NAME);
2985 		if (v != NULL) {
2986 		     const xmlChar *start = value, *end;
2987 		     while (IS_BLANK_CH(*start)) start++;
2988 		     end = start;
2989 		     while ((*end != 0) && (!IS_BLANK_CH(*end))) end++;
2990 		     v->value.str = xmlStrndup(start, end - start);
2991 		    *val = v;
2992 		} else {
2993 		    goto error;
2994 		}
2995             }
2996             goto done;
2997         case XML_SCHEMAS_QNAME:{
2998                 const xmlChar *uri = NULL;
2999                 xmlChar *local = NULL;
3000 
3001                 ret = xmlValidateQName(value, 1);
3002 		if (ret != 0)
3003 		    goto done;
3004                 if (node != NULL) {
3005                     xmlChar *prefix;
3006 		    xmlNsPtr ns;
3007 
3008                     local = xmlSplitQName2(value, &prefix);
3009 		    ns = xmlSearchNs(node->doc, node, prefix);
3010 		    if ((ns == NULL) && (prefix != NULL)) {
3011 			xmlFree(prefix);
3012 			if (local != NULL)
3013 			    xmlFree(local);
3014 			goto return1;
3015 		    }
3016 		    if (ns != NULL)
3017 			uri = ns->href;
3018                     if (prefix != NULL)
3019                         xmlFree(prefix);
3020                 }
3021                 if (val != NULL) {
3022                     v = xmlSchemaNewValue(XML_SCHEMAS_QNAME);
3023                     if (v == NULL) {
3024 			if (local != NULL)
3025 			    xmlFree(local);
3026 			goto error;
3027 		    }
3028 		    if (local != NULL)
3029 			v->value.qname.name = local;
3030 		    else
3031 			v->value.qname.name = xmlStrdup(value);
3032 		    if (uri != NULL)
3033 			v->value.qname.uri = xmlStrdup(uri);
3034 		    *val = v;
3035                 } else
3036 		    if (local != NULL)
3037 			xmlFree(local);
3038                 goto done;
3039             }
3040         case XML_SCHEMAS_NCNAME:
3041             ret = xmlValidateNCName(value, 1);
3042             if ((ret == 0) && (val != NULL)) {
3043                 v = xmlSchemaNewValue(XML_SCHEMAS_NCNAME);
3044                 if (v != NULL) {
3045                     v->value.str = xmlStrdup(value);
3046                     *val = v;
3047                 } else {
3048                     goto error;
3049                 }
3050             }
3051             goto done;
3052         case XML_SCHEMAS_ID:
3053             ret = xmlValidateNCName(value, 1);
3054             if ((ret == 0) && (val != NULL)) {
3055                 v = xmlSchemaNewValue(XML_SCHEMAS_ID);
3056                 if (v != NULL) {
3057                     v->value.str = xmlStrdup(value);
3058                     *val = v;
3059                 } else {
3060                     goto error;
3061                 }
3062             }
3063             if ((ret == 0) && (node != NULL) &&
3064                 (node->type == XML_ATTRIBUTE_NODE)) {
3065                 xmlAttrPtr attr = (xmlAttrPtr) node;
3066 
3067                 /*
3068                  * NOTE: the IDness might have already be declared in the DTD
3069                  */
3070                 if (attr->atype != XML_ATTRIBUTE_ID) {
3071                     xmlChar *strip;
3072                     int res;
3073 
3074                     strip = xmlSchemaStrip(value);
3075                     if (strip != NULL) {
3076                         res = xmlAddIDSafe(attr, strip);
3077                         xmlFree(strip);
3078                     } else
3079                         res = xmlAddIDSafe(attr, value);
3080                     if (res < 0) {
3081                         goto error;
3082                     } else if (res == 0) {
3083                         ret = 2;
3084                     }
3085                 }
3086             }
3087             goto done;
3088         case XML_SCHEMAS_IDREF:
3089             ret = xmlValidateNCName(value, 1);
3090             if ((ret == 0) && (val != NULL)) {
3091 		v = xmlSchemaNewValue(XML_SCHEMAS_IDREF);
3092 		if (v == NULL)
3093 		    goto error;
3094 		v->value.str = xmlStrdup(value);
3095 		*val = v;
3096             }
3097             if ((ret == 0) && (node != NULL) &&
3098                 (node->type == XML_ATTRIBUTE_NODE)) {
3099                 xmlAttrPtr attr = (xmlAttrPtr) node;
3100                 xmlChar *strip;
3101 
3102                 strip = xmlSchemaStrip(value);
3103                 if (strip != NULL) {
3104                     xmlAddRef(NULL, node->doc, strip, attr);
3105                     xmlFree(strip);
3106                 } else
3107                     xmlAddRef(NULL, node->doc, value, attr);
3108                 attr->atype = XML_ATTRIBUTE_IDREF;
3109             }
3110             goto done;
3111         case XML_SCHEMAS_IDREFS:
3112             ret = xmlSchemaValAtomicListNode(xmlSchemaTypeIdrefDef,
3113                                              value, val, node);
3114             if (ret < 0)
3115                 ret = 2;
3116             else
3117                 ret = 0;
3118             if ((ret == 0) && (node != NULL) &&
3119                 (node->type == XML_ATTRIBUTE_NODE)) {
3120                 xmlAttrPtr attr = (xmlAttrPtr) node;
3121 
3122                 attr->atype = XML_ATTRIBUTE_IDREFS;
3123             }
3124             goto done;
3125         case XML_SCHEMAS_ENTITY:{
3126                 xmlChar *strip;
3127 
3128                 ret = xmlValidateNCName(value, 1);
3129                 if ((node == NULL) || (node->doc == NULL))
3130                     ret = 3;
3131                 if (ret == 0) {
3132                     xmlEntityPtr ent;
3133 
3134                     strip = xmlSchemaStrip(value);
3135                     if (strip != NULL) {
3136                         ent = xmlGetDocEntity(node->doc, strip);
3137                         xmlFree(strip);
3138                     } else {
3139                         ent = xmlGetDocEntity(node->doc, value);
3140                     }
3141                     if ((ent == NULL) ||
3142                         (ent->etype !=
3143                          XML_EXTERNAL_GENERAL_UNPARSED_ENTITY))
3144                         ret = 4;
3145                 }
3146                 if ((ret == 0) && (val != NULL)) {
3147                     /* TODO */
3148                 }
3149                 if ((ret == 0) && (node != NULL) &&
3150                     (node->type == XML_ATTRIBUTE_NODE)) {
3151                     xmlAttrPtr attr = (xmlAttrPtr) node;
3152 
3153                     attr->atype = XML_ATTRIBUTE_ENTITY;
3154                 }
3155                 goto done;
3156             }
3157         case XML_SCHEMAS_ENTITIES:
3158             if ((node == NULL) || (node->doc == NULL))
3159                 goto return3;
3160             ret = xmlSchemaValAtomicListNode(xmlSchemaTypeEntityDef,
3161                                              value, val, node);
3162             if (ret <= 0)
3163                 ret = 1;
3164             else
3165                 ret = 0;
3166             if ((ret == 0) && (node != NULL) &&
3167                 (node->type == XML_ATTRIBUTE_NODE)) {
3168                 xmlAttrPtr attr = (xmlAttrPtr) node;
3169 
3170                 attr->atype = XML_ATTRIBUTE_ENTITIES;
3171             }
3172             goto done;
3173         case XML_SCHEMAS_NOTATION:{
3174                 xmlChar *uri = NULL;
3175                 xmlChar *local = NULL;
3176 
3177                 ret = xmlValidateQName(value, 1);
3178                 if ((ret == 0) && (node != NULL)) {
3179                     xmlChar *prefix;
3180 
3181                     local = xmlSplitQName2(value, &prefix);
3182                     if (prefix != NULL) {
3183                         xmlNsPtr ns;
3184 
3185                         ns = xmlSearchNs(node->doc, node, prefix);
3186                         if (ns == NULL)
3187                             ret = 1;
3188                         else if (val != NULL)
3189                             uri = xmlStrdup(ns->href);
3190                     }
3191                     if ((local != NULL) && ((val == NULL) || (ret != 0)))
3192                         xmlFree(local);
3193                     if (prefix != NULL)
3194                         xmlFree(prefix);
3195                 }
3196                 if ((node == NULL) || (node->doc == NULL))
3197                     ret = 3;
3198                 if (ret == 0) {
3199                     xmlNotationPtr nota;
3200 
3201                     nota = xmlGetDtdNotationDesc(node->doc->intSubset, value);
3202                     if ((nota == NULL) && (node->doc->extSubset != NULL))
3203                         nota = xmlGetDtdNotationDesc(node->doc->extSubset,
3204                                                      value);
3205                     if (nota != NULL)
3206                         ret = 0;
3207                     else
3208                         ret = 1;
3209                 }
3210                 if ((ret == 0) && (val != NULL)) {
3211                     v = xmlSchemaNewValue(XML_SCHEMAS_NOTATION);
3212                     if (v != NULL) {
3213                         if (local != NULL)
3214                             v->value.qname.name = local;
3215                         else
3216                             v->value.qname.name = xmlStrdup(value);
3217                         if (uri != NULL)
3218                             v->value.qname.uri = uri;
3219 
3220                         *val = v;
3221                     } else {
3222                         if (local != NULL)
3223                             xmlFree(local);
3224                         if (uri != NULL)
3225                             xmlFree(uri);
3226                         goto error;
3227                     }
3228                 }
3229                 goto done;
3230             }
3231         case XML_SCHEMAS_ANYURI:{
3232                 if (*value != 0) {
3233 		    xmlURIPtr uri;
3234 		    xmlChar *tmpval, *cur;
3235 		    if ((norm == NULL) && (normOnTheFly)) {
3236 			norm = xmlSchemaCollapseString(value);
3237 			if (norm != NULL)
3238 			    value = norm;
3239 		    }
3240 		    tmpval = xmlStrdup(value);
3241                     if (tmpval == NULL)
3242                         goto error;
3243 		    for (cur = tmpval; *cur; ++cur) {
3244 			if (*cur < 32 || *cur >= 127 || *cur == ' ' ||
3245 			    *cur == '<' || *cur == '>' || *cur == '"' ||
3246 			    *cur == '{' || *cur == '}' || *cur == '|' ||
3247 			    *cur == '\\' || *cur == '^' || *cur == '`' ||
3248 			    *cur == '\'')
3249 			    *cur = '_';
3250 		    }
3251                     uri = xmlParseURI((const char *) tmpval);
3252 		    xmlFree(tmpval);
3253                     if (uri == NULL)
3254                         goto return1;
3255                     xmlFreeURI(uri);
3256                 }
3257 
3258                 if (val != NULL) {
3259                     v = xmlSchemaNewValue(XML_SCHEMAS_ANYURI);
3260                     if (v == NULL)
3261                         goto error;
3262                     v->value.str = xmlStrdup(value);
3263                     *val = v;
3264                 }
3265                 goto return0;
3266             }
3267         case XML_SCHEMAS_HEXBINARY:{
3268                 const xmlChar *cur = value, *start;
3269                 xmlChar *base;
3270                 int total, i = 0;
3271 
3272                 if (cur == NULL)
3273                     goto return1;
3274 
3275 		if (normOnTheFly)
3276 		    while IS_WSP_BLANK_CH(*cur) cur++;
3277 
3278 		start = cur;
3279                 while (((*cur >= '0') && (*cur <= '9')) ||
3280                        ((*cur >= 'A') && (*cur <= 'F')) ||
3281                        ((*cur >= 'a') && (*cur <= 'f'))) {
3282                     i++;
3283                     cur++;
3284                 }
3285 		if (normOnTheFly)
3286 		    while IS_WSP_BLANK_CH(*cur) cur++;
3287 
3288                 if (*cur != 0)
3289                     goto return1;
3290                 if ((i % 2) != 0)
3291                     goto return1;
3292 
3293                 if (val != NULL) {
3294 
3295                     v = xmlSchemaNewValue(XML_SCHEMAS_HEXBINARY);
3296                     if (v == NULL)
3297                         goto error;
3298 		    /*
3299 		    * Copy only the normalized piece.
3300 		    * CRITICAL TODO: Check this.
3301 		    */
3302                     cur = xmlStrndup(start, i);
3303                     if (cur == NULL) {
3304 		        xmlSchemaTypeErrMemory();
3305                         xmlFree(v);
3306                         goto return1;
3307                     }
3308 
3309                     total = i / 2;      /* number of octets */
3310 
3311                     base = (xmlChar *) cur;
3312                     while (i-- > 0) {
3313                         if (*base >= 'a')
3314                             *base = *base - ('a' - 'A');
3315                         base++;
3316                     }
3317 
3318                     v->value.hex.str = (xmlChar *) cur;
3319                     v->value.hex.total = total;
3320                     *val = v;
3321                 }
3322                 goto return0;
3323             }
3324         case XML_SCHEMAS_BASE64BINARY:{
3325                 /* ISSUE:
3326                  *
3327                  * Ignore all stray characters? (yes, currently)
3328                  * Worry about long lines? (no, currently)
3329                  *
3330                  * rfc2045.txt:
3331                  *
3332                  * "The encoded output stream must be represented in lines of
3333                  * no more than 76 characters each.  All line breaks or other
3334                  * characters not found in Table 1 must be ignored by decoding
3335                  * software.  In base64 data, characters other than those in
3336                  * Table 1, line breaks, and other white space probably
3337                  * indicate a transmission error, about which a warning
3338                  * message or even a message rejection might be appropriate
3339                  * under some circumstances." */
3340                 const xmlChar *cur = value;
3341                 xmlChar *base;
3342                 int total, i = 0, pad = 0;
3343 
3344                 if (cur == NULL)
3345                     goto return1;
3346 
3347                 for (; *cur; ++cur) {
3348                     int decc;
3349 
3350                     decc = _xmlSchemaBase64Decode(*cur);
3351                     if (decc < 0) ;
3352                     else if (decc < 64)
3353                         i++;
3354                     else
3355                         break;
3356                 }
3357                 for (; *cur; ++cur) {
3358                     int decc;
3359 
3360                     decc = _xmlSchemaBase64Decode(*cur);
3361                     if (decc < 0) ;
3362                     else if (decc < 64)
3363                         goto return1;
3364                     if (decc == 64)
3365                         pad++;
3366                 }
3367 
3368                 /* rfc2045.txt: "Special processing is performed if fewer than
3369                  * 24 bits are available at the end of the data being encoded.
3370                  * A full encoding quantum is always completed at the end of a
3371                  * body.  When fewer than 24 input bits are available in an
3372                  * input group, zero bits are added (on the right) to form an
3373                  * integral number of 6-bit groups.  Padding at the end of the
3374                  * data is performed using the "=" character.  Since all
3375                  * base64 input is an integral number of octets, only the
3376                  * following cases can arise: (1) the final quantum of
3377                  * encoding input is an integral multiple of 24 bits; here,
3378                  * the final unit of encoded output will be an integral
3379                  * multiple of indent: Standard input:701: Warning:old style
3380 		 * assignment ambiguity in "=*".  Assuming "= *" 4 characters
3381 		 * with no "=" padding, (2) the final
3382                  * quantum of encoding input is exactly 8 bits; here, the
3383                  * final unit of encoded output will be two characters
3384                  * followed by two "=" padding characters, or (3) the final
3385                  * quantum of encoding input is exactly 16 bits; here, the
3386                  * final unit of encoded output will be three characters
3387                  * followed by one "=" padding character." */
3388 
3389                 total = 3 * (i / 4);
3390                 if (pad == 0) {
3391                     if (i % 4 != 0)
3392                         goto return1;
3393                 } else if (pad == 1) {
3394                     int decc;
3395 
3396                     if (i % 4 != 3)
3397                         goto return1;
3398                     for (decc = _xmlSchemaBase64Decode(*cur);
3399                          (decc < 0) || (decc > 63);
3400                          decc = _xmlSchemaBase64Decode(*cur))
3401                         --cur;
3402                     /* 16bits in 24bits means 2 pad bits: nnnnnn nnmmmm mmmm00*/
3403                     /* 00111100 -> 0x3c */
3404                     if (decc & ~0x3c)
3405                         goto return1;
3406                     total += 2;
3407                 } else if (pad == 2) {
3408                     int decc;
3409 
3410                     if (i % 4 != 2)
3411                         goto return1;
3412                     for (decc = _xmlSchemaBase64Decode(*cur);
3413                          (decc < 0) || (decc > 63);
3414                          decc = _xmlSchemaBase64Decode(*cur))
3415                         --cur;
3416                     /* 8bits in 12bits means 4 pad bits: nnnnnn nn0000 */
3417                     /* 00110000 -> 0x30 */
3418                     if (decc & ~0x30)
3419                         goto return1;
3420                     total += 1;
3421                 } else
3422                     goto return1;
3423 
3424                 if (val != NULL) {
3425                     v = xmlSchemaNewValue(XML_SCHEMAS_BASE64BINARY);
3426                     if (v == NULL)
3427                         goto error;
3428                     base =
3429                         xmlMalloc(i + pad + 1);
3430                     if (base == NULL) {
3431 		        xmlSchemaTypeErrMemory();
3432                         xmlFree(v);
3433                         goto return1;
3434                     }
3435                     v->value.base64.str = base;
3436                     for (cur = value; *cur; ++cur)
3437                         if (_xmlSchemaBase64Decode(*cur) >= 0) {
3438                             *base = *cur;
3439                             ++base;
3440                         }
3441                     *base = 0;
3442                     v->value.base64.total = total;
3443                     *val = v;
3444                 }
3445                 goto return0;
3446             }
3447         case XML_SCHEMAS_INTEGER:
3448         case XML_SCHEMAS_PINTEGER:
3449         case XML_SCHEMAS_NPINTEGER:
3450         case XML_SCHEMAS_NINTEGER:
3451         case XML_SCHEMAS_NNINTEGER:
3452         case XML_SCHEMAS_LONG:
3453         case XML_SCHEMAS_BYTE:
3454         case XML_SCHEMAS_SHORT:
3455         case XML_SCHEMAS_INT:
3456         case XML_SCHEMAS_UINT:
3457         case XML_SCHEMAS_ULONG:
3458         case XML_SCHEMAS_USHORT:
3459         case XML_SCHEMAS_UBYTE: {
3460                 const xmlChar *cur = value;
3461                 xmlSchemaValDecimal decimal;
3462                 xmlChar sign = '+';
3463 
3464                 memset(&decimal, 0, sizeof(decimal));
3465 
3466                 if (cur == NULL)
3467                     goto return1;
3468  		if (normOnTheFly)
3469 		    while IS_WSP_BLANK_CH(*cur) cur++;
3470                 if (*cur == '-') {
3471                     sign = '-';
3472                     cur++;
3473                 } else if (*cur == '+')
3474                     cur++;
3475                 ret = xmlSchemaParseUInt(&cur, &decimal);
3476                 /* add sign */
3477                 if (ret < 0)
3478                     goto valIntegerReturn1;
3479                 decimal.str[0] = sign;
3480 		if (normOnTheFly)
3481 		    while IS_WSP_BLANK_CH(*cur) cur++;
3482                 if (*cur != 0)
3483                     goto valIntegerReturn1;
3484                 if (type->builtInType == XML_SCHEMAS_NPINTEGER)
3485                 {
3486                     if(xmlSchemaValDecimalCompareWithInteger(&decimal, 0) > 0)
3487                         goto valIntegerReturn1;
3488                 }
3489                 else if (type->builtInType == XML_SCHEMAS_PINTEGER)
3490                 {
3491                     if (sign == '-')
3492                         goto valIntegerReturn1;
3493                     if (xmlSchemaValDecimalCompareWithInteger(&decimal, 0) <= 0)
3494                         goto valIntegerReturn1;
3495                 }
3496                 else if (type->builtInType == XML_SCHEMAS_NINTEGER)
3497                 {
3498                     if (xmlSchemaValDecimalCompareWithInteger(&decimal, 0) >= 0)
3499                         goto valIntegerReturn1;
3500                 }
3501                 else if (type->builtInType == XML_SCHEMAS_NNINTEGER)
3502                 {
3503                     if (xmlSchemaValDecimalCompareWithInteger(&decimal, 0) < 0)
3504                         goto valIntegerReturn1;
3505                 }
3506                 else if(type->builtInType == XML_SCHEMAS_LONG)
3507                 {
3508                     /* (u)int64_t may not be available on 32 bit platform, just use decimal */
3509                     xmlSchemaValDecimal tmpDecimal;
3510                     static const char maxLong[] = "+9223372036854775807.0";
3511                     static const char minLong[] = "-9223372036854775808.0";
3512                     tmpDecimal.fractionalPlaces = 1;
3513                     tmpDecimal.integralPlaces = 19;
3514                     tmpDecimal.str = BAD_CAST maxLong;
3515                     if (xmlSchemaValDecimalCompare(&decimal, &tmpDecimal) > 0)
3516                         goto valIntegerReturn1;
3517                     tmpDecimal.str = BAD_CAST minLong;
3518                     if (xmlSchemaValDecimalCompare(&decimal, &tmpDecimal) < 0)
3519                         goto valIntegerReturn1;
3520                 }
3521                 else if(type->builtInType == XML_SCHEMAS_ULONG)
3522                 {
3523                     xmlSchemaValDecimal tmpDecimal;
3524                     static const char maxULong[] = "+18446744073709551615.0";
3525                     tmpDecimal.fractionalPlaces = 1;
3526                     tmpDecimal.integralPlaces = 20;
3527                     tmpDecimal.str = (xmlChar*)maxULong;
3528                     if (xmlSchemaValDecimalCompare(&decimal, &tmpDecimal) > 0)
3529                         goto valIntegerReturn1;
3530                     if (xmlSchemaValDecimalCompareWithInteger(&decimal, 0) < 0)
3531                         goto valIntegerReturn1;
3532                 }
3533                 else if(type->builtInType == XML_SCHEMAS_INT)
3534                 {
3535                     if (xmlSchemaValDecimalCompareWithInteger(&decimal, 0x7fffffff) > 0) /* INT32_MAX */
3536                         goto valIntegerReturn1;
3537                     if (xmlSchemaValDecimalCompareWithInteger(&decimal, -0x7fffffff-1) < 0) /* INT32_MIN */
3538                         goto valIntegerReturn1;
3539                 }
3540                 else if(type->builtInType == XML_SCHEMAS_SHORT)
3541                 {
3542                     if (xmlSchemaValDecimalCompareWithInteger(&decimal, 0x7fff) > 0) /* INT16_MAX */
3543                         goto valIntegerReturn1;
3544                     if (xmlSchemaValDecimalCompareWithInteger(&decimal, -0x8000) < 0) /* INT16_MIN */
3545                         goto valIntegerReturn1;
3546                 }
3547                 else if(type->builtInType == XML_SCHEMAS_BYTE)
3548                 {if (xmlSchemaValDecimalCompareWithInteger(&decimal, 0x7f) > 0) /* INT8_MAX */
3549                         goto valIntegerReturn1;
3550                     if (xmlSchemaValDecimalCompareWithInteger(&decimal, -0x80) < 0) /* INT8_MIN */
3551                         goto valIntegerReturn1;
3552                 }
3553                 else if(type->builtInType == XML_SCHEMAS_UINT)
3554                 {
3555                     xmlSchemaValDecimal tmpDecimal;
3556                     static const char maxUInt[] = "+4294967295.0";
3557                     tmpDecimal.fractionalPlaces = 1;
3558                     tmpDecimal.integralPlaces = 10;
3559                     tmpDecimal.str = (xmlChar*)maxUInt;
3560                     if (xmlSchemaValDecimalCompare(&decimal, &tmpDecimal) > 0)
3561                         goto valIntegerReturn1;
3562                     if (xmlSchemaValDecimalCompareWithInteger(&decimal, 0) < 0)
3563                         goto valIntegerReturn1;
3564                 }
3565                 else if(type->builtInType == XML_SCHEMAS_USHORT)
3566                 {
3567                     if (xmlSchemaValDecimalCompareWithInteger(&decimal, 0xffff) > 0) /* UINT16_MAX */
3568                         goto valIntegerReturn1;
3569                     if (xmlSchemaValDecimalCompareWithInteger(&decimal, 0) < 0)
3570                         goto valIntegerReturn1;
3571                 }
3572                 else if(type->builtInType == XML_SCHEMAS_UBYTE)
3573                 {
3574                     if (xmlSchemaValDecimalCompareWithInteger(&decimal, 0xff) > 0) /* UINT8_MAX */
3575                         goto valIntegerReturn1;
3576                     if (xmlSchemaValDecimalCompareWithInteger(&decimal, 0) < 0)
3577                         goto valIntegerReturn1;
3578                 }
3579                 if (val != NULL) {
3580                     v = xmlSchemaNewValue(type->builtInType);
3581                     if (v != NULL) {
3582                         v->value.decimal = decimal;
3583                         *val = v;
3584                     }
3585                 }
3586                 else if(decimal.str != NULL)
3587                 {
3588                     xmlFree(decimal.str);
3589                 }
3590                 goto return0;
3591             valIntegerReturn1:
3592                 if(decimal.str != NULL)
3593                 {
3594                     xmlFree(decimal.str);
3595                 }
3596                 goto return1;
3597             }
3598     }
3599 
3600   done:
3601     if (norm != NULL)
3602         xmlFree(norm);
3603     return (ret);
3604   return3:
3605     if (norm != NULL)
3606         xmlFree(norm);
3607     return (3);
3608   return1:
3609     if (norm != NULL)
3610         xmlFree(norm);
3611     return (1);
3612   return0:
3613     if (norm != NULL)
3614         xmlFree(norm);
3615     return (0);
3616   error:
3617     if (norm != NULL)
3618         xmlFree(norm);
3619     return (-1);
3620 }
3621 
3622 /**
3623  * xmlSchemaValPredefTypeNode:
3624  * @type: the predefined type
3625  * @value: the value to check
3626  * @val:  the return computed value
3627  * @node:  the node containing the value
3628  *
3629  * Check that a value conforms to the lexical space of the predefined type.
3630  * if true a value is computed and returned in @val.
3631  *
3632  * Returns 0 if this validates, a positive error code number otherwise
3633  *         and -1 in case of internal or API error.
3634  */
3635 int
xmlSchemaValPredefTypeNode(xmlSchemaTypePtr type,const xmlChar * value,xmlSchemaValPtr * val,xmlNodePtr node)3636 xmlSchemaValPredefTypeNode(xmlSchemaTypePtr type, const xmlChar *value,
3637 	                   xmlSchemaValPtr *val, xmlNodePtr node) {
3638     return(xmlSchemaValAtomicType(type, value, val, node, 0,
3639 	XML_SCHEMA_WHITESPACE_UNKNOWN, 1, 1, 0));
3640 }
3641 
3642 /**
3643  * xmlSchemaValPredefTypeNodeNoNorm:
3644  * @type: the predefined type
3645  * @value: the value to check
3646  * @val:  the return computed value
3647  * @node:  the node containing the value
3648  *
3649  * Check that a value conforms to the lexical space of the predefined type.
3650  * if true a value is computed and returned in @val.
3651  * This one does apply any normalization to the value.
3652  *
3653  * Returns 0 if this validates, a positive error code number otherwise
3654  *         and -1 in case of internal or API error.
3655  */
3656 int
xmlSchemaValPredefTypeNodeNoNorm(xmlSchemaTypePtr type,const xmlChar * value,xmlSchemaValPtr * val,xmlNodePtr node)3657 xmlSchemaValPredefTypeNodeNoNorm(xmlSchemaTypePtr type, const xmlChar *value,
3658 				 xmlSchemaValPtr *val, xmlNodePtr node) {
3659     return(xmlSchemaValAtomicType(type, value, val, node, 1,
3660 	XML_SCHEMA_WHITESPACE_UNKNOWN, 1, 0, 1));
3661 }
3662 
3663 /**
3664  * xmlSchemaValidatePredefinedType:
3665  * @type: the predefined type
3666  * @value: the value to check
3667  * @val:  the return computed value
3668  *
3669  * Check that a value conforms to the lexical space of the predefined type.
3670  * if true a value is computed and returned in @val.
3671  *
3672  * Returns 0 if this validates, a positive error code number otherwise
3673  *         and -1 in case of internal or API error.
3674  */
3675 int
xmlSchemaValidatePredefinedType(xmlSchemaTypePtr type,const xmlChar * value,xmlSchemaValPtr * val)3676 xmlSchemaValidatePredefinedType(xmlSchemaTypePtr type, const xmlChar *value,
3677 	                        xmlSchemaValPtr *val) {
3678     return(xmlSchemaValPredefTypeNode(type, value, val, NULL));
3679 }
3680 
3681 /**
3682  * xmlSchemaCompareDecimals:
3683  * @x:  a first decimal value
3684  * @y:  a second decimal value
3685  *
3686  * Compare 2 decimals
3687  *
3688  * Returns -1 if x < y, 0 if x == y, 1 if x > y and -2 in case of error
3689  */
3690 static int
xmlSchemaCompareDecimals(xmlSchemaValPtr x,xmlSchemaValPtr y)3691 xmlSchemaCompareDecimals(xmlSchemaValPtr x, xmlSchemaValPtr y)
3692 {
3693     int res = xmlSchemaValDecimalCompare(&x->value.decimal, &y->value.decimal);
3694     if(res > 0)
3695     {
3696         return 1;
3697     }
3698     if(res < 0)
3699     {
3700         return -1;
3701     }
3702     return 0;
3703 }
3704 
3705 /**
3706  * xmlSchemaCompareDurations:
3707  * @x:  a first duration value
3708  * @y:  a second duration value
3709  *
3710  * Compare 2 durations
3711  *
3712  * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
3713  * case of error
3714  */
3715 static int
xmlSchemaCompareDurations(xmlSchemaValPtr x,xmlSchemaValPtr y)3716 xmlSchemaCompareDurations(xmlSchemaValPtr x, xmlSchemaValPtr y)
3717 {
3718     long carry, mon, day;
3719     double sec;
3720     int invert = 1;
3721     long xmon, xday, myear, minday, maxday;
3722     static const long dayRange [2][12] = {
3723         { 0, 28, 59, 89, 120, 150, 181, 212, 242, 273, 303, 334, },
3724         { 0, 31, 62, 92, 123, 153, 184, 215, 245, 276, 306, 337} };
3725 
3726     if ((x == NULL) || (y == NULL))
3727         return -2;
3728 
3729     /* months */
3730     mon = x->value.dur.mon - y->value.dur.mon;
3731 
3732     /* seconds */
3733     sec = x->value.dur.sec - y->value.dur.sec;
3734     carry = (long)(sec / SECS_PER_DAY);
3735     sec -= ((double)carry) * SECS_PER_DAY;
3736 
3737     /* days */
3738     day = x->value.dur.day - y->value.dur.day + carry;
3739 
3740     /* easy test */
3741     if (mon == 0) {
3742         if (day == 0)
3743             if (sec == 0.0)
3744                 return 0;
3745             else if (sec < 0.0)
3746                 return -1;
3747             else
3748                 return 1;
3749         else if (day < 0)
3750             return -1;
3751         else
3752             return 1;
3753     }
3754 
3755     if (mon > 0) {
3756         if ((day >= 0) && (sec >= 0.0))
3757             return 1;
3758         else {
3759             xmon = mon;
3760             xday = -day;
3761         }
3762     } else if ((day <= 0) && (sec <= 0.0)) {
3763         return -1;
3764     } else {
3765 	invert = -1;
3766         xmon = -mon;
3767         xday = day;
3768     }
3769 
3770     myear = xmon / 12;
3771     if (myear == 0) {
3772 	minday = 0;
3773 	maxday = 0;
3774     } else {
3775         if (myear > LONG_MAX / 366)
3776             return -2;
3777         /* FIXME: This doesn't take leap year exceptions every 100/400 years
3778            into account. */
3779 	maxday = 365 * myear + (myear + 3) / 4;
3780         /* FIXME: Needs to be calculated separately */
3781 	minday = maxday - 1;
3782     }
3783 
3784     xmon = xmon % 12;
3785     minday += dayRange[0][xmon];
3786     maxday += dayRange[1][xmon];
3787 
3788     if ((maxday == minday) && (maxday == xday))
3789 	return(0); /* can this really happen ? */
3790     if (maxday < xday)
3791         return(-invert);
3792     if (minday > xday)
3793         return(invert);
3794 
3795     /* indeterminate */
3796     return 2;
3797 }
3798 
3799 /*
3800  * macros for adding date/times and durations
3801  */
3802 #define FQUOTIENT(a,b)                  (floor(((double)a/(double)b)))
3803 #define MODULO(a,b)                     (a - FQUOTIENT(a,b) * b)
3804 #define FQUOTIENT_RANGE(a,low,high)     (FQUOTIENT((a-low),(high-low)))
3805 #define MODULO_RANGE(a,low,high)        ((MODULO((a-low),(high-low)))+low)
3806 
3807 /**
3808  * xmlSchemaDupVal:
3809  * @v: the #xmlSchemaValPtr value to duplicate
3810  *
3811  * Makes a copy of @v. The calling program is responsible for freeing
3812  * the returned value.
3813  *
3814  * returns a pointer to a duplicated #xmlSchemaValPtr or NULL if error.
3815  */
3816 static xmlSchemaValPtr
xmlSchemaDupVal(xmlSchemaValPtr v)3817 xmlSchemaDupVal (xmlSchemaValPtr v)
3818 {
3819     xmlSchemaValPtr ret = xmlSchemaNewValue(v->type);
3820     if (ret == NULL)
3821         return NULL;
3822 
3823     memcpy(ret, v, sizeof(xmlSchemaVal));
3824     ret->next = NULL;
3825     return ret;
3826 }
3827 
3828 /**
3829  * xmlSchemaCopyValue:
3830  * @val:  the precomputed value to be copied
3831  *
3832  * Copies the precomputed value. This duplicates any string within.
3833  *
3834  * Returns the copy or NULL if a copy for a data-type is not implemented.
3835  */
3836 xmlSchemaValPtr
xmlSchemaCopyValue(xmlSchemaValPtr val)3837 xmlSchemaCopyValue(xmlSchemaValPtr val)
3838 {
3839     xmlSchemaValPtr ret = NULL, prev = NULL, cur;
3840 
3841     /*
3842     * Copy the string values.
3843     */
3844     while (val != NULL) {
3845 	switch (val->type) {
3846 	    case XML_SCHEMAS_ANYTYPE:
3847 	    case XML_SCHEMAS_IDREFS:
3848 	    case XML_SCHEMAS_ENTITIES:
3849 	    case XML_SCHEMAS_NMTOKENS:
3850 		xmlSchemaFreeValue(ret);
3851 		return (NULL);
3852 	    case XML_SCHEMAS_ANYSIMPLETYPE:
3853 	    case XML_SCHEMAS_STRING:
3854 	    case XML_SCHEMAS_NORMSTRING:
3855 	    case XML_SCHEMAS_TOKEN:
3856 	    case XML_SCHEMAS_LANGUAGE:
3857 	    case XML_SCHEMAS_NAME:
3858 	    case XML_SCHEMAS_NCNAME:
3859 	    case XML_SCHEMAS_ID:
3860 	    case XML_SCHEMAS_IDREF:
3861 	    case XML_SCHEMAS_ENTITY:
3862 	    case XML_SCHEMAS_NMTOKEN:
3863 	    case XML_SCHEMAS_ANYURI:
3864 		cur = xmlSchemaDupVal(val);
3865 		if (val->value.str != NULL)
3866 		    cur->value.str = xmlStrdup(BAD_CAST val->value.str);
3867 		break;
3868 	    case XML_SCHEMAS_QNAME:
3869 	    case XML_SCHEMAS_NOTATION:
3870 		cur = xmlSchemaDupVal(val);
3871 		if (val->value.qname.name != NULL)
3872 		    cur->value.qname.name =
3873                     xmlStrdup(BAD_CAST val->value.qname.name);
3874 		if (val->value.qname.uri != NULL)
3875 		    cur->value.qname.uri =
3876                     xmlStrdup(BAD_CAST val->value.qname.uri);
3877 		break;
3878 	    case XML_SCHEMAS_HEXBINARY:
3879 		cur = xmlSchemaDupVal(val);
3880 		if (val->value.hex.str != NULL)
3881 		    cur->value.hex.str = xmlStrdup(BAD_CAST val->value.hex.str);
3882 		break;
3883 	    case XML_SCHEMAS_BASE64BINARY:
3884 		cur = xmlSchemaDupVal(val);
3885 		if (val->value.base64.str != NULL)
3886 		    cur->value.base64.str =
3887                     xmlStrdup(BAD_CAST val->value.base64.str);
3888 		break;
3889             case XML_SCHEMAS_DECIMAL:
3890             case XML_SCHEMAS_INTEGER:
3891             case XML_SCHEMAS_PINTEGER:
3892             case XML_SCHEMAS_NPINTEGER:
3893             case XML_SCHEMAS_NINTEGER:
3894             case XML_SCHEMAS_NNINTEGER:
3895             case XML_SCHEMAS_LONG:
3896             case XML_SCHEMAS_BYTE:
3897             case XML_SCHEMAS_SHORT:
3898             case XML_SCHEMAS_INT:
3899             case XML_SCHEMAS_UINT:
3900             case XML_SCHEMAS_ULONG:
3901             case XML_SCHEMAS_USHORT:
3902             case XML_SCHEMAS_UBYTE:
3903                 cur = xmlSchemaDupVal(val);
3904                 if (val->value.decimal.str != NULL)
3905                     cur->value.decimal.str = xmlStrdup(BAD_CAST val->value.decimal.str);
3906 		break;
3907 	    default:
3908 		cur = xmlSchemaDupVal(val);
3909 		break;
3910 	}
3911 	if (ret == NULL)
3912 	    ret = cur;
3913 	else
3914 	    prev->next = cur;
3915 	prev = cur;
3916 	val = val->next;
3917     }
3918     return (ret);
3919 }
3920 
3921 /**
3922  * _xmlSchemaDateAdd:
3923  * @dt: an #xmlSchemaValPtr
3924  * @dur: an #xmlSchemaValPtr of type #XS_DURATION
3925  *
3926  * Compute a new date/time from @dt and @dur. This function assumes @dt
3927  * is either #XML_SCHEMAS_DATETIME, #XML_SCHEMAS_DATE, #XML_SCHEMAS_GYEARMONTH,
3928  * or #XML_SCHEMAS_GYEAR. The returned #xmlSchemaVal is the same type as
3929  * @dt. The calling program is responsible for freeing the returned value.
3930  *
3931  * Returns a pointer to a new #xmlSchemaVal or NULL if error.
3932  */
3933 static xmlSchemaValPtr
_xmlSchemaDateAdd(xmlSchemaValPtr dt,xmlSchemaValPtr dur)3934 _xmlSchemaDateAdd (xmlSchemaValPtr dt, xmlSchemaValPtr dur)
3935 {
3936     xmlSchemaValPtr ret, tmp;
3937     long carry, tempdays, temp;
3938     xmlSchemaValDatePtr r, d;
3939     xmlSchemaValDurationPtr u;
3940 
3941     if ((dt == NULL) || (dur == NULL))
3942         return NULL;
3943 
3944     ret = xmlSchemaNewValue(dt->type);
3945     if (ret == NULL)
3946         return NULL;
3947 
3948     /* make a copy so we don't alter the original value */
3949     tmp = xmlSchemaDupVal(dt);
3950     if (tmp == NULL) {
3951         xmlSchemaFreeValue(ret);
3952         return NULL;
3953     }
3954 
3955     r = &(ret->value.date);
3956     d = &(tmp->value.date);
3957     u = &(dur->value.dur);
3958 
3959     /* normalization */
3960     if (d->mon == 0)
3961         d->mon = 1;
3962 
3963     /* normalize for time zone offset */
3964     u->sec -= (d->tzo * 60);
3965     d->tzo = 0;
3966 
3967     /* normalization */
3968     if (d->day == 0)
3969         d->day = 1;
3970 
3971     /* month */
3972     carry  = d->mon + u->mon;
3973     r->mon = (unsigned int) MODULO_RANGE(carry, 1, 13);
3974     carry  = (long) FQUOTIENT_RANGE(carry, 1, 13);
3975 
3976     /* year (may be modified later) */
3977     r->year = d->year + carry;
3978     if (r->year == 0) {
3979         if (d->year > 0)
3980             r->year--;
3981         else
3982             r->year++;
3983     }
3984 
3985     /* time zone */
3986     r->tzo     = d->tzo;
3987     r->tz_flag = d->tz_flag;
3988 
3989     /* seconds */
3990     r->sec = d->sec + u->sec;
3991     carry  = (long) FQUOTIENT((long)r->sec, 60);
3992     if (r->sec != 0.0) {
3993         r->sec = MODULO(r->sec, 60.0);
3994     }
3995 
3996     /* minute */
3997     carry += d->min;
3998     r->min = (unsigned int) MODULO(carry, 60);
3999     carry  = (long) FQUOTIENT(carry, 60);
4000 
4001     /* hours */
4002     carry  += d->hour;
4003     r->hour = (unsigned int) MODULO(carry, 24);
4004     carry   = (long)FQUOTIENT(carry, 24);
4005 
4006     /*
4007      * days
4008      * Note we use tempdays because the temporary values may need more
4009      * than 5 bits
4010      */
4011     if ((VALID_YEAR(r->year)) && (VALID_MONTH(r->mon)) &&
4012                   (d->day > MAX_DAYINMONTH(r->year, r->mon)))
4013         tempdays = MAX_DAYINMONTH(r->year, r->mon);
4014     else if (d->day < 1)
4015         tempdays = 1;
4016     else
4017         tempdays = d->day;
4018 
4019     tempdays += u->day + carry;
4020 
4021     while (1) {
4022         if (tempdays < 1) {
4023             long tmon = (long) MODULO_RANGE((int)r->mon-1, 1, 13);
4024             long tyr  = r->year + (long)FQUOTIENT_RANGE((int)r->mon-1, 1, 13);
4025             if (tyr == 0)
4026                 tyr--;
4027 	    /*
4028 	     * Coverity detected an overrun in daysInMonth
4029 	     * of size 12 at position 12 with index variable "((r)->mon - 1)"
4030 	     */
4031 	    if (tmon < 1)
4032 	        tmon = 1;
4033 	    if (tmon > 12)
4034 	        tmon = 12;
4035             tempdays += MAX_DAYINMONTH(tyr, tmon);
4036             carry = -1;
4037         } else if (VALID_YEAR(r->year) && VALID_MONTH(r->mon) &&
4038                    tempdays > (long) MAX_DAYINMONTH(r->year, r->mon)) {
4039             tempdays = tempdays - MAX_DAYINMONTH(r->year, r->mon);
4040             carry = 1;
4041         } else
4042             break;
4043 
4044         temp = r->mon + carry;
4045         r->mon = (unsigned int) MODULO_RANGE(temp, 1, 13);
4046         r->year = r->year + (long) FQUOTIENT_RANGE(temp, 1, 13);
4047         if (r->year == 0) {
4048             if (temp < 1)
4049                 r->year--;
4050             else
4051                 r->year++;
4052 	}
4053     }
4054 
4055     r->day = tempdays;
4056 
4057     /*
4058      * adjust the date/time type to the date values
4059      */
4060     if (ret->type != XML_SCHEMAS_DATETIME) {
4061         if ((r->hour) || (r->min) || (r->sec))
4062             ret->type = XML_SCHEMAS_DATETIME;
4063         else if (ret->type != XML_SCHEMAS_DATE) {
4064             if ((r->mon != 1) && (r->day != 1))
4065                 ret->type = XML_SCHEMAS_DATE;
4066             else if ((ret->type != XML_SCHEMAS_GYEARMONTH) && (r->mon != 1))
4067                 ret->type = XML_SCHEMAS_GYEARMONTH;
4068         }
4069     }
4070 
4071     xmlSchemaFreeValue(tmp);
4072 
4073     return ret;
4074 }
4075 
4076 /**
4077  * xmlSchemaDateNormalize:
4078  * @dt: an #xmlSchemaValPtr of a date/time type value.
4079  * @offset: number of seconds to adjust @dt by.
4080  *
4081  * Normalize @dt to GMT time. The @offset parameter is subtracted from
4082  * the return value is a time-zone offset is present on @dt.
4083  *
4084  * Returns a normalized copy of @dt or NULL if error.
4085  */
4086 static xmlSchemaValPtr
xmlSchemaDateNormalize(xmlSchemaValPtr dt,double offset)4087 xmlSchemaDateNormalize (xmlSchemaValPtr dt, double offset)
4088 {
4089     xmlSchemaValPtr dur, ret;
4090 
4091     if (dt == NULL)
4092         return NULL;
4093 
4094     if (((dt->type != XML_SCHEMAS_TIME) &&
4095          (dt->type != XML_SCHEMAS_DATETIME) &&
4096 	 (dt->type != XML_SCHEMAS_DATE)) || (dt->value.date.tzo == 0))
4097         return xmlSchemaDupVal(dt);
4098 
4099     dur = xmlSchemaNewValue(XML_SCHEMAS_DURATION);
4100     if (dur == NULL)
4101         return NULL;
4102 
4103     dur->value.date.sec -= offset;
4104 
4105     ret = _xmlSchemaDateAdd(dt, dur);
4106     if (ret == NULL)
4107         return NULL;
4108 
4109     xmlSchemaFreeValue(dur);
4110 
4111     /* ret->value.date.tzo = 0; */
4112     return ret;
4113 }
4114 
4115 /**
4116  * _xmlSchemaDateCastYMToDays:
4117  * @dt: an #xmlSchemaValPtr
4118  *
4119  * Convert mon and year of @dt to total number of days. Take the
4120  * number of years since (or before) 1 AD and add the number of leap
4121  * years. This is a function  because negative
4122  * years must be handled a little differently and there is no zero year.
4123  *
4124  * Returns number of days.
4125  */
4126 static long
_xmlSchemaDateCastYMToDays(const xmlSchemaValPtr dt)4127 _xmlSchemaDateCastYMToDays (const xmlSchemaValPtr dt)
4128 {
4129     long ret;
4130     int mon;
4131 
4132     mon = dt->value.date.mon;
4133     if (mon <= 0) mon = 1; /* normalization */
4134 
4135     if (dt->value.date.year <= 0)
4136         ret = (dt->value.date.year * 365) +
4137               (((dt->value.date.year+1)/4)-((dt->value.date.year+1)/100)+
4138                ((dt->value.date.year+1)/400)) +
4139               DAY_IN_YEAR(0, mon, dt->value.date.year);
4140     else
4141         ret = ((dt->value.date.year-1) * 365) +
4142               (((dt->value.date.year-1)/4)-((dt->value.date.year-1)/100)+
4143                ((dt->value.date.year-1)/400)) +
4144               DAY_IN_YEAR(0, mon, dt->value.date.year);
4145 
4146     return ret;
4147 }
4148 
4149 /**
4150  * TIME_TO_NUMBER:
4151  * @dt:  an #xmlSchemaValPtr
4152  *
4153  * Calculates the number of seconds in the time portion of @dt.
4154  *
4155  * Returns seconds.
4156  */
4157 #define TIME_TO_NUMBER(dt)                              \
4158     ((double)((dt->value.date.hour * SECS_PER_HOUR) +   \
4159               (dt->value.date.min * SECS_PER_MIN) +	\
4160               (dt->value.date.tzo * SECS_PER_MIN)) +	\
4161                dt->value.date.sec)
4162 
4163 /**
4164  * xmlSchemaCompareDates:
4165  * @x:  a first date/time value
4166  * @y:  a second date/time value
4167  *
4168  * Compare 2 date/times
4169  *
4170  * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
4171  * case of error
4172  */
4173 static int
xmlSchemaCompareDates(xmlSchemaValPtr x,xmlSchemaValPtr y)4174 xmlSchemaCompareDates (xmlSchemaValPtr x, xmlSchemaValPtr y)
4175 {
4176     unsigned char xmask, ymask, xor_mask, and_mask;
4177     xmlSchemaValPtr p1, p2, q1, q2;
4178     long p1d, p2d, q1d, q2d;
4179 
4180     if ((x == NULL) || (y == NULL))
4181         return -2;
4182 
4183     if ((x->value.date.year > LONG_MAX / 366) ||
4184         (x->value.date.year < LONG_MIN / 366) ||
4185         (y->value.date.year > LONG_MAX / 366) ||
4186         (y->value.date.year < LONG_MIN / 366)) {
4187         /* Possible overflow when converting to days. */
4188         return -2;
4189     }
4190 
4191     if (x->value.date.tz_flag) {
4192 
4193         if (!y->value.date.tz_flag) {
4194             p1 = xmlSchemaDateNormalize(x, 0);
4195             if (p1 == NULL)
4196                 return -2;
4197             p1d = _xmlSchemaDateCastYMToDays(p1) + p1->value.date.day;
4198             /* normalize y + 14:00 */
4199             q1 = xmlSchemaDateNormalize(y, (14 * SECS_PER_HOUR));
4200             if (q1 == NULL) {
4201 		xmlSchemaFreeValue(p1);
4202                 return -2;
4203             }
4204 
4205             q1d = _xmlSchemaDateCastYMToDays(q1) + q1->value.date.day;
4206             if (p1d < q1d) {
4207 		xmlSchemaFreeValue(p1);
4208 		xmlSchemaFreeValue(q1);
4209                 return -1;
4210 	    } else if (p1d == q1d) {
4211                 double sec;
4212 
4213                 sec = TIME_TO_NUMBER(p1) - TIME_TO_NUMBER(q1);
4214                 if (sec < 0.0) {
4215 		    xmlSchemaFreeValue(p1);
4216 		    xmlSchemaFreeValue(q1);
4217                     return -1;
4218 		} else {
4219 		    int ret = 0;
4220                     /* normalize y - 14:00 */
4221                     q2 = xmlSchemaDateNormalize(y, -(14 * SECS_PER_HOUR));
4222                     if (q2 == NULL) {
4223                         xmlSchemaFreeValue(p1);
4224                         xmlSchemaFreeValue(q1);
4225                         return -2;
4226                     }
4227                     q2d = _xmlSchemaDateCastYMToDays(q2) + q2->value.date.day;
4228                     if (p1d > q2d)
4229                         ret = 1;
4230                     else if (p1d == q2d) {
4231                         sec = TIME_TO_NUMBER(p1) - TIME_TO_NUMBER(q2);
4232                         if (sec > 0.0)
4233                             ret = 1;
4234                         else
4235                             ret = 2; /* indeterminate */
4236                     }
4237 		    xmlSchemaFreeValue(p1);
4238 		    xmlSchemaFreeValue(q1);
4239 		    xmlSchemaFreeValue(q2);
4240 		    if (ret != 0)
4241 		        return(ret);
4242                 }
4243             } else {
4244 		xmlSchemaFreeValue(p1);
4245 		xmlSchemaFreeValue(q1);
4246 	    }
4247         }
4248     } else if (y->value.date.tz_flag) {
4249         q1 = xmlSchemaDateNormalize(y, 0);
4250         if (q1 == NULL)
4251             return -2;
4252         q1d = _xmlSchemaDateCastYMToDays(q1) + q1->value.date.day;
4253 
4254         /* normalize x - 14:00 */
4255         p1 = xmlSchemaDateNormalize(x, -(14 * SECS_PER_HOUR));
4256         if (p1 == NULL) {
4257 	    xmlSchemaFreeValue(q1);
4258             return -2;
4259         }
4260         p1d = _xmlSchemaDateCastYMToDays(p1) + p1->value.date.day;
4261 
4262         if (p1d < q1d) {
4263 	    xmlSchemaFreeValue(p1);
4264 	    xmlSchemaFreeValue(q1);
4265             return -1;
4266 	} else if (p1d == q1d) {
4267             double sec;
4268 
4269             sec = TIME_TO_NUMBER(p1) - TIME_TO_NUMBER(q1);
4270             if (sec < 0.0) {
4271 		xmlSchemaFreeValue(p1);
4272 		xmlSchemaFreeValue(q1);
4273                 return -1;
4274 	    } else {
4275 	        int ret = 0;
4276                 /* normalize x + 14:00 */
4277                 p2 = xmlSchemaDateNormalize(x, (14 * SECS_PER_HOUR));
4278                 if (p2 == NULL) {
4279                     xmlSchemaFreeValue(p1);
4280                     xmlSchemaFreeValue(q1);
4281                     return -2;
4282                 }
4283                 p2d = _xmlSchemaDateCastYMToDays(p2) + p2->value.date.day;
4284 
4285                 if (p2d > q1d) {
4286                     ret = 1;
4287 		} else if (p2d == q1d) {
4288                     sec = TIME_TO_NUMBER(p2) - TIME_TO_NUMBER(q1);
4289                     if (sec > 0.0)
4290                         ret = 1;
4291                     else
4292                         ret = 2; /* indeterminate */
4293                 }
4294 		xmlSchemaFreeValue(p1);
4295 		xmlSchemaFreeValue(q1);
4296 		xmlSchemaFreeValue(p2);
4297 		if (ret != 0)
4298 		    return(ret);
4299             }
4300 	} else {
4301 	    xmlSchemaFreeValue(p1);
4302 	    xmlSchemaFreeValue(q1);
4303         }
4304     }
4305 
4306     /*
4307      * if the same type then calculate the difference
4308      */
4309     if (x->type == y->type) {
4310         int ret = 0;
4311         q1 = xmlSchemaDateNormalize(y, 0);
4312         if (q1 == NULL)
4313             return -2;
4314         q1d = _xmlSchemaDateCastYMToDays(q1) + q1->value.date.day;
4315 
4316         p1 = xmlSchemaDateNormalize(x, 0);
4317         if (p1 == NULL) {
4318 	    xmlSchemaFreeValue(q1);
4319             return -2;
4320         }
4321         p1d = _xmlSchemaDateCastYMToDays(p1) + p1->value.date.day;
4322 
4323         if (p1d < q1d) {
4324             ret = -1;
4325 	} else if (p1d > q1d) {
4326             ret = 1;
4327 	} else {
4328             double sec;
4329 
4330             sec = TIME_TO_NUMBER(p1) - TIME_TO_NUMBER(q1);
4331             if (sec < 0.0)
4332                 ret = -1;
4333             else if (sec > 0.0)
4334                 ret = 1;
4335 
4336         }
4337 	xmlSchemaFreeValue(p1);
4338 	xmlSchemaFreeValue(q1);
4339         return(ret);
4340     }
4341 
4342     switch (x->type) {
4343         case XML_SCHEMAS_DATETIME:
4344             xmask = 0xf;
4345             break;
4346         case XML_SCHEMAS_DATE:
4347             xmask = 0x7;
4348             break;
4349         case XML_SCHEMAS_GYEAR:
4350             xmask = 0x1;
4351             break;
4352         case XML_SCHEMAS_GMONTH:
4353             xmask = 0x2;
4354             break;
4355         case XML_SCHEMAS_GDAY:
4356             xmask = 0x3;
4357             break;
4358         case XML_SCHEMAS_GYEARMONTH:
4359             xmask = 0x3;
4360             break;
4361         case XML_SCHEMAS_GMONTHDAY:
4362             xmask = 0x6;
4363             break;
4364         case XML_SCHEMAS_TIME:
4365             xmask = 0x8;
4366             break;
4367         default:
4368             xmask = 0;
4369             break;
4370     }
4371 
4372     switch (y->type) {
4373         case XML_SCHEMAS_DATETIME:
4374             ymask = 0xf;
4375             break;
4376         case XML_SCHEMAS_DATE:
4377             ymask = 0x7;
4378             break;
4379         case XML_SCHEMAS_GYEAR:
4380             ymask = 0x1;
4381             break;
4382         case XML_SCHEMAS_GMONTH:
4383             ymask = 0x2;
4384             break;
4385         case XML_SCHEMAS_GDAY:
4386             ymask = 0x3;
4387             break;
4388         case XML_SCHEMAS_GYEARMONTH:
4389             ymask = 0x3;
4390             break;
4391         case XML_SCHEMAS_GMONTHDAY:
4392             ymask = 0x6;
4393             break;
4394         case XML_SCHEMAS_TIME:
4395             ymask = 0x8;
4396             break;
4397         default:
4398             ymask = 0;
4399             break;
4400     }
4401 
4402     xor_mask = xmask ^ ymask;           /* mark type differences */
4403     and_mask = xmask & ymask;           /* mark field specification */
4404 
4405     /* year */
4406     if (xor_mask & 1)
4407         return 2; /* indeterminate */
4408     else if (and_mask & 1) {
4409         if (x->value.date.year < y->value.date.year)
4410             return -1;
4411         else if (x->value.date.year > y->value.date.year)
4412             return 1;
4413     }
4414 
4415     /* month */
4416     if (xor_mask & 2)
4417         return 2; /* indeterminate */
4418     else if (and_mask & 2) {
4419         if (x->value.date.mon < y->value.date.mon)
4420             return -1;
4421         else if (x->value.date.mon > y->value.date.mon)
4422             return 1;
4423     }
4424 
4425     /* day */
4426     if (xor_mask & 4)
4427         return 2; /* indeterminate */
4428     else if (and_mask & 4) {
4429         if (x->value.date.day < y->value.date.day)
4430             return -1;
4431         else if (x->value.date.day > y->value.date.day)
4432             return 1;
4433     }
4434 
4435     /* time */
4436     if (xor_mask & 8)
4437         return 2; /* indeterminate */
4438     else if (and_mask & 8) {
4439         if (x->value.date.hour < y->value.date.hour)
4440             return -1;
4441         else if (x->value.date.hour > y->value.date.hour)
4442             return 1;
4443         else if (x->value.date.min < y->value.date.min)
4444             return -1;
4445         else if (x->value.date.min > y->value.date.min)
4446             return 1;
4447         else if (x->value.date.sec < y->value.date.sec)
4448             return -1;
4449         else if (x->value.date.sec > y->value.date.sec)
4450             return 1;
4451     }
4452 
4453     return 0;
4454 }
4455 
4456 /**
4457  * xmlSchemaComparePreserveReplaceStrings:
4458  * @x:  a first string value
4459  * @y:  a second string value
4460  * @invert: inverts the result if x < y or x > y.
4461  *
4462  * Compare 2 string for their normalized values.
4463  * @x is a string with whitespace of "preserve", @y is
4464  * a string with a whitespace of "replace". I.e. @x could
4465  * be an "xsd:string" and @y an "xsd:normalizedString".
4466  *
4467  * Returns -1 if x < y, 0 if x == y, 1 if x > y, and -2 in
4468  * case of error
4469  */
4470 static int
xmlSchemaComparePreserveReplaceStrings(const xmlChar * x,const xmlChar * y,int invert)4471 xmlSchemaComparePreserveReplaceStrings(const xmlChar *x,
4472 				       const xmlChar *y,
4473 				       int invert)
4474 {
4475     int tmp;
4476 
4477     while ((*x != 0) && (*y != 0)) {
4478 	if (IS_WSP_REPLACE_CH(*y)) {
4479 	    if (! IS_WSP_SPACE_CH(*x)) {
4480 		if ((*x - 0x20) < 0) {
4481 		    if (invert)
4482 			return(1);
4483 		    else
4484 			return(-1);
4485 		} else {
4486 		    if (invert)
4487 			return(-1);
4488 		    else
4489 			return(1);
4490 		}
4491 	    }
4492 	} else {
4493 	    tmp = *x - *y;
4494 	    if (tmp < 0) {
4495 		if (invert)
4496 		    return(1);
4497 		else
4498 		    return(-1);
4499 	    }
4500 	    if (tmp > 0) {
4501 		if (invert)
4502 		    return(-1);
4503 		else
4504 		    return(1);
4505 	    }
4506 	}
4507 	x++;
4508 	y++;
4509     }
4510     if (*x != 0) {
4511 	if (invert)
4512 	    return(-1);
4513 	else
4514 	    return(1);
4515     }
4516     if (*y != 0) {
4517 	if (invert)
4518 	    return(1);
4519 	else
4520 	    return(-1);
4521     }
4522     return(0);
4523 }
4524 
4525 /**
4526  * xmlSchemaComparePreserveCollapseStrings:
4527  * @x:  a first string value
4528  * @y:  a second string value
4529  *
4530  * Compare 2 string for their normalized values.
4531  * @x is a string with whitespace of "preserve", @y is
4532  * a string with a whitespace of "collapse". I.e. @x could
4533  * be an "xsd:string" and @y an "xsd:normalizedString".
4534  *
4535  * Returns -1 if x < y, 0 if x == y, 1 if x > y, and -2 in
4536  * case of error
4537  */
4538 static int
xmlSchemaComparePreserveCollapseStrings(const xmlChar * x,const xmlChar * y,int invert)4539 xmlSchemaComparePreserveCollapseStrings(const xmlChar *x,
4540 				        const xmlChar *y,
4541 					int invert)
4542 {
4543     int tmp;
4544 
4545     /*
4546     * Skip leading blank chars of the collapsed string.
4547     */
4548     while IS_WSP_BLANK_CH(*y)
4549 	y++;
4550 
4551     while ((*x != 0) && (*y != 0)) {
4552 	if IS_WSP_BLANK_CH(*y) {
4553 	    if (! IS_WSP_SPACE_CH(*x)) {
4554 		/*
4555 		* The yv character would have been replaced to 0x20.
4556 		*/
4557 		if ((*x - 0x20) < 0) {
4558 		    if (invert)
4559 			return(1);
4560 		    else
4561 			return(-1);
4562 		} else {
4563 		    if (invert)
4564 			return(-1);
4565 		    else
4566 			return(1);
4567 		}
4568 	    }
4569 	    x++;
4570 	    y++;
4571 	    /*
4572 	    * Skip contiguous blank chars of the collapsed string.
4573 	    */
4574 	    while IS_WSP_BLANK_CH(*y)
4575 		y++;
4576 	} else {
4577 	    tmp = *x++ - *y++;
4578 	    if (tmp < 0) {
4579 		if (invert)
4580 		    return(1);
4581 		else
4582 		    return(-1);
4583 	    }
4584 	    if (tmp > 0) {
4585 		if (invert)
4586 		    return(-1);
4587 		else
4588 		    return(1);
4589 	    }
4590 	}
4591     }
4592     if (*x != 0) {
4593 	 if (invert)
4594 	     return(-1);
4595 	 else
4596 	     return(1);
4597     }
4598     if (*y != 0) {
4599 	/*
4600 	* Skip trailing blank chars of the collapsed string.
4601 	*/
4602 	while IS_WSP_BLANK_CH(*y)
4603 	    y++;
4604 	if (*y != 0) {
4605 	    if (invert)
4606 		return(1);
4607 	    else
4608 		return(-1);
4609 	}
4610     }
4611     return(0);
4612 }
4613 
4614 /**
4615  * xmlSchemaComparePreserveCollapseStrings:
4616  * @x:  a first string value
4617  * @y:  a second string value
4618  *
4619  * Compare 2 string for their normalized values.
4620  * @x is a string with whitespace of "preserve", @y is
4621  * a string with a whitespace of "collapse". I.e. @x could
4622  * be an "xsd:string" and @y an "xsd:normalizedString".
4623  *
4624  * Returns -1 if x < y, 0 if x == y, 1 if x > y, and -2 in
4625  * case of error
4626  */
4627 static int
xmlSchemaCompareReplaceCollapseStrings(const xmlChar * x,const xmlChar * y,int invert)4628 xmlSchemaCompareReplaceCollapseStrings(const xmlChar *x,
4629 				       const xmlChar *y,
4630 				       int invert)
4631 {
4632     int tmp;
4633 
4634     /*
4635     * Skip leading blank chars of the collapsed string.
4636     */
4637     while IS_WSP_BLANK_CH(*y)
4638 	y++;
4639 
4640     while ((*x != 0) && (*y != 0)) {
4641 	if IS_WSP_BLANK_CH(*y) {
4642 	    if (! IS_WSP_BLANK_CH(*x)) {
4643 		/*
4644 		* The yv character would have been replaced to 0x20.
4645 		*/
4646 		if ((*x - 0x20) < 0) {
4647 		    if (invert)
4648 			return(1);
4649 		    else
4650 			return(-1);
4651 		} else {
4652 		    if (invert)
4653 			return(-1);
4654 		    else
4655 			return(1);
4656 		}
4657 	    }
4658 	    x++;
4659 	    y++;
4660 	    /*
4661 	    * Skip contiguous blank chars of the collapsed string.
4662 	    */
4663 	    while IS_WSP_BLANK_CH(*y)
4664 		y++;
4665 	} else {
4666 	    if IS_WSP_BLANK_CH(*x) {
4667 		/*
4668 		* The xv character would have been replaced to 0x20.
4669 		*/
4670 		if ((0x20 - *y) < 0) {
4671 		    if (invert)
4672 			return(1);
4673 		    else
4674 			return(-1);
4675 		} else {
4676 		    if (invert)
4677 			return(-1);
4678 		    else
4679 			return(1);
4680 		}
4681 	    }
4682 	    tmp = *x++ - *y++;
4683 	    if (tmp < 0)
4684 		return(-1);
4685 	    if (tmp > 0)
4686 		return(1);
4687 	}
4688     }
4689     if (*x != 0) {
4690 	 if (invert)
4691 	     return(-1);
4692 	 else
4693 	     return(1);
4694     }
4695     if (*y != 0) {
4696 	/*
4697 	* Skip trailing blank chars of the collapsed string.
4698 	*/
4699 	while IS_WSP_BLANK_CH(*y)
4700 	    y++;
4701 	if (*y != 0) {
4702 	    if (invert)
4703 		return(1);
4704 	    else
4705 		return(-1);
4706 	}
4707     }
4708     return(0);
4709 }
4710 
4711 
4712 /**
4713  * xmlSchemaCompareReplacedStrings:
4714  * @x:  a first string value
4715  * @y:  a second string value
4716  *
4717  * Compare 2 string for their normalized values.
4718  *
4719  * Returns -1 if x < y, 0 if x == y, 1 if x > y, and -2 in
4720  * case of error
4721  */
4722 static int
xmlSchemaCompareReplacedStrings(const xmlChar * x,const xmlChar * y)4723 xmlSchemaCompareReplacedStrings(const xmlChar *x,
4724 				const xmlChar *y)
4725 {
4726     int tmp;
4727 
4728     while ((*x != 0) && (*y != 0)) {
4729 	if IS_WSP_BLANK_CH(*y) {
4730 	    if (! IS_WSP_BLANK_CH(*x)) {
4731 		if ((*x - 0x20) < 0)
4732 		    return(-1);
4733 		else
4734 		    return(1);
4735 	    }
4736 	} else {
4737 	    if IS_WSP_BLANK_CH(*x) {
4738 		if ((0x20 - *y) < 0)
4739 		    return(-1);
4740 		else
4741 		    return(1);
4742 	    }
4743 	    tmp = *x - *y;
4744 	    if (tmp < 0)
4745 		return(-1);
4746 	    if (tmp > 0)
4747 		return(1);
4748 	}
4749 	x++;
4750 	y++;
4751     }
4752     if (*x != 0)
4753         return(1);
4754     if (*y != 0)
4755         return(-1);
4756     return(0);
4757 }
4758 
4759 /**
4760  * xmlSchemaCompareNormStrings:
4761  * @x:  a first string value
4762  * @y:  a second string value
4763  *
4764  * Compare 2 string for their normalized values.
4765  *
4766  * Returns -1 if x < y, 0 if x == y, 1 if x > y, and -2 in
4767  * case of error
4768  */
4769 static int
xmlSchemaCompareNormStrings(const xmlChar * x,const xmlChar * y)4770 xmlSchemaCompareNormStrings(const xmlChar *x,
4771 			    const xmlChar *y) {
4772     int tmp;
4773 
4774     while (IS_BLANK_CH(*x)) x++;
4775     while (IS_BLANK_CH(*y)) y++;
4776     while ((*x != 0) && (*y != 0)) {
4777 	if (IS_BLANK_CH(*x)) {
4778 	    if (!IS_BLANK_CH(*y)) {
4779 		tmp = *x - *y;
4780 		return(tmp);
4781 	    }
4782 	    while (IS_BLANK_CH(*x)) x++;
4783 	    while (IS_BLANK_CH(*y)) y++;
4784 	} else {
4785 	    tmp = *x++ - *y++;
4786 	    if (tmp < 0)
4787 		return(-1);
4788 	    if (tmp > 0)
4789 		return(1);
4790 	}
4791     }
4792     if (*x != 0) {
4793 	while (IS_BLANK_CH(*x)) x++;
4794 	if (*x != 0)
4795 	    return(1);
4796     }
4797     if (*y != 0) {
4798 	while (IS_BLANK_CH(*y)) y++;
4799 	if (*y != 0)
4800 	    return(-1);
4801     }
4802     return(0);
4803 }
4804 
4805 /**
4806  * xmlSchemaCompareFloats:
4807  * @x:  a first float or double value
4808  * @y:  a second float or double value
4809  *
4810  * Compare 2 values
4811  *
4812  * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
4813  * case of error
4814  */
4815 static int
xmlSchemaCompareFloats(xmlSchemaValPtr x,xmlSchemaValPtr y)4816 xmlSchemaCompareFloats(xmlSchemaValPtr x, xmlSchemaValPtr y) {
4817     double d1, d2;
4818 
4819     if ((x == NULL) || (y == NULL))
4820 	return(-2);
4821 
4822     /*
4823      * Cast everything to doubles.
4824      */
4825     if (x->type == XML_SCHEMAS_DOUBLE)
4826 	d1 = x->value.d;
4827     else if (x->type == XML_SCHEMAS_FLOAT)
4828 	d1 = x->value.f;
4829     else
4830 	return(-2);
4831 
4832     if (y->type == XML_SCHEMAS_DOUBLE)
4833 	d2 = y->value.d;
4834     else if (y->type == XML_SCHEMAS_FLOAT)
4835 	d2 = y->value.f;
4836     else
4837 	return(-2);
4838 
4839     /*
4840      * Check for special cases.
4841      */
4842     if (isnan(d1)) {
4843 	if (isnan(d2))
4844 	    return(0);
4845 	return(1);
4846     }
4847     if (isnan(d2))
4848 	return(-1);
4849 
4850     /*
4851      * basic tests, the last one we should have equality, but
4852      * portability is more important than speed and handling
4853      * NaN or Inf in a portable way is always a challenge, so ...
4854      */
4855     if (d1 < d2)
4856 	return(-1);
4857     if (d1 > d2)
4858 	return(1);
4859     if (d1 == d2)
4860 	return(0);
4861     return(2);
4862 }
4863 
4864 /**
4865  * xmlSchemaCompareValues:
4866  * @x:  a first value
4867  * @xvalue: the first value as a string (optional)
4868  * @xwtsp: the whitespace type
4869  * @y:  a second value
4870  * @xvalue: the second value as a string (optional)
4871  * @ywtsp: the whitespace type
4872  *
4873  * Compare 2 values
4874  *
4875  * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, 3 if not
4876  * comparable and -2 in case of error
4877  */
4878 static int
xmlSchemaCompareValuesInternal(xmlSchemaValType xtype,xmlSchemaValPtr x,const xmlChar * xvalue,xmlSchemaWhitespaceValueType xws,xmlSchemaValType ytype,xmlSchemaValPtr y,const xmlChar * yvalue,xmlSchemaWhitespaceValueType yws)4879 xmlSchemaCompareValuesInternal(xmlSchemaValType xtype,
4880 			       xmlSchemaValPtr x,
4881 			       const xmlChar *xvalue,
4882 			       xmlSchemaWhitespaceValueType xws,
4883 			       xmlSchemaValType ytype,
4884 			       xmlSchemaValPtr y,
4885 			       const xmlChar *yvalue,
4886 			       xmlSchemaWhitespaceValueType yws)
4887 {
4888     switch (xtype) {
4889 	case XML_SCHEMAS_UNKNOWN:
4890 	case XML_SCHEMAS_ANYTYPE:
4891 	    return(-2);
4892         case XML_SCHEMAS_INTEGER:
4893         case XML_SCHEMAS_NPINTEGER:
4894         case XML_SCHEMAS_NINTEGER:
4895         case XML_SCHEMAS_NNINTEGER:
4896         case XML_SCHEMAS_PINTEGER:
4897         case XML_SCHEMAS_INT:
4898         case XML_SCHEMAS_UINT:
4899         case XML_SCHEMAS_LONG:
4900         case XML_SCHEMAS_ULONG:
4901         case XML_SCHEMAS_SHORT:
4902         case XML_SCHEMAS_USHORT:
4903         case XML_SCHEMAS_BYTE:
4904         case XML_SCHEMAS_UBYTE:
4905 	case XML_SCHEMAS_DECIMAL:
4906 	    if ((x == NULL) || (y == NULL))
4907 		return(-2);
4908 	    if (ytype == xtype)
4909 		return(xmlSchemaCompareDecimals(x, y));
4910 	    if ((ytype == XML_SCHEMAS_DECIMAL) ||
4911 		(ytype == XML_SCHEMAS_INTEGER) ||
4912 		(ytype == XML_SCHEMAS_NPINTEGER) ||
4913 		(ytype == XML_SCHEMAS_NINTEGER) ||
4914 		(ytype == XML_SCHEMAS_NNINTEGER) ||
4915 		(ytype == XML_SCHEMAS_PINTEGER) ||
4916 		(ytype == XML_SCHEMAS_INT) ||
4917 		(ytype == XML_SCHEMAS_UINT) ||
4918 		(ytype == XML_SCHEMAS_LONG) ||
4919 		(ytype == XML_SCHEMAS_ULONG) ||
4920 		(ytype == XML_SCHEMAS_SHORT) ||
4921 		(ytype == XML_SCHEMAS_USHORT) ||
4922 		(ytype == XML_SCHEMAS_BYTE) ||
4923 		(ytype == XML_SCHEMAS_UBYTE))
4924 		return(xmlSchemaCompareDecimals(x, y));
4925 	    return(-2);
4926         case XML_SCHEMAS_DURATION:
4927 	    if ((x == NULL) || (y == NULL))
4928 		return(-2);
4929 	    if (ytype == XML_SCHEMAS_DURATION)
4930                 return(xmlSchemaCompareDurations(x, y));
4931             return(-2);
4932         case XML_SCHEMAS_TIME:
4933         case XML_SCHEMAS_GDAY:
4934         case XML_SCHEMAS_GMONTH:
4935         case XML_SCHEMAS_GMONTHDAY:
4936         case XML_SCHEMAS_GYEAR:
4937         case XML_SCHEMAS_GYEARMONTH:
4938         case XML_SCHEMAS_DATE:
4939         case XML_SCHEMAS_DATETIME:
4940 	    if ((x == NULL) || (y == NULL))
4941 		return(-2);
4942             if ((ytype == XML_SCHEMAS_DATETIME)  ||
4943                 (ytype == XML_SCHEMAS_TIME)      ||
4944                 (ytype == XML_SCHEMAS_GDAY)      ||
4945                 (ytype == XML_SCHEMAS_GMONTH)    ||
4946                 (ytype == XML_SCHEMAS_GMONTHDAY) ||
4947                 (ytype == XML_SCHEMAS_GYEAR)     ||
4948                 (ytype == XML_SCHEMAS_DATE)      ||
4949                 (ytype == XML_SCHEMAS_GYEARMONTH))
4950                 return (xmlSchemaCompareDates(x, y));
4951             return (-2);
4952 	/*
4953 	* Note that we will support comparison of string types against
4954 	* anySimpleType as well.
4955 	*/
4956 	case XML_SCHEMAS_ANYSIMPLETYPE:
4957 	case XML_SCHEMAS_STRING:
4958         case XML_SCHEMAS_NORMSTRING:
4959         case XML_SCHEMAS_TOKEN:
4960         case XML_SCHEMAS_LANGUAGE:
4961         case XML_SCHEMAS_NMTOKEN:
4962         case XML_SCHEMAS_NAME:
4963         case XML_SCHEMAS_NCNAME:
4964         case XML_SCHEMAS_ID:
4965         case XML_SCHEMAS_IDREF:
4966         case XML_SCHEMAS_ENTITY:
4967         case XML_SCHEMAS_ANYURI:
4968 	{
4969 	    const xmlChar *xv, *yv;
4970 
4971 	    if (x == NULL)
4972 		xv = xvalue;
4973 	    else
4974 		xv = x->value.str;
4975 	    if (y == NULL)
4976 		yv = yvalue;
4977 	    else
4978 		yv = y->value.str;
4979 	    /*
4980 	    * TODO: Compare those against QName.
4981 	    */
4982 	    if (ytype == XML_SCHEMAS_QNAME) {
4983 		/* TODO */
4984 		if (y == NULL)
4985 		    return(-2);
4986 		return (-2);
4987 	    }
4988             if ((ytype == XML_SCHEMAS_ANYSIMPLETYPE) ||
4989 		(ytype == XML_SCHEMAS_STRING) ||
4990 		(ytype == XML_SCHEMAS_NORMSTRING) ||
4991                 (ytype == XML_SCHEMAS_TOKEN) ||
4992                 (ytype == XML_SCHEMAS_LANGUAGE) ||
4993                 (ytype == XML_SCHEMAS_NMTOKEN) ||
4994                 (ytype == XML_SCHEMAS_NAME) ||
4995                 (ytype == XML_SCHEMAS_NCNAME) ||
4996                 (ytype == XML_SCHEMAS_ID) ||
4997                 (ytype == XML_SCHEMAS_IDREF) ||
4998                 (ytype == XML_SCHEMAS_ENTITY) ||
4999                 (ytype == XML_SCHEMAS_ANYURI)) {
5000 
5001 		if (xws == XML_SCHEMA_WHITESPACE_PRESERVE) {
5002 
5003 		    if (yws == XML_SCHEMA_WHITESPACE_PRESERVE) {
5004 			/* TODO: What about x < y or x > y. */
5005 			if (xmlStrEqual(xv, yv))
5006 			    return (0);
5007 			else
5008 			    return (2);
5009 		    } else if (yws == XML_SCHEMA_WHITESPACE_REPLACE)
5010 			return (xmlSchemaComparePreserveReplaceStrings(xv, yv, 0));
5011 		    else if (yws == XML_SCHEMA_WHITESPACE_COLLAPSE)
5012 			return (xmlSchemaComparePreserveCollapseStrings(xv, yv, 0));
5013 
5014 		} else if (xws == XML_SCHEMA_WHITESPACE_REPLACE) {
5015 
5016 		    if (yws == XML_SCHEMA_WHITESPACE_PRESERVE)
5017 			return (xmlSchemaComparePreserveReplaceStrings(yv, xv, 1));
5018 		    if (yws == XML_SCHEMA_WHITESPACE_REPLACE)
5019 			return (xmlSchemaCompareReplacedStrings(xv, yv));
5020 		    if (yws == XML_SCHEMA_WHITESPACE_COLLAPSE)
5021 			return (xmlSchemaCompareReplaceCollapseStrings(xv, yv, 0));
5022 
5023 		} else if (xws == XML_SCHEMA_WHITESPACE_COLLAPSE) {
5024 
5025 		    if (yws == XML_SCHEMA_WHITESPACE_PRESERVE)
5026 			return (xmlSchemaComparePreserveCollapseStrings(yv, xv, 1));
5027 		    if (yws == XML_SCHEMA_WHITESPACE_REPLACE)
5028 			return (xmlSchemaCompareReplaceCollapseStrings(yv, xv, 1));
5029 		    if (yws == XML_SCHEMA_WHITESPACE_COLLAPSE)
5030 			return (xmlSchemaCompareNormStrings(xv, yv));
5031 		} else
5032 		    return (-2);
5033 
5034 	    }
5035             return (-2);
5036 	}
5037         case XML_SCHEMAS_QNAME:
5038 	case XML_SCHEMAS_NOTATION:
5039 	    if ((x == NULL) || (y == NULL))
5040 		return(-2);
5041             if ((ytype == XML_SCHEMAS_QNAME) ||
5042 		(ytype == XML_SCHEMAS_NOTATION)) {
5043 		if ((xmlStrEqual(x->value.qname.name, y->value.qname.name)) &&
5044 		    (xmlStrEqual(x->value.qname.uri, y->value.qname.uri)))
5045 		    return(0);
5046 		return(2);
5047 	    }
5048 	    return (-2);
5049         case XML_SCHEMAS_FLOAT:
5050         case XML_SCHEMAS_DOUBLE:
5051 	    if ((x == NULL) || (y == NULL))
5052 		return(-2);
5053             if ((ytype == XML_SCHEMAS_FLOAT) ||
5054                 (ytype == XML_SCHEMAS_DOUBLE))
5055                 return (xmlSchemaCompareFloats(x, y));
5056             return (-2);
5057         case XML_SCHEMAS_BOOLEAN:
5058 	    if ((x == NULL) || (y == NULL))
5059 		return(-2);
5060             if (ytype == XML_SCHEMAS_BOOLEAN) {
5061 		if (x->value.b == y->value.b)
5062 		    return(0);
5063 		if (x->value.b == 0)
5064 		    return(-1);
5065 		return(1);
5066 	    }
5067 	    return (-2);
5068         case XML_SCHEMAS_HEXBINARY:
5069 	    if ((x == NULL) || (y == NULL))
5070 		return(-2);
5071             if (ytype == XML_SCHEMAS_HEXBINARY) {
5072 	        if (x->value.hex.total == y->value.hex.total) {
5073 		    int ret = xmlStrcmp(x->value.hex.str, y->value.hex.str);
5074 		    if (ret > 0)
5075 			return(1);
5076 		    else if (ret == 0)
5077 			return(0);
5078 		}
5079 		else if (x->value.hex.total > y->value.hex.total)
5080 		    return(1);
5081 
5082 		return(-1);
5083             }
5084             return (-2);
5085         case XML_SCHEMAS_BASE64BINARY:
5086 	    if ((x == NULL) || (y == NULL))
5087 		return(-2);
5088             if (ytype == XML_SCHEMAS_BASE64BINARY) {
5089                 if (x->value.base64.total == y->value.base64.total) {
5090                     int ret = xmlStrcmp(x->value.base64.str,
5091 		                        y->value.base64.str);
5092                     if (ret > 0)
5093                         return(1);
5094                     else if (ret == 0)
5095                         return(0);
5096 		    else
5097 		        return(-1);
5098                 }
5099                 else if (x->value.base64.total > y->value.base64.total)
5100                     return(1);
5101                 else
5102                     return(-1);
5103             }
5104             return (-2);
5105         case XML_SCHEMAS_IDREFS:
5106         case XML_SCHEMAS_ENTITIES:
5107         case XML_SCHEMAS_NMTOKENS:
5108 	    /* TODO */
5109 	    break;
5110     }
5111     return -2;
5112 }
5113 
5114 /**
5115  * xmlSchemaCompareValues:
5116  * @x:  a first value
5117  * @y:  a second value
5118  *
5119  * Compare 2 values
5120  *
5121  * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
5122  * case of error
5123  */
5124 int
xmlSchemaCompareValues(xmlSchemaValPtr x,xmlSchemaValPtr y)5125 xmlSchemaCompareValues(xmlSchemaValPtr x, xmlSchemaValPtr y) {
5126     xmlSchemaWhitespaceValueType xws, yws;
5127 
5128     if ((x == NULL) || (y == NULL))
5129         return(-2);
5130     if (x->type == XML_SCHEMAS_STRING)
5131 	xws = XML_SCHEMA_WHITESPACE_PRESERVE;
5132     else if (x->type == XML_SCHEMAS_NORMSTRING)
5133         xws = XML_SCHEMA_WHITESPACE_REPLACE;
5134     else
5135         xws = XML_SCHEMA_WHITESPACE_COLLAPSE;
5136 
5137     if (y->type == XML_SCHEMAS_STRING)
5138 	yws = XML_SCHEMA_WHITESPACE_PRESERVE;
5139     else if (y->type == XML_SCHEMAS_NORMSTRING)
5140         yws = XML_SCHEMA_WHITESPACE_REPLACE;
5141     else
5142         yws = XML_SCHEMA_WHITESPACE_COLLAPSE;
5143 
5144     return(xmlSchemaCompareValuesInternal(x->type, x, NULL, xws, y->type,
5145 	y, NULL, yws));
5146 }
5147 
5148 /**
5149  * xmlSchemaCompareValuesWhtsp:
5150  * @x:  a first value
5151  * @xws: the whitespace value of x
5152  * @y:  a second value
5153  * @yws: the whitespace value of y
5154  *
5155  * Compare 2 values
5156  *
5157  * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
5158  * case of error
5159  */
5160 int
xmlSchemaCompareValuesWhtsp(xmlSchemaValPtr x,xmlSchemaWhitespaceValueType xws,xmlSchemaValPtr y,xmlSchemaWhitespaceValueType yws)5161 xmlSchemaCompareValuesWhtsp(xmlSchemaValPtr x,
5162 			    xmlSchemaWhitespaceValueType xws,
5163 			    xmlSchemaValPtr y,
5164 			    xmlSchemaWhitespaceValueType yws)
5165 {
5166     if ((x == NULL) || (y == NULL))
5167 	return(-2);
5168     return(xmlSchemaCompareValuesInternal(x->type, x, NULL, xws, y->type,
5169 	y, NULL, yws));
5170 }
5171 
5172 /**
5173  * xmlSchemaCompareValuesWhtspExt:
5174  * @x:  a first value
5175  * @xws: the whitespace value of x
5176  * @y:  a second value
5177  * @yws: the whitespace value of y
5178  *
5179  * Compare 2 values
5180  *
5181  * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
5182  * case of error
5183  */
5184 static int
xmlSchemaCompareValuesWhtspExt(xmlSchemaValType xtype,xmlSchemaValPtr x,const xmlChar * xvalue,xmlSchemaWhitespaceValueType xws,xmlSchemaValType ytype,xmlSchemaValPtr y,const xmlChar * yvalue,xmlSchemaWhitespaceValueType yws)5185 xmlSchemaCompareValuesWhtspExt(xmlSchemaValType xtype,
5186 			       xmlSchemaValPtr x,
5187 			       const xmlChar *xvalue,
5188 			       xmlSchemaWhitespaceValueType xws,
5189 			       xmlSchemaValType ytype,
5190 			       xmlSchemaValPtr y,
5191 			       const xmlChar *yvalue,
5192 			       xmlSchemaWhitespaceValueType yws)
5193 {
5194     return(xmlSchemaCompareValuesInternal(xtype, x, xvalue, xws, ytype, y,
5195 	yvalue, yws));
5196 }
5197 
5198 /**
5199  * xmlSchemaNormLen:
5200  * @value:  a string
5201  *
5202  * Computes the UTF8 length of the normalized value of the string
5203  *
5204  * Returns the length or -1 in case of error.
5205  */
5206 static int
xmlSchemaNormLen(const xmlChar * value)5207 xmlSchemaNormLen(const xmlChar *value) {
5208     const xmlChar *utf;
5209     int ret = 0;
5210 
5211     if (value == NULL)
5212 	return(-1);
5213     utf = value;
5214     while (IS_BLANK_CH(*utf)) utf++;
5215     while (*utf != 0) {
5216 	if (utf[0] & 0x80) {
5217 	    if ((utf[1] & 0xc0) != 0x80)
5218 		return(-1);
5219 	    if ((utf[0] & 0xe0) == 0xe0) {
5220 		if ((utf[2] & 0xc0) != 0x80)
5221 		    return(-1);
5222 		if ((utf[0] & 0xf0) == 0xf0) {
5223 		    if ((utf[0] & 0xf8) != 0xf0 || (utf[3] & 0xc0) != 0x80)
5224 			return(-1);
5225 		    utf += 4;
5226 		} else {
5227 		    utf += 3;
5228 		}
5229 	    } else {
5230 		utf += 2;
5231 	    }
5232 	} else if (IS_BLANK_CH(*utf)) {
5233 	    while (IS_BLANK_CH(*utf)) utf++;
5234 	    if (*utf == 0)
5235 		break;
5236 	} else {
5237 	    utf++;
5238 	}
5239 	ret++;
5240     }
5241     return(ret);
5242 }
5243 
5244 /**
5245  * xmlSchemaGetFacetValueAsULong:
5246  * @facet: an schemas type facet
5247  *
5248  * Extract the value of a facet
5249  *
5250  * Returns the value as a long
5251  */
5252 unsigned long
xmlSchemaGetFacetValueAsULong(xmlSchemaFacetPtr facet)5253 xmlSchemaGetFacetValueAsULong(xmlSchemaFacetPtr facet)
5254 {
5255     /*
5256     * TODO: Check if this is a decimal.
5257     */
5258     char *discard;
5259     if (facet == NULL || facet->val == NULL)
5260         return 0;
5261     return strtoul((const char*)facet->val->value.decimal.str+1, &discard, 10);
5262 }
5263 
5264 /**
5265  * xmlSchemaValidateListSimpleTypeFacet:
5266  * @facet:  the facet to check
5267  * @value:  the lexical repr of the value to validate
5268  * @actualLen:  the number of list items
5269  * @expectedLen: the resulting expected number of list items
5270  *
5271  * Checks the value of a list simple type against a facet.
5272  *
5273  * Returns 0 if the value is valid, a positive error code
5274  * number otherwise and -1 in case of an internal error.
5275  */
5276 int
xmlSchemaValidateListSimpleTypeFacet(xmlSchemaFacetPtr facet,const xmlChar * value,unsigned long actualLen,unsigned long * expectedLen)5277 xmlSchemaValidateListSimpleTypeFacet(xmlSchemaFacetPtr facet,
5278 				     const xmlChar *value,
5279 				     unsigned long actualLen,
5280 				     unsigned long *expectedLen)
5281 {
5282     if (facet == NULL)
5283         return(-1);
5284     /*
5285     * TODO: Check if this will work with large numbers.
5286     * (compare value.decimal.mi and value.decimal.hi as well?).
5287     */
5288     if (facet->type == XML_SCHEMA_FACET_LENGTH) {
5289         if (actualLen != xmlSchemaGetFacetValueAsULong(facet)) {
5290 	    if (expectedLen != NULL)
5291                 *expectedLen = xmlSchemaGetFacetValueAsULong(facet);
5292 	    return (XML_SCHEMAV_CVC_LENGTH_VALID);
5293 	}
5294     } else if (facet->type == XML_SCHEMA_FACET_MINLENGTH) {
5295         if (actualLen < xmlSchemaGetFacetValueAsULong(facet)) {
5296 	    if (expectedLen != NULL)
5297                 *expectedLen = xmlSchemaGetFacetValueAsULong(facet);
5298 	    return (XML_SCHEMAV_CVC_MINLENGTH_VALID);
5299 	}
5300     } else if (facet->type == XML_SCHEMA_FACET_MAXLENGTH) {
5301         if (actualLen > xmlSchemaGetFacetValueAsULong(facet)) {
5302 	    if (expectedLen != NULL)
5303                 *expectedLen = xmlSchemaGetFacetValueAsULong(facet);
5304 	    return (XML_SCHEMAV_CVC_MAXLENGTH_VALID);
5305 	}
5306     } else
5307 	/*
5308 	* NOTE: That we can pass NULL as xmlSchemaValPtr to
5309 	* xmlSchemaValidateFacet, since the remaining facet types
5310 	* are: XML_SCHEMA_FACET_PATTERN, XML_SCHEMA_FACET_ENUMERATION.
5311 	*/
5312 	return(xmlSchemaValidateFacet(NULL, facet, value, NULL));
5313     return (0);
5314 }
5315 
5316 /**
5317  * xmlSchemaValidateLengthFacet:
5318  * @type:  the built-in type
5319  * @facet:  the facet to check
5320  * @value:  the lexical repr. of the value to be validated
5321  * @val:  the precomputed value
5322  * @ws: the whitespace type of the value
5323  * @length: the actual length of the value
5324  *
5325  * Checka a value against a "length", "minLength" and "maxLength"
5326  * facet; sets @length to the computed length of @value.
5327  *
5328  * Returns 0 if the value is valid, a positive error code
5329  * otherwise and -1 in case of an internal or API error.
5330  */
5331 static int
xmlSchemaValidateLengthFacetInternal(xmlSchemaFacetPtr facet,xmlSchemaValType valType,const xmlChar * value,xmlSchemaValPtr val,unsigned long * length,xmlSchemaWhitespaceValueType ws)5332 xmlSchemaValidateLengthFacetInternal(xmlSchemaFacetPtr facet,
5333 				     xmlSchemaValType valType,
5334 				     const xmlChar *value,
5335 				     xmlSchemaValPtr val,
5336 				     unsigned long *length,
5337 				     xmlSchemaWhitespaceValueType ws)
5338 {
5339     unsigned int len = 0;
5340 
5341     if ((length == NULL) || (facet == NULL))
5342         return (-1);
5343     *length = 0;
5344     if ((facet->type != XML_SCHEMA_FACET_LENGTH) &&
5345 	(facet->type != XML_SCHEMA_FACET_MAXLENGTH) &&
5346 	(facet->type != XML_SCHEMA_FACET_MINLENGTH))
5347 	return (-1);
5348 
5349     /*
5350     * TODO: length, maxLength and minLength must be of type
5351     * nonNegativeInteger only. Check if decimal is used somehow.
5352     */
5353     if ((facet->val == NULL) ||
5354 	((facet->val->type != XML_SCHEMAS_DECIMAL) &&
5355 	 (facet->val->type != XML_SCHEMAS_NNINTEGER)) ||
5356 	!(xmlSchemaValDecimalIsInteger(&facet->val->value.decimal)))
5357  {
5358 	return(-1);
5359     }
5360     if ((val != NULL) && (val->type == XML_SCHEMAS_HEXBINARY))
5361 	len = val->value.hex.total;
5362     else if ((val != NULL) && (val->type == XML_SCHEMAS_BASE64BINARY))
5363 	len = val->value.base64.total;
5364     else {
5365 	switch (valType) {
5366 	    case XML_SCHEMAS_STRING:
5367 	    case XML_SCHEMAS_NORMSTRING:
5368 		if (ws == XML_SCHEMA_WHITESPACE_UNKNOWN) {
5369 		    /*
5370 		    * This is to ensure API compatibility with the old
5371 		    * xmlSchemaValidateLengthFacet(). Anyway, this was and
5372 		    * is not the correct handling.
5373 		    * TODO: Get rid of this case somehow.
5374 		    */
5375 		    if (valType == XML_SCHEMAS_STRING)
5376 			len = xmlUTF8Strlen(value);
5377 		    else
5378 			len = xmlSchemaNormLen(value);
5379 		} else if (value != NULL) {
5380 		    if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
5381 			len = xmlSchemaNormLen(value);
5382 		    else
5383 		    /*
5384 		    * Should be OK for "preserve" as well.
5385 		    */
5386 		    len = xmlUTF8Strlen(value);
5387 		}
5388 		break;
5389 	    case XML_SCHEMAS_IDREF:
5390 	    case XML_SCHEMAS_TOKEN:
5391 	    case XML_SCHEMAS_LANGUAGE:
5392 	    case XML_SCHEMAS_NMTOKEN:
5393 	    case XML_SCHEMAS_NAME:
5394 	    case XML_SCHEMAS_NCNAME:
5395 	    case XML_SCHEMAS_ID:
5396 		/*
5397 		* FIXME: What exactly to do with anyURI?
5398 		*/
5399 	    case XML_SCHEMAS_ANYURI:
5400 		if (value != NULL)
5401 		    len = xmlSchemaNormLen(value);
5402 		break;
5403 	    case XML_SCHEMAS_QNAME:
5404 	    case XML_SCHEMAS_NOTATION:
5405 		/*
5406 		* For QName and NOTATION, those facets are
5407 		* deprecated and should be ignored.
5408 		*/
5409 		return (0);
5410 	    default:
5411 		/* TODO */
5412                 break;
5413 	}
5414     }
5415     *length = (unsigned long) len;
5416     /*
5417     * TODO: Return the whole expected value. (This may be possible now with xmlSchemaValDecimalCompareWithInteger)
5418     */
5419     if (facet->type == XML_SCHEMA_FACET_LENGTH) {
5420         if (len != xmlSchemaGetFacetValueAsULong(facet))
5421 	    return(XML_SCHEMAV_CVC_LENGTH_VALID);
5422     } else if (facet->type == XML_SCHEMA_FACET_MINLENGTH) {
5423         if (len < xmlSchemaGetFacetValueAsULong(facet))
5424 	    return(XML_SCHEMAV_CVC_MINLENGTH_VALID);
5425     } else {
5426         if (len > xmlSchemaGetFacetValueAsULong(facet))
5427 	    return(XML_SCHEMAV_CVC_MAXLENGTH_VALID);
5428     }
5429 
5430     return (0);
5431 }
5432 
5433 /**
5434  * xmlSchemaValidateLengthFacet:
5435  * @type:  the built-in type
5436  * @facet:  the facet to check
5437  * @value:  the lexical repr. of the value to be validated
5438  * @val:  the precomputed value
5439  * @length: the actual length of the value
5440  *
5441  * Checka a value against a "length", "minLength" and "maxLength"
5442  * facet; sets @length to the computed length of @value.
5443  *
5444  * Returns 0 if the value is valid, a positive error code
5445  * otherwise and -1 in case of an internal or API error.
5446  */
5447 int
xmlSchemaValidateLengthFacet(xmlSchemaTypePtr type,xmlSchemaFacetPtr facet,const xmlChar * value,xmlSchemaValPtr val,unsigned long * length)5448 xmlSchemaValidateLengthFacet(xmlSchemaTypePtr type,
5449 			     xmlSchemaFacetPtr facet,
5450 			     const xmlChar *value,
5451 			     xmlSchemaValPtr val,
5452 			     unsigned long *length)
5453 {
5454     if (type == NULL)
5455         return(-1);
5456     return (xmlSchemaValidateLengthFacetInternal(facet,
5457 	type->builtInType, value, val, length,
5458 	XML_SCHEMA_WHITESPACE_UNKNOWN));
5459 }
5460 
5461 /**
5462  * xmlSchemaValidateLengthFacetWhtsp:
5463  * @facet:  the facet to check
5464  * @valType:  the built-in type
5465  * @value:  the lexical repr. of the value to be validated
5466  * @val:  the precomputed value
5467  * @ws: the whitespace type of the value
5468  * @length: the actual length of the value
5469  *
5470  * Checka a value against a "length", "minLength" and "maxLength"
5471  * facet; sets @length to the computed length of @value.
5472  *
5473  * Returns 0 if the value is valid, a positive error code
5474  * otherwise and -1 in case of an internal or API error.
5475  */
5476 int
xmlSchemaValidateLengthFacetWhtsp(xmlSchemaFacetPtr facet,xmlSchemaValType valType,const xmlChar * value,xmlSchemaValPtr val,unsigned long * length,xmlSchemaWhitespaceValueType ws)5477 xmlSchemaValidateLengthFacetWhtsp(xmlSchemaFacetPtr facet,
5478 				  xmlSchemaValType valType,
5479 				  const xmlChar *value,
5480 				  xmlSchemaValPtr val,
5481 				  unsigned long *length,
5482 				  xmlSchemaWhitespaceValueType ws)
5483 {
5484     return (xmlSchemaValidateLengthFacetInternal(facet, valType, value, val,
5485 	length, ws));
5486 }
5487 
5488 /**
5489  * xmlSchemaValidateFacetInternal:
5490  * @facet:  the facet to check
5491  * @fws: the whitespace type of the facet's value
5492  * @valType: the built-in type of the value
5493  * @value:  the lexical repr of the value to validate
5494  * @val:  the precomputed value
5495  * @ws: the whitespace type of the value
5496  *
5497  * Check a value against a facet condition
5498  *
5499  * Returns 0 if the element is schemas valid, a positive error code
5500  *     number otherwise and -1 in case of internal or API error.
5501  */
5502 static int
xmlSchemaValidateFacetInternal(xmlSchemaFacetPtr facet,xmlSchemaWhitespaceValueType fws,xmlSchemaValType valType,const xmlChar * value,xmlSchemaValPtr val,xmlSchemaWhitespaceValueType ws)5503 xmlSchemaValidateFacetInternal(xmlSchemaFacetPtr facet,
5504 			       xmlSchemaWhitespaceValueType fws,
5505 			       xmlSchemaValType valType,
5506 			       const xmlChar *value,
5507 			       xmlSchemaValPtr val,
5508 			       xmlSchemaWhitespaceValueType ws)
5509 {
5510     int ret;
5511 
5512     if (facet == NULL)
5513 	return(-1);
5514 
5515     switch (facet->type) {
5516 	case XML_SCHEMA_FACET_PATTERN:
5517 	    /*
5518 	    * NOTE that for patterns, the @value needs to be the normalized
5519 	    * value, *not* the lexical initial value or the canonical value.
5520 	    */
5521 	    if (value == NULL)
5522 		return(-1);
5523 	    /*
5524 	    * If string-derived type, regexp must be tested on the value space of
5525 	    * the datatype.
5526 	    * See https://www.w3.org/TR/xmlschema-2/#rf-pattern
5527 	    */
5528 	    if (val &&
5529                 val->value.str &&
5530                 ((val->type >= XML_SCHEMAS_STRING &&
5531                   val->type <= XML_SCHEMAS_NORMSTRING) ||
5532                  (val->type >= XML_SCHEMAS_TOKEN &&
5533                   val->type <= XML_SCHEMAS_ENTITIES &&
5534                   val->type != XML_SCHEMAS_QNAME))) {
5535                 value = val->value.str;
5536             }
5537 	    ret = xmlRegexpExec(facet->regexp, value);
5538 	    if (ret == 1)
5539 		return(0);
5540 	    if (ret == 0)
5541 		return(XML_SCHEMAV_CVC_PATTERN_VALID);
5542 	    return(ret);
5543 	case XML_SCHEMA_FACET_MAXEXCLUSIVE:
5544 	    ret = xmlSchemaCompareValues(val, facet->val);
5545 	    if (ret == -2)
5546 		return(-1);
5547 	    if (ret == -1)
5548 		return(0);
5549 	    return(XML_SCHEMAV_CVC_MAXEXCLUSIVE_VALID);
5550 	case XML_SCHEMA_FACET_MAXINCLUSIVE:
5551 	    ret = xmlSchemaCompareValues(val, facet->val);
5552 	    if (ret == -2)
5553 		return(-1);
5554 	    if ((ret == -1) || (ret == 0))
5555 		return(0);
5556 	    return(XML_SCHEMAV_CVC_MAXINCLUSIVE_VALID);
5557 	case XML_SCHEMA_FACET_MINEXCLUSIVE:
5558 	    ret = xmlSchemaCompareValues(val, facet->val);
5559 	    if (ret == -2)
5560 		return(-1);
5561 	    if (ret == 1)
5562 		return(0);
5563 	    return(XML_SCHEMAV_CVC_MINEXCLUSIVE_VALID);
5564 	case XML_SCHEMA_FACET_MININCLUSIVE:
5565 	    ret = xmlSchemaCompareValues(val, facet->val);
5566 	    if (ret == -2)
5567 		return(-1);
5568 	    if ((ret == 1) || (ret == 0))
5569 		return(0);
5570 	    return(XML_SCHEMAV_CVC_MININCLUSIVE_VALID);
5571 	case XML_SCHEMA_FACET_WHITESPACE:
5572 	    /* TODO whitespaces */
5573 	    /*
5574 	    * NOTE: Whitespace should be handled to normalize
5575 	    * the value to be validated against a the facets;
5576 	    * not to normalize the value in-between.
5577 	    */
5578 	    return(0);
5579 	case  XML_SCHEMA_FACET_ENUMERATION:
5580 	    if (ws == XML_SCHEMA_WHITESPACE_UNKNOWN) {
5581 		/*
5582 		* This is to ensure API compatibility with the old
5583 		* xmlSchemaValidateFacet().
5584 		* TODO: Get rid of this case.
5585 		*/
5586 		if ((facet->value != NULL) &&
5587 		    (xmlStrEqual(facet->value, value)))
5588 		    return(0);
5589 	    } else {
5590 		ret = xmlSchemaCompareValuesWhtspExt(facet->val->type,
5591 		    facet->val, facet->value, fws, valType, val,
5592 		    value, ws);
5593 		if (ret == -2)
5594 		    return(-1);
5595 		if (ret == 0)
5596 		    return(0);
5597 	    }
5598 	    return(XML_SCHEMAV_CVC_ENUMERATION_VALID);
5599 	case XML_SCHEMA_FACET_LENGTH:
5600 	    /*
5601 	    * SPEC (1.3) "if {primitive type definition} is QName or NOTATION,
5602 	    * then any {value} is facet-valid."
5603 	    */
5604 	    if ((valType == XML_SCHEMAS_QNAME) ||
5605 		(valType == XML_SCHEMAS_NOTATION))
5606 		return (0);
5607             /* Falls through. */
5608 	case XML_SCHEMA_FACET_MAXLENGTH:
5609 	case XML_SCHEMA_FACET_MINLENGTH: {
5610 	    unsigned int len = 0;
5611 
5612 	    if ((valType == XML_SCHEMAS_QNAME) ||
5613 		(valType == XML_SCHEMAS_NOTATION))
5614 		return (0);
5615 	    /*
5616 	    * TODO: length, maxLength and minLength must be of type
5617 	    * nonNegativeInteger only. Check if decimal is used somehow.
5618 	    */
5619 	    if ((facet->val == NULL) ||
5620 		((facet->val->type != XML_SCHEMAS_DECIMAL) &&
5621 		 (facet->val->type != XML_SCHEMAS_NNINTEGER)) ||
5622 		!xmlSchemaValDecimalIsInteger(&facet->val->value.decimal)) {
5623 		return(-1);
5624 	    }
5625 	    if ((val != NULL) && (val->type == XML_SCHEMAS_HEXBINARY))
5626 		len = val->value.hex.total;
5627 	    else if ((val != NULL) && (val->type == XML_SCHEMAS_BASE64BINARY))
5628 		len = val->value.base64.total;
5629 	    else {
5630 		switch (valType) {
5631 		    case XML_SCHEMAS_STRING:
5632 		    case XML_SCHEMAS_NORMSTRING:
5633 			if (ws == XML_SCHEMA_WHITESPACE_UNKNOWN) {
5634 			    /*
5635 			    * This is to ensure API compatibility with the old
5636 			    * xmlSchemaValidateFacet(). Anyway, this was and
5637 			    * is not the correct handling.
5638 			    * TODO: Get rid of this case somehow.
5639 			    */
5640 			    if (valType == XML_SCHEMAS_STRING)
5641 				len = xmlUTF8Strlen(value);
5642 			    else
5643 				len = xmlSchemaNormLen(value);
5644 			} else if (value != NULL) {
5645 			    if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
5646 				len = xmlSchemaNormLen(value);
5647 			    else
5648 				/*
5649 				* Should be OK for "preserve" as well.
5650 				*/
5651 				len = xmlUTF8Strlen(value);
5652 			}
5653 			break;
5654 		    case XML_SCHEMAS_IDREF:
5655 		    case XML_SCHEMAS_TOKEN:
5656 		    case XML_SCHEMAS_LANGUAGE:
5657 		    case XML_SCHEMAS_NMTOKEN:
5658 		    case XML_SCHEMAS_NAME:
5659 		    case XML_SCHEMAS_NCNAME:
5660 		    case XML_SCHEMAS_ID:
5661 		    case XML_SCHEMAS_ANYURI:
5662 			if (value != NULL)
5663 			    len = xmlSchemaNormLen(value);
5664 			break;
5665 		    default:
5666 		        /* TODO */
5667                         break;
5668 		}
5669 	    }
5670 	    if (facet->type == XML_SCHEMA_FACET_LENGTH) {
5671                 if (len != xmlSchemaGetFacetValueAsULong(facet))
5672 		    return(XML_SCHEMAV_CVC_LENGTH_VALID);
5673 	    } else if (facet->type == XML_SCHEMA_FACET_MINLENGTH) {
5674                 if (len < xmlSchemaGetFacetValueAsULong(facet))
5675 		    return(XML_SCHEMAV_CVC_MINLENGTH_VALID);
5676 	    } else if (len > xmlSchemaGetFacetValueAsULong(facet)) {
5677                 return (XML_SCHEMAV_CVC_MAXLENGTH_VALID);
5678 	    }
5679 	    break;
5680 	}
5681 	case XML_SCHEMA_FACET_TOTALDIGITS:
5682 	case XML_SCHEMA_FACET_FRACTIONDIGITS:
5683 
5684 	    if ((facet->val == NULL) ||
5685 		((facet->val->type != XML_SCHEMAS_PINTEGER) &&
5686 		 (facet->val->type != XML_SCHEMAS_NNINTEGER)) ||
5687 		!xmlSchemaValDecimalIsInteger(&facet->val->value.decimal)) {
5688 		return(-1);
5689 	    }
5690 	    if ((val == NULL) ||
5691 		((val->type != XML_SCHEMAS_DECIMAL) &&
5692 		 (val->type != XML_SCHEMAS_INTEGER) &&
5693 		 (val->type != XML_SCHEMAS_NPINTEGER) &&
5694 		 (val->type != XML_SCHEMAS_NINTEGER) &&
5695 		 (val->type != XML_SCHEMAS_NNINTEGER) &&
5696 		 (val->type != XML_SCHEMAS_PINTEGER) &&
5697 		 (val->type != XML_SCHEMAS_INT) &&
5698 		 (val->type != XML_SCHEMAS_UINT) &&
5699 		 (val->type != XML_SCHEMAS_LONG) &&
5700 		 (val->type != XML_SCHEMAS_ULONG) &&
5701 		 (val->type != XML_SCHEMAS_SHORT) &&
5702 		 (val->type != XML_SCHEMAS_USHORT) &&
5703 		 (val->type != XML_SCHEMAS_BYTE) &&
5704 		 (val->type != XML_SCHEMAS_UBYTE))) {
5705 		return(-1);
5706 	    }
5707 	    if (facet->type == XML_SCHEMA_FACET_TOTALDIGITS) {
5708                 if (xmlSchemaValDecimalGetSignificantDigitCount(&val->value.decimal) > xmlSchemaGetFacetValueAsULong(facet))
5709 	            return(XML_SCHEMAV_CVC_TOTALDIGITS_VALID);
5710 
5711 	    } else if (facet->type == XML_SCHEMA_FACET_FRACTIONDIGITS) {
5712 			if ((xmlSchemaValDecimalIsInteger(&val->value.decimal) ? 0 : val->value.decimal.fractionalPlaces) > xmlSchemaGetFacetValueAsULong(facet))
5713 		    return(XML_SCHEMAV_CVC_FRACTIONDIGITS_VALID);
5714 	    }
5715 	    break;
5716 	default:
5717 	    /* TODO */
5718             break;
5719     }
5720     return(0);
5721 
5722 }
5723 
5724 /**
5725  * xmlSchemaValidateFacet:
5726  * @base:  the base type
5727  * @facet:  the facet to check
5728  * @value:  the lexical repr of the value to validate
5729  * @val:  the precomputed value
5730  *
5731  * Check a value against a facet condition
5732  *
5733  * Returns 0 if the element is schemas valid, a positive error code
5734  *     number otherwise and -1 in case of internal or API error.
5735  */
5736 int
xmlSchemaValidateFacet(xmlSchemaTypePtr base,xmlSchemaFacetPtr facet,const xmlChar * value,xmlSchemaValPtr val)5737 xmlSchemaValidateFacet(xmlSchemaTypePtr base,
5738 	               xmlSchemaFacetPtr facet,
5739 	               const xmlChar *value,
5740 		       xmlSchemaValPtr val)
5741 {
5742     /*
5743     * This tries to ensure API compatibility regarding the old
5744     * xmlSchemaValidateFacet() and the new xmlSchemaValidateFacetInternal() and
5745     * xmlSchemaValidateFacetWhtsp().
5746     */
5747     if (val != NULL)
5748 	return(xmlSchemaValidateFacetInternal(facet,
5749 	    XML_SCHEMA_WHITESPACE_UNKNOWN, val->type, value, val,
5750 	    XML_SCHEMA_WHITESPACE_UNKNOWN));
5751     else if (base != NULL)
5752 	return(xmlSchemaValidateFacetInternal(facet,
5753 	    XML_SCHEMA_WHITESPACE_UNKNOWN, base->builtInType, value, val,
5754 	    XML_SCHEMA_WHITESPACE_UNKNOWN));
5755     return(-1);
5756 }
5757 
5758 /**
5759  * xmlSchemaValidateFacetWhtsp:
5760  * @facet:  the facet to check
5761  * @fws: the whitespace type of the facet's value
5762  * @valType: the built-in type of the value
5763  * @value:  the lexical (or normalized for pattern) repr of the value to validate
5764  * @val:  the precomputed value
5765  * @ws: the whitespace type of the value
5766  *
5767  * Check a value against a facet condition. This takes value normalization
5768  * according to the specified whitespace types into account.
5769  * Note that @value needs to be the *normalized* value if the facet
5770  * is of type "pattern".
5771  *
5772  * Returns 0 if the element is schemas valid, a positive error code
5773  *     number otherwise and -1 in case of internal or API error.
5774  */
5775 int
xmlSchemaValidateFacetWhtsp(xmlSchemaFacetPtr facet,xmlSchemaWhitespaceValueType fws,xmlSchemaValType valType,const xmlChar * value,xmlSchemaValPtr val,xmlSchemaWhitespaceValueType ws)5776 xmlSchemaValidateFacetWhtsp(xmlSchemaFacetPtr facet,
5777 			    xmlSchemaWhitespaceValueType fws,
5778 			    xmlSchemaValType valType,
5779 			    const xmlChar *value,
5780 			    xmlSchemaValPtr val,
5781 			    xmlSchemaWhitespaceValueType ws)
5782 {
5783      return(xmlSchemaValidateFacetInternal(facet, fws, valType,
5784 	 value, val, ws));
5785 }
5786 
5787 /**
5788  * xmlSchemaGetCanonValue:
5789  * @val: the precomputed value
5790  * @retValue: the returned value
5791  *
5792  * Get the canonical lexical representation of the value.
5793  * The caller has to FREE the returned retValue.
5794  *
5795  * WARNING: Some value types are not supported yet, resulting
5796  * in a @retValue of "???".
5797  *
5798  * TODO: XML Schema 1.0 does not define canonical representations
5799  * for: duration, gYearMonth, gYear, gMonthDay, gMonth, gDay,
5800  * anyURI, QName, NOTATION. This will be fixed in XML Schema 1.1.
5801  *
5802  *
5803  * Returns 0 if the value could be built, 1 if the value type is
5804  * not supported yet and -1 in case of API errors.
5805  */
5806 int
xmlSchemaGetCanonValue(xmlSchemaValPtr val,const xmlChar ** retValue)5807 xmlSchemaGetCanonValue(xmlSchemaValPtr val, const xmlChar **retValue)
5808 {
5809     if ((retValue == NULL) || (val == NULL))
5810 	return (-1);
5811     *retValue = NULL;
5812     switch (val->type) {
5813 	case XML_SCHEMAS_STRING:
5814 	    if (val->value.str == NULL)
5815 		*retValue = BAD_CAST xmlStrdup(BAD_CAST "");
5816 	    else
5817 		*retValue =
5818 		    BAD_CAST xmlStrdup((const xmlChar *) val->value.str);
5819 	    break;
5820 	case XML_SCHEMAS_NORMSTRING:
5821 	    if (val->value.str == NULL)
5822 		*retValue = BAD_CAST xmlStrdup(BAD_CAST "");
5823 	    else {
5824 		*retValue = xmlSchemaWhiteSpaceReplace(
5825 		    (const xmlChar *) val->value.str);
5826 		if ((*retValue) == NULL)
5827 		    *retValue = BAD_CAST xmlStrdup(
5828 			(const xmlChar *) val->value.str);
5829 	    }
5830 	    break;
5831 	case XML_SCHEMAS_TOKEN:
5832 	case XML_SCHEMAS_LANGUAGE:
5833 	case XML_SCHEMAS_NMTOKEN:
5834 	case XML_SCHEMAS_NAME:
5835 	case XML_SCHEMAS_NCNAME:
5836 	case XML_SCHEMAS_ID:
5837 	case XML_SCHEMAS_IDREF:
5838 	case XML_SCHEMAS_ENTITY:
5839 	case XML_SCHEMAS_NOTATION: /* Unclear */
5840 	case XML_SCHEMAS_ANYURI:   /* Unclear */
5841 	    if (val->value.str == NULL)
5842 		return (-1);
5843 	    *retValue =
5844 		BAD_CAST xmlSchemaCollapseString(BAD_CAST val->value.str);
5845 	    if (*retValue == NULL)
5846 		*retValue =
5847 		    BAD_CAST xmlStrdup((const xmlChar *) val->value.str);
5848 	    break;
5849 	case XML_SCHEMAS_QNAME:
5850 	    /* TODO: Unclear in XML Schema 1.0. */
5851 	    if (val->value.qname.uri == NULL) {
5852 		*retValue = BAD_CAST xmlStrdup(BAD_CAST val->value.qname.name);
5853 		return (0);
5854 	    } else {
5855 		*retValue = BAD_CAST xmlStrdup(BAD_CAST "{");
5856 		*retValue = BAD_CAST xmlStrcat((xmlChar *) (*retValue),
5857 		    BAD_CAST val->value.qname.uri);
5858 		*retValue = BAD_CAST xmlStrcat((xmlChar *) (*retValue),
5859 		    BAD_CAST "}");
5860 		*retValue = BAD_CAST xmlStrcat((xmlChar *) (*retValue),
5861 		    BAD_CAST val->value.qname.uri);
5862 	    }
5863 	    break;
5864 	case XML_SCHEMAS_DECIMAL: {
5865                 xmlChar *start = val->value.decimal.str;
5866                 if(start[0] == '+')
5867                 {
5868                     start += 1;
5869                 }
5870                 *retValue = xmlStrdup(start);
5871 	    }
5872 	    break;
5873 	case XML_SCHEMAS_INTEGER:
5874         case XML_SCHEMAS_PINTEGER:
5875         case XML_SCHEMAS_NPINTEGER:
5876         case XML_SCHEMAS_NINTEGER:
5877         case XML_SCHEMAS_NNINTEGER:
5878 	case XML_SCHEMAS_LONG:
5879         case XML_SCHEMAS_BYTE:
5880         case XML_SCHEMAS_SHORT:
5881         case XML_SCHEMAS_INT:
5882 	case XML_SCHEMAS_UINT:
5883         case XML_SCHEMAS_ULONG:
5884         case XML_SCHEMAS_USHORT:
5885         case XML_SCHEMAS_UBYTE: {
5886             xmlChar *start = val->value.decimal.str;
5887             /* 2 = sign+NULL */
5888             size_t bufSize = val->value.decimal.integralPlaces+2;
5889             if(start[0] == '+')
5890             {
5891                 start += 1;
5892                 bufSize -= 1;
5893             }
5894             *retValue = xmlMalloc(bufSize);
5895             if(*retValue) {
5896                 /* no need to limit string length in format, it will only print bufSize-1 chars anyways */
5897                 snprintf((char*)*retValue, bufSize, "%s", start);
5898             }
5899 	    }
5900 	    break;
5901 	case XML_SCHEMAS_BOOLEAN:
5902 	    if (val->value.b)
5903 		*retValue = BAD_CAST xmlStrdup(BAD_CAST "true");
5904 	    else
5905 		*retValue = BAD_CAST xmlStrdup(BAD_CAST "false");
5906 	    break;
5907 	case XML_SCHEMAS_DURATION: {
5908 		char buf[100];
5909 		unsigned long year;
5910 		unsigned long mon, day, hour = 0, min = 0;
5911 		double sec = 0, left;
5912 
5913 		/* TODO: Unclear in XML Schema 1.0 */
5914 		/*
5915 		* TODO: This results in a normalized output of the value
5916 		* - which is NOT conformant to the spec -
5917 		* since the exact values of each property are not
5918 		* recoverable. Think about extending the structure to
5919 		* provide a field for every property.
5920 		*/
5921 		year = (unsigned long) FQUOTIENT(labs(val->value.dur.mon), 12);
5922 		mon = labs(val->value.dur.mon) - 12 * year;
5923 
5924 		day = (unsigned long) FQUOTIENT(fabs(val->value.dur.sec), 86400);
5925 		left = fabs(val->value.dur.sec) - day * 86400;
5926 		if (left > 0) {
5927 		    hour = (unsigned long) FQUOTIENT(left, 3600);
5928 		    left = left - (hour * 3600);
5929 		    if (left > 0) {
5930 			min = (unsigned long) FQUOTIENT(left, 60);
5931 			sec = left - (min * 60);
5932 		    }
5933 		}
5934 		if ((val->value.dur.mon < 0) || (val->value.dur.sec < 0))
5935 		    snprintf(buf, 100, "P%luY%luM%luDT%luH%luM%.14gS",
5936 			year, mon, day, hour, min, sec);
5937 		else
5938 		    snprintf(buf, 100, "-P%luY%luM%luDT%luH%luM%.14gS",
5939 			year, mon, day, hour, min, sec);
5940 		*retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
5941 	    }
5942 	    break;
5943 	case XML_SCHEMAS_GYEAR: {
5944 		char buf[30];
5945 		/* TODO: Unclear in XML Schema 1.0 */
5946 		/* TODO: What to do with the timezone? */
5947 		snprintf(buf, 30, "%04ld", val->value.date.year);
5948 		*retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
5949 	    }
5950 	    break;
5951 	case XML_SCHEMAS_GMONTH: {
5952 		/* TODO: Unclear in XML Schema 1.0 */
5953 		/* TODO: What to do with the timezone? */
5954 		*retValue = xmlMalloc(6);
5955 		if (*retValue == NULL)
5956 		    return(-1);
5957 		snprintf((char *) *retValue, 6, "--%02u",
5958 		    val->value.date.mon);
5959 	    }
5960 	    break;
5961         case XML_SCHEMAS_GDAY: {
5962 		/* TODO: Unclear in XML Schema 1.0 */
5963 		/* TODO: What to do with the timezone? */
5964 		*retValue = xmlMalloc(6);
5965 		if (*retValue == NULL)
5966 		    return(-1);
5967 		snprintf((char *) *retValue, 6, "---%02u",
5968 		    val->value.date.day);
5969 	    }
5970 	    break;
5971         case XML_SCHEMAS_GMONTHDAY: {
5972 		/* TODO: Unclear in XML Schema 1.0 */
5973 		/* TODO: What to do with the timezone? */
5974 		*retValue = xmlMalloc(8);
5975 		if (*retValue == NULL)
5976 		    return(-1);
5977 		snprintf((char *) *retValue, 8, "--%02u-%02u",
5978 		    val->value.date.mon, val->value.date.day);
5979 	    }
5980 	    break;
5981         case XML_SCHEMAS_GYEARMONTH: {
5982 		char buf[35];
5983 		/* TODO: Unclear in XML Schema 1.0 */
5984 		/* TODO: What to do with the timezone? */
5985 		if (val->value.date.year < 0)
5986 		    snprintf(buf, 35, "-%04ld-%02u",
5987 			labs(val->value.date.year),
5988 			val->value.date.mon);
5989 		else
5990 		    snprintf(buf, 35, "%04ld-%02u",
5991 			val->value.date.year, val->value.date.mon);
5992 		*retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
5993 	    }
5994 	    break;
5995 	case XML_SCHEMAS_TIME:
5996 	    {
5997 		char buf[30];
5998 
5999 		if (val->value.date.tz_flag) {
6000 		    xmlSchemaValPtr norm;
6001 
6002 		    norm = xmlSchemaDateNormalize(val, 0);
6003 		    if (norm == NULL)
6004 			return (-1);
6005 		    /*
6006 		    * TODO: Check if "%.14g" is portable.
6007 		    */
6008 		    snprintf(buf, 30,
6009 			"%02u:%02u:%02.14gZ",
6010 			norm->value.date.hour,
6011 			norm->value.date.min,
6012 			norm->value.date.sec);
6013 		    xmlSchemaFreeValue(norm);
6014 		} else {
6015 		    snprintf(buf, 30,
6016 			"%02u:%02u:%02.14g",
6017 			val->value.date.hour,
6018 			val->value.date.min,
6019 			val->value.date.sec);
6020 		}
6021 		*retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
6022 	    }
6023 	    break;
6024         case XML_SCHEMAS_DATE:
6025 	    {
6026 		char buf[30];
6027 
6028 		if (val->value.date.tz_flag) {
6029 		    xmlSchemaValPtr norm;
6030 
6031 		    norm = xmlSchemaDateNormalize(val, 0);
6032 		    if (norm == NULL)
6033 			return (-1);
6034 		    /*
6035 		    * TODO: Append the canonical value of the
6036 		    * recoverable timezone and not "Z".
6037 		    */
6038 		    snprintf(buf, 30,
6039 			"%04ld-%02u-%02uZ",
6040 			norm->value.date.year, norm->value.date.mon,
6041 			norm->value.date.day);
6042 		    xmlSchemaFreeValue(norm);
6043 		} else {
6044 		    snprintf(buf, 30,
6045 			"%04ld-%02u-%02u",
6046 			val->value.date.year, val->value.date.mon,
6047 			val->value.date.day);
6048 		}
6049 		*retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
6050 	    }
6051 	    break;
6052         case XML_SCHEMAS_DATETIME:
6053 	    {
6054 		char buf[50];
6055 
6056 		if (val->value.date.tz_flag) {
6057 		    xmlSchemaValPtr norm;
6058 
6059 		    norm = xmlSchemaDateNormalize(val, 0);
6060 		    if (norm == NULL)
6061 			return (-1);
6062 		    /*
6063 		    * TODO: Check if "%.14g" is portable.
6064 		    */
6065 		    snprintf(buf, 50,
6066 			"%04ld-%02u-%02uT%02u:%02u:%02.14gZ",
6067 			norm->value.date.year, norm->value.date.mon,
6068 			norm->value.date.day, norm->value.date.hour,
6069 			norm->value.date.min, norm->value.date.sec);
6070 		    xmlSchemaFreeValue(norm);
6071 		} else {
6072 		    snprintf(buf, 50,
6073 			"%04ld-%02u-%02uT%02u:%02u:%02.14g",
6074 			val->value.date.year, val->value.date.mon,
6075 			val->value.date.day, val->value.date.hour,
6076 			val->value.date.min, val->value.date.sec);
6077 		}
6078 		*retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
6079 	    }
6080 	    break;
6081 	case XML_SCHEMAS_HEXBINARY:
6082 	    *retValue = BAD_CAST xmlStrdup(BAD_CAST val->value.hex.str);
6083 	    break;
6084 	case XML_SCHEMAS_BASE64BINARY:
6085 	    /*
6086 	    * TODO: Is the following spec piece implemented?:
6087 	    * SPEC: "Note: For some values the canonical form defined
6088 	    * above does not conform to [RFC 2045], which requires breaking
6089 	    * with linefeeds at appropriate intervals."
6090 	    */
6091 	    *retValue = BAD_CAST xmlStrdup(BAD_CAST val->value.base64.str);
6092 	    break;
6093 	case XML_SCHEMAS_FLOAT: {
6094 		char buf[30];
6095 		/*
6096 		* |m| < 16777216, -149 <= e <= 104.
6097 		* TODO: Handle, NaN, INF, -INF. The format is not
6098 		* yet conformant. The c type float does not cover
6099 		* the whole range.
6100 		*/
6101 		snprintf(buf, 30, "%01.14e", val->value.f);
6102 		*retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
6103 	    }
6104 	    break;
6105 	case XML_SCHEMAS_DOUBLE: {
6106 		char buf[40];
6107 		/* |m| < 9007199254740992, -1075 <= e <= 970 */
6108 		/*
6109 		* TODO: Handle, NaN, INF, -INF. The format is not
6110 		* yet conformant. The c type float does not cover
6111 		* the whole range.
6112 		*/
6113 		snprintf(buf, 40, "%01.14e", val->value.d);
6114 		*retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
6115 	    }
6116 	    break;
6117 	default:
6118 	    *retValue = BAD_CAST xmlStrdup(BAD_CAST "???");
6119 	    return (1);
6120     }
6121     if (*retValue == NULL)
6122 	return(-1);
6123     return (0);
6124 }
6125 
6126 /**
6127  * xmlSchemaGetCanonValueWhtsp:
6128  * @val: the precomputed value
6129  * @retValue: the returned value
6130  * @ws: the whitespace type of the value
6131  *
6132  * Get the canonical representation of the value.
6133  * The caller has to free the returned @retValue.
6134  *
6135  * Returns 0 if the value could be built, 1 if the value type is
6136  * not supported yet and -1 in case of API errors.
6137  */
6138 int
xmlSchemaGetCanonValueWhtsp(xmlSchemaValPtr val,const xmlChar ** retValue,xmlSchemaWhitespaceValueType ws)6139 xmlSchemaGetCanonValueWhtsp(xmlSchemaValPtr val,
6140 			    const xmlChar **retValue,
6141 			    xmlSchemaWhitespaceValueType ws)
6142 {
6143     if ((retValue == NULL) || (val == NULL))
6144 	return (-1);
6145     if ((ws == XML_SCHEMA_WHITESPACE_UNKNOWN) ||
6146 	(ws > XML_SCHEMA_WHITESPACE_COLLAPSE))
6147 	return (-1);
6148 
6149     *retValue = NULL;
6150     switch (val->type) {
6151 	case XML_SCHEMAS_STRING:
6152 	    if (val->value.str == NULL)
6153 		*retValue = BAD_CAST xmlStrdup(BAD_CAST "");
6154 	    else if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
6155 		*retValue = xmlSchemaCollapseString(val->value.str);
6156 	    else if (ws == XML_SCHEMA_WHITESPACE_REPLACE)
6157 		*retValue = xmlSchemaWhiteSpaceReplace(val->value.str);
6158 	    if ((*retValue) == NULL)
6159 		*retValue = BAD_CAST xmlStrdup(val->value.str);
6160 	    break;
6161 	case XML_SCHEMAS_NORMSTRING:
6162 	    if (val->value.str == NULL)
6163 		*retValue = BAD_CAST xmlStrdup(BAD_CAST "");
6164 	    else {
6165 		if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
6166 		    *retValue = xmlSchemaCollapseString(val->value.str);
6167 		else
6168 		    *retValue = xmlSchemaWhiteSpaceReplace(val->value.str);
6169 		if ((*retValue) == NULL)
6170 		    *retValue = BAD_CAST xmlStrdup(val->value.str);
6171 	    }
6172 	    break;
6173 	default:
6174 	    return (xmlSchemaGetCanonValue(val, retValue));
6175     }
6176     return (0);
6177 }
6178 
6179 /**
6180  * xmlSchemaGetValType:
6181  * @val: a schemas value
6182  *
6183  * Accessor for the type of a value
6184  *
6185  * Returns the xmlSchemaValType of the value
6186  */
6187 xmlSchemaValType
xmlSchemaGetValType(xmlSchemaValPtr val)6188 xmlSchemaGetValType(xmlSchemaValPtr val)
6189 {
6190     if (val == NULL)
6191         return(XML_SCHEMAS_UNKNOWN);
6192     return (val->type);
6193 }
6194 
6195 #endif /* LIBXML_SCHEMAS_ENABLED */
6196