зеркало из https://github.com/mozilla/gecko-dev.git
Added code to properly decode multi-dimensional arrays as nested arrays
in XPCOM. Unfortunately, there is no way to test this because Apache SOAP servers do not seem to produce them in any simple configuration because Java does not support multidimensional arrays. I will be writing code to test this later as I add support for encoding multi-dimensional arrays, as specified by a schema type, which I can then decode without actually sending / receiving a message, but I need to put this fix back now. At least I didn't break decoding of single-dimensional arrays. SOAP is not part of default build.
This commit is contained in:
Родитель
9bc075c94c
Коммит
9db9d11f19
|
@ -1746,7 +1746,7 @@ NS_IMETHODIMP
|
||||||
* if specifying a position. In these cases, the
|
* if specifying a position. In these cases, the
|
||||||
* bracketted values are removed.
|
* bracketted values are removed.
|
||||||
*/
|
*/
|
||||||
static PRInt32 GetArrayDimensions(const nsAString& src, PRInt32* dim, nsAString & dst)
|
static PRInt32 GetArrayDimensions(const nsAString& src, PRInt32* aDimensionSizes, nsAString & dst)
|
||||||
{
|
{
|
||||||
dst.Assign(src);
|
dst.Assign(src);
|
||||||
nsReadingIterator < PRUnichar > i1;
|
nsReadingIterator < PRUnichar > i1;
|
||||||
|
@ -1763,7 +1763,7 @@ static PRInt32 GetArrayDimensions(const nsAString& src, PRInt32* dim, nsAString
|
||||||
return -1; // Eliminated white space.
|
return -1; // Eliminated white space.
|
||||||
}
|
}
|
||||||
|
|
||||||
int d = 1; // Counting the dimensions
|
int dimensionCount = 1; // Counting the dimensions
|
||||||
for (;;) { // First look for the matching bracket from reverse and commas.
|
for (;;) { // First look for the matching bracket from reverse and commas.
|
||||||
if (i1 == i2) { // No matching bracket.
|
if (i1 == i2) { // No matching bracket.
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -1773,7 +1773,7 @@ static PRInt32 GetArrayDimensions(const nsAString& src, PRInt32* dim, nsAString
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (c == ',') {
|
if (c == ',') {
|
||||||
d++;
|
dimensionCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int len;
|
int len;
|
||||||
|
@ -1788,7 +1788,7 @@ static PRInt32 GetArrayDimensions(const nsAString& src, PRInt32* dim, nsAString
|
||||||
len = Distance(i1, i3); // Length remaining in string after operation
|
len = Distance(i1, i3); // Length remaining in string after operation
|
||||||
}
|
}
|
||||||
|
|
||||||
if (d > MAX_ARRAY_DIMENSIONS) { // Completely ignore it if too many dimensions.
|
if (dimensionCount > MAX_ARRAY_DIMENSIONS) { // Completely ignore it if too many dimensions.
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1797,8 +1797,8 @@ static PRInt32 GetArrayDimensions(const nsAString& src, PRInt32* dim, nsAString
|
||||||
while (*(--i2) != ']') // Find end bracket again
|
while (*(--i2) != ']') // Find end bracket again
|
||||||
;
|
;
|
||||||
|
|
||||||
d = 0; // Start with first dimension.
|
dimensionCount = 0; // Start with first dimension.
|
||||||
dim[d] = -1;
|
aDimensionSizes[dimensionCount] = -1;
|
||||||
PRBool finished = PR_FALSE; // Disallow space within numbers
|
PRBool finished = PR_FALSE; // Disallow space within numbers
|
||||||
|
|
||||||
while (i1 != i2) {
|
while (i1 != i2) {
|
||||||
|
@ -1806,12 +1806,12 @@ static PRInt32 GetArrayDimensions(const nsAString& src, PRInt32* dim, nsAString
|
||||||
if (c < '0' || c > '9') {
|
if (c < '0' || c > '9') {
|
||||||
// There may be slightly more to do here if alternative radixes are supported.
|
// There may be slightly more to do here if alternative radixes are supported.
|
||||||
if (c <= ' ') { // Accept anything < space as whitespace
|
if (c <= ' ') { // Accept anything < space as whitespace
|
||||||
if (dim[d] >= 0) {
|
if (aDimensionSizes[dimensionCount] >= 0) {
|
||||||
finished = PR_TRUE;
|
finished = PR_TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (c == ',') { // Introducing new dimension
|
else if (c == ',') { // Introducing new dimension
|
||||||
dim[++d] = -1; // Restarting it at -1
|
aDimensionSizes[++dimensionCount] = -1; // Restarting it at -1
|
||||||
finished = PR_FALSE;
|
finished = PR_FALSE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1820,10 +1820,10 @@ static PRInt32 GetArrayDimensions(const nsAString& src, PRInt32* dim, nsAString
|
||||||
if (finished) {
|
if (finished) {
|
||||||
return -1; // Numbers not allowed after white space
|
return -1; // Numbers not allowed after white space
|
||||||
}
|
}
|
||||||
if (dim[d] == -1)
|
if (aDimensionSizes[dimensionCount] == -1)
|
||||||
dim[d] = 0;
|
aDimensionSizes[dimensionCount] = 0;
|
||||||
if (dim[d] < 214748364) {
|
if (aDimensionSizes[dimensionCount] < 214748364) {
|
||||||
dim[d] = dim[d] * 10 + c - '0';
|
aDimensionSizes[dimensionCount] = aDimensionSizes[dimensionCount] * 10 + c - '0';
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return -1; // Number got too big.
|
return -1; // Number got too big.
|
||||||
|
@ -1831,7 +1831,7 @@ static PRInt32 GetArrayDimensions(const nsAString& src, PRInt32* dim, nsAString
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
src.Left(dst, len); // Truncate the string.
|
src.Left(dst, len); // Truncate the string.
|
||||||
return d + 1; // Return the number of dimensions
|
return dimensionCount + 1; // Return the number of dimensions
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1847,28 +1847,75 @@ static PRInt32 GetArrayDimensions(const nsAString& src, PRInt32* dim, nsAString
|
||||||
* within the string result in a return of -1, which is
|
* within the string result in a return of -1, which is
|
||||||
* bad wherever a position string was interpreted.
|
* bad wherever a position string was interpreted.
|
||||||
*/
|
*/
|
||||||
static PRInt32 GetArrayPosition(const nsAString& src, PRInt32 d, PRInt32* dim)
|
static PRInt32 GetArrayPosition(const nsAString& src, PRInt32 aDimensionCount, PRInt32* aDimensionSizes)
|
||||||
{
|
{
|
||||||
PRInt32 pos[MAX_ARRAY_DIMENSIONS];
|
PRInt32 pos[MAX_ARRAY_DIMENSIONS];
|
||||||
nsAutoString leftover;
|
nsAutoString leftover;
|
||||||
PRInt32 result = GetArrayDimensions(src, pos, leftover);
|
PRInt32 result = GetArrayDimensions(src, pos, leftover);
|
||||||
if (result != d // Easy cases where something went wrong
|
if (result != aDimensionCount // Easy cases where something went wrong
|
||||||
|| !leftover.IsEmpty())
|
|| !leftover.IsEmpty())
|
||||||
return -1;
|
return -1;
|
||||||
result = 0;
|
result = 0;
|
||||||
for (PRInt32 i = 0;;) {
|
for (PRInt32 i = 0;;) {
|
||||||
PRInt32 next = pos[i];
|
PRInt32 next = pos[i];
|
||||||
if (next == -1
|
if (next == -1
|
||||||
|| next >= dim[i])
|
|| next >= aDimensionSizes[i])
|
||||||
return -1;
|
return -1;
|
||||||
result = result + next;
|
result = result + next;
|
||||||
if (++i < d) // Multiply for next round.
|
if (++i < aDimensionCount) // Multiply for next round.
|
||||||
result = result * dim[i];
|
result = result * aDimensionSizes[i];
|
||||||
else
|
else
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expand the resulting array out into a nice pseudo-multi-dimensional
|
||||||
|
* array. We trust that the caller guaranteed aDimensionCount >= 1 and that
|
||||||
|
* the other sizes are reasonable (or they couldn't pass us a resultant
|
||||||
|
* array). * The result is produced recursively as:
|
||||||
|
* an array [of arrays [...]] of the specified type.
|
||||||
|
* Variants are used to embed arrays inside of * arrays.
|
||||||
|
*/
|
||||||
|
static nsresult CreateArray(nsIWritableVariant* aResult, PRUint16 aType, const nsIID* aIID,
|
||||||
|
PRInt32 aDimensionCount, PRInt32* aDimensionSizes, PRUint32 aSizeof, PRUint8* aArray)
|
||||||
|
{
|
||||||
|
if (aDimensionCount > 1) { // We cannot reuse variants because they are kept by resulting array
|
||||||
|
PRInt32 count = aDimensionSizes[0];
|
||||||
|
PRUint32 size = aSizeof / count;
|
||||||
|
PRInt32 i;
|
||||||
|
nsIVariant** a = new nsIVariant*[count]; // Create variant array.
|
||||||
|
|
||||||
|
nsresult rc = NS_OK;
|
||||||
|
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
|
nsCOMPtr<nsIWritableVariant> v = do_CreateInstance(NS_VARIANT_CONTRACTID, &rc);
|
||||||
|
if (NS_FAILED(rc))
|
||||||
|
break;
|
||||||
|
nsresult rc = CreateArray(v, aType, aIID, aDimensionCount - 1, aDimensionSizes + 1,
|
||||||
|
size, aArray);
|
||||||
|
if (NS_FAILED(rc))
|
||||||
|
break;
|
||||||
|
NS_ADDREF(v); // Addref for array reference
|
||||||
|
a[i] = v;
|
||||||
|
aArray += size;
|
||||||
|
}
|
||||||
|
if (!NS_FAILED(rc)) {
|
||||||
|
rc = aResult->SetAsArray(nsIDataType::VTYPE_INTERFACE,&NS_GET_IID(nsIVariant),count,a);
|
||||||
|
}
|
||||||
|
for (i = 0; i < count; i++) { // Release variants for array
|
||||||
|
nsIVariant* v = a[i];
|
||||||
|
if (v)
|
||||||
|
v->Release();
|
||||||
|
}
|
||||||
|
delete[] a;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return aResult->SetAsArray(aType,aIID,aDimensionSizes[0],aArray);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Incomplete -- becomes very complex due to variant arrays
|
// Incomplete -- becomes very complex due to variant arrays
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsArrayEncoder::Decode(nsISOAPEncoding * aEncoding,
|
nsArrayEncoder::Decode(nsISOAPEncoding * aEncoding,
|
||||||
|
@ -1881,20 +1928,20 @@ NS_IMETHODIMP
|
||||||
nsAutoString name;
|
nsAutoString name;
|
||||||
nsCOMPtr < nsISchemaType > subtype;
|
nsCOMPtr < nsISchemaType > subtype;
|
||||||
nsAutoString value;
|
nsAutoString value;
|
||||||
PRInt32 d; // Number of dimensions
|
PRInt32 dimensionCount; // Number of dimensions
|
||||||
PRInt32 dim[MAX_ARRAY_DIMENSIONS];
|
PRInt32 dimensionSizes[MAX_ARRAY_DIMENSIONS];
|
||||||
PRInt32 size = -1;
|
PRInt32 size = -1;
|
||||||
nsresult rc;
|
nsresult rc;
|
||||||
if (nsSOAPUtils::GetAttribute(aEncoding, aSource, *nsSOAPUtils::kSOAPEncURI[mSOAPVersion],
|
if (nsSOAPUtils::GetAttribute(aEncoding, aSource, *nsSOAPUtils::kSOAPEncURI[mSOAPVersion],
|
||||||
kSOAPArrayTypeAttribute, value)) {
|
kSOAPArrayTypeAttribute, value)) {
|
||||||
nsAutoString dst;
|
nsAutoString dst;
|
||||||
d = GetArrayDimensions(value, dim, dst);
|
dimensionCount = GetArrayDimensions(value, dimensionSizes, dst);
|
||||||
value.Assign(dst);
|
value.Assign(dst);
|
||||||
|
|
||||||
if (d > 0) {
|
if (dimensionCount > 0) {
|
||||||
PRInt64 tot = 1; // Collect in 64 bits, just to make sure it fits
|
PRInt64 tot = 1; // Collect in 64 bits, just to make sure it fits
|
||||||
for (PRInt32 i = 0; i < d; i++) {
|
for (PRInt32 i = 0; i < dimensionCount; i++) {
|
||||||
PRInt32 next = dim[i];
|
PRInt32 next = dimensionSizes[i];
|
||||||
if (next == -1) {
|
if (next == -1) {
|
||||||
tot = -1;
|
tot = -1;
|
||||||
break;
|
break;
|
||||||
|
@ -1932,28 +1979,28 @@ NS_IMETHODIMP
|
||||||
PRInt32 pos[MAX_ARRAY_DIMENSIONS];
|
PRInt32 pos[MAX_ARRAY_DIMENSIONS];
|
||||||
nsAutoString leftover;
|
nsAutoString leftover;
|
||||||
offset = GetArrayDimensions(value, pos, leftover);
|
offset = GetArrayDimensions(value, pos, leftover);
|
||||||
if (d == -1)
|
if (dimensionCount == -1)
|
||||||
d = offset;
|
dimensionCount = offset;
|
||||||
if (offset == -1 // We have to understand this or report an error
|
if (offset == -1 // We have to understand this or report an error
|
||||||
|| offset != d // But the offset does not need to be understood
|
|| offset != dimensionCount // But the offset does not need to be understood
|
||||||
|| !leftover.IsEmpty())
|
|| !leftover.IsEmpty())
|
||||||
return NS_ERROR_ILLEGAL_VALUE;
|
return NS_ERROR_ILLEGAL_VALUE;
|
||||||
PRInt32 old0 = dim[0];
|
PRInt32 old0 = dimensionSizes[0];
|
||||||
if (dim[0] == -1) { // It is OK to have a offset where dimension 0 is unspecified
|
if (dimensionSizes[0] == -1) { // It is OK to have a offset where dimension 0 is unspecified
|
||||||
dim[0] = 2147483647;
|
dimensionSizes[0] = 2147483647;
|
||||||
}
|
}
|
||||||
offset = 0;
|
offset = 0;
|
||||||
for (PRInt32 i = 0;;) {
|
for (PRInt32 i = 0;;) {
|
||||||
PRInt64 next = pos[i];
|
PRInt64 next = pos[i];
|
||||||
if (next == -1
|
if (next == -1
|
||||||
|| next >= dim[i])
|
|| next >= dimensionSizes[i])
|
||||||
return NS_ERROR_ILLEGAL_VALUE;
|
return NS_ERROR_ILLEGAL_VALUE;
|
||||||
next = (offset + next);
|
next = (offset + next);
|
||||||
if (next > 2147483647)
|
if (next > 2147483647)
|
||||||
return NS_ERROR_ILLEGAL_VALUE;
|
return NS_ERROR_ILLEGAL_VALUE;
|
||||||
offset = (PRInt32)next;
|
offset = (PRInt32)next;
|
||||||
if (++i < d) {
|
if (++i < dimensionCount) {
|
||||||
next = offset * dim[i];
|
next = offset * dimensionSizes[i];
|
||||||
if (next > 2147483647)
|
if (next > 2147483647)
|
||||||
return NS_ERROR_ILLEGAL_VALUE;
|
return NS_ERROR_ILLEGAL_VALUE;
|
||||||
offset = (PRInt32)next;
|
offset = (PRInt32)next;
|
||||||
|
@ -1962,7 +2009,7 @@ NS_IMETHODIMP
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dim[0] = old0;
|
dimensionSizes[0] = old0;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
offset = 0;
|
offset = 0;
|
||||||
|
@ -1971,8 +2018,8 @@ NS_IMETHODIMP
|
||||||
nsCOMPtr<nsIDOMElement> child;
|
nsCOMPtr<nsIDOMElement> child;
|
||||||
nsSOAPUtils::GetFirstChildElement(aSource, getter_AddRefs(child));
|
nsSOAPUtils::GetFirstChildElement(aSource, getter_AddRefs(child));
|
||||||
PRInt32 pp[MAX_ARRAY_DIMENSIONS];
|
PRInt32 pp[MAX_ARRAY_DIMENSIONS];
|
||||||
if (d != -1) {
|
if (dimensionCount != -1) {
|
||||||
for (PRUint32 i = d; i-- != 0;) {
|
for (PRUint32 i = dimensionCount; i-- != 0;) {
|
||||||
pp[i] = 0;
|
pp[i] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1987,16 +2034,16 @@ NS_IMETHODIMP
|
||||||
PRInt32 i = GetArrayDimensions(pos, inc, leftover);
|
PRInt32 i = GetArrayDimensions(pos, inc, leftover);
|
||||||
if (i == -1 // We have to understand this or report an error
|
if (i == -1 // We have to understand this or report an error
|
||||||
|| !leftover.IsEmpty()
|
|| !leftover.IsEmpty()
|
||||||
|| (d != -1
|
|| (dimensionCount != -1
|
||||||
&& d != i))
|
&& dimensionCount != i))
|
||||||
return NS_ERROR_ILLEGAL_VALUE;
|
return NS_ERROR_ILLEGAL_VALUE;
|
||||||
if (d == -1) {
|
if (dimensionCount == -1) {
|
||||||
d = i; // If we never had dimension count before, we do now.
|
dimensionCount = i; // If we never had dimension count before, we do now.
|
||||||
for (PRUint32 i = d; i-- != 0;) {
|
for (PRUint32 i = dimensionCount; i-- != 0;) {
|
||||||
pp[i] = 0;
|
pp[i] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (i = 0; i < d; i++) {
|
for (i = 0; i < dimensionCount; i++) {
|
||||||
PRInt32 n = inc[i];
|
PRInt32 n = inc[i];
|
||||||
if (n == -1) { // Positions must be concrete
|
if (n == -1) { // Positions must be concrete
|
||||||
return NS_ERROR_ILLEGAL_VALUE;
|
return NS_ERROR_ILLEGAL_VALUE;
|
||||||
|
@ -2013,19 +2060,19 @@ NS_IMETHODIMP
|
||||||
nsSOAPUtils::GetNextSiblingElement(child, getter_AddRefs(nextchild));
|
nsSOAPUtils::GetNextSiblingElement(child, getter_AddRefs(nextchild));
|
||||||
child = nextchild;
|
child = nextchild;
|
||||||
}
|
}
|
||||||
if (d == -1) { // If unknown or 1 dimension, unpositioned entries can help
|
if (dimensionCount == -1) { // If unknown or 1 dimension, unpositioned entries can help
|
||||||
d = 1;
|
dimensionCount = 1;
|
||||||
pp[0] = next;
|
pp[0] = next;
|
||||||
}
|
}
|
||||||
else if (d == 1
|
else if (dimensionCount == 1
|
||||||
&& next > pp[0]) {
|
&& next > pp[0]) {
|
||||||
pp[0] = next;
|
pp[0] = next;
|
||||||
}
|
}
|
||||||
PRInt64 tot = 1; // Collect in 64 bits, just to make sure it fits
|
PRInt64 tot = 1; // Collect in 64 bits, just to make sure it fits
|
||||||
for (PRInt32 i = 0; i < d; i++) {
|
for (PRInt32 i = 0; i < dimensionCount; i++) {
|
||||||
PRInt32 next = dim[i];
|
PRInt32 next = dimensionSizes[i];
|
||||||
if (next == -1) { // Only derive those with no other declaration
|
if (next == -1) { // Only derive those with no other declaration
|
||||||
dim[i] = next = pp[i];
|
dimensionSizes[i] = next = pp[i];
|
||||||
}
|
}
|
||||||
tot = tot * next;
|
tot = tot * next;
|
||||||
if (tot > 2147483647) {
|
if (tot > 2147483647) {
|
||||||
|
@ -2051,7 +2098,7 @@ NS_IMETHODIMP
|
||||||
PRInt32 p;\
|
PRInt32 p;\
|
||||||
if (nsSOAPUtils::GetAttribute(aEncoding, aSource, *nsSOAPUtils::kSOAPEncURI[mSOAPVersion],\
|
if (nsSOAPUtils::GetAttribute(aEncoding, aSource, *nsSOAPUtils::kSOAPEncURI[mSOAPVersion],\
|
||||||
kSOAPArrayPositionAttribute, pos)) {\
|
kSOAPArrayPositionAttribute, pos)) {\
|
||||||
PRInt32 p = GetArrayPosition(pos, d, dim);\
|
PRInt32 p = GetArrayPosition(pos, dimensionCount, dimensionSizes);\
|
||||||
if (p == -1) {\
|
if (p == -1) {\
|
||||||
rc = NS_ERROR_ILLEGAL_VALUE;\
|
rc = NS_ERROR_ILLEGAL_VALUE;\
|
||||||
break;\
|
break;\
|
||||||
|
@ -2077,7 +2124,7 @@ NS_IMETHODIMP
|
||||||
child = next;\
|
child = next;\
|
||||||
}\
|
}\
|
||||||
if (!NS_FAILED(rc)) {\
|
if (!NS_FAILED(rc)) {\
|
||||||
rc = result->SetAsArray(nsIDataType::VTYPE_##VTYPE,iid,size,a);\
|
rc = CreateArray(result, nsIDataType::VTYPE_##VTYPE,iid,dimensionCount,dimensionSizes,sizeof(a[0])*size,(PRUint8*)a);\
|
||||||
}\
|
}\
|
||||||
Free\
|
Free\
|
||||||
delete[] a;\
|
delete[] a;\
|
||||||
|
|
|
@ -444,15 +444,6 @@ NS_IMETHODIMP
|
||||||
if (NS_FAILED(rv))
|
if (NS_FAILED(rv))
|
||||||
return rv;
|
return rv;
|
||||||
body = call;
|
body = call;
|
||||||
nsAutoString prefix;
|
|
||||||
rv = nsSOAPUtils::MakeNamespacePrefix(encoding, body, aTargetObjectURI, prefix);
|
|
||||||
if (NS_FAILED(rv))
|
|
||||||
return rv;
|
|
||||||
if (!prefix.IsEmpty()) {
|
|
||||||
rv = body->SetPrefix(prefix);
|
|
||||||
if (NS_FAILED(rv))
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// Encode and add all of the parameters into the body
|
// Encode and add all of the parameters into the body
|
||||||
|
|
||||||
|
|
|
@ -1746,7 +1746,7 @@ NS_IMETHODIMP
|
||||||
* if specifying a position. In these cases, the
|
* if specifying a position. In these cases, the
|
||||||
* bracketted values are removed.
|
* bracketted values are removed.
|
||||||
*/
|
*/
|
||||||
static PRInt32 GetArrayDimensions(const nsAString& src, PRInt32* dim, nsAString & dst)
|
static PRInt32 GetArrayDimensions(const nsAString& src, PRInt32* aDimensionSizes, nsAString & dst)
|
||||||
{
|
{
|
||||||
dst.Assign(src);
|
dst.Assign(src);
|
||||||
nsReadingIterator < PRUnichar > i1;
|
nsReadingIterator < PRUnichar > i1;
|
||||||
|
@ -1763,7 +1763,7 @@ static PRInt32 GetArrayDimensions(const nsAString& src, PRInt32* dim, nsAString
|
||||||
return -1; // Eliminated white space.
|
return -1; // Eliminated white space.
|
||||||
}
|
}
|
||||||
|
|
||||||
int d = 1; // Counting the dimensions
|
int dimensionCount = 1; // Counting the dimensions
|
||||||
for (;;) { // First look for the matching bracket from reverse and commas.
|
for (;;) { // First look for the matching bracket from reverse and commas.
|
||||||
if (i1 == i2) { // No matching bracket.
|
if (i1 == i2) { // No matching bracket.
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -1773,7 +1773,7 @@ static PRInt32 GetArrayDimensions(const nsAString& src, PRInt32* dim, nsAString
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (c == ',') {
|
if (c == ',') {
|
||||||
d++;
|
dimensionCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int len;
|
int len;
|
||||||
|
@ -1788,7 +1788,7 @@ static PRInt32 GetArrayDimensions(const nsAString& src, PRInt32* dim, nsAString
|
||||||
len = Distance(i1, i3); // Length remaining in string after operation
|
len = Distance(i1, i3); // Length remaining in string after operation
|
||||||
}
|
}
|
||||||
|
|
||||||
if (d > MAX_ARRAY_DIMENSIONS) { // Completely ignore it if too many dimensions.
|
if (dimensionCount > MAX_ARRAY_DIMENSIONS) { // Completely ignore it if too many dimensions.
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1797,8 +1797,8 @@ static PRInt32 GetArrayDimensions(const nsAString& src, PRInt32* dim, nsAString
|
||||||
while (*(--i2) != ']') // Find end bracket again
|
while (*(--i2) != ']') // Find end bracket again
|
||||||
;
|
;
|
||||||
|
|
||||||
d = 0; // Start with first dimension.
|
dimensionCount = 0; // Start with first dimension.
|
||||||
dim[d] = -1;
|
aDimensionSizes[dimensionCount] = -1;
|
||||||
PRBool finished = PR_FALSE; // Disallow space within numbers
|
PRBool finished = PR_FALSE; // Disallow space within numbers
|
||||||
|
|
||||||
while (i1 != i2) {
|
while (i1 != i2) {
|
||||||
|
@ -1806,12 +1806,12 @@ static PRInt32 GetArrayDimensions(const nsAString& src, PRInt32* dim, nsAString
|
||||||
if (c < '0' || c > '9') {
|
if (c < '0' || c > '9') {
|
||||||
// There may be slightly more to do here if alternative radixes are supported.
|
// There may be slightly more to do here if alternative radixes are supported.
|
||||||
if (c <= ' ') { // Accept anything < space as whitespace
|
if (c <= ' ') { // Accept anything < space as whitespace
|
||||||
if (dim[d] >= 0) {
|
if (aDimensionSizes[dimensionCount] >= 0) {
|
||||||
finished = PR_TRUE;
|
finished = PR_TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (c == ',') { // Introducing new dimension
|
else if (c == ',') { // Introducing new dimension
|
||||||
dim[++d] = -1; // Restarting it at -1
|
aDimensionSizes[++dimensionCount] = -1; // Restarting it at -1
|
||||||
finished = PR_FALSE;
|
finished = PR_FALSE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1820,10 +1820,10 @@ static PRInt32 GetArrayDimensions(const nsAString& src, PRInt32* dim, nsAString
|
||||||
if (finished) {
|
if (finished) {
|
||||||
return -1; // Numbers not allowed after white space
|
return -1; // Numbers not allowed after white space
|
||||||
}
|
}
|
||||||
if (dim[d] == -1)
|
if (aDimensionSizes[dimensionCount] == -1)
|
||||||
dim[d] = 0;
|
aDimensionSizes[dimensionCount] = 0;
|
||||||
if (dim[d] < 214748364) {
|
if (aDimensionSizes[dimensionCount] < 214748364) {
|
||||||
dim[d] = dim[d] * 10 + c - '0';
|
aDimensionSizes[dimensionCount] = aDimensionSizes[dimensionCount] * 10 + c - '0';
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return -1; // Number got too big.
|
return -1; // Number got too big.
|
||||||
|
@ -1831,7 +1831,7 @@ static PRInt32 GetArrayDimensions(const nsAString& src, PRInt32* dim, nsAString
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
src.Left(dst, len); // Truncate the string.
|
src.Left(dst, len); // Truncate the string.
|
||||||
return d + 1; // Return the number of dimensions
|
return dimensionCount + 1; // Return the number of dimensions
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1847,28 +1847,75 @@ static PRInt32 GetArrayDimensions(const nsAString& src, PRInt32* dim, nsAString
|
||||||
* within the string result in a return of -1, which is
|
* within the string result in a return of -1, which is
|
||||||
* bad wherever a position string was interpreted.
|
* bad wherever a position string was interpreted.
|
||||||
*/
|
*/
|
||||||
static PRInt32 GetArrayPosition(const nsAString& src, PRInt32 d, PRInt32* dim)
|
static PRInt32 GetArrayPosition(const nsAString& src, PRInt32 aDimensionCount, PRInt32* aDimensionSizes)
|
||||||
{
|
{
|
||||||
PRInt32 pos[MAX_ARRAY_DIMENSIONS];
|
PRInt32 pos[MAX_ARRAY_DIMENSIONS];
|
||||||
nsAutoString leftover;
|
nsAutoString leftover;
|
||||||
PRInt32 result = GetArrayDimensions(src, pos, leftover);
|
PRInt32 result = GetArrayDimensions(src, pos, leftover);
|
||||||
if (result != d // Easy cases where something went wrong
|
if (result != aDimensionCount // Easy cases where something went wrong
|
||||||
|| !leftover.IsEmpty())
|
|| !leftover.IsEmpty())
|
||||||
return -1;
|
return -1;
|
||||||
result = 0;
|
result = 0;
|
||||||
for (PRInt32 i = 0;;) {
|
for (PRInt32 i = 0;;) {
|
||||||
PRInt32 next = pos[i];
|
PRInt32 next = pos[i];
|
||||||
if (next == -1
|
if (next == -1
|
||||||
|| next >= dim[i])
|
|| next >= aDimensionSizes[i])
|
||||||
return -1;
|
return -1;
|
||||||
result = result + next;
|
result = result + next;
|
||||||
if (++i < d) // Multiply for next round.
|
if (++i < aDimensionCount) // Multiply for next round.
|
||||||
result = result * dim[i];
|
result = result * aDimensionSizes[i];
|
||||||
else
|
else
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expand the resulting array out into a nice pseudo-multi-dimensional
|
||||||
|
* array. We trust that the caller guaranteed aDimensionCount >= 1 and that
|
||||||
|
* the other sizes are reasonable (or they couldn't pass us a resultant
|
||||||
|
* array). * The result is produced recursively as:
|
||||||
|
* an array [of arrays [...]] of the specified type.
|
||||||
|
* Variants are used to embed arrays inside of * arrays.
|
||||||
|
*/
|
||||||
|
static nsresult CreateArray(nsIWritableVariant* aResult, PRUint16 aType, const nsIID* aIID,
|
||||||
|
PRInt32 aDimensionCount, PRInt32* aDimensionSizes, PRUint32 aSizeof, PRUint8* aArray)
|
||||||
|
{
|
||||||
|
if (aDimensionCount > 1) { // We cannot reuse variants because they are kept by resulting array
|
||||||
|
PRInt32 count = aDimensionSizes[0];
|
||||||
|
PRUint32 size = aSizeof / count;
|
||||||
|
PRInt32 i;
|
||||||
|
nsIVariant** a = new nsIVariant*[count]; // Create variant array.
|
||||||
|
|
||||||
|
nsresult rc = NS_OK;
|
||||||
|
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
|
nsCOMPtr<nsIWritableVariant> v = do_CreateInstance(NS_VARIANT_CONTRACTID, &rc);
|
||||||
|
if (NS_FAILED(rc))
|
||||||
|
break;
|
||||||
|
nsresult rc = CreateArray(v, aType, aIID, aDimensionCount - 1, aDimensionSizes + 1,
|
||||||
|
size, aArray);
|
||||||
|
if (NS_FAILED(rc))
|
||||||
|
break;
|
||||||
|
NS_ADDREF(v); // Addref for array reference
|
||||||
|
a[i] = v;
|
||||||
|
aArray += size;
|
||||||
|
}
|
||||||
|
if (!NS_FAILED(rc)) {
|
||||||
|
rc = aResult->SetAsArray(nsIDataType::VTYPE_INTERFACE,&NS_GET_IID(nsIVariant),count,a);
|
||||||
|
}
|
||||||
|
for (i = 0; i < count; i++) { // Release variants for array
|
||||||
|
nsIVariant* v = a[i];
|
||||||
|
if (v)
|
||||||
|
v->Release();
|
||||||
|
}
|
||||||
|
delete[] a;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return aResult->SetAsArray(aType,aIID,aDimensionSizes[0],aArray);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Incomplete -- becomes very complex due to variant arrays
|
// Incomplete -- becomes very complex due to variant arrays
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsArrayEncoder::Decode(nsISOAPEncoding * aEncoding,
|
nsArrayEncoder::Decode(nsISOAPEncoding * aEncoding,
|
||||||
|
@ -1881,20 +1928,20 @@ NS_IMETHODIMP
|
||||||
nsAutoString name;
|
nsAutoString name;
|
||||||
nsCOMPtr < nsISchemaType > subtype;
|
nsCOMPtr < nsISchemaType > subtype;
|
||||||
nsAutoString value;
|
nsAutoString value;
|
||||||
PRInt32 d; // Number of dimensions
|
PRInt32 dimensionCount; // Number of dimensions
|
||||||
PRInt32 dim[MAX_ARRAY_DIMENSIONS];
|
PRInt32 dimensionSizes[MAX_ARRAY_DIMENSIONS];
|
||||||
PRInt32 size = -1;
|
PRInt32 size = -1;
|
||||||
nsresult rc;
|
nsresult rc;
|
||||||
if (nsSOAPUtils::GetAttribute(aEncoding, aSource, *nsSOAPUtils::kSOAPEncURI[mSOAPVersion],
|
if (nsSOAPUtils::GetAttribute(aEncoding, aSource, *nsSOAPUtils::kSOAPEncURI[mSOAPVersion],
|
||||||
kSOAPArrayTypeAttribute, value)) {
|
kSOAPArrayTypeAttribute, value)) {
|
||||||
nsAutoString dst;
|
nsAutoString dst;
|
||||||
d = GetArrayDimensions(value, dim, dst);
|
dimensionCount = GetArrayDimensions(value, dimensionSizes, dst);
|
||||||
value.Assign(dst);
|
value.Assign(dst);
|
||||||
|
|
||||||
if (d > 0) {
|
if (dimensionCount > 0) {
|
||||||
PRInt64 tot = 1; // Collect in 64 bits, just to make sure it fits
|
PRInt64 tot = 1; // Collect in 64 bits, just to make sure it fits
|
||||||
for (PRInt32 i = 0; i < d; i++) {
|
for (PRInt32 i = 0; i < dimensionCount; i++) {
|
||||||
PRInt32 next = dim[i];
|
PRInt32 next = dimensionSizes[i];
|
||||||
if (next == -1) {
|
if (next == -1) {
|
||||||
tot = -1;
|
tot = -1;
|
||||||
break;
|
break;
|
||||||
|
@ -1932,28 +1979,28 @@ NS_IMETHODIMP
|
||||||
PRInt32 pos[MAX_ARRAY_DIMENSIONS];
|
PRInt32 pos[MAX_ARRAY_DIMENSIONS];
|
||||||
nsAutoString leftover;
|
nsAutoString leftover;
|
||||||
offset = GetArrayDimensions(value, pos, leftover);
|
offset = GetArrayDimensions(value, pos, leftover);
|
||||||
if (d == -1)
|
if (dimensionCount == -1)
|
||||||
d = offset;
|
dimensionCount = offset;
|
||||||
if (offset == -1 // We have to understand this or report an error
|
if (offset == -1 // We have to understand this or report an error
|
||||||
|| offset != d // But the offset does not need to be understood
|
|| offset != dimensionCount // But the offset does not need to be understood
|
||||||
|| !leftover.IsEmpty())
|
|| !leftover.IsEmpty())
|
||||||
return NS_ERROR_ILLEGAL_VALUE;
|
return NS_ERROR_ILLEGAL_VALUE;
|
||||||
PRInt32 old0 = dim[0];
|
PRInt32 old0 = dimensionSizes[0];
|
||||||
if (dim[0] == -1) { // It is OK to have a offset where dimension 0 is unspecified
|
if (dimensionSizes[0] == -1) { // It is OK to have a offset where dimension 0 is unspecified
|
||||||
dim[0] = 2147483647;
|
dimensionSizes[0] = 2147483647;
|
||||||
}
|
}
|
||||||
offset = 0;
|
offset = 0;
|
||||||
for (PRInt32 i = 0;;) {
|
for (PRInt32 i = 0;;) {
|
||||||
PRInt64 next = pos[i];
|
PRInt64 next = pos[i];
|
||||||
if (next == -1
|
if (next == -1
|
||||||
|| next >= dim[i])
|
|| next >= dimensionSizes[i])
|
||||||
return NS_ERROR_ILLEGAL_VALUE;
|
return NS_ERROR_ILLEGAL_VALUE;
|
||||||
next = (offset + next);
|
next = (offset + next);
|
||||||
if (next > 2147483647)
|
if (next > 2147483647)
|
||||||
return NS_ERROR_ILLEGAL_VALUE;
|
return NS_ERROR_ILLEGAL_VALUE;
|
||||||
offset = (PRInt32)next;
|
offset = (PRInt32)next;
|
||||||
if (++i < d) {
|
if (++i < dimensionCount) {
|
||||||
next = offset * dim[i];
|
next = offset * dimensionSizes[i];
|
||||||
if (next > 2147483647)
|
if (next > 2147483647)
|
||||||
return NS_ERROR_ILLEGAL_VALUE;
|
return NS_ERROR_ILLEGAL_VALUE;
|
||||||
offset = (PRInt32)next;
|
offset = (PRInt32)next;
|
||||||
|
@ -1962,7 +2009,7 @@ NS_IMETHODIMP
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dim[0] = old0;
|
dimensionSizes[0] = old0;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
offset = 0;
|
offset = 0;
|
||||||
|
@ -1971,8 +2018,8 @@ NS_IMETHODIMP
|
||||||
nsCOMPtr<nsIDOMElement> child;
|
nsCOMPtr<nsIDOMElement> child;
|
||||||
nsSOAPUtils::GetFirstChildElement(aSource, getter_AddRefs(child));
|
nsSOAPUtils::GetFirstChildElement(aSource, getter_AddRefs(child));
|
||||||
PRInt32 pp[MAX_ARRAY_DIMENSIONS];
|
PRInt32 pp[MAX_ARRAY_DIMENSIONS];
|
||||||
if (d != -1) {
|
if (dimensionCount != -1) {
|
||||||
for (PRUint32 i = d; i-- != 0;) {
|
for (PRUint32 i = dimensionCount; i-- != 0;) {
|
||||||
pp[i] = 0;
|
pp[i] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1987,16 +2034,16 @@ NS_IMETHODIMP
|
||||||
PRInt32 i = GetArrayDimensions(pos, inc, leftover);
|
PRInt32 i = GetArrayDimensions(pos, inc, leftover);
|
||||||
if (i == -1 // We have to understand this or report an error
|
if (i == -1 // We have to understand this or report an error
|
||||||
|| !leftover.IsEmpty()
|
|| !leftover.IsEmpty()
|
||||||
|| (d != -1
|
|| (dimensionCount != -1
|
||||||
&& d != i))
|
&& dimensionCount != i))
|
||||||
return NS_ERROR_ILLEGAL_VALUE;
|
return NS_ERROR_ILLEGAL_VALUE;
|
||||||
if (d == -1) {
|
if (dimensionCount == -1) {
|
||||||
d = i; // If we never had dimension count before, we do now.
|
dimensionCount = i; // If we never had dimension count before, we do now.
|
||||||
for (PRUint32 i = d; i-- != 0;) {
|
for (PRUint32 i = dimensionCount; i-- != 0;) {
|
||||||
pp[i] = 0;
|
pp[i] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (i = 0; i < d; i++) {
|
for (i = 0; i < dimensionCount; i++) {
|
||||||
PRInt32 n = inc[i];
|
PRInt32 n = inc[i];
|
||||||
if (n == -1) { // Positions must be concrete
|
if (n == -1) { // Positions must be concrete
|
||||||
return NS_ERROR_ILLEGAL_VALUE;
|
return NS_ERROR_ILLEGAL_VALUE;
|
||||||
|
@ -2013,19 +2060,19 @@ NS_IMETHODIMP
|
||||||
nsSOAPUtils::GetNextSiblingElement(child, getter_AddRefs(nextchild));
|
nsSOAPUtils::GetNextSiblingElement(child, getter_AddRefs(nextchild));
|
||||||
child = nextchild;
|
child = nextchild;
|
||||||
}
|
}
|
||||||
if (d == -1) { // If unknown or 1 dimension, unpositioned entries can help
|
if (dimensionCount == -1) { // If unknown or 1 dimension, unpositioned entries can help
|
||||||
d = 1;
|
dimensionCount = 1;
|
||||||
pp[0] = next;
|
pp[0] = next;
|
||||||
}
|
}
|
||||||
else if (d == 1
|
else if (dimensionCount == 1
|
||||||
&& next > pp[0]) {
|
&& next > pp[0]) {
|
||||||
pp[0] = next;
|
pp[0] = next;
|
||||||
}
|
}
|
||||||
PRInt64 tot = 1; // Collect in 64 bits, just to make sure it fits
|
PRInt64 tot = 1; // Collect in 64 bits, just to make sure it fits
|
||||||
for (PRInt32 i = 0; i < d; i++) {
|
for (PRInt32 i = 0; i < dimensionCount; i++) {
|
||||||
PRInt32 next = dim[i];
|
PRInt32 next = dimensionSizes[i];
|
||||||
if (next == -1) { // Only derive those with no other declaration
|
if (next == -1) { // Only derive those with no other declaration
|
||||||
dim[i] = next = pp[i];
|
dimensionSizes[i] = next = pp[i];
|
||||||
}
|
}
|
||||||
tot = tot * next;
|
tot = tot * next;
|
||||||
if (tot > 2147483647) {
|
if (tot > 2147483647) {
|
||||||
|
@ -2051,7 +2098,7 @@ NS_IMETHODIMP
|
||||||
PRInt32 p;\
|
PRInt32 p;\
|
||||||
if (nsSOAPUtils::GetAttribute(aEncoding, aSource, *nsSOAPUtils::kSOAPEncURI[mSOAPVersion],\
|
if (nsSOAPUtils::GetAttribute(aEncoding, aSource, *nsSOAPUtils::kSOAPEncURI[mSOAPVersion],\
|
||||||
kSOAPArrayPositionAttribute, pos)) {\
|
kSOAPArrayPositionAttribute, pos)) {\
|
||||||
PRInt32 p = GetArrayPosition(pos, d, dim);\
|
PRInt32 p = GetArrayPosition(pos, dimensionCount, dimensionSizes);\
|
||||||
if (p == -1) {\
|
if (p == -1) {\
|
||||||
rc = NS_ERROR_ILLEGAL_VALUE;\
|
rc = NS_ERROR_ILLEGAL_VALUE;\
|
||||||
break;\
|
break;\
|
||||||
|
@ -2077,7 +2124,7 @@ NS_IMETHODIMP
|
||||||
child = next;\
|
child = next;\
|
||||||
}\
|
}\
|
||||||
if (!NS_FAILED(rc)) {\
|
if (!NS_FAILED(rc)) {\
|
||||||
rc = result->SetAsArray(nsIDataType::VTYPE_##VTYPE,iid,size,a);\
|
rc = CreateArray(result, nsIDataType::VTYPE_##VTYPE,iid,dimensionCount,dimensionSizes,sizeof(a[0])*size,(PRUint8*)a);\
|
||||||
}\
|
}\
|
||||||
Free\
|
Free\
|
||||||
delete[] a;\
|
delete[] a;\
|
||||||
|
|
|
@ -444,15 +444,6 @@ NS_IMETHODIMP
|
||||||
if (NS_FAILED(rv))
|
if (NS_FAILED(rv))
|
||||||
return rv;
|
return rv;
|
||||||
body = call;
|
body = call;
|
||||||
nsAutoString prefix;
|
|
||||||
rv = nsSOAPUtils::MakeNamespacePrefix(encoding, body, aTargetObjectURI, prefix);
|
|
||||||
if (NS_FAILED(rv))
|
|
||||||
return rv;
|
|
||||||
if (!prefix.IsEmpty()) {
|
|
||||||
rv = body->SetPrefix(prefix);
|
|
||||||
if (NS_FAILED(rv))
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// Encode and add all of the parameters into the body
|
// Encode and add all of the parameters into the body
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче