smsprotocols/smsstack/wapprot/Src/wapthdr.cpp
branchRCL_3
changeset 19 630d2f34d719
parent 0 3553901f7fa8
child 20 07a122eea281
equal deleted inserted replaced
18:17af172ffa5f 19:630d2f34d719
     1 // Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
     1 // Copyright (c) 1997-2010 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     3 // This component and the accompanying materials are made available
     4 // under the terms of "Eclipse Public License v1.0"
     4 // under the terms of "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
    18 
    18 
    19 /**
    19 /**
    20  @file
    20  @file
    21 */
    21 */
    22 
    22 
       
    23 
       
    24 #include "OstTraceDefinitions.h"
       
    25 #ifdef OST_TRACE_COMPILER_IN_USE
       
    26 #include "wapthdrTraces.h"
       
    27 #endif
       
    28 
    23 #include <e32std.h>
    29 #include <e32std.h>
    24 #include "wapthdr.h"
    30 #include "wapthdr.h"
    25 #include "ws_main.h"
    31 #include "ws_main.h"
    26 
    32 
    27 const TInt TWapTextMessage::KHeaderCount = 6;
    33 const TInt TWapTextMessage::KHeaderCount = 6;
    36  */
    42  */
    37 const TWapTextMessage::TIndexInfo TWapTextMessage::KElemIndexes[TWapTextMessage::KHeaderCount] =
    43 const TWapTextMessage::TIndexInfo TWapTextMessage::KElemIndexes[TWapTextMessage::KHeaderCount] =
    38 {
    44 {
    39 // Long header ("//SCKL") indices
    45 // Long header ("//SCKL") indices
    40 // destination port (, other header)
    46 // destination port (, other header)
    41 	{ 1,{ 6, 10, 0, 0, 0, 0} },
    47     { 1,{ 6, 10, 0, 0, 0, 0} },
    42 // destination port, source port (, other header)
    48 // destination port, source port (, other header)
    43 	{ 2,{ 6, 10, 14, 0, 0, 0} },
    49     { 2,{ 6, 10, 14, 0, 0, 0} },
    44 // destination port, source port,
    50 // destination port, source port,
    45 // reference, total segments, current segment(, other header)
    51 // reference, total segments, current segment(, other header)
    46 	{ 5,{ 6, 10, 14, 16, 18, 20}},
    52     { 5,{ 6, 10, 14, 16, 18, 20}},
    47 
    53 
    48 // Short header ("//SCK") indices
    54 // Short header ("//SCK") indices
    49 // destination port (, other header)
    55 // destination port (, other header)
    50 	{ 1, { 5, 7, 0, 0, 0, 0}},
    56     { 1, { 5, 7, 0, 0, 0, 0}},
    51 // destination port, source port (, other header)
    57 // destination port, source port (, other header)
    52 	{ 2, { 5, 7, 9, 0, 0, 0}},
    58     { 2, { 5, 7, 9, 0, 0, 0}},
    53 // destination port, source port,
    59 // destination port, source port,
    54 // reference, total segments, current segment(, other header)
    60 // reference, total segments, current segment(, other header)
    55 	{ 5,{ 5, 7, 9, 11, 13, 15}},
    61     { 5,{ 5, 7, 9, 11, 13, 15}},
    56 };
    62 };
    57 
    63 
    58 
    64 
    59 /**
    65 /**
    60  *  C'tor
    66  *  C'tor
    61  *  
    67  *  
    62  *  @param aWapMessage WAP message to decode/encode
    68  *  @param aWapMessage WAP message to decode/encode
    63  *  @note simply use KNullDesC8, if you are going to encode.
    69  *  @note simply use KNullDesC8, if you are going to encode.
    64  */
    70  */
    65 TWapTextMessage::TWapTextMessage(const TDesC8& aWapMessage)
    71 TWapTextMessage::TWapTextMessage(const TDesC8& aWapMessage)
    66 	:iIsWapTextMessage(EFalse)
    72     :iIsWapTextMessage(EFalse)
    67 	,iWAPMessage(aWapMessage)
    73     ,iWAPMessage(aWapMessage)
    68 	,iIs16Bit(EFalse)
    74     ,iIs16Bit(EFalse)
    69 	,iDestinationPort(-1)
    75     ,iDestinationPort(-1)
    70 	,iSourcePort(-1)
    76     ,iSourcePort(-1)
    71 	,iReference(0)
    77     ,iReference(0)
    72 	,iTotalSegments(0)
    78     ,iTotalSegments(0)
    73 	,iSegmentNumber(0)
    79     ,iSegmentNumber(0)
    74 	,iOtherHeader(0)
    80     ,iOtherHeader(0)
    75 	,iOtherHeaderLength(0)
    81     ,iOtherHeaderLength(0)
    76 	,iData(0)
    82     ,iData(0)
    77 	,iDataLength(0)
    83     ,iDataLength(0)
    78 	,iRefOtherHeader(KNullDesC8)
    84     ,iRefOtherHeader(KNullDesC8)
    79 	,iRefData(KNullDesC8)
    85     ,iRefData(KNullDesC8)
    80 	{
    86     {
    81 	} // TWapTextMessage::TWapTextMessage
    87     } // TWapTextMessage::TWapTextMessage
    82 
    88 
    83 
    89 
    84 /**
    90 /**
    85  *  Panic is raised, if the header with other header and terminating
    91  *  Panic is raised, if the header with other header and terminating
    86  *  ' ' is > 159 characters. Then 1 byte is left for payload !
    92  *  ' ' is > 159 characters. Then 1 byte is left for payload !
    87  *  what will be the array element type ?
    93  *  what will be the array element type ?
    88  */
    94  */
    89 void TWapTextMessage::EncodeSegmentsL(CArrayPtr<HBufC8>& aSegmentArray)
    95 void TWapTextMessage::EncodeSegmentsL(CArrayPtr<HBufC8>& aSegmentArray)
    90 	{
    96     {
    91 	TBuf8<KMaxSmsChars>  header;        // buffer for a modifiable header
    97     TBuf8<KMaxSmsChars>  header;        // buffer for a modifiable header
    92 	TInt        headerLength = 0;
    98     TInt        headerLength = 0;
    93 	TInt        segmentNumberIndex = 0; // index of segment number field in the header
    99     TInt        segmentNumberIndex = 0; // index of segment number field in the header
    94 	TBuf8<2>    hexSegmentNumber;
   100     TBuf8<2>    hexSegmentNumber;
    95 	TInt        dataSegmented = 0;
   101     TInt        dataSegmented = 0;
    96 
   102 
    97 	LOGWAPPROT1("TWapTextMessage::EncodeSegmentsL()");
   103     OstTraceDef0(OST_TRACE_CATEGORY_DEBUG, TRACE_INTERNALS, TWAPTEXTMESSAGE_ENCODESEGMENTSL_1, "TWapTextMessage::EncodeSegmentsL()");
    98 
   104 
    99 	iSegmentNumber = 0;
   105     iSegmentNumber = 0;
   100 	do
   106     do
   101 		{
   107         {
   102 		//
   108         //
   103 		// Create the segment and add it to the array...
   109         // Create the segment and add it to the array...
   104 		//
   110         //
   105 		HBufC8*  segment = HBufC8::NewL(KMaxSmsChars); // 160 characters
   111         HBufC8*  segment = HBufC8::NewL(KMaxSmsChars); // 160 characters
   106 		CleanupStack::PushL(segment);
   112         CleanupStack::PushL(segment);
   107 		TPtr8  ptr(segment->Des());
   113         TPtr8  ptr(segment->Des());
   108 		aSegmentArray.AppendL(segment);
   114         aSegmentArray.AppendL(segment);
   109 		CleanupStack::Pop(); // segment
   115         CleanupStack::Pop(); // segment
   110 
   116 
   111 		//
   117         //
   112 		// Calculate length of header and copy it...
   118         // Calculate length of header and copy it...
   113 		//
   119         //
   114 		if (iSegmentNumber==0)
   120         if (iSegmentNumber==0)
   115 			{
   121             {
   116 			headerLength = CreateHeader(header, segmentNumberIndex);
   122             headerLength = CreateHeader(header, segmentNumberIndex);
   117 			}
   123             }
   118 
   124 
   119 		ptr.Copy(header);
   125         ptr.Copy(header);
   120 		if (iTotalSegments>255)
   126         if (iTotalSegments>255)
   121 			{
   127             {
   122 			User::Leave(KErrOverflow);
   128             User::Leave(KErrOverflow);
   123 			}
   129             }
   124 
   130 
   125 		//
   131         //
   126 		// Set segment number...
   132         // Set segment number...
   127 		//
   133         //
   128 		if (segmentNumberIndex != 0)
   134         if (segmentNumberIndex != 0)
   129 			{
   135             {
   130 			hexSegmentNumber.NumFixedWidthUC(iSegmentNumber+1, EHex, 2); // two bytes wide
   136             hexSegmentNumber.NumFixedWidthUC(iSegmentNumber+1, EHex, 2); // two bytes wide
   131 			ptr.Insert(segmentNumberIndex, hexSegmentNumber);
   137             ptr.Insert(segmentNumberIndex, hexSegmentNumber);
   132 			}
   138             }
   133 
   139 
   134 		//
   140         //
   135 		// Count any escaped characters we can be sure that the converted data
   141         // Count any escaped characters we can be sure that the converted data
   136 		// size fits inside the remaining length (e.g. so that non-7bit characters
   142         // size fits inside the remaining length (e.g. so that non-7bit characters
   137 		// when converted by the SMS Stack will still fit).
   143         // when converted by the SMS Stack will still fit).
   138 		//
   144         //
   139 		TInt  segmentSize = iRefData.Length() - dataSegmented;
   145         TInt  segmentSize = iRefData.Length() - dataSegmented;
   140 
   146 
   141 		if (segmentSize > KMaxSmsChars - headerLength)
   147         if (segmentSize > KMaxSmsChars - headerLength)
   142 			{
   148             {
   143 			segmentSize = KMaxSmsChars - headerLength;
   149             segmentSize = KMaxSmsChars - headerLength;
   144 			}
   150             }
   145 
   151 
   146 		while (segmentSize > 1)
   152         while (segmentSize > 1)
   147 			{
   153             {
   148 			TPtrC8  segmentData(iRefData.Mid(dataSegmented, segmentSize));
   154             TPtrC8  segmentData(iRefData.Mid(dataSegmented, segmentSize));
   149 			TInt  non7bitCharEscapes = 0;
   155             TInt  non7bitCharEscapes = 0;
   150 			
   156             
   151 			//
   157             //
   152 			// Count all non-7bit characters that will be escaped (many non-7bit
   158             // Count all non-7bit characters that will be escaped (many non-7bit
   153 			// characters are not escaped, but converted to "?"). The ones
   159             // characters are not escaped, but converted to "?"). The ones
   154 			// that are known to be escaped are list below:
   160             // that are known to be escaped are list below:
   155 			//
   161             //
   156 			//	  12  [Form Feed].
   162             //    12  [Form Feed].
   157 			//	  91  "["
   163             //    91  "["
   158 			//	  92  "\"
   164             //    92  "\"
   159 			//	  93  "]"
   165             //    93  "]"
   160 			//	  94  "^"
   166             //    94  "^"
   161 			//	 123  "{"
   167             //   123  "{"
   162 			//	 124  "|"
   168             //   124  "|"
   163 			//	 125  "}"
   169             //   125  "}"
   164 			//	 126  "~"
   170             //   126  "~"
   165 			//
   171             //
   166 			for (TInt  ch = 0;  ch < segmentSize;  ch++)
   172             for (TInt  ch = 0;  ch < segmentSize;  ch++)
   167 				{
   173                 {
   168 				if (segmentData[ch] == 12  ||
   174                 if (segmentData[ch] == 12  ||
   169 					(segmentData[ch] >= 91  &&  segmentData[ch] <= 94)  ||
   175                     (segmentData[ch] >= 91  &&  segmentData[ch] <= 94)  ||
   170 					(segmentData[ch] >= 123  &&  segmentData[ch] <= 126))
   176                     (segmentData[ch] >= 123  &&  segmentData[ch] <= 126))
   171 					{
   177                     {
   172 					non7bitCharEscapes++;
   178                     non7bitCharEscapes++;
   173 					}
   179                     }
   174 				}
   180                 }
   175 			
   181             
   176 			//
   182             //
   177 			// Can it fit? If so store it, otherwise reduce the size...
   183             // Can it fit? If so store it, otherwise reduce the size...
   178 			//
   184             //
   179 			if (segmentData.Length() + non7bitCharEscapes <= KMaxSmsChars - headerLength)
   185             if (segmentData.Length() + non7bitCharEscapes <= KMaxSmsChars - headerLength)
   180 				{
   186                 {
   181 				ptr.Append(segmentData);
   187                 ptr.Append(segmentData);
   182 				break;
   188                 break;
   183 				}
   189                 }
   184 			
   190             
   185 			segmentSize--;
   191             segmentSize--;
   186 			}
   192             }
   187 		
   193         
   188 			dataSegmented += segmentSize;
   194             dataSegmented += segmentSize;
   189 			iSegmentNumber++;
   195             iSegmentNumber++;
   190 		}
   196         }
   191 	while (dataSegmented < iRefData.Length());
   197     while (dataSegmented < iRefData.Length());
   192 
   198 
   193 	__ASSERT_DEBUG(iTotalSegments == aSegmentArray.Count(), Panic(KPanicEncodingError));
   199     __ASSERT_DEBUG(iTotalSegments == aSegmentArray.Count(), Panic(KPanicEncodingError));
   194 	} // TWapTextMessage::EncodeSegmentsL
   200     } // TWapTextMessage::EncodeSegmentsL
   195 
   201 
   196 
   202 
   197 /**
   203 /**
   198  *  Returns true, if the short message starts with
   204  *  Returns true, if the short message starts with
   199  *  WAP text message header set by SetWapTextMessage.
   205  *  WAP text message header set by SetWapTextMessage.
   200  */
   206  */
   201 TBool TWapTextMessage::Parse()
   207 TBool TWapTextMessage::Parse()
   202 	{
   208     {
   203 	TInt waplength = iWAPMessage.Length();
   209     TInt waplength = iWAPMessage.Length();
   204 	LOGWAPPROT2("TWapTextMessage::Parse [%d bytes]", waplength);
   210     OstTraceDef1(OST_TRACE_CATEGORY_DEBUG, TRACE_INTERNALS, TWAPTEXTMESSAGE_PARSE_1, "TWapTextMessage::Parse [%d bytes]", waplength);
   205 	if(waplength != 0)
   211     if(waplength != 0)
   206 		{
   212         {
   207 		// check whether long or short header
   213         // check whether long or short header
   208 		TInt iBaseIndex = -1;
   214         TInt iBaseIndex = -1;
   209 
   215 
   210 		// minimum length is 8 "//SCKxx "
   216         // minimum length is 8 "//SCKxx "
   211 		if(waplength >= 8)
   217         if(waplength >= 8)
   212 			{
   218             {
   213 			TPtrC8 HeaderIdPart(iWAPMessage.Left(6));
   219             TPtrC8 HeaderIdPart(iWAPMessage.Left(6));
   214 			if(!HeaderIdPart.Compare(KSCKHeaderLong))
   220             if(!HeaderIdPart.Compare(KSCKHeaderLong))
   215 				{
   221                 {
   216 				iBaseIndex = 0;
   222                 iBaseIndex = 0;
   217 				iIs16Bit = ETrue; // Yes, the ports are 16 bit wide
   223                 iIs16Bit = ETrue; // Yes, the ports are 16 bit wide
   218 				}
   224                 }
   219 			else
   225             else
   220 				HeaderIdPart.Set(iWAPMessage.Left(5));
   226                 HeaderIdPart.Set(iWAPMessage.Left(5));
   221 
   227 
   222 			if(iBaseIndex == (-1) && !HeaderIdPart.Compare(KSCKHeaderShort) )
   228             if(iBaseIndex == (-1) && !HeaderIdPart.Compare(KSCKHeaderShort) )
   223 				iBaseIndex = 3;
   229                 iBaseIndex = 3;
   224 			// else  no match
   230             // else  no match
   225 			}
   231             }
   226 
   232 
   227 		if(iBaseIndex >= 0)
   233         if(iBaseIndex >= 0)
   228 			{
   234             {
   229 			// check which of the TIndexInfos match
   235             // check which of the TIndexInfos match
   230 			for(TInt i=iBaseIndex; i<iBaseIndex+3; i++)
   236             for(TInt i=iBaseIndex; i<iBaseIndex+3; i++)
   231 				{
   237                 {
   232 				// Get length (index) of text header variant
   238                 // Get length (index) of text header variant
   233 				TInt lastIndex = KElemIndexes[i].iIndexes[KElemIndexes[i].iLastIndex];
   239                 TInt lastIndex = KElemIndexes[i].iIndexes[KElemIndexes[i].iLastIndex];
   234 				if (iWAPMessage.Length() <= lastIndex)
   240                 if (iWAPMessage.Length() <= lastIndex)
   235 					{
   241                     {
   236 					// no hope about match, because other variants are longer
   242                     // no hope about match, because other variants are longer
   237 					iIsWapTextMessage = EFalse;
   243                     iIsWapTextMessage = EFalse;
   238 					break;
   244                     break;
   239 					}
   245                     }
   240 
   246 
   241 				TInt LastChar = iWAPMessage[lastIndex];
   247                 TInt LastChar = iWAPMessage[lastIndex];
   242 				if (LastChar == '/' || LastChar == ' ' || LastChar == '\n')
   248                 if (LastChar == '/' || LastChar == ' ' || LastChar == '\n')
   243 					{
   249                     {
   244 					// reinitialize, because following maybe absent
   250                     // reinitialize, because following maybe absent
   245 					iTotalSegments = 1;
   251                     iTotalSegments = 1;
   246 					iSegmentNumber = 1;
   252                     iSegmentNumber = 1;
   247 					iIsWapTextMessage = ParseWapTextHeader(KElemIndexes[i]);
   253                     iIsWapTextMessage = ParseWapTextHeader(KElemIndexes[i]);
   248 					break;
   254                     break;
   249 					}
   255                     }
   250 
   256 
   251 				}
   257                 }
   252 
   258 
   253 			if (!iIsWapTextMessage)
   259             if (!iIsWapTextMessage)
   254 				{
   260                 {
   255 				LOGWAPPROT1("WARNING! illegal incoming WAP message");
   261                 OstTraceDef0(OST_TRACE_CATEGORY_DEBUG, TRACE_INTERNALS, TWAPTEXTMESSAGE_PARSE_2, "WARNING! illegal incoming WAP message");
   256 				}
   262                 }
   257 			}
   263             }
   258 		}
   264         }
   259 
   265 
   260 	return iIsWapTextMessage;
   266     return iIsWapTextMessage;
   261 	} // TWapTextMessage::Parse
   267     } // TWapTextMessage::Parse
   262 
   268 
   263 
   269 
   264 /**
   270 /**
   265  *  Parses a string of hex characters representing a number
   271  *  Parses a string of hex characters representing a number
   266  *  
   272  *  
   272  *  number. Maximum width of the hex value can be 4.
   278  *  number. Maximum width of the hex value can be 4.
   273  *  
   279  *  
   274  *  TODO use TLex instead
   280  *  TODO use TLex instead
   275  */
   281  */
   276 TInt TWapTextMessage::ParseNumber(const TDesC8& aInValue,
   282 TInt TWapTextMessage::ParseNumber(const TDesC8& aInValue,
   277 								  TBool   aBigEndian,
   283                                   TBool   aBigEndian,
   278 								  TInt    aRadix)
   284                                   TInt    aRadix)
   279 	{
   285     {
   280 	LOGWAPPROT2("TWapTextMessage::ParseNumber [%S]", &aInValue);
   286     OstTraceDefExt1(OST_TRACE_CATEGORY_DEBUG, TRACE_INTERNALS, TWAPTEXTMESSAGE_PARSENUMBER_1, "TWapTextMessage::ParseNumber [%s]", aInValue);
   281 	// least significant byte first
   287     // least significant byte first
   282 	TInt Values[4] = {0,0,0,0};
   288     TInt Values[4] = {0,0,0,0};
   283 	TInt Temp = 0;
   289     TInt Temp = 0;
   284 	TInt length = aInValue.Length();
   290     TInt length = aInValue.Length();
   285 	TInt i = 0;
   291     TInt i = 0;
   286 	TInt Value = 0;
   292     TInt Value = 0;
   287 
   293 
   288 	__ASSERT_DEBUG(length<5,Panic(KPanicInvalidParseNumber));
   294     __ASSERT_DEBUG(length<5,Panic(KPanicInvalidParseNumber));
   289     if( length >= 5 )
   295     if( length >= 5 )
   290         return KErrNotFound;
   296         return KErrNotFound;
   291 	for(i=0; i<length; i++)
   297     for(i=0; i<length; i++)
   292 		{
   298         {
   293 		Temp = aInValue[i];
   299         Temp = aInValue[i];
   294 		if (Temp>='0' && Temp<='9')
   300         if (Temp>='0' && Temp<='9')
   295 			Temp-='0';
   301             Temp-='0';
   296 		else if (Temp>='A' && Temp<='Z')
   302         else if (Temp>='A' && Temp<='Z')
   297 			Temp = Temp - 'A'+10;
   303             Temp = Temp - 'A'+10;
   298 		else if (Temp>='a' && Temp<='z')
   304         else if (Temp>='a' && Temp<='z')
   299 			Temp = Temp - 'a'+10;
   305             Temp = Temp - 'a'+10;
   300 		else
   306         else
   301             return KErrNotFound;
   307             return KErrNotFound;
   302 		if (aBigEndian)
   308         if (aBigEndian)
   303 			Values[(length-1)-i]=Temp;
   309             Values[(length-1)-i]=Temp;
   304 		else
   310         else
   305 			Values[i]=Temp;
   311             Values[i]=Temp;
   306 		}
   312         }
   307 
   313 
   308 	// build the value
   314     // build the value
   309 	Value=Values[0];
   315     Value=Values[0];
   310 	TInt Base=1;
   316     TInt Base=1;
   311 	for(i=1; i<length; i++)
   317     for(i=1; i<length; i++)
   312 		{
   318         {
   313 		Base*=aRadix;
   319         Base*=aRadix;
   314 		Value+=(Base)*Values[i];
   320         Value+=(Base)*Values[i];
   315 		}
   321         }
   316 
   322 
   317 	return Value;
   323     return Value;
   318 	} // TWapTextMessage::ParseNumber
   324     } // TWapTextMessage::ParseNumber
   319 
   325 
   320 
   326 
   321 /**
   327 /**
   322  *  parse the WAP text header
   328  *  parse the WAP text header
   323  *  
   329  *  
   326  *  Length of element is calculated by
   332  *  Length of element is calculated by
   327  *  subtracting current index value from the next one
   333  *  subtracting current index value from the next one
   328  *  except for KOtherHeader and user data, of course
   334  *  except for KOtherHeader and user data, of course
   329  */
   335  */
   330 TBool TWapTextMessage::ParseWapTextHeader(const TIndexInfo& aIndexArray)
   336 TBool TWapTextMessage::ParseWapTextHeader(const TIndexInfo& aIndexArray)
   331 	{
   337     {
   332 	LOGWAPPROT2("TWapTextMessage::ParseWapTextHeader: %S", &iWAPMessage );
   338     OstTraceDefExt1(OST_TRACE_CATEGORY_DEBUG, TRACE_INTERNALS, TWAPTEXTMESSAGE_PARSEWAPTEXTHEADER_1, "TWapTextMessage::ParseWapTextHeader: %s", iWAPMessage );
   333 
   339 
   334 	TInt ParsedNumber = 0;
   340     TInt ParsedNumber = 0;
   335 
   341 
   336 	// parse the header
   342     // parse the header
   337 	TInt ElemIndexCount=aIndexArray.iLastIndex+1;
   343     TInt ElemIndexCount=aIndexArray.iLastIndex+1;
   338 	for(TInt i=0; i<ElemIndexCount; i++)
   344     for(TInt i=0; i<ElemIndexCount; i++)
   339 		{
   345         {
   340 		if (i<ElemIndexCount-1)
   346         if (i<ElemIndexCount-1)
   341 			{
   347             {
   342 			// all the elems have a length defined in advance
   348             // all the elems have a length defined in advance
   343 			if (iWAPMessage.Length() >= aIndexArray.iIndexes[i+1])
   349             if (iWAPMessage.Length() >= aIndexArray.iIndexes[i+1])
   344 				{
   350                 {
   345 				// the header fits into the wap datagram
   351                 // the header fits into the wap datagram
   346 				TPtrC8 Elem(iWAPMessage.Mid(aIndexArray.iIndexes[i],
   352                 TPtrC8 Elem(iWAPMessage.Mid(aIndexArray.iIndexes[i],
   347 											aIndexArray.iIndexes[i+1]-
   353                                             aIndexArray.iIndexes[i+1]-
   348 											aIndexArray.iIndexes[i]));
   354                                             aIndexArray.iIndexes[i]));
   349 
   355 
   350 				ParsedNumber = ParseNumber(Elem,ETrue,16);
   356                 ParsedNumber = ParseNumber(Elem,ETrue,16);
   351                 if( ParsedNumber == KErrNotFound )
   357                 if( ParsedNumber == KErrNotFound )
   352                     return EFalse;
   358                     return EFalse;
   353 				switch(i)
   359                 switch(i)
   354 					{
   360                     {
   355 				  case KIndexDestinationPort:
   361                   case KIndexDestinationPort:
   356 					  iDestinationPort = ParsedNumber;
   362                       iDestinationPort = ParsedNumber;
   357 
   363 
   358 					  break;
   364                       break;
   359 				  case KIndexSourcePort:
   365                   case KIndexSourcePort:
   360 					  iSourcePort = ParsedNumber;
   366                       iSourcePort = ParsedNumber;
   361 					  break;
   367                       break;
   362 				  case KIndexReferenceNumber:
   368                   case KIndexReferenceNumber:
   363 					  iReference = ParsedNumber;
   369                       iReference = ParsedNumber;
   364 					  break;
   370                       break;
   365 				  case KIndexTotalSegments:
   371                   case KIndexTotalSegments:
   366 					  iTotalSegments = ParsedNumber;
   372                       iTotalSegments = ParsedNumber;
   367 					  break;
   373                       break;
   368 				  case KIndexSegmentNumber:
   374                   case KIndexSegmentNumber:
   369 					  iSegmentNumber = ParsedNumber;
   375                       iSegmentNumber = ParsedNumber;
   370 					  break;
   376                       break;
   371 				  default:
   377                   default:
   372 					  LOGWAPPROT2("Hm. unhandled WAP index [%d]", i );
   378                       OstTraceDef1(OST_TRACE_CATEGORY_DEBUG, TRACE_INTERNALS, TWAPTEXTMESSAGE_PARSEWAPTEXTHEADER_2, "Hm. unhandled WAP index [%d]", i );
   373 					  break;
   379                       break;
   374 					}
   380                     }
   375 				}
   381                 }
   376 			}
   382             }
   377 		else
   383         else
   378 			{
   384             {
   379 			// elems have not a length defined in advance
   385             // elems have not a length defined in advance
   380 			iOtherHeader = 0;
   386             iOtherHeader = 0;
   381 			iOtherHeaderLength = 0;
   387             iOtherHeaderLength = 0;
   382 
   388 
   383 			// Search the terminating character ' '
   389             // Search the terminating character ' '
   384 			iData = iWAPMessage.Locate(' ');
   390             iData = iWAPMessage.Locate(' ');
   385 			TInt dataTmp = iWAPMessage.Locate('\n');
   391             TInt dataTmp = iWAPMessage.Locate('\n');
   386 
   392 
   387 			if (iData == KErrNotFound)
   393             if (iData == KErrNotFound)
   388 				{
   394                 {
   389 				if (dataTmp == KErrNotFound)
   395                 if (dataTmp == KErrNotFound)
   390 					return EFalse;
   396                     return EFalse;
   391 				else
   397                 else
   392 					iData = dataTmp;
   398                     iData = dataTmp;
   393 				}
   399                 }
   394 			else if (dataTmp != KErrNotFound)
   400             else if (dataTmp != KErrNotFound)
   395 				iData = Min(iData, dataTmp);
   401                 iData = Min(iData, dataTmp);
   396 
   402 
   397 			// check the existence of other header
   403             // check the existence of other header
   398 			// at least "// " should be there
   404             // at least "// " should be there
   399 			if (   iWAPMessage.Length() > aIndexArray.iIndexes[i]+2
   405             if (   iWAPMessage.Length() > aIndexArray.iIndexes[i]+2
   400 				   && iWAPMessage[aIndexArray.iIndexes[i]] == '/'
   406                    && iWAPMessage[aIndexArray.iIndexes[i]] == '/'
   401 				   && iWAPMessage[aIndexArray.iIndexes[i]+1] == '/')
   407                    && iWAPMessage[aIndexArray.iIndexes[i]+1] == '/')
   402 				{
   408                 {
   403 				iOtherHeader = aIndexArray.iIndexes[i];
   409                 iOtherHeader = aIndexArray.iIndexes[i];
   404 				iOtherHeaderLength=iData-iOtherHeader;
   410                 iOtherHeaderLength=iData-iOtherHeader;
   405 				}
   411                 }
   406 
   412 
   407 			// data: check if any characters after ' '
   413             // data: check if any characters after ' '
   408 			iDataLength = 0;
   414             iDataLength = 0;
   409 			iData++;
   415             iData++;
   410 			if (iWAPMessage.Length() > iData)
   416             if (iWAPMessage.Length() > iData)
   411 				{
   417                 {
   412 				iDataLength = iWAPMessage.Length() - iData;
   418                 iDataLength = iWAPMessage.Length() - iData;
   413 				}
   419                 }
   414 
   420 
   415 			// That's it
   421             // That's it
   416 			} // end of other header and data
   422             } // end of other header and data
   417 		}// end of for loop
   423         }// end of for loop
   418 	return ETrue;
   424     return ETrue;
   419 	} // TWapTextMessage::ParseWapTextHeader
   425     } // TWapTextMessage::ParseWapTextHeader
   420 
   426 
   421 
   427 
   422 /**
   428 /**
   423  *  Length of header is returned
   429  *  Length of header is returned
   424  *  Sets internally the iTotalSegments
   430  *  Sets internally the iTotalSegments
   430  *  The segment number can be set by inserting it into aSegmentNumberIndex position
   436  *  The segment number can be set by inserting it into aSegmentNumberIndex position
   431  *  If SAR is not needed aSegmentNumberIndex = 0 and
   437  *  If SAR is not needed aSegmentNumberIndex = 0 and
   432  *  aFixedHeader.Length() == (return value of this function) is true
   438  *  aFixedHeader.Length() == (return value of this function) is true
   433  */
   439  */
   434 TInt TWapTextMessage::CreateHeader(TDes8& aFixedHeader, TInt& aSegmentNumberIndex)
   440 TInt TWapTextMessage::CreateHeader(TDes8& aFixedHeader, TInt& aSegmentNumberIndex)
   435 	{
   441     {
   436 	LOGWAPPROT1("TWapTextMessage::CreateHeader");
   442     OstTraceDef0(OST_TRACE_CATEGORY_DEBUG, TRACE_INTERNALS, TWAPTEXTMESSAGE_CREATEHEADER_1, "TWapTextMessage::CreateHeader");
   437 
   443 
   438 	// Index into KElemIndexes indicating which header elements are present
   444     // Index into KElemIndexes indicating which header elements are present
   439 	TInt elemIndex;
   445     TInt elemIndex;
   440 	// Index into Indexes, for current header element
   446     // Index into Indexes, for current header element
   441 	TInt minorIndex=KIndexDestinationPort;
   447     TInt minorIndex=KIndexDestinationPort;
   442 	TBuf8<4> hexNumber;
   448     TBuf8<4> hexNumber;
   443 
   449 
   444 	// Segment number length is set, if SAR is needed
   450     // Segment number length is set, if SAR is needed
   445 	TInt segmentNumberLength = 0;
   451     TInt segmentNumberLength = 0;
   446 	aSegmentNumberIndex = 0;
   452     aSegmentNumberIndex = 0;
   447 
   453 
   448 	// Determine whether long or short form is used
   454     // Determine whether long or short form is used
   449 	if (iIs16Bit || iSourcePort > 255 || iDestinationPort>255)
   455     if (iIs16Bit || iSourcePort > 255 || iDestinationPort>255)
   450 		{
   456         {
   451 		elemIndex = 0;
   457         elemIndex = 0;
   452 		aFixedHeader.Copy(KSCKHeaderLong);
   458         aFixedHeader.Copy(KSCKHeaderLong);
   453 		}
   459         }
   454 	else
   460     else
   455 		{
   461         {
   456 		elemIndex = 3;
   462         elemIndex = 3;
   457 		aFixedHeader.Copy(KSCKHeaderShort);
   463         aFixedHeader.Copy(KSCKHeaderShort);
   458 		}
   464         }
   459 
   465 
   460 	// Set destination port
   466     // Set destination port
   461 	hexNumber.NumFixedWidthUC(iDestinationPort,EHex,
   467     hexNumber.NumFixedWidthUC(iDestinationPort,EHex,
   462 							  KElemIndexes[elemIndex].iIndexes[minorIndex+1]-KElemIndexes[elemIndex].iIndexes[minorIndex]);
   468                               KElemIndexes[elemIndex].iIndexes[minorIndex+1]-KElemIndexes[elemIndex].iIndexes[minorIndex]);
   463 	aFixedHeader.Append(hexNumber);
   469     aFixedHeader.Append(hexNumber);
   464 
   470 
   465 	// Don't set the source port,
   471     // Don't set the source port,
   466 	// 1) if it is not set or it same as destination port and
   472     // 1) if it is not set or it same as destination port and
   467 	// 2) data (and other header) fits in one segment
   473     // 2) data (and other header) fits in one segment
   468 	if (!((iSourcePort==-1 || iDestinationPort==iSourcePort)
   474     if (!((iSourcePort==-1 || iDestinationPort==iSourcePort)
   469 		  && CalculateTotalSegments(KElemIndexes[elemIndex].iIndexes[minorIndex+1])==1))
   475           && CalculateTotalSegments(KElemIndexes[elemIndex].iIndexes[minorIndex+1])==1))
   470 		{
   476         {
   471 		// Source port is present
   477         // Source port is present
   472 		elemIndex++;
   478         elemIndex++;
   473 		minorIndex++;
   479         minorIndex++;
   474 		if (iSourcePort==-1)
   480         if (iSourcePort==-1)
   475 			iSourcePort = iDestinationPort;
   481             iSourcePort = iDestinationPort;
   476 
   482 
   477 		// Set source port
   483         // Set source port
   478 		hexNumber.NumFixedWidthUC(iSourcePort,EHex,
   484         hexNumber.NumFixedWidthUC(iSourcePort,EHex,
   479 								  KElemIndexes[elemIndex].iIndexes[minorIndex+1]-KElemIndexes[elemIndex].iIndexes[minorIndex]);
   485                                   KElemIndexes[elemIndex].iIndexes[minorIndex+1]-KElemIndexes[elemIndex].iIndexes[minorIndex]);
   480 		aFixedHeader.Append(hexNumber);
   486         aFixedHeader.Append(hexNumber);
   481 
   487 
   482 		// Add the SAR info when source port is set
   488         // Add the SAR info when source port is set
   483 		elemIndex++;
   489         elemIndex++;
   484 
   490 
   485 		// Set reference
   491         // Set reference
   486 		minorIndex++;
   492         minorIndex++;
   487 		hexNumber.NumFixedWidthUC(iReference,EHex,
   493         hexNumber.NumFixedWidthUC(iReference,EHex,
   488 								  KElemIndexes[elemIndex].iIndexes[minorIndex+1]-KElemIndexes[elemIndex].iIndexes[minorIndex]);
   494                                   KElemIndexes[elemIndex].iIndexes[minorIndex+1]-KElemIndexes[elemIndex].iIndexes[minorIndex]);
   489 		aFixedHeader.Append(hexNumber);
   495         aFixedHeader.Append(hexNumber);
   490 
   496 
   491 		// Set fragment count
   497         // Set fragment count
   492 		minorIndex++;
   498         minorIndex++;
   493 		CalculateTotalSegments(KElemIndexes[elemIndex].iIndexes[KElemIndexes[elemIndex].iLastIndex]);
   499         CalculateTotalSegments(KElemIndexes[elemIndex].iIndexes[KElemIndexes[elemIndex].iLastIndex]);
   494 		hexNumber.NumFixedWidthUC(iTotalSegments,EHex,
   500         hexNumber.NumFixedWidthUC(iTotalSegments,EHex,
   495 								  KElemIndexes[elemIndex].iIndexes[minorIndex+1]-KElemIndexes[elemIndex].iIndexes[minorIndex]);
   501                                   KElemIndexes[elemIndex].iIndexes[minorIndex+1]-KElemIndexes[elemIndex].iIndexes[minorIndex]);
   496 		aFixedHeader.Append(hexNumber);
   502         aFixedHeader.Append(hexNumber);
   497 
   503 
   498 		// Return the index for segment number in the header
   504         // Return the index for segment number in the header
   499 		minorIndex++;
   505         minorIndex++;
   500 		aSegmentNumberIndex = KElemIndexes[elemIndex].iIndexes[minorIndex];
   506         aSegmentNumberIndex = KElemIndexes[elemIndex].iIndexes[minorIndex];
   501 		segmentNumberLength = 2;
   507         segmentNumberLength = 2;
   502 		}
   508         }
   503 
   509 
   504 	aFixedHeader.Append(iRefOtherHeader);
   510     aFixedHeader.Append(iRefOtherHeader);
   505 	aFixedHeader.Append(_L(" "));
   511     aFixedHeader.Append(_L(" "));
   506 
   512 
   507 	return aFixedHeader.Length()+segmentNumberLength;
   513     return aFixedHeader.Length()+segmentNumberLength;
   508 	} // TWapTextMessage::CreateHeader
   514     } // TWapTextMessage::CreateHeader
   509 
   515 
   510 
   516 
   511 /**
   517 /**
   512  *  Calculates count of segments to send a used data (based on iRefData)
   518  *  Calculates count of segments to send a used data (based on iRefData)
   513  *  The values is assigned to iTotalSegments
   519  *  The values is assigned to iTotalSegments
   514  *  The affect of terminating ' ' is taken into inside the method
   520  *  The affect of terminating ' ' is taken into inside the method
   515  */
   521  */
   516 TInt TWapTextMessage::CalculateTotalSegments(TInt aFixedLength)
   522 TInt TWapTextMessage::CalculateTotalSegments(TInt aFixedLength)
   517 	{
   523     {
   518 	LOGWAPPROT2("TWapTextMessage::CalculateTotalSegments [aFixedLength=%d]", aFixedLength);
   524     OstTraceDef1(OST_TRACE_CATEGORY_DEBUG, TRACE_INTERNALS, TWAPTEXTMESSAGE_CALCULATETOTALSEGMENTS_1, "TWapTextMessage::CalculateTotalSegments [aFixedLength=%d]", aFixedLength);
   519 
   525 
   520 	// '+1': length of terminating ' '
   526     // '+1': length of terminating ' '
   521 	TInt  length        = aFixedLength + iRefOtherHeader.Length() + 1;
   527     TInt  length        = aFixedLength + iRefOtherHeader.Length() + 1;
   522 	TInt  remain        = KMaxSmsChars - length;
   528     TInt  remain        = KMaxSmsChars - length;
   523 	TInt  dataSegmented = 0;
   529     TInt  dataSegmented = 0;
   524 
   530 
   525 	__ASSERT_DEBUG(remain > 0, Panic(KPanicTextHeaderTooLong));
   531     __ASSERT_DEBUG(remain > 0, Panic(KPanicTextHeaderTooLong));
   526 
   532 
   527 	iTotalSegments = 0;
   533     iTotalSegments = 0;
   528 	do
   534     do
   529 		{
   535         {
   530 		iTotalSegments++;
   536         iTotalSegments++;
   531 
   537 
   532 		//
   538         //
   533 		// Count any escaped characters we can be sure that the converted data
   539         // Count any escaped characters we can be sure that the converted data
   534 		// size fits inside the remaining length (e.g. so that non-7bit characters
   540         // size fits inside the remaining length (e.g. so that non-7bit characters
   535 		// when converted by the SMS Stack will still fit).
   541         // when converted by the SMS Stack will still fit).
   536 		//
   542         //
   537 		TInt  segmentSize = iRefData.Length() - dataSegmented;
   543         TInt  segmentSize = iRefData.Length() - dataSegmented;
   538 
   544 
   539 		if (segmentSize > remain)
   545         if (segmentSize > remain)
   540 			{
   546             {
   541 			segmentSize = remain;
   547             segmentSize = remain;
   542 			}
   548             }
   543 
   549 
   544 		while (segmentSize > 1)
   550         while (segmentSize > 1)
   545 			{
   551             {
   546 			TPtrC8  segmentData(iRefData.Mid(dataSegmented, segmentSize));
   552             TPtrC8  segmentData(iRefData.Mid(dataSegmented, segmentSize));
   547 			TInt  non7bitCharEscapes = 0;
   553             TInt  non7bitCharEscapes = 0;
   548 			
   554             
   549 			//
   555             //
   550 			// Count all non-7bit characters that will be escaped (many non-7bit
   556             // Count all non-7bit characters that will be escaped (many non-7bit
   551 			// characters are not escaped, but converted to "?"). The ones
   557             // characters are not escaped, but converted to "?"). The ones
   552 			// that are known to be escaped are list below:
   558             // that are known to be escaped are list below:
   553 			//
   559             //
   554 			//	  12  [Form Feed].
   560             //    12  [Form Feed].
   555 			//	  91  "["
   561             //    91  "["
   556 			//	  92  "\"
   562             //    92  "\"
   557 			//	  93  "]"
   563             //    93  "]"
   558 			//	  94  "^"
   564             //    94  "^"
   559 			//	 123  "{"
   565             //   123  "{"
   560 			//	 124  "|"
   566             //   124  "|"
   561 			//	 125  "}"
   567             //   125  "}"
   562 			//	 126  "~"
   568             //   126  "~"
   563 			//
   569             //
   564 			for (TInt  ch = 0;  ch < segmentSize;  ch++)
   570             for (TInt  ch = 0;  ch < segmentSize;  ch++)
   565 				{
   571                 {
   566 				if (segmentData[ch] == 12  ||
   572                 if (segmentData[ch] == 12  ||
   567 					(segmentData[ch] >= 91  &&  segmentData[ch] <= 94)  ||
   573                     (segmentData[ch] >= 91  &&  segmentData[ch] <= 94)  ||
   568 					(segmentData[ch] >= 123  &&  segmentData[ch] <= 126))
   574                     (segmentData[ch] >= 123  &&  segmentData[ch] <= 126))
   569 					{
   575                     {
   570 					non7bitCharEscapes++;
   576                     non7bitCharEscapes++;
   571 					}
   577                     }
   572 				}
   578                 }
   573 			
   579             
   574 			//
   580             //
   575 			// Can it fit? If so store it, otherwise reduce the size...
   581             // Can it fit? If so store it, otherwise reduce the size...
   576 			//
   582             //
   577 			if (segmentData.Length() + non7bitCharEscapes <= remain)
   583             if (segmentData.Length() + non7bitCharEscapes <= remain)
   578 				{
   584                 {
   579 				break;
   585                 break;
   580 				}
   586                 }
   581 			
   587             
   582 			segmentSize--;
   588             segmentSize--;
   583 			}
   589             }
   584 		
   590         
   585 			dataSegmented += segmentSize;
   591             dataSegmented += segmentSize;
   586 		}
   592         }
   587 	while (dataSegmented < iRefData.Length());
   593     while (dataSegmented < iRefData.Length());
   588 	
   594     
   589 	//
   595     //
   590 	// At least one fragment is needed...
   596     // At least one fragment is needed...
   591 	//
   597     //
   592 	if (iTotalSegments == 0)
   598     if (iTotalSegments == 0)
   593 		{
   599         {
   594 		iTotalSegments = 1;
   600         iTotalSegments = 1;
   595 		}
   601         }
   596 
   602 
   597 	return iTotalSegments;
   603     return iTotalSegments;
   598 	} // TWapTextMessage::CalculateTotalSegments
   604     } // TWapTextMessage::CalculateTotalSegments
   599 
   605 
   600 // EOF - WAPTHDR.CPP
   606 // EOF - WAPTHDR.CPP