smsprotocols/smsstack/wapprot/Src/wapthdr.cpp
branchopencode
changeset 24 6638e7f4bd8f
parent 0 3553901f7fa8
--- a/smsprotocols/smsstack/wapprot/Src/wapthdr.cpp	Mon May 03 13:37:20 2010 +0300
+++ b/smsprotocols/smsstack/wapprot/Src/wapthdr.cpp	Thu May 06 15:10:38 2010 +0100
@@ -1,600 +1,600 @@
-// 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:
-// This file contains the implementation of the TWapTextMessage.
-// TWapTextMessage encodes and decodes 7-bit WAP text headers
-// 
-//
-
-/**
- @file
-*/
-
-#include <e32std.h>
-#include "wapthdr.h"
-#include "ws_main.h"
-
-const TInt TWapTextMessage::KHeaderCount = 6;
-
-_LIT8(KSCKHeaderLong, "//SCKL"); // standard NBS header for 16-bit adresses
-_LIT8(KSCKHeaderShort,"//SCK");  // standard NBS header for 8-bit adresses
-
-
-/**
- *  Indices into different types header for each of the header elements
- *  (dest port, source port, reference, total segments, current segment)
- */
-const TWapTextMessage::TIndexInfo TWapTextMessage::KElemIndexes[TWapTextMessage::KHeaderCount] =
-{
-// Long header ("//SCKL") indices
-// destination port (, other header)
-	{ 1,{ 6, 10, 0, 0, 0, 0} },
-// destination port, source port (, other header)
-	{ 2,{ 6, 10, 14, 0, 0, 0} },
-// destination port, source port,
-// reference, total segments, current segment(, other header)
-	{ 5,{ 6, 10, 14, 16, 18, 20}},
-
-// Short header ("//SCK") indices
-// destination port (, other header)
-	{ 1, { 5, 7, 0, 0, 0, 0}},
-// destination port, source port (, other header)
-	{ 2, { 5, 7, 9, 0, 0, 0}},
-// destination port, source port,
-// reference, total segments, current segment(, other header)
-	{ 5,{ 5, 7, 9, 11, 13, 15}},
-};
-
-
-/**
- *  C'tor
- *  
- *  @param aWapMessage WAP message to decode/encode
- *  @note simply use KNullDesC8, if you are going to encode.
- */
-TWapTextMessage::TWapTextMessage(const TDesC8& aWapMessage)
-	:iIsWapTextMessage(EFalse)
-	,iWAPMessage(aWapMessage)
-	,iIs16Bit(EFalse)
-	,iDestinationPort(-1)
-	,iSourcePort(-1)
-	,iReference(0)
-	,iTotalSegments(0)
-	,iSegmentNumber(0)
-	,iOtherHeader(0)
-	,iOtherHeaderLength(0)
-	,iData(0)
-	,iDataLength(0)
-	,iRefOtherHeader(KNullDesC8)
-	,iRefData(KNullDesC8)
-	{
-	} // TWapTextMessage::TWapTextMessage
-
-
-/**
- *  Panic is raised, if the header with other header and terminating
- *  ' ' is > 159 characters. Then 1 byte is left for payload !
- *  what will be the array element type ?
- */
-void TWapTextMessage::EncodeSegmentsL(CArrayPtr<HBufC8>& aSegmentArray)
-	{
-	TBuf8<KMaxSmsChars>  header;        // buffer for a modifiable header
-	TInt        headerLength = 0;
-	TInt        segmentNumberIndex = 0; // index of segment number field in the header
-	TBuf8<2>    hexSegmentNumber;
-	TInt        dataSegmented = 0;
-
-	LOGWAPPROT1("TWapTextMessage::EncodeSegmentsL()");
-
-	iSegmentNumber = 0;
-	do
-		{
-		//
-		// Create the segment and add it to the array...
-		//
-		HBufC8*  segment = HBufC8::NewL(KMaxSmsChars); // 160 characters
-		CleanupStack::PushL(segment);
-		TPtr8  ptr(segment->Des());
-		aSegmentArray.AppendL(segment);
-		CleanupStack::Pop(); // segment
-
-		//
-		// Calculate length of header and copy it...
-		//
-		if (iSegmentNumber==0)
-			{
-			headerLength = CreateHeader(header, segmentNumberIndex);
-			}
-
-		ptr.Copy(header);
-		if (iTotalSegments>255)
-			{
-			User::Leave(KErrOverflow);
-			}
-
-		//
-		// Set segment number...
-		//
-		if (segmentNumberIndex != 0)
-			{
-			hexSegmentNumber.NumFixedWidthUC(iSegmentNumber+1, EHex, 2); // two bytes wide
-			ptr.Insert(segmentNumberIndex, hexSegmentNumber);
-			}
-
-		//
-		// Count any escaped characters we can be sure that the converted data
-		// size fits inside the remaining length (e.g. so that non-7bit characters
-		// when converted by the SMS Stack will still fit).
-		//
-		TInt  segmentSize = iRefData.Length() - dataSegmented;
-
-		if (segmentSize > KMaxSmsChars - headerLength)
-			{
-			segmentSize = KMaxSmsChars - headerLength;
-			}
-
-		while (segmentSize > 1)
-			{
-			TPtrC8  segmentData(iRefData.Mid(dataSegmented, segmentSize));
-			TInt  non7bitCharEscapes = 0;
-			
-			//
-			// Count all non-7bit characters that will be escaped (many non-7bit
-			// characters are not escaped, but converted to "?"). The ones
-			// that are known to be escaped are list below:
-			//
-			//	  12  [Form Feed].
-			//	  91  "["
-			//	  92  "\"
-			//	  93  "]"
-			//	  94  "^"
-			//	 123  "{"
-			//	 124  "|"
-			//	 125  "}"
-			//	 126  "~"
-			//
-			for (TInt  ch = 0;  ch < segmentSize;  ch++)
-				{
-				if (segmentData[ch] == 12  ||
-					(segmentData[ch] >= 91  &&  segmentData[ch] <= 94)  ||
-					(segmentData[ch] >= 123  &&  segmentData[ch] <= 126))
-					{
-					non7bitCharEscapes++;
-					}
-				}
-			
-			//
-			// Can it fit? If so store it, otherwise reduce the size...
-			//
-			if (segmentData.Length() + non7bitCharEscapes <= KMaxSmsChars - headerLength)
-				{
-				ptr.Append(segmentData);
-				break;
-				}
-			
-			segmentSize--;
-			}
-		
-			dataSegmented += segmentSize;
-			iSegmentNumber++;
-		}
-	while (dataSegmented < iRefData.Length());
-
-	__ASSERT_DEBUG(iTotalSegments == aSegmentArray.Count(), Panic(KPanicEncodingError));
-	} // TWapTextMessage::EncodeSegmentsL
-
-
-/**
- *  Returns true, if the short message starts with
- *  WAP text message header set by SetWapTextMessage.
- */
-TBool TWapTextMessage::Parse()
-	{
-	TInt waplength = iWAPMessage.Length();
-	LOGWAPPROT2("TWapTextMessage::Parse [%d bytes]", waplength);
-	if(waplength != 0)
-		{
-		// check whether long or short header
-		TInt iBaseIndex = -1;
-
-		// minimum length is 8 "//SCKxx "
-		if(waplength >= 8)
-			{
-			TPtrC8 HeaderIdPart(iWAPMessage.Left(6));
-			if(!HeaderIdPart.Compare(KSCKHeaderLong))
-				{
-				iBaseIndex = 0;
-				iIs16Bit = ETrue; // Yes, the ports are 16 bit wide
-				}
-			else
-				HeaderIdPart.Set(iWAPMessage.Left(5));
-
-			if(iBaseIndex == (-1) && !HeaderIdPart.Compare(KSCKHeaderShort) )
-				iBaseIndex = 3;
-			// else  no match
-			}
-
-		if(iBaseIndex >= 0)
-			{
-			// check which of the TIndexInfos match
-			for(TInt i=iBaseIndex; i<iBaseIndex+3; i++)
-				{
-				// Get length (index) of text header variant
-				TInt lastIndex = KElemIndexes[i].iIndexes[KElemIndexes[i].iLastIndex];
-				if (iWAPMessage.Length() <= lastIndex)
-					{
-					// no hope about match, because other variants are longer
-					iIsWapTextMessage = EFalse;
-					break;
-					}
-
-				TInt LastChar = iWAPMessage[lastIndex];
-				if (LastChar == '/' || LastChar == ' ' || LastChar == '\n')
-					{
-					// reinitialize, because following maybe absent
-					iTotalSegments = 1;
-					iSegmentNumber = 1;
-					iIsWapTextMessage = ParseWapTextHeader(KElemIndexes[i]);
-					break;
-					}
-
-				}
-
-			if (!iIsWapTextMessage)
-				{
-				LOGWAPPROT1("WARNING! illegal incoming WAP message");
-				}
-			}
-		}
-
-	return iIsWapTextMessage;
-	} // TWapTextMessage::Parse
-
-
-/**
- *  Parses a string of hex characters representing a number
- *  
- *  @param aInValue descriptor containing the number
- *  @param aBigEndian true if number is big endian
- *  @param aRadix Radixbase; 16, 10 etc
- *  @return TInt the parsed number
- *  @leave Panics with KPanicInvalidParseNumber error code, if not a
- *  number. Maximum width of the hex value can be 4.
- *  
- *  TODO use TLex instead
- */
-TInt TWapTextMessage::ParseNumber(const TDesC8& aInValue,
-								  TBool   aBigEndian,
-								  TInt    aRadix)
-	{
-	LOGWAPPROT2("TWapTextMessage::ParseNumber [%S]", &aInValue);
-	// least significant byte first
-	TInt Values[4] = {0,0,0,0};
-	TInt Temp = 0;
-	TInt length = aInValue.Length();
-	TInt i = 0;
-	TInt Value = 0;
-
-	__ASSERT_DEBUG(length<5,Panic(KPanicInvalidParseNumber));
-    if( length >= 5 )
-        return KErrNotFound;
-	for(i=0; i<length; i++)
-		{
-		Temp = aInValue[i];
-		if (Temp>='0' && Temp<='9')
-			Temp-='0';
-		else if (Temp>='A' && Temp<='Z')
-			Temp = Temp - 'A'+10;
-		else if (Temp>='a' && Temp<='z')
-			Temp = Temp - 'a'+10;
-		else
-            return KErrNotFound;
-		if (aBigEndian)
-			Values[(length-1)-i]=Temp;
-		else
-			Values[i]=Temp;
-		}
-
-	// build the value
-	Value=Values[0];
-	TInt Base=1;
-	for(i=1; i<length; i++)
-		{
-		Base*=aRadix;
-		Value+=(Base)*Values[i];
-		}
-
-	return Value;
-	} // TWapTextMessage::ParseNumber
-
-
-/**
- *  parse the WAP text header
- *  
- *  use ElemIndexes to retrieve the index
- *  an starting position of an element in iWapMessage
- *  Length of element is calculated by
- *  subtracting current index value from the next one
- *  except for KOtherHeader and user data, of course
- */
-TBool TWapTextMessage::ParseWapTextHeader(const TIndexInfo& aIndexArray)
-	{
-	LOGWAPPROT2("TWapTextMessage::ParseWapTextHeader: %S", &iWAPMessage );
-
-	TInt ParsedNumber = 0;
-
-	// parse the header
-	TInt ElemIndexCount=aIndexArray.iLastIndex+1;
-	for(TInt i=0; i<ElemIndexCount; i++)
-		{
-		if (i<ElemIndexCount-1)
-			{
-			// all the elems have a length defined in advance
-			if (iWAPMessage.Length() >= aIndexArray.iIndexes[i+1])
-				{
-				// the header fits into the wap datagram
-				TPtrC8 Elem(iWAPMessage.Mid(aIndexArray.iIndexes[i],
-											aIndexArray.iIndexes[i+1]-
-											aIndexArray.iIndexes[i]));
-
-				ParsedNumber = ParseNumber(Elem,ETrue,16);
-                if( ParsedNumber == KErrNotFound )
-                    return EFalse;
-				switch(i)
-					{
-				  case KIndexDestinationPort:
-					  iDestinationPort = ParsedNumber;
-
-					  break;
-				  case KIndexSourcePort:
-					  iSourcePort = ParsedNumber;
-					  break;
-				  case KIndexReferenceNumber:
-					  iReference = ParsedNumber;
-					  break;
-				  case KIndexTotalSegments:
-					  iTotalSegments = ParsedNumber;
-					  break;
-				  case KIndexSegmentNumber:
-					  iSegmentNumber = ParsedNumber;
-					  break;
-				  default:
-					  LOGWAPPROT2("Hm. unhandled WAP index [%d]", i );
-					  break;
-					}
-				}
-			}
-		else
-			{
-			// elems have not a length defined in advance
-			iOtherHeader = 0;
-			iOtherHeaderLength = 0;
-
-			// Search the terminating character ' '
-			iData = iWAPMessage.Locate(' ');
-			TInt dataTmp = iWAPMessage.Locate('\n');
-
-			if (iData == KErrNotFound)
-				{
-				if (dataTmp == KErrNotFound)
-					return EFalse;
-				else
-					iData = dataTmp;
-				}
-			else if (dataTmp != KErrNotFound)
-				iData = Min(iData, dataTmp);
-
-			// check the existence of other header
-			// at least "// " should be there
-			if (   iWAPMessage.Length() > aIndexArray.iIndexes[i]+2
-				   && iWAPMessage[aIndexArray.iIndexes[i]] == '/'
-				   && iWAPMessage[aIndexArray.iIndexes[i]+1] == '/')
-				{
-				iOtherHeader = aIndexArray.iIndexes[i];
-				iOtherHeaderLength=iData-iOtherHeader;
-				}
-
-			// data: check if any characters after ' '
-			iDataLength = 0;
-			iData++;
-			if (iWAPMessage.Length() > iData)
-				{
-				iDataLength = iWAPMessage.Length() - iData;
-				}
-
-			// That's it
-			} // end of other header and data
-		}// end of for loop
-	return ETrue;
-	} // TWapTextMessage::ParseWapTextHeader
-
-
-/**
- *  Length of header is returned
- *  Sets internally the iTotalSegments
- *  Does not set the segment number into the aFixedHeader
- *  
- *  Length of complete header is returned.
- *  On return the header is not complete, if SAR is needed, because the segment
- *  number is not set. Thus aFixedHeader.Length() != (return value of this function) is true.
- *  The segment number can be set by inserting it into aSegmentNumberIndex position
- *  If SAR is not needed aSegmentNumberIndex = 0 and
- *  aFixedHeader.Length() == (return value of this function) is true
- */
-TInt TWapTextMessage::CreateHeader(TDes8& aFixedHeader, TInt& aSegmentNumberIndex)
-	{
-	LOGWAPPROT1("TWapTextMessage::CreateHeader");
-
-	// Index into KElemIndexes indicating which header elements are present
-	TInt elemIndex;
-	// Index into Indexes, for current header element
-	TInt minorIndex=KIndexDestinationPort;
-	TBuf8<4> hexNumber;
-
-	// Segment number length is set, if SAR is needed
-	TInt segmentNumberLength = 0;
-	aSegmentNumberIndex = 0;
-
-	// Determine whether long or short form is used
-	if (iIs16Bit || iSourcePort > 255 || iDestinationPort>255)
-		{
-		elemIndex = 0;
-		aFixedHeader.Copy(KSCKHeaderLong);
-		}
-	else
-		{
-		elemIndex = 3;
-		aFixedHeader.Copy(KSCKHeaderShort);
-		}
-
-	// Set destination port
-	hexNumber.NumFixedWidthUC(iDestinationPort,EHex,
-							  KElemIndexes[elemIndex].iIndexes[minorIndex+1]-KElemIndexes[elemIndex].iIndexes[minorIndex]);
-	aFixedHeader.Append(hexNumber);
-
-	// Don't set the source port,
-	// 1) if it is not set or it same as destination port and
-	// 2) data (and other header) fits in one segment
-	if (!((iSourcePort==-1 || iDestinationPort==iSourcePort)
-		  && CalculateTotalSegments(KElemIndexes[elemIndex].iIndexes[minorIndex+1])==1))
-		{
-		// Source port is present
-		elemIndex++;
-		minorIndex++;
-		if (iSourcePort==-1)
-			iSourcePort = iDestinationPort;
-
-		// Set source port
-		hexNumber.NumFixedWidthUC(iSourcePort,EHex,
-								  KElemIndexes[elemIndex].iIndexes[minorIndex+1]-KElemIndexes[elemIndex].iIndexes[minorIndex]);
-		aFixedHeader.Append(hexNumber);
-
-		// Add the SAR info when source port is set
-		elemIndex++;
-
-		// Set reference
-		minorIndex++;
-		hexNumber.NumFixedWidthUC(iReference,EHex,
-								  KElemIndexes[elemIndex].iIndexes[minorIndex+1]-KElemIndexes[elemIndex].iIndexes[minorIndex]);
-		aFixedHeader.Append(hexNumber);
-
-		// Set fragment count
-		minorIndex++;
-		CalculateTotalSegments(KElemIndexes[elemIndex].iIndexes[KElemIndexes[elemIndex].iLastIndex]);
-		hexNumber.NumFixedWidthUC(iTotalSegments,EHex,
-								  KElemIndexes[elemIndex].iIndexes[minorIndex+1]-KElemIndexes[elemIndex].iIndexes[minorIndex]);
-		aFixedHeader.Append(hexNumber);
-
-		// Return the index for segment number in the header
-		minorIndex++;
-		aSegmentNumberIndex = KElemIndexes[elemIndex].iIndexes[minorIndex];
-		segmentNumberLength = 2;
-		}
-
-	aFixedHeader.Append(iRefOtherHeader);
-	aFixedHeader.Append(_L(" "));
-
-	return aFixedHeader.Length()+segmentNumberLength;
-	} // TWapTextMessage::CreateHeader
-
-
-/**
- *  Calculates count of segments to send a used data (based on iRefData)
- *  The values is assigned to iTotalSegments
- *  The affect of terminating ' ' is taken into inside the method
- */
-TInt TWapTextMessage::CalculateTotalSegments(TInt aFixedLength)
-	{
-	LOGWAPPROT2("TWapTextMessage::CalculateTotalSegments [aFixedLength=%d]", aFixedLength);
-
-	// '+1': length of terminating ' '
-	TInt  length        = aFixedLength + iRefOtherHeader.Length() + 1;
-	TInt  remain        = KMaxSmsChars - length;
-	TInt  dataSegmented = 0;
-
-	__ASSERT_DEBUG(remain > 0, Panic(KPanicTextHeaderTooLong));
-
-	iTotalSegments = 0;
-	do
-		{
-		iTotalSegments++;
-
-		//
-		// Count any escaped characters we can be sure that the converted data
-		// size fits inside the remaining length (e.g. so that non-7bit characters
-		// when converted by the SMS Stack will still fit).
-		//
-		TInt  segmentSize = iRefData.Length() - dataSegmented;
-
-		if (segmentSize > remain)
-			{
-			segmentSize = remain;
-			}
-
-		while (segmentSize > 1)
-			{
-			TPtrC8  segmentData(iRefData.Mid(dataSegmented, segmentSize));
-			TInt  non7bitCharEscapes = 0;
-			
-			//
-			// Count all non-7bit characters that will be escaped (many non-7bit
-			// characters are not escaped, but converted to "?"). The ones
-			// that are known to be escaped are list below:
-			//
-			//	  12  [Form Feed].
-			//	  91  "["
-			//	  92  "\"
-			//	  93  "]"
-			//	  94  "^"
-			//	 123  "{"
-			//	 124  "|"
-			//	 125  "}"
-			//	 126  "~"
-			//
-			for (TInt  ch = 0;  ch < segmentSize;  ch++)
-				{
-				if (segmentData[ch] == 12  ||
-					(segmentData[ch] >= 91  &&  segmentData[ch] <= 94)  ||
-					(segmentData[ch] >= 123  &&  segmentData[ch] <= 126))
-					{
-					non7bitCharEscapes++;
-					}
-				}
-			
-			//
-			// Can it fit? If so store it, otherwise reduce the size...
-			//
-			if (segmentData.Length() + non7bitCharEscapes <= remain)
-				{
-				break;
-				}
-			
-			segmentSize--;
-			}
-		
-			dataSegmented += segmentSize;
-		}
-	while (dataSegmented < iRefData.Length());
-	
-	//
-	// At least one fragment is needed...
-	//
-	if (iTotalSegments == 0)
-		{
-		iTotalSegments = 1;
-		}
-
-	return iTotalSegments;
-	} // TWapTextMessage::CalculateTotalSegments
-
-// EOF - WAPTHDR.CPP
+// 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:
+// This file contains the implementation of the TWapTextMessage.
+// TWapTextMessage encodes and decodes 7-bit WAP text headers
+// 
+//
+
+/**
+ @file
+*/
+
+#include <e32std.h>
+#include "wapthdr.h"
+#include "ws_main.h"
+
+const TInt TWapTextMessage::KHeaderCount = 6;
+
+_LIT8(KSCKHeaderLong, "//SCKL"); // standard NBS header for 16-bit adresses
+_LIT8(KSCKHeaderShort,"//SCK");  // standard NBS header for 8-bit adresses
+
+
+/**
+ *  Indices into different types header for each of the header elements
+ *  (dest port, source port, reference, total segments, current segment)
+ */
+const TWapTextMessage::TIndexInfo TWapTextMessage::KElemIndexes[TWapTextMessage::KHeaderCount] =
+{
+// Long header ("//SCKL") indices
+// destination port (, other header)
+	{ 1,{ 6, 10, 0, 0, 0, 0} },
+// destination port, source port (, other header)
+	{ 2,{ 6, 10, 14, 0, 0, 0} },
+// destination port, source port,
+// reference, total segments, current segment(, other header)
+	{ 5,{ 6, 10, 14, 16, 18, 20}},
+
+// Short header ("//SCK") indices
+// destination port (, other header)
+	{ 1, { 5, 7, 0, 0, 0, 0}},
+// destination port, source port (, other header)
+	{ 2, { 5, 7, 9, 0, 0, 0}},
+// destination port, source port,
+// reference, total segments, current segment(, other header)
+	{ 5,{ 5, 7, 9, 11, 13, 15}},
+};
+
+
+/**
+ *  C'tor
+ *  
+ *  @param aWapMessage WAP message to decode/encode
+ *  @note simply use KNullDesC8, if you are going to encode.
+ */
+TWapTextMessage::TWapTextMessage(const TDesC8& aWapMessage)
+	:iIsWapTextMessage(EFalse)
+	,iWAPMessage(aWapMessage)
+	,iIs16Bit(EFalse)
+	,iDestinationPort(-1)
+	,iSourcePort(-1)
+	,iReference(0)
+	,iTotalSegments(0)
+	,iSegmentNumber(0)
+	,iOtherHeader(0)
+	,iOtherHeaderLength(0)
+	,iData(0)
+	,iDataLength(0)
+	,iRefOtherHeader(KNullDesC8)
+	,iRefData(KNullDesC8)
+	{
+	} // TWapTextMessage::TWapTextMessage
+
+
+/**
+ *  Panic is raised, if the header with other header and terminating
+ *  ' ' is > 159 characters. Then 1 byte is left for payload !
+ *  what will be the array element type ?
+ */
+void TWapTextMessage::EncodeSegmentsL(CArrayPtr<HBufC8>& aSegmentArray)
+	{
+	TBuf8<KMaxSmsChars>  header;        // buffer for a modifiable header
+	TInt        headerLength = 0;
+	TInt        segmentNumberIndex = 0; // index of segment number field in the header
+	TBuf8<2>    hexSegmentNumber;
+	TInt        dataSegmented = 0;
+
+	LOGWAPPROT1("TWapTextMessage::EncodeSegmentsL()");
+
+	iSegmentNumber = 0;
+	do
+		{
+		//
+		// Create the segment and add it to the array...
+		//
+		HBufC8*  segment = HBufC8::NewL(KMaxSmsChars); // 160 characters
+		CleanupStack::PushL(segment);
+		TPtr8  ptr(segment->Des());
+		aSegmentArray.AppendL(segment);
+		CleanupStack::Pop(); // segment
+
+		//
+		// Calculate length of header and copy it...
+		//
+		if (iSegmentNumber==0)
+			{
+			headerLength = CreateHeader(header, segmentNumberIndex);
+			}
+
+		ptr.Copy(header);
+		if (iTotalSegments>255)
+			{
+			User::Leave(KErrOverflow);
+			}
+
+		//
+		// Set segment number...
+		//
+		if (segmentNumberIndex != 0)
+			{
+			hexSegmentNumber.NumFixedWidthUC(iSegmentNumber+1, EHex, 2); // two bytes wide
+			ptr.Insert(segmentNumberIndex, hexSegmentNumber);
+			}
+
+		//
+		// Count any escaped characters we can be sure that the converted data
+		// size fits inside the remaining length (e.g. so that non-7bit characters
+		// when converted by the SMS Stack will still fit).
+		//
+		TInt  segmentSize = iRefData.Length() - dataSegmented;
+
+		if (segmentSize > KMaxSmsChars - headerLength)
+			{
+			segmentSize = KMaxSmsChars - headerLength;
+			}
+
+		while (segmentSize > 1)
+			{
+			TPtrC8  segmentData(iRefData.Mid(dataSegmented, segmentSize));
+			TInt  non7bitCharEscapes = 0;
+			
+			//
+			// Count all non-7bit characters that will be escaped (many non-7bit
+			// characters are not escaped, but converted to "?"). The ones
+			// that are known to be escaped are list below:
+			//
+			//	  12  [Form Feed].
+			//	  91  "["
+			//	  92  "\"
+			//	  93  "]"
+			//	  94  "^"
+			//	 123  "{"
+			//	 124  "|"
+			//	 125  "}"
+			//	 126  "~"
+			//
+			for (TInt  ch = 0;  ch < segmentSize;  ch++)
+				{
+				if (segmentData[ch] == 12  ||
+					(segmentData[ch] >= 91  &&  segmentData[ch] <= 94)  ||
+					(segmentData[ch] >= 123  &&  segmentData[ch] <= 126))
+					{
+					non7bitCharEscapes++;
+					}
+				}
+			
+			//
+			// Can it fit? If so store it, otherwise reduce the size...
+			//
+			if (segmentData.Length() + non7bitCharEscapes <= KMaxSmsChars - headerLength)
+				{
+				ptr.Append(segmentData);
+				break;
+				}
+			
+			segmentSize--;
+			}
+		
+			dataSegmented += segmentSize;
+			iSegmentNumber++;
+		}
+	while (dataSegmented < iRefData.Length());
+
+	__ASSERT_DEBUG(iTotalSegments == aSegmentArray.Count(), Panic(KPanicEncodingError));
+	} // TWapTextMessage::EncodeSegmentsL
+
+
+/**
+ *  Returns true, if the short message starts with
+ *  WAP text message header set by SetWapTextMessage.
+ */
+TBool TWapTextMessage::Parse()
+	{
+	TInt waplength = iWAPMessage.Length();
+	LOGWAPPROT2("TWapTextMessage::Parse [%d bytes]", waplength);
+	if(waplength != 0)
+		{
+		// check whether long or short header
+		TInt iBaseIndex = -1;
+
+		// minimum length is 8 "//SCKxx "
+		if(waplength >= 8)
+			{
+			TPtrC8 HeaderIdPart(iWAPMessage.Left(6));
+			if(!HeaderIdPart.Compare(KSCKHeaderLong))
+				{
+				iBaseIndex = 0;
+				iIs16Bit = ETrue; // Yes, the ports are 16 bit wide
+				}
+			else
+				HeaderIdPart.Set(iWAPMessage.Left(5));
+
+			if(iBaseIndex == (-1) && !HeaderIdPart.Compare(KSCKHeaderShort) )
+				iBaseIndex = 3;
+			// else  no match
+			}
+
+		if(iBaseIndex >= 0)
+			{
+			// check which of the TIndexInfos match
+			for(TInt i=iBaseIndex; i<iBaseIndex+3; i++)
+				{
+				// Get length (index) of text header variant
+				TInt lastIndex = KElemIndexes[i].iIndexes[KElemIndexes[i].iLastIndex];
+				if (iWAPMessage.Length() <= lastIndex)
+					{
+					// no hope about match, because other variants are longer
+					iIsWapTextMessage = EFalse;
+					break;
+					}
+
+				TInt LastChar = iWAPMessage[lastIndex];
+				if (LastChar == '/' || LastChar == ' ' || LastChar == '\n')
+					{
+					// reinitialize, because following maybe absent
+					iTotalSegments = 1;
+					iSegmentNumber = 1;
+					iIsWapTextMessage = ParseWapTextHeader(KElemIndexes[i]);
+					break;
+					}
+
+				}
+
+			if (!iIsWapTextMessage)
+				{
+				LOGWAPPROT1("WARNING! illegal incoming WAP message");
+				}
+			}
+		}
+
+	return iIsWapTextMessage;
+	} // TWapTextMessage::Parse
+
+
+/**
+ *  Parses a string of hex characters representing a number
+ *  
+ *  @param aInValue descriptor containing the number
+ *  @param aBigEndian true if number is big endian
+ *  @param aRadix Radixbase; 16, 10 etc
+ *  @return TInt the parsed number
+ *  @leave Panics with KPanicInvalidParseNumber error code, if not a
+ *  number. Maximum width of the hex value can be 4.
+ *  
+ *  TODO use TLex instead
+ */
+TInt TWapTextMessage::ParseNumber(const TDesC8& aInValue,
+								  TBool   aBigEndian,
+								  TInt    aRadix)
+	{
+	LOGWAPPROT2("TWapTextMessage::ParseNumber [%S]", &aInValue);
+	// least significant byte first
+	TInt Values[4] = {0,0,0,0};
+	TInt Temp = 0;
+	TInt length = aInValue.Length();
+	TInt i = 0;
+	TInt Value = 0;
+
+	__ASSERT_DEBUG(length<5,Panic(KPanicInvalidParseNumber));
+    if( length >= 5 )
+        return KErrNotFound;
+	for(i=0; i<length; i++)
+		{
+		Temp = aInValue[i];
+		if (Temp>='0' && Temp<='9')
+			Temp-='0';
+		else if (Temp>='A' && Temp<='Z')
+			Temp = Temp - 'A'+10;
+		else if (Temp>='a' && Temp<='z')
+			Temp = Temp - 'a'+10;
+		else
+            return KErrNotFound;
+		if (aBigEndian)
+			Values[(length-1)-i]=Temp;
+		else
+			Values[i]=Temp;
+		}
+
+	// build the value
+	Value=Values[0];
+	TInt Base=1;
+	for(i=1; i<length; i++)
+		{
+		Base*=aRadix;
+		Value+=(Base)*Values[i];
+		}
+
+	return Value;
+	} // TWapTextMessage::ParseNumber
+
+
+/**
+ *  parse the WAP text header
+ *  
+ *  use ElemIndexes to retrieve the index
+ *  an starting position of an element in iWapMessage
+ *  Length of element is calculated by
+ *  subtracting current index value from the next one
+ *  except for KOtherHeader and user data, of course
+ */
+TBool TWapTextMessage::ParseWapTextHeader(const TIndexInfo& aIndexArray)
+	{
+	LOGWAPPROT2("TWapTextMessage::ParseWapTextHeader: %S", &iWAPMessage );
+
+	TInt ParsedNumber = 0;
+
+	// parse the header
+	TInt ElemIndexCount=aIndexArray.iLastIndex+1;
+	for(TInt i=0; i<ElemIndexCount; i++)
+		{
+		if (i<ElemIndexCount-1)
+			{
+			// all the elems have a length defined in advance
+			if (iWAPMessage.Length() >= aIndexArray.iIndexes[i+1])
+				{
+				// the header fits into the wap datagram
+				TPtrC8 Elem(iWAPMessage.Mid(aIndexArray.iIndexes[i],
+											aIndexArray.iIndexes[i+1]-
+											aIndexArray.iIndexes[i]));
+
+				ParsedNumber = ParseNumber(Elem,ETrue,16);
+                if( ParsedNumber == KErrNotFound )
+                    return EFalse;
+				switch(i)
+					{
+				  case KIndexDestinationPort:
+					  iDestinationPort = ParsedNumber;
+
+					  break;
+				  case KIndexSourcePort:
+					  iSourcePort = ParsedNumber;
+					  break;
+				  case KIndexReferenceNumber:
+					  iReference = ParsedNumber;
+					  break;
+				  case KIndexTotalSegments:
+					  iTotalSegments = ParsedNumber;
+					  break;
+				  case KIndexSegmentNumber:
+					  iSegmentNumber = ParsedNumber;
+					  break;
+				  default:
+					  LOGWAPPROT2("Hm. unhandled WAP index [%d]", i );
+					  break;
+					}
+				}
+			}
+		else
+			{
+			// elems have not a length defined in advance
+			iOtherHeader = 0;
+			iOtherHeaderLength = 0;
+
+			// Search the terminating character ' '
+			iData = iWAPMessage.Locate(' ');
+			TInt dataTmp = iWAPMessage.Locate('\n');
+
+			if (iData == KErrNotFound)
+				{
+				if (dataTmp == KErrNotFound)
+					return EFalse;
+				else
+					iData = dataTmp;
+				}
+			else if (dataTmp != KErrNotFound)
+				iData = Min(iData, dataTmp);
+
+			// check the existence of other header
+			// at least "// " should be there
+			if (   iWAPMessage.Length() > aIndexArray.iIndexes[i]+2
+				   && iWAPMessage[aIndexArray.iIndexes[i]] == '/'
+				   && iWAPMessage[aIndexArray.iIndexes[i]+1] == '/')
+				{
+				iOtherHeader = aIndexArray.iIndexes[i];
+				iOtherHeaderLength=iData-iOtherHeader;
+				}
+
+			// data: check if any characters after ' '
+			iDataLength = 0;
+			iData++;
+			if (iWAPMessage.Length() > iData)
+				{
+				iDataLength = iWAPMessage.Length() - iData;
+				}
+
+			// That's it
+			} // end of other header and data
+		}// end of for loop
+	return ETrue;
+	} // TWapTextMessage::ParseWapTextHeader
+
+
+/**
+ *  Length of header is returned
+ *  Sets internally the iTotalSegments
+ *  Does not set the segment number into the aFixedHeader
+ *  
+ *  Length of complete header is returned.
+ *  On return the header is not complete, if SAR is needed, because the segment
+ *  number is not set. Thus aFixedHeader.Length() != (return value of this function) is true.
+ *  The segment number can be set by inserting it into aSegmentNumberIndex position
+ *  If SAR is not needed aSegmentNumberIndex = 0 and
+ *  aFixedHeader.Length() == (return value of this function) is true
+ */
+TInt TWapTextMessage::CreateHeader(TDes8& aFixedHeader, TInt& aSegmentNumberIndex)
+	{
+	LOGWAPPROT1("TWapTextMessage::CreateHeader");
+
+	// Index into KElemIndexes indicating which header elements are present
+	TInt elemIndex;
+	// Index into Indexes, for current header element
+	TInt minorIndex=KIndexDestinationPort;
+	TBuf8<4> hexNumber;
+
+	// Segment number length is set, if SAR is needed
+	TInt segmentNumberLength = 0;
+	aSegmentNumberIndex = 0;
+
+	// Determine whether long or short form is used
+	if (iIs16Bit || iSourcePort > 255 || iDestinationPort>255)
+		{
+		elemIndex = 0;
+		aFixedHeader.Copy(KSCKHeaderLong);
+		}
+	else
+		{
+		elemIndex = 3;
+		aFixedHeader.Copy(KSCKHeaderShort);
+		}
+
+	// Set destination port
+	hexNumber.NumFixedWidthUC(iDestinationPort,EHex,
+							  KElemIndexes[elemIndex].iIndexes[minorIndex+1]-KElemIndexes[elemIndex].iIndexes[minorIndex]);
+	aFixedHeader.Append(hexNumber);
+
+	// Don't set the source port,
+	// 1) if it is not set or it same as destination port and
+	// 2) data (and other header) fits in one segment
+	if (!((iSourcePort==-1 || iDestinationPort==iSourcePort)
+		  && CalculateTotalSegments(KElemIndexes[elemIndex].iIndexes[minorIndex+1])==1))
+		{
+		// Source port is present
+		elemIndex++;
+		minorIndex++;
+		if (iSourcePort==-1)
+			iSourcePort = iDestinationPort;
+
+		// Set source port
+		hexNumber.NumFixedWidthUC(iSourcePort,EHex,
+								  KElemIndexes[elemIndex].iIndexes[minorIndex+1]-KElemIndexes[elemIndex].iIndexes[minorIndex]);
+		aFixedHeader.Append(hexNumber);
+
+		// Add the SAR info when source port is set
+		elemIndex++;
+
+		// Set reference
+		minorIndex++;
+		hexNumber.NumFixedWidthUC(iReference,EHex,
+								  KElemIndexes[elemIndex].iIndexes[minorIndex+1]-KElemIndexes[elemIndex].iIndexes[minorIndex]);
+		aFixedHeader.Append(hexNumber);
+
+		// Set fragment count
+		minorIndex++;
+		CalculateTotalSegments(KElemIndexes[elemIndex].iIndexes[KElemIndexes[elemIndex].iLastIndex]);
+		hexNumber.NumFixedWidthUC(iTotalSegments,EHex,
+								  KElemIndexes[elemIndex].iIndexes[minorIndex+1]-KElemIndexes[elemIndex].iIndexes[minorIndex]);
+		aFixedHeader.Append(hexNumber);
+
+		// Return the index for segment number in the header
+		minorIndex++;
+		aSegmentNumberIndex = KElemIndexes[elemIndex].iIndexes[minorIndex];
+		segmentNumberLength = 2;
+		}
+
+	aFixedHeader.Append(iRefOtherHeader);
+	aFixedHeader.Append(_L(" "));
+
+	return aFixedHeader.Length()+segmentNumberLength;
+	} // TWapTextMessage::CreateHeader
+
+
+/**
+ *  Calculates count of segments to send a used data (based on iRefData)
+ *  The values is assigned to iTotalSegments
+ *  The affect of terminating ' ' is taken into inside the method
+ */
+TInt TWapTextMessage::CalculateTotalSegments(TInt aFixedLength)
+	{
+	LOGWAPPROT2("TWapTextMessage::CalculateTotalSegments [aFixedLength=%d]", aFixedLength);
+
+	// '+1': length of terminating ' '
+	TInt  length        = aFixedLength + iRefOtherHeader.Length() + 1;
+	TInt  remain        = KMaxSmsChars - length;
+	TInt  dataSegmented = 0;
+
+	__ASSERT_DEBUG(remain > 0, Panic(KPanicTextHeaderTooLong));
+
+	iTotalSegments = 0;
+	do
+		{
+		iTotalSegments++;
+
+		//
+		// Count any escaped characters we can be sure that the converted data
+		// size fits inside the remaining length (e.g. so that non-7bit characters
+		// when converted by the SMS Stack will still fit).
+		//
+		TInt  segmentSize = iRefData.Length() - dataSegmented;
+
+		if (segmentSize > remain)
+			{
+			segmentSize = remain;
+			}
+
+		while (segmentSize > 1)
+			{
+			TPtrC8  segmentData(iRefData.Mid(dataSegmented, segmentSize));
+			TInt  non7bitCharEscapes = 0;
+			
+			//
+			// Count all non-7bit characters that will be escaped (many non-7bit
+			// characters are not escaped, but converted to "?"). The ones
+			// that are known to be escaped are list below:
+			//
+			//	  12  [Form Feed].
+			//	  91  "["
+			//	  92  "\"
+			//	  93  "]"
+			//	  94  "^"
+			//	 123  "{"
+			//	 124  "|"
+			//	 125  "}"
+			//	 126  "~"
+			//
+			for (TInt  ch = 0;  ch < segmentSize;  ch++)
+				{
+				if (segmentData[ch] == 12  ||
+					(segmentData[ch] >= 91  &&  segmentData[ch] <= 94)  ||
+					(segmentData[ch] >= 123  &&  segmentData[ch] <= 126))
+					{
+					non7bitCharEscapes++;
+					}
+				}
+			
+			//
+			// Can it fit? If so store it, otherwise reduce the size...
+			//
+			if (segmentData.Length() + non7bitCharEscapes <= remain)
+				{
+				break;
+				}
+			
+			segmentSize--;
+			}
+		
+			dataSegmented += segmentSize;
+		}
+	while (dataSegmented < iRefData.Length());
+	
+	//
+	// At least one fragment is needed...
+	//
+	if (iTotalSegments == 0)
+		{
+		iTotalSegments = 1;
+		}
+
+	return iTotalSegments;
+	} // TWapTextMessage::CalculateTotalSegments
+
+// EOF - WAPTHDR.CPP