smsprotocols/smsstack/wapprot/Src/wapdgrm.cpp
branchopencode
changeset 24 6638e7f4bd8f
parent 23 6b1d113cdff3
--- a/smsprotocols/smsstack/wapprot/Src/wapdgrm.cpp	Mon May 03 13:37:20 2010 +0300
+++ b/smsprotocols/smsstack/wapprot/Src/wapdgrm.cpp	Thu May 06 15:10:38 2010 +0100
@@ -1,707 +1,707 @@
-// Copyright (c) 1997-2009 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:
-//
-
-#include "gsmubuf.h"
-#include "gsmuset.h"
-#include "Gsmuelem.h"
-#include "Gsmumsg.h"
-#include "gsmusar.h"
-#include "gsmupdu.h"
-#include "WAPDGRM.H"
-#include "ws_main.h"
-#include "smsstackutils.h"
-
-//
-// For incoming short message
-//
-CWapDatagram* CWapDatagram::NewL(const CSmsMessage& aSms)
-    {
-    LOGWAPPROT2("CWapDatagram::NewL(): aSms=0x%08x", (TInt) &aSms);
-
-    CWapDatagram* datagram = new (ELeave)CWapDatagram();
-
-    CleanupStack::PushL(datagram);
-    datagram->ConstructL(aSms);
-    CleanupStack::Pop();
-
-    LOGWAPPROT2("CWapDatagram::NewL(): iFromPort: %d", datagram->iFromPort);
-    LOGWAPPROT2("CWapDatagram::NewL(): iToPort: %d", datagram->iToPort);
-    LOGWAPPROT2("CWapDatagram::NewL(): iReference: %d", datagram->iReference);
-    LOGWAPPROT2("CWapDatagram::NewL(): iTotalSegments: %d", datagram->iTotalSegments);
-    LOGWAPPROT2("CWapDatagram::NewL(): iSegmentNumber: %d", datagram->iSegmentNumber);
-    LOGWAPPROT2("CWapDatagram::NewL(): iIsComplete: %d", datagram->iIsComplete);
-    LOGWAPPROT2("CWapDatagram::NewL(): iReference: %d", datagram->iReference);
-    LOGWAPPROT2("CWapDatagram::NewL(): iIsTextHeader: %d", datagram->iIsTextHeader);
-    LOGWAPPROT2("CWapDatagram::NewL(): iLogServerId: %d", datagram->iLogServerId);
-    LOGWAPPROT2("CWapDatagram::NewL(): i16BitPorts: %d", datagram->i16BitPorts);
-
-    // assert destination port
-	if (datagram->i16BitPorts)
-		{
-		if (datagram->iToPort>=0  &&  datagram->iToPort<=65535)
-			{
-			LOGWAPPROT1("iToPort OK");
-			}
-		else
-			{
-			LOGWAPPROT1("iToPort FAILED");
-			}
-		}
-    else
-		{
-        if (datagram->iToPort>=0  &&  datagram->iToPort<=255)
-			{
-		    LOGWAPPROT1("iToPort OK");
-			}
-		else
-			{
-			LOGWAPPROT1("iToPort FAILED");
-			}
-		}
-
-	if (datagram->i16BitPorts)
-		{
-		if (datagram->iFromPort>=0  &&  datagram->iFromPort<=65535)
-			{
-			LOGWAPPROT1("iFromPort OK");
-			}
-		else
-			{
-			LOGWAPPROT1("iFromPort FAILED");
-			}
-		}
-    else
-		{
-        if (datagram->iFromPort>=0  &&  datagram->iFromPort<=255)
-			{
-		    LOGWAPPROT1("iFromPort OK");
-			}
-		else
-			{
-			LOGWAPPROT1("iFromPort FAILED");
-			}
-		}
-
-    return datagram;
-    } // CWapDatagram::NewL
-
-
-//
-// For outgoing short messages
-//
-CWapDatagram* CWapDatagram::NewL(const TDesC8& aSendBuffer)
-    {
-    LOGWAPPROT2("CWapDatagram::NewL(): aSendBuffer=0x%08x", (TInt) &aSendBuffer);
-
-    CWapDatagram* datagram = new (ELeave)CWapDatagram();
-
-    CleanupStack::PushL(datagram);
-    datagram->Construct(aSendBuffer);
-    CleanupStack::Pop();
-
-    return datagram;
-    } // CWapDatagram::NewL
-
-
-CWapDatagram::~CWapDatagram()
-    {
-    LOGWAPPROT1("CWapDatagram::~CWapDatagram()");
-
-	delete iRecvbuf;
-    delete iBuffer;
-    delete iSegment;
-    } // CWapDatagram::~CWapDatagram
-
-
-//
-// What about service centre address ?
-// aSmsMessageArray contains CSmsMessage objects
-//
-void CWapDatagram::EncodeConcatenatedMessagesL(RFs& aFs, CArrayPtr<CSmsMessage>& aSmsMessageArray)
-    {
-    LOGWAPPROT2("CWapDatagram::EncodeConcatenatedMessagesL(): %d messages", aSmsMessageArray.Count());
-
-    // Couple of checkings makes sense
-    __ASSERT_DEBUG(iToPort >=0 && iToAddress.Length()>=0
-            && (iUserDataSettings.Alphabet()==TSmsDataCodingScheme::ESmsAlphabet8Bit
-                 || iUserDataSettings.Alphabet()==TSmsDataCodingScheme::ESmsAlphabet7Bit),
-            Panic(KPanicUsageError));
-
-    // Determine CSmsMessage encoding by character width
-    if (iUserDataSettings.Alphabet() == TSmsDataCodingScheme::ESmsAlphabet8Bit)
-        {
-        CSmsBufferBase* SmsBuffer = CSmsBuffer::NewL();
-
-        CleanupStack::PushL(SmsBuffer);
-        ConvertL(iSendBuffer,*SmsBuffer);
-        CleanupStack::Pop(); // SmsBuffer, popped here since it is pushed again in the following NewL call
-        CSmsMessage* SmsMessage = CSmsMessage::NewL(aFs, CSmsPDU::ESmsSubmit,SmsBuffer,EFalse);
-        CleanupStack::PushL(SmsMessage);
-        // one and only object
-        aSmsMessageArray.AppendL(SmsMessage);
-        CleanupStack::Pop(); // SmsMessage
-
-        SetSmsMessageSettingsL(*SmsMessage,ETrue);
-        }
-    else
-        {
-        // contruct TWapTextMessage object
-        TWapTextMessage* Segment = new (ELeave) TWapTextMessage(KNullDesC8);
-        CleanupStack::PushL(Segment);
-        CArrayPtrFlat<HBufC8>* SegmentArray = new (ELeave) CArrayPtrFlat<HBufC8> (8);
-        CleanupStack::PushL(SegmentArray);
-		// coverity[double_push]
-        CleanupResetAndDestroyPushL(*SegmentArray);
-
-        Segment->SetDestinationPort(iToPort,i16BitPorts);
-        Segment->SetSourcePort(iFromPort,i16BitPorts);
-        Segment->SetReferenceNumber(iReference);
-        Segment->SetUserData(iSendBuffer);
-        Segment->SetOtherHeader(iOtherHeader);
-        Segment->EncodeSegmentsL(*SegmentArray);
-
-        // contruct array of CSmsMessages
-        TInt Count = SegmentArray->Count();
-        for (TInt i=0; i<Count; i++)
-            {
-            CSmsBufferBase* SmsBuffer = CSmsBuffer::NewL();
-
-            CleanupStack::PushL(SmsBuffer);
-            ConvertL(*(SegmentArray->At(i)),*SmsBuffer);
-            CleanupStack::Pop(); // SmsBuffer, popped here since it is pushed again in the following NewL call
-            CSmsMessage* SmsMessage=CSmsMessage::NewL(aFs, CSmsPDU::ESmsSubmit,SmsBuffer,EFalse);
-            CleanupStack::PushL(SmsMessage);
-            aSmsMessageArray.AppendL(SmsMessage);
-            CleanupStack::Pop(); // SmsMessage
-
-            SetSmsMessageSettingsL(*SmsMessage,EFalse);
-            }
-        CleanupStack::PopAndDestroy(3, Segment);  // SegmentArray elements (Reset and Destroy), SegmentArray, Segment
-
-        }
-    } // CWapDatagram::EncodeConcatenatedMessagesL
-
-void CWapDatagram::DecodeConcatenatedMessagesL(CArrayPtr<TSegmentData>& aSmsMessageArray)
-    {
-    LOGWAPPROT1("CWapDatagram::DecodeConcatenatedMessagesL()");
-
-    // The TSegmentData elements are in the random order in the array
-    TInt Count = aSmsMessageArray.Count();
-    TInt i=0;
-
-    if (Count > 0)
-        {
-        TInt DataLength = 0;  // total length of data
-        TInt TempLength = 0;
-
-        // Every TSegmentData should be equal length except last segment
-        // Use that 'constant' segment length as indexes
-        // Count the actual data length
-        for(i=0; i<Count; i++)
-            {
-            TempLength = aSmsMessageArray.At(i)->iData.Length();
-            DataLength += TempLength;
-            }
-
-        TSegmentData* Segment = NULL;
-
-        if (iBuffer)
-            {
-            delete iBuffer;
-            iBuffer = NULL;
-            }
-        iBuffer = HBufC8::NewL(DataLength );
-
-        TPtr8 BufferPtr(iBuffer->Des());
-        BufferPtr.SetLength(DataLength );
-
-        TInt segmentStartPosition=0;
-
-        for(i=0; i<Count; i++)
-            {
-              if (segmentStartPosition >= DataLength)  
-                  {
-                  // Once the start position is out of range,
-                  // there is no point in continuing reconstructing the
-                  // wapdatagram.
-                  break;
-				 }			
-			
-            Segment = aSmsMessageArray.At(i);
-			TPtr8 CopyBufferPtr(&(BufferPtr[segmentStartPosition]),0,160);
-			CopyBufferPtr.Copy(Segment->iData);
- 			segmentStartPosition+=Segment->iData.Length();
-            }
-        }
-    iIsComplete = ETrue;
-    } // CWapDatagram::DecodeConcatenatedMessagesL
-
-
-void CWapDatagram::InternalizeL(RReadStream& aStream)
-    {
-    aStream >> iUserDataSettings;
-    aStream >> iToAddress;
-    iToPort = aStream.ReadInt32L();
-    aStream >> iFromAddress;
-    iFromPort = aStream.ReadInt32L();
-    TInt64 time;
-    aStream >> time;
-    iTime = time;
-    iUTCOffset = aStream.ReadInt32L();
-    iIsTextHeader = aStream.ReadInt32L();
-    iReference = aStream.ReadInt32L();
-    iTotalSegments = aStream.ReadInt32L();
-    iSegmentNumber = aStream.ReadInt32L();
-    iLogServerId = aStream.ReadInt32L();
-    iVersionNumber = aStream.ReadInt32L();
-    iSpare1 =  aStream.ReadInt32L();
-    iSpare2 =  aStream.ReadInt32L();
-    iSpare3 =  aStream.ReadInt32L();
-	
-    // Required for version 1, which is reading and internalizing extra SMS parameters from stream
-    if(iVersionNumber == EFirstVersion)
-    	{
-    	TInt length = aStream.ReadInt32L();
-    	if(length>0)
-    		{
-    		HBufC8* smsBuffer=HBufC8::NewMaxLC(length);
-			TPtr8 recvbuftmp = smsBuffer->Des();
-			aStream >> recvbuftmp;
-			if(!iRecvbuf)
-				{
-				iRecvbuf = CBufFlat::NewL(KSmsBufferExpansion);
-				}
-			iRecvbuf->ResizeL(recvbuftmp.Size());
-			iRecvbuf->Write(0, recvbuftmp);
-			CleanupStack::PopAndDestroy(smsBuffer);
-			}
-    	}
-    
-    } // CWapDatagram::InternalizeL
-
-
-//
-//	Reads iBuffer from stream (for 8Bit messages)
-//
-void CWapDatagram::InternalizeBufferL(RReadStream& aStream)
-	{
-	TInt length;
-	length=aStream.ReadInt32L();
-	iBuffer=HBufC8::NewMaxL(length);
-	TPtr8 tmp = iBuffer->Des();
-	aStream >> tmp;
-	iIsComplete = ETrue;
-	}
-
-
-void CWapDatagram::ExternalizeL(RWriteStream& aStream) const
-    {
-    aStream << iUserDataSettings;
-    aStream << iToAddress;
-    aStream.WriteInt32L(iToPort);
-
-    aStream << iFromAddress;
-    aStream.WriteInt32L(iFromPort);
-    aStream << iTime.Int64();
-    aStream.WriteInt32L(iUTCOffset.Int());
-
-    aStream.WriteInt32L(iIsTextHeader);
-    aStream.WriteInt32L(iReference);
-    aStream.WriteInt32L(iTotalSegments);
-    aStream.WriteInt32L(iSegmentNumber);
-
-    aStream.WriteInt32L(iLogServerId);
-
-    aStream.WriteInt32L(iVersionNumber);
-    aStream.WriteInt32L(iSpare1);
-    aStream.WriteInt32L(iSpare2);
-    aStream.WriteInt32L(iSpare3);
-	
-	// Externalizing the SMS params if exists
-	if(iRecvbuf)
-		{
-		TPtr8 recvbuftmp = iRecvbuf->Ptr(0);
-		aStream.WriteInt32L(recvbuftmp.Length());
-		aStream << recvbuftmp;
-		}
-	else
-		{
-		aStream.WriteInt32L(0);
-		}
-    }
-
-
-//
-// writes iBuffer to writeStream for 8-bit incomming messages
-//
-void CWapDatagram::ExternalizeBufferL(RWriteStream& aStream) const
-	{
-	TInt length= WapDatagramLength();
-	aStream.WriteInt32L(length);
-	TPtr8 tmp= iBuffer->Des();
-	aStream << tmp;
-
-	} // CWapDatagram::ExternalizeBufferL
-
-
-//
-// Outgoing
-//
-void CWapDatagram::Construct(const TDesC8& aSendBuffer)
-    {
-    LOGWAPPROT1("CWapDatagram::Construct()");
-	
-	// Set version number to 1, as we have had to make 
-	// changes to CWapDatagram for CR0929
-	iVersionNumber = EFirstVersion;
-	
-    iSendBuffer.Set(aSendBuffer);
-    } // CWapDatagram::Construct
-
-
-//
-// Incoming
-// code actualy supports 7-bit characters and port numbers
-// encoded in information elements (IE) although it is not
-// a requirement
-//
-void CWapDatagram::ConstructL(const CSmsMessage& aSms)
-    {
-    LOGWAPPROT1("CWapDatagram::ConstructL()");
-
-	// Set version number to 1, as we have had to make 
-	// changes to CWapDatagram for CR0929
-	iVersionNumber = EFirstVersion;
-
-	iRecvbuf = CBufFlat::NewL(KSmsBufferExpansion);
-
-	RBufWriteStream writestream(*iRecvbuf);
-	writestream.Open(*iRecvbuf);
-	CleanupClosePushL(writestream);
-	
-	// Externalizing everything within CSMSMessage except buffer
-	aSms.ExternalizeWithoutBufferL(writestream);
-	
-	CleanupStack::PopAndDestroy();  //  writestream
-
-	iRecvbuf->Compress();
-
-    const CSmsBufferBase& SmsBufferBase = aSms.Buffer();
-
-    GetDatagramSettings(aSms);
-
-    // Get the data from CSmsMessage and convert
-    // SmsBuffer store Unicode short message from CSmsMessage
-    ConvertL(SmsBufferBase,&iBuffer);
-	GetDatagramSettingsL();
-
-    iIsComplete = ETrue;
-    if (iUserDataSettings.Alphabet() == TSmsDataCodingScheme::ESmsAlphabet7Bit)
-        {
-        // this is a good candidate to include a text header.
-        if (iIsTextHeader)
-            {
-            // there is still a minor chance that message is complete:
-            // one fragment long datagram
-            if (iTotalSegments == 1)
-                {
-                // Get the segment data
-                TPtr8 PtrNarrow = iBuffer->Des();
-                PtrNarrow.Zero();
-                iSegment->UserData(PtrNarrow);
-                }
-            else
-                {
-                iIsComplete = EFalse;
-                // delete incomplete message from iBuffer;
-                delete iBuffer;
-                iBuffer = 0;
-                }
-            }
-        else
-            // This means that IEs with 7-bits are used
-            // Happily we support it
-            iIsComplete = ETrue;
-
-        }
-    } // CWapDatagram::ConstructL
-
-
-//
-// Set WAP datagram private members from a text based concatenated message
-// Copies contents of iBuffer to iSmsBuffer
-// Allocates iSegment object
-//
-void CWapDatagram::GetDatagramSettingsL()
-    {
-    LOGWAPPROT1("CWapDatagram::GetDatagramSettingsL()");
-
-	/* The WAP stack always receives 8 bit WAP datagrams from the SMS Stack as a single CSmsMessage.
-	This is because 8 bit WAP messages which cannot be encoded into a single PDU are sent in a segmented SMS
-	message which is reassembled inside the SMS Stack; the SMS Stack always passes the WAP stack
-	a single CSmsMessage containing a single WAP message regardless of the message length.
-	The WAP stack can receive 7 Bit WAP datagrams either as a single CSmsMessage or as a number of CSmsMessages
-	which need to be reassembled into a single WAP message by the WAP stack.  The latter method is provided to maintain backward
-	compatibility with early versions of the WAP stack which were implemented before the concatenation function was
-	available in the SMS stack.*/
-
-	/* 160 is the maximum number of character that can be fitted in a single PDU using 7 bit encoding */
-	if((iUserDataSettings.Alphabet()== TSmsDataCodingScheme::ESmsAlphabet8Bit) ||
-	(iUserDataSettings.Alphabet()== TSmsDataCodingScheme::ESmsAlphabet7Bit && iBuffer->Length()>160 ))
-		{
-		iSegment = new (ELeave)TWapTextMessage(*iBuffer);
-		}
-	else if (iBuffer->Length()<=160)
-        {
-        iSmsBuffer = *iBuffer;
-		iSegment = new (ELeave)TWapTextMessage(iSmsBuffer);
-        iIsTextHeader = iSegment->Parse();
-
-        if (iIsTextHeader)
-            {
-            iFromPort = iSegment->SourcePort(&i16BitPorts);
-            iToPort = iSegment->DestinationPort(&i16BitPorts);
-            iReference = iSegment->ReferenceNumber();
-            iTotalSegments = iSegment->TotalSegments();
-            iSegmentNumber = iSegment->SegmentNumber();
-            }
-        }
-	else
-		{
-        delete iSegment;
-        iSegment = 0;
-		}
-     } // CWapDatagram::GetDatagramSettingsL
-
-
-//
-// Set WAP datagram private members from information element structures
-//
-void CWapDatagram::GetDatagramSettings(const CSmsMessage& aSms)
-    {
-    LOGWAPPROT1("CWapDatagram::GetDatagramSettings()");
-
-    const CSmsPDU& Pdu = aSms.SmsPDU();
-
-    __ASSERT_DEBUG(Pdu.Type()==CSmsPDU::ESmsDeliver || Pdu.Type()==CSmsPDU::ESmsSubmit, // this line is testing purposes only
-			Panic(KPanicUsageError));
-
-    aSms.UserDataSettings(iUserDataSettings);
-
-    Pdu.ApplicationPortAddressing(iToPort,iFromPort,&i16BitPorts);
-    if (iFromPort == (-1))
-        iFromPort = iToPort;
-
-    // From WAP datagram point of view following numbers are applicable
-    iReference = 0;
-    iTotalSegments = 1;
-    iSegmentNumber = 1;
-
-    iFromAddress = aSms.ToFromAddress();
-    iToAddress = KNullDesC;
-    iTime = aSms.Time();
-
-    TBool result = SetUTCOffset(aSms.UTCOffset());
-    __ASSERT_DEBUG(result, Panic(KPanicSmsMsgTimeZoneOutOfRange));
-    } // CWapDatagram::GetDatagramSettings
-
-
-//
-// Set Alphabet information of iUserDataSettings before calling the method
-// Converts from 7/8-bit to UNICODE
-//
-void CWapDatagram::ConvertL(const TDesC8& aNarrowChars,CSmsBufferBase& aSmsBuffer) const
-    {
-    LOGWAPPROT1("CWapDatagram::ConvertL()");
-
-	// Convert the data in segments of specified max size
-	const TInt KMaxSegmentSize=CSmsBufferBase::EMaxBufLength;
-
-	// Create converter and reassembler
-	RFs fs;
-	CCnvCharacterSetConverter* charConv=CCnvCharacterSetConverter::NewLC();
-	CSmsAlphabetConverter* converter=CSmsAlphabetConverter::NewLC(*charConv,fs,iUserDataSettings.Alphabet(),ETrue);
-	TSmsBufferReassembler reassembler(*converter,aSmsBuffer);
-
-	// Rassemble
-	TInt elementsRemaining=aNarrowChars.Length();
-	while (elementsRemaining)
-		{
-		TInt segmentLength=Min(KMaxSegmentSize,elementsRemaining);
-		TPtrC8 ptr(aNarrowChars.Ptr()+aNarrowChars.Length()-elementsRemaining,segmentLength);
-		reassembler.ReassembleNextL(ptr, ESmsEncodingNone,
-									elementsRemaining==segmentLength);
-		elementsRemaining-=segmentLength;
-		}
-
-	CleanupStack::PopAndDestroy(2);	// charConv,
-    } // CWapDatagram::ConvertL
-
-
-//
-// Converts from UNICODE to 7/8-bit
-//
-void CWapDatagram::ConvertL(const CSmsBufferBase& aSmsBuffer,HBufC8** aNarrowChars) const
-    {
-    LOGWAPPROT1("CWapDatagram::ConvertL()");
-
-	// Convert the data in segments of specified max size
-	const TInt KMaxSegmentSize=CSmsBufferBase::EMaxBufLength;
-
-	// Delete the existing buffer
-	if (*aNarrowChars)
-		{
-		delete *aNarrowChars;
-		*aNarrowChars=NULL;
-		}
-
-	// Create converter and segmenter
-	RFs fs;
-	CCnvCharacterSetConverter* charConv=CCnvCharacterSetConverter::NewLC();
-	CSmsAlphabetConverter* converter=CSmsAlphabetConverter::NewLC(*charConv,fs,iUserDataSettings.Alphabet(),ETrue);
-	CSmsBufferSegmenter* segmenter=CSmsBufferSegmenter::NewLC(*converter,aSmsBuffer,KMaxSegmentSize);
-
-	// Create a new buffer based on converted length
-	TInt convertedLength=segmenter->TotalConvertedLengthL(ESmsEncodingNone);
-	*aNarrowChars=HBufC8::NewMaxL(((convertedLength+KMaxSegmentSize-1)/KMaxSegmentSize)*KMaxSegmentSize);
-	TPtr8 narrowPtr=(*aNarrowChars)->Des();
-
-	// Now do the conversion
-	TInt elementsConverted=0;
-	TInt unconvertedChars=0;
-	TInt downgradedChars=0;
-	TBool complete=EFalse;
-	while (elementsConverted<convertedLength)
-		{
-		__ASSERT_DEBUG(elementsConverted<convertedLength,Panic(KPanicTooLongData));
-		TPtr8 ptr((TUint8*)narrowPtr.Ptr()+elementsConverted,0,KMaxSegmentSize);
-		complete=segmenter->SegmentNextL(ptr, unconvertedChars, downgradedChars, ESmsEncodingNone);
-		elementsConverted+=ptr.Length();
-		}
-    if((!complete || (convertedLength!=elementsConverted)) &&  convertedLength)
-        User::Leave( KErrCorrupt );
-	narrowPtr.SetLength(convertedLength);
-
-	CleanupStack::PopAndDestroy(3);	// charConv,converter,segmenter
-    } // CWapDatagram::ConvertL
-
-
-void CWapDatagram::SetSmsMessageSettingsL(CSmsMessage& aSmsMessage, TBool aSetPorts)
-    {
-    LOGWAPPROT1("CWapDatagram::SetSmsMessageSettingsL()");
-
-    CSmsPDU& Pdu = aSmsMessage.SmsPDU();
-
-    aSmsMessage.SetToFromAddressL(iToAddress);
-    aSmsMessage.SetUserDataSettingsL(iUserDataSettings);
-    aSmsMessage.SetTime(iTime);
-
-    TBool result = aSmsMessage.SetUTCOffset(iUTCOffset);
-    __ASSERT_DEBUG(result, Panic(KPanicWapDgrmTimeZoneOutOfRange));
-    
-    if (aSetPorts)
-        {
-        if (iFromPort == (-1))
-            iFromPort = iToPort;
-
-        // Determine whether long or short form is used
-        if (iFromPort > 255 || iToPort>255)
-            i16BitPorts = ETrue;
-
-	    Pdu.SetApplicationPortAddressingL(ETrue,iToPort,iFromPort,i16BitPorts);
-		// WAP implementation guidelines recommend DCS of 0x15, however
-		// some gateways / SCs will only accept DCS 0xf5
-		Pdu.SetBits7To4(TSmsDataCodingScheme::ESmsDCSTextUncompressed7BitOr8Bit);
-		Pdu.SetAlphabet(TSmsDataCodingScheme::ESmsAlphabet8Bit);
-		Pdu.SetClass(ETrue,TSmsDataCodingScheme::ESmsClass1);
-        }
-    } // CWapDatagram::SetSmsMessageSettingsL
-
-
-CWapDatagram::CWapDatagram():
-    iUserDataSettings(),
-    iToAddress(KNullDesC),
-    iFromAddress(KNullDesC),
-    i16BitPorts(EFalse),
-    iFromPort(-1),
-    iToPort(-1),
-    iTime(),
-    iUTCOffset(0),
-    iIsComplete(EFalse),
-    iReference(0),
-    iTotalSegments(0),
-    iSegmentNumber(0),
-    iIsTextHeader(EFalse),
-    iSegment(NULL),
-    iSmsBuffer(KNullDesC8),
-    iBuffer(NULL),
-    iSendBuffer(KNullDesC8),
-    iOtherHeader(KNullDesC8),
-    iLogServerId(0),
-    iVersionNumber(EBaseVersion),// Set version number to EBaseVersion by default.
-    iSpare1(0),
-    iSpare2(0),
-    iSpare3(0),
-    iRecvbuf(NULL)
-    {
-    iTime.UniversalTime();
-
-    TBool result = SetUTCOffset(User::UTCOffset());
-   __ASSERT_DEBUG(result, Panic(KPanicUserSuppliedTimeZoneOutOfRange));
-
-    iUserDataSettings.SetAlphabet(TSmsDataCodingScheme::ESmsAlphabet8Bit);
-    __DECLARE_NAME(_S("CWapDatagram"));
-    } // CWapDatagram::CWapDatagram
-
-
-//
-// Return the location of the link
-//
-TInt CWapDatagram::LinkOffset()
-	{
-	LOGWAPPROT1("CWapDatagram::LinkOffset()");
-
-
-	return _FOFF(CWapDatagram,iLink);
-	} // CWapDatagram::LinkOffset
-
-
-TBool CWapDatagram::SetUTCOffset(const TTimeIntervalSeconds& aUTCOffset)
-    {
-    LOGWAPPROT1("CWapDatagram::SetUTCOffset()");
-
-    TBool rc = ETrue;
-    TInt utcOffset = aUTCOffset.Int();
-
-    if ((utcOffset <=  CSmsMessage::EMaximumSeconds) &&
-        (utcOffset >= -CSmsMessage::EMaximumSeconds))
-       {
-       iUTCOffset = utcOffset;
-       }
-    else
-       {
-       LOGWAPPROT2("CWapDatagram:SetUTCOffset offset [out of range] = %d",utcOffset);
-       rc = EFalse;
-       }
-
-    return rc;
-    } // CWapDatagram::SetUTCOffset
-    
-
-
-CBufFlat* CWapDatagram::SmsExternalisedStream() const
-	{
-	return iRecvbuf;
-	}
+// Copyright (c) 1997-2009 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:
+//
+
+#include "gsmubuf.h"
+#include "gsmuset.h"
+#include "Gsmuelem.h"
+#include "Gsmumsg.h"
+#include "gsmusar.h"
+#include "gsmupdu.h"
+#include "WAPDGRM.H"
+#include "ws_main.h"
+#include "smsstackutils.h"
+
+//
+// For incoming short message
+//
+CWapDatagram* CWapDatagram::NewL(const CSmsMessage& aSms)
+    {
+    LOGWAPPROT2("CWapDatagram::NewL(): aSms=0x%08x", (TInt) &aSms);
+
+    CWapDatagram* datagram = new (ELeave)CWapDatagram();
+
+    CleanupStack::PushL(datagram);
+    datagram->ConstructL(aSms);
+    CleanupStack::Pop();
+
+    LOGWAPPROT2("CWapDatagram::NewL(): iFromPort: %d", datagram->iFromPort);
+    LOGWAPPROT2("CWapDatagram::NewL(): iToPort: %d", datagram->iToPort);
+    LOGWAPPROT2("CWapDatagram::NewL(): iReference: %d", datagram->iReference);
+    LOGWAPPROT2("CWapDatagram::NewL(): iTotalSegments: %d", datagram->iTotalSegments);
+    LOGWAPPROT2("CWapDatagram::NewL(): iSegmentNumber: %d", datagram->iSegmentNumber);
+    LOGWAPPROT2("CWapDatagram::NewL(): iIsComplete: %d", datagram->iIsComplete);
+    LOGWAPPROT2("CWapDatagram::NewL(): iReference: %d", datagram->iReference);
+    LOGWAPPROT2("CWapDatagram::NewL(): iIsTextHeader: %d", datagram->iIsTextHeader);
+    LOGWAPPROT2("CWapDatagram::NewL(): iLogServerId: %d", datagram->iLogServerId);
+    LOGWAPPROT2("CWapDatagram::NewL(): i16BitPorts: %d", datagram->i16BitPorts);
+
+    // assert destination port
+	if (datagram->i16BitPorts)
+		{
+		if (datagram->iToPort>=0  &&  datagram->iToPort<=65535)
+			{
+			LOGWAPPROT1("iToPort OK");
+			}
+		else
+			{
+			LOGWAPPROT1("iToPort FAILED");
+			}
+		}
+    else
+		{
+        if (datagram->iToPort>=0  &&  datagram->iToPort<=255)
+			{
+		    LOGWAPPROT1("iToPort OK");
+			}
+		else
+			{
+			LOGWAPPROT1("iToPort FAILED");
+			}
+		}
+
+	if (datagram->i16BitPorts)
+		{
+		if (datagram->iFromPort>=0  &&  datagram->iFromPort<=65535)
+			{
+			LOGWAPPROT1("iFromPort OK");
+			}
+		else
+			{
+			LOGWAPPROT1("iFromPort FAILED");
+			}
+		}
+    else
+		{
+        if (datagram->iFromPort>=0  &&  datagram->iFromPort<=255)
+			{
+		    LOGWAPPROT1("iFromPort OK");
+			}
+		else
+			{
+			LOGWAPPROT1("iFromPort FAILED");
+			}
+		}
+
+    return datagram;
+    } // CWapDatagram::NewL
+
+
+//
+// For outgoing short messages
+//
+CWapDatagram* CWapDatagram::NewL(const TDesC8& aSendBuffer)
+    {
+    LOGWAPPROT2("CWapDatagram::NewL(): aSendBuffer=0x%08x", (TInt) &aSendBuffer);
+
+    CWapDatagram* datagram = new (ELeave)CWapDatagram();
+
+    CleanupStack::PushL(datagram);
+    datagram->Construct(aSendBuffer);
+    CleanupStack::Pop();
+
+    return datagram;
+    } // CWapDatagram::NewL
+
+
+CWapDatagram::~CWapDatagram()
+    {
+    LOGWAPPROT1("CWapDatagram::~CWapDatagram()");
+
+	delete iRecvbuf;
+    delete iBuffer;
+    delete iSegment;
+    } // CWapDatagram::~CWapDatagram
+
+
+//
+// What about service centre address ?
+// aSmsMessageArray contains CSmsMessage objects
+//
+void CWapDatagram::EncodeConcatenatedMessagesL(RFs& aFs, CArrayPtr<CSmsMessage>& aSmsMessageArray)
+    {
+    LOGWAPPROT2("CWapDatagram::EncodeConcatenatedMessagesL(): %d messages", aSmsMessageArray.Count());
+
+    // Couple of checkings makes sense
+    __ASSERT_DEBUG(iToPort >=0 && iToAddress.Length()>=0
+            && (iUserDataSettings.Alphabet()==TSmsDataCodingScheme::ESmsAlphabet8Bit
+                 || iUserDataSettings.Alphabet()==TSmsDataCodingScheme::ESmsAlphabet7Bit),
+            Panic(KPanicUsageError));
+
+    // Determine CSmsMessage encoding by character width
+    if (iUserDataSettings.Alphabet() == TSmsDataCodingScheme::ESmsAlphabet8Bit)
+        {
+        CSmsBufferBase* SmsBuffer = CSmsBuffer::NewL();
+
+        CleanupStack::PushL(SmsBuffer);
+        ConvertL(iSendBuffer,*SmsBuffer);
+        CleanupStack::Pop(); // SmsBuffer, popped here since it is pushed again in the following NewL call
+        CSmsMessage* SmsMessage = CSmsMessage::NewL(aFs, CSmsPDU::ESmsSubmit,SmsBuffer,EFalse);
+        CleanupStack::PushL(SmsMessage);
+        // one and only object
+        aSmsMessageArray.AppendL(SmsMessage);
+        CleanupStack::Pop(); // SmsMessage
+
+        SetSmsMessageSettingsL(*SmsMessage,ETrue);
+        }
+    else
+        {
+        // contruct TWapTextMessage object
+        TWapTextMessage* Segment = new (ELeave) TWapTextMessage(KNullDesC8);
+        CleanupStack::PushL(Segment);
+        CArrayPtrFlat<HBufC8>* SegmentArray = new (ELeave) CArrayPtrFlat<HBufC8> (8);
+        CleanupStack::PushL(SegmentArray);
+		// coverity[double_push]
+        CleanupResetAndDestroyPushL(*SegmentArray);
+
+        Segment->SetDestinationPort(iToPort,i16BitPorts);
+        Segment->SetSourcePort(iFromPort,i16BitPorts);
+        Segment->SetReferenceNumber(iReference);
+        Segment->SetUserData(iSendBuffer);
+        Segment->SetOtherHeader(iOtherHeader);
+        Segment->EncodeSegmentsL(*SegmentArray);
+
+        // contruct array of CSmsMessages
+        TInt Count = SegmentArray->Count();
+        for (TInt i=0; i<Count; i++)
+            {
+            CSmsBufferBase* SmsBuffer = CSmsBuffer::NewL();
+
+            CleanupStack::PushL(SmsBuffer);
+            ConvertL(*(SegmentArray->At(i)),*SmsBuffer);
+            CleanupStack::Pop(); // SmsBuffer, popped here since it is pushed again in the following NewL call
+            CSmsMessage* SmsMessage=CSmsMessage::NewL(aFs, CSmsPDU::ESmsSubmit,SmsBuffer,EFalse);
+            CleanupStack::PushL(SmsMessage);
+            aSmsMessageArray.AppendL(SmsMessage);
+            CleanupStack::Pop(); // SmsMessage
+
+            SetSmsMessageSettingsL(*SmsMessage,EFalse);
+            }
+        CleanupStack::PopAndDestroy(3, Segment);  // SegmentArray elements (Reset and Destroy), SegmentArray, Segment
+
+        }
+    } // CWapDatagram::EncodeConcatenatedMessagesL
+
+void CWapDatagram::DecodeConcatenatedMessagesL(CArrayPtr<TSegmentData>& aSmsMessageArray)
+    {
+    LOGWAPPROT1("CWapDatagram::DecodeConcatenatedMessagesL()");
+
+    // The TSegmentData elements are in the random order in the array
+    TInt Count = aSmsMessageArray.Count();
+    TInt i=0;
+
+    if (Count > 0)
+        {
+        TInt DataLength = 0;  // total length of data
+        TInt TempLength = 0;
+
+        // Every TSegmentData should be equal length except last segment
+        // Use that 'constant' segment length as indexes
+        // Count the actual data length
+        for(i=0; i<Count; i++)
+            {
+            TempLength = aSmsMessageArray.At(i)->iData.Length();
+            DataLength += TempLength;
+            }
+
+        TSegmentData* Segment = NULL;
+
+        if (iBuffer)
+            {
+            delete iBuffer;
+            iBuffer = NULL;
+            }
+        iBuffer = HBufC8::NewL(DataLength );
+
+        TPtr8 BufferPtr(iBuffer->Des());
+        BufferPtr.SetLength(DataLength );
+
+        TInt segmentStartPosition=0;
+
+        for(i=0; i<Count; i++)
+            {
+              if (segmentStartPosition >= DataLength)  
+                  {
+                  // Once the start position is out of range,
+                  // there is no point in continuing reconstructing the
+                  // wapdatagram.
+                  break;
+				 }			
+			
+            Segment = aSmsMessageArray.At(i);
+			TPtr8 CopyBufferPtr(&(BufferPtr[segmentStartPosition]),0,160);
+			CopyBufferPtr.Copy(Segment->iData);
+ 			segmentStartPosition+=Segment->iData.Length();
+            }
+        }
+    iIsComplete = ETrue;
+    } // CWapDatagram::DecodeConcatenatedMessagesL
+
+
+void CWapDatagram::InternalizeL(RReadStream& aStream)
+    {
+    aStream >> iUserDataSettings;
+    aStream >> iToAddress;
+    iToPort = aStream.ReadInt32L();
+    aStream >> iFromAddress;
+    iFromPort = aStream.ReadInt32L();
+    TInt64 time;
+    aStream >> time;
+    iTime = time;
+    iUTCOffset = aStream.ReadInt32L();
+    iIsTextHeader = aStream.ReadInt32L();
+    iReference = aStream.ReadInt32L();
+    iTotalSegments = aStream.ReadInt32L();
+    iSegmentNumber = aStream.ReadInt32L();
+    iLogServerId = aStream.ReadInt32L();
+    iVersionNumber = aStream.ReadInt32L();
+    iSpare1 =  aStream.ReadInt32L();
+    iSpare2 =  aStream.ReadInt32L();
+    iSpare3 =  aStream.ReadInt32L();
+	
+    // Required for version 1, which is reading and internalizing extra SMS parameters from stream
+    if(iVersionNumber == EFirstVersion)
+    	{
+    	TInt length = aStream.ReadInt32L();
+    	if(length>0)
+    		{
+    		HBufC8* smsBuffer=HBufC8::NewMaxLC(length);
+			TPtr8 recvbuftmp = smsBuffer->Des();
+			aStream >> recvbuftmp;
+			if(!iRecvbuf)
+				{
+				iRecvbuf = CBufFlat::NewL(KSmsBufferExpansion);
+				}
+			iRecvbuf->ResizeL(recvbuftmp.Size());
+			iRecvbuf->Write(0, recvbuftmp);
+			CleanupStack::PopAndDestroy(smsBuffer);
+			}
+    	}
+    
+    } // CWapDatagram::InternalizeL
+
+
+//
+//	Reads iBuffer from stream (for 8Bit messages)
+//
+void CWapDatagram::InternalizeBufferL(RReadStream& aStream)
+	{
+	TInt length;
+	length=aStream.ReadInt32L();
+	iBuffer=HBufC8::NewMaxL(length);
+	TPtr8 tmp = iBuffer->Des();
+	aStream >> tmp;
+	iIsComplete = ETrue;
+	}
+
+
+void CWapDatagram::ExternalizeL(RWriteStream& aStream) const
+    {
+    aStream << iUserDataSettings;
+    aStream << iToAddress;
+    aStream.WriteInt32L(iToPort);
+
+    aStream << iFromAddress;
+    aStream.WriteInt32L(iFromPort);
+    aStream << iTime.Int64();
+    aStream.WriteInt32L(iUTCOffset.Int());
+
+    aStream.WriteInt32L(iIsTextHeader);
+    aStream.WriteInt32L(iReference);
+    aStream.WriteInt32L(iTotalSegments);
+    aStream.WriteInt32L(iSegmentNumber);
+
+    aStream.WriteInt32L(iLogServerId);
+
+    aStream.WriteInt32L(iVersionNumber);
+    aStream.WriteInt32L(iSpare1);
+    aStream.WriteInt32L(iSpare2);
+    aStream.WriteInt32L(iSpare3);
+	
+	// Externalizing the SMS params if exists
+	if(iRecvbuf)
+		{
+		TPtr8 recvbuftmp = iRecvbuf->Ptr(0);
+		aStream.WriteInt32L(recvbuftmp.Length());
+		aStream << recvbuftmp;
+		}
+	else
+		{
+		aStream.WriteInt32L(0);
+		}
+    }
+
+
+//
+// writes iBuffer to writeStream for 8-bit incomming messages
+//
+void CWapDatagram::ExternalizeBufferL(RWriteStream& aStream) const
+	{
+	TInt length= WapDatagramLength();
+	aStream.WriteInt32L(length);
+	TPtr8 tmp= iBuffer->Des();
+	aStream << tmp;
+
+	} // CWapDatagram::ExternalizeBufferL
+
+
+//
+// Outgoing
+//
+void CWapDatagram::Construct(const TDesC8& aSendBuffer)
+    {
+    LOGWAPPROT1("CWapDatagram::Construct()");
+	
+	// Set version number to 1, as we have had to make 
+	// changes to CWapDatagram for CR0929
+	iVersionNumber = EFirstVersion;
+	
+    iSendBuffer.Set(aSendBuffer);
+    } // CWapDatagram::Construct
+
+
+//
+// Incoming
+// code actualy supports 7-bit characters and port numbers
+// encoded in information elements (IE) although it is not
+// a requirement
+//
+void CWapDatagram::ConstructL(const CSmsMessage& aSms)
+    {
+    LOGWAPPROT1("CWapDatagram::ConstructL()");
+
+	// Set version number to 1, as we have had to make 
+	// changes to CWapDatagram for CR0929
+	iVersionNumber = EFirstVersion;
+
+	iRecvbuf = CBufFlat::NewL(KSmsBufferExpansion);
+
+	RBufWriteStream writestream(*iRecvbuf);
+	writestream.Open(*iRecvbuf);
+	CleanupClosePushL(writestream);
+	
+	// Externalizing everything within CSMSMessage except buffer
+	aSms.ExternalizeWithoutBufferL(writestream);
+	
+	CleanupStack::PopAndDestroy();  //  writestream
+
+	iRecvbuf->Compress();
+
+    const CSmsBufferBase& SmsBufferBase = aSms.Buffer();
+
+    GetDatagramSettings(aSms);
+
+    // Get the data from CSmsMessage and convert
+    // SmsBuffer store Unicode short message from CSmsMessage
+    ConvertL(SmsBufferBase,&iBuffer);
+	GetDatagramSettingsL();
+
+    iIsComplete = ETrue;
+    if (iUserDataSettings.Alphabet() == TSmsDataCodingScheme::ESmsAlphabet7Bit)
+        {
+        // this is a good candidate to include a text header.
+        if (iIsTextHeader)
+            {
+            // there is still a minor chance that message is complete:
+            // one fragment long datagram
+            if (iTotalSegments == 1)
+                {
+                // Get the segment data
+                TPtr8 PtrNarrow = iBuffer->Des();
+                PtrNarrow.Zero();
+                iSegment->UserData(PtrNarrow);
+                }
+            else
+                {
+                iIsComplete = EFalse;
+                // delete incomplete message from iBuffer;
+                delete iBuffer;
+                iBuffer = 0;
+                }
+            }
+        else
+            // This means that IEs with 7-bits are used
+            // Happily we support it
+            iIsComplete = ETrue;
+
+        }
+    } // CWapDatagram::ConstructL
+
+
+//
+// Set WAP datagram private members from a text based concatenated message
+// Copies contents of iBuffer to iSmsBuffer
+// Allocates iSegment object
+//
+void CWapDatagram::GetDatagramSettingsL()
+    {
+    LOGWAPPROT1("CWapDatagram::GetDatagramSettingsL()");
+
+	/* The WAP stack always receives 8 bit WAP datagrams from the SMS Stack as a single CSmsMessage.
+	This is because 8 bit WAP messages which cannot be encoded into a single PDU are sent in a segmented SMS
+	message which is reassembled inside the SMS Stack; the SMS Stack always passes the WAP stack
+	a single CSmsMessage containing a single WAP message regardless of the message length.
+	The WAP stack can receive 7 Bit WAP datagrams either as a single CSmsMessage or as a number of CSmsMessages
+	which need to be reassembled into a single WAP message by the WAP stack.  The latter method is provided to maintain backward
+	compatibility with early versions of the WAP stack which were implemented before the concatenation function was
+	available in the SMS stack.*/
+
+	/* 160 is the maximum number of character that can be fitted in a single PDU using 7 bit encoding */
+	if((iUserDataSettings.Alphabet()== TSmsDataCodingScheme::ESmsAlphabet8Bit) ||
+	(iUserDataSettings.Alphabet()== TSmsDataCodingScheme::ESmsAlphabet7Bit && iBuffer->Length()>160 ))
+		{
+		iSegment = new (ELeave)TWapTextMessage(*iBuffer);
+		}
+	else if (iBuffer->Length()<=160)
+        {
+        iSmsBuffer = *iBuffer;
+		iSegment = new (ELeave)TWapTextMessage(iSmsBuffer);
+        iIsTextHeader = iSegment->Parse();
+
+        if (iIsTextHeader)
+            {
+            iFromPort = iSegment->SourcePort(&i16BitPorts);
+            iToPort = iSegment->DestinationPort(&i16BitPorts);
+            iReference = iSegment->ReferenceNumber();
+            iTotalSegments = iSegment->TotalSegments();
+            iSegmentNumber = iSegment->SegmentNumber();
+            }
+        }
+	else
+		{
+        delete iSegment;
+        iSegment = 0;
+		}
+     } // CWapDatagram::GetDatagramSettingsL
+
+
+//
+// Set WAP datagram private members from information element structures
+//
+void CWapDatagram::GetDatagramSettings(const CSmsMessage& aSms)
+    {
+    LOGWAPPROT1("CWapDatagram::GetDatagramSettings()");
+
+    const CSmsPDU& Pdu = aSms.SmsPDU();
+
+    __ASSERT_DEBUG(Pdu.Type()==CSmsPDU::ESmsDeliver || Pdu.Type()==CSmsPDU::ESmsSubmit, // this line is testing purposes only
+			Panic(KPanicUsageError));
+
+    aSms.UserDataSettings(iUserDataSettings);
+
+    Pdu.ApplicationPortAddressing(iToPort,iFromPort,&i16BitPorts);
+    if (iFromPort == (-1))
+        iFromPort = iToPort;
+
+    // From WAP datagram point of view following numbers are applicable
+    iReference = 0;
+    iTotalSegments = 1;
+    iSegmentNumber = 1;
+
+    iFromAddress = aSms.ToFromAddress();
+    iToAddress = KNullDesC;
+    iTime = aSms.Time();
+
+    TBool result = SetUTCOffset(aSms.UTCOffset());
+    __ASSERT_DEBUG(result, Panic(KPanicSmsMsgTimeZoneOutOfRange));
+    } // CWapDatagram::GetDatagramSettings
+
+
+//
+// Set Alphabet information of iUserDataSettings before calling the method
+// Converts from 7/8-bit to UNICODE
+//
+void CWapDatagram::ConvertL(const TDesC8& aNarrowChars,CSmsBufferBase& aSmsBuffer) const
+    {
+    LOGWAPPROT1("CWapDatagram::ConvertL()");
+
+	// Convert the data in segments of specified max size
+	const TInt KMaxSegmentSize=CSmsBufferBase::EMaxBufLength;
+
+	// Create converter and reassembler
+	RFs fs;
+	CCnvCharacterSetConverter* charConv=CCnvCharacterSetConverter::NewLC();
+	CSmsAlphabetConverter* converter=CSmsAlphabetConverter::NewLC(*charConv,fs,iUserDataSettings.Alphabet(),ETrue);
+	TSmsBufferReassembler reassembler(*converter,aSmsBuffer);
+
+	// Rassemble
+	TInt elementsRemaining=aNarrowChars.Length();
+	while (elementsRemaining)
+		{
+		TInt segmentLength=Min(KMaxSegmentSize,elementsRemaining);
+		TPtrC8 ptr(aNarrowChars.Ptr()+aNarrowChars.Length()-elementsRemaining,segmentLength);
+		reassembler.ReassembleNextL(ptr, ESmsEncodingNone,
+									elementsRemaining==segmentLength);
+		elementsRemaining-=segmentLength;
+		}
+
+	CleanupStack::PopAndDestroy(2);	// charConv,
+    } // CWapDatagram::ConvertL
+
+
+//
+// Converts from UNICODE to 7/8-bit
+//
+void CWapDatagram::ConvertL(const CSmsBufferBase& aSmsBuffer,HBufC8** aNarrowChars) const
+    {
+    LOGWAPPROT1("CWapDatagram::ConvertL()");
+
+	// Convert the data in segments of specified max size
+	const TInt KMaxSegmentSize=CSmsBufferBase::EMaxBufLength;
+
+	// Delete the existing buffer
+	if (*aNarrowChars)
+		{
+		delete *aNarrowChars;
+		*aNarrowChars=NULL;
+		}
+
+	// Create converter and segmenter
+	RFs fs;
+	CCnvCharacterSetConverter* charConv=CCnvCharacterSetConverter::NewLC();
+	CSmsAlphabetConverter* converter=CSmsAlphabetConverter::NewLC(*charConv,fs,iUserDataSettings.Alphabet(),ETrue);
+	CSmsBufferSegmenter* segmenter=CSmsBufferSegmenter::NewLC(*converter,aSmsBuffer,KMaxSegmentSize);
+
+	// Create a new buffer based on converted length
+	TInt convertedLength=segmenter->TotalConvertedLengthL(ESmsEncodingNone);
+	*aNarrowChars=HBufC8::NewMaxL(((convertedLength+KMaxSegmentSize-1)/KMaxSegmentSize)*KMaxSegmentSize);
+	TPtr8 narrowPtr=(*aNarrowChars)->Des();
+
+	// Now do the conversion
+	TInt elementsConverted=0;
+	TInt unconvertedChars=0;
+	TInt downgradedChars=0;
+	TBool complete=EFalse;
+	while (elementsConverted<convertedLength)
+		{
+		__ASSERT_DEBUG(elementsConverted<convertedLength,Panic(KPanicTooLongData));
+		TPtr8 ptr((TUint8*)narrowPtr.Ptr()+elementsConverted,0,KMaxSegmentSize);
+		complete=segmenter->SegmentNextL(ptr, unconvertedChars, downgradedChars, ESmsEncodingNone);
+		elementsConverted+=ptr.Length();
+		}
+    if((!complete || (convertedLength!=elementsConverted)) &&  convertedLength)
+        User::Leave( KErrCorrupt );
+	narrowPtr.SetLength(convertedLength);
+
+	CleanupStack::PopAndDestroy(3);	// charConv,converter,segmenter
+    } // CWapDatagram::ConvertL
+
+
+void CWapDatagram::SetSmsMessageSettingsL(CSmsMessage& aSmsMessage, TBool aSetPorts)
+    {
+    LOGWAPPROT1("CWapDatagram::SetSmsMessageSettingsL()");
+
+    CSmsPDU& Pdu = aSmsMessage.SmsPDU();
+
+    aSmsMessage.SetToFromAddressL(iToAddress);
+    aSmsMessage.SetUserDataSettingsL(iUserDataSettings);
+    aSmsMessage.SetTime(iTime);
+
+    TBool result = aSmsMessage.SetUTCOffset(iUTCOffset);
+    __ASSERT_DEBUG(result, Panic(KPanicWapDgrmTimeZoneOutOfRange));
+    
+    if (aSetPorts)
+        {
+        if (iFromPort == (-1))
+            iFromPort = iToPort;
+
+        // Determine whether long or short form is used
+        if (iFromPort > 255 || iToPort>255)
+            i16BitPorts = ETrue;
+
+	    Pdu.SetApplicationPortAddressingL(ETrue,iToPort,iFromPort,i16BitPorts);
+		// WAP implementation guidelines recommend DCS of 0x15, however
+		// some gateways / SCs will only accept DCS 0xf5
+		Pdu.SetBits7To4(TSmsDataCodingScheme::ESmsDCSTextUncompressed7BitOr8Bit);
+		Pdu.SetAlphabet(TSmsDataCodingScheme::ESmsAlphabet8Bit);
+		Pdu.SetClass(ETrue,TSmsDataCodingScheme::ESmsClass1);
+        }
+    } // CWapDatagram::SetSmsMessageSettingsL
+
+
+CWapDatagram::CWapDatagram():
+    iUserDataSettings(),
+    iToAddress(KNullDesC),
+    iFromAddress(KNullDesC),
+    i16BitPorts(EFalse),
+    iFromPort(-1),
+    iToPort(-1),
+    iTime(),
+    iUTCOffset(0),
+    iIsComplete(EFalse),
+    iReference(0),
+    iTotalSegments(0),
+    iSegmentNumber(0),
+    iIsTextHeader(EFalse),
+    iSegment(NULL),
+    iSmsBuffer(KNullDesC8),
+    iBuffer(NULL),
+    iSendBuffer(KNullDesC8),
+    iOtherHeader(KNullDesC8),
+    iLogServerId(0),
+    iVersionNumber(EBaseVersion),// Set version number to EBaseVersion by default.
+    iSpare1(0),
+    iSpare2(0),
+    iSpare3(0),
+    iRecvbuf(NULL)
+    {
+    iTime.UniversalTime();
+
+    TBool result = SetUTCOffset(User::UTCOffset());
+   __ASSERT_DEBUG(result, Panic(KPanicUserSuppliedTimeZoneOutOfRange));
+
+    iUserDataSettings.SetAlphabet(TSmsDataCodingScheme::ESmsAlphabet8Bit);
+    __DECLARE_NAME(_S("CWapDatagram"));
+    } // CWapDatagram::CWapDatagram
+
+
+//
+// Return the location of the link
+//
+TInt CWapDatagram::LinkOffset()
+	{
+	LOGWAPPROT1("CWapDatagram::LinkOffset()");
+
+
+	return _FOFF(CWapDatagram,iLink);
+	} // CWapDatagram::LinkOffset
+
+
+TBool CWapDatagram::SetUTCOffset(const TTimeIntervalSeconds& aUTCOffset)
+    {
+    LOGWAPPROT1("CWapDatagram::SetUTCOffset()");
+
+    TBool rc = ETrue;
+    TInt utcOffset = aUTCOffset.Int();
+
+    if ((utcOffset <=  CSmsMessage::EMaximumSeconds) &&
+        (utcOffset >= -CSmsMessage::EMaximumSeconds))
+       {
+       iUTCOffset = utcOffset;
+       }
+    else
+       {
+       LOGWAPPROT2("CWapDatagram:SetUTCOffset offset [out of range] = %d",utcOffset);
+       rc = EFalse;
+       }
+
+    return rc;
+    } // CWapDatagram::SetUTCOffset
+    
+
+
+CBufFlat* CWapDatagram::SmsExternalisedStream() const
+	{
+	return iRecvbuf;
+	}