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