|
1 /* |
|
2 * Copyright (c) 2002-2007 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: Decoding of binary multimedia message |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 |
|
20 #include <apparc.h> |
|
21 #include <s32mem.h> |
|
22 #include <utf.h> |
|
23 #include <msvids.h> |
|
24 #include <escapeutils.h> |
|
25 #include <e32math.h> |
|
26 #include <badesca.h> |
|
27 #include <cmsvmimeheaders.h> |
|
28 #include <mmsvattachmentmanager.h> |
|
29 #include <mmsvattachmentmanagersync.h> |
|
30 #include <fileprotectionresolver.h> |
|
31 #include <apmstd.h> |
|
32 // Features |
|
33 #include <featmgr.h> |
|
34 #include <bldvariant.hrh> |
|
35 |
|
36 #include "mmsheaders.h" |
|
37 #include "mmsconst.h" |
|
38 #include "mmsdecode.h" |
|
39 #include "mmscodec.h" |
|
40 #include "mmsservercommon.h" |
|
41 #include "mmssession.h" |
|
42 #include "mmsgenutils.h" |
|
43 #include "mmsentrywrapper.h" |
|
44 #include "mmserrors.h" |
|
45 #include "mmsmmboxmessageheaders.h" |
|
46 #include "mmsmmboxviewheaders.h" |
|
47 #include "mmselementdescriptor.h" |
|
48 |
|
49 enum TMmsMachineStates |
|
50 { |
|
51 EMmsIdle, |
|
52 EMmsDecodingHeaders, |
|
53 EMmsDecodingAttachments, |
|
54 EMmsFinished |
|
55 }; |
|
56 |
|
57 // These are the stages for chunked encoding. |
|
58 // The chunked encoding is synchronous, so the stages are different |
|
59 // from the machine states. |
|
60 enum TMmsChunkedDecodingStages |
|
61 { |
|
62 EMmsNotApplicable, // stage used when not doing chunks |
|
63 EMmsHeaders, |
|
64 EMmsAttachmentHeaders, |
|
65 EMmsAttachmentDataStart, // create attachment file and add data |
|
66 EMmsAttachmentDataAppend, // append data to existing attachment |
|
67 EMmsDone |
|
68 }; |
|
69 |
|
70 static const CMmsDecode::TMmsExtensionLookup KMmsFileExtensionMatchTable[] = |
|
71 { |
|
72 { _S8( "jpeg" ), _S16( "*.jpg" ) }, |
|
73 { _S8( "gif" ), _S16( "*.gif" ) }, |
|
74 { _S8( "text" ), _S16( "*.txt" ) }, |
|
75 { _S8( "smil" ), _S16( "*.smil" ) }, |
|
76 { _S8( "wbmp" ), _S16( "*.wbmp" ) }, |
|
77 { _S8( "png" ), _S16( "*.png" ) }, |
|
78 { _S8( "amr" ), _S16( "*.amr" ) }, |
|
79 { _S8( "vcard" ), _S16( "*.vcf" ) }, |
|
80 { _S8( "calendar" ), _S16( "*.vcs" ) }, |
|
81 { _S8( "drm.message" ), _S16( "*.dm" ) }, |
|
82 { _S8( "drm.content" ), _S16( "*.dcf" ) }, |
|
83 { _S8( "drm.rights+xml" ), _S16( "*.dr" ) }, |
|
84 { _S8( "drm.rights+wbxml" ), _S16( "*.drc" ) }, |
|
85 { _S8( "drm.dcf" ), _S16( "*.odf" ) }, |
|
86 // last entries in the table are empty so that |
|
87 // we can find the end of the table |
|
88 { _S8( "" ), _S16( "" ) } |
|
89 }; |
|
90 |
|
91 // application specific headers with known handling |
|
92 static const CMmsDecode::TMmsExtensionHeaderLookup KMmsExtensionHeaderLookup[] = |
|
93 { |
|
94 { _S8( "X-Mms-Vodafone-Notif-Text" ), &KMmsAssignedExtendedNotificationText }, |
|
95 { _S8( "X-Mms-Vodafone-Notif-EOL" ), &KMmsAssignedExtendedNotificationEOL }, |
|
96 // end of table |
|
97 { _S8( "" ), 0 } |
|
98 }; |
|
99 |
|
100 _LIT8( KMmsWapMultipartReport, "application/vnd.wap.multipart.report" ); |
|
101 // fake assigned number - last one possible |
|
102 const TUint8 KMmsAssignedApplicationVndWapMultipartReport = 0x7F; |
|
103 |
|
104 // a header that is a text string, not assigned number |
|
105 const TUint8 KMmsTextHeader = 0x7F; |
|
106 |
|
107 _LIT8( KMmsExtension, "X-" ); |
|
108 |
|
109 #ifndef _NO_MMSS_LOGGING_ |
|
110 _LIT16( KLogYes, "-- Yes" ); |
|
111 _LIT16( KLogNo, "-- No" ); |
|
112 _LIT16( KLogUnknown, "-- Unknown %d" ); |
|
113 #endif |
|
114 |
|
115 _LIT8( KmmsSmilMimeType,"application/smil"); |
|
116 _LIT8( KMmsSmilSubtype, "smil" ); |
|
117 _LIT8( KMmsAudioSubtype, "amr" ); |
|
118 _LIT8( KMmsAudioSubtype2, "x-amr" ); // old subtype - someone may send this |
|
119 // main type for audio, don't mark for example "application/amr" as audiomessage |
|
120 // as audiomessage UI can't handle it. UI only handles "audio/amr" |
|
121 _LIT8( KMmsAudioType, "audio" ); |
|
122 |
|
123 _LIT8( KMessageClassPersonal, "Personal" ); |
|
124 _LIT8( KMessageClassAdvertisement, "Advertisement" ); |
|
125 _LIT8( KMessageClassInformational, "Informational" ); |
|
126 _LIT8( KMessageClassAuto, "Auto" ); |
|
127 |
|
128 #ifndef _NO_MMSS_LOGGING_ |
|
129 const TInt KMmsHalfByteShift = 4; |
|
130 const TUint8 KMms0x0F = 0x0F; |
|
131 const TInt KMmsDateFormatLength = 30; // length for date string buffer for logging |
|
132 const TInt KMmsMicroToSeconds = 1000000; |
|
133 #endif |
|
134 const TUint8 KMms0x20 = 0x20; // lowest ascii, space |
|
135 const TInt KMmsMinHeaderLength = 2; // no header can be shorter than this |
|
136 const TInt KMmsBitsInByte = 8; |
|
137 const TInt KMmsMaxIntegerLength = 4; |
|
138 const TInt KMmsMaxLongIntegerLength = 8; |
|
139 const TUint8 KMms0x80 = 0x80; // 128 |
|
140 const TUint8 KMms0x7F = 0x7F; // 127 |
|
141 const TInt KMms2 = 2; // used to calculate length when converting 8 bit to 16 bit encoding |
|
142 const TUint8 KMms31 = 31; // uintvar indicator |
|
143 const TUint8 KMms32 = 32; // low limit for text string encoding |
|
144 const TUint8 KMms30 = 30; // upper limit for short length encoding |
|
145 const TInt KMmsUintvarShift = 7; // bit shift for decoding uintvars |
|
146 const TInt KMms14 = 14; // atta name length for self-generated names |
|
147 const TInt KMms2k = 2000; |
|
148 const TInt KMmsTestIllegalValue = 255; |
|
149 // ==================== LOCAL FUNCTIONS ==================== |
|
150 |
|
151 // ================= MEMBER FUNCTIONS ======================= |
|
152 |
|
153 // --------------------------------------------------------------------------- |
|
154 // C++ default constructor can NOT contain any code, that |
|
155 // might leave. |
|
156 // All member variables are automatically zeroed in the constructor |
|
157 // of a class derived from CBase. |
|
158 // --------------------------------------------------------------------------- |
|
159 // |
|
160 CMmsDecode::CMmsDecode() |
|
161 :CMsgActive ( KMmsActiveObjectPriority ), |
|
162 iState ( EMmsIdle ) |
|
163 { |
|
164 } |
|
165 |
|
166 // --------------------------------------------------------------------------- |
|
167 // Symbian OS default constructor can leave. |
|
168 // --------------------------------------------------------------------------- |
|
169 // |
|
170 void CMmsDecode::ConstructL(RFs& aFs) |
|
171 { |
|
172 iFs = aFs; |
|
173 iMimeHeaders = CMsvMimeHeaders::NewL(); |
|
174 // This is obsolete. Everything is always logged in debug version |
|
175 iLogAllDecoded = ETrue; |
|
176 CActiveScheduler::Add(this); |
|
177 } |
|
178 |
|
179 // --------------------------------------------------------------------------- |
|
180 // Two-phased constructor. |
|
181 // --------------------------------------------------------------------------- |
|
182 // |
|
183 EXPORT_C CMmsDecode* CMmsDecode::NewL(RFs& aFs) |
|
184 { |
|
185 CMmsDecode* self = new (ELeave) CMmsDecode; |
|
186 |
|
187 CleanupStack::PushL( self ); |
|
188 self->ConstructL(aFs); |
|
189 CleanupStack::Pop( self ); |
|
190 |
|
191 return self; |
|
192 } |
|
193 |
|
194 |
|
195 // --------------------------------------------------------------------------- |
|
196 // Destructor |
|
197 // --------------------------------------------------------------------------- |
|
198 // |
|
199 CMmsDecode::~CMmsDecode() |
|
200 { |
|
201 Cancel(); |
|
202 delete iMimeHeaders; |
|
203 delete iStore; // the store should be committed earlier, not anymore |
|
204 delete iRootContentIdBuffer; |
|
205 |
|
206 } |
|
207 |
|
208 // --------------------------------------------------------- |
|
209 // |
|
210 // --------------------------------------------------------- |
|
211 // |
|
212 EXPORT_C void CMmsDecode::StartL( |
|
213 MMmsEntryWrapper& aEntryWrapper, |
|
214 CMmsHeaders& aMmsHeaders, |
|
215 CBufFlat& aDecodeBuffer, |
|
216 TRequestStatus& aStatus, |
|
217 TInt aStartPosition /* = 0 */, |
|
218 TInt aLength /* = 0 */ ) |
|
219 { |
|
220 |
|
221 Reset(); |
|
222 |
|
223 iEntryWrapper = &aEntryWrapper; |
|
224 iDecodeBuffer = &aDecodeBuffer; |
|
225 iMmsHeaders = &aMmsHeaders; |
|
226 iDRMFlags = 0; |
|
227 // length will be checked later when we start actual decoding |
|
228 iPosition = aStartPosition; |
|
229 if ( aLength == 0 ) |
|
230 { |
|
231 iLength = aDecodeBuffer.Size(); |
|
232 } |
|
233 else |
|
234 { |
|
235 iLength = aLength + aStartPosition; |
|
236 } |
|
237 |
|
238 iDumpIncoming = iEntryWrapper->GetDumpFlag(); |
|
239 |
|
240 DumpL(); |
|
241 |
|
242 Queue(aStatus); |
|
243 |
|
244 CompleteSelf( iError ); |
|
245 |
|
246 } |
|
247 |
|
248 // --------------------------------------------------------- |
|
249 // |
|
250 // --------------------------------------------------------- |
|
251 // |
|
252 EXPORT_C void CMmsDecode::DecodeHeadersL( |
|
253 MMmsEntryWrapper& aEntryWrapper, |
|
254 CMmsHeaders& aMmsHeaders, |
|
255 CBufFlat& aDecodeBuffer, |
|
256 TInt aStartPosition /* = 0 */, |
|
257 TInt aLength /* = 0 */, |
|
258 TInt* aNumberOfAttachments /* = 0 */, |
|
259 TInt* aDataStart /* = 0 */ ) |
|
260 { |
|
261 // The initial settings are the same as for asynchronous |
|
262 // methods, but decoding just headers is fast enough to |
|
263 // be done synchronously |
|
264 |
|
265 Reset(); |
|
266 |
|
267 iEntryWrapper = &aEntryWrapper; |
|
268 iDecodeBuffer = &aDecodeBuffer; |
|
269 iMmsHeaders = &aMmsHeaders; |
|
270 iPosition = aStartPosition; |
|
271 iNumberOfAttachments = 0; |
|
272 iLastHeader = EFalse; |
|
273 |
|
274 if ( aLength == 0 ) |
|
275 { |
|
276 iLength = aDecodeBuffer.Size(); |
|
277 } |
|
278 else |
|
279 { |
|
280 iLength = aLength + aStartPosition; |
|
281 } |
|
282 if ( aDataStart != 0 ) |
|
283 { |
|
284 // Originally point beyound buffer |
|
285 // If data is found, this will be updated |
|
286 *aDataStart = iLength; |
|
287 } |
|
288 if ( aNumberOfAttachments ) |
|
289 { |
|
290 // initialize to no attachments |
|
291 *aNumberOfAttachments = 0; |
|
292 } |
|
293 |
|
294 iMmsHeaders->Reset(); |
|
295 |
|
296 // Save the time the entry was received into the MMS headers |
|
297 // the value in TMsvEntry may change, but this remains |
|
298 TTime now; |
|
299 now.UniversalTime(); |
|
300 iMmsHeaders->SetReceivingTime( now ); |
|
301 |
|
302 iDumpIncoming = iEntryWrapper->GetDumpFlag(); |
|
303 DumpL(); |
|
304 |
|
305 if ( iLength < KMmsMinHeaderLength ) |
|
306 { |
|
307 // cannot decode if nothing to decode |
|
308 // each header is at least 2 bytes. |
|
309 // If not at least 2 bytes, no can do. |
|
310 iState = EMmsIdle; |
|
311 iError = KErrCorrupt; |
|
312 User::LeaveIfError( iError ); |
|
313 } |
|
314 |
|
315 // each header byte must be followed by at least one byte value. |
|
316 // otherwise the message is corrupted |
|
317 // when we reach the header that indicates the start of the attachment |
|
318 // structure, we expect that no headers follow the attachment part |
|
319 // we could handle even headers following the attachments if we |
|
320 // wanted to, but if the specification is followed strictly, the |
|
321 // attachments are the last part in the message. |
|
322 |
|
323 // each header is at least 2 bytes - header name and value |
|
324 while ( ( iPosition <= iLength - KMmsMinHeaderLength ) && |
|
325 ( iError != KErrCorrupt ) && |
|
326 ( !iLastHeader ) ) |
|
327 { |
|
328 DecodeOneHeaderL(); |
|
329 } |
|
330 |
|
331 iLength = iDecodeBuffer->Size(); |
|
332 if ( iPosition >= iLength || |
|
333 ( iMmsHeaders->MessageType() == KMmsMessageTypeMboxViewConf && |
|
334 iMmsHeaders->MultipartType() == 0 ) ) |
|
335 { |
|
336 // Only content type header, but no actual attachments |
|
337 iNumberOfAttachments = 0; |
|
338 } |
|
339 |
|
340 // If the caller is interested, return the number of attachments we found |
|
341 if ( aNumberOfAttachments ) |
|
342 { |
|
343 *aNumberOfAttachments = iNumberOfAttachments; |
|
344 } |
|
345 |
|
346 if ( aDataStart != 0 ) |
|
347 { |
|
348 *aDataStart = iPosition; |
|
349 } |
|
350 |
|
351 // WE DON'T SAVE THE MESSAGE HERE. |
|
352 // THE CALLER CONTROLS THE SAVING OF THE MESSAGE |
|
353 // AS WE ONLY DECODE HEADERS, AND DON'T HANDLE |
|
354 // ATTACHMENTS HERE |
|
355 // THERE MAY BE NO ENTRY AVAILABLE FOR SAVING THE HEADERS. |
|
356 |
|
357 // We are done - may be called again... |
|
358 iState = EMmsIdle; |
|
359 User::LeaveIfError( iError ); |
|
360 |
|
361 } |
|
362 |
|
363 |
|
364 // --------------------------------------------------------- |
|
365 // |
|
366 // --------------------------------------------------------- |
|
367 // |
|
368 EXPORT_C void CMmsDecode::DecodeAttachmentsL( |
|
369 MMmsEntryWrapper& aEntryWrapper, |
|
370 CMmsHeaders& aMmsHeaders, |
|
371 CBufFlat& aDecodeBuffer, |
|
372 TInt aNumberOfAttachments, |
|
373 TInt& aStartPosition, |
|
374 TRequestStatus& aStatus, |
|
375 TBool aDoNotUpdateParentEntry /* = EFalse*/, |
|
376 TInt aLength /* = 0 */ ) |
|
377 { |
|
378 |
|
379 // The parent entry is updated after specified number of attachments |
|
380 // has been handled. |
|
381 // Normally all attachments should be handled together. |
|
382 // Handling only some attachments is a special case |
|
383 |
|
384 // We must get an edit store when we are called the first time. |
|
385 if ( !iStore ) |
|
386 { |
|
387 iStore = iEntryWrapper->EditStoreL(); |
|
388 } |
|
389 |
|
390 iError = KErrNone; // start with clean slate |
|
391 iDataStart = aStartPosition; |
|
392 iNextStart = aStartPosition; |
|
393 iUpdatedPosition = &aStartPosition; |
|
394 iDoNotUpdateParentEntry = aDoNotUpdateParentEntry; |
|
395 |
|
396 iEntryWrapper = &aEntryWrapper; |
|
397 iMmsHeaders = &aMmsHeaders; |
|
398 iDecodeBuffer = &aDecodeBuffer; |
|
399 iNumberOfAttachments = aNumberOfAttachments; |
|
400 iPosition = aStartPosition; |
|
401 if ( aLength == 0 ) |
|
402 { |
|
403 iLength = iDecodeBuffer->Size(); |
|
404 } |
|
405 else |
|
406 { |
|
407 iLength = aStartPosition + aLength; |
|
408 } |
|
409 iState = EMmsDecodingAttachments; |
|
410 |
|
411 Queue(aStatus); |
|
412 |
|
413 CompleteSelf( iError ); |
|
414 |
|
415 } |
|
416 |
|
417 // --------------------------------------------------------- |
|
418 // |
|
419 // --------------------------------------------------------- |
|
420 // |
|
421 EXPORT_C CMsvMimeHeaders& CMmsDecode::ExtractNextDataPartL( |
|
422 CBufFlat& aDecodeBuffer, |
|
423 TInt& aStartPosition, |
|
424 TInt& aStartOfData, |
|
425 TInt& aLengthOfData) |
|
426 { |
|
427 iMimeHeaders->Reset(); |
|
428 iDecodeBuffer = &aDecodeBuffer; |
|
429 iPosition = aStartPosition; |
|
430 iUpdatedPosition = &aStartPosition; |
|
431 iLength = iDecodeBuffer->Size(); |
|
432 |
|
433 TInt headersLength = 0; |
|
434 TInt dataLength = 0; |
|
435 |
|
436 // This function is only used to extract next data part from multipart structure |
|
437 |
|
438 headersLength = GetUintvar(); |
|
439 dataLength = GetUintvar(); |
|
440 |
|
441 aStartOfData = iPosition + headersLength; |
|
442 iDataStart = aStartOfData; |
|
443 aLengthOfData = dataLength; |
|
444 aStartPosition = iDataStart + dataLength; |
|
445 |
|
446 // Extract mime headers |
|
447 // iPosition points to the start of headers |
|
448 // First is content type without actual header field, just value |
|
449 GetAttachmentContentTypeL(); |
|
450 |
|
451 while ( iPosition < iDataStart ) |
|
452 { |
|
453 DecodeOneContentHeaderL(); |
|
454 } |
|
455 |
|
456 return *iMimeHeaders; |
|
457 } |
|
458 |
|
459 // --------------------------------------------------------- |
|
460 // |
|
461 // --------------------------------------------------------- |
|
462 // |
|
463 EXPORT_C void CMmsDecode::CommitStoreL() |
|
464 { |
|
465 if ( iStore ) |
|
466 { |
|
467 iStore->CommitL(); |
|
468 } |
|
469 } |
|
470 |
|
471 // --------------------------------------------------------- |
|
472 // |
|
473 // --------------------------------------------------------- |
|
474 // |
|
475 EXPORT_C void CMmsDecode::InitializeChunkedMode( |
|
476 MMmsEntryWrapper& aEntryWrapper, |
|
477 CMmsHeaders& aMmsHeaders, |
|
478 CBufFlat& aDecodeBuffer |
|
479 ) |
|
480 { |
|
481 Reset(); |
|
482 iEntryWrapper = &aEntryWrapper; |
|
483 iMmsHeaders = &aMmsHeaders; |
|
484 iDecodeBuffer = &aDecodeBuffer; |
|
485 iDRMFlags = 0; |
|
486 iPosition = 0; |
|
487 iLength = 0; |
|
488 iRemoveDrm = EFalse; |
|
489 iDumpIncoming = iEntryWrapper->GetDumpFlag(); |
|
490 iDecodingStage = EMmsHeaders; |
|
491 |
|
492 TRAP_IGNORE(DumpL()); |
|
493 } |
|
494 |
|
495 // --------------------------------------------------------- |
|
496 // from class MMmsCodecDataSink |
|
497 // |
|
498 // --------------------------------------------------------- |
|
499 // |
|
500 TInt CMmsDecode::NextDataPart( |
|
501 CBufFlat& aBuffer, |
|
502 TInt& aPosition, |
|
503 TBool aLastDataChunk ) |
|
504 { |
|
505 if ( iDecodingStage == EMmsNotApplicable ) |
|
506 { |
|
507 aPosition = 0; // if not chunked, nothing handled by data sink -> keep all. |
|
508 return KErrNone; |
|
509 } |
|
510 |
|
511 TMsvEntry entry; |
|
512 iEntryWrapper->GetIndexEntry( entry ); |
|
513 if ( entry.Id() == KMsvNullIndexEntryId ) |
|
514 { |
|
515 // We have no entry, behave as if in non-chunked mode. |
|
516 // We are getting a response that will not be saved |
|
517 // in a message entry, but may be decoded in its entirety |
|
518 // later. |
|
519 aPosition = 0; // if not chunked, nothing handled by data sink -> keep all. |
|
520 return KErrNone; |
|
521 } |
|
522 |
|
523 iDecodeBuffer = &aBuffer; |
|
524 |
|
525 iPosition = aPosition; |
|
526 // Use iLength to tell how much data must be dumped |
|
527 iLength = iDecodeBuffer->Size() - iPosition; |
|
528 TRAP_IGNORE(DumpL()); |
|
529 // Use this to check when end of buffer has been reached |
|
530 iLength = iDecodeBuffer->Size(); |
|
531 |
|
532 // We must get an edit store when we are called the first time. |
|
533 if ( !iStore && iError == KErrNone ) |
|
534 { |
|
535 TRAP( iError, iStore = iEntryWrapper->EditStoreL() ); |
|
536 } |
|
537 |
|
538 if ( iError != KErrNone ) |
|
539 { |
|
540 return iError; |
|
541 } |
|
542 |
|
543 // clear this to make sure it does not point beyond buffer the next time |
|
544 iOldData = 0; |
|
545 |
|
546 TBool moreDataNeeded = EFalse; |
|
547 if ( iDecodingStage == EMmsHeaders ) |
|
548 { |
|
549 // Decode headers and tell if there was enough data to do that |
|
550 moreDataNeeded = SinkHeaders( aLastDataChunk ); |
|
551 } |
|
552 |
|
553 // If we have decoded all headers, we must see if we have enough data left |
|
554 // to decode the attachments. |
|
555 |
|
556 // If we already ran out of data while decoding the MMS headers |
|
557 // we must get more data before even trying the attachments |
|
558 |
|
559 while ( !moreDataNeeded && !( aLastDataChunk && iPosition == iLength ) && |
|
560 !( iDecodingStage == EMmsDone ) ) |
|
561 { |
|
562 if ( iDecodingStage == EMmsAttachmentHeaders ) |
|
563 { |
|
564 moreDataNeeded = SinkAttachmentHeaders( aLastDataChunk ); |
|
565 } |
|
566 |
|
567 if ( iDecodingStage == EMmsAttachmentDataStart ) |
|
568 { |
|
569 SinkAttachmentDataStart(); |
|
570 } |
|
571 |
|
572 // If we have a monoblock, we don't know the length - we just write everything we've got |
|
573 if ( iDecodingStage == EMmsAttachmentDataAppend && |
|
574 ( iAttaDataWritten < iCurrentAttaLength || iCurrentAttaLength < 0 ) ) |
|
575 { |
|
576 SinkAttachmentData(); |
|
577 } |
|
578 |
|
579 if ( iDecodingStage == EMmsAttachmentDataAppend && |
|
580 ( ( iAttaDataWritten < iCurrentAttaLength ) || |
|
581 ( iCurrentAttaLength < 0 && !aLastDataChunk ) ) ) |
|
582 { |
|
583 moreDataNeeded = ETrue; |
|
584 } |
|
585 |
|
586 if ( ( iDecodingStage == EMmsAttachmentDataAppend && |
|
587 iAttaDataWritten == iCurrentAttaLength ) || aLastDataChunk ) |
|
588 { |
|
589 if ( iCurrentAttaLength > 0 ) |
|
590 { |
|
591 FinishSinkingAttachment( aLastDataChunk ); |
|
592 } |
|
593 } |
|
594 |
|
595 if ( iError != KErrNone && iError != KMmsErrorRemoveDRM ) |
|
596 { |
|
597 if ( iDecodingStage == EMmsAttachmentDataAppend ) |
|
598 { |
|
599 // We try to clean up. |
|
600 // We ignore the error as we have an error already |
|
601 TRAP_IGNORE( iEntryWrapper->FinalizeAttachmentL( |
|
602 *iStore, iCurrentAttaLength, iDRMFlags ) ); |
|
603 } |
|
604 // We cannot continue |
|
605 iDecodingStage = EMmsDone; |
|
606 } |
|
607 } |
|
608 |
|
609 // clear this in case it was set - it's not valid in chunked mode |
|
610 iFakeSubject = 0; |
|
611 iTextPlainLength = 0; |
|
612 |
|
613 if ( aLastDataChunk ) |
|
614 { |
|
615 FinalizeSinkingLastChunk(); |
|
616 } |
|
617 |
|
618 // remember how much data was left over |
|
619 if ( iPosition > iDecodeBuffer->Size() ) |
|
620 { |
|
621 // this is paranoid, but we make sure that the caller will not panic |
|
622 iPosition = iDecodeBuffer->Size(); |
|
623 } |
|
624 iOldData = iDecodeBuffer->Size() - iPosition; |
|
625 aPosition = iPosition; |
|
626 |
|
627 if ( iError != KErrNone ) |
|
628 { |
|
629 #ifndef _NO_MMSS_LOGGING_ |
|
630 TMmsLogger::Log( _L("Chunked decode - error %d, deleting store"), iError ); |
|
631 #endif |
|
632 delete iStore; |
|
633 iStore = NULL; |
|
634 } |
|
635 |
|
636 return iError; |
|
637 } |
|
638 |
|
639 // --------------------------------------------------------- |
|
640 // from class MMmsCodecDataSink |
|
641 // |
|
642 // --------------------------------------------------------- |
|
643 // |
|
644 void CMmsDecode::RelaseDataSink() |
|
645 { |
|
646 // store must be released even in case of error |
|
647 delete iStore; |
|
648 iStore = NULL; |
|
649 } |
|
650 |
|
651 // --------------------------------------------------------- |
|
652 // from class MMmsCodecDataSink |
|
653 // |
|
654 // --------------------------------------------------------- |
|
655 // |
|
656 void CMmsDecode::ResetDataSink() |
|
657 { |
|
658 if ( iDecodingStage == EMmsNotApplicable ) |
|
659 { |
|
660 // not chunked mode - do nothing |
|
661 return; |
|
662 } |
|
663 |
|
664 TMsvEntry entry; |
|
665 if ( iEntryWrapper->GetIndexEntry( entry ) == KErrNone && |
|
666 entry.Id() != KMsvNullIndexEntryId ) |
|
667 { |
|
668 if ( !iStore ) |
|
669 { |
|
670 TRAP_IGNORE(iStore = iEntryWrapper->EditStoreL()); |
|
671 } |
|
672 // This should fail only if we run out of memory. |
|
673 // In that case the whole message entry will be deleted later, |
|
674 // so it does not make sense to return an error here |
|
675 // We just do our best and let the rest of the code to continue |
|
676 TRAP_IGNORE({ |
|
677 MMsvAttachmentManager& attaMan = iStore->AttachmentManagerL(); |
|
678 MMsvAttachmentManagerSync& attaManSync = iStore->AttachmentManagerExtensionsL(); |
|
679 TInt count = attaMan.AttachmentCount(); |
|
680 TInt i; |
|
681 // delete all old attachments as we are starting from the beginning |
|
682 for ( i = count - 1; i >= 0; i-- ) |
|
683 { |
|
684 attaManSync.RemoveAttachmentL( i ); |
|
685 } |
|
686 iStore->CommitL(); |
|
687 }); |
|
688 } |
|
689 |
|
690 Reset(); |
|
691 iMmsHeaders->Reset(); |
|
692 iDRMFlags = 0; |
|
693 iPosition = 0; |
|
694 iLength = 0; |
|
695 iDumpIncoming = iEntryWrapper->GetDumpFlag(); |
|
696 iDecodingStage = EMmsHeaders; |
|
697 if ( entry.Id() == KMsvNullIndexEntryId ) |
|
698 { |
|
699 // no entry - cannot use chunked mode. |
|
700 iDecodingStage = EMmsNotApplicable; |
|
701 } |
|
702 else |
|
703 { |
|
704 TRAP_IGNORE(DumpL()); |
|
705 } |
|
706 } |
|
707 |
|
708 // --------------------------------------------------------- |
|
709 // From class CMsgActive |
|
710 // |
|
711 // --------------------------------------------------------- |
|
712 // |
|
713 void CMmsDecode::DoRunL() |
|
714 { |
|
715 |
|
716 // This routine takes the state machine through the states |
|
717 // until an error is encountered or the cycle completes. |
|
718 |
|
719 if ( iError != KErrNone ) |
|
720 { |
|
721 // We encountered an error, and cannot continue |
|
722 // For the time being we just give up without trying |
|
723 // to do any decent cleanup. |
|
724 iStatus = iError; |
|
725 iState = EMmsIdle; |
|
726 // If we return from DoRunL without becoming active again, |
|
727 // RunL completes. |
|
728 return; |
|
729 } |
|
730 |
|
731 SelectNextState(); |
|
732 |
|
733 if ( iState != EMmsFinished ) |
|
734 { |
|
735 // If appropriate, ChangeStateL makes us active again |
|
736 ChangeStateL(); |
|
737 // If we return from DoRunL without becoming active again, |
|
738 // RunL completes. |
|
739 } |
|
740 else |
|
741 { |
|
742 iUpdatedPosition = NULL; // no longer needed |
|
743 if ( !iDoNotUpdateParentEntry ) |
|
744 { |
|
745 FinishL(); |
|
746 } |
|
747 else |
|
748 { |
|
749 // store must be released in any case |
|
750 CommitStoreL(); |
|
751 delete iStore; |
|
752 iStore = NULL; |
|
753 } |
|
754 iDoNotUpdateParentEntry = EFalse; // default value |
|
755 iState = EMmsIdle; |
|
756 iStatus = iError; |
|
757 // If we return from DoRunL without becoming active again, |
|
758 // RunL completes. |
|
759 } |
|
760 |
|
761 } |
|
762 |
|
763 // --------------------------------------------------------- |
|
764 // From class CMsgActive |
|
765 // |
|
766 // --------------------------------------------------------- |
|
767 // |
|
768 void CMmsDecode::DoComplete( TInt& /* aStatus */ ) |
|
769 { |
|
770 // We are exiting the loop - we say we are idle now |
|
771 iState = EMmsIdle; |
|
772 // store must be released in any case - if it is NULL already, nothing happens |
|
773 // Can't leave here anymore |
|
774 TInt error; |
|
775 TRAP( error, CommitStoreL() ); |
|
776 delete iStore; |
|
777 iStore = NULL; |
|
778 if ( iError == KErrNone ) |
|
779 { |
|
780 iError = error; |
|
781 } |
|
782 } |
|
783 |
|
784 // --------------------------------------------------------- |
|
785 // |
|
786 // --------------------------------------------------------- |
|
787 // |
|
788 void CMmsDecode::SelectNextState() |
|
789 { |
|
790 |
|
791 // If appropiate, the functions called within the switch statement |
|
792 // will make us active again. If all is done, the asynchronous request |
|
793 // will complete |
|
794 |
|
795 switch ( iState ) |
|
796 { |
|
797 case EMmsIdle: |
|
798 // start the loop |
|
799 iState = EMmsDecodingHeaders; |
|
800 break; |
|
801 case EMmsDecodingHeaders: |
|
802 if ( iNumberOfAttachments > 0 ) |
|
803 { |
|
804 iState = EMmsDecodingAttachments; |
|
805 } |
|
806 else |
|
807 { |
|
808 iState = EMmsFinished; |
|
809 } |
|
810 break; |
|
811 case EMmsDecodingAttachments: |
|
812 if ( iNumberOfAttachments > 0 ) |
|
813 { |
|
814 iState = EMmsDecodingAttachments; |
|
815 } |
|
816 else |
|
817 { |
|
818 iState = EMmsFinished; |
|
819 } |
|
820 break; |
|
821 case EMmsFinished: |
|
822 // No more states |
|
823 break; |
|
824 default: |
|
825 // Illegal state |
|
826 #ifndef _NO_MMSS_LOGGING_ |
|
827 TMmsLogger::Log( _L("Decode - illegal state %d"), iState ); |
|
828 #endif |
|
829 break; |
|
830 } |
|
831 } |
|
832 |
|
833 // --------------------------------------------------------- |
|
834 // |
|
835 // --------------------------------------------------------- |
|
836 // |
|
837 void CMmsDecode::ChangeStateL() |
|
838 { |
|
839 switch ( iState ) |
|
840 { |
|
841 case EMmsDecodingHeaders: |
|
842 DecodeHeadersL(); |
|
843 break; |
|
844 case EMmsDecodingAttachments: |
|
845 if ( iNumberOfAttachments > KMmsMaxAttachments ) |
|
846 { |
|
847 // If we have too many attachments, we cannot |
|
848 // handle the message. This is a temporary |
|
849 // error code that takes care of denying retries |
|
850 iError = KMmsErrorEMRUExceeded; |
|
851 CompleteSelf( iError ); |
|
852 return; |
|
853 } |
|
854 DecodeOneAttachmentL(); |
|
855 iNumberOfAttachments--; |
|
856 if ( iUpdatedPosition ) |
|
857 { |
|
858 // The user wants to know where to continue |
|
859 *iUpdatedPosition = iPosition; |
|
860 } |
|
861 break; |
|
862 default: |
|
863 iState = EMmsIdle; |
|
864 break; |
|
865 } |
|
866 } |
|
867 |
|
868 // --------------------------------------------------------- |
|
869 // |
|
870 // --------------------------------------------------------- |
|
871 // |
|
872 void CMmsDecode::Reset() |
|
873 { |
|
874 iError = KErrNone; // start with clean slate |
|
875 iMimeHeaders->Reset(); |
|
876 delete iStore; |
|
877 iStore = NULL; // this is a new message, cannot use old store |
|
878 iUpdatedPosition = NULL; |
|
879 iPosition = 0; |
|
880 iDataStart = 0; |
|
881 iNextStart = 0; |
|
882 iNumberOfAttachments = 0; |
|
883 iLastHeader = EFalse; |
|
884 iTotalSize = 0; |
|
885 iFakeSubject = 0; |
|
886 iCharacterSet = KMmsUsAscii; // if no character set, default is US_ASCII |
|
887 iTextPlainLength = 0; |
|
888 iMultipartType = 0; |
|
889 iRootContentId.Set( TPtrC8() ); |
|
890 delete iRootContentIdBuffer; |
|
891 iRootContentIdBuffer = NULL; |
|
892 iRootAttachmentId = 0; |
|
893 iFirstAttachmentId = 0; |
|
894 iFirstTextPlain = 0; |
|
895 iUseForSubject = EFalse; |
|
896 iAttaNumber = 0; |
|
897 iSmilCount = 0; |
|
898 iAudioCount = 0; |
|
899 iPlainTexts = 0; |
|
900 iDoNotUpdateParentEntry = EFalse; |
|
901 iDecodingStage = EMmsNotApplicable; |
|
902 iOldData = 0; |
|
903 iLogAllDecoded = ETrue; |
|
904 } |
|
905 |
|
906 // --------------------------------------------------------- |
|
907 // |
|
908 // --------------------------------------------------------- |
|
909 TBool CMmsDecode::SinkHeaders( TBool aLastDataChunk ) |
|
910 { |
|
911 TBool enoughData = ETrue; |
|
912 #ifndef _NO_MMSS_LOGGING_ |
|
913 TMmsLogger::Log( _L("Chunked decode - MMS headers")); |
|
914 #endif |
|
915 TInt error = KErrNone; |
|
916 // See if we have a whole header |
|
917 // We must have enough data to contain both the header and its value. |
|
918 // Otherwise we must ask for more data. |
|
919 TRAP ( error, |
|
920 { |
|
921 enoughData = CheckHeaderLength(); |
|
922 while ( enoughData && |
|
923 ( iError != KErrCorrupt ) && |
|
924 ( !iLastHeader ) ) |
|
925 { |
|
926 DecodeOneHeaderL(); |
|
927 if ( ( iError != KErrCorrupt ) && |
|
928 ( !iLastHeader ) ) |
|
929 { |
|
930 enoughData = CheckHeaderLength(); |
|
931 } |
|
932 } |
|
933 }); |
|
934 |
|
935 if ( iError == KErrNone ) |
|
936 { |
|
937 // we should get an error in decoding only if memory runs out |
|
938 // or the message is corrupted |
|
939 iError = error; |
|
940 } |
|
941 // check if we reached the end of the headers and can continue |
|
942 // with attachments |
|
943 if ( iError == KErrNone ) |
|
944 { |
|
945 if ( iLastHeader ) |
|
946 { |
|
947 // Headers decoded successfully, can continue with attachments |
|
948 // The uintvar specifying then number of attachments was decoded |
|
949 // at the end of the MMS headers in connection with multipart header. |
|
950 // This leaves only if out of disk space or out of memory |
|
951 TRAP( iError, SaveMMSHeadersL() ); |
|
952 iDecodingStage = EMmsAttachmentHeaders; |
|
953 } |
|
954 else if ( aLastDataChunk && iPosition >= iLength ) |
|
955 { |
|
956 // Headers decoded successfully, but no attachment present |
|
957 // This is an empty message |
|
958 TRAP( iError, SaveMMSHeadersL() ); |
|
959 iDecodingStage = EMmsAttachmentHeaders; |
|
960 } |
|
961 else if ( aLastDataChunk && !enoughData ) |
|
962 { |
|
963 // we have got something that cannot be decoded |
|
964 iError = KErrCorrupt; |
|
965 iDecodingStage = EMmsDone; |
|
966 } |
|
967 else |
|
968 { |
|
969 // Do nothing - keep LINT happy |
|
970 } |
|
971 } |
|
972 // return ETrue if more data is needed. |
|
973 return !enoughData; |
|
974 } |
|
975 |
|
976 // --------------------------------------------------------- |
|
977 // |
|
978 // --------------------------------------------------------- |
|
979 TBool CMmsDecode::SinkAttachmentHeaders( TBool aLastDataChunk ) |
|
980 { |
|
981 TBool moreDataNeeded = EFalse; |
|
982 TInt error = KErrNone; |
|
983 |
|
984 // We try to get all attachment headers at one go |
|
985 // It is easier than decoding the attachment headers one by one |
|
986 // As we have headers that tell the total length of attachment |
|
987 // headers we can ask for more data if needed. |
|
988 // The attachment headers are not normally very long, and if they |
|
989 // are, the message is probably corrupted anyway |
|
990 |
|
991 #ifndef _NO_MMSS_LOGGING_ |
|
992 TMmsLogger::Log( _L("Chunked decode - Attachment headers")); |
|
993 #endif |
|
994 iAttaDataWritten = 0; // no data yet |
|
995 iCurrentAttaLength = 0; |
|
996 TInt currentPosition = iPosition; |
|
997 TInt uintvarStart = iPosition; |
|
998 iRemoveDrm = EFalse; // no DRM so far |
|
999 if ( iMultipartType && CheckUintvarLength() ) |
|
1000 { |
|
1001 // restore position to start of Uintvar |
|
1002 iPosition = uintvarStart; |
|
1003 TUint attaHeaderLength = GetUintvar(); |
|
1004 // got atta header length. Do we still have more data. |
|
1005 uintvarStart = iPosition; |
|
1006 if ( CheckUintvarLength() ) |
|
1007 { |
|
1008 iPosition = uintvarStart; |
|
1009 iCurrentAttaLength = GetUintvar(); |
|
1010 // attaHeaderLength is the length of content type header and other |
|
1011 // headers combined. |
|
1012 // Do we still have that much data. |
|
1013 if ( iLength - iPosition >= attaHeaderLength ) |
|
1014 { |
|
1015 // decode headers |
|
1016 iPosition = currentPosition; |
|
1017 TRAP( error, DecodeAttachmentHeadersL() ); |
|
1018 if ( iError == KErrNone ) |
|
1019 { |
|
1020 iError = error; |
|
1021 } |
|
1022 if ( iCurrentAttaLength == 0 ) |
|
1023 { |
|
1024 // if the attachment is empty, we do not create an attachment |
|
1025 // we should check here if there is any data left |
|
1026 iDecodingStage = EMmsAttachmentHeaders; |
|
1027 } |
|
1028 else if ( iError == KErrNone ) |
|
1029 { |
|
1030 iDecodingStage = EMmsAttachmentDataStart; |
|
1031 } |
|
1032 else |
|
1033 { |
|
1034 // do nothing - keep LINT happy |
|
1035 } |
|
1036 } |
|
1037 else |
|
1038 { |
|
1039 // not enough data for decoding headers - give up |
|
1040 // and ask for more data |
|
1041 iPosition = currentPosition; |
|
1042 moreDataNeeded = ETrue; |
|
1043 #ifndef _NO_MMSS_LOGGING_ |
|
1044 TMmsLogger::Log( _L("Chunked decode - need more data for atta headers")); |
|
1045 #endif |
|
1046 } |
|
1047 } |
|
1048 else |
|
1049 { |
|
1050 // not enough data for determining attachment data length - give up |
|
1051 // and ask for more data |
|
1052 iPosition = currentPosition; |
|
1053 moreDataNeeded = ETrue; |
|
1054 } |
|
1055 } |
|
1056 else if ( iMultipartType == 0 && !( iLength - iPosition < KMms2k && !aLastDataChunk ) ) |
|
1057 { |
|
1058 // One chunk, no multipart, very bad, try anyway |
|
1059 // We can only guess how much of the data is headers. |
|
1060 TRAP( error, DecodeAttachmentHeadersL() ); |
|
1061 if ( iError == KErrNone ) |
|
1062 { |
|
1063 iError = error; |
|
1064 } |
|
1065 iCurrentAttaLength = -1; // Don't know |
|
1066 if ( !( aLastDataChunk && iPosition == iLength ) && iError == KErrNone ) |
|
1067 { |
|
1068 // There is some data |
|
1069 iDecodingStage = EMmsAttachmentDataStart; |
|
1070 } |
|
1071 else |
|
1072 { |
|
1073 iCurrentAttaLength = 0; // no data |
|
1074 } |
|
1075 } |
|
1076 else |
|
1077 { |
|
1078 // not enough data for determining attachment header length - give up |
|
1079 // and ask for more data |
|
1080 iPosition = currentPosition; |
|
1081 moreDataNeeded = ETrue; |
|
1082 } |
|
1083 |
|
1084 return moreDataNeeded; |
|
1085 } |
|
1086 |
|
1087 // --------------------------------------------------------- |
|
1088 // |
|
1089 // --------------------------------------------------------- |
|
1090 // |
|
1091 void CMmsDecode::SinkAttachmentDataStart() |
|
1092 { |
|
1093 TInt error = KErrNone; |
|
1094 |
|
1095 #ifndef _NO_MMSS_LOGGING_ |
|
1096 TMmsLogger::Log( _L("Chunked decode - Attachment data start")); |
|
1097 #endif |
|
1098 // Now the attachment file must be created. |
|
1099 // We should also have enough data |
|
1100 |
|
1101 // First an empty attachment is created. No data is needed for it. |
|
1102 TRAP ( error, iEntryWrapper->CreateEmptyFileAttachmentL( |
|
1103 *iStore, |
|
1104 iParse.NameAndExt(), |
|
1105 *iMimeHeaders, |
|
1106 iCurrentAttachment ) |
|
1107 ); |
|
1108 |
|
1109 if ( iError == KErrNone && error != KErrNone ) |
|
1110 { |
|
1111 iError = error; |
|
1112 } |
|
1113 if ( iError == KErrNone ) |
|
1114 { |
|
1115 if ( iUseForSubject ) |
|
1116 { |
|
1117 iFirstTextPlain = iCurrentAttachment; |
|
1118 iUseForSubject = EFalse; |
|
1119 } |
|
1120 |
|
1121 #ifndef _NO_MMSS_LOGGING_ |
|
1122 TRAP_IGNORE({ |
|
1123 MMsvAttachmentManager& attaMan = iStore->AttachmentManagerL(); |
|
1124 CMsvAttachment* attaInfo = attaMan.GetAttachmentInfoL( iCurrentAttachment ); |
|
1125 TMmsLogger::Log( _L("- Attachment created %S"), &attaInfo->FilePath() ); |
|
1126 delete attaInfo; |
|
1127 attaInfo = NULL; |
|
1128 }); |
|
1129 #endif |
|
1130 } |
|
1131 if ( iError == KErrNone ) |
|
1132 { |
|
1133 iDecodingStage = EMmsAttachmentDataAppend; |
|
1134 } |
|
1135 } |
|
1136 |
|
1137 // --------------------------------------------------------- |
|
1138 // |
|
1139 // --------------------------------------------------------- |
|
1140 // |
|
1141 void CMmsDecode::SinkAttachmentData() |
|
1142 { |
|
1143 TInt error = KErrNone; |
|
1144 // no problem with signed/unsigned comparison - size cannot be signed |
|
1145 if ( iPosition < iDecodeBuffer->Size() ) |
|
1146 { |
|
1147 TPtr8 attaDataPtr = iDecodeBuffer->Ptr( iPosition ); |
|
1148 if ( attaDataPtr.Length() > iCurrentAttaLength - iAttaDataWritten && |
|
1149 iCurrentAttaLength > 0 ) |
|
1150 { |
|
1151 // If we don't know the amount of attachment data, we write the |
|
1152 // whole buffer |
|
1153 attaDataPtr.SetLength( iCurrentAttaLength - iAttaDataWritten ); |
|
1154 } |
|
1155 if ( iError == KMmsErrorRemoveDRM ) |
|
1156 { |
|
1157 iRemoveDrm = ETrue; |
|
1158 iError = KErrNone; |
|
1159 } |
|
1160 if ( !iRemoveDrm ) |
|
1161 { |
|
1162 // we have data that can be written to the file |
|
1163 TRAP( error, |
|
1164 iError = iEntryWrapper->ProcessAttachmentDataL( attaDataPtr, iDRMFlags ) |
|
1165 ); |
|
1166 if ( iError == KErrNone ) |
|
1167 { |
|
1168 iError = error; |
|
1169 } |
|
1170 if ( iError == KMmsErrorRemoveDRM ) |
|
1171 { |
|
1172 iRemoveDrm = ETrue; |
|
1173 iError = KErrNone; |
|
1174 } |
|
1175 } |
|
1176 // if attachment is DRM protected and must be removed, just increase pointers |
|
1177 iPosition += attaDataPtr.Length(); |
|
1178 iAttaDataWritten += attaDataPtr.Length(); |
|
1179 #ifndef _NO_MMSS_LOGGING_ |
|
1180 TMmsLogger::Log( _L("Chunked decode - Attachment data %d, cumulative %d"), |
|
1181 attaDataPtr.Length(), iAttaDataWritten ); |
|
1182 #endif |
|
1183 } |
|
1184 } |
|
1185 |
|
1186 // --------------------------------------------------------- |
|
1187 // |
|
1188 // --------------------------------------------------------- |
|
1189 // |
|
1190 void CMmsDecode::FinishSinkingAttachment( TBool aLastDataChunk ) |
|
1191 { |
|
1192 TInt error = KErrNone; |
|
1193 #ifndef _NO_MMSS_LOGGING_ |
|
1194 TMmsLogger::Log( _L("Chunked decode - Attachment ready")); |
|
1195 #endif |
|
1196 // end of attachment - close file |
|
1197 // This must be called even if the error indicates the DRM file must be removed |
|
1198 // This call does all cleanup and actually removes the DRM attachment if needed. |
|
1199 TRAPD( error2, |
|
1200 error = iEntryWrapper->FinalizeAttachmentL( *iStore, iCurrentAttaLength, iDRMFlags ) |
|
1201 ); |
|
1202 if ( iError == KErrNone ) |
|
1203 { |
|
1204 iError = error; |
|
1205 } |
|
1206 if ( iError == KErrNone ) |
|
1207 { |
|
1208 iError = error2; |
|
1209 } |
|
1210 // If DRM handling changed file size, iCurrentAttaLength gets adjusted |
|
1211 if ( iError == KMmsErrorRemoveDRM ) |
|
1212 { |
|
1213 // if error == KMmsErrorRemoveDRM all is well, and we can continue |
|
1214 // but we don't have an attachment |
|
1215 iError = KErrNone; |
|
1216 // DRM already removed - flag can be cleared now |
|
1217 iRemoveDrm = EFalse; |
|
1218 } |
|
1219 else if ( iError == KErrNone ) |
|
1220 { |
|
1221 iTotalSize += iMimeHeaders->Size() + iCurrentAttaLength; |
|
1222 if ( ( iMultipartType == KMmsAssignedApplicationVndWapMultipartRelated ) && |
|
1223 ( iRootContentId.Length() > 0 ) && |
|
1224 ( iRootAttachmentId == 0 ) ) |
|
1225 { |
|
1226 // check if content-id's match |
|
1227 if ( iRootContentId.Compare( iMimeHeaders->ContentId() ) == 0 ) |
|
1228 { |
|
1229 iRootAttachmentId = iCurrentAttachment; |
|
1230 } |
|
1231 } |
|
1232 } |
|
1233 else |
|
1234 { |
|
1235 // do nothing - keep LINT happy |
|
1236 } |
|
1237 // no problem with signed/unsigned |
|
1238 if ( !( aLastDataChunk && iPosition == iLength ) && |
|
1239 ( iAttaNumber < iNumberOfAttachments ) ) |
|
1240 { |
|
1241 iDecodingStage = EMmsAttachmentHeaders; |
|
1242 } |
|
1243 else |
|
1244 { |
|
1245 iDecodingStage = EMmsDone; |
|
1246 } |
|
1247 } |
|
1248 |
|
1249 // --------------------------------------------------------- |
|
1250 // |
|
1251 // --------------------------------------------------------- |
|
1252 // |
|
1253 void CMmsDecode::FinalizeSinkingLastChunk() |
|
1254 { |
|
1255 TInt error = KErrNone; |
|
1256 |
|
1257 #ifndef _NO_MMSS_LOGGING_ |
|
1258 TMmsLogger::Log( _L("Chunked decode - last chunk")); |
|
1259 #endif |
|
1260 // If we have reached the last chunk, all data should be handled by now |
|
1261 iDecodingStage = EMmsDone; |
|
1262 |
|
1263 // Read possible data from plain text file into encode buffer |
|
1264 // and set iFake subject to point to the buffer |
|
1265 // Must start from 1 because data would never start from 0 |
|
1266 // and value 0 indicates no fake subject available. |
|
1267 |
|
1268 // Fake subject handling |
|
1269 // Our store should still be valid. |
|
1270 // The fake subject handling and multipart/report handling are "best effort" |
|
1271 // Even if the operations fail, the code continues as if no error was encountered. |
|
1272 TInt oldSize = iDecodeBuffer->Size(); |
|
1273 TRAP_IGNORE( |
|
1274 { |
|
1275 // if we have no subject but we do have only one text attachment |
|
1276 // we take text from the beginning as subject |
|
1277 // |
|
1278 if ( iFirstTextPlain && iPlainTexts == 1 && iMmsHeaders->Subject().Length() == 0 ) |
|
1279 { |
|
1280 MMsvAttachmentManager& attaMan = iStore->AttachmentManagerL(); |
|
1281 RFile textAtta = attaMan.GetAttachmentFileL( iFirstTextPlain ); |
|
1282 CleanupClosePushL( textAtta ); |
|
1283 iDecodeBuffer->ResizeL( KMmsMaxDescription + 1 ); |
|
1284 // We must start from any position > 0 |
|
1285 TPtr8 pointer = iDecodeBuffer->Ptr( 1 ); |
|
1286 // read text into buffer |
|
1287 error = textAtta.Read( pointer ); |
|
1288 if ( error == KErrNone ) |
|
1289 { |
|
1290 iFakeSubject = 1; |
|
1291 iTextPlainLength = pointer.Length(); |
|
1292 } |
|
1293 CleanupStack::PopAndDestroy( &textAtta ); // textAtta file handle closed |
|
1294 } |
|
1295 |
|
1296 // Multipart/report handling |
|
1297 if ( iMultipartType == KMmsAssignedApplicationVndWapMultipartReport ) |
|
1298 { |
|
1299 // we only keep the first part from multipart/report |
|
1300 MMsvAttachmentManager& attaMan = iStore->AttachmentManagerL(); |
|
1301 MMsvAttachmentManagerSync& attaManSync = iStore->AttachmentManagerExtensionsL(); |
|
1302 TInt count = attaMan.AttachmentCount(); |
|
1303 TInt i; |
|
1304 for ( i = count - 1; i > 0; i-- ) |
|
1305 { |
|
1306 attaManSync.RemoveAttachmentL( i ); |
|
1307 } |
|
1308 } |
|
1309 }); |
|
1310 |
|
1311 error = KErrNone; |
|
1312 iLength = iDecodeBuffer->Size(); |
|
1313 TRAP( error, FinishL() ); |
|
1314 TRAP_IGNORE( CommitStoreL() ); |
|
1315 delete iStore; |
|
1316 iStore = NULL; |
|
1317 if ( iError == KErrNone ) |
|
1318 { |
|
1319 iError = error; |
|
1320 } |
|
1321 // Restore the original buffer size |
|
1322 // This should actually never leave because we are just restoring the original size |
|
1323 TRAP_IGNORE( iDecodeBuffer->ResizeL( oldSize )); |
|
1324 iLength = iDecodeBuffer->Size(); |
|
1325 } |
|
1326 |
|
1327 // --------------------------------------------------------- |
|
1328 // |
|
1329 // --------------------------------------------------------- |
|
1330 // |
|
1331 void CMmsDecode::DecodeHeadersL() |
|
1332 { |
|
1333 |
|
1334 if ( iLength < KMmsMinHeaderLength ) |
|
1335 { |
|
1336 // cannot decode if nothing to decode |
|
1337 // each header is at least 2 bytes. |
|
1338 // If not at least 2 bytes, no can do. |
|
1339 iError = KErrCorrupt; |
|
1340 } |
|
1341 |
|
1342 iMmsHeaders->Reset(); |
|
1343 |
|
1344 // Save the time the entry was received into the MMS headers |
|
1345 // the value in TMsvEntry may change, but this remains |
|
1346 TTime now; |
|
1347 now.UniversalTime(); |
|
1348 iMmsHeaders->SetReceivingTime( now ); |
|
1349 |
|
1350 // each header byte must be followed by at least one byte value. |
|
1351 // otherwise the message is corrupted |
|
1352 // when we reach the header that indicates the start of the attachment |
|
1353 // structure, we expect that no headers follow the attachment part. |
|
1354 |
|
1355 // each header is at least 2 bytes - header name and value |
|
1356 while ( ( iPosition <= iLength - KMmsMinHeaderLength ) && |
|
1357 ( iError != KErrCorrupt ) && |
|
1358 ( !iLastHeader ) ) |
|
1359 { |
|
1360 DecodeOneHeaderL(); |
|
1361 } |
|
1362 |
|
1363 SaveMMSHeadersL(); |
|
1364 |
|
1365 TRequestStatus* status = &iStatus; |
|
1366 *status = KRequestPending; |
|
1367 SetActive(); |
|
1368 |
|
1369 // Now we indicate we already did everything. |
|
1370 User::RequestComplete( status, iError ); |
|
1371 |
|
1372 } |
|
1373 |
|
1374 // --------------------------------------------------------- |
|
1375 // |
|
1376 // --------------------------------------------------------- |
|
1377 // |
|
1378 void CMmsDecode::SaveMMSHeadersL() |
|
1379 { |
|
1380 |
|
1381 // We save the headers only in case we are decoding an incoming |
|
1382 // message. In other cases we deliver the results back to the caller |
|
1383 // in iMmsHeaders. |
|
1384 // Only retrieve confirmation is supposed to contain body that |
|
1385 // needs saving of attachments. |
|
1386 |
|
1387 // We save a message of type KMmsMessageTypeMSendReq as it were an |
|
1388 // incoming message, as during tests we get our own |
|
1389 // send requests back as new messages. |
|
1390 // We also save notifications and delivery reports. |
|
1391 // However, in normal case MMS server calls a different function |
|
1392 // (CMmsDecode::DecodeHeadersL) to decode notifications and delivery |
|
1393 // reports as they do not contain attachments, and delivery reports |
|
1394 // are not saved on disk, but are logged and deleted. |
|
1395 // For testing purposes upload request is saved as an incoming message |
|
1396 |
|
1397 if ( ( iMmsHeaders->MessageType() == KMmsMessageTypeMRetrieveConf || |
|
1398 iMmsHeaders->MessageType() == KMmsMessageTypeMSendReq || |
|
1399 iMmsHeaders->MessageType() == KMmsMessageTypeMNotificationInd || |
|
1400 iMmsHeaders->MessageType() == KMmsMessageTypeDeliveryInd || |
|
1401 iMmsHeaders->MessageType() == KMmsMessageTypeMBoxUploadReq ) && |
|
1402 iError == KErrNone ) |
|
1403 { |
|
1404 // The entry wrapper must be pointing to our message entry |
|
1405 if ( !iStore ) |
|
1406 { |
|
1407 iStore = iEntryWrapper->EditStoreL(); |
|
1408 } |
|
1409 iError = iEntryWrapper->DiskSpaceBelowCriticalLevelL( iMmsHeaders->Size() ); |
|
1410 if ( iError == KErrNone ) |
|
1411 { |
|
1412 iMmsHeaders->StoreL( *iStore ); |
|
1413 iStore->CommitL(); |
|
1414 } |
|
1415 // the store will be left open until all the attachments have been saved |
|
1416 } |
|
1417 |
|
1418 // Afterwards we must calculate the total message size and |
|
1419 // store it in the entry. |
|
1420 } |
|
1421 |
|
1422 // --------------------------------------------------------- |
|
1423 // |
|
1424 // --------------------------------------------------------- |
|
1425 // |
|
1426 void CMmsDecode::DecodeOneHeaderL() |
|
1427 { |
|
1428 |
|
1429 TInt header; |
|
1430 header = GetHeaderName(); |
|
1431 |
|
1432 if ( header == -1 ) |
|
1433 { |
|
1434 return; // skip unknown |
|
1435 } |
|
1436 |
|
1437 // Get the corresponding value |
|
1438 |
|
1439 switch ( header ) |
|
1440 { |
|
1441 case KMmsAssignedFrom: |
|
1442 DecodeFromHeaderL(); |
|
1443 break; |
|
1444 case KMmsAssignedTo: |
|
1445 DecodeToL(); |
|
1446 break; |
|
1447 case KMmsAssignedCc: |
|
1448 DecodeCcL(); |
|
1449 break; |
|
1450 case KMmsAssignedBcc: |
|
1451 DecodeBccL(); |
|
1452 break; |
|
1453 case KMmsAssignedContentLocation: |
|
1454 DecodeContentLocationHeaderL(); |
|
1455 break; |
|
1456 case KMmsAssignedDate: |
|
1457 DecodeDateHeaderL(); |
|
1458 break; |
|
1459 case KMmsAssignedDeliveryReport: |
|
1460 DecodeDeliveryReportHeader(); |
|
1461 break; |
|
1462 case KMmsAssignedDeliveryTime: |
|
1463 DecodeDeliveryTimeL(); |
|
1464 break; |
|
1465 case KMmsAssignedExpiry: |
|
1466 DecodeExpiryL(); |
|
1467 break; |
|
1468 case KMmsAssignedMessageClass: |
|
1469 DecodeMessageClass(); |
|
1470 break; |
|
1471 case KMmsAssignedMessageId: |
|
1472 DecodeMessageIdL(); |
|
1473 break; |
|
1474 case KMmsAssignedMessageType: |
|
1475 DecodeMessageType(); |
|
1476 break; |
|
1477 case KMmsAssignedMmsVersion: |
|
1478 DecodeMmsVersion(); |
|
1479 break; |
|
1480 case KMmsAssignedMessageSize: |
|
1481 DecodeMessageSize(); |
|
1482 break; |
|
1483 case KMmsAssignedPriority: |
|
1484 DecodePriority(); |
|
1485 break; |
|
1486 case KMmsAssignedReadReply: |
|
1487 DecodeReadReply(); |
|
1488 break; |
|
1489 case KMmsAssignedReportAllowed: |
|
1490 DecodeReportAllowed(); |
|
1491 break; |
|
1492 case KMmsAssignedResponseStatus: |
|
1493 case KMmsAssignedRetrieveStatus: |
|
1494 DecodeResponseStatusL( header ); |
|
1495 break; |
|
1496 case KMmsAssignedResponseText: |
|
1497 case KMmsAssignedRetrieveText: |
|
1498 case KMmsAssignedStatusText: |
|
1499 DecodeResponseTextL( header ); |
|
1500 break; |
|
1501 case KMmsAssignedSenderVisibility: |
|
1502 DecodeSenderVisibility(); |
|
1503 break; |
|
1504 case KMmsAssignedStatus: |
|
1505 DecodeStatus(); |
|
1506 break; |
|
1507 case KMmsAssignedSubject: |
|
1508 DecodeSubjectL(); |
|
1509 break; |
|
1510 case KMmsAssignedTID: |
|
1511 DecodeTidL(); |
|
1512 break; |
|
1513 case KMmsAssignedContentType: |
|
1514 // Content type is the last header in the PDU |
|
1515 // Number of attachments and last header indicator will be set |
|
1516 DecodeContentTypeL(); |
|
1517 break; |
|
1518 case KMmsAssignedReadStatus: |
|
1519 DecodeReadStatus(); |
|
1520 break; |
|
1521 case KMmsAssignedReplyCharging: |
|
1522 DecodeReplyCharging(); |
|
1523 break; |
|
1524 case KMmsAssignedReplyChargingDeadline: |
|
1525 DecodeReplyChargingDeadlineL(); |
|
1526 break; |
|
1527 case KMmsAssignedReplyChargingID: |
|
1528 DecodeReplyChargingIdL(); |
|
1529 break; |
|
1530 case KMmsAssignedReplyChargingSize: |
|
1531 DecodeReplyChargingSize(); |
|
1532 break; |
|
1533 case KMmsAssignedPreviouslySentBy: |
|
1534 DecodePreviousSenderL(); |
|
1535 break; |
|
1536 case KMmsAssignedPreviouslySentDate: |
|
1537 DecodePreviouslySentDateL(); |
|
1538 break; |
|
1539 case KMmsAssignedMmsStore: |
|
1540 DecodeStoreHeaderL(); |
|
1541 break; |
|
1542 case KMmsAssignedMMState: |
|
1543 DecodeMMBoxStateL(); |
|
1544 break; |
|
1545 case KMmsAssignedMMFlags: |
|
1546 GetKeywordL(); |
|
1547 break; |
|
1548 case KMmsAssignedStoreStatus: |
|
1549 DecodeMMBoxStoreStatusL(); |
|
1550 break; |
|
1551 case KMmsAssignedStoreStatusText: |
|
1552 DecodeMMBoxStoreStatusTextL(); |
|
1553 break; |
|
1554 case KMmsAssignedStored: |
|
1555 DecodeStoredInMMBoxHeaderL(); |
|
1556 break; |
|
1557 case KMmsAssignedAttributes: |
|
1558 DecodeAttributesHeaderL(); |
|
1559 break; |
|
1560 case KMmsAssignedTotals: |
|
1561 DecodeTotalsL(); |
|
1562 break; |
|
1563 case KMmsAssignedMboxTotals: |
|
1564 DecodeMboxTotalsL(); |
|
1565 break; |
|
1566 case KMmsAssignedQuotas: |
|
1567 DecodeQuotaHeaderL(); |
|
1568 break; |
|
1569 case KMmsAssignedMboxQuotas: |
|
1570 DecodeMBoxQuotasL(); |
|
1571 break; |
|
1572 case KMmsAssignedMessageCount: |
|
1573 DecodeMessageCountL(); |
|
1574 break; |
|
1575 case KMmsAssignedStart: |
|
1576 DecodeStartInMMBoxViewL(); |
|
1577 break; |
|
1578 case KMmsAssignedDistributionIndicator: |
|
1579 DecodeDistributionIndicator(); |
|
1580 break; |
|
1581 case KMmsAssignedElementDescriptor: |
|
1582 DecodeElementDescriptorL(); |
|
1583 break; |
|
1584 case KMmsAssignedLimit: |
|
1585 DecodeMessageLimitL(); |
|
1586 break; |
|
1587 case KMmsAssignedExtendedNotificationText: |
|
1588 DecodeExtNotifTextL(); |
|
1589 break; |
|
1590 case KMmsAssignedExtendedNotificationEOL: |
|
1591 DecodeExtNotifEolL(); |
|
1592 break; |
|
1593 case KMmsAssignedContentClass: |
|
1594 DecodeContentClass(); |
|
1595 break; |
|
1596 case KMmsAssignedDrmContent: |
|
1597 DecodeDrmContentHeader(); |
|
1598 break; |
|
1599 case KMmsAssignedAdaptationAllowed: |
|
1600 DecodeAdaptationAllowed(); |
|
1601 break; |
|
1602 case KMmsAssignedApplicId: |
|
1603 DecodeApplicationIdL(); |
|
1604 break; |
|
1605 case KMmsAssignedReplyApplicId: |
|
1606 DecodeReplyApplicationIdL(); |
|
1607 break; |
|
1608 case KMmsAssignedAuxApplicInfo: |
|
1609 DecodeApplicationInfoL(); |
|
1610 break; |
|
1611 case KMmsAssignedRecommendedRetrievalMode: |
|
1612 DecodeRecommendedRetrievalMode(); |
|
1613 break; |
|
1614 case KMmsAssignedRecommendedRetrievalModeText: |
|
1615 DecodeRecommendedRetrievalModeTextL(); |
|
1616 break; |
|
1617 case KMmsAssignedReplaceId: |
|
1618 case KMmsAssignedCancelId: |
|
1619 DecodeCancelReplaceIdL( header ); |
|
1620 break; |
|
1621 case KMmsAssignedCancelStatus: |
|
1622 DecodeCancelStatus(); |
|
1623 break; |
|
1624 default: |
|
1625 #ifndef _NO_MMSS_LOGGING_ |
|
1626 TMmsLogger::Log( _L("- Unsupported header : 0x%02X"), (header & KMms0x7F) ); |
|
1627 #endif |
|
1628 // This is an error. |
|
1629 // This is an unknown header, just ignore it. |
|
1630 SkipFieldValue(); |
|
1631 break; |
|
1632 } |
|
1633 |
|
1634 } |
|
1635 |
|
1636 // --------------------------------------------------------- |
|
1637 // |
|
1638 // --------------------------------------------------------- |
|
1639 // |
|
1640 TInt CMmsDecode::GetHeaderName() |
|
1641 { |
|
1642 |
|
1643 TInt header; |
|
1644 header = -1; // unknown |
|
1645 |
|
1646 TUint8 byte; |
|
1647 |
|
1648 if ( iPosition > iLength - KMmsMinHeaderLength ) |
|
1649 { |
|
1650 iError = KErrCorrupt; |
|
1651 return header; |
|
1652 } |
|
1653 |
|
1654 iDecodeBuffer->Read(iPosition, &byte, 1); |
|
1655 |
|
1656 // byte cannot be bigger than 255. No need to test upper limit |
|
1657 if ( byte >= KMms0x80 ) |
|
1658 { |
|
1659 // well known header, advance pointer |
|
1660 iPosition++; |
|
1661 header = byte; |
|
1662 return header; |
|
1663 } |
|
1664 |
|
1665 // we cannot handle headers which are not well known. |
|
1666 // however, we should be able to skip them and ignore them. |
|
1667 // If a field name has no encoding, it must be encoded as text. |
|
1668 |
|
1669 // If the header is corrupted, the value may be something |
|
1670 // illegal. We should have a mechanism of skipping |
|
1671 // illegal codings, too, but if the header name is not a |
|
1672 // short integer or a text string, we are so deep in trouble |
|
1673 // that we cannot decode the whole message anyway. |
|
1674 |
|
1675 // We handle some known text headers. Here we check if possible |
|
1676 // text header is one we know. If not, it is skipped. |
|
1677 |
|
1678 TPtrC8 byteString = GetByteString(); |
|
1679 |
|
1680 // see if this is in our table |
|
1681 TInt i = 0; |
|
1682 TBool matchFound = EFalse; |
|
1683 TPtrC8 matchTablePointer; |
|
1684 matchTablePointer.Set( KMmsExtensionHeaderLookup[i].extensionHeader ); |
|
1685 while ( matchTablePointer.Length() > 0 && !matchFound ) |
|
1686 { |
|
1687 if ( matchTablePointer.CompareF( byteString ) == 0 ) |
|
1688 { |
|
1689 header = *KMmsExtensionHeaderLookup[i].assignedValue; |
|
1690 matchFound = ETrue; |
|
1691 } |
|
1692 i++; |
|
1693 matchTablePointer.Set( KMmsExtensionHeaderLookup[i].extensionHeader ); |
|
1694 } |
|
1695 |
|
1696 #ifndef _NO_MMSS_LOGGING_ |
|
1697 // we do not leave because of logging. |
|
1698 TInt error = KErrNone; |
|
1699 TRAP( error, |
|
1700 { |
|
1701 // length - terminating zero |
|
1702 HBufC16* buffer = NULL; |
|
1703 buffer = HBufC16::NewLC( byteString.Length() ); |
|
1704 buffer->Des().Copy( byteString ); |
|
1705 TPtrC dummy; |
|
1706 // we cannot log indefinitely long strings. |
|
1707 // We get this long strings only if the message is corrupted. |
|
1708 dummy.Set( buffer->Des().Left( KMmsMaxLogStringLength ) ); |
|
1709 TMmsLogger::Log( _L("- Text header : %S"), &dummy ); |
|
1710 CleanupStack::PopAndDestroy( buffer ); |
|
1711 }); |
|
1712 if ( error != KErrNone ) |
|
1713 { |
|
1714 TMmsLogger::Log( _L("- Decode left when reading Text header, error: %d"), error ); |
|
1715 } |
|
1716 #endif |
|
1717 |
|
1718 if ( matchFound ) |
|
1719 { |
|
1720 return header; |
|
1721 } |
|
1722 |
|
1723 // If we could interpret text headers, it should be done here |
|
1724 // For now we just skip the field value without trying to interpret it. |
|
1725 // As we cannot interpret the header, we must skip the value. |
|
1726 // If a text header match was found in our table, we can interpret the header |
|
1727 // and we leave the value intact |
|
1728 |
|
1729 if ( iPosition < iLength && header == -1 ) |
|
1730 { |
|
1731 SkipFieldValue(); |
|
1732 } |
|
1733 else |
|
1734 { |
|
1735 iError = KErrCorrupt; |
|
1736 } |
|
1737 |
|
1738 return header; |
|
1739 } |
|
1740 |
|
1741 // --------------------------------------------------------- |
|
1742 // |
|
1743 // --------------------------------------------------------- |
|
1744 // |
|
1745 /* |
|
1746 // not used any more |
|
1747 void CMmsDecode::SkipTextString() |
|
1748 { |
|
1749 |
|
1750 TUint8 byte; |
|
1751 |
|
1752 iDecodeBuffer->Read(iPosition, &byte, 1); |
|
1753 iPosition++; |
|
1754 |
|
1755 // don't read beyond buffer |
|
1756 while ( byte != 0 && iPosition < iLength ) |
|
1757 { |
|
1758 iDecodeBuffer->Read(iPosition, &byte, 1); |
|
1759 iPosition++; |
|
1760 } |
|
1761 |
|
1762 return; |
|
1763 } |
|
1764 */ |
|
1765 |
|
1766 // --------------------------------------------------------- |
|
1767 // |
|
1768 // --------------------------------------------------------- |
|
1769 // |
|
1770 void CMmsDecode::SkipFieldValue() |
|
1771 { |
|
1772 |
|
1773 TUint length; |
|
1774 length = GetValueLength(); |
|
1775 #ifndef _NO_MMSS_LOGGING_ |
|
1776 // This is an error situation, log always if logging allowed |
|
1777 TMmsLogger::Log( _L("- Skipped field value: %d bytes"), length); |
|
1778 #endif |
|
1779 |
|
1780 #ifndef _NO_MMSS_LOGGING_ |
|
1781 // this may produce a long log - but only if the message is weird |
|
1782 TUint i; |
|
1783 TUint8 byte; |
|
1784 TBuf<1> character; |
|
1785 for ( i = iPosition; i < iPosition + length && i < iLength; i++ ) |
|
1786 { |
|
1787 iDecodeBuffer->Read(i, &byte, 1); |
|
1788 TUint16 word = byte; |
|
1789 if ( byte >= KMms0x20 && byte < KMms0x7F ) |
|
1790 { |
|
1791 character.Copy( &word, 1 ); |
|
1792 TMmsLogger::Log( _L("- 0x%02X %S"), byte, &character ); |
|
1793 } |
|
1794 else |
|
1795 { |
|
1796 TMmsLogger::Log( _L("- 0x%02X"), byte ); |
|
1797 } |
|
1798 } |
|
1799 #endif |
|
1800 iPosition += length; |
|
1801 // if iPosition == iLength, this was the last header, and we are not necessaily corrupted |
|
1802 // If the PDU contains only headers, and the last one is a text header whose value will be |
|
1803 // skipped, we are all right if iPosition == iLength. |
|
1804 if ( iPosition > iLength ) |
|
1805 { |
|
1806 iError = KErrCorrupt; |
|
1807 } |
|
1808 |
|
1809 } |
|
1810 |
|
1811 // --------------------------------------------------------- |
|
1812 // |
|
1813 // --------------------------------------------------------- |
|
1814 // |
|
1815 void CMmsDecode::SkipParameterName() |
|
1816 { |
|
1817 |
|
1818 TUint8 byte; |
|
1819 |
|
1820 if ( iPosition >= iLength ) |
|
1821 { |
|
1822 return; |
|
1823 } |
|
1824 |
|
1825 iDecodeBuffer->Read(iPosition, &byte, 1); |
|
1826 |
|
1827 |
|
1828 // byte cannot be bigger than 255. No need to test upper limit |
|
1829 if ( byte >= KMms0x80 ) |
|
1830 { |
|
1831 // well known header, advance pointer and remove high bit |
|
1832 iPosition++; |
|
1833 #ifndef _NO_MMSS_LOGGING_ |
|
1834 TMmsLogger::Log( _L("- Skipped parameter: 0x%02X"), byte); |
|
1835 #endif |
|
1836 } |
|
1837 else |
|
1838 { |
|
1839 TPtrC8 byteString = GetByteString(); |
|
1840 #ifndef _NO_MMSS_LOGGING_ |
|
1841 // we don't leave because of logging |
|
1842 TInt error = KErrNone; |
|
1843 TRAP( error, |
|
1844 { |
|
1845 HBufC16* buffer = NULL; |
|
1846 buffer = HBufC16::NewLC( byteString.Length() ); |
|
1847 buffer->Des().Copy( byteString ); |
|
1848 TPtrC dummy; |
|
1849 // we cannot log indefinitely long strings. |
|
1850 // We get this long strings only if the message is corrupted. |
|
1851 dummy.Set( buffer->Des().Left( KMmsMaxLogStringLength ) ); |
|
1852 TMmsLogger::Log( _L("- Skipped parameter : %S"), &dummy ); |
|
1853 CleanupStack::PopAndDestroy( buffer ); |
|
1854 }); |
|
1855 if ( error != KErrNone ) |
|
1856 { |
|
1857 TMmsLogger::Log( _L("- Decode left when logging skipped parameter, error : %d"), |
|
1858 error ); |
|
1859 } |
|
1860 #endif |
|
1861 } |
|
1862 |
|
1863 } |
|
1864 |
|
1865 |
|
1866 // --------------------------------------------------------- |
|
1867 // |
|
1868 // --------------------------------------------------------- |
|
1869 // |
|
1870 TUint32 CMmsDecode::GetUintvar() |
|
1871 { |
|
1872 |
|
1873 TUint32 uintvar; |
|
1874 uintvar = 0; |
|
1875 TUint8 byte; |
|
1876 |
|
1877 if ( iPosition >= iLength ) |
|
1878 { |
|
1879 return uintvar; |
|
1880 } |
|
1881 |
|
1882 iDecodeBuffer->Read(iPosition, &byte, 1); |
|
1883 |
|
1884 while ( byte & KMms0x80 && iPosition < iLength - 1 ) |
|
1885 { |
|
1886 uintvar += ( byte & KMms0x7F ); |
|
1887 uintvar <<= KMmsUintvarShift; |
|
1888 iPosition++; |
|
1889 iDecodeBuffer->Read(iPosition, &byte, 1); |
|
1890 } |
|
1891 |
|
1892 // add last byte without shift |
|
1893 uintvar += byte; |
|
1894 iPosition++; |
|
1895 |
|
1896 // If the file is corrupted, the length may be so big it becomes negative |
|
1897 // We must make sure the value is less than maximum signed 32-bit integer. |
|
1898 // |
|
1899 if ( uintvar > TUint32( KMaxTInt32 ) ) |
|
1900 { |
|
1901 uintvar = TUint32( KMaxTInt32 ); |
|
1902 } |
|
1903 |
|
1904 return uintvar; |
|
1905 } |
|
1906 |
|
1907 // --------------------------------------------------------- |
|
1908 // |
|
1909 // --------------------------------------------------------- |
|
1910 // |
|
1911 HBufC16* CMmsDecode::DecodeFromL() |
|
1912 { |
|
1913 |
|
1914 TUint8 byte = 0; |
|
1915 TUint length = 0; |
|
1916 |
|
1917 TUint start; |
|
1918 start = iPosition; |
|
1919 length = GetValueLength(); |
|
1920 |
|
1921 // Get next token to see, if we have the address present token |
|
1922 if ( iPosition < iLength ) |
|
1923 { |
|
1924 iDecodeBuffer->Read(iPosition, &byte, 1); |
|
1925 } |
|
1926 |
|
1927 if ( byte > KMms0x7F ) |
|
1928 { |
|
1929 // an encoded token |
|
1930 // It must be address present or be insert address |
|
1931 iPosition++; |
|
1932 if ( iPosition >= iLength ) |
|
1933 { |
|
1934 iError = KErrCorrupt; |
|
1935 return HBufC16::NewL( 0 ); |
|
1936 } |
|
1937 |
|
1938 // These two are the only two valid ones. |
|
1939 if ( byte != KMmsAddressPresentToken && byte != KMmsInsertAddressToken) |
|
1940 { |
|
1941 // this encoding is a mess. |
|
1942 // try if it resolves as an encoded string without |
|
1943 // these tokens |
|
1944 iPosition = start; |
|
1945 } |
|
1946 } |
|
1947 |
|
1948 if ( length > 1 ) |
|
1949 { |
|
1950 return DecodeAddressL(); |
|
1951 } |
|
1952 else |
|
1953 { |
|
1954 return HBufC16::NewL( 0 ); |
|
1955 } |
|
1956 |
|
1957 } |
|
1958 |
|
1959 // --------------------------------------------------------- |
|
1960 // |
|
1961 // --------------------------------------------------------- |
|
1962 // |
|
1963 HBufC16* CMmsDecode::DecodeAddressL() |
|
1964 { |
|
1965 |
|
1966 HBufC16* buffer = NULL; // will be allocated by called subroutine |
|
1967 |
|
1968 if ( iPosition >= iLength ) |
|
1969 { |
|
1970 return HBufC16::NewL( 0 ); |
|
1971 } |
|
1972 |
|
1973 // always use GetEncodedTextStringL(), it handles simple text strings, too |
|
1974 |
|
1975 buffer = GetEncodedTextStringL(); |
|
1976 |
|
1977 // If our address contains an appended type specification, |
|
1978 // it must be removed |
|
1979 |
|
1980 TInt position; |
|
1981 TPtr temp = buffer->Des(); |
|
1982 _LIT ( KDot, "." ); |
|
1983 |
|
1984 position = buffer->FindF( KMmsPlmnu().Ptr(), KMmsPlmnLength ); |
|
1985 if ( position != KErrNotFound ) |
|
1986 { |
|
1987 temp.SetLength( position ); |
|
1988 // remove dots from phone number in order to keep |
|
1989 // plmn number and ipv4 number different. |
|
1990 position = temp.Find( KDot ); |
|
1991 while ( position >= 0 ) |
|
1992 { |
|
1993 temp.Delete( position, 1 ); |
|
1994 position = temp.Find( KDot ); |
|
1995 } |
|
1996 } |
|
1997 else |
|
1998 { |
|
1999 position = buffer->FindF( KMmsIpv4u().Ptr(), KMmsIpv4Length ); |
|
2000 if ( position != KErrNotFound ) |
|
2001 { |
|
2002 temp.SetLength( position ); |
|
2003 } |
|
2004 else |
|
2005 { |
|
2006 position = buffer->FindF( KMmsIpv6u().Ptr(), KMmsIpv4Length ); |
|
2007 if ( position != KErrNotFound ) |
|
2008 { |
|
2009 temp.SetLength( position ); |
|
2010 } |
|
2011 } |
|
2012 } |
|
2013 |
|
2014 return buffer; |
|
2015 } |
|
2016 |
|
2017 |
|
2018 // --------------------------------------------------------- |
|
2019 // |
|
2020 // --------------------------------------------------------- |
|
2021 // |
|
2022 HBufC16* CMmsDecode::GetSimpleTextStringL( TBool aKeepQuote /*= EFalse*/ ) |
|
2023 { |
|
2024 // we don't handle quoted strings. |
|
2025 // they should be present only in application headers, and |
|
2026 // we don't handle those |
|
2027 |
|
2028 TUint8 byte; |
|
2029 HBufC16* buffer = NULL; // we must know length before trying to allocate |
|
2030 TUint stringLength; |
|
2031 TChar character; |
|
2032 |
|
2033 if ( iPosition >= iLength ) |
|
2034 { |
|
2035 return HBufC16::NewL(0); |
|
2036 } |
|
2037 iDecodeBuffer->Read( iPosition, &byte, 1 ); |
|
2038 |
|
2039 if ( byte == 0 ) |
|
2040 { |
|
2041 // empty string. |
|
2042 iPosition++; |
|
2043 return HBufC16::NewL(0); |
|
2044 } |
|
2045 |
|
2046 if ( byte == KMmsQuote ) |
|
2047 { |
|
2048 // skip quote |
|
2049 iPosition++; |
|
2050 if ( iPosition >= iLength ) |
|
2051 { |
|
2052 return HBufC16::NewL(1); |
|
2053 } |
|
2054 iDecodeBuffer->Read( iPosition, &byte, 1 ); |
|
2055 } |
|
2056 |
|
2057 TBool foundQuote = EFalse; |
|
2058 |
|
2059 if ( byte == KMmsStringQuote && !aKeepQuote ) |
|
2060 { |
|
2061 // skip quote |
|
2062 iPosition++; |
|
2063 foundQuote = ETrue; |
|
2064 if ( iPosition >= iLength ) |
|
2065 { |
|
2066 return HBufC16::NewL(0); |
|
2067 } |
|
2068 iDecodeBuffer->Read( iPosition, &byte, 1 ); |
|
2069 } |
|
2070 |
|
2071 stringLength = iPosition; |
|
2072 |
|
2073 while ( byte != 0 && stringLength < iLength ) |
|
2074 { |
|
2075 iDecodeBuffer->Read( stringLength, &byte, 1 ); |
|
2076 stringLength++; |
|
2077 } |
|
2078 |
|
2079 // The diffrence of pointers is the actual string length |
|
2080 // including the terminating zero. |
|
2081 stringLength -= iPosition; |
|
2082 |
|
2083 if ( iPosition >= iLength ) |
|
2084 { |
|
2085 return HBufC16::NewL(0); |
|
2086 } |
|
2087 |
|
2088 iDecodeBuffer->Read( iPosition, &byte, 1 ); |
|
2089 if ( byte == 0 ) |
|
2090 { |
|
2091 // Empty string. Only terminating zero. |
|
2092 // Must point past the terminating zero at exit |
|
2093 iPosition++; |
|
2094 } |
|
2095 |
|
2096 // Allocate buffer for unicode. |
|
2097 // Check if this is too long, |
|
2098 // (allocating just stringLength left or panicked...) |
|
2099 buffer = HBufC16::NewL( stringLength*KMms2 + KMms2 ); |
|
2100 |
|
2101 while ( byte != 0 && iPosition < iLength ) |
|
2102 { |
|
2103 iDecodeBuffer->Read(iPosition, &byte, 1); |
|
2104 if ( byte != 0 ) |
|
2105 { |
|
2106 character = byte; |
|
2107 buffer->Des().Append( character ); |
|
2108 } |
|
2109 iPosition++; |
|
2110 } |
|
2111 |
|
2112 if ( foundQuote && buffer->Des().Right( 1 ).Compare( KQuote16 ) == 0 ) |
|
2113 { |
|
2114 // if we removed the leading quote, we remove the trailing quote, too. |
|
2115 buffer->Des().Delete( buffer->Des().Length() - 1, 1 ); |
|
2116 } |
|
2117 return buffer; |
|
2118 |
|
2119 } |
|
2120 |
|
2121 // --------------------------------------------------------- |
|
2122 // |
|
2123 // --------------------------------------------------------- |
|
2124 // |
|
2125 HBufC16* CMmsDecode::GetEncodedTextStringL() |
|
2126 { |
|
2127 |
|
2128 TUint8 byte; |
|
2129 HBufC16* buffer = NULL; // we must know length before trying to allocate |
|
2130 TUint stringLength = 0; |
|
2131 TUint32 charset = 0; |
|
2132 TUint start; |
|
2133 |
|
2134 if (iPosition >= iLength ) |
|
2135 { |
|
2136 iError = KErrCorrupt; |
|
2137 buffer = HBufC16::NewL(0); |
|
2138 return buffer; |
|
2139 } |
|
2140 |
|
2141 iDecodeBuffer->Read(iPosition, &byte, 1); |
|
2142 |
|
2143 if ( ( byte > KMms31 && byte < KMms0x80 ) || byte == 0 ) |
|
2144 { |
|
2145 // simple text string. Restart. |
|
2146 // (includes empty strings) |
|
2147 // Keep quote because these are strange strings that may contain any |
|
2148 // number of quotes all over the place |
|
2149 buffer = GetSimpleTextStringL( ETrue ); |
|
2150 // check if this looks like it needs decoding of MIME stuff (RFC2047) |
|
2151 if ( buffer->Des().FindF( KEqualsQuestion16 ) == KErrNotFound ) |
|
2152 { |
|
2153 return buffer; |
|
2154 } |
|
2155 else |
|
2156 { |
|
2157 // contains the magic equals-question mark combination, |
|
2158 // try if MIME decoding succeeds |
|
2159 CleanupStack::PushL( buffer ); |
|
2160 HBufC8* buffer8 = HBufC8::NewL( buffer->Des().Length() ); |
|
2161 buffer8->Des().Copy( buffer->Des() ); |
|
2162 CleanupStack::PushL( buffer8 ); |
|
2163 TPtr pointer = buffer->Des(); |
|
2164 TRAPD( error, |
|
2165 TMmsGenUtils::DecodeAndConvertMessageHeaderL( buffer8->Des(), pointer, iFs ) ); |
|
2166 if ( error != KErrNone ) |
|
2167 { |
|
2168 // if did not succeed, keep original as is |
|
2169 buffer->Des().Copy( buffer8->Des() ); |
|
2170 } |
|
2171 CleanupStack::PopAndDestroy( buffer8 ); |
|
2172 CleanupStack::Pop( buffer ); |
|
2173 return buffer; |
|
2174 } |
|
2175 } |
|
2176 |
|
2177 iPosition++; |
|
2178 |
|
2179 if (iPosition >= iLength ) |
|
2180 { |
|
2181 iError = KErrCorrupt; |
|
2182 buffer = HBufC16::NewL(0); |
|
2183 return buffer; |
|
2184 } |
|
2185 |
|
2186 if ( byte >= KMms0x80 ) |
|
2187 { |
|
2188 // the message is corrupted. |
|
2189 iError = KErrCorrupt; |
|
2190 buffer = HBufC16::NewL(0); |
|
2191 return buffer; |
|
2192 } |
|
2193 |
|
2194 if ( byte == KMms31 ) |
|
2195 { |
|
2196 stringLength = GetUintvar(); |
|
2197 } |
|
2198 else |
|
2199 { |
|
2200 stringLength = byte; |
|
2201 } |
|
2202 |
|
2203 // Get character set |
|
2204 // Character set must be an integer, short or long |
|
2205 |
|
2206 // check if character set is missing |
|
2207 charset = GetLongOrShortInteger(); |
|
2208 #ifndef _NO_MMSS_LOGGING_ |
|
2209 if ( charset != 0 ) |
|
2210 { |
|
2211 TMmsLogger::Log( _L("- Encoded string charset %d"), charset ); |
|
2212 } |
|
2213 #endif |
|
2214 |
|
2215 if ( iPosition >= iLength || iError == KErrCorrupt ) |
|
2216 { |
|
2217 iError = KErrCorrupt; |
|
2218 buffer = HBufC16::NewL(0); |
|
2219 return buffer; |
|
2220 } |
|
2221 |
|
2222 // Get text length whatever character set |
|
2223 |
|
2224 iDecodeBuffer->Read(iPosition, &byte, 1); |
|
2225 |
|
2226 if ( byte == KMmsQuote ) |
|
2227 { |
|
2228 // skip quote |
|
2229 iPosition++; |
|
2230 if (iPosition < iLength) |
|
2231 { |
|
2232 iDecodeBuffer->Read(iPosition, &byte, 1); |
|
2233 } |
|
2234 } |
|
2235 |
|
2236 start = iPosition; |
|
2237 stringLength = 0; |
|
2238 TBool foundQuote = EFalse; |
|
2239 |
|
2240 // Leave quote as is. |
|
2241 // It has turned out that we do not get quoted strings in the WSP format |
|
2242 // with leading quote only. We tend to get either both the leading and |
|
2243 // trailing quote or none at all, so we better not remove the quote. |
|
2244 // If we start seeing WSP quoted strings, we must start checking that |
|
2245 // leading and trailing quotes match. |
|
2246 |
|
2247 /* |
|
2248 if ( byte == KMmsStringQuote ) |
|
2249 { |
|
2250 // skip quote |
|
2251 iPosition++; |
|
2252 start++; |
|
2253 foundQuote = ETrue; |
|
2254 } |
|
2255 */ |
|
2256 |
|
2257 while ( byte != 0 && iPosition < iLength ) |
|
2258 { |
|
2259 iDecodeBuffer->Read(iPosition, &byte, 1); |
|
2260 iPosition++; |
|
2261 stringLength++; |
|
2262 } |
|
2263 |
|
2264 // stringLength includes the terminating zero |
|
2265 |
|
2266 // allocate buffer for unicode |
|
2267 // this should be the maximum we'll ever need |
|
2268 if ( stringLength == 0 ) |
|
2269 { |
|
2270 // The length of the string == 0 |
|
2271 // This is an empty string |
|
2272 // I'm not sure if it is legal or not - but we keep it anyway |
|
2273 if ( iPosition == start ) |
|
2274 { |
|
2275 // we did not read anything, the first byte was 0. |
|
2276 // we must advance out pointer beyond it |
|
2277 iPosition++; |
|
2278 } |
|
2279 buffer = HBufC16::NewL(0); |
|
2280 return buffer; |
|
2281 } |
|
2282 |
|
2283 stringLength--; // remove the terminating zero |
|
2284 buffer = HBufC16::NewL( stringLength * KMms2 ); |
|
2285 |
|
2286 if ( stringLength == 0 ) |
|
2287 { |
|
2288 // buffer has zero length |
|
2289 // I assume this is an empty string |
|
2290 // I'm not sure if it is legal or not |
|
2291 return buffer; |
|
2292 } |
|
2293 |
|
2294 if ( charset == KMmsUtf8 ) |
|
2295 { |
|
2296 TPtr8 pointer( iDecodeBuffer->Ptr( start ) ); |
|
2297 pointer.SetLength( stringLength ); |
|
2298 TInt error; |
|
2299 TPtr16 pointer16 = buffer->Des(); |
|
2300 error = CnvUtfConverter::ConvertToUnicodeFromUtf8( pointer16, pointer ); |
|
2301 // should check error |
|
2302 if ( error != KErrNone ) |
|
2303 { |
|
2304 buffer->Des().Copy( pointer ) ; // could not convert, just copy garbage |
|
2305 } |
|
2306 } |
|
2307 else |
|
2308 { |
|
2309 // other character sets to be implemented... |
|
2310 TPtr8 pointer( iDecodeBuffer->Ptr( start ) ); |
|
2311 pointer.SetLength( stringLength ); |
|
2312 buffer->Des().Copy( pointer ) ; // just copy without conversion |
|
2313 } |
|
2314 |
|
2315 if ( foundQuote && buffer->Des().Right( 1 ).Compare( KQuote16 ) == 0 ) |
|
2316 { |
|
2317 // if we removed the leading quote, we remove the trailing quote, too. |
|
2318 buffer->Des().Delete( buffer->Des().Length() - 1, 1 ); |
|
2319 } |
|
2320 return buffer; |
|
2321 } |
|
2322 |
|
2323 // --------------------------------------------------------- |
|
2324 // |
|
2325 // --------------------------------------------------------- |
|
2326 // |
|
2327 TPtrC8 CMmsDecode::GetByteString() |
|
2328 { |
|
2329 |
|
2330 TUint8 byte = 0; |
|
2331 if ( iPosition < iLength ) |
|
2332 { |
|
2333 iDecodeBuffer->Read( iPosition, &byte, 1 ); |
|
2334 } |
|
2335 else |
|
2336 { |
|
2337 return TPtrC8(); |
|
2338 } |
|
2339 |
|
2340 TUint start = iPosition; |
|
2341 TUint length = 0; |
|
2342 |
|
2343 if ( byte == 0 ) |
|
2344 { |
|
2345 // Empty string, skip over terminating zero. |
|
2346 // Empty string may or may not be legal - we must |
|
2347 // be prepared to accept it. |
|
2348 // The caller must decide if empty value is legal or not. |
|
2349 iPosition++; |
|
2350 return TPtrC8(); |
|
2351 } |
|
2352 |
|
2353 TBool foundQuote = EFalse; |
|
2354 if ( ( byte >= KMms32 ) && ( byte <= KMms0x7F ) ) |
|
2355 { |
|
2356 if ( byte == KMmsStringQuote ) |
|
2357 { |
|
2358 // skip quote |
|
2359 iPosition++; |
|
2360 start++; |
|
2361 foundQuote = ETrue; |
|
2362 } |
|
2363 else if ( byte == KMmsQuote ) |
|
2364 { |
|
2365 // We are not supposed to have a string starting with quote here |
|
2366 // but we must be careful and strip the quote in case one exists. |
|
2367 // skip quote |
|
2368 iPosition++; |
|
2369 start++; |
|
2370 } |
|
2371 |
|
2372 // don't read beyond buffer |
|
2373 // byte is between 32 and 127 when we come here. |
|
2374 while ( byte != 0 && iPosition < iLength ) |
|
2375 { |
|
2376 iDecodeBuffer->Read(iPosition, &byte, 1); |
|
2377 iPosition++; |
|
2378 } |
|
2379 // now iPosition points beyond terminating zero - if there is one |
|
2380 |
|
2381 length = iPosition - start; |
|
2382 if ( length > 1 ) |
|
2383 { |
|
2384 // remove terminating zero if there is one |
|
2385 length--; |
|
2386 } |
|
2387 // If we got a end-of-string immediately after string quote, |
|
2388 // we have nothing left here. |
|
2389 // Or even worse - we have not even the terminating zero |
|
2390 if ( length < 1 ) |
|
2391 { |
|
2392 return TPtrC8(); |
|
2393 } |
|
2394 TPtr8 pointer( iDecodeBuffer->Ptr( start ) ); |
|
2395 pointer.SetLength( length ); |
|
2396 // Length is at least one, it was just checked. |
|
2397 if ( foundQuote && ( pointer.Right( 1 )[0] == KMmsStringQuote ) ) |
|
2398 { |
|
2399 length--; // decrease length to remove end quote |
|
2400 } |
|
2401 pointer.SetLength( length ); |
|
2402 return TPtrC8( pointer ); |
|
2403 } |
|
2404 else |
|
2405 { |
|
2406 SkipFieldValue(); |
|
2407 return TPtrC8(); |
|
2408 } |
|
2409 |
|
2410 } |
|
2411 |
|
2412 // --------------------------------------------------------- |
|
2413 // |
|
2414 // --------------------------------------------------------- |
|
2415 // |
|
2416 TPtrC8 CMmsDecode::GetUtf8String() |
|
2417 { |
|
2418 TUint8 byte = 0; |
|
2419 if ( iPosition < iLength ) |
|
2420 { |
|
2421 iDecodeBuffer->Read( iPosition, &byte, 1 ); |
|
2422 } |
|
2423 else |
|
2424 { |
|
2425 return TPtrC8(); |
|
2426 } |
|
2427 |
|
2428 TUint start = iPosition; |
|
2429 TUint length = 0; |
|
2430 |
|
2431 if ( byte == 0 ) |
|
2432 { |
|
2433 // Empty string, skip over terminating zero. |
|
2434 // Empty string may or may not be legal - we must |
|
2435 // be prepared to accept it. |
|
2436 // The caller must decide if empty value is legal or not. |
|
2437 iPosition++; |
|
2438 return TPtrC8(); |
|
2439 } |
|
2440 |
|
2441 if ( byte == KMmsQuote ) |
|
2442 { |
|
2443 // skip quote |
|
2444 iPosition++; |
|
2445 start++; |
|
2446 } |
|
2447 |
|
2448 // don't read beyond buffer |
|
2449 while ( byte != 0 && iPosition < iLength ) |
|
2450 { |
|
2451 iDecodeBuffer->Read(iPosition, &byte, 1); |
|
2452 iPosition++; |
|
2453 } |
|
2454 |
|
2455 // now iPosition points beyond terminating zero |
|
2456 length = iPosition - start - 1; |
|
2457 // If we got a end-of-string immediately after string quote, |
|
2458 // we have nothing left here. |
|
2459 if ( length < 1 ) |
|
2460 { |
|
2461 return TPtrC8(); |
|
2462 } |
|
2463 TPtr8 pointer( iDecodeBuffer->Ptr( start ) ); |
|
2464 pointer.SetLength( length ); |
|
2465 return TPtrC8( pointer ); |
|
2466 } |
|
2467 |
|
2468 // --------------------------------------------------------- |
|
2469 // |
|
2470 // --------------------------------------------------------- |
|
2471 // |
|
2472 TUint32 CMmsDecode::GetLongOrShortInteger() |
|
2473 { |
|
2474 |
|
2475 TUint8 byte; |
|
2476 TUint32 integer = 0; |
|
2477 |
|
2478 if ( iPosition >= iLength ) |
|
2479 { |
|
2480 return integer; |
|
2481 } |
|
2482 |
|
2483 iDecodeBuffer->Read(iPosition, &byte, 1); |
|
2484 iPosition++; |
|
2485 if ( byte & KMms0x80 ) |
|
2486 { |
|
2487 integer = byte & KMms0x7F; |
|
2488 return integer; |
|
2489 } |
|
2490 |
|
2491 if ( byte > KMms30 ) |
|
2492 { |
|
2493 // Data is corrupted. |
|
2494 iError = KErrCorrupt; |
|
2495 return integer; |
|
2496 } |
|
2497 |
|
2498 if ( byte > KMmsMaxIntegerLength ) |
|
2499 { |
|
2500 // too long. |
|
2501 iError = KErrTooBig; |
|
2502 iPosition--; |
|
2503 // It the caller thinks retry is possible, he must store the |
|
2504 // original starting position. |
|
2505 // So far no case has been found where the retry with very long |
|
2506 // integer would be needed. |
|
2507 SkipFieldValue(); |
|
2508 return integer; |
|
2509 } |
|
2510 |
|
2511 TUint i; |
|
2512 TUint length; |
|
2513 length = byte; |
|
2514 for ( i = 0; i < length && iPosition < iLength; i++) |
|
2515 { |
|
2516 integer <<= KMmsBitsInByte; |
|
2517 iDecodeBuffer->Read(iPosition, &byte, 1); |
|
2518 iPosition++; |
|
2519 integer += byte; |
|
2520 } |
|
2521 |
|
2522 return integer; |
|
2523 |
|
2524 } |
|
2525 |
|
2526 // --------------------------------------------------------- |
|
2527 // |
|
2528 // --------------------------------------------------------- |
|
2529 // |
|
2530 TInt64 CMmsDecode::GetVeryLongInteger() |
|
2531 { |
|
2532 |
|
2533 TUint8 byte; |
|
2534 TInt64 veryLongInteger; |
|
2535 |
|
2536 veryLongInteger = 0; |
|
2537 |
|
2538 iDecodeBuffer->Read(iPosition, &byte, 1); |
|
2539 iPosition++; |
|
2540 if ( byte & KMms0x80 ) |
|
2541 { |
|
2542 veryLongInteger = byte & KMms0x7F; |
|
2543 return veryLongInteger; |
|
2544 } |
|
2545 |
|
2546 if ( byte > KMms30 ) |
|
2547 { |
|
2548 // data is corrupted. |
|
2549 iError = KErrCorrupt; |
|
2550 return veryLongInteger; |
|
2551 } |
|
2552 |
|
2553 if ( byte > KMmsMaxLongIntegerLength ) |
|
2554 { |
|
2555 // too long. |
|
2556 iError = KErrTooBig; |
|
2557 iPosition--; |
|
2558 // caller may do whatever he wants, or skip whole field |
|
2559 return veryLongInteger; |
|
2560 } |
|
2561 |
|
2562 TUint i; |
|
2563 TUint length; |
|
2564 length = byte; |
|
2565 |
|
2566 for ( i = 0; i < length && iPosition < iLength; i++) |
|
2567 { |
|
2568 veryLongInteger <<= KMmsBitsInByte; |
|
2569 iDecodeBuffer->Read(iPosition, &byte, 1); |
|
2570 iPosition++; |
|
2571 veryLongInteger += TUint( byte ); |
|
2572 } |
|
2573 |
|
2574 return veryLongInteger; |
|
2575 } |
|
2576 |
|
2577 // --------------------------------------------------------- |
|
2578 // |
|
2579 // --------------------------------------------------------- |
|
2580 // |
|
2581 TUint8 CMmsDecode::GetWellKnownFieldValueOrSkip() |
|
2582 { |
|
2583 |
|
2584 TUint8 byte; |
|
2585 byte = 0; |
|
2586 iDecodeBuffer->Read(iPosition, &byte, 1); |
|
2587 |
|
2588 // Interpret the length of the field |
|
2589 |
|
2590 // one byte encoded value, this field has no more data |
|
2591 if ( byte >= KMms0x80 ) |
|
2592 { |
|
2593 iPosition++; |
|
2594 return byte; |
|
2595 } |
|
2596 |
|
2597 // if not one byte token, skip it |
|
2598 SkipFieldValue(); |
|
2599 return byte; // this is < 128, which is never a legal token |
|
2600 |
|
2601 } |
|
2602 |
|
2603 // --------------------------------------------------------- |
|
2604 // |
|
2605 // --------------------------------------------------------- |
|
2606 // |
|
2607 TUint8 CMmsDecode::GetRelativeOrAbsoluteTime( TInt64& aTime ) |
|
2608 { |
|
2609 TUint8 byte; |
|
2610 TInt length; |
|
2611 |
|
2612 // we don't use the length, we just skip it |
|
2613 length = GetValueLength(); |
|
2614 if ( ( iPosition + length ) > iLength || iPosition >= iLength ) |
|
2615 { |
|
2616 iPosition = iLength; |
|
2617 aTime = 0; |
|
2618 byte = 0; |
|
2619 iError = KErrCorrupt; |
|
2620 return byte; |
|
2621 } |
|
2622 |
|
2623 iDecodeBuffer->Read(iPosition, &byte, 1); |
|
2624 |
|
2625 if ( ( byte != KMmsAbsoluteToken ) && ( byte != KMmsRelativeToken ) ) |
|
2626 { |
|
2627 // illegal encoding, skip. |
|
2628 iPosition += length; |
|
2629 byte = 0; |
|
2630 aTime = 0; |
|
2631 return byte; |
|
2632 } |
|
2633 |
|
2634 iPosition++; |
|
2635 if ( iPosition >= iLength ) |
|
2636 { |
|
2637 iError = KErrCorrupt; |
|
2638 byte = 0; |
|
2639 aTime = 0; |
|
2640 return byte; |
|
2641 } |
|
2642 |
|
2643 aTime = GetVeryLongInteger(); |
|
2644 |
|
2645 return byte; |
|
2646 } |
|
2647 |
|
2648 // --------------------------------------------------------- |
|
2649 // |
|
2650 // --------------------------------------------------------- |
|
2651 // |
|
2652 TUint CMmsDecode::GetValueLength() |
|
2653 { |
|
2654 TUint8 byte; |
|
2655 TUint length = 0; |
|
2656 |
|
2657 if ( iPosition >= iLength ) |
|
2658 { |
|
2659 return 0; |
|
2660 } |
|
2661 |
|
2662 iDecodeBuffer->Read(iPosition, &byte, 1); |
|
2663 |
|
2664 // Interpret the length of the field |
|
2665 |
|
2666 // one byte encoded value, this field has no more data |
|
2667 if ( byte >= KMms0x80 ) |
|
2668 { |
|
2669 length = 1; |
|
2670 return length; |
|
2671 } |
|
2672 |
|
2673 // text string |
|
2674 // ( byte >= 128 returned already, so byte must be <=127 if we are here ) |
|
2675 if ( byte >= KMms32 ) |
|
2676 { |
|
2677 // find the end |
|
2678 length = iPosition; |
|
2679 |
|
2680 while ( byte != 0 && length < iLength ) |
|
2681 { |
|
2682 iDecodeBuffer->Read(length, &byte, 1); |
|
2683 length++; |
|
2684 } |
|
2685 |
|
2686 // The difference of pointers is the actual string length |
|
2687 length -= iPosition; |
|
2688 |
|
2689 return length; |
|
2690 } |
|
2691 |
|
2692 // octet followed by a uintvar |
|
2693 if ( byte == KMms31 ) |
|
2694 { |
|
2695 iPosition++; |
|
2696 // uintvar can be max 5 bytes, max value of |
|
2697 // result is 32 bits. |
|
2698 // get uintvar |
|
2699 if ( iPosition < iLength ) |
|
2700 { |
|
2701 length = GetUintvar(); |
|
2702 } |
|
2703 return length; |
|
2704 } |
|
2705 |
|
2706 // remains: octets 0 - 30 |
|
2707 // octet followed by the indicated number of data octets |
|
2708 iPosition++; |
|
2709 length = byte; |
|
2710 return length; |
|
2711 |
|
2712 } |
|
2713 |
|
2714 |
|
2715 // --------------------------------------------------------- |
|
2716 // |
|
2717 // --------------------------------------------------------- |
|
2718 // |
|
2719 TBool CMmsDecode::CheckHeaderLength() |
|
2720 { |
|
2721 TInt oldPosition = iPosition; |
|
2722 TBool retVal = ETrue; // optimistic |
|
2723 TUint8 byte; |
|
2724 |
|
2725 TBool checkUintvarData = ETrue; |
|
2726 |
|
2727 if ( iPosition < iLength ) |
|
2728 { |
|
2729 // read first byte for some special checks |
|
2730 iDecodeBuffer->Read( iPosition, &byte, 1 ); |
|
2731 } |
|
2732 else |
|
2733 { |
|
2734 return EFalse; |
|
2735 } |
|
2736 |
|
2737 if ( iDecodingStage == EMmsAttachmentHeaders ) |
|
2738 { |
|
2739 if ( ( byte & KMms0x80 ) && ( ( byte & KMms0x7F ) == KWspQValue ) ) |
|
2740 { |
|
2741 // Quality factor in attachment headers has strange encoding |
|
2742 checkUintvarData = EFalse; |
|
2743 } |
|
2744 } |
|
2745 |
|
2746 // check header first - uintvar data included |
|
2747 retVal = CheckValueLength( ETrue ); |
|
2748 |
|
2749 // The position of the pointer is at the end of the header name |
|
2750 // if the whole header name is in the buffer |
|
2751 |
|
2752 // Check the length of the header |
|
2753 if ( retVal ) |
|
2754 { |
|
2755 retVal = CheckValueLength( checkUintvarData ); |
|
2756 } |
|
2757 |
|
2758 if ( iDecodingStage == EMmsHeaders ) |
|
2759 { |
|
2760 if ( byte == KMmsAssignedContentType && retVal ) |
|
2761 { |
|
2762 // we need to have an uintvar specifying the number of attachments |
|
2763 // to follow content type header |
|
2764 retVal = CheckUintvarLength(); |
|
2765 } |
|
2766 } |
|
2767 |
|
2768 // always restore the pointer for decoding |
|
2769 iPosition = oldPosition; |
|
2770 return retVal; |
|
2771 } |
|
2772 |
|
2773 // --------------------------------------------------------- |
|
2774 // |
|
2775 // --------------------------------------------------------- |
|
2776 // |
|
2777 TBool CMmsDecode::CheckValueLength( TBool aCheckUintvarData ) |
|
2778 { |
|
2779 TBool retVal = ETrue; // optimistic |
|
2780 |
|
2781 TUint8 byte; |
|
2782 TUint length = 0; |
|
2783 |
|
2784 if ( iPosition >= iLength ) |
|
2785 { |
|
2786 return EFalse; |
|
2787 } |
|
2788 |
|
2789 iDecodeBuffer->Read(iPosition, &byte, 1); |
|
2790 |
|
2791 // Interpret the length of the field |
|
2792 |
|
2793 if ( byte >= KMms0x80 ) |
|
2794 { |
|
2795 // one byte encoded value, this field has no more data |
|
2796 iPosition++; |
|
2797 } |
|
2798 else if ( byte >= KMms32 ) |
|
2799 { |
|
2800 // text string - find the end |
|
2801 while ( byte != 0 && iPosition < iLength ) |
|
2802 { |
|
2803 iDecodeBuffer->Read( iPosition, &byte, 1 ); |
|
2804 iPosition++; |
|
2805 } |
|
2806 if ( byte != 0 ) |
|
2807 { |
|
2808 // we reached the end of the buffer without finding the terminating 0 |
|
2809 // there is not enough data |
|
2810 retVal = EFalse; |
|
2811 } |
|
2812 } |
|
2813 else if ( byte == KMms31 ) |
|
2814 { |
|
2815 // octet followed by a uintvar |
|
2816 iPosition++; |
|
2817 // get all bytes belonging to uintvar first to see if we have them all. |
|
2818 TInt uintvarStart = iPosition; |
|
2819 if ( CheckUintvarLength() ) |
|
2820 { |
|
2821 // we have an uintvar, do we have all the following bytes |
|
2822 if ( aCheckUintvarData ) |
|
2823 { |
|
2824 iPosition = uintvarStart; |
|
2825 // we are asked to check the data, too |
|
2826 length = GetUintvar(); |
|
2827 if ( ( iLength - iPosition ) < length ) |
|
2828 { |
|
2829 retVal = EFalse; |
|
2830 } |
|
2831 else |
|
2832 { |
|
2833 iPosition += length; |
|
2834 } |
|
2835 } |
|
2836 } |
|
2837 else |
|
2838 { |
|
2839 // we did not even have the uintvar let alone the data following it |
|
2840 retVal = EFalse; |
|
2841 } |
|
2842 } |
|
2843 else |
|
2844 { |
|
2845 // remains: octets 0 - 30 |
|
2846 // octet followed by the indicated number of data octets |
|
2847 iPosition++; |
|
2848 length = byte; |
|
2849 if ( ( iLength - iPosition ) < length ) |
|
2850 { |
|
2851 retVal = EFalse; |
|
2852 } |
|
2853 else |
|
2854 { |
|
2855 iPosition += length; |
|
2856 } |
|
2857 } |
|
2858 |
|
2859 return retVal; |
|
2860 } |
|
2861 |
|
2862 |
|
2863 // --------------------------------------------------------- |
|
2864 // |
|
2865 // --------------------------------------------------------- |
|
2866 // |
|
2867 TBool CMmsDecode::CheckUintvarLength() |
|
2868 { |
|
2869 TBool retVal = ETrue; // optimistic |
|
2870 TUint8 byte; |
|
2871 |
|
2872 if ( iPosition >= iLength ) |
|
2873 { |
|
2874 return EFalse; |
|
2875 } |
|
2876 |
|
2877 // get all bytes belonging to uintvar to see if we have them all. |
|
2878 iDecodeBuffer->Read( iPosition, &byte, 1 ); |
|
2879 while ( byte & KMms0x80 && iPosition < iLength - 1 ) |
|
2880 { |
|
2881 iPosition++; |
|
2882 iDecodeBuffer->Read(iPosition, &byte, 1); |
|
2883 } |
|
2884 iPosition++; |
|
2885 if ( byte & KMms0x80 ) |
|
2886 { |
|
2887 // if byte still has high bit set, we have not found |
|
2888 // the end of the uintvar -> there is not enough data |
|
2889 retVal = EFalse; |
|
2890 } |
|
2891 |
|
2892 return retVal; |
|
2893 } |
|
2894 |
|
2895 // --------------------------------------------------------- |
|
2896 // |
|
2897 // --------------------------------------------------------- |
|
2898 // |
|
2899 TPtrC8 CMmsDecode::GetContentTypeL() |
|
2900 { |
|
2901 |
|
2902 TUint8 byte; |
|
2903 TPtrC8 pointer = TPtrC8(); |
|
2904 |
|
2905 if ( iPosition >= iLength ) |
|
2906 { |
|
2907 iError = KErrCorrupt; |
|
2908 return pointer; |
|
2909 } |
|
2910 |
|
2911 iDecodeBuffer->Read(iPosition, &byte, 1); |
|
2912 |
|
2913 // Test if it is a well-known media type |
|
2914 if ( byte >= KMms0x80 ) |
|
2915 { |
|
2916 iPosition++; // skip the content type byte |
|
2917 byte &= KMms0x7F; // remove the short integer identifier bit |
|
2918 if ( ( byte == KMmsAssignedTextPlain ) ) |
|
2919 { |
|
2920 // The beginning of the first text/plain part is used |
|
2921 // to generate a description of the message, if |
|
2922 // no real subject is available. |
|
2923 // Save the starting point of corresponding data. |
|
2924 if ( iDataStart < iLength ) |
|
2925 { |
|
2926 iFakeSubject = iDataStart; |
|
2927 } |
|
2928 iUseForSubject = ETrue; |
|
2929 // count the number of plain text attas. |
|
2930 // We use iFakeSubject only if iPlainTexts == 1 |
|
2931 iPlainTexts++; |
|
2932 } |
|
2933 // encoded value |
|
2934 if ( byte < KNumberContentTypes ) |
|
2935 { |
|
2936 pointer.Set( KContentTypeTable[byte] ); |
|
2937 } |
|
2938 else |
|
2939 { |
|
2940 pointer.Set( KContentTypeTable[KMmsUnAssigned] ); |
|
2941 } |
|
2942 return pointer; |
|
2943 } |
|
2944 |
|
2945 // Test if it is a text string without parameters |
|
2946 // ( byte >= 128 returned already, byte is <= 127 if we get here ) |
|
2947 if ( byte >= KMms32 ) |
|
2948 { |
|
2949 // text string |
|
2950 return GetByteString(); |
|
2951 } |
|
2952 |
|
2953 // We have the worst case left: |
|
2954 // Content-General-Form = Value-length Media-Type |
|
2955 |
|
2956 TUint mediaLength = 0; |
|
2957 mediaLength = GetValueLength(); |
|
2958 TUint start = iPosition; |
|
2959 |
|
2960 if ( iPosition < iLength ) |
|
2961 { |
|
2962 pointer.Set( GetContentTypeL() ); // We call ourselves. |
|
2963 } |
|
2964 |
|
2965 // Now we should get the parameters, but we know nothing of |
|
2966 // parameters. For now we just throw them away. |
|
2967 // The handling of parameters of specific media types needs more study |
|
2968 |
|
2969 // The only parameter we care about now is charset. |
|
2970 // its coding should be well-known |
|
2971 |
|
2972 while ( iPosition < start + mediaLength && iPosition < iLength ) |
|
2973 { |
|
2974 iDecodeBuffer->Read( iPosition, &byte, 1 ); |
|
2975 if ( ( byte & KMms0x80 ) && ( ( byte & KMms0x7F ) == KWspCharset ) ) |
|
2976 { |
|
2977 iPosition++; |
|
2978 TUint32 charset; |
|
2979 charset = GetLongOrShortInteger(); |
|
2980 iMimeHeaders->SetMimeCharset( charset ); |
|
2981 // if this is the part possibly used to generate |
|
2982 // our fake subject, save the character set. |
|
2983 if ( iFakeSubject == iDataStart ) |
|
2984 { |
|
2985 iCharacterSet = charset; |
|
2986 } |
|
2987 } |
|
2988 else if ( ( byte & KMms0x80 ) && ( ( byte & KMms0x7F ) == KWspName ) ) |
|
2989 { |
|
2990 iPosition++; |
|
2991 // Get name parameter to be suggestion of filename |
|
2992 iMimeHeaders->ContentTypeParams().AppendL( KWspNameString ); |
|
2993 iMimeHeaders->ContentTypeParams().AppendL( GetByteString() ); |
|
2994 } |
|
2995 else if ( ( byte & KMms0x80 ) && ( ( byte & KMms0x7F ) == KWspQValue ) ) |
|
2996 { |
|
2997 iPosition++; |
|
2998 // value encoded as Uintvar, must skip differently than others. |
|
2999 GetUintvar(); |
|
3000 } |
|
3001 else |
|
3002 { |
|
3003 if ( byte >= KMms0x20 && byte <= KMms0x7F ) |
|
3004 { |
|
3005 // text string, save as content type parameter |
|
3006 // If we don have a pair of two text strings, the message is illegal |
|
3007 // The code will probably leave at some point |
|
3008 iMimeHeaders->ContentTypeParams().AppendL( GetByteString() ); |
|
3009 iMimeHeaders->ContentTypeParams().AppendL( GetByteString() ); |
|
3010 } |
|
3011 else |
|
3012 { |
|
3013 // skip |
|
3014 SkipParameterName(); |
|
3015 SkipFieldValue(); |
|
3016 } |
|
3017 } |
|
3018 } |
|
3019 |
|
3020 iPosition = start + mediaLength; |
|
3021 |
|
3022 return pointer; |
|
3023 |
|
3024 } |
|
3025 |
|
3026 // --------------------------------------------------------- |
|
3027 // If the content type is multipart, pointer will be positioned |
|
3028 // to the start of the multipart block (The first attachment) |
|
3029 // --------------------------------------------------------- |
|
3030 // |
|
3031 TUint8 CMmsDecode::GetMultipartContentTypeL() |
|
3032 { |
|
3033 |
|
3034 TUint8 byte; |
|
3035 #ifndef _NO_MMSS_LOGGING_ |
|
3036 TPtrC dummy; |
|
3037 #endif |
|
3038 |
|
3039 iMultipartRootType.Set( TPtrC8() ); // clear contents |
|
3040 iDecodeBuffer->Read(iPosition, &byte, 1); |
|
3041 // Test if it is a well-known media type. |
|
3042 if ( byte >= KMms0x80 ) |
|
3043 { |
|
3044 byte &= KMms0x7F; // remove the short integer identifier bit |
|
3045 // Test if it is a multipart type. |
|
3046 if ( ( byte >= KMmsAssignedApplicationVndWapMultipart && |
|
3047 byte <= KMmsAssignedApplicationVndWapMultipartAlternative ) || |
|
3048 ( byte == KMmsAssignedApplicationVndWapMultipartRelated ) ) |
|
3049 { |
|
3050 iPosition++; // skip the content type byte |
|
3051 // Get number of parts in multipart |
|
3052 iNumberOfAttachments = GetUintvar(); |
|
3053 } |
|
3054 else |
|
3055 { |
|
3056 byte = 0; |
|
3057 iNumberOfAttachments = 1; |
|
3058 } |
|
3059 // No more data in this header. |
|
3060 // For example multipart/mixed has no parameters |
|
3061 return byte; |
|
3062 } |
|
3063 |
|
3064 // if we get here byte is <= 127 |
|
3065 if ( byte >= KMms32 ) |
|
3066 { |
|
3067 // text string, we don't even try to analyze it. |
|
3068 // Nobody should send a well-known media type as a text string, |
|
3069 // and if it is not a well-known type, we don't know what |
|
3070 // to do with it, it will be treated as a monoblock |
|
3071 byte = 0; |
|
3072 iNumberOfAttachments = 1; |
|
3073 return byte; |
|
3074 } |
|
3075 |
|
3076 // The most complicated case: Content-General Form |
|
3077 // Content-General-Form = Value-length Media-Type |
|
3078 |
|
3079 // we save the position in case this is monoblock and |
|
3080 // we must keep the old position to get the content type for |
|
3081 // the attachment. |
|
3082 TUint oldPosition = iPosition; |
|
3083 |
|
3084 TUint mediaLength = 0; |
|
3085 mediaLength = GetValueLength(); |
|
3086 TUint start = iPosition; |
|
3087 byte = 0; |
|
3088 |
|
3089 if ( iPosition < iLength ) |
|
3090 { |
|
3091 iDecodeBuffer->Read(iPosition, &byte, 1); |
|
3092 } |
|
3093 else |
|
3094 { |
|
3095 iNumberOfAttachments = 0; |
|
3096 return 0; |
|
3097 } |
|
3098 |
|
3099 if ( byte >= KMms0x80 ) |
|
3100 { |
|
3101 byte &= KMms0x7F; // remove the short integer identifier bit |
|
3102 // Test if it is a multipart type. |
|
3103 if ( ( byte >= KMmsAssignedApplicationVndWapMultipart && |
|
3104 byte <= KMmsAssignedApplicationVndWapMultipartAlternative ) || |
|
3105 ( byte == KMmsAssignedApplicationVndWapMultipartRelated ) ) |
|
3106 { |
|
3107 iPosition++; // skip the content type byte |
|
3108 } |
|
3109 else |
|
3110 { |
|
3111 // Not a multipart we can handle |
|
3112 byte = 0; |
|
3113 iNumberOfAttachments = 1; |
|
3114 // point back to start of header |
|
3115 // parameters will belong to the attachment |
|
3116 iPosition = oldPosition; |
|
3117 return byte; |
|
3118 } |
|
3119 } |
|
3120 else |
|
3121 { |
|
3122 // text string, we don't even try to analyze it. |
|
3123 // Nobody should send a well-known media type as a text string, |
|
3124 // and if it is not a well-known type, we don't know what |
|
3125 // to do with it, it will be treated as a monoblock |
|
3126 TPtrC8 mediatype = GetByteString(); |
|
3127 if ( mediatype.CompareF( KMmsWapMultipartReport ) == 0 ) |
|
3128 { |
|
3129 byte = KMmsAssignedApplicationVndWapMultipartReport; |
|
3130 } |
|
3131 else |
|
3132 { |
|
3133 byte = 0; |
|
3134 iNumberOfAttachments = 1; |
|
3135 // point back to start of header |
|
3136 // parameters will belong to the attachment |
|
3137 iPosition = oldPosition; |
|
3138 return byte; |
|
3139 } |
|
3140 } |
|
3141 |
|
3142 // If we get here we have a WSP type multipart. |
|
3143 // We must still extract the parameters of the content type |
|
3144 // If we have multipart/related, we have start parameter. |
|
3145 // We must also try to extract Application-Id and Reply-To-Application-ID |
|
3146 // in case Java has added them. |
|
3147 // We don't care about the others now. |
|
3148 |
|
3149 TInt header; |
|
3150 TPtrC8 contentHeader; // parameter name in case it is a string |
|
3151 |
|
3152 while ( iPosition < start + mediaLength && iPosition < iLength ) |
|
3153 { |
|
3154 header = GetContentHeaderName( contentHeader ); |
|
3155 if ( header == KWspStart ) |
|
3156 { |
|
3157 // Now we must get the content-id of the root part |
|
3158 // and save it temporarily. We can get the actual |
|
3159 // TMsvId for the attachment only by comparing the |
|
3160 // Content-Id parameters of the attachments to the |
|
3161 // saved root-id. |
|
3162 TPtrC8 pointer = GetByteString(); |
|
3163 if ( pointer.Find( KMmsLeftAngle ) == 0 && |
|
3164 pointer.Find( KMmsRightAngle ) == pointer.Length() - 1 ) |
|
3165 { |
|
3166 // remove angle brackets from cid, 2 characters removed |
|
3167 pointer.Set( pointer.Mid( 1, pointer.Length() - KMms2 ) ); |
|
3168 } |
|
3169 delete iRootContentIdBuffer; |
|
3170 iRootContentIdBuffer = NULL; |
|
3171 iRootContentIdBuffer = HBufC8::NewL( pointer.Length() ); |
|
3172 iRootContentIdBuffer->Des().Copy( pointer ); |
|
3173 iRootContentId.Set( iRootContentIdBuffer->Des() ); |
|
3174 } |
|
3175 else if ( header == KWspQValue ) |
|
3176 { |
|
3177 // value encoded as Uintvar, must skip differently than others. |
|
3178 GetUintvar(); |
|
3179 } |
|
3180 else if ( header == KWspRelatedType ) |
|
3181 { |
|
3182 // get content type |
|
3183 iMultipartRootType.Set( GetContentTypeL() ); |
|
3184 } |
|
3185 else if ( header == KMmsTextHeader ) |
|
3186 { |
|
3187 // see if this is Java application id |
|
3188 if ( contentHeader.CompareF( KMmsJavaApplicationId ) == 0 ) |
|
3189 { |
|
3190 DecodeApplicationIdL(); |
|
3191 } |
|
3192 else if ( contentHeader.CompareF( KMmsJavaReplyApplicationId ) == 0 ) |
|
3193 { |
|
3194 DecodeReplyApplicationIdL(); |
|
3195 } |
|
3196 else |
|
3197 { |
|
3198 // something we don't handle |
|
3199 #ifndef _NO_MMSS_LOGGING_ |
|
3200 HBufC16* buffer = NULL; |
|
3201 buffer = HBufC16::NewLC( contentHeader.Length() ); |
|
3202 buffer->Des().Copy( contentHeader ); |
|
3203 // we cannot log indefinitely long strings. |
|
3204 // We get this long strings only if the message is corrupted. |
|
3205 dummy.Set( buffer->Des().Left( KMmsMaxLogStringLength ) ); |
|
3206 TMmsLogger::Log( _L("- Text header: %S"), &dummy ); |
|
3207 CleanupStack::PopAndDestroy( buffer ); |
|
3208 buffer = NULL; |
|
3209 #endif |
|
3210 SkipFieldValue(); |
|
3211 } |
|
3212 } |
|
3213 else |
|
3214 { |
|
3215 // skip |
|
3216 // If the caller has messed things up and sent "start" |
|
3217 // as a text string, we will miss it... |
|
3218 // GetContentHeaderName always skips the header name. |
|
3219 // if header < 0, the field has already been skipped |
|
3220 if ( header >= 0 ) |
|
3221 { |
|
3222 SkipFieldValue(); |
|
3223 } |
|
3224 } |
|
3225 } |
|
3226 |
|
3227 iPosition = start + mediaLength; |
|
3228 iNumberOfAttachments = GetUintvar(); |
|
3229 |
|
3230 return byte; |
|
3231 } |
|
3232 |
|
3233 // --------------------------------------------------------- |
|
3234 // |
|
3235 // --------------------------------------------------------- |
|
3236 // |
|
3237 void CMmsDecode::GetAttachmentContentTypeL() |
|
3238 { |
|
3239 TPtrC8 byteString; |
|
3240 #ifndef _NO_MMSS_LOGGING_ |
|
3241 HBufC16* buffer = NULL; |
|
3242 TPtrC dummy; |
|
3243 #endif |
|
3244 |
|
3245 // get content type |
|
3246 byteString.Set( GetContentTypeL() ); |
|
3247 TInt semicolonPosition = 0; |
|
3248 TInt position = 0; |
|
3249 semicolonPosition = byteString.FindF( KSemicolon8 ); |
|
3250 // check if this content type has been sent to us as a string containing |
|
3251 // parameters |
|
3252 if ( semicolonPosition != KErrNotFound && semicolonPosition != 0 ) |
|
3253 { |
|
3254 TInt endString = ( byteString.Left( semicolonPosition ).FindF( KSpace8 ) ); |
|
3255 if ( endString == KErrNotFound ) |
|
3256 { |
|
3257 endString = semicolonPosition; |
|
3258 } |
|
3259 // First part of string is actual content-type header, |
|
3260 // trailing blanks removed. |
|
3261 // If the string was total garbage like "type huh;hei=hui", |
|
3262 // the result will be wrong, but that cannot be helped if the input |
|
3263 // is not legal. |
|
3264 // The following should be OK |
|
3265 // "application/type ;param1=value1 |
|
3266 TPtrC8 contentType = byteString.Left( endString ); |
|
3267 position = contentType.Find( KMmsSlash8 ); |
|
3268 if ( position <= 0 || position == contentType.Length() ) |
|
3269 { |
|
3270 // weird string - no subtype, keep as is |
|
3271 iMimeHeaders->SetContentTypeL( contentType ); |
|
3272 } |
|
3273 else |
|
3274 { |
|
3275 iMimeHeaders->SetContentTypeL( contentType.Left( position ) ); |
|
3276 iMimeHeaders->SetContentSubTypeL( contentType.Mid( position + 1 ) ); |
|
3277 } |
|
3278 // get the rest of the stuff as parameters |
|
3279 ExtractContentTypeParametersL( byteString.Mid( semicolonPosition + 1 ) ); |
|
3280 } |
|
3281 else |
|
3282 { |
|
3283 // If first character is semicolon, the content type is garbage anyway, |
|
3284 // and we keep it "as is" |
|
3285 position = byteString.Find( KMmsSlash8 ); |
|
3286 if ( position <= 0 || position == byteString.Length() ) |
|
3287 { |
|
3288 // weird string - no subtype, keep as is |
|
3289 iMimeHeaders->SetContentTypeL( byteString ); |
|
3290 } |
|
3291 else |
|
3292 { |
|
3293 iMimeHeaders->SetContentTypeL( byteString.Left( position ) ); |
|
3294 iMimeHeaders->SetContentSubTypeL( byteString.Mid( position + 1 ) ); |
|
3295 } |
|
3296 } |
|
3297 |
|
3298 // if attachment subtype is "smil" or "amr", increase respective counter. |
|
3299 |
|
3300 |
|
3301 if ( iMimeHeaders->ContentSubType().CompareF( KMmsSmilSubtype ) == 0 ) |
|
3302 { |
|
3303 iSmilCount++; |
|
3304 } |
|
3305 else if ( iMimeHeaders->ContentType().CompareF( KMmsAudioType ) == 0 ) |
|
3306 { |
|
3307 if ( iMimeHeaders->ContentSubType().CompareF( KMmsAudioSubtype ) == 0 ) |
|
3308 { |
|
3309 iAudioCount++; |
|
3310 } |
|
3311 else if ( iMimeHeaders->ContentSubType().CompareF( KMmsAudioSubtype2 ) == 0 ) |
|
3312 { |
|
3313 // Change the subtype because the x-amr is not supported |
|
3314 iMimeHeaders->SetContentSubTypeL( KMmsAudioSubtype ); |
|
3315 iAudioCount++; |
|
3316 } |
|
3317 else |
|
3318 { |
|
3319 // do nothing - keep LINT happy |
|
3320 } |
|
3321 } |
|
3322 else |
|
3323 { |
|
3324 // do nothing - keep LINT happy |
|
3325 } |
|
3326 |
|
3327 #ifndef _NO_MMSS_LOGGING_ |
|
3328 if ( semicolonPosition > 0 ) |
|
3329 { |
|
3330 byteString.Set( byteString.Left( semicolonPosition ) ); |
|
3331 } |
|
3332 buffer = HBufC16::NewLC( byteString.Length() ); |
|
3333 buffer->Des().Copy( byteString ); |
|
3334 // we cannot log indefinitely long strings. |
|
3335 // We get this long strings only if the message is corrupted. |
|
3336 dummy.Set( buffer->Des().Left( KMmsMaxLogStringLength ) ); |
|
3337 TMmsLogger::Log( _L("- Content Type: %S"), &dummy ); |
|
3338 CleanupStack::PopAndDestroy( buffer ); |
|
3339 if ( iMimeHeaders->MimeCharset() != 0 ) |
|
3340 { |
|
3341 TMmsLogger::Log( _L("- Character set: %d"), iMimeHeaders->MimeCharset() ); |
|
3342 } |
|
3343 if ( iMimeHeaders->ContentTypeParams().MdcaCount() > 0 ) |
|
3344 { |
|
3345 TInt i; |
|
3346 // we increment by 2 because every other value is parameter name |
|
3347 // and every othe one the value |
|
3348 for ( i = 0; i < iMimeHeaders->ContentTypeParams().MdcaCount(); i += KMms2 ) |
|
3349 { |
|
3350 HBufC16* buffer2 = NULL; |
|
3351 buffer = HBufC16::NewLC( |
|
3352 iMimeHeaders->ContentTypeParams().MdcaPoint( i ).Length() ); |
|
3353 buffer->Des().Copy( iMimeHeaders->ContentTypeParams().MdcaPoint( i ) ); |
|
3354 // we cannot log indefinitely long strings. |
|
3355 // We get this long strings only if the message is corrupted. |
|
3356 dummy.Set( buffer->Des().Left( KMmsMaxLogStringLength ) ); |
|
3357 if ( i + 1 < iMimeHeaders->ContentTypeParams().MdcaCount() ) |
|
3358 { |
|
3359 buffer2 = HBufC16::NewLC( |
|
3360 iMimeHeaders->ContentTypeParams().MdcaPoint( i + 1 ).Length() ); |
|
3361 TPtrC dummy2; |
|
3362 buffer2->Des().Copy( iMimeHeaders->ContentTypeParams().MdcaPoint( i + 1 ) ); |
|
3363 dummy2.Set( buffer2->Des().Left( KMmsMaxLogStringLength ) ); |
|
3364 TMmsLogger::Log( _L("- %S: %S"), &dummy, &dummy2 ); |
|
3365 CleanupStack::PopAndDestroy( buffer2 ); |
|
3366 } |
|
3367 else |
|
3368 { |
|
3369 TMmsLogger::Log( _L("- %S"), &dummy ); |
|
3370 } |
|
3371 CleanupStack::PopAndDestroy( buffer ); |
|
3372 } |
|
3373 } |
|
3374 #endif |
|
3375 |
|
3376 } |
|
3377 |
|
3378 // --------------------------------------------------------- |
|
3379 // |
|
3380 // --------------------------------------------------------- |
|
3381 // |
|
3382 void CMmsDecode::DecodeOneContentHeaderL() |
|
3383 { |
|
3384 |
|
3385 TInt header; |
|
3386 HBufC16* buffer = NULL; |
|
3387 TUint8 byte = 0; |
|
3388 TPtrC8 contentHeader; // content header in case it is a string |
|
3389 #ifndef _NO_MMSS_LOGGING_ |
|
3390 TPtrC dummy; |
|
3391 #endif |
|
3392 header = GetContentHeaderName( contentHeader ); |
|
3393 |
|
3394 if ( header < 0 ) |
|
3395 { |
|
3396 return; // skip unknown |
|
3397 } |
|
3398 |
|
3399 // Get the corresponding value |
|
3400 |
|
3401 switch ( header ) |
|
3402 { |
|
3403 case KWspContentLocation: |
|
3404 { |
|
3405 // I hope this is a simple text string. we cannot handle |
|
3406 // different character sets in this context. |
|
3407 |
|
3408 buffer = GetSimpleTextStringL(); // we might try to convert from utf8 to unicode |
|
3409 CleanupStack::PushL( buffer ); |
|
3410 iMimeHeaders->SetContentLocationL( buffer->Des() ); |
|
3411 CleanupStack::PopAndDestroy( buffer ); |
|
3412 buffer = NULL; |
|
3413 |
|
3414 #ifndef _NO_MMSS_LOGGING_ |
|
3415 buffer = HBufC16::NewLC( iMimeHeaders->ContentLocation().Length() ); |
|
3416 buffer->Des().Copy( iMimeHeaders->ContentLocation() ); |
|
3417 // we cannot log indefinitely long strings. |
|
3418 // We get this long strings only if the message is corrupted. |
|
3419 dummy.Set( buffer->Des().Left( KMmsMaxLogStringLength ) ); |
|
3420 TMmsLogger::Log( _L("- Content location: %S"), &dummy ); |
|
3421 CleanupStack::PopAndDestroy( buffer ); |
|
3422 #endif |
|
3423 break; |
|
3424 } |
|
3425 case KWspContentId: |
|
3426 { |
|
3427 TPtrC8 pointer = GetByteString(); |
|
3428 if ( pointer.Find( KMmsLeftAngle ) == 0 && |
|
3429 pointer.Find( KMmsRightAngle ) == pointer.Length() - 1 ) |
|
3430 { |
|
3431 // remove angle brackets from cid, 2 characters removed |
|
3432 pointer.Set( pointer.Mid( 1, pointer.Length() - KMms2 ) ); |
|
3433 } |
|
3434 iMimeHeaders->SetContentIdL( pointer ); |
|
3435 if ( iAttaNumber == 1 && |
|
3436 iMultipartType == KMmsAssignedApplicationVndWapMultipartRelated && |
|
3437 iRootContentId.Length() == 0 ) |
|
3438 { |
|
3439 iRootContentId.Set( pointer ); |
|
3440 } |
|
3441 #ifndef _NO_MMSS_LOGGING_ |
|
3442 buffer = HBufC16::NewLC( iMimeHeaders->ContentId().Length() ); |
|
3443 buffer->Des().Copy( iMimeHeaders->ContentId() ); |
|
3444 // we cannot log indefinitely long strings. |
|
3445 // We get this long strings only if the message is corrupted. |
|
3446 dummy.Set( buffer->Des().Left( KMmsMaxLogStringLength ) ); |
|
3447 TMmsLogger::Log( _L("- Content Id: %S"), &dummy ); |
|
3448 CleanupStack::PopAndDestroy( buffer ); |
|
3449 #endif |
|
3450 break; |
|
3451 } |
|
3452 case KWspContentDisposition: |
|
3453 { |
|
3454 TUint length; |
|
3455 length = GetValueLength(); |
|
3456 TUint currentPosition = iPosition; |
|
3457 |
|
3458 if ( iPosition < iLength ) |
|
3459 { |
|
3460 iDecodeBuffer->Read(iPosition, &byte, 1); |
|
3461 } |
|
3462 if ( byte >= KMms0x80 ) |
|
3463 { |
|
3464 // well known header |
|
3465 iPosition++; |
|
3466 byte &= KMms0x7F; |
|
3467 if ( byte == KWspAttachment ) |
|
3468 { |
|
3469 iMimeHeaders->SetContentDispositionL( KWspAttachmentString ); |
|
3470 } |
|
3471 else if ( byte == KWspInline ) |
|
3472 { |
|
3473 iMimeHeaders->SetContentDispositionL( KWspInlineString ); |
|
3474 } |
|
3475 // never mind others - might be form-data or something unknown |
|
3476 else |
|
3477 { |
|
3478 // do nothing - keep LINT happy |
|
3479 } |
|
3480 } |
|
3481 else |
|
3482 { |
|
3483 // string - use as is |
|
3484 TPtrC8 pointer = GetByteString(); |
|
3485 iMimeHeaders->SetContentDispositionL( pointer ); |
|
3486 } |
|
3487 #ifndef _NO_MMSS_LOGGING_ |
|
3488 buffer = HBufC16::NewLC( iMimeHeaders->ContentDisposition().Length() ); |
|
3489 buffer->Des().Copy( iMimeHeaders->ContentDisposition() ); |
|
3490 // we cannot log indefinitely long strings. |
|
3491 // We get this long strings only if the message is corrupted. |
|
3492 dummy.Set( buffer->Des().Left( KMmsMaxLogStringLength ) ); |
|
3493 TMmsLogger::Log( _L("- Content Disposition: %S"), &dummy ); |
|
3494 CleanupStack::PopAndDestroy( buffer ); |
|
3495 #endif |
|
3496 // now try to see if we have filename parameter |
|
3497 while ( iPosition < ( currentPosition + length ) && iPosition < iLength ) |
|
3498 { |
|
3499 byte = 0; // clean out old data |
|
3500 iDecodeBuffer->Read(iPosition, &byte, 1); |
|
3501 |
|
3502 if ( byte >= KMms0x80 ) |
|
3503 { |
|
3504 // well known parameter |
|
3505 iPosition++; |
|
3506 byte &= KMms0x7F; |
|
3507 if ( byte == KWspFileName ) |
|
3508 { |
|
3509 // this might contain some strange encodings (against specs.) |
|
3510 // should be checked |
|
3511 TPtrC8 pointer = GetByteString(); |
|
3512 iMimeHeaders->ContentDispositionParams().AppendL( KWspFilenameString ); |
|
3513 iMimeHeaders->ContentDispositionParams().AppendL( pointer ); |
|
3514 #ifndef _NO_MMSS_LOGGING_ |
|
3515 buffer = HBufC16::NewLC( pointer.Length() ); |
|
3516 buffer->Des().Copy( pointer ); |
|
3517 // we cannot log indefinitely long strings. |
|
3518 // We get this long strings only if the message is corrupted. |
|
3519 dummy.Set( buffer->Des().Left( KMmsMaxLogStringLength ) ); |
|
3520 TMmsLogger::Log( _L("- filename: %S"), &dummy ); |
|
3521 CleanupStack::PopAndDestroy( buffer ); |
|
3522 #endif |
|
3523 } |
|
3524 else |
|
3525 { |
|
3526 SkipFieldValue(); |
|
3527 } |
|
3528 } |
|
3529 else |
|
3530 { |
|
3531 // if "filename" has been sent as string, we skip it |
|
3532 if ( byte >= KMms0x20 && byte <= KMms0x7F ) |
|
3533 { |
|
3534 // text string, save as content type parameter |
|
3535 // If we don have a pair of two text strings, the message is illegal |
|
3536 // The code will probably leave at some point |
|
3537 iMimeHeaders->ContentDispositionParams().AppendL( GetByteString() ); |
|
3538 iMimeHeaders->ContentDispositionParams().AppendL( GetByteString() ); |
|
3539 } |
|
3540 else |
|
3541 { |
|
3542 // skip |
|
3543 SkipParameterName(); |
|
3544 SkipFieldValue(); |
|
3545 } |
|
3546 } |
|
3547 } |
|
3548 |
|
3549 iPosition = currentPosition + length; |
|
3550 if ( iPosition >= iLength ) |
|
3551 { |
|
3552 iError = KErrCorrupt; |
|
3553 } |
|
3554 break; |
|
3555 } |
|
3556 case KMmsTextHeader: |
|
3557 { |
|
3558 // contentHeader points to the textual header |
|
3559 #ifndef _NO_MMSS_LOGGING_ |
|
3560 // we don't leave just for logging |
|
3561 TInt error = KErrNone; |
|
3562 TRAP( error, |
|
3563 { |
|
3564 buffer = NULL; |
|
3565 buffer = HBufC16::NewLC( contentHeader.Length() ); |
|
3566 buffer->Des().Copy( contentHeader ); |
|
3567 // we cannot log indefinitely long strings. |
|
3568 // We get this long strings only if the message is corrupted. |
|
3569 dummy.Set( buffer->Des().Left( KMmsMaxLogStringLength ) ); |
|
3570 TMmsLogger::Log( _L("- Textual content header: %S"), &dummy ); |
|
3571 CleanupStack::PopAndDestroy( buffer ); |
|
3572 };); |
|
3573 if ( error != KErrNone ) |
|
3574 { |
|
3575 TMmsLogger::Log( _L("- Decode left when logging content header, error : %d"), |
|
3576 error ); |
|
3577 } |
|
3578 #endif |
|
3579 if ( contentHeader.FindF( KMmsExtension ) == 0 ) |
|
3580 { |
|
3581 // extension header, store to mime headers, get corresponding parameter |
|
3582 // and store to MIME headers |
|
3583 TPtrC8 pointer = GetByteString(); |
|
3584 iMimeHeaders->XTypeParams().AppendL( contentHeader ); // header name |
|
3585 iMimeHeaders->XTypeParams().AppendL( pointer ); // header value |
|
3586 #ifndef _NO_MMSS_LOGGING_ |
|
3587 buffer = HBufC16::NewLC( pointer.Length() ); |
|
3588 buffer->Des().Copy( pointer ); |
|
3589 // we cannot log indefinitely long strings. |
|
3590 // We get this long strings only if the message is corrupted. |
|
3591 dummy.Set( buffer->Des().Left( KMmsMaxLogStringLength ) ); |
|
3592 TMmsLogger::Log( _L("- extension header value: %S"), &dummy ); |
|
3593 CleanupStack::PopAndDestroy( buffer ); |
|
3594 #endif |
|
3595 } |
|
3596 else |
|
3597 { |
|
3598 SkipFieldValue(); |
|
3599 } |
|
3600 |
|
3601 break; |
|
3602 } |
|
3603 default: |
|
3604 #ifndef _NO_MMSS_LOGGING_ |
|
3605 TMmsLogger::Log( _L("- Unknown content header: 0x%02X"), header ); |
|
3606 #endif |
|
3607 SkipFieldValue(); |
|
3608 break; |
|
3609 } |
|
3610 |
|
3611 } |
|
3612 |
|
3613 // --------------------------------------------------------- |
|
3614 // |
|
3615 // --------------------------------------------------------- |
|
3616 // |
|
3617 TInt CMmsDecode::GetContentHeaderName( TPtrC8& aTextHeader ) |
|
3618 { |
|
3619 |
|
3620 TInt header; |
|
3621 header = -1; // unknown |
|
3622 aTextHeader.Set( TPtrC8() ); // empty string |
|
3623 |
|
3624 TUint8 byte; |
|
3625 |
|
3626 if ( iPosition < iLength ) |
|
3627 { |
|
3628 iDecodeBuffer->Read(iPosition, &byte, 1); |
|
3629 } |
|
3630 else |
|
3631 { |
|
3632 return header; |
|
3633 } |
|
3634 |
|
3635 // byte cannot be bigger than 255. No need to test upper limit |
|
3636 if ( byte >= KMms0x80 ) |
|
3637 { |
|
3638 // well known header, advance pointer and remove high bit |
|
3639 iPosition++; |
|
3640 header = (byte & KMms0x7F); |
|
3641 return header; |
|
3642 } |
|
3643 else |
|
3644 { |
|
3645 TPtrC8 pointer = GetByteString(); |
|
3646 aTextHeader.Set( pointer ); |
|
3647 header = KMmsTextHeader; // this will cover X-headers |
|
3648 if ( pointer.CompareF( KWspContentIdString ) == 0 ) |
|
3649 { |
|
3650 header = KWspContentId; |
|
3651 } |
|
3652 } |
|
3653 |
|
3654 // To handle X-headers and Java apllication id parameters, |
|
3655 // the text string is offered to caller. |
|
3656 // The header has been set to KMmsTextHeader to indicate that the field value |
|
3657 // is still available. |
|
3658 |
|
3659 if ( ( header < 0 ) && ( iPosition < iLength ) ) |
|
3660 { |
|
3661 SkipFieldValue(); |
|
3662 } |
|
3663 |
|
3664 return header; |
|
3665 } |
|
3666 |
|
3667 // --------------------------------------------------------- |
|
3668 // |
|
3669 // --------------------------------------------------------- |
|
3670 // |
|
3671 // |
|
3672 void CMmsDecode::DecodeOneAttachmentL() |
|
3673 { |
|
3674 |
|
3675 DecodeAttachmentHeadersL(); |
|
3676 |
|
3677 // We must be able to handle an empty message without panic |
|
3678 if ( iCurrentAttaLength == 0 ) |
|
3679 { |
|
3680 // if attachment length == 0, do not create an attachment |
|
3681 return; |
|
3682 } |
|
3683 |
|
3684 TMsvAttachmentId attachmentId = 0; |
|
3685 TInt32 drmFlags = 0; |
|
3686 TPtrC8 attaData; |
|
3687 if ( iPosition >= iLength ) |
|
3688 { |
|
3689 iCurrentAttaLength = 0; |
|
3690 } |
|
3691 attaData.Set( iDecodeBuffer->Ptr( iPosition ).Ptr(), iCurrentAttaLength ); |
|
3692 |
|
3693 TInt size = 0; |
|
3694 |
|
3695 #ifndef _NO_MMSS_LOGGING_ |
|
3696 TMmsLogger::Log( _L("- Attachment creation starts %S"), &iParse.FullName() ); |
|
3697 #endif |
|
3698 if ( iError == KErrNone ) |
|
3699 { |
|
3700 iError = iEntryWrapper->CreateFileAttachmentL( |
|
3701 *iStore, |
|
3702 iParse.NameAndExt(), |
|
3703 attaData, |
|
3704 *iMimeHeaders, |
|
3705 attachmentId, |
|
3706 size, |
|
3707 drmFlags); |
|
3708 } |
|
3709 |
|
3710 #ifndef _NO_MMSS_LOGGING_ |
|
3711 if ( iError == KErrNone ) |
|
3712 { |
|
3713 TRAP_IGNORE({ |
|
3714 MMsvAttachmentManager& attaMan = iStore->AttachmentManagerL(); |
|
3715 CMsvAttachment* attaInfo = attaMan.GetAttachmentInfoL( attachmentId ); |
|
3716 TMmsLogger::Log( _L("- Attachment created %S"), &attaInfo->FilePath() ); |
|
3717 delete attaInfo; |
|
3718 attaInfo = NULL; |
|
3719 }); |
|
3720 } |
|
3721 #endif |
|
3722 |
|
3723 iDRMFlags |= drmFlags; |
|
3724 |
|
3725 if ( iError == KMmsErrorRemoveDRM ) |
|
3726 { |
|
3727 // The attachment was not saved, but we can continue |
|
3728 iError = KErrNone; |
|
3729 #ifndef _NO_MMSS_LOGGING_ |
|
3730 TMmsLogger::Log( _L("- DRM attachment removed") ); |
|
3731 #endif |
|
3732 } |
|
3733 else if ( iError == KErrNone ) |
|
3734 { |
|
3735 if ( ( iMultipartType == KMmsAssignedApplicationVndWapMultipartRelated ) && |
|
3736 ( iRootContentId.Length() > 0 ) && |
|
3737 ( iRootAttachmentId == 0 ) ) |
|
3738 { |
|
3739 // check if content-id's match |
|
3740 if ( iRootContentId.Compare( iMimeHeaders->ContentId() ) == 0 ) |
|
3741 { |
|
3742 iRootAttachmentId = attachmentId; |
|
3743 } |
|
3744 } |
|
3745 iTotalSize += size; |
|
3746 } |
|
3747 else |
|
3748 { |
|
3749 // do nothing - keep LINT happy |
|
3750 } |
|
3751 |
|
3752 if ( iDataStart == iFakeSubject ) |
|
3753 { |
|
3754 iTextPlainLength = iCurrentAttaLength; |
|
3755 } |
|
3756 |
|
3757 // if doing dumping, also dump the smil part to a file |
|
3758 // Note: this modifies iFileName, but our original file was closed already |
|
3759 |
|
3760 #ifndef _NO_MMSS_LOGGING_ |
|
3761 DumpSmil( iCurrentAttaLength ); |
|
3762 #endif |
|
3763 |
|
3764 iPosition = iNextStart; |
|
3765 |
|
3766 if ( iMultipartType == KMmsAssignedApplicationVndWapMultipartReport ) |
|
3767 { |
|
3768 // If we have a multipart/report, we ignore the rest of attachments |
|
3769 iNumberOfAttachments = 1; |
|
3770 iPosition = iLength; |
|
3771 } |
|
3772 |
|
3773 CompleteSelf( iError ); |
|
3774 |
|
3775 } |
|
3776 |
|
3777 // --------------------------------------------------------- |
|
3778 // |
|
3779 // --------------------------------------------------------- |
|
3780 // |
|
3781 void CMmsDecode::DecodeAttachmentHeadersL() |
|
3782 { |
|
3783 TUint32 headersLength = 0; |
|
3784 iCurrentAttaLength = 0; |
|
3785 iAttaNumber++; // starts fron zero, is 1 after first increment |
|
3786 TInt error = KErrNone; // temporary error |
|
3787 #ifndef _NO_MMSS_LOGGING_ |
|
3788 TPtrC dummy; |
|
3789 #endif |
|
3790 |
|
3791 #ifndef _NO_MMSS_LOGGING_ |
|
3792 TMmsLogger::Log( _L("- Attachment #%d"), iAttaNumber ); |
|
3793 #endif |
|
3794 // we may have a multipart structure or a single monoblock data body |
|
3795 // we handle both here. |
|
3796 // The momoblock structure probably won't work correctly in chunked mode |
|
3797 // but it is not supposed to be supported anyway. |
|
3798 |
|
3799 // Before this funtion is called in the chunked mode we have checked |
|
3800 // that we have enough data to cover all the headers (the length of the |
|
3801 // headers is given in the beginning) |
|
3802 |
|
3803 if ( iMultipartType != 0 ) |
|
3804 { |
|
3805 if ( iPosition < iLength ) |
|
3806 { |
|
3807 headersLength = GetUintvar(); |
|
3808 } |
|
3809 else |
|
3810 { |
|
3811 iError = KErrCorrupt; |
|
3812 if ( iDecodingStage == EMmsNotApplicable ) |
|
3813 { |
|
3814 CompleteSelf( iError ); |
|
3815 } |
|
3816 return; |
|
3817 } |
|
3818 |
|
3819 if ( iPosition < iLength ) |
|
3820 { |
|
3821 iCurrentAttaLength = GetUintvar(); |
|
3822 } |
|
3823 else |
|
3824 { |
|
3825 iError = KErrCorrupt; |
|
3826 if ( iDecodingStage == EMmsNotApplicable ) |
|
3827 { |
|
3828 CompleteSelf( iError ); |
|
3829 } |
|
3830 return; |
|
3831 } |
|
3832 |
|
3833 // Data start can be calculated now. |
|
3834 // Also the start of next attachment. |
|
3835 |
|
3836 iDataStart = iPosition + headersLength; |
|
3837 |
|
3838 if ( iDataStart > iLength && iDecodingStage == EMmsNotApplicable ) |
|
3839 { |
|
3840 // This is an error only if we are handling all data, not chunks |
|
3841 iError = KErrCorrupt; |
|
3842 CompleteSelf( iError ); |
|
3843 return; |
|
3844 } |
|
3845 |
|
3846 if ( iDataStart + iCurrentAttaLength > iLength && iDecodingStage == EMmsNotApplicable ) |
|
3847 { |
|
3848 // if we are doing chunked decoding there may not be enough data in our buffer |
|
3849 iCurrentAttaLength = iLength - iDataStart; |
|
3850 } |
|
3851 iNextStart = iDataStart + iCurrentAttaLength; |
|
3852 } |
|
3853 else |
|
3854 // monoblock - this probably won't work in chunked mode |
|
3855 // but then MMS engine is not supposed to support this kind of structure anyway |
|
3856 // The data should always be wrapped in multipart structure even if there is |
|
3857 // only one part. |
|
3858 // If the message is so small that everything fits into the buffer at one go, |
|
3859 // then this will work in chunked mode, too. |
|
3860 { |
|
3861 // save old position |
|
3862 TUint oldPosition = iPosition; |
|
3863 headersLength = GetValueLength(); |
|
3864 iDataStart = iPosition + headersLength; |
|
3865 iCurrentAttaLength = iLength - iDataStart; |
|
3866 iNextStart = iDataStart + iCurrentAttaLength; |
|
3867 // Header's length is part of content type header. |
|
3868 // we cannot remove it, or we cannot interpret the |
|
3869 // content type header correctly. |
|
3870 iPosition = oldPosition; |
|
3871 } |
|
3872 |
|
3873 #ifndef _NO_MMSS_LOGGING_ |
|
3874 TMmsLogger::Log( _L("- Headers length: %d"), headersLength ); |
|
3875 TMmsLogger::Log( _L("- Data length: %d"), iCurrentAttaLength ); |
|
3876 #endif |
|
3877 |
|
3878 |
|
3879 // don't touch iMmsHeaders, they may still be needed. |
|
3880 // Just reset mime headers, attachments don't need anything else. |
|
3881 iMimeHeaders->Reset(); |
|
3882 |
|
3883 // We must be able to handle an empty message without panic |
|
3884 if ( iCurrentAttaLength == 0 ) |
|
3885 { |
|
3886 // empty attachment, don't create entry |
|
3887 iPosition = iNextStart; |
|
3888 if ( iDecodingStage == EMmsNotApplicable ) |
|
3889 { |
|
3890 // chunked mode is not an active object |
|
3891 CompleteSelf( iError ); |
|
3892 } |
|
3893 return; |
|
3894 } |
|
3895 |
|
3896 // attachment creation cannot be done before we have all the headers |
|
3897 |
|
3898 GetAttachmentContentTypeL(); |
|
3899 |
|
3900 // Now we must analyze the content-headers |
|
3901 // We only try to find Content-Location to get the filename |
|
3902 // We should also save the Content-ID:s in case the SMIL part uses them |
|
3903 // We also need to check if the Content-ID of some part matches |
|
3904 // the content id given as the start parameter for multipart/related type |
|
3905 // Some terminals put filename as parameter of content-disposition, |
|
3906 // so that should be checked, too. |
|
3907 |
|
3908 while ( iPosition < iDataStart ) |
|
3909 { |
|
3910 DecodeOneContentHeaderL(); |
|
3911 } |
|
3912 |
|
3913 if ( ( iMultipartType == KMmsAssignedApplicationVndWapMultipartRelated ) && |
|
3914 ( iRootContentId.Length() == 0 ) && iAttaNumber == 1 ) |
|
3915 { |
|
3916 // First part must be root if start parameter not defined |
|
3917 if ( iMimeHeaders->ContentId().Length() == 0 ) |
|
3918 { |
|
3919 TTime now; |
|
3920 now.UniversalTime(); |
|
3921 TInt random; |
|
3922 TInt64 seed = now.Int64(); |
|
3923 // no problem with conversions - just creating a magic number for content id |
|
3924 random = Math::Rand( seed ); |
|
3925 iTempBuffer.Des().Num( random ); |
|
3926 iMimeHeaders->SetContentIdL( iTempBuffer.Des() ); |
|
3927 iRootContentId.Set( iTempBuffer.Des() ); |
|
3928 } |
|
3929 } |
|
3930 |
|
3931 // Now we have a root content id if the message is multipart/related. |
|
3932 // we can set up the id for the root part after the attachment has been |
|
3933 // created |
|
3934 |
|
3935 iPosition = iDataStart; // binary data starts here |
|
3936 |
|
3937 // Now we must try to generate a filename for the attachment. |
|
3938 // A name must be generated before the actual attachment is saved |
|
3939 |
|
3940 TPtrC temp = TPtrC(); |
|
3941 TPtrC ptr; |
|
3942 |
|
3943 TBool isContentLocationFileName = EFalse; |
|
3944 TPtrC8 dummy8; |
|
3945 |
|
3946 // Try name parameter of content location first |
|
3947 if ( !isContentLocationFileName ) |
|
3948 { |
|
3949 dummy8.Set( iMimeHeaders->GetContentTypeValue( KWspNameString ) ); |
|
3950 isContentLocationFileName = MakeFilenameL( dummy8, iParse, TPtrC() ); |
|
3951 } |
|
3952 |
|
3953 // Try filename parameter of content-disposition header next |
|
3954 TInt i; |
|
3955 // every other string is parameter, every other one is value |
|
3956 for ( i = 0; |
|
3957 i < iMimeHeaders->ContentDispositionParams().MdcaCount() && !isContentLocationFileName; |
|
3958 i += KMms2 ) |
|
3959 { |
|
3960 // Try to generate a filename from the filename parameter |
|
3961 if ( iMimeHeaders->ContentDispositionParams().MdcaPoint( i ).CompareF( |
|
3962 KWspFilenameString ) == 0 ) |
|
3963 { |
|
3964 dummy8.Set( iMimeHeaders->ContentDispositionParams().MdcaPoint( i + 1 ) ); |
|
3965 isContentLocationFileName = MakeFilenameL( dummy8, iParse, TPtrC() ); |
|
3966 } |
|
3967 } |
|
3968 |
|
3969 HBufC16* uri = NULL; |
|
3970 if ( !isContentLocationFileName && |
|
3971 iMimeHeaders->ContentLocation().Length() > 0 ) |
|
3972 { |
|
3973 // Try to generate a filename from the content location |
|
3974 error = KErrNone; |
|
3975 TRAP( error, ( uri = EscapeUtils::EscapeDecodeL( iMimeHeaders->ContentLocation() ) ) ); |
|
3976 if ( error == KErrNone ) |
|
3977 { |
|
3978 temp.Set( uri->Des().Right( KMmsMaxFileName ) ); |
|
3979 } |
|
3980 else |
|
3981 { |
|
3982 temp.Set( iMimeHeaders->ContentLocation().Right( KMmsMaxFileName ) ); |
|
3983 } |
|
3984 error = iParse.Set( TPtrC(), &temp, NULL ); |
|
3985 if ( error == KErrNone ) |
|
3986 { |
|
3987 isContentLocationFileName = iEntryWrapper->IsValidFilename( iParse.NameAndExt() ); |
|
3988 } |
|
3989 } |
|
3990 CleanupStack::PushL( uri ); |
|
3991 |
|
3992 // if content location not specified, use name parameter |
|
3993 // as content location. FIX for /// originated messages. |
|
3994 if ( iMimeHeaders->ContentLocation().Length() == 0 ) |
|
3995 { |
|
3996 dummy8.Set( iMimeHeaders->GetContentTypeValue( KWspNameString ) ); |
|
3997 // This may use some strange charset. Should be decoded. |
|
3998 // We only use it if it appears to be ascii. |
|
3999 if ( dummy8.Length() > 0 && IsStringSafe( dummy8 ) ) |
|
4000 { |
|
4001 HBufC* name = HBufC::NewL( dummy8.Length() ); |
|
4002 CleanupStack::PushL( name ); |
|
4003 name->Des().Copy( dummy8 ); |
|
4004 iMimeHeaders->SetContentLocationL( name->Des() ); |
|
4005 #ifndef _NO_MMSS_LOGGING_ |
|
4006 // we cannot log indefinitely long strings. |
|
4007 // We get this long strings only if the message is corrupted. |
|
4008 dummy.Set( name->Des().Left( KMmsMaxLogStringLength ) ); |
|
4009 TMmsLogger::Log( _L("- Content location from name parameter: %S"), &dummy ); |
|
4010 #endif |
|
4011 CleanupStack::PopAndDestroy( name ); |
|
4012 name = NULL; |
|
4013 } |
|
4014 } |
|
4015 |
|
4016 TBuf<KMms14> attaName; // max 4294967295 attas. |
|
4017 _LIT( KRelated, "att"); |
|
4018 |
|
4019 if ( !isContentLocationFileName ) |
|
4020 { |
|
4021 // We don't have content location, we must invent a filename |
|
4022 // We should try to generate a sensible extension based on content type |
|
4023 // Now we will have no extension |
|
4024 attaName.Num( iAttaNumber, EDecimal ); |
|
4025 attaName.Insert( 0, KRelated ); |
|
4026 |
|
4027 i = 0; |
|
4028 TBool matchFound = EFalse; |
|
4029 TPtrC8 matchTablePointer; |
|
4030 matchTablePointer.Set( KMmsFileExtensionMatchTable[i].tag ); |
|
4031 while ( matchTablePointer.Length() > 0 && !matchFound ) |
|
4032 { |
|
4033 if ( iMimeHeaders->ContentSubType().FindF( |
|
4034 TPtrC8( KMmsFileExtensionMatchTable[i].tag ) ) != KErrNotFound ) |
|
4035 { |
|
4036 temp.Set( KMmsFileExtensionMatchTable[i].extension ); |
|
4037 matchFound = ETrue; |
|
4038 } |
|
4039 i++; |
|
4040 matchTablePointer.Set( KMmsFileExtensionMatchTable[i].tag ); |
|
4041 } |
|
4042 ptr.Set( attaName ); |
|
4043 if ( !matchFound ) |
|
4044 { |
|
4045 // unknown type, no extension |
|
4046 iParse.Set( TPtrC(), &ptr, NULL ); |
|
4047 } |
|
4048 else |
|
4049 { |
|
4050 iParse.Set( TPtrC(), &ptr, &temp ); |
|
4051 } |
|
4052 } |
|
4053 |
|
4054 // We are through with filename, and URI may go if it ever was allocated |
|
4055 CleanupStack::PopAndDestroy( uri ); |
|
4056 |
|
4057 |
|
4058 // We have to use iParse.NameAndExt as a guess for filename |
|
4059 // we cannot call CApaApplication::GenerateFileName without a path |
|
4060 |
|
4061 // The next thing to do is to create an empty file ready to accept |
|
4062 // the attachment data. |
|
4063 |
|
4064 |
|
4065 |
|
4066 } |
|
4067 |
|
4068 // --------------------------------------------------------- |
|
4069 // |
|
4070 // --------------------------------------------------------- |
|
4071 // |
|
4072 void CMmsDecode::ExtractContentTypeParametersL( const TPtrC8& aBuffer ) |
|
4073 { |
|
4074 // we get here the parameter part of content type in the format |
|
4075 // parameter1=value1;parameter2=value2 |
|
4076 TInt start = 0; |
|
4077 TInt end = 0; |
|
4078 TInt tokenEnd = 0; |
|
4079 while ( start < aBuffer.Length() ) |
|
4080 { |
|
4081 // remove leading spaces |
|
4082 while ( start < aBuffer.Length() && aBuffer.Mid( start ).FindF( KSpace8 ) == 0 ) |
|
4083 { |
|
4084 start++; |
|
4085 } |
|
4086 if ( start >= aBuffer.Length() ) |
|
4087 { |
|
4088 return; // done, nothing left |
|
4089 } |
|
4090 // extract token |
|
4091 end = aBuffer.Mid( start ).FindF( KEquals8 ); |
|
4092 if ( end == KErrNotFound ) |
|
4093 { |
|
4094 end = aBuffer.Length(); |
|
4095 } |
|
4096 else |
|
4097 { |
|
4098 end += start; // remember the original offset |
|
4099 } |
|
4100 tokenEnd = end - 1; |
|
4101 // remove trailing spaces from token |
|
4102 while ( tokenEnd - start > start && aBuffer.Mid( start, tokenEnd - start + 1 ).FindF( KSpace8 ) == tokenEnd - start ) |
|
4103 { |
|
4104 tokenEnd--; |
|
4105 } |
|
4106 if ( aBuffer.Mid( start, tokenEnd - start + 1 ).Length() == 0 ) |
|
4107 { |
|
4108 return; // garbage, give up |
|
4109 } |
|
4110 else |
|
4111 { |
|
4112 iMimeHeaders->ContentTypeParams().AppendL( |
|
4113 aBuffer.Mid( start, tokenEnd - start + 1 ) ); |
|
4114 } |
|
4115 // extract value |
|
4116 start = end + 1; |
|
4117 if ( start >= aBuffer.Length() ) |
|
4118 { |
|
4119 iMimeHeaders->ContentTypeParams().AppendL( TPtrC8() ); |
|
4120 return; |
|
4121 } |
|
4122 // remove leading spaces |
|
4123 while ( start < aBuffer.Length() && aBuffer.Mid( start ).FindF( KSpace8 ) == 0 ) |
|
4124 { |
|
4125 start++; |
|
4126 } |
|
4127 if ( start >= aBuffer.Length() ) |
|
4128 { |
|
4129 // there was no value for the parameter - must add an empty value |
|
4130 iMimeHeaders->ContentTypeParams().AppendL( TPtrC8() ); |
|
4131 return; // done, nothing left |
|
4132 } |
|
4133 // A string or a quoted string left. |
|
4134 // If quoted string, search for end quote. |
|
4135 // If not quoted, search for next semicolon (delimiter between parameters) |
|
4136 if ( aBuffer.Mid( start ).FindF( &KMmsStringQuote, 1 ) == 0 ) |
|
4137 { |
|
4138 start++; // discard the quotes |
|
4139 end = aBuffer.Mid( start ).FindF( &KMmsStringQuote, 1 ); |
|
4140 if ( end != KErrNotFound ) |
|
4141 { |
|
4142 end += start; // remember the original offset |
|
4143 } |
|
4144 else |
|
4145 { |
|
4146 end = aBuffer.Length(); |
|
4147 } |
|
4148 tokenEnd = end - 1; |
|
4149 // skip to next delimiter |
|
4150 end = aBuffer.Mid( tokenEnd + 1 ).FindF( KSemicolon8 ); |
|
4151 if ( end == KErrNotFound ) |
|
4152 { |
|
4153 end = aBuffer.Length(); |
|
4154 } |
|
4155 else |
|
4156 { |
|
4157 end += tokenEnd + 1; // remember the original offset |
|
4158 } |
|
4159 } |
|
4160 else |
|
4161 { |
|
4162 end = aBuffer.Mid( start ).FindF( KSemicolon8 ); |
|
4163 if ( end == KErrNotFound ) |
|
4164 { |
|
4165 end = aBuffer.Length(); |
|
4166 } |
|
4167 else |
|
4168 { |
|
4169 end += start; // remember the original offset |
|
4170 } |
|
4171 tokenEnd = end - 1; |
|
4172 // Remove trailing spaces from value. |
|
4173 // If the value was a quoted string, spaces are part of value, |
|
4174 // and must not be removed. |
|
4175 while ( aBuffer.Mid( start, tokenEnd - start + 1 ).FindF( KSpace8 ) == |
|
4176 tokenEnd - start ) |
|
4177 { |
|
4178 tokenEnd--; |
|
4179 } |
|
4180 } |
|
4181 iMimeHeaders->ContentTypeParams().AppendL( aBuffer.Mid( start, tokenEnd - start + 1 ) ); |
|
4182 // keep trying |
|
4183 start = end + 1; |
|
4184 } |
|
4185 } |
|
4186 |
|
4187 // --------------------------------------------------------- |
|
4188 // |
|
4189 // --------------------------------------------------------- |
|
4190 // |
|
4191 TBool CMmsDecode::MakeFilenameL( TPtrC8& aSource, TParse& aDestination, const TFileName& aPath ) |
|
4192 { |
|
4193 if ( aSource.Length() == 0 ) |
|
4194 { |
|
4195 return EFalse; |
|
4196 } |
|
4197 TBool retValue = EFalse; |
|
4198 TInt error = KErrNone; |
|
4199 HBufC* name = NULL; |
|
4200 name = HBufC::NewL( aSource.Length() ); |
|
4201 CleanupStack::PushL( name ); |
|
4202 TPtr pointer = name->Des(); |
|
4203 pointer.Copy( aSource ); |
|
4204 |
|
4205 if ( pointer.FindF( KEqualsQuestion16 ) != KErrNotFound ) |
|
4206 { |
|
4207 // Try to resolve MIME encoding |
|
4208 TRAP( error, TMmsGenUtils::DecodeAndConvertMessageHeaderL( aSource, pointer, iFs ) ); |
|
4209 } |
|
4210 else |
|
4211 { |
|
4212 // not MIME, error is fake, this may be just fine |
|
4213 error = KErrCorrupt; |
|
4214 } |
|
4215 |
|
4216 if ( error != KErrNone ) |
|
4217 { |
|
4218 // Try to resolve plain utf8 |
|
4219 error = CnvUtfConverter::ConvertToUnicodeFromUtf8( pointer, aSource ); |
|
4220 } |
|
4221 |
|
4222 if ( error != KErrNone ) |
|
4223 { |
|
4224 // use as is |
|
4225 name->Des().Copy( aSource ); |
|
4226 } |
|
4227 |
|
4228 TPtrC ptr; |
|
4229 |
|
4230 if ( pointer.Length() > 0 ) |
|
4231 { |
|
4232 #ifndef _NO_MMSS_LOGGING_ |
|
4233 ptr.Set( name->Des().Left( KMmsMaxLogStringLength ) ); |
|
4234 TMmsLogger::Log( _L("- decoded name: %S"), &ptr ); |
|
4235 #endif |
|
4236 // We limit the length in case the filename is way too long (max is 100 characters). |
|
4237 // We take the rightmost part to get the extension. |
|
4238 // If we drop something from the beginning, it may be path or beginning of an overly |
|
4239 // long name. As the too long name does not make sense anyway, we are free to drop |
|
4240 // any part we like. No filenames should be 100 characters long. |
|
4241 ptr.Set( name->Des().Right( KMmsMaxFileName ) ); |
|
4242 error = aDestination.Set( aPath, &ptr, NULL ); |
|
4243 if ( error == KErrNone ) |
|
4244 { |
|
4245 // If the string we are trying to set to TParse is not valid, |
|
4246 // we cannot check for filename |
|
4247 retValue = iEntryWrapper->IsValidFilename( aDestination.NameAndExt() ); |
|
4248 } |
|
4249 } |
|
4250 |
|
4251 CleanupStack::PopAndDestroy( name ); |
|
4252 return retValue; |
|
4253 } |
|
4254 |
|
4255 |
|
4256 // --------------------------------------------------------- |
|
4257 // |
|
4258 // --------------------------------------------------------- |
|
4259 // |
|
4260 void CMmsDecode::FinishL() |
|
4261 { |
|
4262 |
|
4263 // We don't check the critical disk space level here. |
|
4264 // If we got this far, we cannot balk now, |
|
4265 // we have to continue to the bitter end. |
|
4266 |
|
4267 // If root attachment id == 0, the root has been deleted. |
|
4268 // In that case the message structure has been messed up |
|
4269 // and we can only show separate objects |
|
4270 |
|
4271 // use iStore member |
|
4272 if ( !iStore ) |
|
4273 { |
|
4274 iStore = iEntryWrapper->EditStoreL(); |
|
4275 } |
|
4276 |
|
4277 iMmsHeaders->RestoreL( *iStore ); |
|
4278 |
|
4279 if ( iRootContentId.Length() > 0 && |
|
4280 iRootAttachmentId != 0 ) |
|
4281 { |
|
4282 iMmsHeaders->SetRootContentIdL( iRootContentId ); |
|
4283 iMmsHeaders->SetMessageRoot( iRootAttachmentId ); |
|
4284 iMmsHeaders->StoreL( *iStore ); |
|
4285 } |
|
4286 |
|
4287 // this also commits all the attachments |
|
4288 iStore->CommitL(); |
|
4289 |
|
4290 // If we are in chunked mode we must get the possible fake subject from a file |
|
4291 // because buffer gets reused. |
|
4292 |
|
4293 // now everything should be committed, and store can go |
|
4294 delete iStore; |
|
4295 iStore = NULL; |
|
4296 |
|
4297 // calculate the total size of message |
|
4298 iTotalSize += iMmsHeaders->Size(); |
|
4299 |
|
4300 TPtrC details = TPtrC(); |
|
4301 TPtrC description = TPtrC(); |
|
4302 |
|
4303 // Neither sender nor subject might be present. |
|
4304 // We ought to extract a few characters from the beginning of the |
|
4305 // first text/plain part for the subject, if no separate subject is available |
|
4306 |
|
4307 // if the sender is a phone number add alias. |
|
4308 // We don't add alias for email addresses here, as the comms |
|
4309 // database search for email addresses is very slow |
|
4310 // if there are lots of contacts. |
|
4311 |
|
4312 HBufC* buffer = HBufC::NewL( KMmsMaxDescription ); |
|
4313 CleanupStack::PushL( buffer ); |
|
4314 TPtr pBuffer = buffer->Des(); |
|
4315 HBufC* descriptionBuffer = NULL; // we may or may not need this |
|
4316 |
|
4317 if ( TMmsGenUtils::GenerateDetails( iMmsHeaders->Sender(), |
|
4318 pBuffer, KMmsMaxDescription, iFs ) == KErrNone ) |
|
4319 { |
|
4320 details.Set( pBuffer ); |
|
4321 } |
|
4322 else |
|
4323 { |
|
4324 // We come here only if there was a fatal error in GenerateDetails. |
|
4325 // Even if we don't find the alias, we have something in the string |
|
4326 details.Set( iMmsHeaders->Sender() ); |
|
4327 } |
|
4328 |
|
4329 // the buffer cannot be reused, because tEntry only contains |
|
4330 // a pointer to our data, not a copy of it. |
|
4331 if ( iMmsHeaders->Subject().Length() > 0 ) |
|
4332 { |
|
4333 description.Set( iMmsHeaders->Subject() ); |
|
4334 } |
|
4335 else |
|
4336 { |
|
4337 // Check if we have found a text/plain part to be used as description. |
|
4338 // Only use it if there is only one alternative, otherwise we don't |
|
4339 // know which one to use. |
|
4340 if ( iFakeSubject > 0 && iPlainTexts == 1 && iFakeSubject < iDecodeBuffer->Size() ) |
|
4341 { |
|
4342 // we have a pointer to text/plain part |
|
4343 // we need a new buffer as our old buffer should not be destroyed |
|
4344 |
|
4345 descriptionBuffer = HBufC::NewL( KMmsMaxDescription ); |
|
4346 CleanupStack::PushL( descriptionBuffer ); |
|
4347 pBuffer.Set( descriptionBuffer->Des() ); |
|
4348 |
|
4349 if ( iCharacterSet == KMmsIso10646Ucs2 || |
|
4350 iCharacterSet == KMmsUTF16 || |
|
4351 iCharacterSet == KMmsUTF16BE || |
|
4352 iCharacterSet == KMmsUTF16LE) |
|
4353 { |
|
4354 // This may be big-endian or little-endian |
|
4355 TBool nativeEndian = EFalse; // pessimist. |
|
4356 TInt length = iTextPlainLength; |
|
4357 if ( length > KMmsMaxDescription * KMms2 ) |
|
4358 { |
|
4359 length = KMmsMaxDescription * KMms2; // this should be enough |
|
4360 } |
|
4361 TInt i; |
|
4362 TUint start = 0; |
|
4363 TUint16 word = 0; |
|
4364 iPosition = iFakeSubject; |
|
4365 // must be able to read at least 2 bytes |
|
4366 if ( iPosition < iLength - 1 ) |
|
4367 { |
|
4368 iDecodeBuffer->Read( iPosition, &word, KMmsMinHeaderLength ); |
|
4369 } |
|
4370 |
|
4371 // Check if we have a BOM (byte order mark). |
|
4372 if ( word == KMmsByteOrderMark ) |
|
4373 { |
|
4374 nativeEndian = ETrue; |
|
4375 iPosition += KMms2; |
|
4376 start += KMms2; // skip the endianness byte from the subject |
|
4377 } |
|
4378 else if ( word == KMmsReversedByteOrderMark ) |
|
4379 { |
|
4380 nativeEndian = EFalse; |
|
4381 iPosition += KMms2; |
|
4382 start += KMms2; // skip the endianness byte from the subject |
|
4383 } |
|
4384 else |
|
4385 { |
|
4386 CBufFlat* shortBuffer = CBufFlat::NewL( KMms2 ); |
|
4387 CleanupStack::PushL( shortBuffer ); |
|
4388 shortBuffer->ResizeL( KMms2 ); |
|
4389 // no need to put it into cleanupstack... we dont't leave before we delete it |
|
4390 TUint8 byte; |
|
4391 // put little-endian BOM to buffer |
|
4392 byte = 0xFF; |
|
4393 shortBuffer->Write( 0, &byte, 1 ); |
|
4394 byte = 0xFE; |
|
4395 shortBuffer->Write( 1, &byte, 1 ); |
|
4396 // get the result into a word, and see if it came out straight or reversed |
|
4397 shortBuffer->Read( 0, &word, KMms2 ); |
|
4398 CleanupStack::PopAndDestroy( shortBuffer ); |
|
4399 shortBuffer = NULL; |
|
4400 if ( iCharacterSet == KMmsUTF16LE ) |
|
4401 { |
|
4402 // I think we are little endian, better check to be sure |
|
4403 if ( word == KMmsByteOrderMark ) |
|
4404 { |
|
4405 // we are little endian, charset is little endian |
|
4406 nativeEndian = ETrue; |
|
4407 } |
|
4408 else |
|
4409 { |
|
4410 nativeEndian = EFalse; |
|
4411 } |
|
4412 } |
|
4413 else if ( iCharacterSet == KMmsUTF16BE ) |
|
4414 { |
|
4415 if ( word == KMmsByteOrderMark ) |
|
4416 { |
|
4417 // we are little endian, charset is big endian |
|
4418 nativeEndian = EFalse; |
|
4419 } |
|
4420 else |
|
4421 { |
|
4422 nativeEndian = ETrue; |
|
4423 } |
|
4424 } |
|
4425 // if NO BOM and character set does not define byte ordering, |
|
4426 // we don't really know. |
|
4427 // Native endian is left as false - may not be the correct guess. |
|
4428 else |
|
4429 { |
|
4430 // do nothing - keep LINT happy |
|
4431 } |
|
4432 } |
|
4433 |
|
4434 if ( nativeEndian ) |
|
4435 { |
|
4436 for ( i = start; i < length - 1; i += KMms2 ) |
|
4437 { |
|
4438 iDecodeBuffer->Read(iPosition, &word, KMms2 ); |
|
4439 iPosition += KMms2; |
|
4440 pBuffer.Append( word ); |
|
4441 } |
|
4442 } |
|
4443 else |
|
4444 { |
|
4445 for ( i = start; i < length - 1; i += KMms2 ) |
|
4446 { |
|
4447 iDecodeBuffer->Read(iPosition, &word, KMms2 ); |
|
4448 iPosition += KMms2; |
|
4449 TUint16 temp; |
|
4450 temp = TUint16 ( word & 0xff ) ; //lower byte |
|
4451 word >>= KMmsBitsInByte; // higher to lower |
|
4452 word = TUint16 ( ( temp << KMmsBitsInByte ) + word ); |
|
4453 pBuffer.Append( word ); |
|
4454 } |
|
4455 } |
|
4456 |
|
4457 } |
|
4458 else if ( iCharacterSet == KMmsUsAscii ) |
|
4459 { |
|
4460 TInt length = iTextPlainLength; |
|
4461 if ( length > KMmsMaxDescription ) |
|
4462 { |
|
4463 length = KMmsMaxDescription; // this should be enough |
|
4464 } |
|
4465 TPtrC8 attaData; |
|
4466 attaData.Set( iDecodeBuffer->Ptr( iFakeSubject ).Ptr(), length ); |
|
4467 pBuffer.Copy( attaData ); |
|
4468 } |
|
4469 else if ( iCharacterSet == KMmsUtf8 ) |
|
4470 { |
|
4471 TInt length = iTextPlainLength; |
|
4472 if ( length > KMmsMaxDescription ) |
|
4473 { |
|
4474 length = KMmsMaxDescription; // this should be enough |
|
4475 } |
|
4476 // just in case our message is corrupted... |
|
4477 if ( length > (TInt) ( iDecodeBuffer->Size() - iFakeSubject ) ) |
|
4478 { |
|
4479 length = iDecodeBuffer->Size() - iFakeSubject; |
|
4480 } |
|
4481 TPtrC8 attaData; |
|
4482 attaData.Set( iDecodeBuffer->Ptr( iFakeSubject ).Ptr(), length ); |
|
4483 if ( length > 0 ) |
|
4484 { |
|
4485 CnvUtfConverter::ConvertToUnicodeFromUtf8( pBuffer, attaData ); |
|
4486 if ( pBuffer.Length() > 0 && pBuffer.Find( &KMmsByteOrderMark, 1 ) == 0 ) |
|
4487 { |
|
4488 // remove the BOM |
|
4489 pBuffer.Delete( 0, 1 ); |
|
4490 } |
|
4491 } |
|
4492 } |
|
4493 else |
|
4494 { |
|
4495 // we have some unknown character set. |
|
4496 // we should call some converter |
|
4497 } |
|
4498 TInt position; |
|
4499 for ( position = 0; position < pBuffer.Length(); position++ ) |
|
4500 { |
|
4501 if ( pBuffer.Mid( position, 1 ) < KSpace16 || |
|
4502 pBuffer.Mid( position, 1 ) == KMmsUnicodeLineSeparator || |
|
4503 pBuffer.Mid( position, 1 ) == KMmsUnicodeParagraphSeparator || |
|
4504 pBuffer.Mid( position, 1 ) == KMmsIdeographicSpace || |
|
4505 ((TChar)pBuffer[position]).IsControl() ) |
|
4506 { |
|
4507 pBuffer.Replace( position, 1, KSpace16 ); |
|
4508 } |
|
4509 } |
|
4510 |
|
4511 |
|
4512 pBuffer.TrimAll(); |
|
4513 description.Set( pBuffer ); |
|
4514 } |
|
4515 } |
|
4516 |
|
4517 // don't set the response status text to description if the status is OK. |
|
4518 // In that case we have received an empty message that should have no description. |
|
4519 // In OK case the text is mostly "OK" or something equally uninformative |
|
4520 if ( description.Length() == 0 && iMmsHeaders->ResponseText().Length() > 0 && |
|
4521 iMmsHeaders->ResponseStatus() > KMmsResponseStatusOK ) |
|
4522 { |
|
4523 description.Set( iMmsHeaders->ResponseText() ); |
|
4524 } |
|
4525 |
|
4526 TUint32 messageType = 0; |
|
4527 |
|
4528 switch ( iMmsHeaders->MessageType() ) |
|
4529 { |
|
4530 case KMmsMessageTypeMSendReq: |
|
4531 messageType = KMmsMessageMSendReq; |
|
4532 break; |
|
4533 case KMmsMessageTypeMNotificationInd: |
|
4534 messageType = KMmsMessageMNotificationInd; |
|
4535 break; |
|
4536 case KMmsMessageTypeMRetrieveConf: |
|
4537 messageType = KMmsMessageMRetrieveConf; |
|
4538 break; |
|
4539 case KMmsMessageTypeDeliveryInd: |
|
4540 messageType = KMmsMessageDeliveryInd; |
|
4541 break; |
|
4542 default: |
|
4543 // Unrecognized type - or one we are not interested in. |
|
4544 // Messages that should not normally be stored on disk |
|
4545 // have the type "unrecognized" |
|
4546 // The type in TMsvEntry should be used for showing icons |
|
4547 // or other special purposes only |
|
4548 messageType = KMmsMessageUnrecognized; |
|
4549 break; |
|
4550 } |
|
4551 |
|
4552 // All data to iMtmData1 is set to an empty base. |
|
4553 // If caller has more flags to set, they must be set afterwards |
|
4554 TInt32 mtmData = 0; |
|
4555 mtmData |= messageType; |
|
4556 mtmData |= iDRMFlags; |
|
4557 if ( iMmsHeaders->MessageClass() == EMmsClassAdvertisement ) |
|
4558 { |
|
4559 mtmData |= KMmsMessageAdvertisement; |
|
4560 } |
|
4561 else if ( iMmsHeaders->MessageClass() == EMmsClassInformational ) |
|
4562 { |
|
4563 mtmData |= KMmsMessageInformational; |
|
4564 } |
|
4565 else |
|
4566 { |
|
4567 // do nothing - keep LINT happy |
|
4568 } |
|
4569 |
|
4570 TMsvEntry entry; |
|
4571 |
|
4572 iEntryWrapper->GetIndexEntry( entry ); |
|
4573 |
|
4574 entry.iDetails.Set( details ); |
|
4575 entry.iDescription.Set( description ); |
|
4576 entry.iMtmData1 = mtmData; |
|
4577 entry.iSize = iTotalSize; |
|
4578 // Set the date. |
|
4579 // This can in principle be either the arrival time of the message |
|
4580 // or the original time the message was received by MMSC |
|
4581 |
|
4582 entry.iDate = iMmsHeaders->ReceivingTime(); |
|
4583 |
|
4584 switch ( iMmsHeaders->MessagePriority() ) |
|
4585 { |
|
4586 case KMmsPriorityNormal: |
|
4587 entry.SetPriority( EMsvMediumPriority ); |
|
4588 break; |
|
4589 case KMmsPriorityLow: |
|
4590 entry.SetPriority( EMsvLowPriority ); |
|
4591 break; |
|
4592 case KMmsPriorityHigh: |
|
4593 entry.SetPriority( EMsvHighPriority ); |
|
4594 break; |
|
4595 default: |
|
4596 // if not defined default is normal |
|
4597 entry.SetPriority( EMsvMediumPriority ); |
|
4598 break; |
|
4599 } |
|
4600 |
|
4601 // set the bio type to audio message if the message contains nothing but one |
|
4602 // amr part in addition to possible one smil |
|
4603 |
|
4604 if ( iSmilCount <= 1 && iAudioCount == 1 && |
|
4605 ( iAttaNumber == iSmilCount + iAudioCount ) ) |
|
4606 { |
|
4607 if(!CheckDRMContent()) |
|
4608 { |
|
4609 TBool audioSupported = EFalse; |
|
4610 TRAP_IGNORE( |
|
4611 { |
|
4612 FeatureManager::InitializeLibL(); |
|
4613 audioSupported = FeatureManager::FeatureSupported( KFeatureIdAudioMessaging ); |
|
4614 FeatureManager::UnInitializeLib(); |
|
4615 }); |
|
4616 |
|
4617 if ( audioSupported ) |
|
4618 { |
|
4619 entry.iBioType = KUidMsgSubTypeMmsAudioMsg.iUid; |
|
4620 } |
|
4621 } |
|
4622 } |
|
4623 |
|
4624 //Since the changes have been committed to the store , we should get exact attachment count from the store. |
|
4625 //The message type check is not required as the only messagtypes decoded are retrieve-conf in global mode and send-req in local mode |
|
4626 TInt attachmentCount = 0; |
|
4627 CMsvStore* store = iEntryWrapper->ReadStoreL(); |
|
4628 CleanupStack::PushL( store ); |
|
4629 |
|
4630 // Only new attachment structure is supported |
|
4631 MMsvAttachmentManager& attachMan = store->AttachmentManagerL(); |
|
4632 attachmentCount = attachMan.AttachmentCount(); |
|
4633 |
|
4634 CleanupStack::PopAndDestroy( store ); |
|
4635 if ( attachmentCount > 0 ) |
|
4636 { |
|
4637 entry.SetAttachment(ETrue); |
|
4638 } |
|
4639 |
|
4640 iEntryWrapper->ChangeIndexEntry( entry ); |
|
4641 |
|
4642 // now that we have saved our index entry, the buffers can go |
|
4643 if ( descriptionBuffer ) |
|
4644 { |
|
4645 // if we have allocated a separate buffer for the |
|
4646 // description, it sits on cleanups stack too. |
|
4647 CleanupStack::PopAndDestroy( descriptionBuffer ); |
|
4648 } |
|
4649 CleanupStack::PopAndDestroy( buffer ); |
|
4650 |
|
4651 } |
|
4652 |
|
4653 // --------------------------------------------------------- |
|
4654 // CMmsDecode::CheckDRMContent |
|
4655 // --------------------------------------------------------- |
|
4656 // |
|
4657 TBool CMmsDecode::CheckDRMContent() |
|
4658 { |
|
4659 CFileProtectionResolver* resolver = CFileProtectionResolver::NewLC( iFs); |
|
4660 |
|
4661 CMsvStore* store = iEntryWrapper->ReadStoreL(); |
|
4662 CleanupStack::PushL( store ); |
|
4663 MMsvAttachmentManager& attaManager = store->AttachmentManagerL(); |
|
4664 |
|
4665 TInt attaCount = attaManager.AttachmentCount(); |
|
4666 TInt flCount = 0; |
|
4667 TInt sdCount = 0; |
|
4668 |
|
4669 for ( TInt i = 0; i < attaCount; i++ ) |
|
4670 { |
|
4671 CMsvAttachment* info = attaManager.GetAttachmentInfoL( i ); |
|
4672 CleanupStack::PushL( info ); |
|
4673 TDataType dataType( info->MimeType() ); |
|
4674 if(dataType.Des8().Match(KmmsSmilMimeType) != KErrNotFound) |
|
4675 { |
|
4676 CleanupStack::PopAndDestroy( info ); |
|
4677 continue; |
|
4678 } |
|
4679 RFile file = attaManager.GetAttachmentFileL( info->Id() ); |
|
4680 CleanupClosePushL( file ); |
|
4681 |
|
4682 TInt status = resolver->ProtectionStatusL( file, dataType ); |
|
4683 if ( status & EFileProtForwardLocked || |
|
4684 status & EFileProtClosedContent ) |
|
4685 { |
|
4686 flCount++; |
|
4687 } |
|
4688 else if ( status & EFileProtSuperDistributable ) |
|
4689 { |
|
4690 sdCount++; |
|
4691 } |
|
4692 |
|
4693 CleanupStack::PopAndDestroy( 2, info ); // file, info |
|
4694 } |
|
4695 |
|
4696 CleanupStack::PopAndDestroy( 2, resolver ); //store, resolver |
|
4697 #ifndef _NO_MMSS_LOGGING_ |
|
4698 TMmsLogger::Log( _L("- CheckDRMContent:Total count :%d,FlCount: %d"),attaCount, flCount ); |
|
4699 TMmsLogger::Log( _L("- CheckDRMContent:SDCount: %d"), sdCount ); |
|
4700 #endif |
|
4701 if(flCount ||sdCount ) |
|
4702 return ETrue; |
|
4703 else |
|
4704 return EFalse; |
|
4705 } |
|
4706 |
|
4707 // --------------------------------------------------------- |
|
4708 // |
|
4709 // --------------------------------------------------------- |
|
4710 void CMmsDecode::DumpL() |
|
4711 { |
|
4712 // no dump if not logging |
|
4713 #ifndef _NO_MMSS_LOGGING_ |
|
4714 TInt error = KErrNone; |
|
4715 RFile file; |
|
4716 TUint att; |
|
4717 _LIT( KRelated, "Rec.mms"); |
|
4718 // if no can do, sorry. |
|
4719 TRAP( error, |
|
4720 { |
|
4721 if ( ( iDumpIncoming ) && iDecodeBuffer ) |
|
4722 { |
|
4723 if ( iDecodeBuffer->Size() > 0 && iDecodingStage == EMmsNotApplicable ) |
|
4724 { |
|
4725 // non-chunked mode. All data is in buffer, and can be dumped in one go |
|
4726 iFileName = KMmsDefaultLogDirectory; |
|
4727 // Check if directory exists - no directory, no dump |
|
4728 User::LeaveIfError( iFs.Att( iFileName, att ) ); |
|
4729 iParse.Set( iFileName, &KRelated, NULL ); |
|
4730 iFileName = iParse.FullName(); |
|
4731 User::LeaveIfError( CApaApplication::GenerateFileName( |
|
4732 iFs, iFileName ) ); |
|
4733 User::LeaveIfError( file.Create( iFs, iFileName, |
|
4734 EFileWrite | EFileShareExclusive ) ); |
|
4735 // for message id generation |
|
4736 iParse.Set( iFileName, NULL, NULL ); |
|
4737 |
|
4738 // the data is supposed to be in the encode buffer |
|
4739 TPtr8 ptr = iDecodeBuffer->Ptr( 0 ); |
|
4740 file.Write( ptr ); |
|
4741 file.Flush(); |
|
4742 |
|
4743 // done - close files |
|
4744 file.Close(); |
|
4745 } |
|
4746 // chunked mode start - no data yet, initialize file |
|
4747 else if ( iLength == 0 && iDecodingStage == EMmsHeaders ) |
|
4748 { |
|
4749 // This is the initialization of the dump file |
|
4750 iFileName = KMmsDefaultLogDirectory; |
|
4751 // create an empty file |
|
4752 // The name of the file will remain in iFilename |
|
4753 // Later data will be appended to the same file |
|
4754 User::LeaveIfError( iFs.Att( iFileName, att ) ); |
|
4755 iParse.Set( iFileName, &KRelated, NULL ); |
|
4756 iFileName = iParse.FullName(); |
|
4757 User::LeaveIfError( CApaApplication::GenerateFileName( |
|
4758 iFs, iFileName ) ); |
|
4759 User::LeaveIfError( file.Create( iFs, iFileName, |
|
4760 EFileWrite | EFileShareExclusive ) ); |
|
4761 // for message id generation |
|
4762 iParse.Set( iFileName, NULL, NULL ); |
|
4763 file.Close(); |
|
4764 } |
|
4765 else if ( iDecodingStage != EMmsNotApplicable ) |
|
4766 { |
|
4767 User::LeaveIfError( file.Open( iFs, iFileName, |
|
4768 EFileWrite | EFileShareExclusive ) ); |
|
4769 TInt position = 0; |
|
4770 User::LeaveIfError( file.Seek( ESeekEnd, position ) ); |
|
4771 // the data is supposed to be in the encode buffer |
|
4772 // But only write the amount of data that has been processed. |
|
4773 // Some of the data may be pushed back to the beginning of the buffer |
|
4774 // and we do not want to write such data twice. |
|
4775 // iOldData tells how much data was left over from previous round |
|
4776 // We always write as much as we have got so that we can analyze |
|
4777 // a possible error |
|
4778 TPtr8 ptr = iDecodeBuffer->Ptr( iOldData ); |
|
4779 // If there is any data, write it |
|
4780 if ( ptr.Length() > 0 ) |
|
4781 { |
|
4782 file.Write( ptr ); |
|
4783 file.Flush(); |
|
4784 } |
|
4785 |
|
4786 // done - close files |
|
4787 file.Close(); |
|
4788 } |
|
4789 else |
|
4790 { |
|
4791 // do nothing |
|
4792 } |
|
4793 } |
|
4794 } |
|
4795 ); |
|
4796 if ( error != KErrNone ) |
|
4797 { |
|
4798 TMmsLogger::Log( _L("- Dump left, error : %d"), error ); |
|
4799 } |
|
4800 #endif |
|
4801 } |
|
4802 |
|
4803 // --------------------------------------------------------- |
|
4804 // |
|
4805 // --------------------------------------------------------- |
|
4806 void CMmsDecode::DumpSmil( TInt aDataLength ) |
|
4807 { |
|
4808 // no dump if not logging |
|
4809 #ifndef _NO_MMSS_LOGGING_ |
|
4810 |
|
4811 TBool lowMemory = EFalse; |
|
4812 |
|
4813 TRAP_IGNORE({ |
|
4814 lowMemory = iEntryWrapper->DiskSpaceBelowCriticalLevelL( aDataLength ); |
|
4815 }); |
|
4816 |
|
4817 // Only dump smil part if not decoding in chunks. |
|
4818 // In chunked mode it would be too complicated. |
|
4819 if ( iDumpIncoming && iMimeHeaders->ContentType().CompareF( KMmsApplicationSmil ) == 0 |
|
4820 && !lowMemory && iDecodingStage == EMmsNotApplicable) |
|
4821 { |
|
4822 RFile file; |
|
4823 iFileName = KMmsDefaultLogDirectory; |
|
4824 TUint att; |
|
4825 if ( iFs.Att( iFileName, att ) == KErrNone ) |
|
4826 { |
|
4827 _LIT( KRelated2, "smil.txt"); |
|
4828 iParse.Set( iFileName, &KRelated2, NULL ); |
|
4829 iFileName = iParse.FullName(); |
|
4830 TInt error = CApaApplication::GenerateFileName( iFs, iFileName ); |
|
4831 if ( error == KErrNone ) |
|
4832 { |
|
4833 error = file.Create( iFs, iFileName, EFileWrite | EFileShareExclusive ); |
|
4834 // for message id generation |
|
4835 iParse.Set( iFileName, NULL, NULL ); |
|
4836 |
|
4837 if ( error == KErrNone ) |
|
4838 { |
|
4839 // the data is supposed to be in the encode buffer |
|
4840 TPtrC8 ptrx; |
|
4841 ptrx.Set( iDecodeBuffer->Ptr( iPosition ).Ptr(), aDataLength ); |
|
4842 file.Write( ptrx ); |
|
4843 file.Flush(); |
|
4844 } |
|
4845 |
|
4846 // done - close files |
|
4847 file.Close(); |
|
4848 } |
|
4849 } |
|
4850 } |
|
4851 #endif |
|
4852 } |
|
4853 |
|
4854 |
|
4855 // --------------------------------------------------------- |
|
4856 // |
|
4857 // --------------------------------------------------------- |
|
4858 void CMmsDecode::LogYesNo( TRefByValue<const TDesC> aTitle, TInt aValue ) |
|
4859 { |
|
4860 #ifndef _NO_MMSS_LOGGING_ |
|
4861 TMmsLogger::Log( aTitle ); |
|
4862 switch ( aValue ) |
|
4863 { |
|
4864 case ( KMmsYes ): |
|
4865 TMmsLogger::Log( KLogYes ); |
|
4866 break; |
|
4867 case ( KMmsNo ): |
|
4868 TMmsLogger::Log( KLogNo ); |
|
4869 break; |
|
4870 default: |
|
4871 TMmsLogger::Log( KLogUnknown, aValue ); |
|
4872 break; |
|
4873 } |
|
4874 #endif |
|
4875 } |
|
4876 |
|
4877 // --------------------------------------------------------- |
|
4878 // |
|
4879 // --------------------------------------------------------- |
|
4880 void CMmsDecode::GetKeywordL() |
|
4881 { |
|
4882 GetValueLength(); // must be read just to get it out of way |
|
4883 TUint8 byte; // for simple reads |
|
4884 byte = GetWellKnownFieldValueOrSkip(); |
|
4885 TUint temp; |
|
4886 temp = byte; // should be add, remove or filter |
|
4887 HBufC16* buffer = NULL; |
|
4888 buffer = GetEncodedTextStringL(); |
|
4889 CleanupStack::PushL( buffer ); // keyword |
|
4890 TPtrC dummy; |
|
4891 dummy.Set( buffer->Des() ); |
|
4892 |
|
4893 iMmsHeaders->MMBoxMessageHeadersL().AppendKeywordItemL( temp, dummy ); |
|
4894 #ifndef _NO_MMSS_LOGGING_ |
|
4895 dummy.Set( buffer->Des().Left( KMmsMaxLogStringLength ) ); |
|
4896 TMmsLogger::Log( _L("- Keyword: %S"), &dummy ); |
|
4897 switch ( temp ) |
|
4898 { |
|
4899 case KMmsAddToken: |
|
4900 TMmsLogger::Log( _L("-- Add") ); |
|
4901 break; |
|
4902 case KMmsRemoveToken: |
|
4903 TMmsLogger::Log( _L("-- Remove") ); |
|
4904 break; |
|
4905 case KMmsFilterToken: |
|
4906 TMmsLogger::Log( _L("-- Filter") ); |
|
4907 break; |
|
4908 default: |
|
4909 TMmsLogger::Log( KLogUnknown, temp ); |
|
4910 break; |
|
4911 } |
|
4912 #endif |
|
4913 CleanupStack::PopAndDestroy( buffer ); |
|
4914 } |
|
4915 |
|
4916 // --------------------------------------------------------- |
|
4917 // |
|
4918 // --------------------------------------------------------- |
|
4919 void CMmsDecode::CompleteSelf( TInt aError ) |
|
4920 { |
|
4921 // completed own status to get back to the RunL |
|
4922 iStatus = KRequestPending; |
|
4923 SetActive(); |
|
4924 TRequestStatus* status = &iStatus; |
|
4925 User::RequestComplete( status, aError ); |
|
4926 } |
|
4927 |
|
4928 // --------------------------------------------------------- |
|
4929 // |
|
4930 // --------------------------------------------------------- |
|
4931 // |
|
4932 TBool CMmsDecode::IsStringSafe( const TDesC8& aString ) |
|
4933 { |
|
4934 |
|
4935 // Very simple check to see if string is "safe" ASCII |
|
4936 // Used for headers, which are short strings |
|
4937 |
|
4938 TInt i; |
|
4939 TBool safe = ETrue; |
|
4940 for ( i = 0; i < aString.Length() && safe; i++ ) |
|
4941 { |
|
4942 if ( aString[i] < KMmsLowestAscii || aString[i] >= KMmsHighestAscii ) |
|
4943 { |
|
4944 safe = EFalse; |
|
4945 } |
|
4946 } |
|
4947 return safe; |
|
4948 } |
|
4949 |
|
4950 // --------------------------------------------------------- |
|
4951 // |
|
4952 // --------------------------------------------------------- |
|
4953 void CMmsDecode::DecodeFromHeaderL() |
|
4954 { |
|
4955 HBufC16* buffer = NULL; |
|
4956 buffer = DecodeFromL(); |
|
4957 CleanupStack::PushL( buffer ); |
|
4958 iMmsHeaders->SetSenderL( buffer->Des() ); |
|
4959 #ifndef _NO_MMSS_LOGGING_ |
|
4960 // we cannot log indefinitely long strings. |
|
4961 // We get this long strings only if the message is corrupted. |
|
4962 TPtrC dummy; |
|
4963 dummy.Set( buffer->Des().Left( KMmsMaxLogStringLength ) ); |
|
4964 TMmsLogger::Log( _L("- From: %S"), &dummy ); |
|
4965 #endif |
|
4966 CleanupStack::PopAndDestroy( buffer ); |
|
4967 } |
|
4968 |
|
4969 // --------------------------------------------------------- |
|
4970 // |
|
4971 // --------------------------------------------------------- |
|
4972 void CMmsDecode::DecodeToL() |
|
4973 { |
|
4974 HBufC16* buffer = NULL; |
|
4975 buffer = DecodeAddressL(); |
|
4976 CleanupStack::PushL( buffer ); |
|
4977 iMmsHeaders->AddTypedAddresseeL( buffer->Des(), EMmsTo ); |
|
4978 #ifndef _NO_MMSS_LOGGING_ |
|
4979 // we cannot log indefinitely long strings. |
|
4980 // We get this long strings only if the message is corrupted. |
|
4981 TPtrC dummy; |
|
4982 dummy.Set( buffer->Des().Left( KMmsMaxLogStringLength ) ); |
|
4983 TMmsLogger::Log( _L("- To: %S"), &dummy ); |
|
4984 #endif |
|
4985 CleanupStack::PopAndDestroy( buffer ); |
|
4986 } |
|
4987 |
|
4988 // --------------------------------------------------------- |
|
4989 // |
|
4990 // --------------------------------------------------------- |
|
4991 void CMmsDecode::DecodeCcL() |
|
4992 { |
|
4993 HBufC16* buffer = NULL; |
|
4994 buffer = DecodeAddressL(); |
|
4995 CleanupStack::PushL( buffer ); |
|
4996 iMmsHeaders->AddTypedAddresseeL( buffer->Des(), EMmsCc ); |
|
4997 #ifndef _NO_MMSS_LOGGING_ |
|
4998 // we cannot log indefinitely long strings. |
|
4999 // We get this long strings only if the message is corrupted. |
|
5000 TPtrC dummy; |
|
5001 dummy.Set( buffer->Des().Left( KMmsMaxLogStringLength ) ); |
|
5002 TMmsLogger::Log( _L("- Cc: %S"), &dummy ); |
|
5003 #endif |
|
5004 CleanupStack::PopAndDestroy( buffer ); |
|
5005 } |
|
5006 |
|
5007 // --------------------------------------------------------- |
|
5008 // |
|
5009 // --------------------------------------------------------- |
|
5010 void CMmsDecode::DecodeBccL() |
|
5011 { |
|
5012 HBufC16* buffer = NULL; |
|
5013 buffer = DecodeAddressL(); |
|
5014 CleanupStack::PushL( buffer ); |
|
5015 iMmsHeaders->AddTypedAddresseeL( buffer->Des(), EMmsBcc ); |
|
5016 #ifndef _NO_MMSS_LOGGING_ |
|
5017 // we cannot log indefinitely long strings. |
|
5018 // We get this long strings only if the message is corrupted. |
|
5019 TPtrC dummy; |
|
5020 dummy.Set( buffer->Des().Left( KMmsMaxLogStringLength ) ); |
|
5021 TMmsLogger::Log( _L("- Bcc: %S"), &dummy ); |
|
5022 #endif |
|
5023 CleanupStack::PopAndDestroy( buffer ); |
|
5024 } |
|
5025 |
|
5026 // --------------------------------------------------------- |
|
5027 // |
|
5028 // --------------------------------------------------------- |
|
5029 void CMmsDecode::DecodeContentLocationHeaderL() |
|
5030 { |
|
5031 TPtrC8 byteString; |
|
5032 TUint32 size = 0; |
|
5033 // Request headers are handled for testing purposes only |
|
5034 // Only PDUs that we should decode are the confirmation types |
|
5035 if ( iMmsHeaders->MessageType() != KMmsMessageTypeMBoxDeleteConf && |
|
5036 iMmsHeaders->MessageType() != KMmsMessageTypeDeleteConf ) |
|
5037 { |
|
5038 byteString.Set( GetByteString() ); |
|
5039 // for the MMBox view type PDUs the content locations go into the array |
|
5040 if ( iMmsHeaders->MessageType() == KMmsMessageTypeMboxViewConf || |
|
5041 iMmsHeaders->MessageType() == KMmsMessageTypeMboxViewReq || |
|
5042 iMmsHeaders->MessageType() == KMmsMessageTypeMBoxDeleteReq || |
|
5043 iMmsHeaders->MessageType() == KMmsMessageTypeDeleteReq ) |
|
5044 { |
|
5045 iMmsHeaders->MMBoxMessageHeadersL().ContentLocationList().AppendL( |
|
5046 byteString ); |
|
5047 } |
|
5048 else if ( iMmsHeaders->ContentLocation().Length() == 0 ) |
|
5049 { |
|
5050 iMmsHeaders->SetContentLocationL( byteString ); |
|
5051 } |
|
5052 else |
|
5053 { |
|
5054 // This is some message type that allows more than one content location |
|
5055 // The only one should be M-Mbox-Delete.req. |
|
5056 if ( iMmsHeaders->MMBoxMessageHeadersL().ContentLocationList().MdcaCount() |
|
5057 == 0 ) |
|
5058 { |
|
5059 // nothing in the list, append the old one, too |
|
5060 iMmsHeaders->MMBoxMessageHeadersL().ContentLocationList().AppendL( |
|
5061 iMmsHeaders->ContentLocation() ); |
|
5062 } |
|
5063 iMmsHeaders->MMBoxMessageHeadersL().ContentLocationList().AppendL( |
|
5064 byteString ); |
|
5065 } |
|
5066 } |
|
5067 else // KMmsMessageTypeMBoxDeleteConf has different format |
|
5068 { |
|
5069 GetValueLength(); |
|
5070 size = GetLongOrShortInteger(); // this is actually index |
|
5071 byteString.Set( GetByteString() ); |
|
5072 iMmsHeaders->InsertDeleteContentLocationL( size, byteString ); |
|
5073 #ifndef _NO_MMSS_LOGGING_ |
|
5074 TMmsLogger::Log( _L("- Content Location index: %d"), size ); |
|
5075 #endif |
|
5076 } |
|
5077 #ifndef _NO_MMSS_LOGGING_ |
|
5078 HBufC16* buffer = NULL; |
|
5079 buffer = HBufC16::NewLC( byteString.Length() ); |
|
5080 buffer->Des().Copy( byteString ); |
|
5081 // we cannot log indefinitely long strings. |
|
5082 // We get this long strings only if the message is corrupted. |
|
5083 TPtrC dummy; |
|
5084 dummy.Set( buffer->Des().Left( KMmsMaxLogStringLength ) ); |
|
5085 TMmsLogger::Log( _L("- Content Location: %S"), &dummy ); |
|
5086 CleanupStack::PopAndDestroy( buffer ); |
|
5087 #endif |
|
5088 } |
|
5089 |
|
5090 // --------------------------------------------------------- |
|
5091 // |
|
5092 // --------------------------------------------------------- |
|
5093 void CMmsDecode::DecodeDateHeaderL() |
|
5094 { |
|
5095 TInt64 date; |
|
5096 TUint8 byte; |
|
5097 date = GetVeryLongInteger(); |
|
5098 if ( iError == KErrTooBig ) |
|
5099 { |
|
5100 // we get here only if we have at least one byte to read |
|
5101 iDecodeBuffer->Read(iPosition, &byte, 1); |
|
5102 iPosition++; |
|
5103 // skip rest of field if too long |
|
5104 iPosition += byte; |
|
5105 } |
|
5106 if ( iPosition >= iLength ) |
|
5107 { |
|
5108 iError = KErrCorrupt; |
|
5109 return; |
|
5110 } |
|
5111 iMmsHeaders->SetDate( date ); |
|
5112 #ifndef _NO_MMSS_LOGGING_ |
|
5113 TMmsLogger::Log( _L("- Date:") ); |
|
5114 LogDateL( date ); |
|
5115 #endif |
|
5116 } |
|
5117 |
|
5118 // --------------------------------------------------------- |
|
5119 // |
|
5120 // --------------------------------------------------------- |
|
5121 void CMmsDecode::DecodeDeliveryReportHeader() |
|
5122 { |
|
5123 TUint8 byte; |
|
5124 TUint temp; |
|
5125 byte = GetWellKnownFieldValueOrSkip(); |
|
5126 temp = byte; |
|
5127 iMmsHeaders->SetDeliveryReport( temp ); |
|
5128 #ifndef _NO_MMSS_LOGGING_ |
|
5129 LogYesNo( _L("- DeliveryReport:"), temp ); |
|
5130 #endif |
|
5131 } |
|
5132 |
|
5133 // --------------------------------------------------------- |
|
5134 // |
|
5135 // --------------------------------------------------------- |
|
5136 void CMmsDecode::DecodeDeliveryTimeL() |
|
5137 { |
|
5138 TUint8 byte; |
|
5139 TInt64 date; |
|
5140 byte = GetRelativeOrAbsoluteTime( date ); |
|
5141 if ( byte == KMmsRelativeToken ) |
|
5142 { |
|
5143 iMmsHeaders->SetDeliveryTimeInterval( I64LOW( date ) ); |
|
5144 #ifndef _NO_MMSS_LOGGING_ |
|
5145 TMmsLogger::Log( _L("- Delivery Time, interval %d s"), I64LOW( date ) ); |
|
5146 #endif |
|
5147 } |
|
5148 if ( byte == KMmsAbsoluteToken ) |
|
5149 { |
|
5150 // keep as universal time, don't convert to local time |
|
5151 iMmsHeaders->SetDeliveryDate( date ); |
|
5152 #ifndef _NO_MMSS_LOGGING_ |
|
5153 TMmsLogger::Log( _L("- Delivery Time, absolute ") ); |
|
5154 LogDateL( date ); |
|
5155 #endif |
|
5156 } |
|
5157 // If could not interpret field, don't set anything. |
|
5158 } |
|
5159 |
|
5160 // --------------------------------------------------------- |
|
5161 // |
|
5162 // --------------------------------------------------------- |
|
5163 void CMmsDecode::DecodeExpiryL() |
|
5164 { |
|
5165 TUint8 byte; |
|
5166 TInt64 date; |
|
5167 byte = GetRelativeOrAbsoluteTime( date ); |
|
5168 if ( byte == KMmsRelativeToken ) |
|
5169 { |
|
5170 iMmsHeaders->SetExpiryInterval( I64LOW( date ) ); |
|
5171 #ifndef _NO_MMSS_LOGGING_ |
|
5172 TMmsLogger::Log( _L("- Expiry interval: %d s"), I64LOW( date ) ); |
|
5173 #endif |
|
5174 } |
|
5175 if ( byte == KMmsAbsoluteToken ) |
|
5176 { |
|
5177 // keep as universal time, don't convert to local time |
|
5178 iMmsHeaders->SetExpiryDate( date ); |
|
5179 #ifndef _NO_MMSS_LOGGING_ |
|
5180 TMmsLogger::Log( _L("- Expiry, absolute:") ); |
|
5181 LogDateL( date ); |
|
5182 #endif |
|
5183 } |
|
5184 // If could not interpret field, don't set anything. |
|
5185 } |
|
5186 |
|
5187 // --------------------------------------------------------- |
|
5188 // |
|
5189 // --------------------------------------------------------- |
|
5190 void CMmsDecode::DecodeMessageClass() |
|
5191 { |
|
5192 TUint8 byte = 0; |
|
5193 TUint temp; |
|
5194 |
|
5195 iDecodeBuffer->Read(iPosition, &byte, 1); |
|
5196 |
|
5197 if ( byte >= KMms0x80 ) |
|
5198 { |
|
5199 iPosition++; |
|
5200 temp = byte; |
|
5201 iMmsHeaders->SetMessageClass( temp ); |
|
5202 #ifndef _NO_MMSS_LOGGING_ |
|
5203 TMmsLogger::Log( _L("-- MessageCalss encoded as Class-identifier") ); |
|
5204 #endif |
|
5205 } |
|
5206 else |
|
5207 { |
|
5208 TPtrC8 byteString = GetByteString(); |
|
5209 #ifndef _NO_MMSS_LOGGING_ |
|
5210 TMmsLogger::Log( _L("-- MessageCalss encoded as Token-text") ); |
|
5211 // we don't leave because of logging |
|
5212 TInt error = KErrNone; |
|
5213 TRAP( error, |
|
5214 { |
|
5215 HBufC16* buffer = NULL; |
|
5216 buffer = HBufC16::NewLC( byteString.Length() ); |
|
5217 buffer->Des().Copy( byteString ); |
|
5218 TPtrC dummy; |
|
5219 // we cannot log indefinitely long strings. |
|
5220 // We get this long strings only if the message is corrupted. |
|
5221 dummy.Set( buffer->Des().Left( KMmsMaxLogStringLength ) ); |
|
5222 TMmsLogger::Log( _L("- Message class : %S"), &dummy ); |
|
5223 CleanupStack::PopAndDestroy( buffer ); |
|
5224 }); |
|
5225 if ( error != KErrNone ) |
|
5226 { |
|
5227 TMmsLogger::Log( _L("- Decode left when logging Message class, error : %d"), |
|
5228 error ); |
|
5229 } |
|
5230 #endif |
|
5231 temp = KMmsTestIllegalValue; |
|
5232 if ( byteString.CompareF( KMessageClassPersonal ) == 0 ) |
|
5233 { |
|
5234 temp = KMmsMessageClassPersonal; |
|
5235 } |
|
5236 else if ( byteString.CompareF( KMessageClassAdvertisement ) == 0 ) |
|
5237 { |
|
5238 temp = KMmsMessageClassAdvertisement; |
|
5239 } |
|
5240 else if ( byteString.CompareF( KMessageClassInformational ) == 0 ) |
|
5241 { |
|
5242 temp = KMmsMessageClassInformational; |
|
5243 } |
|
5244 else if ( byteString.CompareF( KMessageClassAuto ) == 0 ) |
|
5245 { |
|
5246 temp = KMmsMessageClassAuto; |
|
5247 } |
|
5248 iMmsHeaders->SetMessageClass( temp ); |
|
5249 } |
|
5250 #ifndef _NO_MMSS_LOGGING_ |
|
5251 TMmsLogger::Log( _L("- Message Class:") ); |
|
5252 switch ( temp ) |
|
5253 { |
|
5254 case KMmsMessageClassPersonal: |
|
5255 TMmsLogger::Log( _L("-- Personal") ); |
|
5256 break; |
|
5257 case KMmsMessageClassAdvertisement: |
|
5258 TMmsLogger::Log( _L("-- Advertisement") ); |
|
5259 break; |
|
5260 case KMmsMessageClassInformational: |
|
5261 TMmsLogger::Log( _L("-- Informational") ); |
|
5262 break; |
|
5263 case KMmsMessageClassAuto: |
|
5264 TMmsLogger::Log( _L("-- Auto") ); |
|
5265 break; |
|
5266 default: |
|
5267 TMmsLogger::Log( KLogUnknown, temp ); |
|
5268 break; |
|
5269 } |
|
5270 #endif |
|
5271 } |
|
5272 |
|
5273 // --------------------------------------------------------- |
|
5274 // |
|
5275 // --------------------------------------------------------- |
|
5276 void CMmsDecode::DecodeMessageIdL() |
|
5277 { |
|
5278 TPtrC8 byteString; |
|
5279 byteString.Set( GetByteString() ); |
|
5280 iMmsHeaders->SetMessageIdL( byteString ); |
|
5281 #ifndef _NO_MMSS_LOGGING_ |
|
5282 HBufC16* buffer = NULL; |
|
5283 buffer = HBufC16::NewLC( byteString.Length() ); |
|
5284 buffer->Des().Copy( byteString ); |
|
5285 // we cannot log indefinitely long strings. |
|
5286 // We get this long strings only if the message is corrupted. |
|
5287 TPtrC dummy; |
|
5288 dummy.Set( buffer->Des().Left( KMmsMaxLogStringLength ) ); |
|
5289 TMmsLogger::Log( _L("- Message Id: %S"), &dummy ); |
|
5290 CleanupStack::PopAndDestroy( buffer ); |
|
5291 #endif |
|
5292 } |
|
5293 |
|
5294 // --------------------------------------------------------- |
|
5295 // |
|
5296 // --------------------------------------------------------- |
|
5297 void CMmsDecode::DecodeMessageType() |
|
5298 { |
|
5299 TUint8 byte; |
|
5300 TUint temp; |
|
5301 byte = GetWellKnownFieldValueOrSkip(); |
|
5302 temp = byte; |
|
5303 iMmsHeaders->SetMessageType( temp ); |
|
5304 #ifndef _NO_MMSS_LOGGING_ |
|
5305 TMmsLogger::Log( _L("- MessageType:") ); |
|
5306 switch ( temp ) |
|
5307 { |
|
5308 case KMmsMessageTypeMSendReq: |
|
5309 TMmsLogger::Log( _L("-- send-req") ); |
|
5310 break; |
|
5311 case KMmsMessageTypeMSendConf: |
|
5312 TMmsLogger::Log( _L("-- send-conf") ); |
|
5313 break; |
|
5314 case KMmsMessageTypeMNotificationInd: |
|
5315 TMmsLogger::Log( _L("-- notification-ind") ); |
|
5316 break; |
|
5317 case KMmsMessageTypeMNotifyRespInd: |
|
5318 TMmsLogger::Log( _L("-- notifyresp-ind") ); |
|
5319 break; |
|
5320 case KMmsMessageTypeMRetrieveConf: |
|
5321 TMmsLogger::Log( _L("-- retrieve-conf") ); |
|
5322 break; |
|
5323 case KMmsMessageTypeAcknowledgeInd: |
|
5324 TMmsLogger::Log( _L("-- acknowledge-ind") ); |
|
5325 break; |
|
5326 case KMmsMessageTypeDeliveryInd: |
|
5327 TMmsLogger::Log( _L("-- delivery-ind") ); |
|
5328 break; |
|
5329 case KMmsMessageTypeReadRecInd: |
|
5330 TMmsLogger::Log( _L("-- read-rec-ind") ); |
|
5331 break; |
|
5332 case KMmsMessageTypeReadOrigInd: |
|
5333 TMmsLogger::Log( _L("-- read-orig-ind") ); |
|
5334 break; |
|
5335 case KMmsMessageTypeForwardReq: |
|
5336 TMmsLogger::Log( _L("-- forward-req") ); |
|
5337 break; |
|
5338 case KMmsMessageTypeForwardConf: |
|
5339 TMmsLogger::Log( _L("-- forward-conf") ); |
|
5340 break; |
|
5341 case KMmsMessageTypeMboxStoreReq: |
|
5342 TMmsLogger::Log( _L("-- m-mbox-store-req") ); |
|
5343 break; |
|
5344 case KMmsMessageTypeMboxStoreConf: |
|
5345 TMmsLogger::Log( _L("-- m-mbox-store-conf") ); |
|
5346 break; |
|
5347 case KMmsMessageTypeMboxViewReq: |
|
5348 TMmsLogger::Log( _L("-- m-mbox-view-req") ); |
|
5349 break; |
|
5350 case KMmsMessageTypeMboxViewConf: |
|
5351 TMmsLogger::Log( _L("-- m-mbox-view-conf") ); |
|
5352 break; |
|
5353 case KMmsMessageTypeMBoxUploadReq: |
|
5354 TMmsLogger::Log( _L("-- m-mbox-upload-req") ); |
|
5355 break; |
|
5356 case KMmsMessageTypeMBoxUploadConf: |
|
5357 TMmsLogger::Log( _L("-- m-mbox-upload-conf") ); |
|
5358 break; |
|
5359 case KMmsMessageTypeMBoxDeleteReq: |
|
5360 TMmsLogger::Log( _L("-- m-mbox-delete-req") ); |
|
5361 break; |
|
5362 case KMmsMessageTypeMBoxDeleteConf: |
|
5363 TMmsLogger::Log( _L("-- m-mbox-delete-conf") ); |
|
5364 break; |
|
5365 case KMmsMessageTypeMBoxDescr: |
|
5366 TMmsLogger::Log( _L("-- m-mbox-descr") ); |
|
5367 break; |
|
5368 case KMmsMessageTypeDeleteReq: |
|
5369 TMmsLogger::Log( _L("-- m-delete-req") ); |
|
5370 break; |
|
5371 case KMmsMessageTypeDeleteConf: |
|
5372 TMmsLogger::Log( _L("-- m-delete-conf") ); |
|
5373 break; |
|
5374 case KMmsMessageTypeCancelReq: |
|
5375 TMmsLogger::Log( _L("-- m-cancel-req") ); |
|
5376 break; |
|
5377 case KMmsMessageTypeCancelConf: |
|
5378 TMmsLogger::Log( _L("-- m-cancel-conf") ); |
|
5379 break; |
|
5380 default: |
|
5381 TMmsLogger::Log( KLogUnknown, temp ); |
|
5382 break; |
|
5383 } |
|
5384 #endif |
|
5385 } |
|
5386 |
|
5387 // --------------------------------------------------------- |
|
5388 // |
|
5389 // --------------------------------------------------------- |
|
5390 void CMmsDecode::DecodeMmsVersion() |
|
5391 { |
|
5392 TUint8 byte; |
|
5393 byte = GetWellKnownFieldValueOrSkip(); |
|
5394 byte &= KMms0x7F; |
|
5395 // if version major number is greater than 1, |
|
5396 // we may not be compatible any more. |
|
5397 // We save the version number, and check later |
|
5398 // what we should do about it. |
|
5399 iMmsHeaders->SetMmsVersion( byte ); |
|
5400 #ifndef _NO_MMSS_LOGGING_ |
|
5401 // log version number always - even when decode logging is off |
|
5402 TUint high = ( byte & KMms0x7F ) >> KMmsHalfByteShift; |
|
5403 TUint low = byte & KMms0x0F; |
|
5404 TMmsLogger::Log( _L("- MMS version: %d.%d"), high, low ); |
|
5405 #endif |
|
5406 } |
|
5407 |
|
5408 // --------------------------------------------------------- |
|
5409 // |
|
5410 // --------------------------------------------------------- |
|
5411 void CMmsDecode::DecodeMessageSize() |
|
5412 { |
|
5413 TUint32 size = 0; |
|
5414 size = GetLongOrShortInteger(); |
|
5415 iMmsHeaders->SetMessageSize( size ); |
|
5416 #ifndef _NO_MMSS_LOGGING_ |
|
5417 if ( iError != KErrTooBig ) |
|
5418 { |
|
5419 TMmsLogger::Log( _L("- Message Size: %d"), size ); |
|
5420 } |
|
5421 else |
|
5422 { |
|
5423 TMmsLogger::Log( _L("- Message Size bigger than maxint") ); |
|
5424 } |
|
5425 #endif |
|
5426 } |
|
5427 |
|
5428 // --------------------------------------------------------- |
|
5429 // |
|
5430 // --------------------------------------------------------- |
|
5431 void CMmsDecode::DecodePriority() |
|
5432 { |
|
5433 TUint8 byte; |
|
5434 byte = GetWellKnownFieldValueOrSkip(); |
|
5435 TUint temp; |
|
5436 temp = byte; |
|
5437 iMmsHeaders->SetMessagePriority( temp ); |
|
5438 #ifndef _NO_MMSS_LOGGING_ |
|
5439 TMmsLogger::Log( _L("- Priority:") ); |
|
5440 switch ( temp ) |
|
5441 { |
|
5442 case KMmsPriorityLow: |
|
5443 TMmsLogger::Log( _L("-- Low") ); |
|
5444 break; |
|
5445 case KMmsPriorityNormal: |
|
5446 TMmsLogger::Log( _L("-- Normal") ); |
|
5447 break; |
|
5448 case KMmsPriorityHigh: |
|
5449 TMmsLogger::Log( _L("-- High") ); |
|
5450 break; |
|
5451 default: |
|
5452 TMmsLogger::Log( KLogUnknown, temp ); |
|
5453 break; |
|
5454 } |
|
5455 #endif |
|
5456 } |
|
5457 |
|
5458 // --------------------------------------------------------- |
|
5459 // |
|
5460 // --------------------------------------------------------- |
|
5461 void CMmsDecode::DecodeReadReply() |
|
5462 { |
|
5463 TUint8 byte; |
|
5464 byte = GetWellKnownFieldValueOrSkip(); |
|
5465 TUint temp; |
|
5466 temp = byte; |
|
5467 iMmsHeaders->SetReadReply( temp ); |
|
5468 #ifndef _NO_MMSS_LOGGING_ |
|
5469 LogYesNo( _L("- Read Reply:"), temp ); |
|
5470 #endif |
|
5471 } |
|
5472 |
|
5473 // --------------------------------------------------------- |
|
5474 // |
|
5475 // --------------------------------------------------------- |
|
5476 void CMmsDecode::DecodeReportAllowed() |
|
5477 { |
|
5478 TUint8 byte; |
|
5479 byte = GetWellKnownFieldValueOrSkip(); |
|
5480 TUint temp; |
|
5481 temp = byte; |
|
5482 iMmsHeaders->SetReportAllowed( temp ); |
|
5483 #ifndef _NO_MMSS_LOGGING_ |
|
5484 LogYesNo( _L("- Report Allowed:"), temp ); |
|
5485 #endif |
|
5486 } |
|
5487 |
|
5488 // --------------------------------------------------------- |
|
5489 // |
|
5490 // --------------------------------------------------------- |
|
5491 #ifndef _NO_MMSS_LOGGING_ |
|
5492 void CMmsDecode::DecodeResponseStatusL( TInt aHeader ) |
|
5493 #else |
|
5494 void CMmsDecode::DecodeResponseStatusL( TInt /*aHeader*/ ) |
|
5495 #endif |
|
5496 { |
|
5497 TUint8 byte; |
|
5498 TUint temp; |
|
5499 if ( iMmsHeaders->MessageType() != KMmsMessageTypeMBoxDeleteConf ) |
|
5500 { |
|
5501 byte = GetWellKnownFieldValueOrSkip(); |
|
5502 temp = byte; |
|
5503 iMmsHeaders->SetResponseStatus( temp ); |
|
5504 } |
|
5505 else // KMmsMessageTypeMBoxDeleteConf has different format |
|
5506 { |
|
5507 TUint32 size = 0; |
|
5508 GetValueLength(); |
|
5509 size = GetLongOrShortInteger(); // this is actually index |
|
5510 byte = GetWellKnownFieldValueOrSkip(); |
|
5511 temp = byte; |
|
5512 iMmsHeaders->InsertDeleteStatusL( size, temp ); |
|
5513 #ifndef _NO_MMSS_LOGGING_ |
|
5514 TMmsLogger::Log( _L("- Response Status Index: %d"), size ); |
|
5515 #endif |
|
5516 } |
|
5517 #ifndef _NO_MMSS_LOGGING_ |
|
5518 if ( aHeader == KMmsAssignedResponseStatus ) |
|
5519 { |
|
5520 TMmsLogger::Log( _L("- Response Status:") ); |
|
5521 } |
|
5522 else |
|
5523 { |
|
5524 TMmsLogger::Log( _L("- Retrieve Status:") ); |
|
5525 } |
|
5526 switch ( temp ) |
|
5527 { |
|
5528 case KMmsStatusOk: |
|
5529 TMmsLogger::Log( _L("-- Ok") ); |
|
5530 break; |
|
5531 case KMmsErrorUnspecified: |
|
5532 TMmsLogger::Log( _L("-- ErrUnspecified") ); |
|
5533 break; |
|
5534 case KMmsErrorServiceDenied: |
|
5535 TMmsLogger::Log( _L("-- ErrServiceDenied") ); |
|
5536 break; |
|
5537 case KMmsErrorMessageFormatCorrupt: |
|
5538 TMmsLogger::Log( _L("-- ErrMessageFormatCorrupt") ); |
|
5539 break; |
|
5540 case KMmsErrorSendingAddressUnresolved: |
|
5541 TMmsLogger::Log( _L("-- ErrSendingAddressUnresolved") ); |
|
5542 break; |
|
5543 case KMmsErrorMessageNotFound: |
|
5544 TMmsLogger::Log( _L("-- ErrMessageNotFound") ); |
|
5545 break; |
|
5546 case KMmsErrorNetworkProblem: |
|
5547 TMmsLogger::Log( _L("-- ErrNetworkProblem") ); |
|
5548 break; |
|
5549 case KMmsErrorNoContentAccepted: |
|
5550 TMmsLogger::Log( _L("-- ErrNoContentAccepted") ); |
|
5551 break; |
|
5552 case KMmsErrorUnsupportedMessage: |
|
5553 TMmsLogger::Log( _L("-- ErrUnsupportedMessage") ); |
|
5554 break; |
|
5555 default: |
|
5556 if ( ( temp & KMmsErrorRangeMask ) == KMmsErrorTransient ) |
|
5557 { |
|
5558 TMmsLogger::Log( _L("-- Transient error %d"), temp ); |
|
5559 } |
|
5560 else if ( ( temp & KMmsErrorRangeMask ) == KMmsErrorPermanent ) |
|
5561 { |
|
5562 TMmsLogger::Log( _L("-- Permanent error %d"), temp ); |
|
5563 } |
|
5564 else |
|
5565 { |
|
5566 TMmsLogger::Log( KLogUnknown, temp ); |
|
5567 } |
|
5568 break; |
|
5569 } |
|
5570 #endif |
|
5571 } |
|
5572 |
|
5573 // --------------------------------------------------------- |
|
5574 // |
|
5575 // --------------------------------------------------------- |
|
5576 void CMmsDecode::DecodeResponseTextL( TInt aHeader ) |
|
5577 { |
|
5578 // The text may be response status text, retrieve status text |
|
5579 // or status text depending on which PDU we are decoding. |
|
5580 // Only one text string appears in each case, so we reuse the header |
|
5581 HBufC16* buffer = NULL; |
|
5582 if ( iMmsHeaders->MessageType() != KMmsMessageTypeMBoxDeleteConf ) |
|
5583 { |
|
5584 // both notes go to the same variable, as both can never be present |
|
5585 buffer = GetEncodedTextStringL(); |
|
5586 CleanupStack::PushL( buffer ); |
|
5587 iMmsHeaders->SetResponseTextL( buffer->Des() ); |
|
5588 } |
|
5589 else // KMmsMessageTypeMBoxDeleteConf has different format |
|
5590 { |
|
5591 GetValueLength(); |
|
5592 TUint32 index = 0; |
|
5593 index = GetLongOrShortInteger(); |
|
5594 buffer = GetEncodedTextStringL(); |
|
5595 CleanupStack::PushL( buffer ); |
|
5596 iMmsHeaders->InsertDeleteResponseTextL( index, buffer->Des() ); |
|
5597 #ifndef _NO_MMSS_LOGGING_ |
|
5598 TMmsLogger::Log( _L("- Response Text Index: %d"), index ); |
|
5599 #endif |
|
5600 } |
|
5601 #ifndef _NO_MMSS_LOGGING_ |
|
5602 switch ( aHeader ) |
|
5603 { |
|
5604 case KMmsAssignedResponseText: |
|
5605 TMmsLogger::Log( _L("- Response text:") ); |
|
5606 break; |
|
5607 case KMmsAssignedRetrieveText: |
|
5608 TMmsLogger::Log( _L("- Retrieve text:") ); |
|
5609 break; |
|
5610 case KMmsAssignedStatusText: |
|
5611 TMmsLogger::Log( _L("- Status text:") ); |
|
5612 break; |
|
5613 } |
|
5614 // we cannot log indefinitely long strings. |
|
5615 // We get this long strings only if the message is corrupted. |
|
5616 TPtrC dummy; |
|
5617 dummy.Set( buffer->Des().Left( KMmsMaxLogStringLength ) ); |
|
5618 TMmsLogger::Log( _L("%S"), &dummy ); |
|
5619 #endif |
|
5620 CleanupStack::PopAndDestroy( buffer ); |
|
5621 } |
|
5622 |
|
5623 // --------------------------------------------------------- |
|
5624 // |
|
5625 // --------------------------------------------------------- |
|
5626 void CMmsDecode::DecodeSenderVisibility() |
|
5627 { |
|
5628 TUint8 byte; |
|
5629 byte = GetWellKnownFieldValueOrSkip(); |
|
5630 TUint temp; |
|
5631 temp = byte; |
|
5632 iMmsHeaders->SetSenderVisibility( temp ); |
|
5633 #ifndef _NO_MMSS_LOGGING_ |
|
5634 TMmsLogger::Log( _L("- Sender Visibility:") ); |
|
5635 switch ( temp ) |
|
5636 { |
|
5637 case KMmsSenderHide: |
|
5638 TMmsLogger::Log( _L("-- Hide") ); |
|
5639 break; |
|
5640 case KMmsSenderShow: |
|
5641 TMmsLogger::Log( _L("-- Show") ); |
|
5642 break; |
|
5643 default: |
|
5644 TMmsLogger::Log( KLogUnknown, temp ); |
|
5645 break; |
|
5646 } |
|
5647 #endif |
|
5648 } |
|
5649 |
|
5650 // --------------------------------------------------------- |
|
5651 // |
|
5652 // --------------------------------------------------------- |
|
5653 void CMmsDecode::DecodeStatus() |
|
5654 { |
|
5655 TUint8 byte; |
|
5656 byte = GetWellKnownFieldValueOrSkip(); |
|
5657 TUint temp; |
|
5658 temp = byte; |
|
5659 iMmsHeaders->SetStatus( temp ); |
|
5660 #ifndef _NO_MMSS_LOGGING_ |
|
5661 TMmsLogger::Log( _L("- Status:") ); |
|
5662 switch ( temp ) |
|
5663 { |
|
5664 case KMmsMessageStatusExpired: |
|
5665 TMmsLogger::Log( _L("-- Expired") ); |
|
5666 break; |
|
5667 case KMmsMessageStatusRetrieved: |
|
5668 TMmsLogger::Log( _L("-- Retrieved") ); |
|
5669 break; |
|
5670 case KMmsMessageStatusRejected: |
|
5671 TMmsLogger::Log( _L("-- Rejected") ); |
|
5672 break; |
|
5673 case KMmsMessageStatusDeferred: |
|
5674 TMmsLogger::Log( _L("-- Deferred") ); |
|
5675 break; |
|
5676 case KMmsMessageStatusUnrecognized: |
|
5677 TMmsLogger::Log( _L("-- Unrecognized") ); |
|
5678 break; |
|
5679 case KMmsMessageStatusIndeterminate: |
|
5680 TMmsLogger::Log( _L("-- Indeterminate") ); |
|
5681 break; |
|
5682 case KMmsMessageStatusForwarded: |
|
5683 TMmsLogger::Log( _L("-- Forwarded") ); |
|
5684 break; |
|
5685 case KMmsMessageStatusUnreachable: |
|
5686 TMmsLogger::Log( _L("-- Unreachable") ); |
|
5687 break; |
|
5688 default: |
|
5689 TMmsLogger::Log( KLogUnknown, temp ); |
|
5690 break; |
|
5691 } |
|
5692 #endif |
|
5693 } |
|
5694 |
|
5695 // --------------------------------------------------------- |
|
5696 // |
|
5697 // --------------------------------------------------------- |
|
5698 void CMmsDecode::DecodeSubjectL() |
|
5699 { |
|
5700 HBufC16* buffer = NULL; |
|
5701 buffer = GetEncodedTextStringL(); |
|
5702 CleanupStack::PushL( buffer ); |
|
5703 // TMsvEntry.iDescription will be updated separately. |
|
5704 iMmsHeaders->SetSubjectL( buffer->Des()); |
|
5705 #ifndef _NO_MMSS_LOGGING_ |
|
5706 // we cannot log indefinitely long strings. |
|
5707 // We get this long strings only if the message is corrupted. |
|
5708 TPtrC dummy; |
|
5709 dummy.Set( buffer->Des().Left( KMmsMaxLogStringLength ) ); |
|
5710 TMmsLogger::Log( _L("- Subject: %S"), &dummy ); |
|
5711 #endif |
|
5712 CleanupStack::PopAndDestroy( buffer ); |
|
5713 } |
|
5714 |
|
5715 // --------------------------------------------------------- |
|
5716 // |
|
5717 // --------------------------------------------------------- |
|
5718 void CMmsDecode::DecodeTidL() |
|
5719 { |
|
5720 TPtrC8 byteString; |
|
5721 byteString.Set( GetByteString() ); |
|
5722 iMmsHeaders->SetTidL( byteString ); |
|
5723 #ifndef _NO_MMSS_LOGGING_ |
|
5724 HBufC16* buffer = NULL; |
|
5725 buffer = HBufC16::NewLC( byteString.Length() ); |
|
5726 buffer->Des().Copy( byteString ); |
|
5727 TPtrC dummy; |
|
5728 dummy.Set( buffer->Des() ); |
|
5729 // we cannot log indefinitely long strings. |
|
5730 // We get this long strings only if the message is corrupted. |
|
5731 dummy.Set( buffer->Des().Left( KMmsMaxLogStringLength ) ); |
|
5732 TMmsLogger::Log( _L("- Transaction Id: %S"), &dummy ); |
|
5733 CleanupStack::PopAndDestroy( buffer ); |
|
5734 #endif |
|
5735 } |
|
5736 |
|
5737 // --------------------------------------------------------- |
|
5738 // |
|
5739 // --------------------------------------------------------- |
|
5740 void CMmsDecode::DecodeContentTypeL() |
|
5741 { |
|
5742 // Now we must analyze the content type in order to |
|
5743 // handle the body correctly. |
|
5744 // The body may be a multipart, or a single part. |
|
5745 // The subroutine will set the number of Attachments. |
|
5746 // For a monoblock body the number of attachments will be 1. |
|
5747 iMultipartType = GetMultipartContentTypeL(); |
|
5748 // save the multipart type in case we must later make decisions |
|
5749 // about the multipart/alternative type |
|
5750 iMmsHeaders->SetMultipartType( iMultipartType ); |
|
5751 iLastHeader = ETrue; // Content type is always the last header |
|
5752 #ifndef _NO_MMSS_LOGGING_ |
|
5753 TPtrC8 byteString; |
|
5754 HBufC16* buffer = NULL; |
|
5755 TPtrC dummy; |
|
5756 if ( iMultipartType != 0 ) |
|
5757 { |
|
5758 if ( iMultipartType <= KNumberContentTypes ) |
|
5759 { |
|
5760 byteString.Set( KContentTypeTable[ iMultipartType ] ); |
|
5761 } |
|
5762 else if ( iMultipartType == KMmsAssignedApplicationVndWapMultipartReport ) |
|
5763 { |
|
5764 byteString.Set( KMmsWapMultipartReport ); |
|
5765 } |
|
5766 else |
|
5767 { |
|
5768 byteString.Set( KContentTypeTable[ KNumberContentTypes ] ); |
|
5769 } |
|
5770 buffer = HBufC16::NewLC( byteString.Length() ); |
|
5771 // we cannot log indefinitely long strings. |
|
5772 // We get this long strings only if the message is corrupted. |
|
5773 buffer->Des().Copy( byteString ); |
|
5774 // no entries from our table are more than 200 bytes long. |
|
5775 dummy.Set( buffer->Des() ); |
|
5776 TMmsLogger::Log( _L("- Content Type: %S"), &dummy ); |
|
5777 CleanupStack::PopAndDestroy( buffer ); |
|
5778 if ( iMultipartRootType.Length() > 0 ) |
|
5779 { |
|
5780 buffer = HBufC16::NewLC( iMultipartRootType.Length() ); |
|
5781 buffer->Des().Copy( iMultipartRootType ); |
|
5782 // we cannot log indefinitely long strings. |
|
5783 // We get this long strings only if the message is corrupted. |
|
5784 dummy.Set( buffer->Des().Left( KMmsMaxLogStringLength ) ); |
|
5785 TMmsLogger::Log( _L("- Root content type: %S"), &dummy ); |
|
5786 CleanupStack::PopAndDestroy( buffer ); |
|
5787 } |
|
5788 if ( iRootContentId.Length() > 0 ) |
|
5789 { |
|
5790 buffer = HBufC16::NewLC( iRootContentId.Length() ); |
|
5791 buffer->Des().Copy( iRootContentId ); |
|
5792 // we cannot log indefinitely long strings. |
|
5793 // We get this long strings only if the message is corrupted. |
|
5794 dummy.Set( buffer->Des().Left( KMmsMaxLogStringLength ) ); |
|
5795 TMmsLogger::Log( _L("- Root content id: %S"), &dummy ); |
|
5796 CleanupStack::PopAndDestroy( buffer ); |
|
5797 } |
|
5798 } |
|
5799 TMmsLogger::Log( _L("- Number of attachments: %d"), iNumberOfAttachments ); |
|
5800 #endif |
|
5801 } |
|
5802 |
|
5803 // --------------------------------------------------------- |
|
5804 // |
|
5805 // --------------------------------------------------------- |
|
5806 void CMmsDecode::DecodeReadStatus() |
|
5807 { |
|
5808 TUint8 byte; |
|
5809 byte = GetWellKnownFieldValueOrSkip(); |
|
5810 TUint temp; |
|
5811 temp = byte; |
|
5812 iMmsHeaders->SetReadStatus( temp ); |
|
5813 #ifndef _NO_MMSS_LOGGING_ |
|
5814 TMmsLogger::Log( _L("- ReadStatus:") ); |
|
5815 switch ( temp ) |
|
5816 { |
|
5817 case KMmsReadStatusRead: |
|
5818 TMmsLogger::Log( _L("-- Read") ); |
|
5819 break; |
|
5820 case KMmsReadStatusDeletedWithoutBeingRead: |
|
5821 TMmsLogger::Log( _L("-- Deleted unread") ); |
|
5822 break; |
|
5823 default: |
|
5824 TMmsLogger::Log( KLogUnknown, temp ); |
|
5825 break; |
|
5826 } |
|
5827 #endif |
|
5828 } |
|
5829 |
|
5830 // --------------------------------------------------------- |
|
5831 // |
|
5832 // --------------------------------------------------------- |
|
5833 void CMmsDecode::DecodeReplyCharging() |
|
5834 { |
|
5835 TUint8 byte; |
|
5836 byte = GetWellKnownFieldValueOrSkip(); |
|
5837 TUint temp; |
|
5838 temp = byte; |
|
5839 iMmsHeaders->SetReplyCharging( temp ); |
|
5840 #ifndef _NO_MMSS_LOGGING_ |
|
5841 TMmsLogger::Log( _L("- ReplyCharging:") ); |
|
5842 switch ( temp ) |
|
5843 { |
|
5844 case KMmsReplyChargingRequested: |
|
5845 TMmsLogger::Log( _L("-- Requested") ); |
|
5846 break; |
|
5847 case KMmsReplyChargingRequestedTextOnly: |
|
5848 TMmsLogger::Log( _L("-- Requested text only") ); |
|
5849 break; |
|
5850 case KMmsReplyChargingAccepted: |
|
5851 TMmsLogger::Log( _L("-- Accepted") ); |
|
5852 break; |
|
5853 case KMmsReplyChargingAcceptedTextOnly: |
|
5854 TMmsLogger::Log( _L("-- Accepted text only") ); |
|
5855 break; |
|
5856 default: |
|
5857 TMmsLogger::Log( KLogUnknown, temp ); |
|
5858 break; |
|
5859 } |
|
5860 #endif |
|
5861 } |
|
5862 |
|
5863 // --------------------------------------------------------- |
|
5864 // |
|
5865 // --------------------------------------------------------- |
|
5866 void CMmsDecode::DecodeReplyChargingDeadlineL() |
|
5867 { |
|
5868 TUint8 byte; |
|
5869 TInt64 date; |
|
5870 byte = GetRelativeOrAbsoluteTime( date ); |
|
5871 if ( byte == KMmsRelativeToken ) |
|
5872 { |
|
5873 iMmsHeaders->SetReplyChargingInterval( I64LOW( date ) ); |
|
5874 #ifndef _NO_MMSS_LOGGING_ |
|
5875 TMmsLogger::Log( _L("- Reply charging interval: %d s"), I64LOW( date ) ); |
|
5876 #endif |
|
5877 } |
|
5878 if ( byte == KMmsAbsoluteToken ) |
|
5879 { |
|
5880 // keep as universal time, don't convert to local time |
|
5881 iMmsHeaders->SetReplyChargingDate( date ); |
|
5882 #ifndef _NO_MMSS_LOGGING_ |
|
5883 TMmsLogger::Log( _L("- Reply charging date, absolute:") ); |
|
5884 LogDateL( date ); |
|
5885 #endif |
|
5886 } |
|
5887 } |
|
5888 |
|
5889 // --------------------------------------------------------- |
|
5890 // |
|
5891 // --------------------------------------------------------- |
|
5892 void CMmsDecode::DecodeReplyChargingIdL() |
|
5893 { |
|
5894 TPtrC8 byteString; |
|
5895 byteString.Set( GetByteString() ); |
|
5896 iMmsHeaders->SetReplyChargingIdL( byteString ); |
|
5897 #ifndef _NO_MMSS_LOGGING_ |
|
5898 HBufC16* buffer = NULL; |
|
5899 buffer = HBufC16::NewLC( byteString.Length() ); |
|
5900 buffer->Des().Copy( byteString ); |
|
5901 // we cannot log indefinitely long strings. |
|
5902 // We get this long strings only if the message is corrupted. |
|
5903 TPtrC dummy; |
|
5904 dummy.Set( buffer->Des().Left( KMmsMaxLogStringLength ) ); |
|
5905 TMmsLogger::Log( _L("- Reply Charging Id: %S"), &dummy ); |
|
5906 CleanupStack::PopAndDestroy( buffer ); |
|
5907 #endif |
|
5908 } |
|
5909 |
|
5910 // --------------------------------------------------------- |
|
5911 // |
|
5912 // --------------------------------------------------------- |
|
5913 void CMmsDecode::DecodeReplyChargingSize() |
|
5914 { |
|
5915 TUint32 size = 0; |
|
5916 size = GetLongOrShortInteger(); |
|
5917 iMmsHeaders->SetReplyChargingSize( size ); |
|
5918 #ifndef _NO_MMSS_LOGGING_ |
|
5919 if ( iError != KErrTooBig ) |
|
5920 { |
|
5921 TMmsLogger::Log( _L("- Reply charging Size: %d"), size ); |
|
5922 } |
|
5923 else |
|
5924 { |
|
5925 TMmsLogger::Log( _L("- Reply charging Size bigger than: %d"), |
|
5926 TInt64 (0xffffffff) ); |
|
5927 } |
|
5928 #endif |
|
5929 } |
|
5930 |
|
5931 // --------------------------------------------------------- |
|
5932 // |
|
5933 // --------------------------------------------------------- |
|
5934 void CMmsDecode::DecodePreviousSenderL() |
|
5935 { |
|
5936 GetValueLength(); // we don't need this |
|
5937 TUint32 size = 0; |
|
5938 size = GetLongOrShortInteger(); // This is actually index |
|
5939 HBufC16* buffer = NULL; |
|
5940 buffer = DecodeAddressL(); |
|
5941 CleanupStack::PushL( buffer ); |
|
5942 // If message is corrupted, the result may be garbage, but we do our best |
|
5943 iMmsHeaders->InsertPreviouslySentByL( size, buffer->Des() ); |
|
5944 #ifndef _NO_MMSS_LOGGING_ |
|
5945 // we cannot log indefinitely long strings. |
|
5946 // We get this long strings only if the message is corrupted. |
|
5947 TPtrC dummy; |
|
5948 dummy.Set( buffer->Des().Left( KMmsMaxLogStringLength ) ); |
|
5949 TMmsLogger::Log( _L("- Prevously sent by: %S, order # %d"), &dummy, size ); |
|
5950 #endif |
|
5951 CleanupStack::PopAndDestroy( buffer ); |
|
5952 } |
|
5953 |
|
5954 // --------------------------------------------------------- |
|
5955 // |
|
5956 // --------------------------------------------------------- |
|
5957 void CMmsDecode::DecodePreviouslySentDateL() |
|
5958 { |
|
5959 GetValueLength(); // we don't need this |
|
5960 TUint32 size = 0; |
|
5961 size = GetLongOrShortInteger(); |
|
5962 TInt64 date; |
|
5963 date = GetVeryLongInteger(); |
|
5964 TUint8 byte; |
|
5965 if ( iError == KErrTooBig ) |
|
5966 { |
|
5967 // we get here only if we have at least one byte to read |
|
5968 iDecodeBuffer->Read(iPosition, &byte, 1); |
|
5969 iPosition++; |
|
5970 // skip rest of field if too long |
|
5971 iPosition += byte; |
|
5972 // If this is too big, we just ignore it. It is no legal date. |
|
5973 date = 0; |
|
5974 iError = KErrNone; |
|
5975 } |
|
5976 // We insert the result no matter what |
|
5977 iMmsHeaders->InsertPreviouslySentDateL( size, date ); |
|
5978 #ifndef _NO_MMSS_LOGGING_ |
|
5979 TMmsLogger::Log( _L("- Previously sent date: (order # %d)"), size ); |
|
5980 LogDateL( date ); |
|
5981 #endif |
|
5982 } |
|
5983 |
|
5984 // --------------------------------------------------------- |
|
5985 // |
|
5986 // --------------------------------------------------------- |
|
5987 void CMmsDecode::DecodeStoreHeaderL() |
|
5988 { |
|
5989 TUint8 byte; |
|
5990 byte = GetWellKnownFieldValueOrSkip(); |
|
5991 TUint temp; |
|
5992 temp = byte; |
|
5993 iMmsHeaders->MMBoxMessageHeadersL().SetMmsStore( temp ); |
|
5994 #ifndef _NO_MMSS_LOGGING_ |
|
5995 LogYesNo( _L("- Store to MMBox:"), temp ); |
|
5996 #endif |
|
5997 } |
|
5998 |
|
5999 // --------------------------------------------------------- |
|
6000 // |
|
6001 // --------------------------------------------------------- |
|
6002 void CMmsDecode::DecodeMMBoxStateL() |
|
6003 { |
|
6004 TUint8 byte; |
|
6005 byte = GetWellKnownFieldValueOrSkip(); |
|
6006 TUint temp; |
|
6007 temp = byte; |
|
6008 if ( iMmsHeaders->MessageType() != KMmsMessageTypeMboxViewReq && |
|
6009 iMmsHeaders->MessageType() != KMmsMessageTypeMboxViewConf ) |
|
6010 { |
|
6011 iMmsHeaders->MMBoxMessageHeadersL().SetMMState( temp ); |
|
6012 } |
|
6013 else |
|
6014 { |
|
6015 // For the MMBox view PDU types we must put the states into |
|
6016 // an array as they are used for filtering, and there may be |
|
6017 // more than one state headers |
|
6018 iMmsHeaders->MMBoxViewHeadersL().MMStateArray().InsertInOrder( temp ); |
|
6019 } |
|
6020 #ifndef _NO_MMSS_LOGGING_ |
|
6021 TMmsLogger::Log( _L("- State in MMBox:") ); |
|
6022 switch ( temp ) |
|
6023 { |
|
6024 case KMmsDraft: |
|
6025 TMmsLogger::Log( _L("-- Draft") ); |
|
6026 break; |
|
6027 case KMmsSent: |
|
6028 TMmsLogger::Log( _L("-- Sent") ); |
|
6029 break; |
|
6030 case KMmsNew: |
|
6031 TMmsLogger::Log( _L("-- New") ); |
|
6032 break; |
|
6033 case KMmsRetrieved: |
|
6034 TMmsLogger::Log( _L("-- Retrieved") ); |
|
6035 break; |
|
6036 case KMmsForwarded: |
|
6037 TMmsLogger::Log( _L("-- Forwarded") ); |
|
6038 break; |
|
6039 default: |
|
6040 TMmsLogger::Log( KLogUnknown, temp ); |
|
6041 break; |
|
6042 } |
|
6043 #endif |
|
6044 } |
|
6045 |
|
6046 // --------------------------------------------------------- |
|
6047 // |
|
6048 // --------------------------------------------------------- |
|
6049 void CMmsDecode::DecodeMMBoxStoreStatusL() |
|
6050 { |
|
6051 TUint8 byte; |
|
6052 byte = GetWellKnownFieldValueOrSkip(); |
|
6053 TUint temp; |
|
6054 temp = byte; |
|
6055 iMmsHeaders->MMBoxMessageHeadersL().SetMmsStoreStatus( temp ); |
|
6056 #ifndef _NO_MMSS_LOGGING_ |
|
6057 TMmsLogger::Log( _L("- MMBox Store Status:") ); |
|
6058 switch ( temp ) |
|
6059 { |
|
6060 case KMmsStatusOk: |
|
6061 TMmsLogger::Log( _L("-- Ok") ); |
|
6062 break; |
|
6063 default: |
|
6064 if ( ( temp & KMmsErrorRangeMask ) == KMmsErrorTransient ) |
|
6065 { |
|
6066 TMmsLogger::Log( _L("-- Transient error %d"), temp ); |
|
6067 } |
|
6068 else if ( ( temp & KMmsErrorRangeMask ) == KMmsErrorPermanent ) |
|
6069 { |
|
6070 TMmsLogger::Log( _L("-- Permanent error %d"), temp ); |
|
6071 } |
|
6072 else |
|
6073 { |
|
6074 TMmsLogger::Log( KLogUnknown, temp ); |
|
6075 } |
|
6076 break; |
|
6077 } |
|
6078 #endif |
|
6079 } |
|
6080 |
|
6081 // --------------------------------------------------------- |
|
6082 // |
|
6083 // --------------------------------------------------------- |
|
6084 void CMmsDecode::DecodeMMBoxStoreStatusTextL() |
|
6085 { |
|
6086 HBufC16* buffer = NULL; |
|
6087 buffer = GetEncodedTextStringL(); |
|
6088 CleanupStack::PushL( buffer ); |
|
6089 iMmsHeaders->MMBoxMessageHeadersL().SetMmsStoreStatusTextL( buffer->Des() ); |
|
6090 #ifndef _NO_MMSS_LOGGING_ |
|
6091 // we cannot log indefinitely long strings. |
|
6092 // We get this long strings only if the message is corrupted. |
|
6093 TPtrC dummy; |
|
6094 dummy.Set( buffer->Des().Left( KMmsMaxLogStringLength ) ); |
|
6095 TMmsLogger::Log( _L("- MMBox Store Status Text: %S"), &dummy ); |
|
6096 #endif |
|
6097 CleanupStack::PopAndDestroy( buffer ); |
|
6098 } |
|
6099 |
|
6100 // --------------------------------------------------------- |
|
6101 // |
|
6102 // --------------------------------------------------------- |
|
6103 void CMmsDecode::DecodeStoredInMMBoxHeaderL() |
|
6104 { |
|
6105 TUint8 byte; |
|
6106 byte = GetWellKnownFieldValueOrSkip(); |
|
6107 TUint temp; |
|
6108 temp = byte; |
|
6109 iMmsHeaders->MMBoxMessageHeadersL().SetMmsStored( temp ); |
|
6110 #ifndef _NO_MMSS_LOGGING_ |
|
6111 LogYesNo( _L("- Stored to MMBox:"), temp ); |
|
6112 #endif |
|
6113 } |
|
6114 |
|
6115 // --------------------------------------------------------- |
|
6116 // |
|
6117 // --------------------------------------------------------- |
|
6118 void CMmsDecode::DecodeAttributesHeaderL() |
|
6119 { |
|
6120 TUint8 byte; |
|
6121 byte = GetWellKnownFieldValueOrSkip(); |
|
6122 TUint temp; |
|
6123 temp = byte; |
|
6124 User::LeaveIfError(iMmsHeaders->MMBoxViewHeadersL().AttributeArray().Append( temp )); |
|
6125 #ifndef _NO_MMSS_LOGGING_ |
|
6126 TMmsLogger::Log( _L("- MMBox Attribute: %d"), temp ); |
|
6127 #endif |
|
6128 } |
|
6129 |
|
6130 // --------------------------------------------------------- |
|
6131 // |
|
6132 // --------------------------------------------------------- |
|
6133 void CMmsDecode::DecodeTotalsL() |
|
6134 { |
|
6135 TUint8 byte; |
|
6136 byte = GetWellKnownFieldValueOrSkip(); |
|
6137 TUint temp; |
|
6138 temp = byte; |
|
6139 iMmsHeaders->MMBoxViewHeadersL().SetMmsTotals( temp ); |
|
6140 #ifndef _NO_MMSS_LOGGING_ |
|
6141 LogYesNo( _L("- MMBox Totals requested:"), temp ); |
|
6142 #endif |
|
6143 } |
|
6144 |
|
6145 // --------------------------------------------------------- |
|
6146 // |
|
6147 // --------------------------------------------------------- |
|
6148 void CMmsDecode::DecodeMboxTotalsL() |
|
6149 { |
|
6150 GetValueLength(); // we don't need this |
|
6151 // get message quota or size quota |
|
6152 TUint8 byte; |
|
6153 byte = GetWellKnownFieldValueOrSkip(); |
|
6154 // actual value of the quota |
|
6155 // We only get normal integer (not a 64 bit integer) as a 32 bit integer |
|
6156 // will give quota 4294967295 bytes or messages (which should be plenty) |
|
6157 TUint32 size = 0; |
|
6158 size = GetLongOrShortInteger(); |
|
6159 // save message quota |
|
6160 if ( byte == KMmsMessageCountToken ) |
|
6161 { |
|
6162 iMmsHeaders->MMBoxViewHeadersL().SetMMBoxTotalNumber( size ); |
|
6163 #ifndef _NO_MMSS_LOGGING_ |
|
6164 TMmsLogger::Log( _L("- MMBox total: %d messages"), size ); |
|
6165 #endif |
|
6166 } |
|
6167 else if ( byte == KMmsMessageSizeToken ) |
|
6168 { |
|
6169 iMmsHeaders->MMBoxViewHeadersL().SetMMBoxTotalSize( size ); |
|
6170 #ifndef _NO_MMSS_LOGGING_ |
|
6171 TMmsLogger::Log( _L("- MMBox total: %d bytes"), size ); |
|
6172 #endif |
|
6173 } |
|
6174 // illegal token value is ignored. |
|
6175 else |
|
6176 { |
|
6177 #ifndef _NO_MMSS_LOGGING_ |
|
6178 TUint temp; |
|
6179 temp = byte; |
|
6180 TMmsLogger::Log( _L("- MMBox total: illegal token %d"), temp ); |
|
6181 #endif |
|
6182 } |
|
6183 } |
|
6184 |
|
6185 // --------------------------------------------------------- |
|
6186 // |
|
6187 // --------------------------------------------------------- |
|
6188 void CMmsDecode::DecodeQuotaHeaderL() |
|
6189 { |
|
6190 TUint8 byte; |
|
6191 byte = GetWellKnownFieldValueOrSkip(); |
|
6192 TUint temp; |
|
6193 temp = byte; |
|
6194 iMmsHeaders->MMBoxViewHeadersL().SetMmsQuotas( temp ); |
|
6195 #ifndef _NO_MMSS_LOGGING_ |
|
6196 LogYesNo( _L("- MMBox Quotas requested:"), temp ); |
|
6197 #endif |
|
6198 } |
|
6199 |
|
6200 // --------------------------------------------------------- |
|
6201 // |
|
6202 // --------------------------------------------------------- |
|
6203 void CMmsDecode::DecodeMBoxQuotasL() |
|
6204 { |
|
6205 TUint8 byte; |
|
6206 GetValueLength(); // we don't need this |
|
6207 // get message quota or size quota |
|
6208 byte = GetWellKnownFieldValueOrSkip(); |
|
6209 // actual value of the quota |
|
6210 // We only get normal integer (not a 64 bit integer) as a 32 bit integer |
|
6211 // will give quota 4294967295 bytes or messages (which should be plenty) |
|
6212 TUint32 size = 0; |
|
6213 size = GetLongOrShortInteger(); |
|
6214 // save message quota |
|
6215 if ( byte == KMmsMessageCountToken ) |
|
6216 { |
|
6217 iMmsHeaders->MMBoxViewHeadersL().SetMMBoxQuotaNumber( size ); |
|
6218 #ifndef _NO_MMSS_LOGGING_ |
|
6219 TMmsLogger::Log( _L("- MMBox quota: %d messages"), size ); |
|
6220 #endif |
|
6221 } |
|
6222 else if ( byte == KMmsMessageSizeToken ) |
|
6223 { |
|
6224 iMmsHeaders->MMBoxViewHeadersL().SetMMBoxQuotaSize( size ); |
|
6225 #ifndef _NO_MMSS_LOGGING_ |
|
6226 TMmsLogger::Log( _L("- MMBox quota: %d bytes"), size ); |
|
6227 #endif |
|
6228 } |
|
6229 // illegal token value is ignored. |
|
6230 else |
|
6231 { |
|
6232 #ifndef _NO_MMSS_LOGGING_ |
|
6233 TUint temp; |
|
6234 temp = byte; |
|
6235 TMmsLogger::Log( _L("- MMBox quota: illegal token %d"), temp ); |
|
6236 #endif |
|
6237 } |
|
6238 } |
|
6239 |
|
6240 // --------------------------------------------------------- |
|
6241 // |
|
6242 // --------------------------------------------------------- |
|
6243 void CMmsDecode::DecodeMessageCountL() |
|
6244 { |
|
6245 TUint32 size = 0; |
|
6246 size = GetLongOrShortInteger(); |
|
6247 iMmsHeaders->MMBoxViewHeadersL().SetMmsMessageCount( size ); |
|
6248 #ifndef _NO_MMSS_LOGGING_ |
|
6249 TMmsLogger::Log( _L("- Message count: %d"), size ); |
|
6250 #endif |
|
6251 } |
|
6252 |
|
6253 // --------------------------------------------------------- |
|
6254 // |
|
6255 // --------------------------------------------------------- |
|
6256 void CMmsDecode::DecodeStartInMMBoxViewL() |
|
6257 { |
|
6258 TUint32 size = 0; |
|
6259 size = GetLongOrShortInteger(); |
|
6260 iMmsHeaders->MMBoxViewHeadersL().SetMmsStart( size ); |
|
6261 #ifndef _NO_MMSS_LOGGING_ |
|
6262 TMmsLogger::Log( _L("- Start of messages: %d"), size ); |
|
6263 #endif |
|
6264 } |
|
6265 |
|
6266 |
|
6267 // --------------------------------------------------------- |
|
6268 // |
|
6269 // --------------------------------------------------------- |
|
6270 void CMmsDecode::DecodeDistributionIndicator() |
|
6271 { |
|
6272 TUint8 byte; |
|
6273 byte = GetWellKnownFieldValueOrSkip(); |
|
6274 TUint temp; |
|
6275 temp = byte; |
|
6276 iMmsHeaders->SetDistributionIndicator( temp ); |
|
6277 #ifndef _NO_MMSS_LOGGING_ |
|
6278 LogYesNo( _L("- May be distributed further:"), temp ); |
|
6279 #endif |
|
6280 } |
|
6281 |
|
6282 // --------------------------------------------------------- |
|
6283 // |
|
6284 // --------------------------------------------------------- |
|
6285 void CMmsDecode::DecodeElementDescriptorL() |
|
6286 { |
|
6287 #ifndef _NO_MMSS_LOGGING_ |
|
6288 TPtrC dummy; |
|
6289 #endif |
|
6290 TUint32 size = 0; |
|
6291 // remember where we are |
|
6292 size = GetValueLength(); |
|
6293 if ( size > iLength - iPosition ) |
|
6294 { |
|
6295 // If the message is corrupted and indicates incorrect length, |
|
6296 // make sure we don't read beyond the buffer |
|
6297 // We don't declare that the message is corrupted because of this. |
|
6298 // We just read what we can, we don't use this header anyway. |
|
6299 // If there is data following a corrupted header, it will be lost. |
|
6300 size = iLength - iPosition; |
|
6301 } |
|
6302 TUint endPosition = iPosition + size; |
|
6303 HBufC16* buffer = NULL; |
|
6304 buffer = GetSimpleTextStringL(); // I hope this is correct. |
|
6305 CleanupStack::PushL( buffer ); |
|
6306 iMmsHeaders->ElementDescriptorL().SetContentReferenceL( buffer->Des() ); |
|
6307 #ifndef _NO_MMSS_LOGGING_ |
|
6308 dummy.Set( buffer->Des().Left( KMmsMaxLogStringLength ) ); |
|
6309 TMmsLogger::Log( _L("- Content reference: %S"), &dummy ); |
|
6310 #endif |
|
6311 CleanupStack::PopAndDestroy( buffer ); |
|
6312 buffer = NULL; |
|
6313 TUint8 byte; |
|
6314 while ( iPosition < endPosition ) |
|
6315 { |
|
6316 byte = GetWellKnownFieldValueOrSkip(); |
|
6317 if ( byte != KMmsAssignedTopLevelContentType ) |
|
6318 { |
|
6319 // Unknown parameter, ignore |
|
6320 SkipFieldValue(); |
|
6321 } |
|
6322 else |
|
6323 { |
|
6324 // the value of the parameter is content-type of the top-level message content |
|
6325 TPtrC8 contType = GetContentTypeL(); |
|
6326 iMmsHeaders->ElementDescriptorL().SetContentTypeL( contType ); |
|
6327 #ifndef _NO_MMSS_LOGGING_ |
|
6328 buffer = HBufC16::NewL( contType.Length() ); |
|
6329 CleanupStack::PushL( buffer ); |
|
6330 buffer->Des().Copy( contType ); |
|
6331 dummy.Set( buffer->Des().Left( KMmsMaxLogStringLength ) ); |
|
6332 TMmsLogger::Log( _L("-- Top level content type : %S"), &dummy ); |
|
6333 CleanupStack::PopAndDestroy( buffer ); |
|
6334 buffer = NULL; |
|
6335 #endif |
|
6336 } |
|
6337 } |
|
6338 iPosition = endPosition; |
|
6339 } |
|
6340 |
|
6341 // --------------------------------------------------------- |
|
6342 // |
|
6343 // --------------------------------------------------------- |
|
6344 void CMmsDecode::DecodeMessageLimitL() |
|
6345 { |
|
6346 TUint32 size = 0; |
|
6347 size = GetLongOrShortInteger(); |
|
6348 iMmsHeaders->MMBoxViewHeadersL().SetMmsLimit( size ); |
|
6349 #ifndef _NO_MMSS_LOGGING_ |
|
6350 TMmsLogger::Log( _L("- Max number of messages to list: %d"), size ); |
|
6351 #endif |
|
6352 } |
|
6353 |
|
6354 // --------------------------------------------------------- |
|
6355 // |
|
6356 // --------------------------------------------------------- |
|
6357 void CMmsDecode::DecodeExtNotifTextL() |
|
6358 { |
|
6359 TPtrC8 byteString; |
|
6360 HBufC16* buffer = NULL; |
|
6361 byteString.Set( GetUtf8String() ); |
|
6362 // There will be at most one unicode character per one utf-8 character |
|
6363 buffer = HBufC16::NewL( byteString.Length() * KMms2 ); |
|
6364 TPtr16 pointer16 = buffer->Des(); |
|
6365 CleanupStack::PushL( buffer ); |
|
6366 // We convert what we can and forget the rest. |
|
6367 CnvUtfConverter::ConvertToUnicodeFromUtf8( pointer16, byteString ); |
|
6368 iMmsHeaders->SetExtendedNotificationL( pointer16 ); |
|
6369 #ifndef _NO_MMSS_LOGGING_ |
|
6370 // we cannot log indefinitely long strings. |
|
6371 // We get this long strings only if the message is corrupted. |
|
6372 TPtrC dummy; |
|
6373 dummy.Set( buffer->Des().Left( KMmsMaxLogStringLength ) ); |
|
6374 TMmsLogger::Log( _L("- Extend. notif. txt: %S"), &dummy ); |
|
6375 #endif |
|
6376 CleanupStack::PopAndDestroy( buffer ); |
|
6377 } |
|
6378 |
|
6379 // --------------------------------------------------------- |
|
6380 // |
|
6381 // --------------------------------------------------------- |
|
6382 void CMmsDecode::DecodeExtNotifEolL() |
|
6383 { |
|
6384 HBufC16* buffer = NULL; |
|
6385 buffer = GetSimpleTextStringL(); |
|
6386 CleanupStack::PushL( buffer ); |
|
6387 iMmsHeaders->SetMessageComplete( ( buffer->Des() )[0] ); |
|
6388 #ifndef _NO_MMSS_LOGGING_ |
|
6389 TUint temp; |
|
6390 temp = ( buffer->Des() )[0]; |
|
6391 TMmsLogger::Log( _L("- End of ext. notif: 0x%02X"), temp ); |
|
6392 #endif |
|
6393 CleanupStack::PopAndDestroy( buffer ); |
|
6394 |
|
6395 } |
|
6396 |
|
6397 // --------------------------------------------------------- |
|
6398 // |
|
6399 // --------------------------------------------------------- |
|
6400 void CMmsDecode::DecodeContentClass() |
|
6401 { |
|
6402 TUint8 byte; // for simple reads |
|
6403 TUint temp; |
|
6404 byte = GetWellKnownFieldValueOrSkip(); |
|
6405 temp = byte; |
|
6406 iMmsHeaders->SetContentClass( temp ); |
|
6407 #ifndef _NO_MMSS_LOGGING_ |
|
6408 TMmsLogger::Log( _L("- Content Class:") ); |
|
6409 switch ( temp ) |
|
6410 { |
|
6411 case KMmsContentClassText: |
|
6412 TMmsLogger::Log( _L("-- Text") ); |
|
6413 break; |
|
6414 case KMmsContentClassImageBasic: |
|
6415 TMmsLogger::Log( _L("-- Image Basic") ); |
|
6416 break; |
|
6417 case KMmsContentClassImageRich: |
|
6418 TMmsLogger::Log( _L("-- Image Rich") ); |
|
6419 break; |
|
6420 case KMmsContentClassVideoBasic: |
|
6421 TMmsLogger::Log( _L("-- Video Basic") ); |
|
6422 break; |
|
6423 case KMmsContentClassVideoRich: |
|
6424 TMmsLogger::Log( _L("-- Video Rich") ); |
|
6425 break; |
|
6426 case KMmsContentClassMegaPixel: |
|
6427 TMmsLogger::Log( _L("-- Megapixel") ); |
|
6428 break; |
|
6429 case KMmsContentClassContentBasic: |
|
6430 TMmsLogger::Log( _L("-- Content Basic") ); |
|
6431 break; |
|
6432 case KMmsContentClassContentRich: |
|
6433 TMmsLogger::Log( _L("-- Content Rich") ); |
|
6434 break; |
|
6435 default: |
|
6436 TMmsLogger::Log( _L("-- Unknown %d"), temp ); |
|
6437 break; |
|
6438 } |
|
6439 #endif |
|
6440 } |
|
6441 |
|
6442 // --------------------------------------------------------- |
|
6443 // |
|
6444 // --------------------------------------------------------- |
|
6445 // |
|
6446 void CMmsDecode::DecodeDrmContentHeader() |
|
6447 { |
|
6448 TUint8 byte; // for simple reads |
|
6449 TUint temp; |
|
6450 byte = GetWellKnownFieldValueOrSkip(); |
|
6451 temp = byte; |
|
6452 iMmsHeaders->SetDrmContent( temp ); |
|
6453 #ifndef _NO_MMSS_LOGGING_ |
|
6454 LogYesNo( _L("- DRM Content:"), temp ); |
|
6455 #endif |
|
6456 } |
|
6457 |
|
6458 // --------------------------------------------------------- |
|
6459 // |
|
6460 // --------------------------------------------------------- |
|
6461 // |
|
6462 void CMmsDecode::DecodeAdaptationAllowed() |
|
6463 { |
|
6464 TUint8 byte; // for simple reads |
|
6465 TUint temp; |
|
6466 byte = GetWellKnownFieldValueOrSkip(); |
|
6467 temp = byte; |
|
6468 iMmsHeaders->SetAdaptationAllowed( temp ); |
|
6469 #ifndef _NO_MMSS_LOGGING_ |
|
6470 LogYesNo( _L("- Adaptation allowed:"), temp ); |
|
6471 #endif |
|
6472 } |
|
6473 |
|
6474 // --------------------------------------------------------- |
|
6475 // |
|
6476 // --------------------------------------------------------- |
|
6477 // |
|
6478 void CMmsDecode::DecodeApplicationIdL() |
|
6479 { |
|
6480 HBufC16* buffer = NULL; |
|
6481 buffer = GetSimpleTextStringL(); |
|
6482 CleanupStack::PushL( buffer ); |
|
6483 iMmsHeaders->SetApplicIdL( buffer->Des() ); |
|
6484 #ifndef _NO_MMSS_LOGGING_ |
|
6485 TPtrC dummy; |
|
6486 dummy.Set( buffer->Des().Left( KMmsMaxLogStringLength ) ); |
|
6487 TMmsLogger::Log( _L("- Application-ID: %S"), &dummy ); |
|
6488 #endif |
|
6489 CleanupStack::PopAndDestroy( buffer ); |
|
6490 } |
|
6491 |
|
6492 // --------------------------------------------------------- |
|
6493 // |
|
6494 // --------------------------------------------------------- |
|
6495 // |
|
6496 void CMmsDecode::DecodeReplyApplicationIdL() |
|
6497 { |
|
6498 HBufC16* buffer = NULL; |
|
6499 buffer = GetSimpleTextStringL(); |
|
6500 CleanupStack::PushL( buffer ); |
|
6501 iMmsHeaders->SetReplyApplicIdL( buffer->Des() ); |
|
6502 #ifndef _NO_MMSS_LOGGING_ |
|
6503 TPtrC dummy; |
|
6504 dummy.Set( buffer->Des().Left( KMmsMaxLogStringLength ) ); |
|
6505 TMmsLogger::Log( _L("- Reply-To-Application-ID: %S"), &dummy ); |
|
6506 #endif |
|
6507 CleanupStack::PopAndDestroy( buffer ); |
|
6508 } |
|
6509 |
|
6510 // --------------------------------------------------------- |
|
6511 // |
|
6512 // --------------------------------------------------------- |
|
6513 // |
|
6514 void CMmsDecode::DecodeApplicationInfoL() |
|
6515 { |
|
6516 TPtrC8 byteString; |
|
6517 byteString.Set( GetByteString() ); |
|
6518 iMmsHeaders->SetAuxApplicInfoL( byteString ); |
|
6519 #ifndef _NO_MMSS_LOGGING_ |
|
6520 TPtrC dummy; |
|
6521 HBufC16* buffer = NULL; |
|
6522 buffer = HBufC16::NewLC( byteString.Length() ); |
|
6523 buffer->Des().Copy( byteString ); |
|
6524 dummy.Set( buffer->Des().Left( KMmsMaxLogStringLength ) ); |
|
6525 TMmsLogger::Log( _L("- Aux-Applic-Info: %S"), &dummy ); |
|
6526 CleanupStack::PopAndDestroy( buffer ); |
|
6527 #endif |
|
6528 } |
|
6529 |
|
6530 // --------------------------------------------------------- |
|
6531 // |
|
6532 // --------------------------------------------------------- |
|
6533 // |
|
6534 void CMmsDecode::DecodeRecommendedRetrievalMode() |
|
6535 { |
|
6536 TUint8 byte; |
|
6537 TUint temp; |
|
6538 byte = GetWellKnownFieldValueOrSkip(); |
|
6539 temp = byte; |
|
6540 iMmsHeaders->SetRecommendedRetrievalMode( temp ); |
|
6541 #ifndef _NO_MMSS_LOGGING_ |
|
6542 if ( temp == KMmsRecommendedRetrievalModeManual ) |
|
6543 { |
|
6544 TMmsLogger::Log( _L("- Recommended retrieval mode: Manual") ); |
|
6545 } |
|
6546 else |
|
6547 { |
|
6548 TMmsLogger::Log( _L("- Recommended retrieval mode unknown %d"), temp ); |
|
6549 } |
|
6550 #endif |
|
6551 } |
|
6552 |
|
6553 // --------------------------------------------------------- |
|
6554 // |
|
6555 // --------------------------------------------------------- |
|
6556 // |
|
6557 void CMmsDecode::DecodeRecommendedRetrievalModeTextL() |
|
6558 { |
|
6559 HBufC16* buffer = NULL; |
|
6560 buffer = GetEncodedTextStringL(); |
|
6561 CleanupStack::PushL( buffer ); |
|
6562 iMmsHeaders->SetRecommendedRetrievalModeTextL( buffer->Des() ); |
|
6563 #ifndef _NO_MMSS_LOGGING_ |
|
6564 // we cannot log indefinitely long strings. |
|
6565 // We get this long strings only if the message is corrupted. |
|
6566 TPtrC dummy; |
|
6567 dummy.Set( buffer->Des().Left( KMmsMaxLogStringLength ) ); |
|
6568 TMmsLogger::Log( _L("- Response text: %S"), &dummy ); |
|
6569 #endif |
|
6570 CleanupStack::PopAndDestroy( buffer ); |
|
6571 } |
|
6572 |
|
6573 // --------------------------------------------------------- |
|
6574 // |
|
6575 // --------------------------------------------------------- |
|
6576 // |
|
6577 void CMmsDecode::DecodeCancelReplaceIdL( TInt aHeader ) |
|
6578 { |
|
6579 TPtrC8 byteString; |
|
6580 byteString.Set( GetByteString() ); |
|
6581 iMmsHeaders->SetReplaceCancelIdL( byteString ); |
|
6582 #ifndef _NO_MMSS_LOGGING_ |
|
6583 HBufC16* buffer = NULL; |
|
6584 buffer = HBufC16::NewLC( byteString.Length() ); |
|
6585 buffer->Des().Copy( byteString ); |
|
6586 // we cannot log indefinitely long strings. |
|
6587 // We get this long strings only if the message is corrupted. |
|
6588 TPtrC dummy; |
|
6589 dummy.Set( buffer->Des().Left( KMmsMaxLogStringLength ) ); |
|
6590 if ( aHeader == KMmsAssignedReplaceId ) |
|
6591 { |
|
6592 TMmsLogger::Log( _L("- Replace Id: %S"), &dummy ); |
|
6593 } |
|
6594 if ( aHeader == KMmsAssignedCancelId ) |
|
6595 { |
|
6596 TMmsLogger::Log( _L("- Cancel Id: %S"), &dummy ); |
|
6597 } |
|
6598 CleanupStack::PopAndDestroy( buffer ); |
|
6599 #endif |
|
6600 } |
|
6601 |
|
6602 // --------------------------------------------------------- |
|
6603 // |
|
6604 // --------------------------------------------------------- |
|
6605 void CMmsDecode::DecodeCancelStatus() |
|
6606 { |
|
6607 TUint8 byte; |
|
6608 byte = GetWellKnownFieldValueOrSkip(); |
|
6609 TUint temp; |
|
6610 temp = byte; |
|
6611 iMmsHeaders->SetCancelStatus( temp ); |
|
6612 #ifndef _NO_MMSS_LOGGING_ |
|
6613 TMmsLogger::Log( _L("- Cancel Status:") ); |
|
6614 switch ( temp ) |
|
6615 { |
|
6616 case KMmsCancelRequestSuccessfullyReceived: |
|
6617 TMmsLogger::Log( _L("-- successful") ); |
|
6618 break; |
|
6619 case KMmsCancelRequestCorrupted: |
|
6620 TMmsLogger::Log( _L("-- corrupted") ); |
|
6621 break; |
|
6622 default: |
|
6623 TMmsLogger::Log( KLogUnknown, temp ); |
|
6624 break; |
|
6625 } |
|
6626 #endif |
|
6627 } |
|
6628 |
|
6629 #ifndef _NO_MMSS_LOGGING_ |
|
6630 // --------------------------------------------------------- |
|
6631 // |
|
6632 // --------------------------------------------------------- |
|
6633 void CMmsDecode::LogDateL( const TInt64& aDate ) |
|
6634 { |
|
6635 TBuf<KMmsDateFormatLength> dateString; |
|
6636 |
|
6637 TMmsLogger::Log( _L("%d seconds from 1.1.1970 (UTC)"), aDate ); |
|
6638 TTime time = TTime( KMmsYear1970String ) + |
|
6639 TTimeIntervalMicroSeconds( aDate * KMmsMicroToSeconds ); |
|
6640 time.FormatL(dateString,(_L("%*E%*D%X%*N%Y %1 %2 '%3"))); |
|
6641 TMmsLogger::Log( _L("date %S"), &dateString ); |
|
6642 time.FormatL(dateString,(_L("%-B%:0%J%:1%T%:2%S%:3%+B"))); |
|
6643 TMmsLogger::Log( _L("time %S"), &dateString ); |
|
6644 } |
|
6645 #endif |
|
6646 |
|
6647 |
|
6648 // ================= OTHER EXPORTED FUNCTIONS ============== |
|
6649 |
|
6650 // End of File |
|
6651 |