mirror of
https://gitlab.gnome.org/GNOME/libxml2.git
synced 2025-07-30 22:43:14 +03:00
fixed an error reporting bug in Relax-NG when we end up with multiple
* relaxng.c: fixed an error reporting bug in Relax-NG when we end up with multiple states, select the "best" one. Fix #120682 * result/relaxng/tutor11_2_3.err: small change resulting * xmlschemastypes.c: applied base64 support patch from Anthony Carrico
This commit is contained in:
10
ChangeLog
10
ChangeLog
@ -1,3 +1,13 @@
|
||||
Wed Aug 27 16:12:41 CEST 2003 Daniel Veillard <daniel@veillard.com>
|
||||
|
||||
* relaxng.c: fixed an error reporting bug in Relax-NG when we end
|
||||
up with multiple states, select the "best" one. Fix #120682
|
||||
* result/relaxng/tutor11_2_3.err: small change resulting
|
||||
|
||||
Wed Aug 27 11:25:25 CEST 2003 Daniel Veillard <daniel@veillard.com>
|
||||
|
||||
* xmlschemastypes.c: applied base64 support patch from Anthony Carrico
|
||||
|
||||
Wed Aug 27 10:58:51 CEST 2003 Igor Zlatkovic <igor@zlatkovic.com>
|
||||
|
||||
* include/libxml/[threads-xpointer].h: realigned parameters
|
||||
|
142
relaxng.c
142
relaxng.c
@ -7786,7 +7786,8 @@ xmlRelaxNGValidateCompiledContent(xmlRelaxNGValidCtxtPtr ctxt,
|
||||
************************************************************************/
|
||||
static int xmlRelaxNGValidateAttributeList(xmlRelaxNGValidCtxtPtr ctxt,
|
||||
xmlRelaxNGDefinePtr defines);
|
||||
static int xmlRelaxNGValidateElementEnd(xmlRelaxNGValidCtxtPtr ctxt);
|
||||
static int xmlRelaxNGValidateElementEnd(xmlRelaxNGValidCtxtPtr ctxt, int log);
|
||||
static void xmlRelaxNGLogBestError(xmlRelaxNGValidCtxtPtr ctxt);
|
||||
|
||||
/**
|
||||
* xmlRelaxNGElemPush:
|
||||
@ -7944,7 +7945,7 @@ xmlRelaxNGValidateProgressiveCallback(xmlRegExecCtxtPtr exec ATTRIBUTE_UNUSED,
|
||||
}
|
||||
if (ctxt->state != NULL) {
|
||||
ctxt->state->seq = NULL;
|
||||
ret = xmlRelaxNGValidateElementEnd(ctxt);
|
||||
ret = xmlRelaxNGValidateElementEnd(ctxt, 1);
|
||||
if (ret != 0) {
|
||||
ctxt->pstate = -1;
|
||||
}
|
||||
@ -7953,16 +7954,27 @@ xmlRelaxNGValidateProgressiveCallback(xmlRegExecCtxtPtr exec ATTRIBUTE_UNUSED,
|
||||
int tmp = -1, i;
|
||||
|
||||
oldflags = ctxt->flags;
|
||||
ctxt->flags |= FLAGS_IGNORABLE;
|
||||
|
||||
for (i = 0; i < ctxt->states->nbState; i++) {
|
||||
state = ctxt->states->tabState[i];
|
||||
ctxt->state = state;
|
||||
ctxt->state->seq = NULL;
|
||||
|
||||
if (xmlRelaxNGValidateElementEnd(ctxt) == 0)
|
||||
if (xmlRelaxNGValidateElementEnd(ctxt, 0) == 0) {
|
||||
tmp = 0;
|
||||
xmlRelaxNGFreeValidState(ctxt, state);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (tmp != 0) {
|
||||
/*
|
||||
* validation error, log the message for the "best" one
|
||||
*/
|
||||
ctxt->flags |= FLAGS_IGNORABLE;
|
||||
xmlRelaxNGLogBestError(ctxt);
|
||||
}
|
||||
for (i = 0; i < ctxt->states->nbState; i++) {
|
||||
xmlRelaxNGFreeValidState(ctxt,
|
||||
ctxt->states->tabState[i]);
|
||||
}
|
||||
xmlRelaxNGFreeStates(ctxt, ctxt->states);
|
||||
ctxt->states = NULL;
|
||||
@ -9301,9 +9313,75 @@ xmlRelaxNGElementMatch(xmlRelaxNGValidCtxtPtr ctxt,
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlRelaxNGBestState:
|
||||
* @ctxt: a Relax-NG validation context
|
||||
*
|
||||
* Find the "best" state in the ctxt->states list of states to report
|
||||
* errors about. I.e. a state with no element left in the child list
|
||||
* or the one with the less attributes left.
|
||||
* This is called only if a falidation error was detected
|
||||
*
|
||||
* Returns the index of the "best" state or -1 in case of error
|
||||
*/
|
||||
static int
|
||||
xmlRelaxNGBestState(xmlRelaxNGValidCtxtPtr ctxt) {
|
||||
xmlRelaxNGValidStatePtr state;
|
||||
int i, tmp;
|
||||
int best = -1;
|
||||
int value = 1000000;
|
||||
|
||||
if ((ctxt == NULL) || (ctxt->states == NULL) ||
|
||||
(ctxt->states->nbState <= 0))
|
||||
return(-1);
|
||||
|
||||
for (i = 0;i < ctxt->states->nbState;i++) {
|
||||
state = ctxt->states->tabState[i];
|
||||
if (state == NULL)
|
||||
continue;
|
||||
if (state->seq != NULL) {
|
||||
if ((best == -1) || (value > 100000)) {
|
||||
value = 100000;
|
||||
best = i;
|
||||
}
|
||||
} else {
|
||||
tmp = state->nbAttrLeft;
|
||||
if ((best == -1) || (value > tmp)) {
|
||||
value = tmp;
|
||||
best = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return(best);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlRelaxNGLogBestError:
|
||||
* @ctxt: a Relax-NG validation context
|
||||
*
|
||||
* Find the "best" state in the ctxt->states list of states to report
|
||||
* errors about and log it.
|
||||
*/
|
||||
static void
|
||||
xmlRelaxNGLogBestError(xmlRelaxNGValidCtxtPtr ctxt) {
|
||||
int best;
|
||||
|
||||
if ((ctxt == NULL) || (ctxt->states == NULL) ||
|
||||
(ctxt->states->nbState <= 0))
|
||||
return;
|
||||
|
||||
best = xmlRelaxNGBestState(ctxt);
|
||||
if ((best >= 0) && (best < ctxt->states->nbState)) {
|
||||
ctxt->state = ctxt->states->tabState[best];
|
||||
|
||||
xmlRelaxNGValidateElementEnd(ctxt, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlRelaxNGValidateElementEnd:
|
||||
* @ctxt: a Relax-NG validation context
|
||||
* @log: indicate that error logging should be done
|
||||
*
|
||||
* Validate the end of the element, implements check that
|
||||
* there is nothing left not consumed in the element content
|
||||
@ -9312,27 +9390,31 @@ xmlRelaxNGElementMatch(xmlRelaxNGValidCtxtPtr ctxt,
|
||||
* Returns 0 if the validation succeeded or an error code.
|
||||
*/
|
||||
static int
|
||||
xmlRelaxNGValidateElementEnd(xmlRelaxNGValidCtxtPtr ctxt) {
|
||||
int ret = 0, i;
|
||||
xmlRelaxNGValidateElementEnd(xmlRelaxNGValidCtxtPtr ctxt, int log) {
|
||||
int i;
|
||||
xmlRelaxNGValidStatePtr state;
|
||||
|
||||
state = ctxt->state;
|
||||
if (state->seq != NULL) {
|
||||
state->seq = xmlRelaxNGSkipIgnored(ctxt, state->seq);
|
||||
if (state->seq != NULL) {
|
||||
if (log) {
|
||||
VALID_ERR3(XML_RELAXNG_ERR_EXTRACONTENT,
|
||||
state->node->name, state->seq->name);
|
||||
ret = -1;
|
||||
}
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
for (i = 0;i < state->nbAttrs;i++) {
|
||||
if (state->attrs[i] != NULL) {
|
||||
if (log) {
|
||||
VALID_ERR3(XML_RELAXNG_ERR_INVALIDATTR,
|
||||
state->attrs[i]->name, state->node->name);
|
||||
ret = -1;
|
||||
}
|
||||
return(-1 -i);
|
||||
}
|
||||
}
|
||||
return(ret);
|
||||
return(0);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -9503,16 +9585,26 @@ xmlRelaxNGValidateState(xmlRelaxNGValidCtxtPtr ctxt,
|
||||
if (ctxt->states != NULL) {
|
||||
tmp = -1;
|
||||
|
||||
ctxt->flags |= FLAGS_IGNORABLE;
|
||||
|
||||
for (i = 0; i < ctxt->states->nbState; i++) {
|
||||
state = ctxt->states->tabState[i];
|
||||
ctxt->state = state;
|
||||
ctxt->state->seq = nseq;
|
||||
|
||||
if (xmlRelaxNGValidateElementEnd(ctxt) == 0)
|
||||
if (xmlRelaxNGValidateElementEnd(ctxt, 0) == 0) {
|
||||
tmp = 0;
|
||||
xmlRelaxNGFreeValidState(ctxt, state);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (tmp != 0) {
|
||||
/*
|
||||
* validation error, log the message for the "best" one
|
||||
*/
|
||||
ctxt->flags |= FLAGS_IGNORABLE;
|
||||
xmlRelaxNGLogBestError(ctxt);
|
||||
}
|
||||
for (i = 0; i < ctxt->states->nbState; i++) {
|
||||
xmlRelaxNGFreeValidState(ctxt,
|
||||
ctxt->states->tabState[i]);
|
||||
}
|
||||
xmlRelaxNGFreeStates(ctxt, ctxt->states);
|
||||
ctxt->flags = oldflags;
|
||||
@ -9523,7 +9615,7 @@ xmlRelaxNGValidateState(xmlRelaxNGValidCtxtPtr ctxt,
|
||||
state = ctxt->state;
|
||||
ctxt->state->seq = nseq;
|
||||
if (ret == 0)
|
||||
ret = xmlRelaxNGValidateElementEnd(ctxt);
|
||||
ret = xmlRelaxNGValidateElementEnd(ctxt, 1);
|
||||
xmlRelaxNGFreeValidState(ctxt, state);
|
||||
}
|
||||
} else {
|
||||
@ -9547,15 +9639,25 @@ xmlRelaxNGValidateState(xmlRelaxNGValidCtxtPtr ctxt,
|
||||
if (ctxt->states != NULL) {
|
||||
tmp = -1;
|
||||
|
||||
ctxt->flags |= FLAGS_IGNORABLE;
|
||||
|
||||
for (i = 0; i < ctxt->states->nbState; i++) {
|
||||
state = ctxt->states->tabState[i];
|
||||
ctxt->state = state;
|
||||
|
||||
if (xmlRelaxNGValidateElementEnd(ctxt) == 0)
|
||||
if (xmlRelaxNGValidateElementEnd(ctxt, 0) == 0) {
|
||||
tmp = 0;
|
||||
xmlRelaxNGFreeValidState(ctxt, state);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (tmp != 0) {
|
||||
/*
|
||||
* validation error, log the message for the "best" one
|
||||
*/
|
||||
ctxt->flags |= FLAGS_IGNORABLE;
|
||||
xmlRelaxNGLogBestError(ctxt);
|
||||
}
|
||||
for (i = 0; i < ctxt->states->nbState; i++) {
|
||||
xmlRelaxNGFreeValidState(ctxt,
|
||||
ctxt->states->tabState[i]);
|
||||
}
|
||||
xmlRelaxNGFreeStates(ctxt, ctxt->states);
|
||||
ctxt->flags = oldflags;
|
||||
@ -9565,7 +9667,7 @@ xmlRelaxNGValidateState(xmlRelaxNGValidCtxtPtr ctxt,
|
||||
} else {
|
||||
state = ctxt->state;
|
||||
if (ret == 0)
|
||||
ret = xmlRelaxNGValidateElementEnd(ctxt);
|
||||
ret = xmlRelaxNGValidateElementEnd(ctxt, 1);
|
||||
xmlRelaxNGFreeValidState(ctxt, state);
|
||||
}
|
||||
}
|
||||
|
@ -1,2 +1,2 @@
|
||||
RNG validity error: file ./test/relaxng/tutor11_2_3.xml line 3 element card
|
||||
Invalid attribute foo for element card
|
||||
Invalid attribute b for element card
|
||||
|
@ -83,7 +83,8 @@ typedef enum {
|
||||
XML_SCHEMAS_USHORT,
|
||||
XML_SCHEMAS_BYTE,
|
||||
XML_SCHEMAS_UBYTE,
|
||||
XML_SCHEMAS_HEXBINARY
|
||||
XML_SCHEMAS_HEXBINARY,
|
||||
XML_SCHEMAS_BASE64BINARY
|
||||
} xmlSchemaValType;
|
||||
|
||||
static unsigned long powten[10] = {
|
||||
@ -141,6 +142,13 @@ struct _xmlSchemaValHex {
|
||||
unsigned int total;
|
||||
};
|
||||
|
||||
typedef struct _xmlSchemaValBase64 xmlSchemaValBase64;
|
||||
typedef xmlSchemaValBase64 *xmlSchemaValBase64Ptr;
|
||||
struct _xmlSchemaValBase64 {
|
||||
xmlChar *str;
|
||||
unsigned int total;
|
||||
};
|
||||
|
||||
struct _xmlSchemaVal {
|
||||
xmlSchemaValType type;
|
||||
union {
|
||||
@ -149,6 +157,7 @@ struct _xmlSchemaVal {
|
||||
xmlSchemaValDuration dur;
|
||||
xmlSchemaValQName qname;
|
||||
xmlSchemaValHex hex;
|
||||
xmlSchemaValBase64 base64;
|
||||
float f;
|
||||
double d;
|
||||
int b;
|
||||
@ -179,6 +188,7 @@ static xmlSchemaTypePtr xmlSchemaTypeFloatDef = NULL;
|
||||
static xmlSchemaTypePtr xmlSchemaTypeBooleanDef = NULL;
|
||||
static xmlSchemaTypePtr xmlSchemaTypeDoubleDef = NULL;
|
||||
static xmlSchemaTypePtr xmlSchemaTypeHexBinaryDef = NULL;
|
||||
static xmlSchemaTypePtr xmlSchemaTypeBase64BinaryDef = NULL;
|
||||
static xmlSchemaTypePtr xmlSchemaTypeAnyURIDef = NULL;
|
||||
|
||||
/*
|
||||
@ -290,6 +300,8 @@ xmlSchemaInitTypes(void)
|
||||
XML_SCHEMAS_ANYURI);
|
||||
xmlSchemaTypeHexBinaryDef = xmlSchemaInitBasicType("hexBinary",
|
||||
XML_SCHEMAS_HEXBINARY);
|
||||
xmlSchemaTypeBase64BinaryDef
|
||||
= xmlSchemaInitBasicType("base64Binary", XML_SCHEMAS_BASE64BINARY);
|
||||
|
||||
/*
|
||||
* derived datatypes
|
||||
@ -425,6 +437,10 @@ xmlSchemaFreeValue(xmlSchemaValPtr value) {
|
||||
if (value->value.hex.str != NULL)
|
||||
xmlFree(value->value.hex.str);
|
||||
break;
|
||||
case XML_SCHEMAS_BASE64BINARY:
|
||||
if (value->value.base64.str != NULL)
|
||||
xmlFree(value->value.base64.str);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -795,6 +811,25 @@ _xmlSchemaParseTimeZone (xmlSchemaValDatePtr dt, const xmlChar **str) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* _xmlSchemaBase64Decode:
|
||||
* @ch: a character
|
||||
*
|
||||
* Converts a base64 encoded character to its base 64 value.
|
||||
*
|
||||
* Returns 0-63 (value), 64 (pad), or -1 (not recognized)
|
||||
*/
|
||||
static int
|
||||
_xmlSchemaBase64Decode (const xmlChar ch) {
|
||||
if (('A' <= ch) && (ch <= 'Z')) return ch - 'A';
|
||||
if (('a' <= ch) && (ch <= 'z')) return ch - 'a' + 26;
|
||||
if (('0' <= ch) && (ch <= '9')) return ch - '0' + 52;
|
||||
if ('+' == ch) return 62;
|
||||
if ('/' == ch) return 63;
|
||||
if ('=' == ch) return 64;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
* *
|
||||
* XML Schema Dates/Times Datatypes Handling *
|
||||
@ -1392,7 +1427,8 @@ xmlSchemaParseUInt(const xmlChar **str, unsigned long *llo,
|
||||
*/
|
||||
static int
|
||||
xmlSchemaValAtomicType(xmlSchemaTypePtr type, const xmlChar * value,
|
||||
xmlSchemaValPtr *val, xmlNodePtr node, int flags) {
|
||||
xmlSchemaValPtr * val, xmlNodePtr node, int flags)
|
||||
{
|
||||
xmlSchemaValPtr v;
|
||||
xmlChar *norm = NULL;
|
||||
int ret = 0;
|
||||
@ -1421,12 +1457,12 @@ xmlSchemaValAtomicType(xmlSchemaTypePtr type, const xmlChar *value,
|
||||
case XML_SCHEMAS_STRING:
|
||||
goto return0;
|
||||
case XML_SCHEMAS_NORMSTRING:
|
||||
TODO
|
||||
goto return0;
|
||||
TODO goto return0;
|
||||
case XML_SCHEMAS_DECIMAL:{
|
||||
const xmlChar *cur = value, *tmp;
|
||||
unsigned int frac = 0, len, neg = 0;
|
||||
unsigned long base = 0;
|
||||
|
||||
if (cur == NULL)
|
||||
goto return1;
|
||||
if (*cur == '+')
|
||||
@ -1481,6 +1517,7 @@ xmlSchemaValAtomicType(xmlSchemaTypePtr type, const xmlChar *value,
|
||||
case XML_SCHEMAS_DOUBLE:{
|
||||
const xmlChar *cur = value;
|
||||
int neg = 0;
|
||||
|
||||
if (cur == NULL)
|
||||
goto return1;
|
||||
if ((cur[0] == 'N') && (cur[1] == 'a') && (cur[2] == 'N')) {
|
||||
@ -1570,11 +1607,14 @@ xmlSchemaValAtomicType(xmlSchemaTypePtr type, const xmlChar *value,
|
||||
if (type == xmlSchemaTypeFloatDef) {
|
||||
v = xmlSchemaNewValue(XML_SCHEMAS_FLOAT);
|
||||
if (v != NULL) {
|
||||
if (sscanf((const char *)value, "%f", &(v->value.f))==1) {
|
||||
if (sscanf
|
||||
((const char *) value, "%f",
|
||||
&(v->value.f)) == 1) {
|
||||
*val = v;
|
||||
} else {
|
||||
xmlGenericError(xmlGenericErrorContext,
|
||||
"failed to scanf float %s\n", value);
|
||||
"failed to scanf float %s\n",
|
||||
value);
|
||||
xmlSchemaFreeValue(v);
|
||||
goto return1;
|
||||
}
|
||||
@ -1584,11 +1624,14 @@ xmlSchemaValAtomicType(xmlSchemaTypePtr type, const xmlChar *value,
|
||||
} else {
|
||||
v = xmlSchemaNewValue(XML_SCHEMAS_DOUBLE);
|
||||
if (v != NULL) {
|
||||
if (sscanf((const char *)value, "%lf", &(v->value.d))==1) {
|
||||
if (sscanf
|
||||
((const char *) value, "%lf",
|
||||
&(v->value.d)) == 1) {
|
||||
*val = v;
|
||||
} else {
|
||||
xmlGenericError(xmlGenericErrorContext,
|
||||
"failed to scanf double %s\n", value);
|
||||
"failed to scanf double %s\n",
|
||||
value);
|
||||
xmlSchemaFreeValue(v);
|
||||
goto return1;
|
||||
}
|
||||
@ -1606,11 +1649,13 @@ xmlSchemaValAtomicType(xmlSchemaTypePtr type, const xmlChar *value,
|
||||
ret = 0;
|
||||
else if ((cur[0] == '1') && (cur[1] == 0))
|
||||
ret = 1;
|
||||
else if ((cur[0] == 't') && (cur[1] == 'r') && (cur[2] == 'u') &&
|
||||
(cur[3] == 'e') && (cur[4] == 0))
|
||||
else if ((cur[0] == 't') && (cur[1] == 'r')
|
||||
&& (cur[2] == 'u') && (cur[3] == 'e')
|
||||
&& (cur[4] == 0))
|
||||
ret = 1;
|
||||
else if ((cur[0] == 'f') && (cur[1] == 'a') && (cur[2] == 'l') &&
|
||||
(cur[3] == 's') && (cur[4] == 'e') && (cur[5] == 0))
|
||||
else if ((cur[0] == 'f') && (cur[1] == 'a')
|
||||
&& (cur[2] == 'l') && (cur[3] == 's')
|
||||
&& (cur[4] == 'e') && (cur[5] == 0))
|
||||
ret = 0;
|
||||
else
|
||||
goto return1;
|
||||
@ -1704,6 +1749,7 @@ xmlSchemaValAtomicType(xmlSchemaTypePtr type, const xmlChar *value,
|
||||
ret = xmlValidateQName(value, 1);
|
||||
if ((ret == 0) && (node != NULL)) {
|
||||
xmlChar *prefix;
|
||||
|
||||
local = xmlSplitQName2(value, &prefix);
|
||||
if (prefix != NULL) {
|
||||
xmlNsPtr ns;
|
||||
@ -1766,6 +1812,7 @@ xmlSchemaValAtomicType(xmlSchemaTypePtr type, const xmlChar *value,
|
||||
if ((ret == 0) && (node != NULL) &&
|
||||
(node->type == XML_ATTRIBUTE_NODE)) {
|
||||
xmlAttrPtr attr = (xmlAttrPtr) node;
|
||||
|
||||
/*
|
||||
* NOTE: the IDness might have already be declared in the DTD
|
||||
*/
|
||||
@ -1822,6 +1869,7 @@ xmlSchemaValAtomicType(xmlSchemaTypePtr type, const xmlChar *value,
|
||||
goto done;
|
||||
case XML_SCHEMAS_ENTITY:{
|
||||
xmlChar *strip;
|
||||
|
||||
ret = xmlValidateNCName(value, 1);
|
||||
if ((node == NULL) || (node->doc == NULL))
|
||||
ret = 3;
|
||||
@ -1836,7 +1884,8 @@ xmlSchemaValAtomicType(xmlSchemaTypePtr type, const xmlChar *value,
|
||||
ent = xmlGetDocEntity(node->doc, value);
|
||||
}
|
||||
if ((ent == NULL) ||
|
||||
(ent->etype != XML_EXTERNAL_GENERAL_UNPARSED_ENTITY))
|
||||
(ent->etype !=
|
||||
XML_EXTERNAL_GENERAL_UNPARSED_ENTITY))
|
||||
ret = 4;
|
||||
}
|
||||
if ((ret == 0) && (val != NULL)) {
|
||||
@ -1873,6 +1922,7 @@ xmlSchemaValAtomicType(xmlSchemaTypePtr type, const xmlChar *value,
|
||||
ret = xmlValidateQName(value, 1);
|
||||
if ((ret == 0) && (node != NULL)) {
|
||||
xmlChar *prefix;
|
||||
|
||||
local = xmlSplitQName2(value, &prefix);
|
||||
if (prefix != NULL) {
|
||||
xmlNsPtr ns;
|
||||
@ -1941,7 +1991,8 @@ xmlSchemaValAtomicType(xmlSchemaTypePtr type, const xmlChar *value,
|
||||
while (((*cur >= '0') && (*cur <= '9')) ||
|
||||
((*cur >= 'A') && (*cur <= 'F')) ||
|
||||
((*cur >= 'a') && (*cur <= 'f'))) {
|
||||
i++;cur++;
|
||||
i++;
|
||||
cur++;
|
||||
}
|
||||
|
||||
if (*cur != 0)
|
||||
@ -1976,6 +2027,133 @@ xmlSchemaValAtomicType(xmlSchemaTypePtr type, const xmlChar *value,
|
||||
}
|
||||
goto return0;
|
||||
}
|
||||
case XML_SCHEMAS_BASE64BINARY:{
|
||||
/* ISSUE:
|
||||
*
|
||||
* Ignore all stray characters? (yes, currently)
|
||||
* Worry about long lines? (no, currently)
|
||||
*
|
||||
* rfc2045.txt:
|
||||
*
|
||||
* "The encoded output stream must be represented in lines of
|
||||
* no more than 76 characters each. All line breaks or other
|
||||
* characters not found in Table 1 must be ignored by decoding
|
||||
* software. In base64 data, characters other than those in
|
||||
* Table 1, line breaks, and other white space probably
|
||||
* indicate a transmission error, about which a warning
|
||||
* message or even a message rejection might be appropriate
|
||||
* under some circumstances." */
|
||||
const xmlChar *cur = value;
|
||||
xmlChar *base;
|
||||
int total, i = 0, pad = 0;
|
||||
|
||||
if (cur == NULL)
|
||||
goto return1;
|
||||
|
||||
for (; *cur; ++cur) {
|
||||
int decc;
|
||||
|
||||
decc = _xmlSchemaBase64Decode(*cur);
|
||||
if (decc < 0) ;
|
||||
else if (decc < 64)
|
||||
i++;
|
||||
else
|
||||
break;
|
||||
}
|
||||
for (; *cur; ++cur) {
|
||||
int decc;
|
||||
|
||||
decc = _xmlSchemaBase64Decode(*cur);
|
||||
if (decc < 0) ;
|
||||
else if (decc < 64)
|
||||
goto return1;
|
||||
if (decc == 64)
|
||||
pad++;
|
||||
}
|
||||
|
||||
/* rfc2045.txt: "Special processing is performed if fewer than
|
||||
* 24 bits are available at the end of the data being encoded.
|
||||
* A full encoding quantum is always completed at the end of a
|
||||
* body. When fewer than 24 input bits are available in an
|
||||
* input group, zero bits are added (on the right) to form an
|
||||
* integral number of 6-bit groups. Padding at the end of the
|
||||
* data is performed using the "=" character. Since all
|
||||
* base64 input is an integral number of octets, only the
|
||||
* following cases can arise: (1) the final quantum of
|
||||
* encoding input is an integral multiple of 24 bits; here,
|
||||
* the final unit of encoded output will be an integral
|
||||
* multiple ofindent: Standard input:701: Warning:old style
|
||||
* assignment ambiguity in "=*". Assuming "= *" 4 characters
|
||||
* with no "=" padding, (2) the final
|
||||
* quantum of encoding input is exactly 8 bits; here, the
|
||||
* final unit of encoded output will be two characters
|
||||
* followed by two "=" padding characters, or (3) the final
|
||||
* quantum of encoding input is exactly 16 bits; here, the
|
||||
* final unit of encoded output will be three characters
|
||||
* followed by one "=" padding character." */
|
||||
|
||||
total = 3 * (i / 4);
|
||||
if (pad == 0) {
|
||||
if (i % 4 != 0)
|
||||
goto return1;
|
||||
} else if (pad == 1) {
|
||||
int decc;
|
||||
|
||||
if (i % 4 != 3)
|
||||
goto return1;
|
||||
for (decc = _xmlSchemaBase64Decode(*cur);
|
||||
(decc < 0) || (decc > 63);
|
||||
decc = _xmlSchemaBase64Decode(*cur))
|
||||
--cur;
|
||||
/* 16bits in 24bits means 2 pad bits: nnnnnn nnmmmm mmmm00*/
|
||||
/* 00111100 -> 0x3c */
|
||||
if (decc & ~0x3c)
|
||||
goto return1;
|
||||
total += 2;
|
||||
} else if (pad == 2) {
|
||||
int decc;
|
||||
|
||||
if (i % 4 != 2)
|
||||
goto return1;
|
||||
for (decc = _xmlSchemaBase64Decode(*cur);
|
||||
(decc < 0) || (decc > 63);
|
||||
decc = _xmlSchemaBase64Decode(*cur))
|
||||
--cur;
|
||||
/* 8bits in 12bits means 4 pad bits: nnnnnn nn0000 */
|
||||
/* 00110000 -> 0x30 */
|
||||
if (decc & ~0x30)
|
||||
goto return1;
|
||||
total += 1;
|
||||
} else
|
||||
goto return1;
|
||||
|
||||
if (val != NULL) {
|
||||
v = xmlSchemaNewValue(XML_SCHEMAS_BASE64BINARY);
|
||||
if (v == NULL)
|
||||
goto error;
|
||||
base =
|
||||
(xmlChar *) xmlMallocAtomic((i + pad + 1) *
|
||||
sizeof(xmlChar));
|
||||
if (base == NULL) {
|
||||
xmlGenericError(xmlGenericErrorContext,
|
||||
"malloc of %ld byte failed\n",
|
||||
(i + pad +
|
||||
1) * (long) sizeof(xmlChar));
|
||||
xmlFree(v);
|
||||
goto return1;
|
||||
}
|
||||
v->value.base64.str = base;
|
||||
for (cur = value; *cur; ++cur)
|
||||
if (_xmlSchemaBase64Decode(*cur) >= 0) {
|
||||
*base = *cur;
|
||||
++base;
|
||||
}
|
||||
*base = 0;
|
||||
v->value.base64.total = total;
|
||||
*val = v;
|
||||
}
|
||||
goto return0;
|
||||
}
|
||||
case XML_SCHEMAS_INTEGER:
|
||||
case XML_SCHEMAS_PINTEGER:
|
||||
case XML_SCHEMAS_NPINTEGER:
|
||||
@ -1984,6 +2162,7 @@ xmlSchemaValAtomicType(xmlSchemaTypePtr type, const xmlChar *value,
|
||||
const xmlChar *cur = value;
|
||||
unsigned long lo, mi, hi;
|
||||
int sign = 0;
|
||||
|
||||
if (cur == NULL)
|
||||
goto return1;
|
||||
if (*cur == '-') {
|
||||
@ -2040,6 +2219,7 @@ xmlSchemaValAtomicType(xmlSchemaTypePtr type, const xmlChar *value,
|
||||
unsigned long lo, mi, hi;
|
||||
int total = 0;
|
||||
int sign = 0;
|
||||
|
||||
if (cur == NULL)
|
||||
goto return1;
|
||||
if (*cur == '-') {
|
||||
@ -2112,6 +2292,7 @@ xmlSchemaValAtomicType(xmlSchemaTypePtr type, const xmlChar *value,
|
||||
const xmlChar *cur = value;
|
||||
unsigned long lo, mi, hi;
|
||||
int total = 0;
|
||||
|
||||
if (cur == NULL)
|
||||
goto return1;
|
||||
ret = xmlSchemaParseUInt(&cur, &lo, &mi, &hi);
|
||||
@ -2167,19 +2348,24 @@ xmlSchemaValAtomicType(xmlSchemaTypePtr type, const xmlChar *value,
|
||||
}
|
||||
|
||||
done:
|
||||
if (norm != NULL) xmlFree(norm);
|
||||
if (norm != NULL)
|
||||
xmlFree(norm);
|
||||
return (ret);
|
||||
return3:
|
||||
if (norm != NULL) xmlFree(norm);
|
||||
if (norm != NULL)
|
||||
xmlFree(norm);
|
||||
return (3);
|
||||
return1:
|
||||
if (norm != NULL) xmlFree(norm);
|
||||
if (norm != NULL)
|
||||
xmlFree(norm);
|
||||
return (1);
|
||||
return0:
|
||||
if (norm != NULL) xmlFree(norm);
|
||||
if (norm != NULL)
|
||||
xmlFree(norm);
|
||||
return (0);
|
||||
error:
|
||||
if (norm != NULL) xmlFree(norm);
|
||||
if (norm != NULL)
|
||||
xmlFree(norm);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
@ -3138,6 +3324,22 @@ xmlSchemaCompareValues(xmlSchemaValPtr x, xmlSchemaValPtr y) {
|
||||
return(-1);
|
||||
}
|
||||
return (-2);
|
||||
case XML_SCHEMAS_BASE64BINARY:
|
||||
if (y->type == XML_SCHEMAS_BASE64BINARY) {
|
||||
if (x->value.base64.total == y->value.base64.total) {
|
||||
int ret = xmlStrcmp(x->value.base64.str,
|
||||
y->value.base64.str);
|
||||
if (ret > 0)
|
||||
return(1);
|
||||
else if (ret == 0)
|
||||
return(0);
|
||||
}
|
||||
else if (x->value.base64.total > y->value.base64.total)
|
||||
return(1);
|
||||
else
|
||||
return(-1);
|
||||
}
|
||||
return (-2);
|
||||
case XML_SCHEMAS_STRING:
|
||||
case XML_SCHEMAS_IDREFS:
|
||||
case XML_SCHEMAS_ENTITIES:
|
||||
@ -3284,6 +3486,8 @@ xmlSchemaValidateFacet(xmlSchemaTypePtr base ATTRIBUTE_UNUSED,
|
||||
}
|
||||
if ((val != NULL) && (val->type == XML_SCHEMAS_HEXBINARY))
|
||||
len = val->value.hex.total;
|
||||
else if ((val != NULL) && (val->type == XML_SCHEMAS_BASE64BINARY))
|
||||
len = val->value.base64.total;
|
||||
else {
|
||||
switch (base->flags) {
|
||||
case XML_SCHEMAS_IDREF:
|
||||
|
Reference in New Issue
Block a user