--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/upnp/upnpstack/serviceframework/src/upnpsoapmessagefactory.cpp Tue Feb 02 01:12:20 2010 +0200
@@ -0,0 +1,497 @@
+/** @file
+* Copyright (c) 2005-2006 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: Produces SOAP messages
+*
+*/
+
+
+
+// INCLUDE FILES
+#include "upnpsoapmessagefactory.h"
+#include "upnphttpmessagefactory.h"
+#include "upnpsoapmessage.h"
+#include "upnpaction.h"
+#include "upnpargument.h"
+#include "upnperrors.h"
+#include "upnpserviceimplementation.h"
+#include "upnpdevice.h"
+#include "upnpstring.h"
+#include "upnpcommonupnplits.h"
+#define KLogFile _L("UPnPStack.txt")
+#include "upnpcustomlog.h"
+#include "upnplist.h"
+#include "upnpcons.h"
+
+// CONSTANTS
+_LIT8(KSoapEnvelopeStart, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\n<s:Body>\n<u:");
+_LIT8(KSoapServiceNsStart, " xmlns:u=\"urn:schemas-upnp-org:service:");
+_LIT8(KSoapServiceNsEnd, "\">\n");
+_LIT8(KActionNameEnd, "</u:");
+_LIT8(KSoapEnvelopeEnd, ">\n</s:Body>\n</s:Envelope>");
+_LIT8(KSoapActionStart, "\"urn:schemas-upnp-org:service:");
+_LIT8(KCrash, "#");
+_LIT8(KOpenBracket, "<");
+_LIT8(KCloseBracket, ">");
+_LIT8(KLinefeed, "\n");
+_LIT8(KResponse, "Response");
+
+_LIT(KSoapErrorStart,
+ "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\n<s:Body>\n<s:Fault>\n<faultcode>s:Client</faultcode>\n<faultstring>UPnPError</faultstring>\n<detail>\n<UPnPError xmlns=\"urn:schemas-upnp-org:control-1-0\">\n<errorCode>");
+
+_LIT(KSoapErrorBetween,
+ "</errorCode>\n<errorDescription>");
+_LIT(KSoapErrorEnd,
+ "</errorDescription>\n</UPnPError>\n</detail>\n</s:Fault>\n</s:Body>\n</s:Envelope>");
+
+static const TInt KTagCharsLength = 7;
+static const TInt KExtraCharsLength = 2;
+static const TInt KMaxErrorCodeLength = 20;
+
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// RUpnpSoapMessageFactory::SoapRequest
+//
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CUpnpSoapMessage* RUpnpSoapMessageFactory::SoapRequestL(CUpnpAction* aAction)
+ {
+ LOGS("RUpnpSoapMessageFactory::SoapRequest(CUpnpAction*)");
+
+ if (aAction == NULL)
+ {
+ return NULL;
+ }
+ const TDesC8& actName = aAction->Name();
+ HBufC8* servTypeB = NULL;
+ TInt posS(KErrNotFound);
+ TInt posD(KErrNotFound);
+
+ const TDesC8& servType = aAction->ServiceType();
+ TInt serviceVersion(KErrNotFound);
+ if(servType.Length())
+ {
+ posS = servType.LocateReverse(':');
+ if (posS != KErrNotFound)
+ {
+ TLex8 number(servType.Right(servType.Length() - posS - 1));
+ if(number.Val(serviceVersion) != KErrNone)
+ {
+ serviceVersion = KErrNotFound;
+ }
+ }
+ }
+
+ const TDesC8& devType = aAction->Service().Device().DeviceType();
+ TInt deviceVersion(KErrNotFound);
+
+ if(devType.Length())
+ {
+ posD = devType.LocateReverse(':');
+ if (posD != KErrNotFound)
+ {
+ TLex8 number(devType.Right(devType.Length() - posD - 1));
+ if(number.Val(deviceVersion) != KErrNone)
+ {
+ deviceVersion = KErrNotFound;
+ }
+ }
+ }
+
+ if(deviceVersion != KErrNotFound && serviceVersion != KErrNotFound)
+ {
+ if(deviceVersion < serviceVersion)
+ {
+ servTypeB = HBufC8::NewLC(servType.Length() + devType.Length() - posD);
+ TPtr8 buf = servTypeB->Des();
+ buf.Append(servType.Left(posS + 1));
+ buf.Append(devType.Right(devType.Length() - posD - 1));
+ }
+ else
+ {
+ servTypeB = servType.AllocLC();
+ }
+ }
+ else
+ {
+ servTypeB = servType.AllocLC();
+ }
+
+ RPointerArray<CUpnpArgument>& args = aAction->ArgumentList();
+
+ TInt argLength = 0;
+
+ TInt i=0;
+ for(i=0; i<args.Count(); i++)
+ {
+ argLength += KTagCharsLength;
+ argLength += args[i]->Name().Length() * 2;
+ argLength += args[i]->Value().Length();
+ }
+
+ argLength += KSoapEnvelopeStart().Length();
+ argLength += KSoapServiceNsStart().Length();
+ argLength += KSoapServiceNsEnd().Length();
+ argLength += KActionNameEnd().Length();
+ argLength += KSoapEnvelopeEnd().Length();
+
+ argLength += actName.Length()*2;
+ argLength += servTypeB->Length();
+
+ HBufC8* buffer = HBufC8::NewLC(argLength);
+ TPtr8 ptr = buffer->Des();
+
+ ptr.Append(KSoapEnvelopeStart());
+ ptr.Append(actName);
+ ptr.Append(KSoapServiceNsStart());
+ ptr.Append(*servTypeB);
+ ptr.Append(KSoapServiceNsEnd());
+
+ for (i=0; i<args.Count(); i++)
+ {
+ if (args[i]->Direction() == EIn)
+ {
+ const TDesC8& name = args[i]->Name();
+ const TDesC8& value = args[i]->Value();
+
+ ptr.Append(KOpenBracket());
+ ptr.Append(name);
+ ptr.Append(KCloseBracket());
+ ptr.Append(value);
+ ptr.Append(KOpenBracket());
+ ptr.Append(UpnpString::KSlash());
+ ptr.Append(name);
+ ptr.Append(KCloseBracket());
+ ptr.Append(KLinefeed());
+
+ }
+ }
+ ptr.Append(KActionNameEnd());
+ ptr.Append(actName);
+ ptr.Append(KSoapEnvelopeEnd());
+
+
+ CUpnpSoapMessage* self = NULL;
+
+ TInetAddr dest = aAction->DestinationAddr();
+ dest.SetFamily(KAfInet);
+
+ TPtrC8 destPath = aAction->DestinationPath();
+ if (destPath.Length() > KHttp().Length() &&
+ destPath.Left( KHttp().Length() ) == KHttp())
+ {
+ self = static_cast<CUpnpSoapMessage*>(RUpnpHttpMessageFactory::HttpPostL(
+ destPath));
+ }
+ else if (destPath.Find(UpnpString::KSlash()) != 0)
+ {
+ HBufC8* longPath = HBufC8::NewLC(destPath.Length() +1);
+ longPath->Des().Append(UpnpString::KSlash());
+ longPath->Des().Append(destPath);
+ self = static_cast<CUpnpSoapMessage*>(RUpnpHttpMessageFactory::HttpPostL(
+ dest, *longPath));
+
+ CleanupStack::PopAndDestroy( longPath );
+ }
+ else
+ {
+ self = static_cast<CUpnpSoapMessage*>(RUpnpHttpMessageFactory::HttpPostL(
+ dest, destPath));
+ }
+
+ CleanupStack::PushL(self);
+ CUpnpHttpHeaderList* hdrList=self->HeaderList();
+
+ CUpnpHttpHeader* hdr = hdrList->First();
+
+
+ while ( hdr )
+ {
+ TBool flag = EFalse;
+ if(hdr->Name().Length() == UpnpSSDP::KHdrHost().Length())
+ {
+ if (hdr->Name().FindC(UpnpSSDP::KHdrHost()) == 0)
+ {
+ CUpnpHttpHeader* temp = hdr;
+ hdr = hdrList->Next(hdr);
+ flag = ETrue;
+ hdrList->Remove(temp);
+ delete temp;
+
+ }
+ }
+ if(!flag)
+ hdr = hdrList->Next(hdr);
+ }
+
+ HBufC8* host = UpnpString::InetToStringL( self->Sender() );
+ CleanupStack::PushL( host );
+ self->AddPairL( UpnpSSDP::KHdrHost(), *host );
+ CleanupStack::PopAndDestroy( host );
+
+ self->SetSessionId(aAction->SessionId());
+ self->SetBodyL(*buffer);
+ self->AddPairL(UpnpHTTP::KHdrContentType(), UpnpGENA::KTextXmlUtf8());
+
+
+ HBufC8* soapAction = HBufC8::NewLC(
+ KSoapActionStart().Length() +
+ aAction->Name().Length() +
+ servTypeB->Length() +
+ KExtraCharsLength);
+
+ TPtr8 soapPtr = soapAction->Des();
+
+ // soapPtr = "urn:schemas-upnp-org:service:
+ soapPtr.Append(KSoapActionStart());
+ // soapPtr = "urn:schemas-upnp-org:service:serviceType:v
+ soapPtr.Append(*servTypeB);
+ // soapPtr = "urn:schemas-upnp-org:service:serviceType:v#
+ soapPtr.Append(KCrash());
+ // soapPtr = "urn:schemas-upnp-org:service:serviceType:v#actionName
+ soapPtr.Append(aAction->Name());
+ // soapPtr = "urn:schemas-upnp-org:service:serviceType:v#actionName"
+ soapPtr.Append(UpnpString::KInvComma());
+
+ self->AddPairL(KSoapAction(), soapPtr);
+
+ self->SetLocal(aAction->Local());
+ CleanupStack::PopAndDestroy(soapAction);
+ CleanupStack::Pop(self);
+ CleanupStack::PopAndDestroy(buffer);
+
+ CleanupStack::PopAndDestroy(servTypeB);
+
+ return self;
+}
+
+// -----------------------------------------------------------------------------
+// RUpnpSoapMessageFactory::SoapResponseL
+//
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CUpnpSoapMessage* RUpnpSoapMessageFactory::SoapResponseL(CUpnpAction* aAction)
+{
+ LOGS("RUpnpSoapMessageFactory::SoapResponseL(CUpnpAction*)");
+ if (aAction == NULL)
+ {
+ return NULL;
+ }
+ const TDesC8& actName = aAction->Name();
+ const TDesC8& servType = aAction->ServiceType();
+
+ RPointerArray<CUpnpArgument>& args = aAction->ArgumentList();
+
+ TInt argLength = 0;
+
+ TInt i=0;
+ for(i=0; i<args.Count(); i++)
+ {
+ argLength += KTagCharsLength;
+
+ argLength += args[i]->Name().Length() * 2;
+ argLength += args[i]->Value().Length();
+ }
+
+ argLength += (2 * KResponse().Length());
+
+ argLength += KSoapEnvelopeStart().Length();
+ argLength += KSoapServiceNsStart().Length();
+ argLength += KSoapServiceNsEnd().Length();
+ argLength += KActionNameEnd().Length();
+ argLength += KSoapEnvelopeEnd().Length();
+
+ argLength += actName.Length() * 2;
+ argLength += servType.Length();
+
+ HBufC8* buffer = HBufC8::NewLC(argLength);
+ TPtr8 ptr = buffer->Des();
+
+ ptr.Append(KSoapEnvelopeStart());
+ ptr.Append(actName);
+ ptr.Append(KResponse());
+ ptr.Append(KSoapServiceNsStart());
+ ptr.Append(servType);
+ ptr.Append(KSoapServiceNsEnd());
+
+ for (i=0; i<args.Count(); i++)
+ {
+ if (args[i]->Direction() == EOut)
+ {
+ TDesC8& name = args[i]->Name();
+ TDesC8& value = args[i]->Value();
+
+ ptr.Append(KOpenBracket());
+ ptr.Append(name);
+ ptr.Append(KCloseBracket());
+ ptr.Append(value);
+ ptr.Append(KOpenBracket());
+ ptr.Append(UpnpString::KSlash());
+ ptr.Append(name);
+ ptr.Append(KCloseBracket());
+ ptr.Append(KLinefeed());
+
+ }
+ }
+ ptr.Append(KActionNameEnd());
+ ptr.Append(actName);
+ ptr.Append(KResponse());
+ ptr.Append(KSoapEnvelopeEnd());
+
+ CUpnpSoapMessage* self = static_cast<CUpnpSoapMessage*>(
+ RUpnpHttpMessageFactory::HttpResponseOkL(aAction->Sender()));
+ CleanupStack::PushL(self);
+
+ self->SetSessionId(aAction->SessionId());
+
+ self->SetBodyL(*buffer);
+
+ self->AddPairL(UpnpHTTP::KHdrContentType(), UpnpGENA::KTextXmlUtf8());
+
+ self->AddPairL(UpnpHTTP::KHdrExtWithoutColon(), KNullDesC8);
+
+ self->SetLocal(aAction->Local());
+
+ CleanupStack::Pop(self);
+ CleanupStack::PopAndDestroy(buffer);
+
+ return self;
+}
+
+// -----------------------------------------------------------------------------
+// RUpnpSoapMessageFactory::SoapResponseL
+//
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CUpnpSoapMessage* RUpnpSoapMessageFactory::SoapResponseL( CUpnpAction* aAction, TUpnpErrorCode aCode)
+{
+ LOGS("RUpnpSoapMessageFactory::SoapResponseL(CUpnpAction*, TUpnpErrorCode)");
+
+ HBufC8* errorString = CUpnpSoapMessage::UpnpErrorL(aCode);
+ CleanupStack::PushL(errorString);
+ CUpnpSoapMessage* self = RUpnpSoapMessageFactory::SoapResponseL(aAction, aCode, *errorString);
+ CleanupStack::PopAndDestroy(errorString);
+ return self;
+}
+
+EXPORT_C CUpnpSoapMessage* RUpnpSoapMessageFactory::SoapResponseL( CUpnpAction* aAction,
+ TUpnpErrorCode aCode,
+ const TDesC8& aDescription)
+{
+ LOGS("RUpnpSoapMessageFactory::SoapResponseL(CUpnpAction*, TUpnpErrorCode,TDesC8&)");
+
+ if (aAction == NULL)
+ {
+ return NULL;
+ }
+ TBuf8<KMaxErrorCodeLength> errorCode;
+ TInt code = aCode;
+ errorCode.Num(code);
+
+ TInt length = 0;
+ length += KSoapErrorStart().Length();
+ length += KSoapErrorBetween().Length();
+ length += KSoapErrorEnd().Length();
+ length += errorCode.Length();
+
+ length += aDescription.Length();
+
+ HBufC8* buffer = HBufC8::NewL(length);
+ TPtr8 ptr = buffer->Des();
+
+ ptr.Append(KSoapErrorStart());
+ ptr.Append(errorCode);
+ ptr.Append(KSoapErrorBetween());
+ ptr.Append(aDescription);
+ ptr.Append(KSoapErrorEnd());
+
+ CleanupStack::PushL(buffer);
+
+ CUpnpSoapMessage* self = static_cast<CUpnpSoapMessage*>(
+ RUpnpHttpMessageFactory::HttpResponseErrorL(aAction->Sender(), 500));
+
+ CleanupStack::PushL(self);
+ self->SetSessionId(aAction->SessionId());
+
+ self->SetBodyL(*buffer);
+ self->AddPairL(UpnpHTTP::KHdrContentType(), UpnpGENA::KTextXmlUtf8());
+ self->AddPairL(UpnpHTTP::KHdrExtWithoutColon(), KNullDesC8);
+
+ self->SetLocal(aAction->Local());
+
+ CleanupStack::Pop(self);
+ CleanupStack::PopAndDestroy(buffer);
+
+ return self;
+}
+
+// -----------------------------------------------------------------------------
+// RUpnpSoapMessageFactory::SoapResponseL
+//
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CUpnpSoapMessage* RUpnpSoapMessageFactory::SoapResponseL(
+ CUpnpSoapMessage* aMessage,
+ TUpnpErrorCode aCode )
+{
+ if (aMessage == NULL)
+ {
+ return NULL;
+ }
+ TBuf8<KMaxErrorCodeLength> errorCode;
+ TInt code = aCode;
+ errorCode.Num(code);
+
+ TInt length = 0;
+ length += KSoapErrorStart().Length();
+ length += KSoapErrorBetween().Length();
+ length += KSoapErrorEnd().Length();
+ length += errorCode.Length();
+
+ HBufC8* errorString = CUpnpSoapMessage::UpnpErrorL(aCode);
+ CleanupStack::PushL(errorString);
+
+ length += errorString->Length();
+
+ HBufC8* buffer = HBufC8::NewLC(length);
+ TPtr8 ptr = buffer->Des();
+
+ ptr.Append(KSoapErrorStart());
+ ptr.Append(errorCode);
+ ptr.Append(KSoapErrorBetween());
+ ptr.Append(*errorString);
+ ptr.Append(KSoapErrorEnd());
+
+ CUpnpSoapMessage* self = static_cast<CUpnpSoapMessage*>(
+ RUpnpHttpMessageFactory::HttpResponseErrorL(aMessage->Sender(), 500));
+
+ self->SetSessionId(aMessage->SessionId());
+
+ self->SetBodyL(*buffer);
+ self->AddPairL(UpnpHTTP::KHdrContentType(), UpnpGENA::KTextXmlUtf8());
+ self->AddPairL(UpnpHTTP::KHdrExtWithoutColon(), KNullDesC8);
+
+ self->SetLocal(aMessage->Local());
+
+ CleanupStack::PopAndDestroy(2);
+
+ return self;
+}
+
+// End of File