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