3395 lines
119 KiB
C++
3395 lines
119 KiB
C++
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* ***** BEGIN LICENSE BLOCK *****
|
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
*
|
|
* The contents of this file are subject to the Mozilla 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/MPL/
|
|
*
|
|
* 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 MPL, 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 MPL, 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 "nsXPCOM.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 "plbase64.h"
|
|
#include "prmem.h"
|
|
#include "nsReadableUtils.h"
|
|
#include "nsIDOMNamedNodeMap.h"
|
|
#include "nsIDOMAttr.h"
|
|
#include "nsPrintfCString.h"
|
|
#include "nsISOAPPropertyBagMutator.h"
|
|
#include "nsIPropertyBag.h"
|
|
#include "nsSupportsArray.h"
|
|
|
|
|
|
#define MAX_ARRAY_DIMENSIONS 100
|
|
|
|
//
|
|
// Macros to declare and implement the default encoder classes
|
|
//
|
|
|
|
#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) {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)
|
|
DECLARE_ENCODER(Base64Binary)
|
|
|
|
/**
|
|
* 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, gSOAPStrings->k##name##type##Type, encodingKey);\
|
|
SetEncoder(encodingKey, handler); \
|
|
SetDecoder(encodingKey, handler); \
|
|
}
|
|
|
|
#define REGISTER_SCHEMA_ENCODER(name) REGISTER_ENCODER(name,Schema,gSOAPStrings->kXSURI)
|
|
#define REGISTER_SOAP_ENCODER(name) REGISTER_ENCODER(name,SOAP,gSOAPStrings->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)\
|
|
REGISTER_SCHEMA_ENCODER(Base64Binary)
|
|
|
|
//
|
|
// Default SOAP Encodings
|
|
//
|
|
|
|
NS_IMPL_ADDREF(nsDefaultSOAPEncoding_1_1)
|
|
NS_IMPL_RELEASE(nsDefaultSOAPEncoding_1_1)
|
|
|
|
nsDefaultSOAPEncoding_1_1::nsDefaultSOAPEncoding_1_1()
|
|
: nsSOAPEncoding(gSOAPStrings->kSOAPEncURI11, nsnull, nsnull)
|
|
{
|
|
PRUint16 version = nsISOAPMessage::VERSION_1_1;
|
|
PRBool result;
|
|
MapSchemaURI(gSOAPStrings->kXSURI1999,gSOAPStrings->kXSURI,PR_TRUE,&result);
|
|
MapSchemaURI(gSOAPStrings->kXSIURI1999,gSOAPStrings->kXSIURI,PR_TRUE,&result);
|
|
MapSchemaURI(gSOAPStrings->kSOAPEncURI11,gSOAPStrings->kSOAPEncURI,PR_TRUE,&result);
|
|
REGISTER_ENCODERS
|
|
}
|
|
|
|
NS_IMPL_ADDREF(nsDefaultSOAPEncoding_1_2)
|
|
NS_IMPL_RELEASE(nsDefaultSOAPEncoding_1_2)
|
|
|
|
nsDefaultSOAPEncoding_1_2::nsDefaultSOAPEncoding_1_2()
|
|
: nsSOAPEncoding(gSOAPStrings->kSOAPEncURI, nsnull, nsnull)
|
|
{
|
|
PRUint16 version = nsISOAPMessage::VERSION_1_2;
|
|
PRBool result;
|
|
MapSchemaURI(gSOAPStrings->kXSURI1999,gSOAPStrings->kXSURI,PR_FALSE,&result);
|
|
MapSchemaURI(gSOAPStrings->kXSIURI1999,gSOAPStrings->kXSIURI,PR_FALSE,&result);
|
|
MapSchemaURI(gSOAPStrings->kSOAPEncURI11,gSOAPStrings->kSOAPEncURI,PR_FALSE,&result);
|
|
REGISTER_ENCODERS
|
|
}
|
|
|
|
//
|
|
// Default Encoders -- static helper functions intermixed
|
|
//
|
|
|
|
// 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 = gSOAPStrings->kAnyTypeSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_NORMALIZED_STRING:
|
|
name = gSOAPStrings->kStringSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_TOKEN:
|
|
name = gSOAPStrings->kNormalizedStringSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_BYTE:
|
|
name = gSOAPStrings->kShortSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_UNSIGNEDBYTE:
|
|
name = gSOAPStrings->kUnsignedShortSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_BASE64BINARY:
|
|
// name = kAnySimpleTypeSchemaType;
|
|
name = gSOAPStrings->kAnyTypeSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_HEXBINARY:
|
|
// name = kAnySimpleTypeSchemaType;
|
|
name = gSOAPStrings->kAnyTypeSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_INTEGER:
|
|
name = gSOAPStrings->kDecimalSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_POSITIVEINTEGER:
|
|
name = gSOAPStrings->kNonNegativeIntegerSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_NEGATIVEINTEGER:
|
|
name = gSOAPStrings->kNonPositiveIntegerSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_NONNEGATIVEINTEGER:
|
|
name = gSOAPStrings->kIntegerSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_NONPOSITIVEINTEGER:
|
|
name = gSOAPStrings->kIntegerSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_INT:
|
|
name = gSOAPStrings->kLongSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_UNSIGNEDINT:
|
|
name = gSOAPStrings->kUnsignedLongSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_LONG:
|
|
name = gSOAPStrings->kIntegerSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_UNSIGNEDLONG:
|
|
name = gSOAPStrings->kNonNegativeIntegerSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_SHORT:
|
|
name = gSOAPStrings->kIntSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_UNSIGNEDSHORT:
|
|
name = gSOAPStrings->kUnsignedIntSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_DECIMAL:
|
|
// name = kAnySimpleTypeSchemaType;
|
|
name = gSOAPStrings->kAnyTypeSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_FLOAT:
|
|
// name = kAnySimpleTypeSchemaType;
|
|
name = gSOAPStrings->kAnyTypeSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_DOUBLE:
|
|
// name = kAnySimpleTypeSchemaType;
|
|
name = gSOAPStrings->kAnyTypeSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_BOOLEAN:
|
|
// name = kAnySimpleTypeSchemaType;
|
|
name = gSOAPStrings->kAnyTypeSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_TIME:
|
|
// name = kAnySimpleTypeSchemaType;
|
|
name = gSOAPStrings->kAnyTypeSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_DATETIME:
|
|
// name = kAnySimpleTypeSchemaType;
|
|
name = gSOAPStrings->kAnyTypeSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_DURATION:
|
|
// name = kAnySimpleTypeSchemaType;
|
|
name = gSOAPStrings->kAnyTypeSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_DATE:
|
|
// name = kAnySimpleTypeSchemaType;
|
|
name = gSOAPStrings->kAnyTypeSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_GMONTH:
|
|
// name = kAnySimpleTypeSchemaType;
|
|
name = gSOAPStrings->kAnyTypeSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_GYEAR:
|
|
// name = kAnySimpleTypeSchemaType;
|
|
name = gSOAPStrings->kAnyTypeSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_GYEARMONTH:
|
|
// name = kAnySimpleTypeSchemaType;
|
|
name = gSOAPStrings->kAnyTypeSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_GDAY:
|
|
// name = kAnySimpleTypeSchemaType;
|
|
name = gSOAPStrings->kAnyTypeSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_GMONTHDAY:
|
|
// name = kAnySimpleTypeSchemaType;
|
|
name = gSOAPStrings->kAnyTypeSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_NAME:
|
|
// name = kAnySimpleTypeSchemaType;
|
|
name = gSOAPStrings->kAnyTypeSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_QNAME:
|
|
// name = kAnySimpleTypeSchemaType;
|
|
name = gSOAPStrings->kAnyTypeSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_NCNAME:
|
|
name = gSOAPStrings->kNameSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_ANYURI:
|
|
// name = kAnySimpleTypeSchemaType;
|
|
name = gSOAPStrings->kAnyTypeSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_LANGUAGE:
|
|
name = gSOAPStrings->kTokenSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_ID:
|
|
name = gSOAPStrings->kNCNameSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_IDREF:
|
|
name = gSOAPStrings->kNCNameSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_IDREFS:
|
|
name = gSOAPStrings->kNormalizedStringSchemaType; // Really a list...
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_ENTITY:
|
|
name = gSOAPStrings->kNCNameSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_ENTITIES:
|
|
name = gSOAPStrings->kNormalizedStringSchemaType; // Really a list...
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_NOTATION:
|
|
// name = kAnySimpleTypeSchemaType;
|
|
name = gSOAPStrings->kAnyTypeSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_NMTOKEN:
|
|
name = gSOAPStrings->kTokenSchemaType;
|
|
break;
|
|
case nsISchemaBuiltinType::BUILTIN_TYPE_NMTOKENS:
|
|
name = gSOAPStrings->kNormalizedStringSchemaType; // Really a list...
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
if (!base) {
|
|
if (name.IsEmpty()) {
|
|
switch (typevalue) {
|
|
case nsISchemaType::SCHEMA_TYPE_COMPLEX:
|
|
name = gSOAPStrings->kAnyTypeSchemaType;
|
|
break;
|
|
default:
|
|
// name = kAnySimpleTypeSchemaType;
|
|
name = gSOAPStrings->kAnyTypeSchemaType;
|
|
}
|
|
}
|
|
nsCOMPtr<nsISchemaCollection> collection;
|
|
rc = aEncoding->GetSchemaCollection(getter_AddRefs(collection));
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
rc = collection->GetType(name,
|
|
gSOAPStrings->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.IsEmpty() &&
|
|
!(typeName.Equals(gSOAPStrings->kAnyTypeSchemaType) &&
|
|
typeNS.Equals(gSOAPStrings->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.
|
|
// The idea here seems to be to walk up the schema hierarchy to
|
|
// find the base type and use the name of that as the element name.
|
|
ns = gSOAPStrings->kSOAPEncURI;
|
|
nsAutoString currentURI = ns;
|
|
nsCOMPtr<nsISchemaType> currentType = aSchemaType;
|
|
while (currentType
|
|
&& !(currentURI.Equals(gSOAPStrings->kXSURI)
|
|
|| currentURI.Equals(gSOAPStrings->kSOAPEncURI))) {
|
|
nsCOMPtr<nsISchemaType> supertype;
|
|
rc = GetSupertype(aEncoding, currentType, getter_AddRefs(supertype));
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
if (!currentType) {
|
|
break;
|
|
}
|
|
currentType = supertype;
|
|
rc = currentType->GetTargetNamespace(currentURI);
|
|
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 = gSOAPStrings->kAnyTypeSchemaType;
|
|
needType = PR_FALSE;
|
|
}
|
|
rc = aEncoding->GetExternalSchemaURI(gSOAPStrings->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(gSOAPStrings->kQualifiedSeparator);
|
|
type.Append(typeName);
|
|
rc = aEncoding->GetExternalSchemaURI(gSOAPStrings->kXSIURI, ns);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
rc = (element)->
|
|
SetAttributeNS(ns, gSOAPStrings->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(aDestination);
|
|
NS_ENSURE_ARG_POINTER(aReturnValue);
|
|
*aReturnValue = nsnull;
|
|
if (aSource == nsnull) {
|
|
nsAutoString ns;
|
|
nsCOMPtr<nsIDOMElement> cloneable;
|
|
nsresult rc = aEncoding->GetExternalSchemaURI(gSOAPStrings->kXSIURI, ns);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
nsAutoString name;
|
|
if (!aName.IsEmpty())
|
|
name.Assign(gSOAPStrings->kNull);
|
|
rc = EncodeSimpleValue(aEncoding, gSOAPStrings->kEmpty, gSOAPStrings->kEmpty,
|
|
name, nsnull, aDestination, aReturnValue);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
rc = (*aReturnValue)->SetAttributeNS(ns, gSOAPStrings->kNull, gSOAPStrings->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(gSOAPStrings->kXSURI,
|
|
gSOAPStrings->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 void
|
|
GetNativeType(PRUint16 aType, nsAString & aSchemaNamespaceURI, nsAString & aSchemaType)
|
|
{
|
|
aSchemaNamespaceURI.Assign(gSOAPStrings->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:
|
|
case nsIDataType::VTYPE_DOMSTRING:
|
|
case nsIDataType::VTYPE_CSTRING:
|
|
case nsIDataType::VTYPE_UTF8STRING:
|
|
aSchemaType.Assign(gSOAPStrings->kStringSchemaType);
|
|
break;
|
|
case nsIDataType::VTYPE_INT8:
|
|
aSchemaType.Assign(gSOAPStrings->kByteSchemaType);
|
|
break;
|
|
case nsIDataType::VTYPE_INT16:
|
|
aSchemaType.Assign(gSOAPStrings->kShortSchemaType);
|
|
break;
|
|
case nsIDataType::VTYPE_INT32:
|
|
aSchemaType.Assign(gSOAPStrings->kIntSchemaType);
|
|
break;
|
|
case nsIDataType::VTYPE_INT64:
|
|
aSchemaType.Assign(gSOAPStrings->kLongSchemaType);
|
|
break;
|
|
case nsIDataType::VTYPE_UINT8:
|
|
aSchemaType.Assign(gSOAPStrings->kUnsignedByteSchemaType);
|
|
break;
|
|
case nsIDataType::VTYPE_UINT16:
|
|
aSchemaType.Assign(gSOAPStrings->kUnsignedShortSchemaType);
|
|
break;
|
|
case nsIDataType::VTYPE_UINT32:
|
|
aSchemaType.Assign(gSOAPStrings->kUnsignedIntSchemaType);
|
|
break;
|
|
case nsIDataType::VTYPE_UINT64:
|
|
aSchemaType.Assign(gSOAPStrings->kUnsignedLongSchemaType);
|
|
break;
|
|
case nsIDataType::VTYPE_FLOAT:
|
|
aSchemaType.Assign(gSOAPStrings->kFloatSchemaType);
|
|
break;
|
|
case nsIDataType::VTYPE_DOUBLE:
|
|
aSchemaType.Assign(gSOAPStrings->kDoubleSchemaType);
|
|
break;
|
|
case nsIDataType::VTYPE_BOOL:
|
|
aSchemaType.Assign(gSOAPStrings->kBooleanSchemaType);
|
|
break;
|
|
case nsIDataType::VTYPE_ARRAY:
|
|
case nsIDataType::VTYPE_EMPTY_ARRAY:
|
|
aSchemaType.Assign(gSOAPStrings->kArraySOAPType);
|
|
aSchemaNamespaceURI.Assign(gSOAPStrings->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(gSOAPStrings->kStructSOAPType);
|
|
aSchemaNamespaceURI.Assign(gSOAPStrings->kSOAPEncURI);
|
|
break;
|
|
default:
|
|
aSchemaType.Assign(gSOAPStrings->kAnySimpleTypeSchemaType);
|
|
}
|
|
}
|
|
|
|
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(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_EMPTY_ARRAY:
|
|
case nsIDataType::VTYPE_INTERFACE_IS:
|
|
case nsIDataType::VTYPE_INTERFACE:
|
|
simple = PR_FALSE;
|
|
break;
|
|
}
|
|
}
|
|
if (simple) {
|
|
nativeSchemaType.Assign(gSOAPStrings->kAnySimpleTypeSchemaType);
|
|
nativeSchemaURI.Assign(gSOAPStrings->kXSURI);
|
|
}
|
|
else {
|
|
nativeSchemaType.Assign(gSOAPStrings->kStructSOAPType);
|
|
nativeSchemaURI.Assign(gSOAPStrings->kSOAPEncURI);
|
|
}
|
|
}
|
|
else {
|
|
GetNativeType(typevalue, nativeSchemaURI, nativeSchemaType);
|
|
}
|
|
|
|
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_SUCCEEDED(rc)) {
|
|
nsCOMPtr<nsIDOMElement> dummy;
|
|
rc = aEncoding->Encode(value, gSOAPStrings->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_SUCCEEDED(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;
|
|
rc = aPropertyBag->GetEnumerator(getter_AddRefs(e));
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
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,gSOAPStrings->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(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, gSOAPStrings->kEmpty,
|
|
gSOAPStrings->kSOAPEncURI,
|
|
gSOAPStrings->kStructSOAPType,
|
|
aSchemaType, aDestination,
|
|
aReturnValue);
|
|
}
|
|
else {
|
|
rc = EncodeSimpleValue(aEncoding, gSOAPStrings->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(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,
|
|
gSOAPStrings->kSOAPEncURI,
|
|
gSOAPStrings->kAnySimpleTypeSchemaType,
|
|
aSchemaType,
|
|
aDestination,
|
|
aReturnValue);
|
|
}
|
|
return EncodeSimpleValue(aEncoding,
|
|
value,
|
|
aNamespaceURI,
|
|
aName,
|
|
aSchemaType,
|
|
aDestination,
|
|
aReturnValue);
|
|
}
|
|
|
|
/**
|
|
* 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;
|
|
nsresult rc;
|
|
PRUint32 i;
|
|
rc = aSource->GetDataType(&type);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
if (type == nsIDataType::VTYPE_EMPTY
|
|
|| type == nsIDataType::VTYPE_VOID
|
|
|| type == nsIDataType::VTYPE_EMPTY_ARRAY) {
|
|
rc = NS_OK;
|
|
count = 0;
|
|
type = nsIDataType::VTYPE_EMPTY;
|
|
array = nsnull;
|
|
}
|
|
else {
|
|
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) {
|
|
nsresult rc = aSource->GetDataType(&type);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
if (type == nsIDataType::VTYPE_EMPTY
|
|
|| type == nsIDataType::VTYPE_VOID
|
|
|| type == nsIDataType::VTYPE_EMPTY_ARRAY) {
|
|
rc = NS_OK;
|
|
count = 0;
|
|
type = nsIDataType::VTYPE_EMPTY;
|
|
array = nsnull;
|
|
}
|
|
else {
|
|
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(gSOAPStrings->kXSIURI, ns);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
rc = EncodeSimpleValue(aEncoding, gSOAPStrings->kEmpty, gSOAPStrings->kEmpty,
|
|
gSOAPStrings->kNull, nsnull, aArray, getter_AddRefs(cloneable));
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
rc = cloneable->SetAttributeNS(ns, gSOAPStrings->kNull, gSOAPStrings->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,\
|
|
gSOAPStrings->kEmpty,\
|
|
gSOAPStrings->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],
|
|
gSOAPStrings->kEmpty,
|
|
gSOAPStrings->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,
|
|
gSOAPStrings->kEmpty,
|
|
gSOAPStrings->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_ARRAY:
|
|
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(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 = gSOAPStrings->kAnyTypeSchemaType;
|
|
arrayTypeSchemaURI = gSOAPStrings->kXSURI;
|
|
break;
|
|
default: // Everything else can be interpreted correctly
|
|
GetNativeType(arrayNativeType, arrayTypeSchemaURI, arrayTypeSchemaName);
|
|
}
|
|
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, gSOAPStrings->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(gSOAPStrings->kQualifiedSeparator);
|
|
value.Append(arrayTypeSchemaName);
|
|
value.Append(PRUnichar('['));
|
|
for (i = 0; i < dimensionCount; i++) {
|
|
if (i > 0)
|
|
value.Append(PRUnichar(','));
|
|
char* ptr = PR_smprintf("%d", dimensionSizes[i]);
|
|
AppendUTF8toUTF16(ptr, value);
|
|
PR_smprintf_free(ptr);
|
|
}
|
|
value.Append(PRUnichar(']'));
|
|
nsAutoString encURI;
|
|
rc = aEncoding->GetExternalSchemaURI(gSOAPStrings->kSOAPEncURI,encURI);
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
|
|
rc = (*aReturnValue)->SetAttributeNS(encURI, gSOAPStrings->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(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(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 ? gSOAPStrings->kTrueA : gSOAPStrings->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(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(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(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(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(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(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(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(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);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsBase64BinaryEncoder::Encode(nsISOAPEncoding * aEncoding,
|
|
nsIVariant * aSource,
|
|
const nsAString & aNamespaceURI,
|
|
const nsAString & aName,
|
|
nsISchemaType * aSchemaType,
|
|
nsISOAPAttachments * aAttachments,
|
|
nsIDOMElement * aDestination,
|
|
nsIDOMElement * *aReturnValue)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aSource);
|
|
NS_ENSURE_ARG_POINTER(aEncoding);
|
|
NS_ENSURE_ARG_POINTER(aDestination);
|
|
NS_ENSURE_ARG_POINTER(aReturnValue);
|
|
|
|
*aReturnValue = nsnull;
|
|
|
|
PRUint16 typeValue;
|
|
nsresult rv = aSource->GetDataType(&typeValue);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
if (typeValue != nsIDataType::VTYPE_ARRAY) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
nsIID iid;
|
|
PRUint32 count;
|
|
void* array;
|
|
rv = aSource->GetAsArray(&typeValue, &iid, &count, &array);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
if (typeValue != nsIDataType::VTYPE_UINT8) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
char* encodedVal = PL_Base64Encode(NS_STATIC_CAST(const char*, array), count, nsnull);
|
|
if (!encodedVal) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
nsAdoptingCString encodedString(encodedVal);
|
|
|
|
nsAutoString name, ns;
|
|
if (aName.IsEmpty()) {
|
|
// If we don't have a name, we pick soapenc:base64Binary.
|
|
rv = aEncoding->GetStyleURI(ns);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
name.Append(gSOAPStrings->kBase64BinarySchemaType);
|
|
}
|
|
else {
|
|
name = aName;
|
|
// ns remains empty. This is ok.
|
|
}
|
|
|
|
nsCOMPtr<nsIDOMDocument> document;
|
|
rv = aDestination->GetOwnerDocument(getter_AddRefs(document));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
nsCOMPtr<nsIDOMElement> element;
|
|
rv = document->CreateElementNS(ns, name, getter_AddRefs(element));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
nsCOMPtr<nsIDOMNode> ignore;
|
|
rv = aDestination->AppendChild(element, getter_AddRefs(ignore));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
if (aSchemaType) {
|
|
nsAutoString typeName, typeNS;
|
|
rv = aSchemaType->GetName(typeName);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = aSchemaType->GetTargetNamespace(typeNS);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
nsAutoString qname;
|
|
rv = nsSOAPUtils::MakeNamespacePrefix(nsnull, element, typeNS, qname);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
qname.Append(gSOAPStrings->kQualifiedSeparator + typeName);
|
|
|
|
nsAutoString ns;
|
|
rv = aEncoding->GetExternalSchemaURI(gSOAPStrings->kXSIURI, ns);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
rv = element->SetAttributeNS(ns, gSOAPStrings->kXSITypeAttribute, qname);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
}
|
|
|
|
nsCOMPtr<nsIDOMText> text;
|
|
rv = document->CreateTextNode(NS_ConvertASCIItoUTF16(encodedString),
|
|
getter_AddRefs(text));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
rv = element->AppendChild(text, getter_AddRefs(ignore));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
NS_ADDREF(*aReturnValue = element);
|
|
|
|
return rv;
|
|
}
|
|
|
|
|
|
// 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(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(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(*gSOAPStrings->kSOAPEnvURI[mSOAPVersion],
|
|
gSOAPStrings->kEncodingStyleAttribute,
|
|
getter_AddRefs(enc));
|
|
if (NS_FAILED(rv))
|
|
return rv;
|
|
if (enc) {
|
|
nsAutoString oldstyle;
|
|
rv = encoding->GetStyleURI(oldstyle);
|
|
if (NS_FAILED(rv))
|
|
return rv;
|
|
nsAutoString style;
|
|
rv = enc->GetNodeValue(style);
|
|
if (NS_FAILED(rv))
|
|
return rv;
|
|
if (!style.Equals(oldstyle)) {
|
|
nsCOMPtr<nsISOAPEncoding> newencoding;
|
|
rv = 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, gSOAPStrings->kXSIURI, gSOAPStrings->kNull, nullstr)) {
|
|
if (nullstr.Equals(gSOAPStrings->kTrue)
|
|
|| nullstr.Equals(gSOAPStrings->kTrueA)) {
|
|
*_retval = nsnull;
|
|
return NS_OK;
|
|
}
|
|
else if (!(nullstr.Equals(gSOAPStrings->kFalse)
|
|
|| nullstr.Equals(gSOAPStrings->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(gSOAPStrings->kSOAPEncURI)) { // Last-ditch hack to get undeclared types from SOAP namespace
|
|
if (name.Equals(gSOAPStrings->kArraySOAPType)
|
|
|| name.Equals(gSOAPStrings->kStructSOAPType)) { // This should not be needed if schema has these declarations
|
|
rc = collection->GetType(name, internal, getter_AddRefs(subType));
|
|
} else {
|
|
rc = collection->GetType(name,
|
|
gSOAPStrings->kXSURI,
|
|
getter_AddRefs(subType));
|
|
}
|
|
}
|
|
// if (NS_FAILED(rc)) return rc;
|
|
}
|
|
if (!subType)
|
|
subType = type;
|
|
|
|
nsCOMPtr<nsISchemaType> subsubType;
|
|
nsAutoString explicitType;
|
|
if (nsSOAPUtils::GetAttribute(aEncoding, aSource, gSOAPStrings->kXSIURI,
|
|
gSOAPStrings->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
|
|
for(;;) {
|
|
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) {
|
|
type = subsubType;
|
|
break;
|
|
}
|
|
decoder = nsnull;
|
|
if (!subType) {
|
|
subType = type;
|
|
}
|
|
subsubType = subType;
|
|
}
|
|
}
|
|
}
|
|
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(gSOAPStrings->kSOAPEncURI,
|
|
gSOAPStrings->kStructSOAPType, decodingKey);
|
|
} else {
|
|
SOAPEncodingKey(gSOAPStrings->kXSURI,
|
|
gSOAPStrings->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(gSOAPStrings->kSOAPEncURI,
|
|
gSOAPStrings->kStructSOAPType, decodingKey);
|
|
} else {
|
|
SOAPEncodingKey(gSOAPStrings->kXSURI,
|
|
gSOAPStrings->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 an 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_SUCCEEDED(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;
|
|
if (!value) {
|
|
nsCOMPtr<nsIWritableVariant> nullVariant(do_CreateInstance("@mozilla.org/variant;1"));
|
|
if (nullVariant) {
|
|
nullVariant->SetAsISupports(nsnull);
|
|
value = do_QueryInterface(nullVariant);
|
|
}
|
|
}
|
|
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
|
|
if (!all)
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
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, next, child, aAttachments, aDestination, getter_AddRefs(after));
|
|
if (NS_SUCCEEDED(rc)) {
|
|
next = after;
|
|
mangled = PR_TRUE;
|
|
rc = all->RemoveElementAt(i);
|
|
particleCount--;
|
|
if (NS_FAILED(rc))
|
|
return rc;
|
|
break;
|
|
}
|
|
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_SUCCEEDED(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, next, child, aAttachments, aDestination, getter_AddRefs(after));
|
|
if (NS_SUCCEEDED(rc)) {
|
|
next = after;
|
|
}
|
|
if (compositor == nsISchemaModelGroup::COMPOSITOR_CHOICE) {
|
|
if (rc == NS_ERROR_NOT_AVAILABLE) {
|
|
rc = NS_OK;
|
|
}
|
|
else {
|
|
if (NS_SUCCEEDED(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_SUCCEEDED(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;
|
|
if (!value) {
|
|
nsCOMPtr<nsIWritableVariant> nullVariant(do_CreateInstance("@mozilla.org/variant;1"));
|
|
if (nullVariant) {
|
|
nullVariant->SetAsISupports(nsnull);
|
|
value = do_QueryInterface(nullVariant);
|
|
}
|
|
}
|
|
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_SUCCEEDED(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;
|
|
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.
|
|
dst = Substring(src, 0, 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.
|
|
}
|
|
}
|
|
}
|
|
dst = Substring(src, 0, 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->SetAsEmptyArray();
|
|
}
|
|
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_SUCCEEDED(rc)) {
|
|
rc = aResult->SetAsArray(nsIDataType::VTYPE_INTERFACE_IS,&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, gSOAPStrings->kSOAPEncURI,
|
|
gSOAPStrings->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(gSOAPStrings->kSOAPEncURI);
|
|
name.Assign(gSOAPStrings->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, gSOAPStrings->kSOAPEncURI,
|
|
gSOAPStrings->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, gSOAPStrings->kSOAPEncURI,
|
|
gSOAPStrings->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];\
|
|
if (!a)\
|
|
return NS_ERROR_OUT_OF_MEMORY;\
|
|
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, gSOAPStrings->kSOAPEncURI,\
|
|
gSOAPStrings->kSOAPArrayPositionAttribute, pos)) {\
|
|
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_SUCCEEDED(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(gSOAPStrings->kXSURI)) {
|
|
if (name.Equals(gSOAPStrings->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(gSOAPStrings->kBooleanSchemaType)) {
|
|
DECODE_SIMPLE_ARRAY(PRBool,Bool,BOOL);
|
|
} else if (name.Equals(gSOAPStrings->kFloatSchemaType)) {
|
|
DECODE_SIMPLE_ARRAY(float,Float,FLOAT);
|
|
} else if (name.Equals(gSOAPStrings->kDoubleSchemaType)) {
|
|
DECODE_SIMPLE_ARRAY(double,Double,DOUBLE);
|
|
} else if (name.Equals(gSOAPStrings->kLongSchemaType)) {
|
|
DECODE_SIMPLE_ARRAY(PRInt64,Int64,INT64);
|
|
} else if (name.Equals(gSOAPStrings->kIntSchemaType)) {
|
|
DECODE_SIMPLE_ARRAY(PRInt32,Int32,INT32);
|
|
} else if (name.Equals(gSOAPStrings->kShortSchemaType)) {
|
|
DECODE_SIMPLE_ARRAY(PRInt16,Int16,INT16);
|
|
} else if (name.Equals(gSOAPStrings->kByteSchemaType)) {
|
|
DECODE_SIMPLE_ARRAY(PRUint8,Int8,INT8);
|
|
} else if (name.Equals(gSOAPStrings->kUnsignedLongSchemaType)) {
|
|
DECODE_SIMPLE_ARRAY(PRUint64,Uint64,UINT64);
|
|
} else if (name.Equals(gSOAPStrings->kUnsignedIntSchemaType)) {
|
|
DECODE_SIMPLE_ARRAY(PRUint32,Uint32,UINT32);
|
|
} else if (name.Equals(gSOAPStrings->kUnsignedShortSchemaType)) {
|
|
DECODE_SIMPLE_ARRAY(PRUint16,Uint16,UINT16);
|
|
} else if (name.Equals(gSOAPStrings->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_IS,&NS_GET_IID(nsIVariant),
|
|
a[p] = v;NS_ADDREF(a[p]);,
|
|
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;
|
|
PRBool b;
|
|
if (value.Equals(gSOAPStrings->kTrue)
|
|
|| value.Equals(gSOAPStrings->kTrueA)) {
|
|
b = PR_TRUE;
|
|
} else if (value.Equals(gSOAPStrings->kFalse)
|
|
|| value.Equals(gSOAPStrings->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
|
|
nsBase64BinaryEncoder::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;
|
|
|
|
|
|
nsString value;
|
|
nsresult rv = nsSOAPUtils::GetElementTextContent(aSource, value);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
NS_LossyConvertUTF16toASCII valueStr(value);
|
|
valueStr.StripChars(" \n\r\t");
|
|
|
|
char* decodedVal = PL_Base64Decode(valueStr.get(), valueStr.Length(), nsnull);
|
|
if (!decodedVal) {
|
|
return SOAP_EXCEPTION(NS_ERROR_ILLEGAL_VALUE,
|
|
"SOAP_ILLEGAL_BASE64",
|
|
"Data cannot be decoded as Base64");
|
|
}
|
|
|
|
nsCOMPtr<nsIWritableVariant> p =
|
|
do_CreateInstance(NS_VARIANT_CONTRACTID, &rv);
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
rv = p->SetAsArray(nsIDataType::VTYPE_UINT8, nsnull,
|
|
strlen(decodedVal), decodedVal);
|
|
}
|
|
|
|
PR_Free(decodedVal);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
NS_ADDREF(*_retval = p);
|
|
|
|
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;
|
|
}
|