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