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