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