--- 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