MOZ_WSP. This was only done inside of the MOZ_SOAP defines. Tested build with and without SOAP define. This permits SOAP to be built without web service proxies. Related to bug 107795, but needed whether or not SOAP becomes part of default build. sr=vidur. SOAP is not part of default build. git-svn-id: svn://10.0.0.236/trunk@114842 18797224-902f-48f8-a5cc-f745e15eee43
3254 lines
116 KiB
C++
3254 lines
116 KiB
C++
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* ***** BEGIN LICENSE BLOCK *****
|
|
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
|
*
|
|
* The contents of this file are subject to the Netscape Public License
|
|
* Version 1.1 (the "License"); you may not use this file except in
|
|
* compliance with the License. You may obtain a copy of the License at
|
|
* http://www.mozilla.org/NPL/
|
|
*
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
* for the specific language governing rights and limitations under the
|
|
* License.
|
|
*
|
|
* The Original Code is mozilla.org code.
|
|
*
|
|
* The Initial Developer of the Original Code is
|
|
* Netscape Communications Corporation.
|
|
* Portions created by the Initial Developer are Copyright (C) 2001
|
|
* the Initial Developer. All Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
*
|
|
*
|
|
* Alternatively, the contents of this file may be used under the terms of
|
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
* of those above. If you wish to allow use of your version of this file only
|
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
* use your version of this file under the terms of the NPL, indicate your
|
|
* decision by deleting the provisions above and replace them with the notice
|
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
* the provisions above, a recipient may use your version of this file under
|
|
* the terms of any one of the NPL, the GPL or the LGPL.
|
|
*
|
|
* ***** END LICENSE BLOCK ***** */
|
|
|
|
#include "nsDefaultSOAPEncoder.h"
|
|
#include "nsSOAPUtils.h"
|
|
#include "nsSOAPParameter.h"
|
|
#include "nsISOAPAttachments.h"
|
|
#include "nsXPIDLString.h"
|
|
#include "nsIDOMDocument.h"
|
|
#include "nsIDOMText.h"
|
|
#include "nsCOMPtr.h"
|
|
#include "nsISchema.h"
|
|
#include "nsIComponentManager.h"
|
|
#include "nsIServiceManager.h"
|
|
#include "nsISupportsPrimitives.h"
|
|
#include "nsIDOMParser.h"
|
|
#include "nsSOAPUtils.h"
|
|
#include "nsISOAPEncoding.h"
|
|
#include "nsISOAPEncoder.h"
|
|
#include "nsISOAPDecoder.h"
|
|
#include "nsISOAPMessage.h"
|
|
#include "nsSOAPException.h"
|
|
#include "prprf.h"
|
|
#include "prdtoa.h"
|
|
#include "nsReadableUtils.h"
|
|
#include "nsIDOMNamedNodeMap.h"
|
|
#include "nsIDOMAttr.h"
|
|
#include "nsPrintfCString.h"
|
|
#include "nsISOAPPropertyBagMutator.h"
|
|
#include "nsIPropertyBag.h"
|
|
#include "nsSupportsArray.h"
|
|
|
|
static NS_NAMED_LITERAL_STRING(kEmpty, "");
|
|
|
|
static NS_NAMED_LITERAL_STRING(kNull, "null");
|
|
static NS_NAMED_LITERAL_STRING(kNil, "nil");
|
|
|
|
static NS_NAMED_LITERAL_STRING(kSOAPArrayTypeAttribute, "arrayType");
|
|
static NS_NAMED_LITERAL_STRING(kSOAPArrayOffsetAttribute, "offset");
|
|
static NS_NAMED_LITERAL_STRING(kSOAPArrayPositionAttribute, "position");
|
|
|
|
static NS_NAMED_LITERAL_STRING(kAnyTypeSchemaType, "anyType");
|
|
static NS_NAMED_LITERAL_STRING(kAnySimpleTypeSchemaType, "anySimpleType");
|
|
static NS_NAMED_LITERAL_STRING(kArraySOAPType, "Array");
|
|
static NS_NAMED_LITERAL_STRING(kStructSOAPType, "Struct");
|
|
|
|
static NS_NAMED_LITERAL_STRING(kStringSchemaType, "string");
|
|
static NS_NAMED_LITERAL_STRING(kBooleanSchemaType, "boolean");
|
|
static NS_NAMED_LITERAL_STRING(kFloatSchemaType, "float");
|
|
static NS_NAMED_LITERAL_STRING(kDoubleSchemaType, "double");
|
|
static NS_NAMED_LITERAL_STRING(kLongSchemaType, "long");
|
|
static NS_NAMED_LITERAL_STRING(kIntSchemaType, "int");
|
|
static NS_NAMED_LITERAL_STRING(kShortSchemaType, "short");
|
|
static NS_NAMED_LITERAL_STRING(kByteSchemaType, "byte");
|
|
static NS_NAMED_LITERAL_STRING(kUnsignedLongSchemaType, "unsignedLong");
|
|
static NS_NAMED_LITERAL_STRING(kUnsignedIntSchemaType, "unsignedInt");
|
|
static NS_NAMED_LITERAL_STRING(kUnsignedShortSchemaType, "unsignedShort");
|
|
static NS_NAMED_LITERAL_STRING(kUnsignedByteSchemaType, "unsignedByte");
|
|
|
|
static NS_NAMED_LITERAL_STRING(kDurationSchemaType, "duration");
|
|
static NS_NAMED_LITERAL_STRING(kDateTimeSchemaType, "dateTime");
|
|
static NS_NAMED_LITERAL_STRING(kTimeSchemaType, "time");
|
|
static NS_NAMED_LITERAL_STRING(kDateSchemaType, "date");
|
|
static NS_NAMED_LITERAL_STRING(kGYearMonthSchemaType, "gYearMonth");
|
|
static NS_NAMED_LITERAL_STRING(kGYearSchemaType, "gYear");
|
|
static NS_NAMED_LITERAL_STRING(kGMonthDaySchemaType, "gMonthDay");
|
|
static NS_NAMED_LITERAL_STRING(kGDaySchemaType, "gDay");
|
|
static NS_NAMED_LITERAL_STRING(kGMonthSchemaType, "gMonth");
|
|
static NS_NAMED_LITERAL_STRING(kHexBinarySchemaType, "hexBinary");
|
|
static NS_NAMED_LITERAL_STRING(kBase64BinarySchemaType, "base64Binary");
|
|
static NS_NAMED_LITERAL_STRING(kAnyURISchemaType, "anyURI");
|
|
static NS_NAMED_LITERAL_STRING(kQNameSchemaType, "QName");
|
|
static NS_NAMED_LITERAL_STRING(kNOTATIONSchemaType, "NOTATION");
|
|
static NS_NAMED_LITERAL_STRING(kNormalizedStringSchemaType, "normalizedString");
|
|
static NS_NAMED_LITERAL_STRING(kTokenSchemaType, "token");
|
|
static NS_NAMED_LITERAL_STRING(kLanguageSchemaType, "language");
|
|
static NS_NAMED_LITERAL_STRING(kNMTOKENSchemaType, "NMTOKEN");
|
|
static NS_NAMED_LITERAL_STRING(kNMTOKENSSchemaType, "NMTOKENS");
|
|
static NS_NAMED_LITERAL_STRING(kNameSchemaType, "Name");
|
|
static NS_NAMED_LITERAL_STRING(kNCNameSchemaType, "NCName");
|
|
static NS_NAMED_LITERAL_STRING(kIDSchemaType, "ID");
|
|
static NS_NAMED_LITERAL_STRING(kIDREFSchemaType, "IDREF");
|
|
static NS_NAMED_LITERAL_STRING(kIDREFSSchemaType, "IDREFS");
|
|
static NS_NAMED_LITERAL_STRING(kENTITYSchemaType, "ENTITY");
|
|
static NS_NAMED_LITERAL_STRING(kENTITIESSchemaType, "ENTITIES");
|
|
static NS_NAMED_LITERAL_STRING(kDecimalSchemaType, "decimal");
|
|
static NS_NAMED_LITERAL_STRING(kIntegerSchemaType, "integer");
|
|
static NS_NAMED_LITERAL_STRING(kNonPositiveIntegerSchemaType,
|
|
"nonPositiveInteger");
|
|
static NS_NAMED_LITERAL_STRING(kNegativeIntegerSchemaType, "negativeInteger");
|
|
static NS_NAMED_LITERAL_STRING(kNonNegativeIntegerSchemaType,
|
|
"nonNegativeInteger");
|
|
static NS_NAMED_LITERAL_STRING(kPositiveIntegerSchemaType, "positiveInteger");
|
|
|
|
#define DECLARE_ENCODER(name) \
|
|
class ns##name##Encoder : \
|
|
public nsISOAPEncoder, \
|
|
public nsISOAPDecoder \
|
|
{\
|
|
public:\
|
|
ns##name##Encoder();\
|
|
ns##name##Encoder(PRUint16 aSOAPVersion);\
|
|
virtual ~ns##name##Encoder();\
|
|
PRUint16 mSOAPVersion;\
|
|
NS_DECL_ISUPPORTS\
|
|
NS_DECL_NSISOAPENCODER\
|
|
NS_DECL_NSISOAPDECODER\
|
|
};\
|
|
NS_IMPL_ISUPPORTS2(ns##name##Encoder,nsISOAPEncoder,nsISOAPDecoder) \
|
|
ns##name##Encoder::ns##name##Encoder(PRUint16 aSOAPVersion) {NS_INIT_ISUPPORTS();mSOAPVersion=aSOAPVersion;}\
|
|
ns##name##Encoder::~ns##name##Encoder() {}
|
|
|
|
// All encoders must be first declared and then registered.
|
|
DECLARE_ENCODER(Default)
|
|
DECLARE_ENCODER(AnyType)
|
|
DECLARE_ENCODER(AnySimpleType)
|
|
DECLARE_ENCODER(Array)
|
|
DECLARE_ENCODER(Struct)
|
|
DECLARE_ENCODER(String)
|
|
DECLARE_ENCODER(Boolean)
|
|
DECLARE_ENCODER(Double)
|
|
DECLARE_ENCODER(Float)
|
|
DECLARE_ENCODER(Long)
|
|
DECLARE_ENCODER(Int)
|
|
DECLARE_ENCODER(Short)
|
|
DECLARE_ENCODER(Byte)
|
|
DECLARE_ENCODER(UnsignedLong)
|
|
DECLARE_ENCODER(UnsignedInt)
|
|
DECLARE_ENCODER(UnsignedShort)
|
|
DECLARE_ENCODER(UnsignedByte)
|
|
|
|
/**
|
|
* This now separates the version with respect to the SOAP specification from the version
|
|
* with respect to the schema version (using the same constants for both). This permits
|
|
* a user of a SOAP 1.1 or 1.2 encoding to choose which encoding to encode to.
|
|
*/
|
|
#define REGISTER_ENCODER(name,type,uri) \
|
|
{\
|
|
ns##name##Encoder *handler = new ns##name##Encoder(version);\
|
|
nsAutoString encodingKey;\
|
|
SOAPEncodingKey(uri, k##name##type##Type, encodingKey);\
|
|
SetEncoder(encodingKey, handler); \
|
|
SetDecoder(encodingKey, handler); \
|
|
}
|
|
#define REGISTER_SCHEMA_ENCODER(name) REGISTER_ENCODER(name,Schema,nsSOAPUtils::kXSURI)
|
|
#define REGISTER_SOAP_ENCODER(name) REGISTER_ENCODER(name,SOAP,nsSOAPUtils::kSOAPEncURI)
|
|
|
|
#define REGISTER_ENCODERS \
|
|
{\
|
|
nsDefaultEncoder *handler = new nsDefaultEncoder(version);\
|
|
SetDefaultEncoder(handler);\
|
|
SetDefaultDecoder(handler);\
|
|
}\
|
|
REGISTER_SCHEMA_ENCODER(AnyType) \
|
|
REGISTER_SCHEMA_ENCODER(AnySimpleType) \
|
|
REGISTER_SOAP_ENCODER(Array)\
|
|
REGISTER_SOAP_ENCODER(Struct)\
|
|
REGISTER_SCHEMA_ENCODER(String)\
|
|
REGISTER_SCHEMA_ENCODER(Boolean)\
|
|
REGISTER_SCHEMA_ENCODER(Double)\
|
|
REGISTER_SCHEMA_ENCODER(Float)\
|
|
REGISTER_SCHEMA_ENCODER(Long)\
|
|
REGISTER_SCHEMA_ENCODER(Int)\
|
|
REGISTER_SCHEMA_ENCODER(Short)\
|
|
REGISTER_SCHEMA_ENCODER(Byte)\
|
|
REGISTER_SCHEMA_ENCODER(UnsignedLong)\
|
|
REGISTER_SCHEMA_ENCODER(UnsignedInt)\
|
|
REGISTER_SCHEMA_ENCODER(UnsignedShort)\
|
|
REGISTER_SCHEMA_ENCODER(UnsignedByte)\
|
|
|
|
nsDefaultSOAPEncoder_1_1::nsDefaultSOAPEncoder_1_1() : nsSOAPEncoding(nsSOAPUtils::kSOAPEncURI11,
|
|
nsnull,
|
|
nsnull)
|
|
{
|
|
PRUint16 version = nsISOAPMessage::VERSION_1_1;
|
|
PRBool result;
|
|
MapSchemaURI(nsSOAPUtils::kXSURI1999,nsSOAPUtils::kXSURI,PR_TRUE,&result);
|
|
MapSchemaURI(nsSOAPUtils::kXSIURI1999,nsSOAPUtils::kXSIURI,PR_TRUE,&result);
|
|
MapSchemaURI(nsSOAPUtils::kSOAPEncURI11,nsSOAPUtils::kSOAPEncURI,PR_TRUE,&result);
|
|
REGISTER_ENCODERS
|
|
}
|
|
|
|
nsDefaultSOAPEncoder_1_2::nsDefaultSOAPEncoder_1_2() : nsSOAPEncoding(nsSOAPUtils::kSOAPEncURI,
|
|
nsnull,
|
|
nsnull)
|
|
{
|
|
PRUint16 version = nsISOAPMessage::VERSION_1_2;
|
|
PRBool result;
|
|
MapSchemaURI(nsSOAPUtils::kXSURI1999,nsSOAPUtils::kXSURI,PR_FALSE,&result);
|
|
MapSchemaURI(nsSOAPUtils::kXSIURI1999,nsSOAPUtils::kXSIURI,PR_FALSE,&result);
|
|
MapSchemaURI(nsSOAPUtils::kSOAPEncURI11,nsSOAPUtils::kSOAPEncURI,PR_FALSE,&result);
|
|
REGISTER_ENCODERS
|
|
}
|
|
|
|
// Here is the implementation of the encoders.
|
|
|
|
// Getting the immediate supertype of any type
|
|
static nsresult GetSupertype(nsISOAPEncoding * aEncoding, nsISchemaType* aType, nsISchemaType** _retval)
|
|
{
|
|
PRUint16 typevalue;
|
|
nsresult rc = aType->GetSchemaType(&typevalue);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
nsCOMPtr<nsISchemaType> base;
|
|
nsAutoString name;
|
|
switch (typevalue) {
|
|
case nsISchemaType::SCHEMA_TYPE_COMPLEX:
|
|
{
|
|
nsCOMPtr < nsISchemaComplexType > type =
|
|
do_QueryInterface(aType);
|
|
rc = type->GetBaseType(getter_AddRefs(base));
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
break;
|
|
}
|
|
case nsISchemaType::SCHEMA_TYPE_SIMPLE:
|
|
{
|
|
nsCOMPtr < nsISchemaSimpleType > type =
|
|
do_QueryInterface(aType);
|
|
PRUint16 simpletypevalue;
|
|
rc = type->GetSimpleType(&simpletypevalue);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
switch (simpletypevalue) {
|
|
// Ultimately, this is wrong because in XML types are value spaces
|
|
// We have not handled unions and lists.
|
|
// A union might be considered a supertype of anything it joins
|
|
// but it is the supertype of all types with value spaces it includes.
|
|
// SOAP is an attempt to treat XML types as though they were
|
|
// data types, which are governed by labels instead of value spaces.
|
|
// So two unrelated values may coexist, but we will disallow it
|
|
// because the caller probably wants type guarantees, not value
|
|
// guarantees.
|
|
case nsISchemaSimpleType::SIMPLE_TYPE_RESTRICTION:
|
|
{
|
|
nsCOMPtr < nsISchemaRestrictionType > simpletype =
|
|
do_QueryInterface(type);
|
|
nsCOMPtr < nsISchemaSimpleType > simplebasetype;
|
|
rc = simpletype->GetBaseType(getter_AddRefs(simplebasetype));
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
base = simplebasetype;
|
|
break;
|
|
}
|
|
case nsISchemaSimpleType::SIMPLE_TYPE_BUILTIN:
|
|
{
|
|
nsCOMPtr < nsISchemaBuiltinType > builtintype =
|
|
do_QueryInterface(type);
|
|
PRUint16 builtintypevalue;
|
|
rc = builtintype->GetBuiltinType(&builtintypevalue);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
switch(builtintypevalue) {
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_ANYTYPE: // Root of all types
|
|
*_retval = nsnull;
|
|
return NS_OK;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_STRING:
|
|
// name = kAnySimpleTypeSchemaType;
|
|
name = kAnyTypeSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_NORMALIZED_STRING:
|
|
name = kStringSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_TOKEN:
|
|
name = kNormalizedStringSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_BYTE:
|
|
name = kShortSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_UNSIGNEDBYTE:
|
|
name = kUnsignedShortSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_BASE64BINARY:
|
|
// name = kAnySimpleTypeSchemaType;
|
|
name = kAnyTypeSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_HEXBINARY:
|
|
// name = kAnySimpleTypeSchemaType;
|
|
name = kAnyTypeSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_INTEGER:
|
|
name = kDecimalSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_POSITIVEINTEGER:
|
|
name = kNonNegativeIntegerSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_NEGATIVEINTEGER:
|
|
name = kNonPositiveIntegerSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_NONNEGATIVEINTEGER:
|
|
name = kIntegerSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_NONPOSITIVEINTEGER:
|
|
name = kIntegerSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_INT:
|
|
name = kLongSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_UNSIGNEDINT:
|
|
name = kUnsignedLongSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_LONG:
|
|
name = kIntegerSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_UNSIGNEDLONG:
|
|
name = kNonNegativeIntegerSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_SHORT:
|
|
name = kIntSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_UNSIGNEDSHORT:
|
|
name = kUnsignedIntSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_DECIMAL:
|
|
// name = kAnySimpleTypeSchemaType;
|
|
name = kAnyTypeSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_FLOAT:
|
|
// name = kAnySimpleTypeSchemaType;
|
|
name = kAnyTypeSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_DOUBLE:
|
|
// name = kAnySimpleTypeSchemaType;
|
|
name = kAnyTypeSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_BOOLEAN:
|
|
// name = kAnySimpleTypeSchemaType;
|
|
name = kAnyTypeSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_TIME:
|
|
// name = kAnySimpleTypeSchemaType;
|
|
name = kAnyTypeSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_DATETIME:
|
|
// name = kAnySimpleTypeSchemaType;
|
|
name = kAnyTypeSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_DURATION:
|
|
// name = kAnySimpleTypeSchemaType;
|
|
name = kAnyTypeSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_DATE:
|
|
// name = kAnySimpleTypeSchemaType;
|
|
name = kAnyTypeSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_GMONTH:
|
|
// name = kAnySimpleTypeSchemaType;
|
|
name = kAnyTypeSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_GYEAR:
|
|
// name = kAnySimpleTypeSchemaType;
|
|
name = kAnyTypeSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_GYEARMONTH:
|
|
// name = kAnySimpleTypeSchemaType;
|
|
name = kAnyTypeSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_GDAY:
|
|
// name = kAnySimpleTypeSchemaType;
|
|
name = kAnyTypeSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_GMONTHDAY:
|
|
// name = kAnySimpleTypeSchemaType;
|
|
name = kAnyTypeSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_NAME:
|
|
// name = kAnySimpleTypeSchemaType;
|
|
name = kAnyTypeSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_QNAME:
|
|
// name = kAnySimpleTypeSchemaType;
|
|
name = kAnyTypeSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_NCNAME:
|
|
name = kNameSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_ANYURI:
|
|
// name = kAnySimpleTypeSchemaType;
|
|
name = kAnyTypeSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_LANGUAGE:
|
|
name = kTokenSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_ID:
|
|
name = kNCNameSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_IDREF:
|
|
name = kNCNameSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_IDREFS:
|
|
name = kNormalizedStringSchemaType; // Really a list...
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_ENTITY:
|
|
name = kNCNameSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_ENTITIES:
|
|
name = kNormalizedStringSchemaType; // Really a list...
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_NOTATION:
|
|
// name = kAnySimpleTypeSchemaType;
|
|
name = kAnyTypeSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_NMTOKEN:
|
|
name = kTokenSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_NMTOKENS:
|
|
name = kNormalizedStringSchemaType; // Really a list...
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
if (!base) {
|
|
if (name.IsEmpty()) {
|
|
switch (typevalue) {
|
|
case nsISchemaType::SCHEMA_TYPE_COMPLEX:
|
|
name = kAnyTypeSchemaType;
|
|
break;
|
|
default:
|
|
// name = kAnySimpleTypeSchemaType;
|
|
name = kAnyTypeSchemaType;
|
|
}
|
|
}
|
|
nsCOMPtr<nsISchemaCollection> collection;
|
|
rc = aEncoding->GetSchemaCollection(getter_AddRefs(collection));
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
rc = collection->GetType(name,
|
|
nsSOAPUtils::kXSURI,
|
|
getter_AddRefs(base));
|
|
// if (NS_FAILED(rc)) return rc;
|
|
}
|
|
*_retval = base;
|
|
NS_IF_ADDREF(*_retval);
|
|
return NS_OK;
|
|
}
|
|
|
|
static nsresult
|
|
EncodeSimpleValue(nsISOAPEncoding * aEncoding,
|
|
const nsAString & aValue,
|
|
const nsAString & aNamespaceURI,
|
|
const nsAString & aName,
|
|
nsISchemaType * aSchemaType,
|
|
nsIDOMElement * aDestination, nsIDOMElement ** _retval)
|
|
{
|
|
nsresult rc;
|
|
PRBool needType = PR_FALSE;
|
|
nsAutoString typeName;
|
|
nsAutoString typeNS;
|
|
if (aSchemaType) {
|
|
rc = aSchemaType->GetName(typeName);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
rc = aSchemaType->GetTargetNamespace(typeNS);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
needType = !(typeName.Equals(kAnyTypeSchemaType) && typeNS.Equals(nsSOAPUtils::kXSURI));
|
|
}
|
|
nsAutoString name; // First choose the appropriate name and namespace for the element.
|
|
nsAutoString ns;
|
|
if (aName.IsEmpty()) { // We automatically choose appropriate element names where none exist.
|
|
ns = nsSOAPUtils::kSOAPEncURI;
|
|
nsAutoString currentURI = ns;
|
|
nsCOMPtr<nsISchemaType>currentType = aSchemaType;
|
|
while (currentType
|
|
&& !(typeNS.Equals(nsSOAPUtils::kXSURI)
|
|
|| typeNS.Equals(nsSOAPUtils::kSOAPEncURI))) {
|
|
nsCOMPtr<nsISchemaType> supertype;
|
|
rc = GetSupertype(aEncoding, currentType, getter_AddRefs(supertype));
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
if (!currentType) {
|
|
currentURI = nsSOAPUtils::kXSURI;
|
|
break;
|
|
}
|
|
currentType = supertype;
|
|
rc = currentType->GetTargetNamespace(typeNS);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
}
|
|
if (currentType) {
|
|
rc = aSchemaType->GetName(name);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
needType = needType && (currentType != aSchemaType); // We may not need type
|
|
}
|
|
else {
|
|
name = kAnyTypeSchemaType;
|
|
needType = PR_FALSE;
|
|
}
|
|
rc = aEncoding->GetExternalSchemaURI(nsSOAPUtils::kSOAPEncURI, ns);
|
|
}
|
|
else {
|
|
name = aName;
|
|
rc = aEncoding->GetExternalSchemaURI(aNamespaceURI, ns);
|
|
}
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
nsCOMPtr < nsIDOMDocument > document;
|
|
rc = aDestination->GetOwnerDocument(getter_AddRefs(document));
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
nsCOMPtr < nsIDOMElement > element;
|
|
rc = document->CreateElementNS(ns, name, getter_AddRefs(element));
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
nsCOMPtr < nsIDOMNode > ignore;
|
|
rc = aDestination->AppendChild(element, getter_AddRefs(ignore));
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
if (needType) {
|
|
nsAutoString type;
|
|
rc = nsSOAPUtils::MakeNamespacePrefix(aEncoding, element,
|
|
typeNS, type);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
type.Append(nsSOAPUtils::kQualifiedSeparator);
|
|
type.Append(typeName);
|
|
rc = aEncoding->GetExternalSchemaURI(nsSOAPUtils::kXSIURI, ns);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
rc = (element)->
|
|
SetAttributeNS(ns, nsSOAPUtils::kXSITypeAttribute, type);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
}
|
|
if (!aValue.IsEmpty()) {
|
|
nsCOMPtr < nsIDOMText > text;
|
|
rc = document->CreateTextNode(aValue, getter_AddRefs(text));
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
rc = (element)->AppendChild(text, getter_AddRefs(ignore));
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
}
|
|
*_retval = element;
|
|
NS_IF_ADDREF(*_retval);
|
|
return rc;
|
|
}
|
|
|
|
// Testing for a simple value
|
|
static nsresult HasSimpleValue(nsISchemaType * aSchemaType, PRBool * aResult) {
|
|
PRUint16 typevalue;
|
|
nsresult rc = aSchemaType->GetSchemaType(&typevalue);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
if (typevalue == nsISchemaComplexType::SCHEMA_TYPE_COMPLEX) {
|
|
nsCOMPtr<nsISchemaComplexType> ct = do_QueryInterface(aSchemaType);
|
|
rc = ct->GetContentModel(&typevalue);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
*aResult = typevalue == nsISchemaComplexType::CONTENT_MODEL_SIMPLE;
|
|
} else {
|
|
*aResult = PR_TRUE;
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
// Default
|
|
|
|
NS_IMETHODIMP
|
|
nsDefaultEncoder::Encode(nsISOAPEncoding * aEncoding,
|
|
nsIVariant * aSource,
|
|
const nsAString & aNamespaceURI,
|
|
const nsAString & aName,
|
|
nsISchemaType * aSchemaType,
|
|
nsISOAPAttachments * aAttachments,
|
|
nsIDOMElement * aDestination,
|
|
nsIDOMElement * *aReturnValue)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aEncoding);
|
|
NS_ENSURE_ARG_POINTER(&aNamespaceURI);
|
|
NS_ENSURE_ARG_POINTER(&aName);
|
|
NS_ENSURE_ARG_POINTER(aDestination);
|
|
NS_ENSURE_ARG_POINTER(aReturnValue);
|
|
*aReturnValue = nsnull;
|
|
if (aSource == nsnull) {
|
|
nsAutoString ns;
|
|
nsCOMPtr<nsIDOMElement> cloneable;
|
|
nsresult rc = aEncoding->GetExternalSchemaURI(nsSOAPUtils::kXSIURI, ns);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
nsAutoString name;
|
|
if (!aName.IsEmpty())
|
|
name.Assign(kNull);
|
|
rc = EncodeSimpleValue(aEncoding, kEmpty, kEmpty,
|
|
name, nsnull, aDestination, aReturnValue);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
rc = (*aReturnValue)->SetAttributeNS(ns, kNull, nsSOAPUtils::kTrueA);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
}
|
|
nsCOMPtr < nsISOAPEncoder > encoder;
|
|
if (aSchemaType) {
|
|
nsCOMPtr < nsISchemaType > lookupType = aSchemaType;
|
|
do {
|
|
nsAutoString schemaType;
|
|
nsAutoString schemaURI;
|
|
nsAutoString encodingKey;
|
|
nsresult rc = lookupType->GetName(schemaType);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
rc = lookupType->GetTargetNamespace(schemaURI);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
SOAPEncodingKey(schemaURI, schemaType, encodingKey);
|
|
rc = aEncoding->GetEncoder(encodingKey, getter_AddRefs(encoder));
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
if (encoder)
|
|
break;
|
|
nsCOMPtr<nsISchemaType> supertype;
|
|
rc = GetSupertype(aEncoding, lookupType, getter_AddRefs(supertype));
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
lookupType = supertype;
|
|
}
|
|
while (lookupType);
|
|
}
|
|
if (!encoder) {
|
|
nsAutoString encodingKey;
|
|
SOAPEncodingKey(nsSOAPUtils::kXSURI,
|
|
kAnyTypeSchemaType, encodingKey);
|
|
nsresult rc =
|
|
aEncoding->GetEncoder(encodingKey, getter_AddRefs(encoder));
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
}
|
|
if (encoder) {
|
|
return encoder->Encode(aEncoding, aSource, aNamespaceURI, aName,
|
|
aSchemaType, aAttachments, aDestination,
|
|
aReturnValue);
|
|
}
|
|
return SOAP_EXCEPTION(NS_ERROR_NOT_IMPLEMENTED,"SOAP_NO_ENCODER_FOR_TYPE","The default encoder finds no encoder for specific type");
|
|
}
|
|
|
|
static nsresult GetNativeType(PRUint16 aType, nsAString & aSchemaNamespaceURI, nsAString & aSchemaType)
|
|
{
|
|
aSchemaNamespaceURI.Assign(nsSOAPUtils::kXSURI);
|
|
switch (aType) {
|
|
case nsIDataType::VTYPE_CHAR_STR:
|
|
case nsIDataType::VTYPE_WCHAR_STR:
|
|
case nsIDataType::VTYPE_CHAR:
|
|
case nsIDataType::VTYPE_WCHAR:
|
|
case nsIDataType::VTYPE_STRING_SIZE_IS:
|
|
case nsIDataType::VTYPE_WSTRING_SIZE_IS:
|
|
case nsIDataType::VTYPE_ASTRING:
|
|
aSchemaType.Assign(kStringSchemaType);
|
|
break;
|
|
case nsIDataType::VTYPE_INT8:
|
|
aSchemaType.Assign(kByteSchemaType);
|
|
break;
|
|
case nsIDataType::VTYPE_INT16:
|
|
aSchemaType.Assign(kShortSchemaType);
|
|
break;
|
|
case nsIDataType::VTYPE_INT32:
|
|
aSchemaType.Assign(kIntSchemaType);
|
|
break;
|
|
case nsIDataType::VTYPE_INT64:
|
|
aSchemaType.Assign(kLongSchemaType);
|
|
break;
|
|
case nsIDataType::VTYPE_UINT8:
|
|
aSchemaType.Assign(kUnsignedByteSchemaType);
|
|
break;
|
|
case nsIDataType::VTYPE_UINT16:
|
|
aSchemaType.Assign(kUnsignedShortSchemaType);
|
|
break;
|
|
case nsIDataType::VTYPE_UINT32:
|
|
aSchemaType.Assign(kUnsignedIntSchemaType);
|
|
break;
|
|
case nsIDataType::VTYPE_UINT64:
|
|
aSchemaType.Assign(kUnsignedLongSchemaType);
|
|
break;
|
|
case nsIDataType::VTYPE_FLOAT:
|
|
aSchemaType.Assign(kFloatSchemaType);
|
|
break;
|
|
case nsIDataType::VTYPE_DOUBLE:
|
|
aSchemaType.Assign(kDoubleSchemaType);
|
|
break;
|
|
case nsIDataType::VTYPE_BOOL:
|
|
aSchemaType.Assign(kBooleanSchemaType);
|
|
break;
|
|
case nsIDataType::VTYPE_ARRAY:
|
|
aSchemaType.Assign(kArraySOAPType);
|
|
aSchemaNamespaceURI.Assign(nsSOAPUtils::kSOAPEncURI);
|
|
break;
|
|
case nsIDataType::VTYPE_VOID:
|
|
case nsIDataType::VTYPE_EMPTY:
|
|
// Empty may be either simple or complex.
|
|
break;
|
|
case nsIDataType::VTYPE_INTERFACE_IS:
|
|
case nsIDataType::VTYPE_INTERFACE:
|
|
aSchemaType.Assign(kStructSOAPType);
|
|
aSchemaNamespaceURI.Assign(nsSOAPUtils::kSOAPEncURI);
|
|
break;
|
|
default:
|
|
aSchemaType.Assign(kAnySimpleTypeSchemaType);
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsAnyTypeEncoder::Encode(nsISOAPEncoding * aEncoding,
|
|
nsIVariant * aSource,
|
|
const nsAString & aNamespaceURI,
|
|
const nsAString & aName,
|
|
nsISchemaType * aSchemaType,
|
|
nsISOAPAttachments * aAttachments,
|
|
nsIDOMElement * aDestination,
|
|
nsIDOMElement * *aReturnValue)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aEncoding);
|
|
NS_ENSURE_ARG_POINTER(&aNamespaceURI);
|
|
NS_ENSURE_ARG_POINTER(&aName);
|
|
NS_ENSURE_ARG_POINTER(aDestination);
|
|
NS_ENSURE_ARG_POINTER(aReturnValue);
|
|
*aReturnValue = nsnull;
|
|
nsAutoString nativeSchemaType;
|
|
nsAutoString nativeSchemaURI;
|
|
PRUint16 typevalue;
|
|
nsresult rc = aSource->GetDataType(&typevalue);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
// If there is a schema type then regular native types will not avail us anything.
|
|
if (aSchemaType) {
|
|
PRBool simple = PR_FALSE;
|
|
rc = HasSimpleValue(aSchemaType, &simple);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
if (simple) {
|
|
switch (typevalue) {
|
|
case nsIDataType::VTYPE_ARRAY:
|
|
case nsIDataType::VTYPE_INTERFACE_IS:
|
|
case nsIDataType::VTYPE_INTERFACE:
|
|
simple = PR_FALSE;
|
|
break;
|
|
}
|
|
}
|
|
if (simple) {
|
|
nativeSchemaType.Assign(kAnySimpleTypeSchemaType);
|
|
nativeSchemaURI.Assign(nsSOAPUtils::kXSURI);
|
|
}
|
|
else {
|
|
nativeSchemaType.Assign(kStructSOAPType);
|
|
nativeSchemaURI.Assign(nsSOAPUtils::kSOAPEncURI);
|
|
}
|
|
}
|
|
else {
|
|
rc = GetNativeType(typevalue, nativeSchemaURI, nativeSchemaType);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
}
|
|
|
|
nsCOMPtr < nsISOAPEncoder > encoder;
|
|
nsAutoString encodingKey;
|
|
SOAPEncodingKey(nativeSchemaURI, nativeSchemaType, encodingKey);
|
|
rc = aEncoding->GetEncoder(encodingKey, getter_AddRefs(encoder));
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
if (encoder) {
|
|
nsCOMPtr<nsISchemaType> type;
|
|
if (aSchemaType) {
|
|
type = aSchemaType;
|
|
}
|
|
else {
|
|
nsCOMPtr < nsISchemaCollection > collection;
|
|
nsresult rc =
|
|
aEncoding->GetSchemaCollection(getter_AddRefs(collection));
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
rc = collection->GetType(nativeSchemaType,
|
|
nativeSchemaURI,
|
|
getter_AddRefs(type));
|
|
// if (NS_FAILED(rc)) return rc;
|
|
}
|
|
|
|
return encoder->Encode(aEncoding, aSource, aNamespaceURI, aName,
|
|
type, aAttachments, aDestination,
|
|
aReturnValue);
|
|
}
|
|
return SOAP_EXCEPTION(NS_ERROR_NOT_IMPLEMENTED,"SOAP_NO_ENCODER_FOR_TYPE","The any type encoder finds no encoder for specific data");
|
|
}
|
|
|
|
static nsresult EncodeStructParticle(nsISOAPEncoding* aEncoding, nsIPropertyBag* aPropertyBag,
|
|
nsISchemaParticle* aParticle,
|
|
nsISOAPAttachments * aAttachments, nsIDOMElement* aDestination)
|
|
{
|
|
nsresult rc;
|
|
if (aParticle) {
|
|
PRUint32 minOccurs;
|
|
rc = aParticle->GetMinOccurs(&minOccurs);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
PRUint32 maxOccurs;
|
|
rc = aParticle->GetMaxOccurs(&maxOccurs);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
PRUint16 particleType;
|
|
rc = aParticle->GetParticleType(&particleType);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
switch(particleType) {
|
|
case nsISchemaParticle::PARTICLE_TYPE_ELEMENT: {
|
|
if (maxOccurs > 1) { // Todo: Try to make this thing work as an array?
|
|
return NS_ERROR_NOT_AVAILABLE; // For now, we just try something else if we can (recoverable)
|
|
}
|
|
nsCOMPtr<nsISchemaElement> element = do_QueryInterface(aParticle);
|
|
nsAutoString name;
|
|
rc = element->GetTargetNamespace(name);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
if (!name.IsEmpty()) {
|
|
rc = NS_ERROR_NOT_AVAILABLE; // No known way to use namespace qualification in struct
|
|
}
|
|
else {
|
|
rc = element->GetName(name);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
rc = element->GetName(name);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
nsCOMPtr<nsISchemaType> type;
|
|
rc = element->GetType(getter_AddRefs(type));
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
nsCOMPtr<nsIVariant> value;
|
|
rc = aPropertyBag->GetProperty(name, getter_AddRefs(value));
|
|
if (!NS_FAILED(rc)) {
|
|
nsCOMPtr<nsIDOMElement> dummy;
|
|
rc = aEncoding->Encode(value, kEmpty, name, type, aAttachments, aDestination, getter_AddRefs(dummy));
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
}
|
|
}
|
|
if (minOccurs == 0 && rc == NS_ERROR_NOT_AVAILABLE) // If we succeeded or failed recoverably, but we were permitted to, then return success
|
|
rc = NS_OK;
|
|
return rc;
|
|
}
|
|
case nsISchemaParticle::PARTICLE_TYPE_MODEL_GROUP:
|
|
{
|
|
if (maxOccurs > 1) { // Todo: Try to make this thing work as an array?
|
|
return NS_ERROR_NOT_AVAILABLE; // For now, we just try something else if we can (recoverable)
|
|
}
|
|
nsCOMPtr<nsISchemaModelGroup> modelGroup = do_QueryInterface(aParticle);
|
|
PRUint16 compositor;
|
|
rc = modelGroup->GetCompositor(&compositor);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
PRUint32 particleCount;
|
|
rc = modelGroup->GetParticleCount(&particleCount);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
PRUint32 i;
|
|
for (i = 0; i < particleCount; i++) {
|
|
nsCOMPtr<nsISchemaParticle> child;
|
|
rc = modelGroup->GetParticle(i, getter_AddRefs(child));
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
rc = EncodeStructParticle(aEncoding, aPropertyBag, child, aAttachments, aDestination);
|
|
if (compositor == nsISchemaModelGroup::COMPOSITOR_CHOICE) {
|
|
if (!NS_FAILED(rc)) {
|
|
return NS_OK;
|
|
}
|
|
if (rc == NS_ERROR_NOT_AVAILABLE) { // In a choice, recoverable model failures are OK.
|
|
rc = NS_OK;
|
|
}
|
|
}
|
|
else if (i > 0 && rc == NS_ERROR_NOT_AVAILABLE) { // This detects ambiguous model (non-deterministic choice which fails after succeeding on first)
|
|
return SOAP_EXCEPTION(NS_ERROR_ILLEGAL_VALUE,"SOAP_AMBIGUOUS_ENCODING","Cannot proceed due to ambiguity or error in content model");
|
|
}
|
|
if (NS_FAILED(rc))
|
|
break;
|
|
}
|
|
if (compositor == nsISchemaModelGroup::COMPOSITOR_CHOICE) // If choice selected nothing, this is recoverable failure
|
|
rc = NS_ERROR_NOT_AVAILABLE;
|
|
if (minOccurs == 0 && rc == NS_ERROR_NOT_AVAILABLE) // If we succeeded or failed recoverably, but we were permitted to, then return success
|
|
rc = NS_OK;
|
|
return rc; // Return status
|
|
}
|
|
case nsISchemaParticle::PARTICLE_TYPE_ANY:
|
|
// No model available here (we may wish to handle strict versus lazy, but what does that mean with only local accessor names)
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
nsCOMPtr<nsISimpleEnumerator> e;
|
|
aPropertyBag->GetEnumerator(getter_AddRefs(e));
|
|
PRBool more;
|
|
rc = e->HasMoreElements(&more);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
while (more) {
|
|
nsCOMPtr<nsIProperty> p;
|
|
rc = e->GetNext(getter_AddRefs(p));
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
nsAutoString name;
|
|
rc = p->GetName(name);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
nsCOMPtr<nsIVariant>value;
|
|
rc = p->GetValue(getter_AddRefs(value));
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
nsCOMPtr<nsIDOMElement>result;
|
|
rc = aEncoding->Encode(value,kEmpty,name,nsnull,aAttachments,aDestination,getter_AddRefs(result));
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
rc = e->HasMoreElements(&more);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsStructEncoder::Encode(nsISOAPEncoding * aEncoding,
|
|
nsIVariant * aSource,
|
|
const nsAString & aNamespaceURI,
|
|
const nsAString & aName,
|
|
nsISchemaType * aSchemaType,
|
|
nsISOAPAttachments * aAttachments,
|
|
nsIDOMElement * aDestination,
|
|
nsIDOMElement * *aReturnValue)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aEncoding);
|
|
NS_ENSURE_ARG_POINTER(&aNamespaceURI);
|
|
NS_ENSURE_ARG_POINTER(&aName);
|
|
NS_ENSURE_ARG_POINTER(aDestination);
|
|
NS_ENSURE_ARG_POINTER(aReturnValue);
|
|
*aReturnValue = nsnull;
|
|
nsIID* iid;
|
|
nsCOMPtr<nsISupports> ptr;
|
|
nsresult rc = aSource->GetAsInterface(&iid, getter_AddRefs(ptr));
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
nsCOMPtr<nsIPropertyBag>pbptr = do_QueryInterface(ptr);
|
|
if (pbptr) { // Do any object that can QI to a property bag.
|
|
nsCOMPtr<nsISchemaModelGroup>modelGroup;
|
|
if (aSchemaType) {
|
|
nsCOMPtr<nsISchemaComplexType>ctype = do_QueryInterface(aSchemaType);
|
|
if (ctype) {
|
|
rc = ctype->GetModelGroup(getter_AddRefs(modelGroup));
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
}
|
|
}
|
|
// We still have to fake this one, because there is no struct type in schema.
|
|
if (aName.IsEmpty() && !aSchemaType) {
|
|
rc = EncodeSimpleValue(aEncoding, kEmpty,
|
|
nsSOAPUtils::kSOAPEncURI, kStructSOAPType,
|
|
aSchemaType, aDestination,
|
|
aReturnValue);
|
|
}
|
|
else {
|
|
rc = EncodeSimpleValue(aEncoding, kEmpty,
|
|
aNamespaceURI, aName, aSchemaType, aDestination,
|
|
aReturnValue);
|
|
}
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
return EncodeStructParticle(aEncoding, pbptr, modelGroup, aAttachments, *aReturnValue);
|
|
}
|
|
return SOAP_EXCEPTION(NS_ERROR_ILLEGAL_VALUE,"SOAP_PROPERTYBAG_REQUIRED","When encoding as a struct, an object with properties is required");
|
|
}
|
|
|
|
// AnySimpleType
|
|
|
|
NS_IMETHODIMP
|
|
nsAnySimpleTypeEncoder::Encode(nsISOAPEncoding * aEncoding,
|
|
nsIVariant * aSource,
|
|
const nsAString & aNamespaceURI,
|
|
const nsAString & aName,
|
|
nsISchemaType * aSchemaType,
|
|
nsISOAPAttachments * aAttachments,
|
|
nsIDOMElement * aDestination,
|
|
nsIDOMElement * *aReturnValue)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aEncoding);
|
|
NS_ENSURE_ARG_POINTER(&aNamespaceURI);
|
|
NS_ENSURE_ARG_POINTER(&aName);
|
|
NS_ENSURE_ARG_POINTER(aDestination);
|
|
NS_ENSURE_ARG_POINTER(aReturnValue);
|
|
*aReturnValue = nsnull;
|
|
nsresult rc;
|
|
nsAutoString value;
|
|
rc = aSource->GetAsAString(value);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
// We still have to fake this one, because there is no any simple type in schema.
|
|
if (aName.IsEmpty() && !aSchemaType) {
|
|
return EncodeSimpleValue(aEncoding, value,
|
|
nsSOAPUtils::kSOAPEncURI, kAnySimpleTypeSchemaType, aSchemaType, aDestination,
|
|
aReturnValue);
|
|
}
|
|
return EncodeSimpleValue(aEncoding, value,
|
|
aNamespaceURI, aName, aSchemaType, aDestination,
|
|
aReturnValue);
|
|
}
|
|
|
|
#define MAX_ARRAY_DIMENSIONS 100
|
|
|
|
/**
|
|
* Recursive method used by array encoding which counts the sizes of the specified dimensions
|
|
* and does a very primitive determination whether all the members of the array are of a single
|
|
* homogenious type. This intelligently skips nulls wherever they occur.
|
|
*/
|
|
static nsresult GetArrayType(nsIVariant* aSource, PRUint32 aDimensionCount, PRUint32 * aDimensionSizes, PRUint16 * aType)
|
|
{
|
|
if (!aSource) {
|
|
*aType = nsIDataType::VTYPE_EMPTY;
|
|
return NS_OK;
|
|
}
|
|
PRUint16 type;
|
|
nsIID iid;
|
|
PRUint32 count;
|
|
void* array;
|
|
PRUint32 i;
|
|
nsresult rc = aSource->GetAsArray(&type, &iid, &count, &array); // First, get the array, if any.
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
if (count > aDimensionSizes[0]) {
|
|
aDimensionSizes[0] = count;
|
|
}
|
|
if (aDimensionCount > 1) {
|
|
if (type != nsIDataType::VTYPE_INTERFACE_IS
|
|
|| !iid.Equals(NS_GET_IID(nsIVariant))) {
|
|
rc = SOAP_EXCEPTION(NS_ERROR_ILLEGAL_VALUE,"SOAP_ARRAY_OBJECTS","When encoding as an array, an array of array objects is required");
|
|
// All nested arrays (which is what multi-dimensional arrays are) are variants.
|
|
}
|
|
else {
|
|
nsIVariant** a = NS_STATIC_CAST(nsIVariant**,array);
|
|
PRUint16 rtype = nsIDataType::VTYPE_EMPTY;
|
|
for (i = 0; i < count; i++) {
|
|
PRUint16 nexttype;
|
|
rc = GetArrayType(a[i], aDimensionCount - 1, aDimensionSizes + 1, &nexttype);
|
|
if (NS_FAILED(rc))
|
|
break;
|
|
if (rtype == nsIDataType::VTYPE_EMPTY)
|
|
rtype = nexttype;
|
|
else if (nexttype != nsIDataType::VTYPE_EMPTY
|
|
&& nexttype != rtype)
|
|
rtype = nsIDataType::VTYPE_INTERFACE_IS;
|
|
}
|
|
*aType = rtype;
|
|
}
|
|
}
|
|
else {
|
|
*aType = type;
|
|
}
|
|
// The memory model for variant arrays' GetAsArray is difficult to manage
|
|
switch (type) {
|
|
case nsIDataType::VTYPE_INTERFACE_IS:
|
|
{
|
|
nsISupports** values = NS_STATIC_CAST(nsISupports**,array);
|
|
for (i = 0; i < count; i++)
|
|
NS_RELEASE(values[i]);
|
|
}
|
|
break;
|
|
case nsIDataType::VTYPE_WCHAR_STR:
|
|
case nsIDataType::VTYPE_CHAR_STR:
|
|
{
|
|
void** ptrs = NS_STATIC_CAST(void**,array);
|
|
for (i = 0; i < count; i++) {
|
|
nsMemory::Free(ptrs[i]);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
nsMemory::Free(array);
|
|
{ // Individual lengths guaranteed to fit because variant array length is 32-bit.
|
|
PRUint64 tot = 1; // Collect in 64 bits, just to make sure combo fits
|
|
for (i = 0; i < aDimensionCount; i++) {
|
|
tot = tot * aDimensionSizes[i];
|
|
if (tot > 0xffffffffU) {
|
|
return SOAP_EXCEPTION(NS_ERROR_ILLEGAL_VALUE,"SOAP_ARRAY_TOO_BIG","When encoding an object as an array, the total count of items exceeded maximum.");
|
|
}
|
|
}
|
|
}
|
|
return rc;
|
|
}
|
|
/**
|
|
* Recursive method used by array encoding to encode the next level of the array into the
|
|
* established array element. If dimension count is > 1, then it recursively doles out
|
|
* the work. This intelligently skips nulls wherever they occur.
|
|
*/
|
|
static nsresult EncodeArray(nsISOAPEncoding* aEncoding, nsIVariant* aSource, nsISchemaType* aSchemaType,
|
|
nsISOAPAttachments* aAttachments, nsIDOMElement* aArray, PRUint32 aDimensionCount, PRUint32* aDimensionSizes)
|
|
{
|
|
nsresult rc;
|
|
PRUint16 type;
|
|
nsIID iid;
|
|
PRUint32 count;
|
|
void *array;
|
|
if (aSource != nsnull) {
|
|
rc = aSource->GetAsArray(&type, &iid, &count, &array); // First, get the array, if any.
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
}
|
|
else { // If the source is null, then just add a bunch of nulls to the array.
|
|
count = (PRUint32)aDimensionSizes[--aDimensionCount];
|
|
while (aDimensionCount)
|
|
count *= (PRUint32)aDimensionSizes[--aDimensionCount];
|
|
if (count) {
|
|
nsAutoString ns;
|
|
nsCOMPtr<nsIDOMElement> cloneable;
|
|
rc = aEncoding->GetExternalSchemaURI(nsSOAPUtils::kXSIURI, ns);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
rc = EncodeSimpleValue(aEncoding, kEmpty, kEmpty,
|
|
kNull, nsnull, aArray, getter_AddRefs(cloneable));
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
rc = cloneable->SetAttributeNS(ns, kNull, nsSOAPUtils::kTrueA);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
nsCOMPtr<nsIDOMNode> clone;
|
|
nsCOMPtr<nsIDOMNode> dummy;
|
|
for (;--count;) {
|
|
rc = cloneable->CloneNode(PR_TRUE, getter_AddRefs(clone));// No children so deep == shallow
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
rc = aArray->AppendChild(clone, getter_AddRefs(dummy));
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
}
|
|
}
|
|
}
|
|
nsCOMPtr<nsIDOMElement> dummy;
|
|
PRBool freeptrs = PR_FALSE;
|
|
PRUint32 i;
|
|
|
|
// The more-robust way of encoding is to construct variants and call the encoder directly,
|
|
// but for now, we short-circuit it for simple types.
|
|
|
|
#define ENCODE_SIMPLE_ARRAY(XPType, VType, Source) \
|
|
{\
|
|
XPType* values = NS_STATIC_CAST(XPType*, array);\
|
|
nsCOMPtr < nsIWritableVariant > p =\
|
|
do_CreateInstance(NS_VARIANT_CONTRACTID, &rc);\
|
|
if (NS_FAILED(rc)) break;\
|
|
for (i = 0; i < count; i++) {\
|
|
if (NS_FAILED(rc))\
|
|
break;\
|
|
rc = p->SetAs##VType(Source);\
|
|
if (NS_FAILED(rc))\
|
|
break;\
|
|
rc = aEncoding->Encode(p,\
|
|
kEmpty,\
|
|
kEmpty,\
|
|
aSchemaType,\
|
|
aAttachments,\
|
|
aArray,\
|
|
getter_AddRefs(dummy));\
|
|
if (NS_FAILED(rc)) break;\
|
|
}\
|
|
break;\
|
|
}
|
|
|
|
if (aDimensionCount > 1) {
|
|
switch (type) {
|
|
case nsIDataType::VTYPE_INTERFACE_IS:
|
|
{
|
|
nsIVariant** values = NS_STATIC_CAST(nsIVariant**, array);// If not truly a variant, we only release.
|
|
if (iid.Equals(NS_GET_IID(nsIVariant))) { // Only do variants for now.
|
|
for (i = 0; i < count; i++) {
|
|
rc = EncodeArray(aEncoding, values[i],
|
|
aSchemaType,
|
|
aAttachments,
|
|
aArray,
|
|
aDimensionCount - 1,
|
|
aDimensionSizes + 1);
|
|
if (NS_FAILED(rc)) break;
|
|
}
|
|
}
|
|
for (i = 0; i < count; i++)
|
|
NS_RELEASE(values[i]);
|
|
break;
|
|
}
|
|
case nsIDataType::VTYPE_WCHAR_STR:
|
|
case nsIDataType::VTYPE_CHAR_STR:
|
|
freeptrs = PR_TRUE;
|
|
default:
|
|
rc = SOAP_EXCEPTION(NS_ERROR_ILLEGAL_VALUE,"SOAP_ARRAY_OBJECTS","When encoding as an array, an array of array objects is required");
|
|
}
|
|
} else switch (type) {
|
|
case nsIDataType::VTYPE_INT8:
|
|
ENCODE_SIMPLE_ARRAY(PRUint8, Int8,
|
|
(signed char) values[i]);
|
|
case nsIDataType::VTYPE_INT16:
|
|
ENCODE_SIMPLE_ARRAY(PRInt16, Int16, values[i]);
|
|
case nsIDataType::VTYPE_INT32:
|
|
ENCODE_SIMPLE_ARRAY(PRInt32, Int32, values[i]);
|
|
case nsIDataType::VTYPE_INT64:
|
|
ENCODE_SIMPLE_ARRAY(PRInt64, Int64, values[i]);
|
|
case nsIDataType::VTYPE_UINT8:
|
|
ENCODE_SIMPLE_ARRAY(PRUint8, Uint8, values[i]);
|
|
case nsIDataType::VTYPE_UINT16:
|
|
ENCODE_SIMPLE_ARRAY(PRUint16, Uint16, values[i]);
|
|
case nsIDataType::VTYPE_UINT32:
|
|
ENCODE_SIMPLE_ARRAY(PRUint32, Uint32, values[i]);
|
|
case nsIDataType::VTYPE_UINT64:
|
|
ENCODE_SIMPLE_ARRAY(PRUint64, Uint64, values[i]);
|
|
case nsIDataType::VTYPE_FLOAT:
|
|
ENCODE_SIMPLE_ARRAY(float, Float, values[i]);
|
|
case nsIDataType::VTYPE_DOUBLE:
|
|
ENCODE_SIMPLE_ARRAY(double, Double, values[i]);
|
|
case nsIDataType::VTYPE_BOOL:
|
|
ENCODE_SIMPLE_ARRAY(PRBool, Bool, (PRUint16) values[i]);
|
|
case nsIDataType::VTYPE_ID:
|
|
case nsIDataType::VTYPE_CHAR_STR:
|
|
freeptrs = PR_TRUE;
|
|
ENCODE_SIMPLE_ARRAY(char *, String, values[i]);
|
|
case nsIDataType::VTYPE_WCHAR_STR:
|
|
freeptrs = PR_TRUE;
|
|
ENCODE_SIMPLE_ARRAY(PRUnichar *, WString, values[i]);
|
|
case nsIDataType::VTYPE_CHAR:
|
|
ENCODE_SIMPLE_ARRAY(char, Char, values[i]);
|
|
case nsIDataType::VTYPE_WCHAR:
|
|
ENCODE_SIMPLE_ARRAY(PRUnichar, WChar, values[i]);
|
|
case nsIDataType::VTYPE_INTERFACE_IS:
|
|
{
|
|
nsIVariant** values = NS_STATIC_CAST(nsIVariant**, array);// If not truly a variant, we only use as nsISupports
|
|
if (iid.Equals(NS_GET_IID(nsIVariant))) { // Only do variants for now.
|
|
for (i = 0; i < count; i++) {
|
|
rc = aEncoding->Encode(values[i],
|
|
kEmpty,
|
|
kEmpty,
|
|
aSchemaType,
|
|
aAttachments,
|
|
aArray,
|
|
getter_AddRefs(dummy));
|
|
if (NS_FAILED(rc)) break;
|
|
}
|
|
}
|
|
else {
|
|
nsCOMPtr < nsIWritableVariant > p =
|
|
do_CreateInstance(NS_VARIANT_CONTRACTID, &rc);
|
|
if (NS_FAILED(rc)) break;
|
|
for (i = 0; i < count; i++) {
|
|
if (NS_FAILED(rc))
|
|
break;
|
|
rc = p->SetAsInterface(iid, values[i]);
|
|
if (NS_FAILED(rc))
|
|
break;
|
|
rc = aEncoding->Encode(p,
|
|
kEmpty,
|
|
kEmpty,
|
|
aSchemaType,
|
|
aAttachments,
|
|
aArray,
|
|
getter_AddRefs(dummy));
|
|
if (NS_FAILED(rc)) break;
|
|
}
|
|
}
|
|
for (i = 0; i < count; i++)
|
|
NS_RELEASE(values[i]);
|
|
break;
|
|
}
|
|
|
|
case nsIDataType::VTYPE_EMPTY:
|
|
break; // I think an empty array needs no elements?
|
|
// Don't support these array types, as they seem meaningless.
|
|
case nsIDataType::VTYPE_ASTRING:
|
|
case nsIDataType::VTYPE_VOID:
|
|
case nsIDataType::VTYPE_INTERFACE:
|
|
case nsIDataType::VTYPE_ARRAY:
|
|
rc = SOAP_EXCEPTION(NS_ERROR_ILLEGAL_VALUE,"SOAP_ARRAY_TYPES","When encoding an array, unable to handle array elements");
|
|
}
|
|
if (freeptrs) {
|
|
void** ptrs = NS_STATIC_CAST(void**,array);
|
|
for (i = 0; i < count; i++) {
|
|
nsMemory::Free(ptrs[i]);
|
|
}
|
|
nsMemory::Free(array);
|
|
}
|
|
// We know that count does not exceed size of dimension, but it may be less
|
|
return rc;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsArrayEncoder::Encode(nsISOAPEncoding * aEncoding,
|
|
nsIVariant * aSource,
|
|
const nsAString & aNamespaceURI,
|
|
const nsAString & aName,
|
|
nsISchemaType * aSchemaType,
|
|
nsISOAPAttachments * aAttachments,
|
|
nsIDOMElement * aDestination,
|
|
nsIDOMElement * *aReturnValue)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aEncoding);
|
|
NS_ENSURE_ARG_POINTER(&aNamespaceURI);
|
|
NS_ENSURE_ARG_POINTER(&aName);
|
|
NS_ENSURE_ARG_POINTER(aDestination);
|
|
NS_ENSURE_ARG_POINTER(aReturnValue);
|
|
*aReturnValue = nsnull;
|
|
PRUint16 arrayNativeType;
|
|
PRUint32 dimensionSizes[MAX_ARRAY_DIMENSIONS];
|
|
PRUint32 i;
|
|
PRUint32 dimensionCount = 1;
|
|
nsCOMPtr<nsISchemaType> schemaArrayType;
|
|
if (aSchemaType) {
|
|
PRUint16 type;
|
|
nsresult rc = aSchemaType->GetSchemaType(&type);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
if (type == nsISchemaType::SCHEMA_TYPE_COMPLEX) {
|
|
nsCOMPtr<nsISchemaComplexType> ct = do_QueryInterface(aSchemaType);
|
|
nsresult rc = ct->GetArrayDimension(&dimensionCount);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
if (dimensionCount == 0) {
|
|
dimensionCount = 1;
|
|
}
|
|
else {
|
|
// Arrays with no defaults are supposed to return 0, but apparently do not
|
|
rc = ct->GetArrayType(getter_AddRefs(schemaArrayType));
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
}
|
|
}
|
|
}
|
|
for (i = 0; i < dimensionCount; i++)
|
|
dimensionSizes[i] = 0;
|
|
// Look over the array and find its dimensions and common type.
|
|
nsresult rc = GetArrayType(aSource, dimensionCount, dimensionSizes, &arrayNativeType);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
nsAutoString arrayTypeSchemaURI;
|
|
nsAutoString arrayTypeSchemaName;
|
|
if (!schemaArrayType) {
|
|
switch (arrayNativeType) {
|
|
case nsIDataType::VTYPE_INTERFACE: // In a variant, an interface is a struct, but here it is any
|
|
case nsIDataType::VTYPE_INTERFACE_IS:
|
|
arrayTypeSchemaName = kAnyTypeSchemaType;
|
|
arrayTypeSchemaURI = nsSOAPUtils::kXSURI;
|
|
break;
|
|
default: // Everything else can be interpreted correctly
|
|
rc = GetNativeType(arrayNativeType, arrayTypeSchemaURI, arrayTypeSchemaName);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
}
|
|
nsCOMPtr < nsISchemaCollection > collection;
|
|
nsresult rc =
|
|
aEncoding->GetSchemaCollection(getter_AddRefs(collection));
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
rc = collection->GetType(arrayTypeSchemaName,
|
|
arrayTypeSchemaName,
|
|
getter_AddRefs(schemaArrayType));
|
|
// if (NS_FAILED(rc)) return rc;
|
|
}
|
|
else {
|
|
rc = schemaArrayType->GetTargetNamespace(arrayTypeSchemaURI);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
rc = schemaArrayType->GetName(arrayTypeSchemaName);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
}
|
|
rc = EncodeSimpleValue(aEncoding, kEmpty,
|
|
aNamespaceURI,
|
|
aName, aSchemaType, aDestination, aReturnValue);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
|
|
// This needs a real live interpretation of the type.
|
|
|
|
{
|
|
nsAutoString value;
|
|
nsSOAPUtils::MakeNamespacePrefix(aEncoding,*aReturnValue,arrayTypeSchemaURI,value);
|
|
value.Append(nsSOAPUtils::kQualifiedSeparator);
|
|
value.Append(arrayTypeSchemaName);
|
|
value.Append(NS_LITERAL_STRING("["));
|
|
for (i = 0; i < dimensionCount; i++) {
|
|
if (i > 0)
|
|
value.Append(NS_LITERAL_STRING(","));
|
|
char* ptr = PR_smprintf("%d", dimensionSizes[i]);
|
|
value.Append(NS_ConvertUTF8toUCS2(ptr));
|
|
PR_smprintf_free(ptr);
|
|
}
|
|
value.Append(NS_LITERAL_STRING("]"));
|
|
nsAutoString encURI;
|
|
rc = aEncoding->GetExternalSchemaURI(nsSOAPUtils::kSOAPEncURI,encURI);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
|
|
rc = (*aReturnValue)->SetAttributeNS(encURI, kSOAPArrayTypeAttribute, value);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
}
|
|
|
|
// For efficiency, we should perform encoder lookup once here.
|
|
|
|
return EncodeArray(aEncoding, aSource, schemaArrayType, aAttachments, *aReturnValue, dimensionCount, dimensionSizes);
|
|
}
|
|
|
|
// String
|
|
|
|
NS_IMETHODIMP
|
|
nsStringEncoder::Encode(nsISOAPEncoding * aEncoding,
|
|
nsIVariant * aSource,
|
|
const nsAString & aNamespaceURI,
|
|
const nsAString & aName,
|
|
nsISchemaType * aSchemaType,
|
|
nsISOAPAttachments * aAttachments,
|
|
nsIDOMElement * aDestination,
|
|
nsIDOMElement * *aReturnValue)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aEncoding);
|
|
NS_ENSURE_ARG_POINTER(&aNamespaceURI);
|
|
NS_ENSURE_ARG_POINTER(&aName);
|
|
NS_ENSURE_ARG_POINTER(aDestination);
|
|
NS_ENSURE_ARG_POINTER(aReturnValue);
|
|
*aReturnValue = nsnull;
|
|
nsresult rc;
|
|
nsAutoString value;
|
|
rc = aSource->GetAsAString(value);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
return EncodeSimpleValue(aEncoding, value,
|
|
aNamespaceURI, aName, aSchemaType, aDestination,
|
|
aReturnValue);
|
|
}
|
|
|
|
// PRBool
|
|
|
|
NS_IMETHODIMP
|
|
nsBooleanEncoder::Encode(nsISOAPEncoding * aEncoding,
|
|
nsIVariant * aSource,
|
|
const nsAString & aNamespaceURI,
|
|
const nsAString & aName,
|
|
nsISchemaType * aSchemaType,
|
|
nsISOAPAttachments * aAttachments,
|
|
nsIDOMElement * aDestination,
|
|
nsIDOMElement * *aReturnValue)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aEncoding);
|
|
NS_ENSURE_ARG_POINTER(&aNamespaceURI);
|
|
NS_ENSURE_ARG_POINTER(&aName);
|
|
NS_ENSURE_ARG_POINTER(aDestination);
|
|
NS_ENSURE_ARG_POINTER(aReturnValue);
|
|
*aReturnValue = nsnull;
|
|
nsresult rc;
|
|
PRBool b;
|
|
rc = aSource->GetAsBool(&b);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
return EncodeSimpleValue(aEncoding, b ? nsSOAPUtils::kTrueA : nsSOAPUtils::kFalseA,
|
|
aNamespaceURI, aName, aSchemaType, aDestination,
|
|
aReturnValue);
|
|
}
|
|
|
|
// Double
|
|
|
|
NS_IMETHODIMP
|
|
nsDoubleEncoder::Encode(nsISOAPEncoding * aEncoding,
|
|
nsIVariant * aSource,
|
|
const nsAString & aNamespaceURI,
|
|
const nsAString & aName,
|
|
nsISchemaType * aSchemaType,
|
|
nsISOAPAttachments * aAttachments,
|
|
nsIDOMElement * aDestination,
|
|
nsIDOMElement * *aReturnValue)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aEncoding);
|
|
NS_ENSURE_ARG_POINTER(&aNamespaceURI);
|
|
NS_ENSURE_ARG_POINTER(&aName);
|
|
NS_ENSURE_ARG_POINTER(aDestination);
|
|
NS_ENSURE_ARG_POINTER(aReturnValue);
|
|
*aReturnValue = nsnull;
|
|
nsresult rc;
|
|
double f;
|
|
rc = aSource->GetAsDouble(&f); // Check that double works.
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
char *ptr = PR_smprintf("%lf", f);
|
|
if (!ptr)
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
nsAutoString value;
|
|
CopyASCIItoUCS2(nsDependentCString(ptr), value);
|
|
PR_smprintf_free(ptr);
|
|
return EncodeSimpleValue(aEncoding, value,
|
|
aNamespaceURI, aName, aSchemaType, aDestination,
|
|
aReturnValue);
|
|
}
|
|
|
|
// Float
|
|
|
|
NS_IMETHODIMP
|
|
nsFloatEncoder::Encode(nsISOAPEncoding * aEncoding,
|
|
nsIVariant * aSource,
|
|
const nsAString & aNamespaceURI,
|
|
const nsAString & aName,
|
|
nsISchemaType * aSchemaType,
|
|
nsISOAPAttachments * aAttachments,
|
|
nsIDOMElement * aDestination,
|
|
nsIDOMElement * *aReturnValue)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aEncoding);
|
|
NS_ENSURE_ARG_POINTER(&aNamespaceURI);
|
|
NS_ENSURE_ARG_POINTER(&aName);
|
|
NS_ENSURE_ARG_POINTER(aDestination);
|
|
NS_ENSURE_ARG_POINTER(aReturnValue);
|
|
*aReturnValue = nsnull;
|
|
nsresult rc;
|
|
float f;
|
|
rc = aSource->GetAsFloat(&f); // Check that float works.
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
char *ptr = PR_smprintf("%f", f);
|
|
if (!ptr)
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
nsAutoString value;
|
|
CopyASCIItoUCS2(nsDependentCString(ptr), value);
|
|
PR_smprintf_free(ptr);
|
|
return EncodeSimpleValue(aEncoding, value,
|
|
aNamespaceURI, aName, aSchemaType, aDestination,
|
|
aReturnValue);
|
|
}
|
|
|
|
// PRInt64
|
|
|
|
NS_IMETHODIMP
|
|
nsLongEncoder::Encode(nsISOAPEncoding * aEncoding,
|
|
nsIVariant * aSource,
|
|
const nsAString & aNamespaceURI,
|
|
const nsAString & aName,
|
|
nsISchemaType * aSchemaType,
|
|
nsISOAPAttachments * aAttachments,
|
|
nsIDOMElement * aDestination,
|
|
nsIDOMElement * *aReturnValue)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aEncoding);
|
|
NS_ENSURE_ARG_POINTER(&aNamespaceURI);
|
|
NS_ENSURE_ARG_POINTER(&aName);
|
|
NS_ENSURE_ARG_POINTER(aDestination);
|
|
NS_ENSURE_ARG_POINTER(aReturnValue);
|
|
*aReturnValue = nsnull;
|
|
nsresult rc;
|
|
PRInt64 f;
|
|
rc = aSource->GetAsInt64(&f); // Get as a long number.
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
char *ptr = PR_smprintf("%lld", f);
|
|
if (!ptr)
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
nsAutoString value;
|
|
CopyASCIItoUCS2(nsDependentCString(ptr), value);
|
|
PR_smprintf_free(ptr);
|
|
return EncodeSimpleValue(aEncoding, value,
|
|
aNamespaceURI, aName, aSchemaType, aDestination,
|
|
aReturnValue);
|
|
}
|
|
|
|
// PRInt32
|
|
|
|
NS_IMETHODIMP
|
|
nsIntEncoder::Encode(nsISOAPEncoding * aEncoding,
|
|
nsIVariant * aSource,
|
|
const nsAString & aNamespaceURI,
|
|
const nsAString & aName,
|
|
nsISchemaType * aSchemaType,
|
|
nsISOAPAttachments * aAttachments,
|
|
nsIDOMElement * aDestination,
|
|
nsIDOMElement * *aReturnValue)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aEncoding);
|
|
NS_ENSURE_ARG_POINTER(&aNamespaceURI);
|
|
NS_ENSURE_ARG_POINTER(&aName);
|
|
NS_ENSURE_ARG_POINTER(aDestination);
|
|
NS_ENSURE_ARG_POINTER(aReturnValue);
|
|
*aReturnValue = nsnull;
|
|
nsresult rc;
|
|
PRInt32 f;
|
|
rc = aSource->GetAsInt32(&f); // Get as a long number.
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
char *ptr = PR_smprintf("%d", f);
|
|
if (!ptr)
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
nsAutoString value;
|
|
CopyASCIItoUCS2(nsDependentCString(ptr), value);
|
|
PR_smprintf_free(ptr);
|
|
return EncodeSimpleValue(aEncoding, value,
|
|
aNamespaceURI, aName, aSchemaType, aDestination,
|
|
aReturnValue);
|
|
}
|
|
|
|
// PRInt16
|
|
|
|
NS_IMETHODIMP
|
|
nsShortEncoder::Encode(nsISOAPEncoding * aEncoding,
|
|
nsIVariant * aSource,
|
|
const nsAString & aNamespaceURI,
|
|
const nsAString & aName,
|
|
nsISchemaType * aSchemaType,
|
|
nsISOAPAttachments * aAttachments,
|
|
nsIDOMElement * aDestination,
|
|
nsIDOMElement * *aReturnValue)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aEncoding);
|
|
NS_ENSURE_ARG_POINTER(&aNamespaceURI);
|
|
NS_ENSURE_ARG_POINTER(&aName);
|
|
NS_ENSURE_ARG_POINTER(aDestination);
|
|
NS_ENSURE_ARG_POINTER(aReturnValue);
|
|
*aReturnValue = nsnull;
|
|
nsresult rc;
|
|
PRInt16 f;
|
|
rc = aSource->GetAsInt16(&f); // Get as a long number.
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
char *ptr = PR_smprintf("%d", (PRInt32) f);
|
|
if (!ptr)
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
nsAutoString value;
|
|
CopyASCIItoUCS2(nsDependentCString(ptr), value);
|
|
PR_smprintf_free(ptr);
|
|
return EncodeSimpleValue(aEncoding, value,
|
|
aNamespaceURI, aName, aSchemaType, aDestination,
|
|
aReturnValue);
|
|
}
|
|
|
|
// Byte
|
|
|
|
NS_IMETHODIMP
|
|
nsByteEncoder::Encode(nsISOAPEncoding * aEncoding,
|
|
nsIVariant * aSource,
|
|
const nsAString & aNamespaceURI,
|
|
const nsAString & aName,
|
|
nsISchemaType * aSchemaType,
|
|
nsISOAPAttachments * aAttachments,
|
|
nsIDOMElement * aDestination,
|
|
nsIDOMElement * *aReturnValue)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aEncoding);
|
|
NS_ENSURE_ARG_POINTER(&aNamespaceURI);
|
|
NS_ENSURE_ARG_POINTER(&aName);
|
|
NS_ENSURE_ARG_POINTER(aDestination);
|
|
NS_ENSURE_ARG_POINTER(aReturnValue);
|
|
*aReturnValue = nsnull;
|
|
nsresult rc;
|
|
PRUint8 f;
|
|
rc = aSource->GetAsInt8(&f); // Get as a long number.
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
char *ptr = PR_smprintf("%d", (PRInt32) (signed char) f);
|
|
if (!ptr)
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
nsAutoString value;
|
|
CopyASCIItoUCS2(nsDependentCString(ptr), value);
|
|
PR_smprintf_free(ptr);
|
|
return EncodeSimpleValue(aEncoding, value,
|
|
aNamespaceURI, aName, aSchemaType, aDestination,
|
|
aReturnValue);
|
|
}
|
|
|
|
// PRUint64
|
|
|
|
NS_IMETHODIMP
|
|
nsUnsignedLongEncoder::Encode(nsISOAPEncoding * aEncoding,
|
|
nsIVariant * aSource,
|
|
const nsAString & aNamespaceURI,
|
|
const nsAString & aName,
|
|
nsISchemaType * aSchemaType,
|
|
nsISOAPAttachments * aAttachments,
|
|
nsIDOMElement * aDestination,
|
|
nsIDOMElement * *aReturnValue)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aEncoding);
|
|
NS_ENSURE_ARG_POINTER(&aNamespaceURI);
|
|
NS_ENSURE_ARG_POINTER(&aName);
|
|
NS_ENSURE_ARG_POINTER(aDestination);
|
|
NS_ENSURE_ARG_POINTER(aReturnValue);
|
|
*aReturnValue = nsnull;
|
|
nsresult rc;
|
|
PRUint64 f;
|
|
rc = aSource->GetAsUint64(&f); // Get as a long number.
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
char *ptr = PR_smprintf("%llu", f);
|
|
if (!ptr)
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
nsAutoString value;
|
|
CopyASCIItoUCS2(nsDependentCString(ptr), value);
|
|
PR_smprintf_free(ptr);
|
|
return EncodeSimpleValue(aEncoding, value,
|
|
aNamespaceURI, aName, aSchemaType, aDestination,
|
|
aReturnValue);
|
|
}
|
|
|
|
// PRUint32
|
|
|
|
NS_IMETHODIMP
|
|
nsUnsignedIntEncoder::Encode(nsISOAPEncoding * aEncoding,
|
|
nsIVariant * aSource,
|
|
const nsAString & aNamespaceURI,
|
|
const nsAString & aName,
|
|
nsISchemaType * aSchemaType,
|
|
nsISOAPAttachments * aAttachments,
|
|
nsIDOMElement * aDestination,
|
|
nsIDOMElement * *aReturnValue)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aEncoding);
|
|
NS_ENSURE_ARG_POINTER(&aNamespaceURI);
|
|
NS_ENSURE_ARG_POINTER(&aName);
|
|
NS_ENSURE_ARG_POINTER(aDestination);
|
|
NS_ENSURE_ARG_POINTER(aReturnValue);
|
|
*aReturnValue = nsnull;
|
|
nsresult rc;
|
|
PRUint32 f;
|
|
rc = aSource->GetAsUint32(&f); // Get as a long number.
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
char *ptr = PR_smprintf("%u", f);
|
|
if (!ptr)
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
nsAutoString value;
|
|
CopyASCIItoUCS2(nsDependentCString(ptr), value);
|
|
PR_smprintf_free(ptr);
|
|
return EncodeSimpleValue(aEncoding, value,
|
|
aNamespaceURI, aName, aSchemaType, aDestination,
|
|
aReturnValue);
|
|
}
|
|
|
|
// PRUint16
|
|
|
|
NS_IMETHODIMP
|
|
nsUnsignedShortEncoder::Encode(nsISOAPEncoding * aEncoding,
|
|
nsIVariant * aSource,
|
|
const nsAString & aNamespaceURI,
|
|
const nsAString & aName,
|
|
nsISchemaType * aSchemaType,
|
|
nsISOAPAttachments * aAttachments,
|
|
nsIDOMElement * aDestination,
|
|
nsIDOMElement * *aReturnValue)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aEncoding);
|
|
NS_ENSURE_ARG_POINTER(&aNamespaceURI);
|
|
NS_ENSURE_ARG_POINTER(&aName);
|
|
NS_ENSURE_ARG_POINTER(aDestination);
|
|
NS_ENSURE_ARG_POINTER(aReturnValue);
|
|
*aReturnValue = nsnull;
|
|
nsresult rc;
|
|
PRUint16 f;
|
|
rc = aSource->GetAsUint16(&f); // Get as a long number.
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
char *ptr = PR_smprintf("%u", (PRUint32) f);
|
|
if (!ptr)
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
nsAutoString value;
|
|
CopyASCIItoUCS2(nsDependentCString(ptr), value);
|
|
PR_smprintf_free(ptr);
|
|
return EncodeSimpleValue(aEncoding, value,
|
|
aNamespaceURI, aName, aSchemaType, aDestination,
|
|
aReturnValue);
|
|
}
|
|
|
|
// Unsigned Byte
|
|
|
|
NS_IMETHODIMP
|
|
nsUnsignedByteEncoder::Encode(nsISOAPEncoding * aEncoding,
|
|
nsIVariant * aSource,
|
|
const nsAString & aNamespaceURI,
|
|
const nsAString & aName,
|
|
nsISchemaType * aSchemaType,
|
|
nsISOAPAttachments * aAttachments,
|
|
nsIDOMElement * aDestination,
|
|
nsIDOMElement * *aReturnValue)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aEncoding);
|
|
NS_ENSURE_ARG_POINTER(&aNamespaceURI);
|
|
NS_ENSURE_ARG_POINTER(&aName);
|
|
NS_ENSURE_ARG_POINTER(aDestination);
|
|
NS_ENSURE_ARG_POINTER(aReturnValue);
|
|
*aReturnValue = nsnull;
|
|
nsresult rc;
|
|
PRUint8 f;
|
|
rc = aSource->GetAsUint8(&f); // Get as a long number.
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
char *ptr = PR_smprintf("%u", (PRUint32) f);
|
|
if (!ptr)
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
nsAutoString value;
|
|
CopyASCIItoUCS2(nsDependentCString(ptr), value);
|
|
PR_smprintf_free(ptr);
|
|
return EncodeSimpleValue(aEncoding, value,
|
|
aNamespaceURI, aName, aSchemaType, aDestination,
|
|
aReturnValue);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsDefaultEncoder::Decode(nsISOAPEncoding * aEncoding,
|
|
nsIDOMElement * aSource,
|
|
nsISchemaType * aSchemaType,
|
|
nsISOAPAttachments * aAttachments,
|
|
nsIVariant ** _retval)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aEncoding);
|
|
NS_ENSURE_ARG_POINTER(aSource);
|
|
NS_ENSURE_ARG_POINTER(_retval);
|
|
*_retval = nsnull;
|
|
nsCOMPtr < nsISOAPEncoding > encoding = aEncoding; // First, handle encoding redesignation, if any
|
|
|
|
{
|
|
nsCOMPtr < nsIDOMAttr > enc;
|
|
nsresult rv =
|
|
aSource->
|
|
GetAttributeNodeNS(*nsSOAPUtils::kSOAPEnvURI[mSOAPVersion],
|
|
nsSOAPUtils::kEncodingStyleAttribute,
|
|
getter_AddRefs(enc));
|
|
if (NS_FAILED(rv))
|
|
return rv;
|
|
if (enc) {
|
|
nsAutoString oldstyle;
|
|
encoding->GetStyleURI(oldstyle);
|
|
if (NS_FAILED(rv))
|
|
return rv;
|
|
nsAutoString style;
|
|
encoding->GetStyleURI(style);
|
|
if (NS_FAILED(rv))
|
|
return rv;
|
|
if (!style.Equals(oldstyle)) {
|
|
nsCOMPtr < nsISOAPEncoding > newencoding;
|
|
encoding->GetAssociatedEncoding(style, PR_FALSE,
|
|
getter_AddRefs(newencoding));
|
|
if (NS_FAILED(rv))
|
|
return rv;
|
|
if (newencoding) {
|
|
return newencoding->Decode(aSource, aSchemaType, aAttachments, _retval);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Handle xsi:null="true"
|
|
|
|
nsAutoString nullstr;
|
|
if (nsSOAPUtils::GetAttribute(aEncoding, aSource, nsSOAPUtils::kXSIURI, kNull, nullstr)) {
|
|
if (nullstr.Equals(nsSOAPUtils::kTrue)
|
|
|| nullstr.Equals(nsSOAPUtils::kTrueA)) {
|
|
*_retval = nsnull;
|
|
return NS_OK;
|
|
}
|
|
else if (!(nullstr.Equals(nsSOAPUtils::kFalse)
|
|
|| nullstr.Equals(nsSOAPUtils::kFalseA)))
|
|
return SOAP_EXCEPTION(NS_ERROR_ILLEGAL_VALUE,"SOAP_NILL_VALUE","The value of the nill attribute must be true or false.");
|
|
}
|
|
|
|
nsCOMPtr < nsISchemaType > type = aSchemaType;
|
|
nsCOMPtr < nsISOAPDecoder > decoder; // All that comes out of this block is decoder, type, and some checks.
|
|
{ // Look up type element and schema attribute, if possible
|
|
nsCOMPtr < nsISchemaType > subType;
|
|
nsCOMPtr < nsISchemaCollection > collection;
|
|
nsresult rc =
|
|
aEncoding->GetSchemaCollection(getter_AddRefs(collection));
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
nsAutoString ns;
|
|
nsAutoString name;
|
|
|
|
rc = aSource->GetNamespaceURI(name);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
rc = aEncoding->GetInternalSchemaURI(name, ns);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
rc = aSource->GetLocalName(name);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
nsCOMPtr < nsISchemaElement > element;
|
|
rc = collection->GetElement(name, ns, getter_AddRefs(element));
|
|
// if (NS_FAILED(rc)) return rc;
|
|
if (element) {
|
|
rc = element->GetType(getter_AddRefs(subType));
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
} else {
|
|
nsAutoString internal;
|
|
rc = aEncoding->GetInternalSchemaURI(ns, internal);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
if (internal.Equals(nsSOAPUtils::kSOAPEncURI)) { // Last-ditch hack to get undeclared types from SOAP namespace
|
|
if (name.Equals(kArraySOAPType)
|
|
|| name.Equals(kStructSOAPType)) { // This should not be needed if schema has these declarations
|
|
rc = collection->GetType(name, internal, getter_AddRefs(subType));
|
|
} else {
|
|
rc = collection->GetType(name,
|
|
nsSOAPUtils::kXSURI,
|
|
getter_AddRefs(subType));
|
|
}
|
|
}
|
|
// if (NS_FAILED(rc)) return rc;
|
|
}
|
|
if (!subType)
|
|
subType = type;
|
|
|
|
nsCOMPtr < nsISchemaType > subsubType;
|
|
nsAutoString explicitType;
|
|
if (nsSOAPUtils::GetAttribute(aEncoding, aSource, nsSOAPUtils::kXSIURI,
|
|
nsSOAPUtils::kXSITypeAttribute,
|
|
explicitType)) {
|
|
rc = nsSOAPUtils::GetNamespaceURI(aEncoding, aSource, explicitType, ns);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
rc = nsSOAPUtils::GetLocalName(explicitType, name);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
rc = collection->GetType(name, ns, getter_AddRefs(subsubType));
|
|
// if (NS_FAILED(rc)) return rc;
|
|
}
|
|
if (!subsubType)
|
|
subsubType = subType;
|
|
|
|
if (subsubType) { // Loop up the hierarchy, to check and look for decoders
|
|
nsCOMPtr < nsISchemaType > lookupType = subsubType;
|
|
do {
|
|
if (lookupType == subType) { // Tick off the located super classes
|
|
subType = nsnull;
|
|
}
|
|
if (lookupType == type) { // Tick off the located super classes
|
|
type = nsnull;
|
|
}
|
|
if (!decoder) {
|
|
nsAutoString schemaType;
|
|
nsAutoString schemaURI;
|
|
nsresult rc = lookupType->GetName(schemaType);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
rc = lookupType->GetTargetNamespace(schemaURI);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
nsAutoString encodingKey;
|
|
SOAPEncodingKey(schemaURI, schemaType, encodingKey);
|
|
rc = aEncoding->GetDecoder(encodingKey, getter_AddRefs(decoder));
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
}
|
|
nsCOMPtr<nsISchemaType> supertype;
|
|
rc = GetSupertype(aEncoding, lookupType, getter_AddRefs(supertype));
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
lookupType = supertype;
|
|
} while (lookupType);
|
|
if (type || subType) // If the proper subclass relationships didn't exist, then error return.
|
|
return SOAP_EXCEPTION(NS_ERROR_ILLEGAL_VALUE,"SOAP_TYPE_SUBCLASS","The type of the element or xsi:type must be a subclass of the required type.");
|
|
type = subsubType; // If they did, then we now have a new, better type.
|
|
}
|
|
}
|
|
if (!decoder) {
|
|
PRBool simple = PR_TRUE;
|
|
if (type) {
|
|
nsresult rc = HasSimpleValue(type, &simple);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
}
|
|
if (simple) {
|
|
nsCOMPtr<nsIDOMElement> child;
|
|
nsSOAPUtils::GetFirstChildElement(aSource, getter_AddRefs(child));
|
|
simple = !child;
|
|
}
|
|
nsAutoString decodingKey;
|
|
if (!simple) {
|
|
SOAPEncodingKey(nsSOAPUtils::kSOAPEncURI,
|
|
kStructSOAPType, decodingKey);
|
|
} else {
|
|
SOAPEncodingKey(nsSOAPUtils::kXSURI,
|
|
kAnySimpleTypeSchemaType, decodingKey);
|
|
}
|
|
nsresult rc =
|
|
aEncoding->GetDecoder(decodingKey, getter_AddRefs(decoder));
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
}
|
|
if (decoder) {
|
|
return decoder->Decode(aEncoding, aSource, type, aAttachments,
|
|
_retval);
|
|
}
|
|
return SOAP_EXCEPTION(NS_ERROR_NOT_IMPLEMENTED,"SOAP_NO_DECODER_FOR_TYPE","The default decoder finds no decoder for specific type");
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsAnyTypeEncoder::Decode(nsISOAPEncoding * aEncoding,
|
|
nsIDOMElement * aSource,
|
|
nsISchemaType * aSchemaType,
|
|
nsISOAPAttachments * aAttachments,
|
|
nsIVariant ** _retval)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aEncoding);
|
|
NS_ENSURE_ARG_POINTER(aSource);
|
|
NS_ENSURE_ARG_POINTER(_retval);
|
|
*_retval = nsnull;
|
|
PRBool simple = PR_TRUE;
|
|
if (aSchemaType) {
|
|
nsresult rc = HasSimpleValue(aSchemaType, &simple);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
}
|
|
if (simple) {
|
|
nsCOMPtr<nsIDOMElement> child;
|
|
nsSOAPUtils::GetFirstChildElement(aSource, getter_AddRefs(child));
|
|
simple = !child;
|
|
}
|
|
nsAutoString decodingKey;
|
|
if (!simple) {
|
|
SOAPEncodingKey(nsSOAPUtils::kSOAPEncURI,
|
|
kStructSOAPType, decodingKey);
|
|
} else {
|
|
SOAPEncodingKey(nsSOAPUtils::kXSURI,
|
|
kAnySimpleTypeSchemaType, decodingKey);
|
|
}
|
|
nsCOMPtr < nsISOAPDecoder > decoder;
|
|
nsresult rc =
|
|
aEncoding->GetDecoder(decodingKey, getter_AddRefs(decoder));
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
if (decoder) {
|
|
return decoder->Decode(aEncoding, aSource,
|
|
aSchemaType, aAttachments, _retval);
|
|
return rc;
|
|
}
|
|
return SOAP_EXCEPTION(NS_ERROR_NOT_IMPLEMENTED,"SOAP_NO_DECODER_FOR_TYPE","The any type decoder finds no decoder for specific element");
|
|
}
|
|
|
|
static nsresult DecodeStructParticle(nsISOAPEncoding* aEncoding, nsIDOMElement* aElement,
|
|
nsISchemaParticle* aParticle,
|
|
nsISOAPAttachments * aAttachments, nsISOAPPropertyBagMutator* aDestination,
|
|
nsIDOMElement** _retElement)
|
|
{
|
|
nsresult rc;
|
|
*_retElement = nsnull;
|
|
if (aParticle) {
|
|
PRUint32 minOccurs;
|
|
rc = aParticle->GetMinOccurs(&minOccurs);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
PRUint32 maxOccurs;
|
|
rc = aParticle->GetMaxOccurs(&maxOccurs);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
PRUint16 particleType;
|
|
rc = aParticle->GetParticleType(&particleType);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
switch(particleType) {
|
|
case nsISchemaParticle::PARTICLE_TYPE_ELEMENT: {
|
|
if (maxOccurs > 1) { // Todo: Try to make this thing work as an array?
|
|
return NS_ERROR_NOT_AVAILABLE; // For now, we just try something else if we can (recoverable)
|
|
}
|
|
nsCOMPtr<nsISchemaElement> element = do_QueryInterface(aParticle);
|
|
nsAutoString name;
|
|
rc = element->GetTargetNamespace(name);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
if (!name.IsEmpty()) {
|
|
rc = NS_ERROR_NOT_AVAILABLE; // No known way to use namespace qualification in struct
|
|
}
|
|
else {
|
|
rc = element->GetName(name);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
nsAutoString ename;
|
|
if (aElement) { // Permits aElement to be null and fail recoverably
|
|
nsAutoString temp;
|
|
rc = aElement->GetNamespaceURI(ename);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
if (!ename.IsEmpty()) { // Only get an ename if there is a non-empty namespaceURI
|
|
rc = aElement->GetLocalName(ename);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
}
|
|
}
|
|
if (!ename.Equals(name))
|
|
rc = NS_ERROR_NOT_AVAILABLE; // The element must be a declaration of the next element
|
|
}
|
|
if (!NS_FAILED(rc)) {
|
|
nsCOMPtr<nsISchemaType> type;
|
|
rc = element->GetType(getter_AddRefs(type));
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
nsCOMPtr<nsIVariant> value;
|
|
rc = aEncoding->Decode(aElement, type, aAttachments, getter_AddRefs(value));
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
rc = aDestination->AddProperty(name, value);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
nsSOAPUtils::GetNextSiblingElement(aElement, _retElement);
|
|
}
|
|
if (minOccurs == 0 && rc == NS_ERROR_NOT_AVAILABLE) { // If we failed recoverably, but we were permitted to, then return success
|
|
*_retElement = aElement;
|
|
NS_IF_ADDREF(*_retElement);
|
|
rc = NS_OK;
|
|
}
|
|
return rc;
|
|
}
|
|
case nsISchemaParticle::PARTICLE_TYPE_MODEL_GROUP:
|
|
{
|
|
if (maxOccurs > 1) { // Todo: Try to make this thing work as an array?
|
|
return NS_ERROR_NOT_AVAILABLE; // For now, we just try something else if we can (recoverable)
|
|
}
|
|
nsCOMPtr<nsISchemaModelGroup> modelGroup = do_QueryInterface(aParticle);
|
|
PRUint16 compositor;
|
|
rc = modelGroup->GetCompositor(&compositor);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
PRUint32 particleCount;
|
|
rc = modelGroup->GetParticleCount(&particleCount);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
PRUint32 i;
|
|
if (compositor == nsISchemaModelGroup::COMPOSITOR_ALL) { // This handles out-of-order appearances.
|
|
nsCOMPtr<nsISupportsArray> all = new nsSupportsArray(); // Create something we can mutate
|
|
all->SizeTo(particleCount);
|
|
nsCOMPtr<nsISchemaParticle> child;
|
|
PRBool mangled = PR_FALSE;
|
|
for (i = 0; i < particleCount; i++) {
|
|
rc = modelGroup->GetParticle(i, getter_AddRefs(child));
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
rc = all->AppendElement(child);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
}
|
|
nsCOMPtr<nsIDOMElement> next = aElement;
|
|
while (particleCount > 0) {
|
|
for (i = 0; i < particleCount; i++) {
|
|
child = dont_AddRef(NS_STATIC_CAST
|
|
(nsISchemaParticle*, all->ElementAt(i)));
|
|
nsCOMPtr<nsIDOMElement> after;
|
|
rc = DecodeStructParticle(aEncoding, aElement, child, aAttachments, aDestination, getter_AddRefs(after));
|
|
if (!NS_FAILED(rc)) {
|
|
next = after;
|
|
mangled = PR_TRUE;
|
|
rc = all->RemoveElementAt(i);
|
|
particleCount--;
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
}
|
|
if (rc != NS_ERROR_NOT_AVAILABLE) {
|
|
break;
|
|
}
|
|
}
|
|
if (mangled && rc == NS_ERROR_NOT_AVAILABLE) { // This detects ambiguous model (non-deterministic choice which fails after succeeding on first)
|
|
rc = SOAP_EXCEPTION(NS_ERROR_ILLEGAL_VALUE,"SOAP_AMBIGUOUS_DECODING","Cannot proceed due to ambiguity or error in content model");
|
|
// Error is not considered recoverable due to partially-created output.
|
|
}
|
|
if (NS_FAILED(rc))
|
|
break;
|
|
}
|
|
if (!NS_FAILED(rc)) {
|
|
*_retElement = next;
|
|
NS_IF_ADDREF(*_retElement);
|
|
}
|
|
if (minOccurs == 0 && rc == NS_ERROR_NOT_AVAILABLE) { // If we succeeded or failed recoverably, but we were permitted to, then return success
|
|
*_retElement = aElement;
|
|
NS_IF_ADDREF(*_retElement);
|
|
rc = NS_OK;
|
|
}
|
|
}
|
|
else { // This handles sequences and choices.
|
|
nsCOMPtr<nsIDOMElement> next = aElement;
|
|
for (i = 0; i < particleCount; i++) {
|
|
nsCOMPtr<nsISchemaParticle> child;
|
|
rc = modelGroup->GetParticle(i, getter_AddRefs(child));
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
nsCOMPtr<nsIDOMElement> after;
|
|
rc = DecodeStructParticle(aEncoding, aElement, child, aAttachments, aDestination, getter_AddRefs(after));
|
|
if (!NS_FAILED(rc)) {
|
|
next = after;
|
|
}
|
|
if (compositor == nsISchemaModelGroup::COMPOSITOR_CHOICE) {
|
|
if (rc == NS_ERROR_NOT_AVAILABLE) {
|
|
rc = NS_OK;
|
|
}
|
|
else {
|
|
if (!NS_FAILED(rc)) {
|
|
*_retElement = next;
|
|
NS_IF_ADDREF(*_retElement);
|
|
}
|
|
return rc;
|
|
}
|
|
}
|
|
else if (i > 0 && rc == NS_ERROR_NOT_AVAILABLE) { // This detects ambiguous model (non-deterministic choice which fails after succeeding on first)
|
|
rc = SOAP_EXCEPTION(NS_ERROR_ILLEGAL_VALUE,"SOAP_AMBIGUOUS_DECODING","Cannot proceed due to ambiguity or error in content model");
|
|
// Error is not considered recoverable due to partially-created output.
|
|
}
|
|
if (NS_FAILED(rc))
|
|
break;
|
|
}
|
|
if (compositor == nsISchemaModelGroup::COMPOSITOR_CHOICE)
|
|
rc = NS_ERROR_NOT_AVAILABLE;
|
|
if (!NS_FAILED(rc)) {
|
|
*_retElement = next;
|
|
NS_IF_ADDREF(*_retElement);
|
|
}
|
|
if (minOccurs == 0 && rc == NS_ERROR_NOT_AVAILABLE) { // If we succeeded or failed recoverably, but we were permitted to, then return success
|
|
*_retElement = aElement;
|
|
NS_IF_ADDREF(*_retElement);
|
|
rc = NS_OK;
|
|
}
|
|
}
|
|
return rc; // Return status
|
|
}
|
|
case nsISchemaParticle::PARTICLE_TYPE_ANY:
|
|
// No model available here (we may wish to handle strict versus lazy, but what does that mean with only local accessor names)
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
nsCOMPtr<nsIDOMElement> child = aElement;
|
|
while (child) {
|
|
nsAutoString name;
|
|
nsAutoString namespaceURI;
|
|
nsCOMPtr<nsIVariant>value;
|
|
rc = child->GetLocalName(name);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
rc = child->GetNamespaceURI(namespaceURI);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
if (!namespaceURI.IsEmpty()) { // If we ever figure out what to do with namespaces, get an internal one
|
|
return SOAP_EXCEPTION(NS_ERROR_ILLEGAL_VALUE,"SOAP_GLOBAL_ACCESSOR","Decoded struct contained global accessor, which does not map well into a property name.");
|
|
}
|
|
rc = aEncoding->Decode(child, nsnull, aAttachments, getter_AddRefs(value));
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
rc = aDestination->AddProperty(name, value);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
|
|
nsCOMPtr<nsIDOMElement> nextchild;
|
|
nsSOAPUtils::GetNextSiblingElement(child, getter_AddRefs(nextchild));
|
|
child = nextchild;
|
|
}
|
|
*_retElement = nsnull;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsStructEncoder::Decode(nsISOAPEncoding * aEncoding,
|
|
nsIDOMElement * aSource,
|
|
nsISchemaType * aSchemaType,
|
|
nsISOAPAttachments * aAttachments,
|
|
nsIVariant ** _retval)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aEncoding);
|
|
NS_ENSURE_ARG_POINTER(aSource);
|
|
NS_ENSURE_ARG_POINTER(_retval);
|
|
*_retval = nsnull;
|
|
nsresult rc;
|
|
nsCOMPtr<nsISOAPPropertyBagMutator> mutator = do_CreateInstance(NS_SOAPPROPERTYBAGMUTATOR_CONTRACTID, &rc);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
nsCOMPtr<nsISchemaModelGroup>modelGroup;
|
|
if (aSchemaType) {
|
|
nsCOMPtr<nsISchemaComplexType>ctype = do_QueryInterface(aSchemaType);
|
|
if (ctype) {
|
|
rc = ctype->GetModelGroup(getter_AddRefs(modelGroup));
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
}
|
|
}
|
|
nsCOMPtr<nsIDOMElement> child;
|
|
nsSOAPUtils::GetFirstChildElement(aSource, getter_AddRefs(child));
|
|
nsCOMPtr<nsIDOMElement> result;
|
|
rc = DecodeStructParticle(aEncoding, child, modelGroup, aAttachments, mutator, getter_AddRefs(result));
|
|
if (!NS_FAILED(rc) // If there were elements left over, then we failed to decode everything.
|
|
&& result)
|
|
rc = SOAP_EXCEPTION(NS_ERROR_ILLEGAL_VALUE,"SOAP_LEFTOVERS","Decoded struct contained extra items not mentioned in the content model.");
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
nsCOMPtr < nsIPropertyBag > bag;
|
|
rc = mutator->GetPropertyBag(getter_AddRefs(bag));
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
nsCOMPtr < nsIWritableVariant > p =
|
|
do_CreateInstance(NS_VARIANT_CONTRACTID, &rc);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
p->SetAsInterface(NS_GET_IID(nsIPropertyBag), bag);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
*_retval = p;
|
|
NS_ADDREF(*_retval);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsAnySimpleTypeEncoder::Decode(nsISOAPEncoding * aEncoding,
|
|
nsIDOMElement * aSource,
|
|
nsISchemaType * aSchemaType,
|
|
nsISOAPAttachments * aAttachments,
|
|
nsIVariant ** _retval)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aEncoding);
|
|
NS_ENSURE_ARG_POINTER(aSource);
|
|
NS_ENSURE_ARG_POINTER(_retval);
|
|
*_retval = nsnull;
|
|
nsAutoString value;
|
|
nsresult rc = nsSOAPUtils::GetElementTextContent(aSource, value);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
nsCOMPtr < nsIWritableVariant > p =
|
|
do_CreateInstance(NS_VARIANT_CONTRACTID, &rc);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
rc = p->SetAsAString(value);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
*_retval = p;
|
|
NS_ADDREF(*_retval);
|
|
return NS_OK;
|
|
}
|
|
|
|
/**
|
|
* Extract multiple bracketted numbers from the end of
|
|
* the string and return the string with the number
|
|
* removed or return the original string and -1. Either
|
|
* the number of dimensions or the size of any particular
|
|
* dimension can be returned as -1. An over-all 0
|
|
* means that either there were no dimensions or there
|
|
* was a fundamental problem interpreting it. A
|
|
* -1 on any particular size of a dimension means that
|
|
* that particular size was not available or was not
|
|
* interpretable. That may be a recoverable error
|
|
* if the values represented a size, because we can
|
|
* manually scan the array, but that shouldbe fatal
|
|
* if specifying a position. In these cases, the
|
|
* bracketted values are removed.
|
|
*/
|
|
static PRUint32 DecodeArrayDimensions(const nsAString& src, PRInt32* aDimensionSizes, nsAString & dst)
|
|
{
|
|
dst.Assign(src);
|
|
nsReadingIterator < PRUnichar > i1;
|
|
nsReadingIterator < PRUnichar > i2;
|
|
src.BeginReading(i1);
|
|
src.EndReading(i2);
|
|
if (src.IsEmpty()) return 0;
|
|
while (i1 != i2 // Loop past white space
|
|
&& *(--i2) <= ' ') // In XML, all valid characters <= space are the only whitespace
|
|
;
|
|
if (*i2 != ']') { // In this case, not an array dimension
|
|
PRInt32 len = Distance(i1, i2) - 1; // This is the size to truncate to at the end.
|
|
src.Left(dst, len); // Truncate the string.
|
|
return 0; // Eliminated white space.
|
|
}
|
|
|
|
PRInt32 dimensionCount = 1; // Counting the dimensions
|
|
for (;;) { // First look for the matching bracket from reverse and commas.
|
|
if (i1 == i2) { // No matching bracket.
|
|
return 0;
|
|
}
|
|
PRUnichar c = *(--i2);
|
|
if (c == '[') { // Matching bracket found!
|
|
break;
|
|
}
|
|
if (c == ',') {
|
|
dimensionCount++;
|
|
}
|
|
}
|
|
PRInt32 len;
|
|
{
|
|
nsReadingIterator < PRUnichar > i3 = i2++; // Cover any extra white space
|
|
while (i1 != i3) { // Loop past white space
|
|
if (*(--i3) > ' ') { // In XML, all valid characters <= space are the only whitespace
|
|
i3++;
|
|
break;
|
|
}
|
|
}
|
|
len = Distance(i1, i3); // Length remaining in string after operation
|
|
}
|
|
|
|
if (dimensionCount > MAX_ARRAY_DIMENSIONS) { // Completely ignore it if too many dimensions.
|
|
return 0;
|
|
}
|
|
|
|
i1 = i2;
|
|
src.EndReading(i2);
|
|
while (*(--i2) != ']') // Find end bracket again
|
|
;
|
|
|
|
dimensionCount = 0; // Start with first dimension.
|
|
aDimensionSizes[dimensionCount] = -1;
|
|
PRBool finished = PR_FALSE; // Disallow space within numbers
|
|
|
|
while (i1 != i2) {
|
|
PRUnichar c = *(i1++);
|
|
if (c < '0' || c > '9') {
|
|
// There may be slightly more to do here if alternative radixes are supported.
|
|
if (c <= ' ') { // In XML, all valid characters <= space are the only whitespace
|
|
if (aDimensionSizes[dimensionCount] >= 0) {
|
|
finished = PR_TRUE;
|
|
}
|
|
}
|
|
else if (c == ',') { // Introducing new dimension
|
|
aDimensionSizes[++dimensionCount] = -1; // Restarting it at -1
|
|
finished = PR_FALSE;
|
|
}
|
|
else
|
|
return 0; // Unrecognized character
|
|
} else {
|
|
if (finished) {
|
|
return 0; // Numbers not allowed after white space
|
|
}
|
|
if (aDimensionSizes[dimensionCount] == -1)
|
|
aDimensionSizes[dimensionCount] = 0;
|
|
if (aDimensionSizes[dimensionCount] < 214748364) {
|
|
aDimensionSizes[dimensionCount] = aDimensionSizes[dimensionCount] * 10 + c - '0';
|
|
}
|
|
else {
|
|
return 0; // Number got too big.
|
|
}
|
|
}
|
|
}
|
|
src.Left(dst, len); // Truncate the string.
|
|
return dimensionCount + 1; // Return the number of dimensions
|
|
}
|
|
|
|
/**
|
|
* Extract multiple bracketted numbers from the end of
|
|
* the string and reconcile with a passed-in set of
|
|
* dimensions, computing the offset in the array.
|
|
* Presumes that the caller already knows the dimensions
|
|
* fit into 32-bit signed integer, due to computing
|
|
* total size of array.
|
|
*
|
|
* If there is extra garbage within the
|
|
* Any blank or unreadable dimensions or extra garbage
|
|
* within the string result in a return of -1, which is
|
|
* bad wherever a position string was interpreted.
|
|
*/
|
|
static PRInt32 DecodeArrayPosition(const nsAString& src, PRUint32 aDimensionCount, PRInt32* aDimensionSizes)
|
|
{
|
|
PRInt32 pos[MAX_ARRAY_DIMENSIONS];
|
|
nsAutoString leftover;
|
|
PRUint32 i = DecodeArrayDimensions(src, pos, leftover);
|
|
if (i != aDimensionCount // Easy cases where something went wrong
|
|
|| !leftover.IsEmpty())
|
|
return -1;
|
|
PRInt32 result = 0;
|
|
for (i = 0;;) {
|
|
PRInt32 next = pos[i];
|
|
if (next == -1
|
|
|| next >= aDimensionSizes[i])
|
|
return -1;
|
|
result = result + next;
|
|
if (++i < aDimensionCount) // Multiply for next round.
|
|
result = result * aDimensionSizes[i];
|
|
else
|
|
break;
|
|
}
|
|
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,
|
|
PRUint32 aDimensionCount, PRInt32* aDimensionSizes, PRUint32 aSizeof, PRUint8* aArray)
|
|
{
|
|
if (aSizeof == 0) { // Variants do not support construction of null-sized arrays
|
|
return aResult->SetAsEmpty();
|
|
}
|
|
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.
|
|
if (!a)
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
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;
|
|
a[i] = v;
|
|
NS_ADDREF(a[i]); // Addref for array reference
|
|
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)
|
|
NS_RELEASE(v);
|
|
}
|
|
delete[] a;
|
|
return rc;
|
|
}
|
|
else {
|
|
return aResult->SetAsArray(aType,aIID,aDimensionSizes[0],aArray);
|
|
}
|
|
}
|
|
|
|
// Incomplete -- becomes very complex due to variant arrays
|
|
NS_IMETHODIMP
|
|
nsArrayEncoder::Decode(nsISOAPEncoding * aEncoding,
|
|
nsIDOMElement * aSource,
|
|
nsISchemaType * aSchemaType,
|
|
nsISOAPAttachments * aAttachments,
|
|
nsIVariant ** _retval)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aEncoding);
|
|
NS_ENSURE_ARG_POINTER(aSource);
|
|
NS_ENSURE_ARG_POINTER(_retval);
|
|
*_retval = nsnull;
|
|
nsAutoString ns;
|
|
nsAutoString name;
|
|
nsCOMPtr < nsISchemaType > schemaArrayType;
|
|
nsAutoString value;
|
|
PRUint32 dimensionCount = 0; // Number of dimensions
|
|
PRInt32 dimensionSizes[MAX_ARRAY_DIMENSIONS];
|
|
PRInt32 size = -1;
|
|
nsresult rc;
|
|
PRUint32 i;
|
|
if (aSchemaType) {
|
|
PRUint16 type;
|
|
nsresult rc = aSchemaType->GetSchemaType(&type);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
if (type == nsISchemaType::SCHEMA_TYPE_COMPLEX) {
|
|
nsCOMPtr<nsISchemaComplexType> ct = do_QueryInterface(aSchemaType);
|
|
nsresult rc = ct->GetArrayDimension(&dimensionCount);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
rc = ct->GetArrayType(getter_AddRefs(schemaArrayType));
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
}
|
|
}
|
|
if (nsSOAPUtils::GetAttribute(aEncoding, aSource, nsSOAPUtils::kSOAPEncURI,
|
|
kSOAPArrayTypeAttribute, value)) {
|
|
nsAutoString dst;
|
|
PRUint32 n = DecodeArrayDimensions(value, dimensionSizes, dst);
|
|
if (n > 0) {
|
|
if (dimensionCount == n
|
|
|| dimensionCount == 0) {
|
|
dimensionCount = n;
|
|
}
|
|
else {
|
|
return SOAP_EXCEPTION(NS_ERROR_ILLEGAL_VALUE,"SOAP_WRONG_ARRAY_SIZE","Array declares different number of dimensions from what schema declared.");
|
|
// We cannot get conflicting information from schema and content.
|
|
}
|
|
}
|
|
value.Assign(dst);
|
|
|
|
if (dimensionCount > 0) {
|
|
PRInt64 tot = 1; // Collect in 64 bits, just to make sure it fits
|
|
for (i = 0; i < dimensionCount; i++) {
|
|
PRInt32 next = dimensionSizes[i];
|
|
if (next == -1) {
|
|
tot = -1;
|
|
break;
|
|
}
|
|
tot = tot * next;
|
|
if (tot > 0x7fffffff) {
|
|
return SOAP_EXCEPTION(NS_ERROR_ILLEGAL_VALUE,"SOAP_ARRAY_TOO_BIG","When decoding an object as an array, the total count of items exceeded maximum.");
|
|
}
|
|
}
|
|
size = (PRInt32)tot;
|
|
}
|
|
else {
|
|
return SOAP_EXCEPTION(NS_ERROR_ILLEGAL_VALUE,"SOAP_ARRAY_UNDECLARED","Array type did not end with proper array dimensions.");
|
|
// A dimension count must be part of the arrayType
|
|
}
|
|
|
|
// The array type is either array if ']' or other specific type.
|
|
nsCOMPtr < nsISchemaCollection > collection;
|
|
rc = aEncoding->GetSchemaCollection(getter_AddRefs(collection));
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
if (value.Last() ==']') {
|
|
ns.Assign(nsSOAPUtils::kSOAPEncURI);
|
|
name.Assign(kArraySOAPType);
|
|
}
|
|
else {
|
|
rc = nsSOAPUtils::GetNamespaceURI(aEncoding, aSource, value, ns);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
rc = nsSOAPUtils::GetLocalName(value, name);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
}
|
|
nsCOMPtr<nsISchemaType> subtype;
|
|
rc = collection->GetType(name, ns, getter_AddRefs(subtype));
|
|
// if (NS_FAILED(rc)) return rc;
|
|
if (!subtype)
|
|
subtype = schemaArrayType;
|
|
|
|
if (subtype) { // Loop up the hierarchy, to ensure suitability of subtype
|
|
if (schemaArrayType) {
|
|
nsCOMPtr < nsISchemaType > lookupType = subtype;
|
|
do {
|
|
if (lookupType == schemaArrayType) { // Tick off the located super classes
|
|
schemaArrayType = nsnull;
|
|
break;
|
|
}
|
|
nsCOMPtr<nsISchemaType> supertype;
|
|
rc = GetSupertype(aEncoding, lookupType, getter_AddRefs(supertype));
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
lookupType = supertype;
|
|
} while (lookupType);
|
|
}
|
|
if (schemaArrayType) // If the proper subclass relationship didn't exist, then error return.
|
|
return SOAP_EXCEPTION(NS_ERROR_ILLEGAL_VALUE,"SOAP_ARRAY_TYPE","The type of the array must be a subclass of the declared type.");
|
|
schemaArrayType = subtype; // If they did, then we now have a new, better type.
|
|
}
|
|
}
|
|
PRUint32 offset; // Computing offset trickier, because size may be unspecified.
|
|
if (nsSOAPUtils::GetAttribute(aEncoding, aSource, nsSOAPUtils::kSOAPEncURI,
|
|
kSOAPArrayOffsetAttribute, value)) {
|
|
PRInt32 pos[MAX_ARRAY_DIMENSIONS];
|
|
nsAutoString leftover;
|
|
offset = DecodeArrayDimensions(value, pos, leftover);
|
|
if (dimensionCount == 0)
|
|
dimensionCount = offset;
|
|
if (offset == 0 // We have to understand this or report an error
|
|
|| offset != dimensionCount // But the offset does not need to be understood
|
|
|| !leftover.IsEmpty())
|
|
return SOAP_EXCEPTION(NS_ERROR_ILLEGAL_VALUE,"SOAP_ARRAY_OFFSET","Illegal value given for array offset");
|
|
PRInt32 old0 = dimensionSizes[0];
|
|
if (dimensionSizes[0] == -1) { // It is OK to have a offset where dimension 0 is unspecified
|
|
dimensionSizes[0] = 2147483647;
|
|
}
|
|
offset = 0;
|
|
for (i = 0;;) {
|
|
PRInt64 next = pos[i];
|
|
if (next == -1
|
|
|| next >= dimensionSizes[i]) {
|
|
rc = NS_ERROR_ILLEGAL_VALUE;
|
|
break;
|
|
}
|
|
next = (offset + next);
|
|
if (next > 2147483647) {
|
|
rc = NS_ERROR_ILLEGAL_VALUE;
|
|
break;
|
|
}
|
|
offset = (PRInt32)next;
|
|
if (++i < dimensionCount) {
|
|
next = offset * dimensionSizes[i];
|
|
if (next > 2147483647) {
|
|
rc = NS_ERROR_ILLEGAL_VALUE;
|
|
break;
|
|
}
|
|
offset = (PRInt32)next;
|
|
}
|
|
else {
|
|
rc = NS_OK;
|
|
break;
|
|
}
|
|
}
|
|
if (NS_FAILED(rc))
|
|
return SOAP_EXCEPTION(NS_ERROR_ILLEGAL_VALUE,"SOAP_ARRAY_OFFSET","Illegal value given for array offset");
|
|
dimensionSizes[0] = old0;
|
|
}
|
|
else {
|
|
offset = 0;
|
|
}
|
|
if (size == -1) { // If no known size, we have to go through and pre-count.
|
|
nsCOMPtr<nsIDOMElement> child;
|
|
nsSOAPUtils::GetFirstChildElement(aSource, getter_AddRefs(child));
|
|
PRInt32 pp[MAX_ARRAY_DIMENSIONS];
|
|
if (dimensionCount != 0) {
|
|
for (i = dimensionCount; i-- != 0;) {
|
|
pp[i] = 0;
|
|
}
|
|
}
|
|
size = 0;
|
|
PRInt32 next = offset;
|
|
while (child) {
|
|
nsAutoString pos;
|
|
if (nsSOAPUtils::GetAttribute(aEncoding, aSource, nsSOAPUtils::kSOAPEncURI,
|
|
kSOAPArrayPositionAttribute, pos)) {
|
|
nsAutoString leftover;
|
|
PRInt32 inc[MAX_ARRAY_DIMENSIONS];
|
|
i = DecodeArrayDimensions(pos, inc, leftover);
|
|
if (i == 0 // We have to understand this or report an error
|
|
|| !leftover.IsEmpty()
|
|
|| (dimensionCount !=0
|
|
&& dimensionCount != i))
|
|
return SOAP_EXCEPTION(NS_ERROR_ILLEGAL_VALUE,"SOAP_ARRAY_POSITION","Illegal value given for array element position");
|
|
if (dimensionCount == 0) {
|
|
dimensionCount = i; // If we never had dimension count before, we do now.
|
|
for (i = dimensionCount; i-- != 0;) {
|
|
pp[i] = 0;
|
|
}
|
|
}
|
|
for (i = 0; i < dimensionCount; i++) {
|
|
PRInt32 n = inc[i];
|
|
if (n == -1) { // Positions must be concrete
|
|
return SOAP_EXCEPTION(NS_ERROR_ILLEGAL_VALUE,"SOAP_ARRAY_POSITION","Illegal value given for array element position");
|
|
}
|
|
if (n >= pp[i])
|
|
pp[i] = n + 1;
|
|
}
|
|
}
|
|
else {
|
|
next++; // Keep tabs on how many unnumbered items there are
|
|
}
|
|
|
|
nsCOMPtr<nsIDOMElement> nextchild;
|
|
nsSOAPUtils::GetNextSiblingElement(child, getter_AddRefs(nextchild));
|
|
child = nextchild;
|
|
}
|
|
if (dimensionCount == 0) { // If unknown or 1 dimension, unpositioned entries can help
|
|
dimensionCount = 1;
|
|
pp[0] = next;
|
|
}
|
|
else if (dimensionCount == 1
|
|
&& next > pp[0]) {
|
|
pp[0] = next;
|
|
}
|
|
PRInt64 tot = 1; // Collect in 64 bits, just to make sure it fits
|
|
for (i = 0; i < dimensionCount; i++) {
|
|
PRInt32 next = dimensionSizes[i];
|
|
if (next == -1) { // Only derive those with no other declaration
|
|
dimensionSizes[i] = next = pp[i];
|
|
}
|
|
tot = tot * next;
|
|
if (tot > 0x7fffffff) {
|
|
return SOAP_EXCEPTION(NS_ERROR_ILLEGAL_VALUE,"SOAP_ARRAY_TOO_BIG","When decoding an object as an array, the total count of items exceeded maximum.");
|
|
}
|
|
}
|
|
size = (PRInt32)tot; // At last, we know the dimensions of the array.
|
|
}
|
|
|
|
// After considerable work, we may have a schema type and a size.
|
|
|
|
nsCOMPtr<nsIWritableVariant> result = do_CreateInstance(NS_VARIANT_CONTRACTID, &rc);
|
|
PRInt32 si;
|
|
|
|
#define DECODE_ARRAY(XPType, VTYPE, iid, Convert, Free) \
|
|
XPType* a = new XPType[size];\
|
|
for (si = 0; si < size; si++) a[si] = 0;\
|
|
nsCOMPtr<nsIDOMElement> child;\
|
|
nsSOAPUtils::GetFirstChildElement(aSource, getter_AddRefs(child));\
|
|
PRUint32 next = offset;\
|
|
while (child) {\
|
|
nsAutoString pos;\
|
|
PRInt32 p;\
|
|
if (nsSOAPUtils::GetAttribute(aEncoding, aSource, nsSOAPUtils::kSOAPEncURI,\
|
|
kSOAPArrayPositionAttribute, pos)) {\
|
|
PRInt32 p = DecodeArrayPosition(pos, dimensionCount, dimensionSizes);\
|
|
if (p == -1) {\
|
|
rc = NS_ERROR_ILLEGAL_VALUE;\
|
|
break;\
|
|
}\
|
|
}\
|
|
else {\
|
|
p = next++;\
|
|
}\
|
|
if (p >= size\
|
|
|| a[p]) {\
|
|
rc = NS_ERROR_ILLEGAL_VALUE;\
|
|
break;\
|
|
}\
|
|
nsCOMPtr<nsIVariant> v;\
|
|
\
|
|
rc = aEncoding->Decode(child, schemaArrayType, aAttachments, getter_AddRefs(v));\
|
|
if (NS_FAILED(rc))\
|
|
break;\
|
|
Convert \
|
|
\
|
|
nsCOMPtr<nsIDOMElement> next;\
|
|
nsSOAPUtils::GetNextSiblingElement(child, getter_AddRefs(next));\
|
|
child = next;\
|
|
}\
|
|
if (!NS_FAILED(rc)) {\
|
|
rc = CreateArray(result, nsIDataType::VTYPE_##VTYPE,iid,dimensionCount,dimensionSizes,sizeof(a[0])*size,(PRUint8*)a);\
|
|
}\
|
|
Free\
|
|
delete[] a;\
|
|
|
|
#define DECODE_SIMPLE_ARRAY(XPType, VType, VTYPE) \
|
|
DECODE_ARRAY(XPType, VTYPE, nsnull, rc = v->GetAs##VType(a + p);if(NS_FAILED(rc))break;,do{}while(0);)
|
|
|
|
if (rc == NS_ERROR_ILLEGAL_VALUE)
|
|
return SOAP_EXCEPTION(NS_ERROR_ILLEGAL_VALUE,"SOAP_ARRAY_POSITIONS","Colliding array positions discovered.");
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
PRBool unhandled = PR_FALSE;
|
|
if (ns.Equals(nsSOAPUtils::kXSURI)) {
|
|
if (name.Equals(kStringSchemaType)) {
|
|
DECODE_ARRAY(PRUnichar*,WCHAR_STR,nsnull,rc = v->GetAsWString(a + p);if(NS_FAILED(rc))break;,
|
|
for (si = 0; si < size; si++) nsMemory::Free(a[si]););
|
|
} else if (name.Equals(kBooleanSchemaType)) {
|
|
DECODE_SIMPLE_ARRAY(PRBool,Bool,BOOL);
|
|
} else if (name.Equals(kFloatSchemaType)) {
|
|
DECODE_SIMPLE_ARRAY(float,Float,FLOAT);
|
|
} else if (name.Equals(kDoubleSchemaType)) {
|
|
DECODE_SIMPLE_ARRAY(double,Double,DOUBLE);
|
|
} else if (name.Equals(kLongSchemaType)) {
|
|
DECODE_SIMPLE_ARRAY(PRInt64,Int64,INT64);
|
|
} else if (name.Equals(kIntSchemaType)) {
|
|
DECODE_SIMPLE_ARRAY(PRInt32,Int32,INT32);
|
|
} else if (name.Equals(kShortSchemaType)) {
|
|
DECODE_SIMPLE_ARRAY(PRInt16,Int16,INT16);
|
|
} else if (name.Equals(kByteSchemaType)) {
|
|
DECODE_SIMPLE_ARRAY(PRUint8,Int8,INT8);
|
|
} else if (name.Equals(kUnsignedLongSchemaType)) {
|
|
DECODE_SIMPLE_ARRAY(PRUint64,Uint64,UINT64);
|
|
} else if (name.Equals(kUnsignedIntSchemaType)) {
|
|
DECODE_SIMPLE_ARRAY(PRUint32,Uint32,UINT32);
|
|
} else if (name.Equals(kUnsignedShortSchemaType)) {
|
|
DECODE_SIMPLE_ARRAY(PRUint16,Uint16,UINT16);
|
|
} else if (name.Equals(kUnsignedByteSchemaType)) {
|
|
DECODE_SIMPLE_ARRAY(PRUint8,Uint8,UINT8);
|
|
} else {
|
|
unhandled = PR_TRUE;
|
|
}
|
|
} else {
|
|
unhandled = PR_TRUE;
|
|
}
|
|
if (unhandled) { // Handle all the other cases
|
|
DECODE_ARRAY(nsIVariant*,INTERFACE,&NS_GET_IID(nsIVariant),a[p] = v;,
|
|
for (si = 0; si < size; si++) NS_RELEASE(a[si]););
|
|
}
|
|
if (NS_FAILED(rc))\
|
|
return rc;
|
|
*_retval = result;
|
|
NS_ADDREF(*_retval);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsStringEncoder::Decode(nsISOAPEncoding * aEncoding,
|
|
nsIDOMElement * aSource,
|
|
nsISchemaType * aSchemaType,
|
|
nsISOAPAttachments * aAttachments,
|
|
nsIVariant ** _retval)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aEncoding);
|
|
NS_ENSURE_ARG_POINTER(aSource);
|
|
NS_ENSURE_ARG_POINTER(_retval);
|
|
*_retval = nsnull;
|
|
nsAutoString value;
|
|
nsresult rc = nsSOAPUtils::GetElementTextContent(aSource, value);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
nsCOMPtr < nsIWritableVariant > p =
|
|
do_CreateInstance(NS_VARIANT_CONTRACTID, &rc);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
rc = p->SetAsAString(value);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
*_retval = p;
|
|
NS_ADDREF(*_retval);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsBooleanEncoder::Decode(nsISOAPEncoding * aEncoding,
|
|
nsIDOMElement * aSource,
|
|
nsISchemaType * aSchemaType,
|
|
nsISOAPAttachments * aAttachments,
|
|
nsIVariant ** _retval)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aEncoding);
|
|
NS_ENSURE_ARG_POINTER(aSource);
|
|
NS_ENSURE_ARG_POINTER(_retval);
|
|
*_retval = nsnull;
|
|
nsAutoString value;
|
|
nsresult rc = nsSOAPUtils::GetElementTextContent(aSource, value);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
bool b;
|
|
if (value.Equals(nsSOAPUtils::kTrue)
|
|
|| value.Equals(nsSOAPUtils::kTrueA)) {
|
|
b = PR_TRUE;
|
|
} else if (value.Equals(nsSOAPUtils::kFalse)
|
|
|| value.Equals(nsSOAPUtils::kFalseA)) {
|
|
b = PR_FALSE;
|
|
} else
|
|
return SOAP_EXCEPTION(NS_ERROR_ILLEGAL_VALUE,"SOAP_ILLEGAL_BOOLEAN","Illegal value discovered for boolean");
|
|
|
|
nsCOMPtr < nsIWritableVariant > p =
|
|
do_CreateInstance(NS_VARIANT_CONTRACTID,&rc);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
p->SetAsBool(b);
|
|
*_retval = p;
|
|
NS_ADDREF(*_retval);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsDoubleEncoder::Decode(nsISOAPEncoding * aEncoding,
|
|
nsIDOMElement * aSource,
|
|
nsISchemaType * aSchemaType,
|
|
nsISOAPAttachments * aAttachments,
|
|
nsIVariant ** _retval)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aEncoding);
|
|
NS_ENSURE_ARG_POINTER(aSource);
|
|
NS_ENSURE_ARG_POINTER(_retval);
|
|
*_retval = nsnull;
|
|
nsAutoString value;
|
|
nsresult rc = nsSOAPUtils::GetElementTextContent(aSource, value);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
double f;
|
|
PRUint32 n;
|
|
PRInt32 r = PR_sscanf(NS_ConvertUCS2toUTF8(value).get(), " %lf %n", &f, &n);
|
|
if (r == 0 || n < value.Length())
|
|
return SOAP_EXCEPTION(NS_ERROR_ILLEGAL_VALUE,"SOAP_ILLEGAL_DOUBLE","Illegal value discovered for double");
|
|
|
|
nsCOMPtr < nsIWritableVariant > p =
|
|
do_CreateInstance(NS_VARIANT_CONTRACTID,&rc);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
p->SetAsDouble(f);
|
|
*_retval = p;
|
|
NS_ADDREF(*_retval);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsFloatEncoder::Decode(nsISOAPEncoding * aEncoding,
|
|
nsIDOMElement * aSource,
|
|
nsISchemaType * aSchemaType,
|
|
nsISOAPAttachments * aAttachments,
|
|
nsIVariant ** _retval)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aEncoding);
|
|
NS_ENSURE_ARG_POINTER(aSource);
|
|
NS_ENSURE_ARG_POINTER(_retval);
|
|
*_retval = nsnull;
|
|
nsAutoString value;
|
|
nsresult rc = nsSOAPUtils::GetElementTextContent(aSource, value);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
float f;
|
|
PRUint32 n;
|
|
PRInt32 r = PR_sscanf(NS_ConvertUCS2toUTF8(value).get(), " %f %n", &f, &n);
|
|
if (r == 0 || n < value.Length())
|
|
return SOAP_EXCEPTION(NS_ERROR_ILLEGAL_VALUE,"SOAP_ILLEGAL_FLOAT","Illegal value discovered for float");
|
|
|
|
nsCOMPtr < nsIWritableVariant > p =
|
|
do_CreateInstance(NS_VARIANT_CONTRACTID,&rc);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
p->SetAsFloat(f);
|
|
*_retval = p;
|
|
NS_ADDREF(*_retval);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsLongEncoder::Decode(nsISOAPEncoding * aEncoding,
|
|
nsIDOMElement * aSource,
|
|
nsISchemaType * aSchemaType,
|
|
nsISOAPAttachments * aAttachments,
|
|
nsIVariant ** _retval)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aEncoding);
|
|
NS_ENSURE_ARG_POINTER(aSource);
|
|
NS_ENSURE_ARG_POINTER(_retval);
|
|
*_retval = nsnull;
|
|
nsAutoString value;
|
|
nsresult rc = nsSOAPUtils::GetElementTextContent(aSource, value);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
PRInt64 f;
|
|
PRUint32 n;
|
|
PRInt32 r = PR_sscanf(NS_ConvertUCS2toUTF8(value).get(), " %lld %n", &f, &n);
|
|
if (r == 0 || n < value.Length())
|
|
return SOAP_EXCEPTION(NS_ERROR_ILLEGAL_VALUE,"SOAP_ILLEGAL_LONG","Illegal value discovered for long");
|
|
|
|
nsCOMPtr < nsIWritableVariant > p =
|
|
do_CreateInstance(NS_VARIANT_CONTRACTID,&rc);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
p->SetAsInt64(f);
|
|
*_retval = p;
|
|
NS_ADDREF(*_retval);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsIntEncoder::Decode(nsISOAPEncoding * aEncoding,
|
|
nsIDOMElement * aSource,
|
|
nsISchemaType * aSchemaType,
|
|
nsISOAPAttachments * aAttachments,
|
|
nsIVariant ** _retval)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aEncoding);
|
|
NS_ENSURE_ARG_POINTER(aSource);
|
|
NS_ENSURE_ARG_POINTER(_retval);
|
|
*_retval = nsnull;
|
|
nsAutoString value;
|
|
nsresult rc = nsSOAPUtils::GetElementTextContent(aSource, value);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
PRInt32 f;
|
|
PRUint32 n;
|
|
PRInt32 r = PR_sscanf(NS_ConvertUCS2toUTF8(value).get(), " %ld %n", &f, &n);
|
|
if (r == 0 || n < value.Length())
|
|
return SOAP_EXCEPTION(NS_ERROR_ILLEGAL_VALUE,"SOAP_ILLEGAL_INT","Illegal value discovered for int");
|
|
|
|
nsCOMPtr < nsIWritableVariant > p =
|
|
do_CreateInstance(NS_VARIANT_CONTRACTID,&rc);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
p->SetAsInt32(f);
|
|
*_retval = p;
|
|
NS_ADDREF(*_retval);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsShortEncoder::Decode(nsISOAPEncoding * aEncoding,
|
|
nsIDOMElement * aSource,
|
|
nsISchemaType * aSchemaType,
|
|
nsISOAPAttachments * aAttachments,
|
|
nsIVariant ** _retval)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aEncoding);
|
|
NS_ENSURE_ARG_POINTER(aSource);
|
|
NS_ENSURE_ARG_POINTER(_retval);
|
|
*_retval = nsnull;
|
|
nsAutoString value;
|
|
nsresult rc = nsSOAPUtils::GetElementTextContent(aSource, value);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
PRInt16 f;
|
|
PRUint32 n;
|
|
PRInt32 r = PR_sscanf(NS_ConvertUCS2toUTF8(value).get(), " %hd %n", &f, &n);
|
|
if (r == 0 || n < value.Length())
|
|
return SOAP_EXCEPTION(NS_ERROR_ILLEGAL_VALUE,"SOAP_ILLEGAL_SHORT","Illegal value discovered for short");
|
|
|
|
nsCOMPtr < nsIWritableVariant > p =
|
|
do_CreateInstance(NS_VARIANT_CONTRACTID,&rc);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
p->SetAsInt16(f);
|
|
*_retval = p;
|
|
NS_ADDREF(*_retval);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsByteEncoder::Decode(nsISOAPEncoding * aEncoding,
|
|
nsIDOMElement * aSource,
|
|
nsISchemaType * aSchemaType,
|
|
nsISOAPAttachments * aAttachments,
|
|
nsIVariant ** _retval)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aEncoding);
|
|
NS_ENSURE_ARG_POINTER(aSource);
|
|
NS_ENSURE_ARG_POINTER(_retval);
|
|
*_retval = nsnull;
|
|
nsAutoString value;
|
|
nsresult rc = nsSOAPUtils::GetElementTextContent(aSource, value);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
PRInt16 f;
|
|
PRUint32 n;
|
|
PRInt32 r = PR_sscanf(NS_ConvertUCS2toUTF8(value).get(), " %hd %n", &f, &n);
|
|
if (r == 0 || n < value.Length() || f < -128 || f > 127)
|
|
return SOAP_EXCEPTION(NS_ERROR_ILLEGAL_VALUE,"SOAP_ILLEGAL_BYTE","Illegal value discovered for byte");
|
|
|
|
nsCOMPtr < nsIWritableVariant > p =
|
|
do_CreateInstance(NS_VARIANT_CONTRACTID,&rc);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
p->SetAsInt8((PRUint8) f);
|
|
*_retval = p;
|
|
NS_ADDREF(*_retval);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsUnsignedLongEncoder::Decode(nsISOAPEncoding * aEncoding,
|
|
nsIDOMElement * aSource,
|
|
nsISchemaType * aSchemaType,
|
|
nsISOAPAttachments * aAttachments,
|
|
nsIVariant ** _retval)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aEncoding);
|
|
NS_ENSURE_ARG_POINTER(aSource);
|
|
NS_ENSURE_ARG_POINTER(_retval);
|
|
*_retval = nsnull;
|
|
nsAutoString value;
|
|
nsresult rc = nsSOAPUtils::GetElementTextContent(aSource, value);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
PRUint64 f;
|
|
PRUint32 n;
|
|
PRInt32 r = PR_sscanf(NS_ConvertUCS2toUTF8(value).get(), " %llu %n", &f, &n);
|
|
if (r == 0 || n < value.Length())
|
|
return SOAP_EXCEPTION(NS_ERROR_ILLEGAL_VALUE,"SOAP_ILLEGAL_ULONG","Illegal value discovered for unsigned long");
|
|
|
|
nsCOMPtr < nsIWritableVariant > p =
|
|
do_CreateInstance(NS_VARIANT_CONTRACTID,&rc);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
p->SetAsUint64(f);
|
|
*_retval = p;
|
|
NS_ADDREF(*_retval);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsUnsignedIntEncoder::Decode(nsISOAPEncoding * aEncoding,
|
|
nsIDOMElement * aSource,
|
|
nsISchemaType * aSchemaType,
|
|
nsISOAPAttachments * aAttachments,
|
|
nsIVariant ** _retval)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aEncoding);
|
|
NS_ENSURE_ARG_POINTER(aSource);
|
|
NS_ENSURE_ARG_POINTER(_retval);
|
|
*_retval = nsnull;
|
|
nsAutoString value;
|
|
nsresult rc = nsSOAPUtils::GetElementTextContent(aSource, value);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
PRUint32 f;
|
|
PRUint32 n;
|
|
PRInt32 r = PR_sscanf(NS_ConvertUCS2toUTF8(value).get(), " %lu %n", &f, &n);
|
|
if (r == 0 || n < value.Length())
|
|
return SOAP_EXCEPTION(NS_ERROR_ILLEGAL_VALUE,"SOAP_ILLEGAL_UINT","Illegal value discovered for unsigned int");
|
|
|
|
nsCOMPtr < nsIWritableVariant > p =
|
|
do_CreateInstance(NS_VARIANT_CONTRACTID,&rc);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
p->SetAsUint32(f);
|
|
*_retval = p;
|
|
NS_ADDREF(*_retval);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsUnsignedShortEncoder::Decode(nsISOAPEncoding * aEncoding,
|
|
nsIDOMElement * aSource,
|
|
nsISchemaType * aSchemaType,
|
|
nsISOAPAttachments * aAttachments,
|
|
nsIVariant ** _retval)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aEncoding);
|
|
NS_ENSURE_ARG_POINTER(aSource);
|
|
NS_ENSURE_ARG_POINTER(_retval);
|
|
*_retval = nsnull;
|
|
nsAutoString value;
|
|
nsresult rc = nsSOAPUtils::GetElementTextContent(aSource, value);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
PRUint16 f;
|
|
PRUint32 n;
|
|
PRInt32 r = PR_sscanf(NS_ConvertUCS2toUTF8(value).get(), " %hu %n", &f, &n);
|
|
if (r == 0 || n < value.Length())
|
|
return SOAP_EXCEPTION(NS_ERROR_ILLEGAL_VALUE,"SOAP_ILLEGAL_USHORT","Illegal value discovered for unsigned short");
|
|
|
|
nsCOMPtr < nsIWritableVariant > p =
|
|
do_CreateInstance(NS_VARIANT_CONTRACTID,&rc);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
p->SetAsUint16(f);
|
|
*_retval = p;
|
|
NS_ADDREF(*_retval);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsUnsignedByteEncoder::Decode(nsISOAPEncoding * aEncoding,
|
|
nsIDOMElement * aSource,
|
|
nsISchemaType * aSchemaType,
|
|
nsISOAPAttachments * aAttachments,
|
|
nsIVariant ** _retval)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aEncoding);
|
|
NS_ENSURE_ARG_POINTER(aSource);
|
|
NS_ENSURE_ARG_POINTER(_retval);
|
|
*_retval = nsnull;
|
|
nsAutoString value;
|
|
nsresult rc = nsSOAPUtils::GetElementTextContent(aSource, value);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
PRUint16 f;
|
|
PRUint32 n;
|
|
PRInt32 r = PR_sscanf(NS_ConvertUCS2toUTF8(value).get(), " %hu %n", &f, &n);
|
|
if (r == 0 || n < value.Length() || f > 255)
|
|
return SOAP_EXCEPTION(NS_ERROR_ILLEGAL_VALUE,"SOAP_ILLEGAL_UBYTE","Illegal value discovered for unsigned byte");
|
|
|
|
nsCOMPtr < nsIWritableVariant > p =
|
|
do_CreateInstance(NS_VARIANT_CONTRACTID,&rc);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
p->SetAsUint8((PRUint8) f);
|
|
*_retval = p;
|
|
NS_ADDREF(*_retval);
|
|
return NS_OK;
|
|
}
|