diff -r 6b1d113cdff3 -r 6638e7f4bd8f smsprotocols/smsstack/wapprot/Src/wapthdr.cpp --- 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 -#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& aSegmentArray) - { - TBuf8 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= 5 ) - return KErrNotFound; - for(i=0; i='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= 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 +#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& aSegmentArray) + { + TBuf8 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= 5 ) + return KErrNotFound; + for(i=0; i='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= 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