|
1 // Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // |
|
15 |
|
16 #include "gsmubuf.h" |
|
17 #include "gsmuset.h" |
|
18 #include "Gsmuelem.h" |
|
19 #include "Gsmumsg.h" |
|
20 #include "gsmusar.h" |
|
21 #include "gsmupdu.h" |
|
22 #include "WAPDGRM.H" |
|
23 #include "ws_main.h" |
|
24 #include "smsstackutils.h" |
|
25 |
|
26 // |
|
27 // For incoming short message |
|
28 // |
|
29 CWapDatagram* CWapDatagram::NewL(const CSmsMessage& aSms) |
|
30 { |
|
31 LOGWAPPROT2("CWapDatagram::NewL(): aSms=0x%08x", (TInt) &aSms); |
|
32 |
|
33 CWapDatagram* datagram = new (ELeave)CWapDatagram(); |
|
34 |
|
35 CleanupStack::PushL(datagram); |
|
36 datagram->ConstructL(aSms); |
|
37 CleanupStack::Pop(); |
|
38 |
|
39 LOGWAPPROT2("CWapDatagram::NewL(): iFromPort: %d", datagram->iFromPort); |
|
40 LOGWAPPROT2("CWapDatagram::NewL(): iToPort: %d", datagram->iToPort); |
|
41 LOGWAPPROT2("CWapDatagram::NewL(): iReference: %d", datagram->iReference); |
|
42 LOGWAPPROT2("CWapDatagram::NewL(): iTotalSegments: %d", datagram->iTotalSegments); |
|
43 LOGWAPPROT2("CWapDatagram::NewL(): iSegmentNumber: %d", datagram->iSegmentNumber); |
|
44 LOGWAPPROT2("CWapDatagram::NewL(): iIsComplete: %d", datagram->iIsComplete); |
|
45 LOGWAPPROT2("CWapDatagram::NewL(): iReference: %d", datagram->iReference); |
|
46 LOGWAPPROT2("CWapDatagram::NewL(): iIsTextHeader: %d", datagram->iIsTextHeader); |
|
47 LOGWAPPROT2("CWapDatagram::NewL(): iLogServerId: %d", datagram->iLogServerId); |
|
48 LOGWAPPROT2("CWapDatagram::NewL(): i16BitPorts: %d", datagram->i16BitPorts); |
|
49 |
|
50 // assert destination port |
|
51 if (datagram->i16BitPorts) |
|
52 { |
|
53 if (datagram->iToPort>=0 && datagram->iToPort<=65535) |
|
54 { |
|
55 LOGWAPPROT1("iToPort OK"); |
|
56 } |
|
57 else |
|
58 { |
|
59 LOGWAPPROT1("iToPort FAILED"); |
|
60 } |
|
61 } |
|
62 else |
|
63 { |
|
64 if (datagram->iToPort>=0 && datagram->iToPort<=255) |
|
65 { |
|
66 LOGWAPPROT1("iToPort OK"); |
|
67 } |
|
68 else |
|
69 { |
|
70 LOGWAPPROT1("iToPort FAILED"); |
|
71 } |
|
72 } |
|
73 |
|
74 if (datagram->i16BitPorts) |
|
75 { |
|
76 if (datagram->iFromPort>=0 && datagram->iFromPort<=65535) |
|
77 { |
|
78 LOGWAPPROT1("iFromPort OK"); |
|
79 } |
|
80 else |
|
81 { |
|
82 LOGWAPPROT1("iFromPort FAILED"); |
|
83 } |
|
84 } |
|
85 else |
|
86 { |
|
87 if (datagram->iFromPort>=0 && datagram->iFromPort<=255) |
|
88 { |
|
89 LOGWAPPROT1("iFromPort OK"); |
|
90 } |
|
91 else |
|
92 { |
|
93 LOGWAPPROT1("iFromPort FAILED"); |
|
94 } |
|
95 } |
|
96 |
|
97 return datagram; |
|
98 } // CWapDatagram::NewL |
|
99 |
|
100 |
|
101 // |
|
102 // For outgoing short messages |
|
103 // |
|
104 CWapDatagram* CWapDatagram::NewL(const TDesC8& aSendBuffer) |
|
105 { |
|
106 LOGWAPPROT2("CWapDatagram::NewL(): aSendBuffer=0x%08x", (TInt) &aSendBuffer); |
|
107 |
|
108 CWapDatagram* datagram = new (ELeave)CWapDatagram(); |
|
109 |
|
110 CleanupStack::PushL(datagram); |
|
111 datagram->Construct(aSendBuffer); |
|
112 CleanupStack::Pop(); |
|
113 |
|
114 return datagram; |
|
115 } // CWapDatagram::NewL |
|
116 |
|
117 |
|
118 CWapDatagram::~CWapDatagram() |
|
119 { |
|
120 LOGWAPPROT1("CWapDatagram::~CWapDatagram()"); |
|
121 |
|
122 delete iRecvbuf; |
|
123 delete iBuffer; |
|
124 delete iSegment; |
|
125 } // CWapDatagram::~CWapDatagram |
|
126 |
|
127 |
|
128 // |
|
129 // What about service centre address ? |
|
130 // aSmsMessageArray contains CSmsMessage objects |
|
131 // |
|
132 void CWapDatagram::EncodeConcatenatedMessagesL(RFs& aFs, CArrayPtr<CSmsMessage>& aSmsMessageArray) |
|
133 { |
|
134 LOGWAPPROT2("CWapDatagram::EncodeConcatenatedMessagesL(): %d messages", aSmsMessageArray.Count()); |
|
135 |
|
136 // Couple of checkings makes sense |
|
137 __ASSERT_DEBUG(iToPort >=0 && iToAddress.Length()>=0 |
|
138 && (iUserDataSettings.Alphabet()==TSmsDataCodingScheme::ESmsAlphabet8Bit |
|
139 || iUserDataSettings.Alphabet()==TSmsDataCodingScheme::ESmsAlphabet7Bit), |
|
140 Panic(KPanicUsageError)); |
|
141 |
|
142 // Determine CSmsMessage encoding by character width |
|
143 if (iUserDataSettings.Alphabet() == TSmsDataCodingScheme::ESmsAlphabet8Bit) |
|
144 { |
|
145 CSmsBufferBase* SmsBuffer = CSmsBuffer::NewL(); |
|
146 |
|
147 CleanupStack::PushL(SmsBuffer); |
|
148 ConvertL(iSendBuffer,*SmsBuffer); |
|
149 CleanupStack::Pop(); // SmsBuffer, popped here since it is pushed again in the following NewL call |
|
150 CSmsMessage* SmsMessage = CSmsMessage::NewL(aFs, CSmsPDU::ESmsSubmit,SmsBuffer,EFalse); |
|
151 CleanupStack::PushL(SmsMessage); |
|
152 // one and only object |
|
153 aSmsMessageArray.AppendL(SmsMessage); |
|
154 CleanupStack::Pop(); // SmsMessage |
|
155 |
|
156 SetSmsMessageSettingsL(*SmsMessage,ETrue); |
|
157 } |
|
158 else |
|
159 { |
|
160 // contruct TWapTextMessage object |
|
161 TWapTextMessage* Segment = new (ELeave) TWapTextMessage(KNullDesC8); |
|
162 CleanupStack::PushL(Segment); |
|
163 CArrayPtrFlat<HBufC8>* SegmentArray = new (ELeave) CArrayPtrFlat<HBufC8> (8); |
|
164 CleanupStack::PushL(SegmentArray); |
|
165 CleanupResetAndDestroyPushL(*SegmentArray); |
|
166 |
|
167 Segment->SetDestinationPort(iToPort,i16BitPorts); |
|
168 Segment->SetSourcePort(iFromPort,i16BitPorts); |
|
169 Segment->SetReferenceNumber(iReference); |
|
170 Segment->SetUserData(iSendBuffer); |
|
171 Segment->SetOtherHeader(iOtherHeader); |
|
172 Segment->EncodeSegmentsL(*SegmentArray); |
|
173 |
|
174 // contruct array of CSmsMessages |
|
175 TInt Count = SegmentArray->Count(); |
|
176 for (TInt i=0; i<Count; i++) |
|
177 { |
|
178 CSmsBufferBase* SmsBuffer = CSmsBuffer::NewL(); |
|
179 |
|
180 CleanupStack::PushL(SmsBuffer); |
|
181 ConvertL(*(SegmentArray->At(i)),*SmsBuffer); |
|
182 CleanupStack::Pop(); // SmsBuffer, popped here since it is pushed again in the following NewL call |
|
183 CSmsMessage* SmsMessage=CSmsMessage::NewL(aFs, CSmsPDU::ESmsSubmit,SmsBuffer,EFalse); |
|
184 CleanupStack::PushL(SmsMessage); |
|
185 aSmsMessageArray.AppendL(SmsMessage); |
|
186 CleanupStack::Pop(); // SmsMessage |
|
187 |
|
188 SetSmsMessageSettingsL(*SmsMessage,EFalse); |
|
189 } |
|
190 CleanupStack::PopAndDestroy(3, Segment); // SegmentArray elements (Reset and Destroy), SegmentArray, Segment |
|
191 |
|
192 } |
|
193 } // CWapDatagram::EncodeConcatenatedMessagesL |
|
194 |
|
195 void CWapDatagram::DecodeConcatenatedMessagesL(CArrayPtr<TSegmentData>& aSmsMessageArray) |
|
196 { |
|
197 LOGWAPPROT1("CWapDatagram::DecodeConcatenatedMessagesL()"); |
|
198 |
|
199 // The TSegmentData elements are in the random order in the array |
|
200 TInt Count = aSmsMessageArray.Count(); |
|
201 TInt i=0; |
|
202 |
|
203 if (Count > 0) |
|
204 { |
|
205 TInt DataLength = 0; // total length of data |
|
206 TInt TempLength = 0; |
|
207 |
|
208 // Every TSegmentData should be equal length except last segment |
|
209 // Use that 'constant' segment length as indexes |
|
210 // Count the actual data length |
|
211 for(i=0; i<Count; i++) |
|
212 { |
|
213 TempLength = aSmsMessageArray.At(i)->iData.Length(); |
|
214 DataLength += TempLength; |
|
215 } |
|
216 |
|
217 TSegmentData* Segment = NULL; |
|
218 |
|
219 if (iBuffer) |
|
220 { |
|
221 delete iBuffer; |
|
222 iBuffer = NULL; |
|
223 } |
|
224 iBuffer = HBufC8::NewL(DataLength ); |
|
225 |
|
226 TPtr8 BufferPtr(iBuffer->Des()); |
|
227 BufferPtr.SetLength(DataLength ); |
|
228 |
|
229 TInt segmentStartPosition=0; |
|
230 |
|
231 for(i=0; i<Count; i++) |
|
232 { |
|
233 if (segmentStartPosition >= DataLength) |
|
234 { |
|
235 // Once the start position is out of range, |
|
236 // there is no point in continuing reconstructing the |
|
237 // wapdatagram. |
|
238 break; |
|
239 } |
|
240 |
|
241 Segment = aSmsMessageArray.At(i); |
|
242 TPtr8 CopyBufferPtr(&(BufferPtr[segmentStartPosition]),0,160); |
|
243 CopyBufferPtr.Copy(Segment->iData); |
|
244 segmentStartPosition+=Segment->iData.Length(); |
|
245 } |
|
246 } |
|
247 iIsComplete = ETrue; |
|
248 } // CWapDatagram::DecodeConcatenatedMessagesL |
|
249 |
|
250 |
|
251 void CWapDatagram::InternalizeL(RReadStream& aStream) |
|
252 { |
|
253 aStream >> iUserDataSettings; |
|
254 aStream >> iToAddress; |
|
255 iToPort = aStream.ReadInt32L(); |
|
256 aStream >> iFromAddress; |
|
257 iFromPort = aStream.ReadInt32L(); |
|
258 TInt64 time; |
|
259 aStream >> time; |
|
260 iTime = time; |
|
261 iUTCOffset = aStream.ReadInt32L(); |
|
262 iIsTextHeader = aStream.ReadInt32L(); |
|
263 iReference = aStream.ReadInt32L(); |
|
264 iTotalSegments = aStream.ReadInt32L(); |
|
265 iSegmentNumber = aStream.ReadInt32L(); |
|
266 iLogServerId = aStream.ReadInt32L(); |
|
267 iVersionNumber = aStream.ReadInt32L(); |
|
268 iSpare1 = aStream.ReadInt32L(); |
|
269 iSpare2 = aStream.ReadInt32L(); |
|
270 iSpare3 = aStream.ReadInt32L(); |
|
271 |
|
272 // Required for version 1, which is reading and internalizing extra SMS parameters from stream |
|
273 if(iVersionNumber == EFirstVersion) |
|
274 { |
|
275 TInt length = aStream.ReadInt32L(); |
|
276 if(length>0) |
|
277 { |
|
278 HBufC8* smsBuffer=HBufC8::NewMaxLC(length); |
|
279 TPtr8 recvbuftmp = smsBuffer->Des(); |
|
280 aStream >> recvbuftmp; |
|
281 if(!iRecvbuf) |
|
282 { |
|
283 iRecvbuf = CBufFlat::NewL(KSmsBufferExpansion); |
|
284 } |
|
285 iRecvbuf->ResizeL(recvbuftmp.Size()); |
|
286 iRecvbuf->Write(0, recvbuftmp); |
|
287 CleanupStack::PopAndDestroy(smsBuffer); |
|
288 } |
|
289 } |
|
290 |
|
291 } // CWapDatagram::InternalizeL |
|
292 |
|
293 |
|
294 // |
|
295 // Reads iBuffer from stream (for 8Bit messages) |
|
296 // |
|
297 void CWapDatagram::InternalizeBufferL(RReadStream& aStream) |
|
298 { |
|
299 TInt length; |
|
300 length=aStream.ReadInt32L(); |
|
301 iBuffer=HBufC8::NewMaxL(length); |
|
302 TPtr8 tmp = iBuffer->Des(); |
|
303 aStream >> tmp; |
|
304 iIsComplete = ETrue; |
|
305 } |
|
306 |
|
307 |
|
308 void CWapDatagram::ExternalizeL(RWriteStream& aStream) const |
|
309 { |
|
310 aStream << iUserDataSettings; |
|
311 aStream << iToAddress; |
|
312 aStream.WriteInt32L(iToPort); |
|
313 |
|
314 aStream << iFromAddress; |
|
315 aStream.WriteInt32L(iFromPort); |
|
316 aStream << iTime.Int64(); |
|
317 aStream.WriteInt32L(iUTCOffset.Int()); |
|
318 |
|
319 aStream.WriteInt32L(iIsTextHeader); |
|
320 aStream.WriteInt32L(iReference); |
|
321 aStream.WriteInt32L(iTotalSegments); |
|
322 aStream.WriteInt32L(iSegmentNumber); |
|
323 |
|
324 aStream.WriteInt32L(iLogServerId); |
|
325 |
|
326 aStream.WriteInt32L(iVersionNumber); |
|
327 aStream.WriteInt32L(iSpare1); |
|
328 aStream.WriteInt32L(iSpare2); |
|
329 aStream.WriteInt32L(iSpare3); |
|
330 |
|
331 // Externalizing the SMS params if exists |
|
332 if(iRecvbuf) |
|
333 { |
|
334 TPtr8 recvbuftmp = iRecvbuf->Ptr(0); |
|
335 aStream.WriteInt32L(recvbuftmp.Length()); |
|
336 aStream << recvbuftmp; |
|
337 } |
|
338 else |
|
339 { |
|
340 aStream.WriteInt32L(0); |
|
341 } |
|
342 } |
|
343 |
|
344 |
|
345 // |
|
346 // writes iBuffer to writeStream for 8-bit incomming messages |
|
347 // |
|
348 void CWapDatagram::ExternalizeBufferL(RWriteStream& aStream) const |
|
349 { |
|
350 TInt length= WapDatagramLength(); |
|
351 aStream.WriteInt32L(length); |
|
352 TPtr8 tmp= iBuffer->Des(); |
|
353 aStream << tmp; |
|
354 |
|
355 } // CWapDatagram::ExternalizeBufferL |
|
356 |
|
357 |
|
358 // |
|
359 // Outgoing |
|
360 // |
|
361 void CWapDatagram::Construct(const TDesC8& aSendBuffer) |
|
362 { |
|
363 LOGWAPPROT1("CWapDatagram::Construct()"); |
|
364 |
|
365 // Set version number to 1, as we have had to make |
|
366 // changes to CWapDatagram for CR0929 |
|
367 iVersionNumber = EFirstVersion; |
|
368 |
|
369 iSendBuffer.Set(aSendBuffer); |
|
370 } // CWapDatagram::Construct |
|
371 |
|
372 |
|
373 // |
|
374 // Incoming |
|
375 // code actualy supports 7-bit characters and port numbers |
|
376 // encoded in information elements (IE) although it is not |
|
377 // a requirement |
|
378 // |
|
379 void CWapDatagram::ConstructL(const CSmsMessage& aSms) |
|
380 { |
|
381 LOGWAPPROT1("CWapDatagram::ConstructL()"); |
|
382 |
|
383 // Set version number to 1, as we have had to make |
|
384 // changes to CWapDatagram for CR0929 |
|
385 iVersionNumber = EFirstVersion; |
|
386 |
|
387 iRecvbuf = CBufFlat::NewL(KSmsBufferExpansion); |
|
388 |
|
389 RBufWriteStream writestream(*iRecvbuf); |
|
390 writestream.Open(*iRecvbuf); |
|
391 CleanupClosePushL(writestream); |
|
392 |
|
393 // Externalizing everything within CSMSMessage except buffer |
|
394 aSms.ExternalizeWithoutBufferL(writestream); |
|
395 |
|
396 CleanupStack::PopAndDestroy(); // writestream |
|
397 |
|
398 iRecvbuf->Compress(); |
|
399 |
|
400 const CSmsBufferBase& SmsBufferBase = aSms.Buffer(); |
|
401 |
|
402 GetDatagramSettings(aSms); |
|
403 |
|
404 // Get the data from CSmsMessage and convert |
|
405 // SmsBuffer store Unicode short message from CSmsMessage |
|
406 ConvertL(SmsBufferBase,&iBuffer); |
|
407 GetDatagramSettingsL(); |
|
408 |
|
409 iIsComplete = ETrue; |
|
410 if (iUserDataSettings.Alphabet() == TSmsDataCodingScheme::ESmsAlphabet7Bit) |
|
411 { |
|
412 // this is a good candidate to include a text header. |
|
413 if (iIsTextHeader) |
|
414 { |
|
415 // there is still a minor chance that message is complete: |
|
416 // one fragment long datagram |
|
417 if (iTotalSegments == 1) |
|
418 { |
|
419 // Get the segment data |
|
420 TPtr8 PtrNarrow = iBuffer->Des(); |
|
421 PtrNarrow.Zero(); |
|
422 iSegment->UserData(PtrNarrow); |
|
423 } |
|
424 else |
|
425 { |
|
426 iIsComplete = EFalse; |
|
427 // delete incomplete message from iBuffer; |
|
428 delete iBuffer; |
|
429 iBuffer = 0; |
|
430 } |
|
431 } |
|
432 else |
|
433 // This means that IEs with 7-bits are used |
|
434 // Happily we support it |
|
435 // But what TODO if we are here due to an error, because |
|
436 // 7-bit with IEs should never happen ? |
|
437 iIsComplete = ETrue; |
|
438 |
|
439 } |
|
440 } // CWapDatagram::ConstructL |
|
441 |
|
442 |
|
443 // |
|
444 // Set WAP datagram private members from a text based concatenated message |
|
445 // Copies contents of iBuffer to iSmsBuffer |
|
446 // Allocates iSegment object |
|
447 // |
|
448 void CWapDatagram::GetDatagramSettingsL() |
|
449 { |
|
450 LOGWAPPROT1("CWapDatagram::GetDatagramSettingsL()"); |
|
451 |
|
452 /* The WAP stack always receives 8 bit WAP datagrams from the SMS Stack as a single CSmsMessage. |
|
453 This is because 8 bit WAP messages which cannot be encoded into a single PDU are sent in a segmented SMS |
|
454 message which is reassembled inside the SMS Stack; the SMS Stack always passes the WAP stack |
|
455 a single CSmsMessage containing a single WAP message regardless of the message length. |
|
456 The WAP stack can receive 7 Bit WAP datagrams either as a single CSmsMessage or as a number of CSmsMessages |
|
457 which need to be reassembled into a single WAP message by the WAP stack. The latter method is provided to maintain backward |
|
458 compatibility with early versions of the WAP stack which were implemented before the concatenation function was |
|
459 available in the SMS stack.*/ |
|
460 |
|
461 /* 160 is the maximum number of character that can be fitted in a single PDU using 7 bit encoding */ |
|
462 if((iUserDataSettings.Alphabet()== TSmsDataCodingScheme::ESmsAlphabet8Bit) || |
|
463 (iUserDataSettings.Alphabet()== TSmsDataCodingScheme::ESmsAlphabet7Bit && iBuffer->Length()>160 )) |
|
464 { |
|
465 iSegment = new (ELeave)TWapTextMessage(*iBuffer); |
|
466 } |
|
467 else if (iBuffer->Length()<=160) |
|
468 { |
|
469 iSmsBuffer = *iBuffer; |
|
470 iSegment = new (ELeave)TWapTextMessage(iSmsBuffer); |
|
471 iIsTextHeader = iSegment->Parse(); |
|
472 |
|
473 if (iIsTextHeader) |
|
474 { |
|
475 iFromPort = iSegment->SourcePort(&i16BitPorts); |
|
476 iToPort = iSegment->DestinationPort(&i16BitPorts); |
|
477 iReference = iSegment->ReferenceNumber(); |
|
478 iTotalSegments = iSegment->TotalSegments(); |
|
479 iSegmentNumber = iSegment->SegmentNumber(); |
|
480 } |
|
481 } |
|
482 else |
|
483 { |
|
484 delete iSegment; |
|
485 iSegment = 0; |
|
486 } |
|
487 } // CWapDatagram::GetDatagramSettingsL |
|
488 |
|
489 |
|
490 // |
|
491 // Set WAP datagram private members from information element structures |
|
492 // |
|
493 void CWapDatagram::GetDatagramSettings(const CSmsMessage& aSms) |
|
494 { |
|
495 LOGWAPPROT1("CWapDatagram::GetDatagramSettings()"); |
|
496 |
|
497 const CSmsPDU& Pdu = aSms.SmsPDU(); |
|
498 |
|
499 __ASSERT_DEBUG(Pdu.Type()==CSmsPDU::ESmsDeliver || Pdu.Type()==CSmsPDU::ESmsSubmit, // this line is testing purposes only |
|
500 Panic(KPanicUsageError)); |
|
501 |
|
502 aSms.UserDataSettings(iUserDataSettings); |
|
503 |
|
504 Pdu.ApplicationPortAddressing(iToPort,iFromPort,&i16BitPorts); |
|
505 if (iFromPort == (-1)) |
|
506 iFromPort = iToPort; |
|
507 |
|
508 // From WAP datagram point of view following numbers are applicable |
|
509 iReference = 0; |
|
510 iTotalSegments = 1; |
|
511 iSegmentNumber = 1; |
|
512 |
|
513 iFromAddress = aSms.ToFromAddress(); |
|
514 iToAddress = KNullDesC; |
|
515 iTime = aSms.Time(); |
|
516 |
|
517 TBool result = SetUTCOffset(aSms.UTCOffset()); |
|
518 __ASSERT_DEBUG(result, Panic(KPanicSmsMsgTimeZoneOutOfRange)); |
|
519 } // CWapDatagram::GetDatagramSettings |
|
520 |
|
521 |
|
522 // |
|
523 // Set Alphabet information of iUserDataSettings before calling the method |
|
524 // Converts from 7/8-bit to UNICODE |
|
525 // |
|
526 void CWapDatagram::ConvertL(const TDesC8& aNarrowChars,CSmsBufferBase& aSmsBuffer) const |
|
527 { |
|
528 LOGWAPPROT1("CWapDatagram::ConvertL()"); |
|
529 |
|
530 // Convert the data in segments of specified max size |
|
531 const TInt KMaxSegmentSize=CSmsBufferBase::EMaxBufLength; |
|
532 |
|
533 // Create converter and reassembler |
|
534 RFs fs; |
|
535 CCnvCharacterSetConverter* charConv=CCnvCharacterSetConverter::NewLC(); |
|
536 CSmsAlphabetConverter* converter=CSmsAlphabetConverter::NewLC(*charConv,fs,iUserDataSettings.Alphabet(),ETrue); |
|
537 TSmsBufferReassembler reassembler(*converter,aSmsBuffer); |
|
538 |
|
539 // Rassemble |
|
540 TInt elementsRemaining=aNarrowChars.Length(); |
|
541 while (elementsRemaining) |
|
542 { |
|
543 TInt segmentLength=Min(KMaxSegmentSize,elementsRemaining); |
|
544 TPtrC8 ptr(aNarrowChars.Ptr()+aNarrowChars.Length()-elementsRemaining,segmentLength); |
|
545 reassembler.ReassembleNextL(ptr, ESmsEncodingNone, |
|
546 elementsRemaining==segmentLength); |
|
547 elementsRemaining-=segmentLength; |
|
548 } |
|
549 |
|
550 CleanupStack::PopAndDestroy(2); // charConv, |
|
551 } // CWapDatagram::ConvertL |
|
552 |
|
553 |
|
554 // |
|
555 // Converts from UNICODE to 7/8-bit |
|
556 // |
|
557 void CWapDatagram::ConvertL(const CSmsBufferBase& aSmsBuffer,HBufC8** aNarrowChars) const |
|
558 { |
|
559 LOGWAPPROT1("CWapDatagram::ConvertL()"); |
|
560 |
|
561 // Convert the data in segments of specified max size |
|
562 const TInt KMaxSegmentSize=CSmsBufferBase::EMaxBufLength; |
|
563 |
|
564 // Delete the existing buffer |
|
565 if (*aNarrowChars) |
|
566 { |
|
567 delete *aNarrowChars; |
|
568 *aNarrowChars=NULL; |
|
569 } |
|
570 |
|
571 // Create converter and segmenter |
|
572 RFs fs; |
|
573 CCnvCharacterSetConverter* charConv=CCnvCharacterSetConverter::NewLC(); |
|
574 CSmsAlphabetConverter* converter=CSmsAlphabetConverter::NewLC(*charConv,fs,iUserDataSettings.Alphabet(),ETrue); |
|
575 CSmsBufferSegmenter* segmenter=CSmsBufferSegmenter::NewLC(*converter,aSmsBuffer,KMaxSegmentSize); |
|
576 |
|
577 // Create a new buffer based on converted length |
|
578 TInt convertedLength=segmenter->TotalConvertedLengthL(ESmsEncodingNone); |
|
579 *aNarrowChars=HBufC8::NewMaxL(((convertedLength+KMaxSegmentSize-1)/KMaxSegmentSize)*KMaxSegmentSize); |
|
580 TPtr8 narrowPtr=(*aNarrowChars)->Des(); |
|
581 |
|
582 // Now do the conversion |
|
583 TInt elementsConverted=0; |
|
584 TInt unconvertedChars=0; |
|
585 TInt downgradedChars=0; |
|
586 TBool complete=EFalse; |
|
587 while (elementsConverted<convertedLength) |
|
588 { |
|
589 __ASSERT_DEBUG(elementsConverted<convertedLength,Panic(KPanicTooLongData)); |
|
590 TPtr8 ptr((TUint8*)narrowPtr.Ptr()+elementsConverted,0,KMaxSegmentSize); |
|
591 complete=segmenter->SegmentNextL(ptr, unconvertedChars, downgradedChars, ESmsEncodingNone); |
|
592 elementsConverted+=ptr.Length(); |
|
593 } |
|
594 if((!complete || (convertedLength!=elementsConverted)) && convertedLength) |
|
595 User::Leave( KErrCorrupt ); |
|
596 narrowPtr.SetLength(convertedLength); |
|
597 |
|
598 CleanupStack::PopAndDestroy(3); // charConv,converter,segmenter |
|
599 } // CWapDatagram::ConvertL |
|
600 |
|
601 |
|
602 void CWapDatagram::SetSmsMessageSettingsL(CSmsMessage& aSmsMessage, TBool aSetPorts) |
|
603 { |
|
604 LOGWAPPROT1("CWapDatagram::SetSmsMessageSettingsL()"); |
|
605 |
|
606 CSmsPDU& Pdu = aSmsMessage.SmsPDU(); |
|
607 |
|
608 aSmsMessage.SetToFromAddressL(iToAddress); |
|
609 aSmsMessage.SetUserDataSettingsL(iUserDataSettings); |
|
610 aSmsMessage.SetTime(iTime); |
|
611 |
|
612 TBool result = aSmsMessage.SetUTCOffset(iUTCOffset); |
|
613 __ASSERT_DEBUG(result, Panic(KPanicWapDgrmTimeZoneOutOfRange)); |
|
614 |
|
615 if (aSetPorts) |
|
616 { |
|
617 if (iFromPort == (-1)) |
|
618 iFromPort = iToPort; |
|
619 |
|
620 // Determine whether long or short form is used |
|
621 if (iFromPort > 255 || iToPort>255) |
|
622 i16BitPorts = ETrue; |
|
623 |
|
624 Pdu.SetApplicationPortAddressingL(ETrue,iToPort,iFromPort,i16BitPorts); |
|
625 // WAP implementation guidelines recommend DCS of 0x15, however |
|
626 // some gateways / SCs will only accept DCS 0xf5 |
|
627 Pdu.SetBits7To4(TSmsDataCodingScheme::ESmsDCSTextUncompressed7BitOr8Bit); |
|
628 Pdu.SetAlphabet(TSmsDataCodingScheme::ESmsAlphabet8Bit); |
|
629 Pdu.SetClass(ETrue,TSmsDataCodingScheme::ESmsClass1); |
|
630 } |
|
631 } // CWapDatagram::SetSmsMessageSettingsL |
|
632 |
|
633 |
|
634 CWapDatagram::CWapDatagram(): |
|
635 iUserDataSettings(), |
|
636 iToAddress(KNullDesC), |
|
637 iFromAddress(KNullDesC), |
|
638 i16BitPorts(EFalse), |
|
639 iFromPort(-1), |
|
640 iToPort(-1), |
|
641 iTime(), |
|
642 iUTCOffset(0), |
|
643 iIsComplete(EFalse), |
|
644 iReference(0), |
|
645 iTotalSegments(0), |
|
646 iSegmentNumber(0), |
|
647 iIsTextHeader(EFalse), |
|
648 iSegment(NULL), |
|
649 iSmsBuffer(KNullDesC8), |
|
650 iBuffer(NULL), |
|
651 iSendBuffer(KNullDesC8), |
|
652 iOtherHeader(KNullDesC8), |
|
653 iLogServerId(0), |
|
654 iVersionNumber(EBaseVersion),// Set version number to EBaseVersion by default. |
|
655 iSpare1(0), |
|
656 iSpare2(0), |
|
657 iSpare3(0), |
|
658 iRecvbuf(NULL) |
|
659 { |
|
660 iTime.UniversalTime(); |
|
661 |
|
662 TBool result = SetUTCOffset(User::UTCOffset()); |
|
663 __ASSERT_DEBUG(result, Panic(KPanicUserSuppliedTimeZoneOutOfRange)); |
|
664 |
|
665 iUserDataSettings.SetAlphabet(TSmsDataCodingScheme::ESmsAlphabet8Bit); |
|
666 __DECLARE_NAME(_S("CWapDatagram")); |
|
667 } // CWapDatagram::CWapDatagram |
|
668 |
|
669 |
|
670 // |
|
671 // Return the location of the link |
|
672 // |
|
673 TInt CWapDatagram::LinkOffset() |
|
674 { |
|
675 LOGWAPPROT1("CWapDatagram::LinkOffset()"); |
|
676 |
|
677 |
|
678 return _FOFF(CWapDatagram,iLink); |
|
679 } // CWapDatagram::LinkOffset |
|
680 |
|
681 |
|
682 TBool CWapDatagram::SetUTCOffset(const TTimeIntervalSeconds& aUTCOffset) |
|
683 { |
|
684 LOGWAPPROT1("CWapDatagram::SetUTCOffset()"); |
|
685 |
|
686 TBool rc = ETrue; |
|
687 TInt utcOffset = aUTCOffset.Int(); |
|
688 |
|
689 if ((utcOffset <= CSmsMessage::EMaximumSeconds) && |
|
690 (utcOffset >= -CSmsMessage::EMaximumSeconds)) |
|
691 { |
|
692 iUTCOffset = utcOffset; |
|
693 } |
|
694 else |
|
695 { |
|
696 LOGWAPPROT2("CWapDatagram:SetUTCOffset offset [out of range] = %d",utcOffset); |
|
697 rc = EFalse; |
|
698 } |
|
699 |
|
700 return rc; |
|
701 } // CWapDatagram::SetUTCOffset |
|
702 |
|
703 |
|
704 |
|
705 CBufFlat* CWapDatagram::SmsExternalisedStream() const |
|
706 { |
|
707 return iRecvbuf; |
|
708 } |