|
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: |
|
15 * Server Mtm |
|
16 * |
|
17 */ |
|
18 |
|
19 |
|
20 |
|
21 // INCLUDE FILES |
|
22 #ifdef SYMBIAN_ENABLE_SPLIT_HEADERS |
|
23 #include <logengdurations.h> |
|
24 #endif |
|
25 #include <apparc.h> |
|
26 #include <msventry.h> |
|
27 #include <msvschedulepackage.h> |
|
28 #include <msvschedulesettings.h> |
|
29 #include <msvsenderroraction.h> |
|
30 #include <bautils.h> |
|
31 #include <e32math.h> // for notification generation |
|
32 #include <logcli.h> |
|
33 #include <logview.h> |
|
34 #include <flogger.h> |
|
35 #include <e32svr.h> |
|
36 #include <centralrepository.h> |
|
37 #include <utf.h> |
|
38 #include <cmsvmimeheaders.h> |
|
39 #include <LogsApiConsts.h> |
|
40 |
|
41 |
|
42 // MMS specific |
|
43 #include "mmsconst.h" |
|
44 #include "mmserrors.h" |
|
45 #include "mmsmmboxmessageheaders.h" |
|
46 #include "mmsservercommon.h" |
|
47 #include "mmscmds.h" |
|
48 #include "mmssettings.h" |
|
49 #include "mmsaccount.h" |
|
50 #include "mmsserver.h" |
|
51 #include "mmssendoperation.h" |
|
52 #include "mmsreceivemessage.h" |
|
53 #include "mmsforwardoperation.h" |
|
54 #include "mmsdeleteoperation.h" |
|
55 #include "mmsmmboxlist.h" |
|
56 #include "mmsdecode.h" |
|
57 #include "mmsencode.h" |
|
58 #include "mmsheaders.h" |
|
59 #include "mmsschedulesend.h" |
|
60 #include "mmsscheduledentry.h" |
|
61 #include "mmslog.h" |
|
62 #include "mmsgenutils.h" |
|
63 #include "mmsserverentry.h" |
|
64 #include "MmsEnginePrivateCRKeys.h" |
|
65 #include "mmsreadreport.h" |
|
66 |
|
67 // LOCAL CONSTANTS AND MACROS |
|
68 const TInt KMmsGarbageCollectionDelay = 30; // 30s delay |
|
69 const TInt KMmsSanityInterval = 96; // 96 hours, 4 days |
|
70 const TInt KMmsScheduleAllowance = 10; |
|
71 const TInt KMmsScheduleDelay = 5; |
|
72 |
|
73 // ================= MEMBER FUNCTIONS ======================= |
|
74 |
|
75 // --------------------------------------------------------- |
|
76 // C++ default constructor can NOT contain any code, that |
|
77 // might leave. |
|
78 // --------------------------------------------------------- |
|
79 // |
|
80 CMmsServerMtm::CMmsServerMtm( |
|
81 CRegisteredMtmDll& aRegisteredMtmDll, |
|
82 CMsvServerEntry* aInitialEntry ) |
|
83 : CScheduleBaseServerMtm( aRegisteredMtmDll, aInitialEntry ), |
|
84 iNotification ( KMsvNullIndexEntryId ), |
|
85 iOOMState ( EFalse ), |
|
86 iDeliveryStatus (EFalse) |
|
87 { |
|
88 // Everything not mentioned gets initialized to NULL |
|
89 // Save our initial entry id |
|
90 // It is either default service or service specified in Entry Selection |
|
91 iServiceEntryId = aInitialEntry->Entry().Id(); |
|
92 // We use the file session offered by initial entry. |
|
93 // Documentation says that it is expensive to open new file sessions |
|
94 // We offer the same session to all classes we create so that everybody |
|
95 // is using the same session. |
|
96 // In the final version file session is needed for attachment access |
|
97 // only, in the preliminary version we have a fake MMSC set up in a |
|
98 // directory on disk, and we need the file session to access that. |
|
99 iFs = aInitialEntry->FileSession(); |
|
100 CActiveScheduler::Add( this ); |
|
101 } |
|
102 |
|
103 // --------------------------------------------------------- |
|
104 // Symbian OS default constructor can leave. |
|
105 // |
|
106 // --------------------------------------------------------- |
|
107 // |
|
108 void CMmsServerMtm::ConstructL() |
|
109 { |
|
110 |
|
111 CScheduleBaseServerMtm::ConstructL(); |
|
112 iScheduleSend = CMmsScheduleSend::NewL( *iServerEntry ); |
|
113 iMsvSelection = new( ELeave ) CMsvEntrySelection; |
|
114 iMmsSettings = CMmsSettings::NewL(); |
|
115 // don't load settings yet in case someone else is trying |
|
116 // to change the settings. |
|
117 iMmsHeaders = CMmsHeaders::NewL( iMmsSettings->MmsVersion() ); |
|
118 iMessageDrive = EDriveC; |
|
119 // see if message server knows better |
|
120 iMessageDrive = MessageServer::CurrentDriveL( iFs ); |
|
121 } |
|
122 |
|
123 // --------------------------------------------------------- |
|
124 // Factory function |
|
125 // |
|
126 // --------------------------------------------------------- |
|
127 // |
|
128 EXPORT_C CMmsServerMtm* CMmsServerMtm::NewL( |
|
129 CRegisteredMtmDll& aRegisteredMtmDll, |
|
130 CMsvServerEntry* aInitialEntry ) |
|
131 { |
|
132 |
|
133 CleanupStack::PushL( aInitialEntry ); // Take ownership of aInitialEntry |
|
134 CMmsServerMtm* self = new( ELeave ) CMmsServerMtm( |
|
135 aRegisteredMtmDll, aInitialEntry ); |
|
136 CleanupStack::Pop( aInitialEntry ); // Entry now safely stored in member |
|
137 |
|
138 CleanupStack::PushL( self ); |
|
139 self->ConstructL(); |
|
140 CleanupStack::Pop( self ); |
|
141 |
|
142 return self; |
|
143 } |
|
144 |
|
145 |
|
146 // --------------------------------------------------------- |
|
147 // Destructor |
|
148 // |
|
149 // --------------------------------------------------------- |
|
150 // |
|
151 CMmsServerMtm::~CMmsServerMtm() |
|
152 { |
|
153 // We don't close the file session anymore, as we |
|
154 // obtained if from the initial entry, and it is not ours to close... |
|
155 Cancel(); // cancel anything that may be pending... |
|
156 if ( iRemoteParties ) |
|
157 { |
|
158 iRemoteParties->Reset(); |
|
159 } |
|
160 delete iEntryWrapper; |
|
161 delete iRemoteParties; |
|
162 delete iReadReport; |
|
163 delete iSendOperation; |
|
164 delete iReceiveMessage; |
|
165 delete iForwardOperation; |
|
166 delete iDeleteOperation; |
|
167 delete iUpdateMmboxList; |
|
168 delete iMsvSelection; |
|
169 delete iMmsSettings; |
|
170 delete iScheduleSend; |
|
171 delete iDecoder; |
|
172 delete iMmsHeaders; |
|
173 delete iEncodeBuffer; |
|
174 delete iMmsLog; |
|
175 delete iLogEvent; |
|
176 delete iLogViewEvent; |
|
177 delete iLogClient; |
|
178 #ifndef _NO_MMSS_LOGGING_ |
|
179 TMmsLogger::Log( _L("MMSServer destructor, done") ); |
|
180 #endif |
|
181 } |
|
182 |
|
183 |
|
184 // --------------------------------------------------------- |
|
185 // CMmsServerMtm::CopyToLocalL |
|
186 // |
|
187 // --------------------------------------------------------- |
|
188 // |
|
189 void CMmsServerMtm::CopyToLocalL( |
|
190 const CMsvEntrySelection& /*aSelection*/, |
|
191 TMsvId /*aDestination*/, |
|
192 TRequestStatus& aStatus ) |
|
193 { |
|
194 |
|
195 TRequestStatus* status = &aStatus; |
|
196 aStatus = KRequestPending; |
|
197 User::RequestComplete( status, KErrNotSupported ); |
|
198 |
|
199 } |
|
200 |
|
201 // --------------------------------------------------------- |
|
202 // CMmsServerMtm::CopyFromLocalL |
|
203 // |
|
204 // --------------------------------------------------------- |
|
205 // |
|
206 void CMmsServerMtm::CopyFromLocalL( |
|
207 const CMsvEntrySelection& aSelection, |
|
208 TMsvId /*aDestination*/, |
|
209 TRequestStatus& aStatus ) |
|
210 { |
|
211 |
|
212 // test code: copy from local means send. |
|
213 // sent folder is handled separately |
|
214 TCommandParameters parameters; |
|
215 parameters.iInitialDelay = 0; |
|
216 TCommandParametersBuf paramPack( parameters ); |
|
217 |
|
218 CMsvEntrySelection* selection = new (ELeave) CMsvEntrySelection; |
|
219 CleanupStack::PushL(selection); |
|
220 if ( aSelection.Count() > 0 ) |
|
221 { |
|
222 selection->AppendL( aSelection.Back( 0 ), aSelection.Count() ); |
|
223 } |
|
224 StartCommandL( *selection, EMmsScheduledSend, paramPack, aStatus ); |
|
225 CleanupStack::PopAndDestroy( selection ); |
|
226 |
|
227 } |
|
228 |
|
229 // --------------------------------------------------------- |
|
230 // CMmsServerMtm::CopyWithinServiceL |
|
231 // |
|
232 // --------------------------------------------------------- |
|
233 // |
|
234 void CMmsServerMtm::CopyWithinServiceL( |
|
235 const CMsvEntrySelection& /*aSelection*/, |
|
236 TMsvId /*aDestination*/, |
|
237 TRequestStatus& aStatus ) |
|
238 { |
|
239 |
|
240 TRequestStatus* status = &aStatus; |
|
241 aStatus = KRequestPending; |
|
242 User::RequestComplete( status, KErrNotSupported ); |
|
243 |
|
244 } |
|
245 |
|
246 // --------------------------------------------------------- |
|
247 // CMmsServerMtm::MoveToLocalL |
|
248 // |
|
249 // --------------------------------------------------------- |
|
250 // |
|
251 void CMmsServerMtm::MoveToLocalL( |
|
252 const CMsvEntrySelection& /*aSelection*/, |
|
253 TMsvId /*aDestination*/, |
|
254 TRequestStatus& aStatus ) |
|
255 { |
|
256 |
|
257 TRequestStatus* status = &aStatus; |
|
258 aStatus = KRequestPending; |
|
259 User::RequestComplete( status, KErrNotSupported ); |
|
260 |
|
261 } |
|
262 |
|
263 // --------------------------------------------------------- |
|
264 // CMmsServerMtm::MoveFromLocalL |
|
265 // |
|
266 // --------------------------------------------------------- |
|
267 // |
|
268 void CMmsServerMtm::MoveFromLocalL( |
|
269 const CMsvEntrySelection& /*aSelection*/, |
|
270 TMsvId /*aDestination*/, |
|
271 TRequestStatus& aStatus ) |
|
272 { |
|
273 |
|
274 TRequestStatus* status = &aStatus; |
|
275 aStatus = KRequestPending; |
|
276 User::RequestComplete( status, KErrNotSupported ); |
|
277 |
|
278 } |
|
279 |
|
280 // --------------------------------------------------------- |
|
281 // CMmsServerMtm::MoveWithinServiceL |
|
282 // |
|
283 // --------------------------------------------------------- |
|
284 // |
|
285 void CMmsServerMtm::MoveWithinServiceL( |
|
286 const CMsvEntrySelection& /*aSelection*/, |
|
287 TMsvId /*aDestination*/, |
|
288 TRequestStatus& aStatus ) |
|
289 { |
|
290 |
|
291 TRequestStatus* status = &aStatus; |
|
292 aStatus = KRequestPending; |
|
293 User::RequestComplete( status, KErrNotSupported ); |
|
294 |
|
295 } |
|
296 |
|
297 // --------------------------------------------------------- |
|
298 // CMmsServerMtm::DeleteAllL |
|
299 // |
|
300 // --------------------------------------------------------- |
|
301 // |
|
302 void CMmsServerMtm::DeleteAllL( |
|
303 const CMsvEntrySelection& aSelection, |
|
304 TRequestStatus& aStatus ) |
|
305 { |
|
306 |
|
307 // this is implemented for scheduled send |
|
308 // It needs to change entry asynchronously, |
|
309 // and needs help on server mtm |
|
310 TInt error; |
|
311 // we are always called with a selection that has at least one member. |
|
312 // we cannot be called with an empty selection (because then the server |
|
313 // does not know whom to call) |
|
314 if ( aSelection.Count() == 0 ) |
|
315 { |
|
316 User::Leave( KErrNotFound ); |
|
317 } |
|
318 User::LeaveIfError( iServerEntry->SetEntry( aSelection[0] ) ); |
|
319 User::LeaveIfError( iServerEntry->SetEntry( iServerEntry->Entry().Parent() ) ); |
|
320 CMsvEntrySelection* sel = aSelection.CopyL(); |
|
321 error = iServerEntry->DeleteEntries( *sel ); |
|
322 if ( error == KErrNotFound ) |
|
323 { |
|
324 error = KErrNone; // if not found, deleted already. |
|
325 } |
|
326 delete sel; |
|
327 |
|
328 TRequestStatus* status = &aStatus; |
|
329 aStatus = KRequestPending; |
|
330 User::RequestComplete( status, error ); |
|
331 } |
|
332 |
|
333 // --------------------------------------------------------- |
|
334 // CMmsServerMtm::CreateL |
|
335 // |
|
336 // --------------------------------------------------------- |
|
337 // |
|
338 void CMmsServerMtm::CreateL( |
|
339 TMsvEntry /*aNewEntry*/, |
|
340 TRequestStatus& aStatus ) |
|
341 { |
|
342 |
|
343 TRequestStatus* status = &aStatus; |
|
344 aStatus = KRequestPending; |
|
345 User::RequestComplete( status, KErrNotSupported ); |
|
346 |
|
347 } |
|
348 |
|
349 // --------------------------------------------------------- |
|
350 // CMmsServerMtm::ChangeL |
|
351 // |
|
352 // --------------------------------------------------------- |
|
353 // |
|
354 void CMmsServerMtm::ChangeL( |
|
355 TMsvEntry aNewEntry, |
|
356 TRequestStatus& aStatus ) |
|
357 { |
|
358 |
|
359 // this is implemented for scheduled send |
|
360 // It needs to change entry asynchronously, |
|
361 // and needs help on server mtm |
|
362 User::LeaveIfError( iServerEntry->SetEntry( aNewEntry.Id() )); |
|
363 User::LeaveIfError( iServerEntry->ChangeEntry( aNewEntry ) ); |
|
364 TRequestStatus* status = &aStatus; |
|
365 aStatus = KRequestPending; |
|
366 User::RequestComplete( status, KErrNone ); |
|
367 |
|
368 } |
|
369 |
|
370 // --------------------------------------------------------- |
|
371 // CMmsServerMtm::StartCommandL |
|
372 // |
|
373 // --------------------------------------------------------- |
|
374 // |
|
375 void CMmsServerMtm::StartCommandL( |
|
376 CMsvEntrySelection& aSelection, |
|
377 TInt aCommand, |
|
378 const TDesC8& aParameter, |
|
379 TRequestStatus& aStatus ) |
|
380 { |
|
381 |
|
382 TInt error = KErrNone; |
|
383 TMsvEntry entry; // This will be used a lot later to access the index data |
|
384 |
|
385 #ifndef _NO_MMSS_LOGGING_ |
|
386 TMmsLogger::Log( _L("MMSServer Start Command %d"), aCommand ); |
|
387 #endif // _NO_MMSS_LOGGING_ |
|
388 // log the code for debugging |
|
389 LogCommandCode( aCommand ); |
|
390 |
|
391 // The content of the parameter depends on command. |
|
392 // For EMmsDecodePushedMessage it will be TWatcherParametersBuf structure, |
|
393 // but the content is currently ignored because it has become impossible |
|
394 // to copy the data between processes in the protected environment. |
|
395 // For EMmsScheduledSend, EMmsScheduledReceive, and EMmsScheduledReceiveForced |
|
396 // it will be TCommandParametersBuf. |
|
397 // For EMmsGarbageCollection it will be TMMSGarbageCollectionParametersBuf |
|
398 // containing the reason for the garbage collection. |
|
399 // For others the parameter will be ignored. |
|
400 // The parameter should be unpackaged only when the contents are known. |
|
401 |
|
402 // The default service entry is always used. |
|
403 |
|
404 // Because of the restriction that only one mtm |
|
405 // per service can be open at any time, the scheduling calls |
|
406 // cheat and offer the stuff here using local service instead |
|
407 // of mms service. As we would like to load our settings |
|
408 // anyway, we try to find out the real service. |
|
409 |
|
410 if ( iServiceEntryId == KMsvLocalServiceIndexEntryId ) |
|
411 { |
|
412 // we have been cheated |
|
413 #ifndef _NO_MMSS_LOGGING_ |
|
414 TMmsLogger::Log( _L("- local service id") ); |
|
415 #endif |
|
416 // Get the actual service id from a message entry |
|
417 GetRealServiceId( aSelection ); |
|
418 } |
|
419 |
|
420 // free whatever entry we are holding |
|
421 iServerEntry->SetEntry( KMsvNullIndexEntryId ); |
|
422 |
|
423 // |
|
424 // Load the service settings. |
|
425 // In case call fails, loading will be retried |
|
426 // |
|
427 TInt loadServiceError = KErrNone; |
|
428 TRAP( loadServiceError, LoadSettingsL( aCommand ) ); |
|
429 |
|
430 #ifndef _NO_MMSS_LOGGING_ |
|
431 if ( loadServiceError != KErrNone ) |
|
432 { |
|
433 TMmsLogger::Log( _L("-ERROR loading settings: %d"), loadServiceError ); |
|
434 } |
|
435 else |
|
436 { |
|
437 TMmsLogger::Log( _L("- settings loaded successfully") ); |
|
438 } |
|
439 #endif |
|
440 |
|
441 iCurrentCommand = aCommand; |
|
442 if ( aCommand != EMmsRetryServiceLoading ) |
|
443 { |
|
444 iCommand = aCommand; |
|
445 iParameter = aParameter; |
|
446 iRequestStatus = &aStatus; |
|
447 |
|
448 // We remove the service entry from the selection, as we don't need it anymore |
|
449 iMsvSelection->Reset(); |
|
450 if ( aSelection.Count() > 0 ) |
|
451 { |
|
452 iMsvSelection->AppendL( aSelection.Back( 0 ), aSelection.Count() ); |
|
453 } |
|
454 } |
|
455 else |
|
456 { |
|
457 // iRequestStatus was set on an earlier round. |
|
458 // EMmsRetryServiceLoading is never the first command |
|
459 iCurrentCommand = iCommand; // orginal command was stored here |
|
460 } |
|
461 |
|
462 // If service loading has failed, we loop through RunL to retry. |
|
463 // Actually only EMmsScheduledReceive and EMmsScheduledReceiveForced |
|
464 // need this service. |
|
465 // Other callers can handle error situations gracefully. |
|
466 // We have saved all our parameters. |
|
467 // All we have to do now is to change iCurrent command and complete ourselves |
|
468 // In order to get to our RunL. |
|
469 // RunL will route us to DoRunL where we can continue |
|
470 |
|
471 if ( loadServiceError != KErrNone ) |
|
472 { |
|
473 // Actually we should no longer get load service error as the settings |
|
474 // are now in central repository, no longer saved into the service entry |
|
475 HandleLoadServiceError( loadServiceError ); |
|
476 // we cannot continue. HandleLoadServiceError has set completion status |
|
477 // as required. |
|
478 return; |
|
479 } |
|
480 |
|
481 // If we have loaded the service, we can discard the service entry |
|
482 // if it still is in our selection |
|
483 if ( iMsvSelection->Count() > 0 && iMsvSelection->At( 0 ) == iServiceEntryId ) |
|
484 { |
|
485 iMsvSelection->Delete( 0 ); |
|
486 } |
|
487 |
|
488 #ifndef _NO_MMSS_LOGGING_ |
|
489 // log the parent folder of the selection (needed for debugging) |
|
490 LogEntryParent(); |
|
491 #endif |
|
492 |
|
493 // we do not move the entries anywhere. |
|
494 // it is the client's responsibility to move them to the right place |
|
495 // we just make them visible because some applications left invisible |
|
496 // entries to outbox. |
|
497 if ( iCurrentCommand == EMmsSend || |
|
498 iCurrentCommand == EMmsScheduledSend || |
|
499 iCurrentCommand == EMmsDeleteSchedule ) |
|
500 { |
|
501 RestoreVisibilityAndService(); |
|
502 } |
|
503 |
|
504 // |
|
505 // Following switch handles all the different requests |
|
506 // |
|
507 switch( iCurrentCommand ) |
|
508 { |
|
509 // scheduled operations can only use default service. |
|
510 case EMmsScheduledSend: |
|
511 if ( iMsvSelection->Count() > 0 ) |
|
512 { |
|
513 iCommand = EMmsSend; |
|
514 // This will complete our caller. |
|
515 // If no error, task scheduler will complete the caller. |
|
516 // If error, the subroutine will complete |
|
517 error = ScheduleSelectionL(); |
|
518 #ifndef _NO_MMSS_LOGGING_ |
|
519 if ( error != KErrNone ) |
|
520 { |
|
521 TMmsLogger::Log( _L("MmsServer Schedule send status %d"), error ); |
|
522 } |
|
523 #endif |
|
524 } |
|
525 else |
|
526 { |
|
527 // nothing to send - successfully sent nothing |
|
528 // ("You must have keen eyes to see nobody coming") |
|
529 *iRequestStatus = KRequestPending; |
|
530 User::RequestComplete( iRequestStatus, KErrNone ); |
|
531 } |
|
532 break; |
|
533 // |
|
534 // Handle push message (i.e. notification or delivery report) |
|
535 // |
|
536 case EMmsDecodePushedMessage: |
|
537 { |
|
538 // |
|
539 // First read pushed data from dummy entries stream store, |
|
540 // and then delete it. |
|
541 // If there is no entry, HandleDummyEntryL() leaves |
|
542 // |
|
543 HandleDummyEntryL(); |
|
544 // |
|
545 // Decode received databuffer into message |
|
546 // |
|
547 TInt err = KErrNone; |
|
548 TRAP( err, DecodePushedMessageL() ); |
|
549 // DecodePushedMessageL might set iError, don't override it |
|
550 if ( iError == KErrNone ) |
|
551 { |
|
552 iError = err; |
|
553 } |
|
554 |
|
555 delete iEncodeBuffer; |
|
556 iEncodeBuffer = NULL; |
|
557 // The resulting id is now in iNotification |
|
558 |
|
559 if ( iNotification != KMsvNullIndexEntryId ) |
|
560 { |
|
561 iMsvSelection->AppendL( iNotification ); |
|
562 if ( iServerEntry->SetEntry( iNotification ) == KErrNone ) |
|
563 { |
|
564 entry = iServerEntry->Entry(); |
|
565 } |
|
566 // Unrecognized PDUs are handled as notifications. |
|
567 // we send a response back to MMSC |
|
568 if ( ( ( entry.iMtmData1 & KMmsMessageTypeMask ) == KMmsMessageDeliveryInd ) || |
|
569 ( ( entry.iMtmData1 & KMmsMessageTypeMask ) == KMmsMessageReadOrigInd ) ) |
|
570 { |
|
571 // Delivery report or PDU read report |
|
572 HandleDeliveryReportL(); |
|
573 } |
|
574 else |
|
575 { |
|
576 // Everything else. Handle as notification. |
|
577 // If not a notification, send back response "unrecognized" |
|
578 // Any PDU with wrong type will fall here besides the actual notifications. |
|
579 HandleNotificationL(); |
|
580 } |
|
581 } |
|
582 else |
|
583 { |
|
584 // something has gone wrong... |
|
585 *iRequestStatus = KRequestPending; |
|
586 User::RequestComplete( iRequestStatus, iError ); |
|
587 } |
|
588 break; |
|
589 } |
|
590 case EMmsScheduledReceiveForced: |
|
591 iCommand = EMmsReceiveForced; |
|
592 iMmsSettings->SetFetchOverride( ETrue ); |
|
593 // if we do forced fetch, we clean up old schedules first |
|
594 if ( iMsvSelection->Count() > 0 ) |
|
595 { |
|
596 CleanSchedulesL( *iMsvSelection ); |
|
597 } |
|
598 // fall through on purpose |
|
599 case EMmsScheduledReceive: |
|
600 if ( iCurrentCommand != EMmsScheduledReceiveForced ) |
|
601 { |
|
602 iCommand = EMmsReceive; |
|
603 } |
|
604 if ( iMsvSelection->Count() < 1 ) |
|
605 { |
|
606 TRAP( iError, CreateNotificationsL() ); |
|
607 } |
|
608 else // iMsvSelection->Count() > 0 |
|
609 { |
|
610 // notifications are not checked if the fetch is forced |
|
611 if ( iCurrentCommand == EMmsScheduledReceive ) |
|
612 { |
|
613 CheckNotificationsL( *iMsvSelection ); |
|
614 } |
|
615 } |
|
616 |
|
617 if ( iMsvSelection->Count() > 0 ) |
|
618 { |
|
619 // This will complete our caller. |
|
620 // If no error, task scheduler will complete the caller. |
|
621 // If error, the subroutine will complete |
|
622 error = ScheduleSelectionL(); |
|
623 #ifndef _NO_MMSS_LOGGING_ |
|
624 if ( error != KErrNone ) |
|
625 { |
|
626 TMmsLogger::Log( _L("MmsServer Schedule receive status %d"), error ); |
|
627 } |
|
628 #endif |
|
629 } |
|
630 else |
|
631 { |
|
632 // Nothing to be done, complete. |
|
633 if ( iError != KErrNoMemory && iError != KErrDiskFull ) |
|
634 { |
|
635 iError = KErrNone; |
|
636 } |
|
637 *iRequestStatus = KRequestPending; |
|
638 User::RequestComplete( iRequestStatus, iError ); |
|
639 } |
|
640 break; |
|
641 case EMmsSend: |
|
642 // send messages in current selection |
|
643 // we cannot do this, if we don't have settings. |
|
644 // Our access point is defined in settings. |
|
645 #ifndef _NO_MMSS_LOGGING_ |
|
646 TMmsLogger::Log( _L("Number of entries to send %d"), iMsvSelection->Count() ); |
|
647 #endif |
|
648 if ( iMsvSelection->Count() == 0 ) |
|
649 { |
|
650 // nothing in the selection... |
|
651 *iRequestStatus = KRequestPending; |
|
652 User::RequestComplete( iRequestStatus, KErrNone ); |
|
653 } |
|
654 else |
|
655 { |
|
656 iCommand = EMmsSend; |
|
657 SendToMmscL(); |
|
658 } |
|
659 break; |
|
660 case EMmsReceive: |
|
661 // fetch message to inbox |
|
662 // This is a troublesome case. |
|
663 // we cannot fetch if we did not manage to load |
|
664 // our settings. |
|
665 // And we cannot leave, because schsend has an assert |
|
666 // that forbids rescheduling entries that are not children |
|
667 // of local service. And our notifications are children of |
|
668 // the MMS service itself. |
|
669 iCommand = EMmsReceive; |
|
670 FetchFromMmscL(); |
|
671 break; |
|
672 case EMmsReceiveForced: |
|
673 iCommand = EMmsReceiveForced; |
|
674 iMmsSettings->SetFetchOverride( ETrue ); |
|
675 FetchFromMmscL(); |
|
676 break; |
|
677 case EMmsLogDeliveryReport: |
|
678 iCommand = EMmsLogDeliveryReport; |
|
679 // delivery reports should appear one by one for handling |
|
680 LogDeliveryReportL(); |
|
681 break; |
|
682 case EMmsDeleteSchedule: |
|
683 iScheduleSend->DeleteScheduleL( aSelection ); |
|
684 *iRequestStatus = KRequestPending; |
|
685 User::RequestComplete( iRequestStatus, KErrNone ); |
|
686 break; |
|
687 case EMmsDeleteEntries: |
|
688 if ( iMsvSelection->Count() > 0 ) |
|
689 { |
|
690 error = iServerEntry->SetEntry( iMsvSelection->At(0) ); |
|
691 if ( error == KErrNone ) |
|
692 { |
|
693 error = iServerEntry->SetEntry( iServerEntry->Entry().Parent() ); |
|
694 if ( error == KErrNone ) |
|
695 { |
|
696 error = iServerEntry->DeleteEntries( *iMsvSelection ); |
|
697 } |
|
698 } |
|
699 *iRequestStatus = KRequestPending; |
|
700 User::RequestComplete( iRequestStatus, error ); |
|
701 } |
|
702 else |
|
703 { |
|
704 // if nothing to delete, then done already |
|
705 *iRequestStatus = KRequestPending; |
|
706 User::RequestComplete( iRequestStatus, KErrNone ); |
|
707 } |
|
708 break; |
|
709 case EMmsGarbageCollection: |
|
710 TRAP(error, GarbageCollectionL()); |
|
711 // This returns at least KMmsErrorOfflineMode |
|
712 *iRequestStatus = KRequestPending; |
|
713 User::RequestComplete( iRequestStatus, error ); |
|
714 break; |
|
715 case EMmsMessageGeneration: |
|
716 iCommand = EMmsReceiveForced; |
|
717 iMmsSettings->SetLocalModeIn( KMmsMessageVariationDirectory() ); |
|
718 iMmsSettings->SetFetchOverride( ETrue ); |
|
719 // set local mode on the fly - not stored anywhere. |
|
720 iMmsSettings->SetLocalMode( ETrue ); |
|
721 iMmsSettings->SetAcceptAnonymousMessages( ETrue ); // variated messages are anonymous |
|
722 FetchFromMmscL(); |
|
723 break; |
|
724 case EMmsDeleteExpiredNotifications: |
|
725 // not implemented |
|
726 *iRequestStatus = KRequestPending; |
|
727 User::RequestComplete( iRequestStatus, KErrNotSupported ); |
|
728 break; |
|
729 |
|
730 case EMmsScheduledForward: |
|
731 // Make sure there is something to schedule |
|
732 if ( iMsvSelection->Count() > 0 ) |
|
733 { |
|
734 iCommand = EMmsForward; |
|
735 // ScheduleSelectionL completes the caller. |
|
736 // If no error, task scheduler will complete the caller. |
|
737 // If error, the subroutine will complete |
|
738 error = ScheduleSelectionL(); |
|
739 #ifndef _NO_MMSS_LOGGING_ |
|
740 if ( error != KErrNone ) |
|
741 { |
|
742 TMmsLogger::Log( _L("MmsServer EMmsScheduledForward status %d"), error ); |
|
743 } |
|
744 #endif |
|
745 } |
|
746 else |
|
747 { |
|
748 // Nothing to send |
|
749 *iRequestStatus = KRequestPending; |
|
750 User::RequestComplete( iRequestStatus, KErrNone ); |
|
751 } |
|
752 break; |
|
753 |
|
754 case EMmsForward: |
|
755 // Sends the current selection (containing forward requests) |
|
756 // we cannot do this, if we don't have settings. |
|
757 // Our access point is defined in settings. |
|
758 #ifndef _NO_MMSS_LOGGING_ |
|
759 TMmsLogger::Log( _L("Number of forward requests to send %d"), iMsvSelection->Count() ); |
|
760 #endif |
|
761 if ( iMsvSelection->Count() == 0 ) |
|
762 { |
|
763 // Nothing in the selection |
|
764 *iRequestStatus = KRequestPending; |
|
765 User::RequestComplete( iRequestStatus, KErrNone ); |
|
766 } |
|
767 else |
|
768 { |
|
769 iCommand = EMmsForward; |
|
770 SendForwardRequestsToMmscL(); |
|
771 } |
|
772 break; |
|
773 |
|
774 // |
|
775 // Handles scheduling of notification deletion |
|
776 // |
|
777 case EMmsScheduledNotificationDelete: |
|
778 // Make sure there is something to schedule |
|
779 if ( iMsvSelection->Count() > 0 ) |
|
780 { |
|
781 iCommand = EMmsNotificationDelete; |
|
782 // ScheduleSelectionL completes the caller. |
|
783 // If no error, task scheduler will complete the caller. |
|
784 // If error, the subroutine will complete |
|
785 error = ScheduleSelectionL(); |
|
786 #ifndef _NO_MMSS_LOGGING_ |
|
787 if ( error != KErrNone ) |
|
788 { |
|
789 TMmsLogger::Log( _L("MmsServer EMmsScheduledNotificationDelete status %d"), error ); |
|
790 } |
|
791 #endif |
|
792 } |
|
793 else |
|
794 { |
|
795 // Nothing to schedule |
|
796 *iRequestStatus = KRequestPending; |
|
797 User::RequestComplete( iRequestStatus, KErrNone ); |
|
798 } |
|
799 break; |
|
800 |
|
801 // |
|
802 // Deletes selection of notifications |
|
803 // |
|
804 case EMmsNotificationDelete: |
|
805 #ifndef _NO_MMSS_LOGGING_ |
|
806 TMmsLogger::Log( _L("Number of notifications to delete %d"), iMsvSelection->Count() ); |
|
807 #endif |
|
808 if ( iMsvSelection->Count() == 0 ) |
|
809 { |
|
810 // Nothing in the selection |
|
811 *iRequestStatus = KRequestPending; |
|
812 User::RequestComplete( iRequestStatus, KErrNone ); |
|
813 } |
|
814 else |
|
815 { |
|
816 iCommand = EMmsNotificationDelete; |
|
817 |
|
818 // Dig out delete type |
|
819 TCommandParameters param; |
|
820 TPckgC<TCommandParameters> paramPack( param ); |
|
821 paramPack.Set( iParameter ); |
|
822 |
|
823 // |
|
824 // Create a CMmsDeleteOperation instance and start it |
|
825 // |
|
826 delete iDeleteOperation; |
|
827 iDeleteOperation = NULL; |
|
828 iDeleteOperation = CMmsDeleteOperation::NewL( iFs, iMmsSettings ); |
|
829 iDeleteOperation->StartL( |
|
830 (TMmsDeleteOperationType)paramPack().iError, |
|
831 *iMsvSelection, |
|
832 *iServerEntry, |
|
833 iServiceEntryId, |
|
834 iStatus ); |
|
835 *iRequestStatus = KRequestPending; |
|
836 SetActive(); |
|
837 } |
|
838 break; |
|
839 // update mmbox list |
|
840 case EMmsUpdateMmboxList: |
|
841 iCommand = EMmsUpdateMmboxList; |
|
842 delete iUpdateMmboxList; |
|
843 iUpdateMmboxList = NULL; |
|
844 iUpdateMmboxList = CMmsMmboxList::NewL( iFs, iMmsSettings ); |
|
845 iUpdateMmboxList->StartL( |
|
846 *iMsvSelection, |
|
847 *iServerEntry, |
|
848 iServiceEntryId, |
|
849 iStatus ); |
|
850 *iRequestStatus = KRequestPending; |
|
851 SetActive(); |
|
852 break; |
|
853 case EMmsSendReadReport: |
|
854 SendReadReportL(); |
|
855 break; |
|
856 case EMmsScheduledReadReport: |
|
857 if ( iMsvSelection->Count() > 0 ) |
|
858 { |
|
859 iCommand = EMmsSendReadReport; |
|
860 // ScheduleSelectionL completes the caller. |
|
861 // If no error, task scheduler will complete the caller. |
|
862 // If error, the subroutine will complete |
|
863 error = ScheduleSelectionL(); |
|
864 #ifndef _NO_MMSS_LOGGING_ |
|
865 if ( error != KErrNone ) |
|
866 { |
|
867 TMmsLogger::Log( _L("MmsServer EMmsScheduledReadReport status %d"), error ); |
|
868 } |
|
869 #endif |
|
870 } |
|
871 else |
|
872 { |
|
873 // Nothing to schedule |
|
874 *iRequestStatus = KRequestPending; |
|
875 User::RequestComplete( iRequestStatus, KErrNone ); |
|
876 } |
|
877 break; |
|
878 default: |
|
879 *iRequestStatus = KRequestPending; |
|
880 User::RequestComplete( iRequestStatus, KErrNotSupported ); |
|
881 break; |
|
882 } |
|
883 } |
|
884 |
|
885 // --------------------------------------------------------- |
|
886 // CMmsServerMtm::CommandExpected |
|
887 // |
|
888 // --------------------------------------------------------- |
|
889 // |
|
890 TBool CMmsServerMtm::CommandExpected() |
|
891 { |
|
892 // so far we don't expect anything |
|
893 |
|
894 return EFalse; |
|
895 |
|
896 } |
|
897 |
|
898 // --------------------------------------------------------- |
|
899 // CMmsServerMtm::Progress |
|
900 // |
|
901 // --------------------------------------------------------- |
|
902 // |
|
903 const TDesC8& CMmsServerMtm::Progress() |
|
904 { |
|
905 // should load in latest progress, if something is going on |
|
906 |
|
907 return iProgressBuffer; |
|
908 |
|
909 } |
|
910 |
|
911 // --------------------------------------------------------- |
|
912 // CMmsServerMtm::LoadResourceFile |
|
913 // |
|
914 // --------------------------------------------------------- |
|
915 // |
|
916 void CMmsServerMtm::LoadResourceFileL() |
|
917 { |
|
918 // THIS IS NO LONGER NEEDED, BECAUSE THERE IS NO RESOURCE FILE ANY MORE. |
|
919 } |
|
920 |
|
921 // --------------------------------------------------------- |
|
922 // CMmsServerMtm::PopulateSchedulePackage |
|
923 // --------------------------------------------------------- |
|
924 // |
|
925 void CMmsServerMtm::PopulateSchedulePackage( const TDesC8& aParameter, |
|
926 const TBool /*aMove*/, TMsvSchedulePackage& aPackage ) const |
|
927 { |
|
928 aPackage.iParameter = aParameter; |
|
929 // We have a member telling what we are supposed to do. |
|
930 // We can schedule both sending and receiving. |
|
931 aPackage.iCommandId = iCommand; |
|
932 } |
|
933 |
|
934 // --------------------------------------------------------- |
|
935 // CMmsServerMtm::RestoreScheduleSettingsL |
|
936 // --------------------------------------------------------- |
|
937 // |
|
938 void CMmsServerMtm::RestoreScheduleSettingsL( |
|
939 TBool /*aRestoreErrorsFromResource*/, |
|
940 TInt /*aErrorsResourceId*/ ) |
|
941 { |
|
942 // EMPTY IMPLEMENTATION |
|
943 } |
|
944 |
|
945 // --------------------------------------------------------- |
|
946 // CMmsServerMtm::DoCancel |
|
947 // |
|
948 // --------------------------------------------------------- |
|
949 // |
|
950 void CMmsServerMtm::DoCancel() |
|
951 { |
|
952 |
|
953 // first cancel whatever operation is active |
|
954 if ( iSendOperation ) |
|
955 { |
|
956 iSendOperation->Cancel(); |
|
957 } |
|
958 |
|
959 if ( iReceiveMessage ) |
|
960 { |
|
961 iReceiveMessage->Cancel(); |
|
962 } |
|
963 |
|
964 if ( iMmsLog ) |
|
965 { |
|
966 iMmsLog->Cancel(); |
|
967 } |
|
968 |
|
969 if( iDeleteOperation ) |
|
970 { |
|
971 iDeleteOperation->Cancel(); |
|
972 } |
|
973 |
|
974 if( iForwardOperation ) |
|
975 { |
|
976 iForwardOperation->Cancel(); |
|
977 } |
|
978 |
|
979 if ( iUpdateMmboxList ) |
|
980 { |
|
981 iUpdateMmboxList->Cancel(); |
|
982 } |
|
983 |
|
984 if ( iReadReport ) |
|
985 { |
|
986 iReadReport->Cancel(); |
|
987 } |
|
988 |
|
989 DoComplete( KErrCancel ); |
|
990 |
|
991 } |
|
992 |
|
993 // --------------------------------------------------------- |
|
994 // CMmsServerMtm::DoRunL |
|
995 // Active object completion |
|
996 // Run is used in this object to clean up after operations have finished. |
|
997 // |
|
998 // --------------------------------------------------------- |
|
999 // |
|
1000 void CMmsServerMtm::DoRunL() |
|
1001 { |
|
1002 #ifndef _NO_MMSS_LOGGING_ |
|
1003 TMmsLogger::Log( _L(" MmsServer DoRunL status %d"), iStatus.Int() ); |
|
1004 #endif |
|
1005 |
|
1006 if ( iCurrentCommand == EMmsRetryServiceLoading ) |
|
1007 { |
|
1008 StartCommandL( |
|
1009 *iMsvSelection, |
|
1010 iCurrentCommand, |
|
1011 iParameter, |
|
1012 *iRequestStatus); |
|
1013 return; |
|
1014 } |
|
1015 |
|
1016 TInt error = KErrNone; |
|
1017 |
|
1018 if ( iOOMState ) // out of memory. |
|
1019 { |
|
1020 error = KErrNoMemory; |
|
1021 } |
|
1022 |
|
1023 if ( iCurrentCommand == EMmsUpdateMmboxList ) |
|
1024 { |
|
1025 error = iStatus.Int(); |
|
1026 } |
|
1027 |
|
1028 // When we come here, we must see, if everything |
|
1029 // was sent - or received, or if some items need resceduling |
|
1030 DoComplete( error ); |
|
1031 |
|
1032 } |
|
1033 |
|
1034 // --------------------------------------------------------- |
|
1035 // CMmsServerMtm::DoComplete |
|
1036 // |
|
1037 // Active object complete |
|
1038 // --------------------------------------------------------- |
|
1039 // |
|
1040 void CMmsServerMtm::DoComplete( TInt aError ) |
|
1041 { |
|
1042 #ifndef _NO_MMSS_LOGGING_ |
|
1043 TMmsLogger::Log( _L(" MmsServer DoComplete with status %d"), aError ); |
|
1044 #endif |
|
1045 |
|
1046 // free whatever entry we were holding |
|
1047 iServerEntry->SetEntry( KMsvNullIndexEntryId ); |
|
1048 |
|
1049 // iSendOperation and iReceiveMessage tell us if |
|
1050 // we were sending or receiving. The one that is non-null |
|
1051 // has done all the work |
|
1052 |
|
1053 // Now we must check if all went fine, or do some entries |
|
1054 // need rescheduling. |
|
1055 |
|
1056 // In the case of sending iMsvSelection holds Ids of the |
|
1057 // messages to be sent. In the case of receiving iMsvSelection |
|
1058 // holds Ids of the notifications corresponding to messages |
|
1059 // to be fetched. |
|
1060 |
|
1061 TRAPD( error, UpdateEntriesL() ); |
|
1062 |
|
1063 #ifdef __WINS__ |
|
1064 if ( iSendOperation ) |
|
1065 { |
|
1066 User::InfoPrint(_L("MMS sending complete")); |
|
1067 } |
|
1068 if ( iReceiveMessage ) |
|
1069 { |
|
1070 User::InfoPrint(_L("MMS receiving complete")); |
|
1071 } |
|
1072 #endif |
|
1073 |
|
1074 // restore original entry |
|
1075 iServerEntry->SetEntry( KMsvNullIndexEntryId ); |
|
1076 |
|
1077 if ( iError == KErrNone ) |
|
1078 { |
|
1079 // The error may be changed in UpdateEntriesL |
|
1080 iError = aError; |
|
1081 } |
|
1082 |
|
1083 if ( iError == KMmsErrorApplicationDiskFull ) |
|
1084 { |
|
1085 // this was handled by restarting the fetch if possible |
|
1086 iError = KErrNone; |
|
1087 } |
|
1088 |
|
1089 if ( iError == KErrNone ) |
|
1090 { |
|
1091 // Pass on the error from UpDateEntriesL if it is relevant |
|
1092 // to the caller. |
|
1093 // First all errors caused by simultaneous backup/restore |
|
1094 // are passed on. |
|
1095 // If the entries were successfully reschedules we should |
|
1096 // have no error here. |
|
1097 if ( error >= KMsvMediaUnavailable && error <= KMsvIndexRestore ) |
|
1098 { |
|
1099 iError = error; |
|
1100 } |
|
1101 } |
|
1102 #ifndef _NO_MMSS_LOGGING_ |
|
1103 TMmsLogger::Log( _L("MmsServer returns error: %d to caller" ), iError ); |
|
1104 #endif |
|
1105 if ( !( IsActive() && iStatus.Int() == KRequestPending ) ) |
|
1106 { |
|
1107 // If CMmsServer has become active again it means that it has restarted |
|
1108 // the fetch after deleting some application messages |
|
1109 // The restarted fetch will complete caller when finished |
|
1110 |
|
1111 // However, if any ongoing operation is cancelled prematurely, |
|
1112 // we may still be in active state but our own status is "cancelled" |
|
1113 |
|
1114 User::RequestComplete( iRequestStatus, iError ); |
|
1115 } |
|
1116 } |
|
1117 |
|
1118 // --------------------------------------------------------- |
|
1119 // CMmsServerMtm::LoadSettingsL |
|
1120 // |
|
1121 // --------------------------------------------------------- |
|
1122 // |
|
1123 void CMmsServerMtm::LoadSettingsL( TInt aCommand ) |
|
1124 { |
|
1125 // Load settings |
|
1126 iMmsSettings->LoadSettingsL(); |
|
1127 |
|
1128 // Save service entry id |
|
1129 iServiceEntryId = iMmsSettings->Service(); |
|
1130 |
|
1131 // Make sure localmode related paths exist |
|
1132 if( iMmsSettings->LocalMode() ) |
|
1133 { |
|
1134 iFs.MkDirAll( iMmsSettings->LocalModeIn() ); |
|
1135 iFs.MkDirAll( iMmsSettings->LocalModeOut() ); |
|
1136 } |
|
1137 |
|
1138 // Load schedule settings |
|
1139 ((CMmsScheduleSend*)iScheduleSend)->LoadSettingsL( aCommand ); |
|
1140 } |
|
1141 |
|
1142 // --------------------------------------------------------- |
|
1143 // CMmsServerMtm::SendToMmscL() |
|
1144 // |
|
1145 // --------------------------------------------------------- |
|
1146 // |
|
1147 void CMmsServerMtm::SendToMmscL() |
|
1148 { |
|
1149 // We call our new excellent state machine |
|
1150 delete iSendOperation; |
|
1151 iSendOperation = NULL; |
|
1152 iSendOperation = CMmsSendOperation::NewL( iFs, iMmsSettings ); |
|
1153 iSendOperation->StartL( *iMsvSelection, *iServerEntry, |
|
1154 iServiceEntryId, iStatus ); |
|
1155 *iRequestStatus = KRequestPending; |
|
1156 SetActive(); |
|
1157 } |
|
1158 |
|
1159 // --------------------------------------------------------- |
|
1160 // CMmsServerMtm::SendForwardRequestsToMmscL() |
|
1161 // |
|
1162 // --------------------------------------------------------- |
|
1163 // |
|
1164 void CMmsServerMtm::SendForwardRequestsToMmscL() |
|
1165 { |
|
1166 // |
|
1167 // Create a CMmsForwardOperation instance and start it |
|
1168 // |
|
1169 delete iForwardOperation; |
|
1170 iForwardOperation = NULL; |
|
1171 iForwardOperation = CMmsForwardOperation::NewL( iFs, iMmsSettings ); |
|
1172 iForwardOperation->StartL( |
|
1173 *iMsvSelection, |
|
1174 *iServerEntry, |
|
1175 iServiceEntryId, |
|
1176 iStatus ); |
|
1177 *iRequestStatus = KRequestPending; |
|
1178 SetActive(); |
|
1179 } |
|
1180 |
|
1181 // --------------------------------------------------------- |
|
1182 // CMmsServerMtm::FetchFromMmscL() |
|
1183 // |
|
1184 // --------------------------------------------------------- |
|
1185 // |
|
1186 void CMmsServerMtm::FetchFromMmscL() |
|
1187 { |
|
1188 // We must put notifications into the selection. |
|
1189 // The notifications will be have the same format |
|
1190 // as message entries, but they will contain only |
|
1191 // MMS headers. |
|
1192 |
|
1193 // The test version will use only the URI (Content-Location) |
|
1194 // from the notification. |
|
1195 // The Content-Location will contain the path and filename - |
|
1196 // as the first approximation. |
|
1197 |
|
1198 // For test purposes we create a fake selection by scanning |
|
1199 // the directory specified in the settings, and storing the |
|
1200 // filenames as messages under current service. |
|
1201 |
|
1202 // If we have rescheduled entries, we don't create a new notification |
|
1203 // list, as we have one already |
|
1204 if ( iMsvSelection->Count() < 1 ) |
|
1205 { |
|
1206 CreateNotificationsL(); |
|
1207 } |
|
1208 |
|
1209 // If anything was left, we fetch them |
|
1210 if ( iMsvSelection->Count() > 0 ) |
|
1211 { |
|
1212 // We call our new excellent state machine |
|
1213 delete iReceiveMessage; |
|
1214 iReceiveMessage = NULL; |
|
1215 iReceiveMessage = CMmsReceiveMessage::NewL( iFs, iMmsSettings ); |
|
1216 |
|
1217 iReceiveMessage->StartL( *iMsvSelection, *iServerEntry, |
|
1218 iServiceEntryId, iStatus ); |
|
1219 if ( iRequestStatus->Int() != KRequestPending ) |
|
1220 { |
|
1221 *iRequestStatus = KRequestPending; |
|
1222 } |
|
1223 SetActive(); |
|
1224 } |
|
1225 else |
|
1226 { |
|
1227 // We say we are done without error, if we pruned everything. |
|
1228 // The original notifications that caused the pruning should |
|
1229 // still be hanging around. |
|
1230 // There is a danger of fetching failing so often that |
|
1231 // we cannot even manage to send a response to MMSC, and |
|
1232 // it sends us a duplicate notification because it thinks |
|
1233 // the original one has got lost. |
|
1234 // We must carefully test the failure conditions and try to |
|
1235 // determine reasonable amount of retries that should be done |
|
1236 // to avoid such situation. |
|
1237 // The other possibility would be to always remove the old |
|
1238 // notification if a new one arrives with identical TID and |
|
1239 // Content location, but then we would be in danger of |
|
1240 // deleting an entry that is currently being used to fetch |
|
1241 // a message. |
|
1242 // The actual fetching code in CMmsReceiveMessage class |
|
1243 // tries to test that the notifications are accessible, |
|
1244 // and it tries not to trap, if the notifications have |
|
1245 // disappeared from its lists, |
|
1246 if ( iError != KErrNoMemory && |
|
1247 iError != KErrDiskFull && iError != KMmsErrorApplicationDiskFull ) |
|
1248 { |
|
1249 iError = KErrNone; |
|
1250 } |
|
1251 if ( iRequestStatus->Int() != KRequestPending ) |
|
1252 { |
|
1253 *iRequestStatus = KRequestPending; |
|
1254 } |
|
1255 if ( iError == KMmsErrorApplicationDiskFull ) |
|
1256 { |
|
1257 // DoComplete will complete caller |
|
1258 iError = KErrNone; |
|
1259 } |
|
1260 else |
|
1261 { |
|
1262 User::RequestComplete( iRequestStatus, iError ); |
|
1263 } |
|
1264 } |
|
1265 } |
|
1266 |
|
1267 // --------------------------------------------------------- |
|
1268 // CMmsServerMtm::UpdateEntriesL() |
|
1269 // |
|
1270 // --------------------------------------------------------- |
|
1271 // |
|
1272 void CMmsServerMtm::UpdateEntriesL() |
|
1273 { |
|
1274 // if something goes fatally wrong, this error will be |
|
1275 // returned to the caller in hope the caller may be able |
|
1276 // to do something to fix the problem |
|
1277 TInt fatalError = KErrNone; |
|
1278 TMsvEntry entry; |
|
1279 #ifndef _NO_MMSS_LOGGING_ |
|
1280 TMmsLogger::Log( _L("UpdateEntriesL" )); |
|
1281 #endif |
|
1282 |
|
1283 // Tell scheduler about entries that were successfully sent |
|
1284 // or received |
|
1285 |
|
1286 // Rescedule failed entries |
|
1287 // We have a member that tells which command to use |
|
1288 // (Send or receive) |
|
1289 |
|
1290 // The central repository file contains a list of hopeless cases. |
|
1291 // These are not rescheduled |
|
1292 |
|
1293 TMsvSchedulePackage* schedulePackage = new( ELeave ) TMsvSchedulePackage; |
|
1294 CleanupStack::PushL( schedulePackage ); |
|
1295 PopulateSchedulePackage( iParameter, ETrue, *schedulePackage ); |
|
1296 |
|
1297 // Failed forward entries |
|
1298 if( iForwardOperation && iForwardOperation->Failed().Count() > 0 ) |
|
1299 { |
|
1300 HandleFailedForwardsL( *schedulePackage ); |
|
1301 } |
|
1302 |
|
1303 // Successfully sent entries |
|
1304 if( iSendOperation && iSendOperation->Sent().Count() > 0 ) |
|
1305 { |
|
1306 HandleSuccessfulSendsL(); |
|
1307 } |
|
1308 |
|
1309 // Entries that failed to be sent |
|
1310 if ( iSendOperation && iSendOperation->Failed().Count() > 0 ) |
|
1311 { |
|
1312 HandleFailedSendsL( *schedulePackage ); |
|
1313 } |
|
1314 |
|
1315 // Message generation (branding messages) |
|
1316 if ( iReceiveMessage && iCurrentCommand == EMmsMessageGeneration ) |
|
1317 { |
|
1318 CleanupAfterMessageGenerationL(); |
|
1319 } |
|
1320 |
|
1321 // Mark entries that failed to be fetched |
|
1322 // If there is some error connected to this, it must be returned to caller |
|
1323 // as fetching is automatic. |
|
1324 TBool restartFetch = EFalse; |
|
1325 if ( iReceiveMessage && iReceiveMessage->Failed().Count() > 0 ) |
|
1326 { |
|
1327 restartFetch = HandleFailedReceivesL( *schedulePackage, fatalError ); |
|
1328 } |
|
1329 |
|
1330 // Successfully received entries |
|
1331 if ( iReceiveMessage && iReceiveMessage->Received().Count() > 0 ) |
|
1332 { |
|
1333 HandleSuccessfulReceivesL(); |
|
1334 } |
|
1335 |
|
1336 // Remove bad notifications from task scheduler |
|
1337 if ( iReceiveMessage && iReceiveMessage->BadNotifications().Count() > 0 ) |
|
1338 { |
|
1339 HandleBadNotificationsL(); |
|
1340 } |
|
1341 |
|
1342 if ( restartFetch ) |
|
1343 { |
|
1344 // We did find some failed notifications that were in inbox or MMBox folder |
|
1345 // These are not normally rescheduled |
|
1346 // But if the error was due to lack of disk space and we have been able to |
|
1347 // free the disk space by deleting some older messages belonging to a |
|
1348 // lazy application, we can retry the fetch immediately |
|
1349 |
|
1350 // We must clear the receiver class to start with a clean slate. |
|
1351 delete iReceiveMessage; |
|
1352 iReceiveMessage = NULL; |
|
1353 FetchFromMmscL(); |
|
1354 iError = KMmsErrorApplicationDiskFull; |
|
1355 } |
|
1356 |
|
1357 // update delivery status counts and reschedule possible extra delivcery reports |
|
1358 if ( iCommand == EMmsLogDeliveryReport ) |
|
1359 { |
|
1360 UpdateDeliveryReportsL( *schedulePackage ); |
|
1361 } |
|
1362 |
|
1363 // handle failed read report entries |
|
1364 if ( iReadReport && iReadReport->Failed().Count() > 0 ) |
|
1365 { |
|
1366 HandleFailedReadReports(); |
|
1367 } |
|
1368 |
|
1369 CleanupStack::PopAndDestroy( schedulePackage ); |
|
1370 |
|
1371 #ifndef _NO_MMSS_LOGGING_ |
|
1372 TMmsLogger::Log( _L("UpdateEntriesL done, error: %d" ), iError ); |
|
1373 #endif |
|
1374 if ( fatalError != KErrNone ) |
|
1375 { |
|
1376 #ifndef _NO_MMSS_LOGGING_ |
|
1377 TMmsLogger::Log( _L("UpdateEntriesL, fatal error: %d" ), fatalError ); |
|
1378 #endif |
|
1379 // we catch this |
|
1380 User::Leave( fatalError ); |
|
1381 // return not needed as User::Leave returns |
|
1382 } |
|
1383 } |
|
1384 |
|
1385 // --------------------------------------------------------- |
|
1386 // |
|
1387 // --------------------------------------------------------- |
|
1388 // |
|
1389 void CMmsServerMtm::HandleFailedForwardsL( TMsvSchedulePackage& aPackage ) |
|
1390 { |
|
1391 TInt count = 0; |
|
1392 TMsvEntry entry; |
|
1393 TInt error = KErrNone; |
|
1394 |
|
1395 count = iForwardOperation->Failed().Count(); |
|
1396 #ifndef _NO_MMSS_LOGGING_ |
|
1397 TMmsLogger::Log( _L("- %d failed (not sent) forward entries"), count ); |
|
1398 TInt rescheduled = count; // rescheduled needed only for logging |
|
1399 #endif |
|
1400 // Loop selection and make them reschedulable (readonly == false) |
|
1401 while ( count-- ) |
|
1402 { |
|
1403 if ( iServerEntry->SetEntry( iForwardOperation->Failed().At( count ) ) == KErrNone ) |
|
1404 { |
|
1405 entry = iServerEntry->Entry(); |
|
1406 entry.SetReadOnly( EFalse ); |
|
1407 iServerEntry->ChangeEntry( entry ); // ignore error |
|
1408 } |
|
1409 } |
|
1410 |
|
1411 // |
|
1412 // Now reschedule. |
|
1413 // |
|
1414 iScheduleSend->ReScheduleL( iForwardOperation->Failed(), aPackage ); |
|
1415 |
|
1416 // Mark entries that failed to be rescheduled |
|
1417 count = iForwardOperation->Failed().Count(); |
|
1418 while ( count-- ) |
|
1419 { |
|
1420 if ( iServerEntry->SetEntry( iForwardOperation->Failed().At( count ) ) == KErrNone ) |
|
1421 { |
|
1422 entry = iServerEntry->Entry(); |
|
1423 if ( entry.SendingState() != KMsvSendStateResend ) |
|
1424 { |
|
1425 #ifndef _NO_MMSS_LOGGING_ |
|
1426 TMmsLogger::Log( _L("- forward entry failed to reschedule, setting state to failed") ); |
|
1427 #endif |
|
1428 entry.SetSendingState( KMsvSendStateFailed ); |
|
1429 error = iServerEntry->ChangeEntry( entry ); // ignore error |
|
1430 #ifndef _NO_MMSS_LOGGING_ |
|
1431 if( error != KErrNone ) |
|
1432 { |
|
1433 TMmsLogger::Log( _L("- ERROR: changing entry failed") ); |
|
1434 } |
|
1435 #endif |
|
1436 // Clear related notification from Inbox: |
|
1437 // Get the related notification id |
|
1438 CMsvStore* store = NULL; |
|
1439 store = iServerEntry->EditStoreL(); |
|
1440 CleanupStack::PushL( store ); // *** |
|
1441 iMmsHeaders->RestoreL( *store ); |
|
1442 CleanupStack::PopAndDestroy( store ); |
|
1443 TMsvId relatedEntryId = iMmsHeaders->RelatedEntry(); |
|
1444 iMmsHeaders->Reset(); // headers not needed any more |
|
1445 |
|
1446 if( relatedEntryId != KMsvNullIndexEntryId ) |
|
1447 { |
|
1448 #ifndef _NO_MMSS_LOGGING_ |
|
1449 TMmsLogger::Log( _L("- related notification-entry exists, clearing it") ); |
|
1450 #endif |
|
1451 // Set context (iServerEntry and entry) to notification and clear it |
|
1452 error = iServerEntry->SetEntry( relatedEntryId ); |
|
1453 #ifndef _NO_MMSS_LOGGING_ |
|
1454 if( error != KErrNone ) |
|
1455 { |
|
1456 TMmsLogger::Log( _L("- ERROR: Could not set entry") ); |
|
1457 } |
|
1458 #endif |
|
1459 entry = iServerEntry->Entry(); |
|
1460 entry.iMtmData2 &= ~KMmsNewOperationForbidden; // not forbidden |
|
1461 entry.iMtmData2 &= ~KMmsOperationOngoing; // not ongoing |
|
1462 entry.iMtmData2 |= KMmsOperationFinished; // finished |
|
1463 entry.iMtmData2 |= KMmsOperationResult; // NOK |
|
1464 entry.SetReadOnly( ETrue ); |
|
1465 error = iServerEntry->ChangeEntry( entry ); |
|
1466 #ifndef _NO_MMSS_LOGGING_ |
|
1467 if( error != KErrNone ) |
|
1468 { |
|
1469 TMmsLogger::Log( _L("- ERROR: Could not change related entry") ); |
|
1470 } |
|
1471 TMmsLogger::Log( _L("- Clear the related-entry link itself") ); |
|
1472 #endif |
|
1473 |
|
1474 // Clear related-id link from forward entry |
|
1475 if ( iMsvSelection->Count() > count ) |
|
1476 { |
|
1477 error = iServerEntry->SetEntry( iMsvSelection->At( count ) ); |
|
1478 } |
|
1479 else |
|
1480 { |
|
1481 // We should never get this, |
|
1482 // we check count only to keep CodeScanner happy |
|
1483 error = KErrNotFound; |
|
1484 } |
|
1485 if ( error == KErrNone ) |
|
1486 { |
|
1487 store = iServerEntry->EditStoreL(); |
|
1488 CleanupStack::PushL( store ); // *** |
|
1489 iMmsHeaders->RestoreL( *store ); |
|
1490 iMmsHeaders->SetRelatedEntry( KMsvNullIndexEntryId ); |
|
1491 iMmsHeaders->StoreL( *store ); |
|
1492 store->CommitL(); |
|
1493 CleanupStack::PopAndDestroy( store ); |
|
1494 iMmsHeaders->Reset(); // headers not needed any more |
|
1495 #ifndef _NO_MMSS_LOGGING_ |
|
1496 TMmsLogger::Log( _L("- Related-entry and the link cleared") ); |
|
1497 #endif |
|
1498 } |
|
1499 } |
|
1500 |
|
1501 // let go of the entry |
|
1502 iServerEntry->SetEntry( KMsvNullIndexEntryId ); |
|
1503 } |
|
1504 else |
|
1505 { |
|
1506 // |
|
1507 // Delete successfully rescheduled entries |
|
1508 // |
|
1509 #ifndef _NO_MMSS_LOGGING_ |
|
1510 TMmsLogger::Log( _L("- notification is in resend, as it should") ); |
|
1511 #endif |
|
1512 iForwardOperation->Failed().Delete( count ); |
|
1513 } |
|
1514 } |
|
1515 #ifndef _NO_MMSS_LOGGING_ |
|
1516 else |
|
1517 { |
|
1518 TMmsLogger::Log( _L("- ERROR: could not access entry %d"), count ); |
|
1519 } |
|
1520 #endif |
|
1521 } |
|
1522 |
|
1523 #ifndef _NO_MMSS_LOGGING_ |
|
1524 count = iForwardOperation->Failed().Count(); |
|
1525 rescheduled = rescheduled - count; |
|
1526 if ( rescheduled > 0 ) |
|
1527 { |
|
1528 TMmsLogger::Log( _L("- %d rescheduled forward entries"), rescheduled ); |
|
1529 } |
|
1530 if ( count > 0 ) |
|
1531 { |
|
1532 TMmsLogger::Log( _L("- %d not rescheduled forward entries"), count ); |
|
1533 } |
|
1534 #endif |
|
1535 } |
|
1536 |
|
1537 // --------------------------------------------------------- |
|
1538 // |
|
1539 // --------------------------------------------------------- |
|
1540 // |
|
1541 void CMmsServerMtm::HandleSuccessfulSendsL() |
|
1542 { |
|
1543 TInt count = 0; |
|
1544 TMsvEntry entry; |
|
1545 |
|
1546 // Delete schedule should not be needed in the case of successfully |
|
1547 // sent entries. |
|
1548 count = iSendOperation->Sent().Count(); |
|
1549 #ifndef _NO_MMSS_LOGGING_ |
|
1550 TMmsLogger::Log( _L("- %d Sent entries"), count ); |
|
1551 #endif |
|
1552 iScheduleSend->DeleteScheduleL( iSendOperation->Sent() ); |
|
1553 while ( count-- ) |
|
1554 { |
|
1555 if ( iServerEntry->SetEntry( iSendOperation->Sent().At( count ) ) == KErrNone ) |
|
1556 { |
|
1557 entry = iServerEntry->Entry(); |
|
1558 entry.SetSendingState( KMsvSendStateSent ); |
|
1559 if ( entry.Parent() == KMsvSentEntryIdValue ) |
|
1560 { |
|
1561 // if we have not managed to move this entry away from outbox, |
|
1562 // it must not be set to read only state |
|
1563 entry.SetReadOnly( ETrue ); |
|
1564 } |
|
1565 // We don't want to leave here, we want to continue. |
|
1566 // The next message may succeed. |
|
1567 // We don't consider this fatal: If the message |
|
1568 // has been successfully sent, it should already |
|
1569 // be moved to sent folder. |
|
1570 // If the user tries to send messages during backup/restore, |
|
1571 // it is his own fault if the messages are sent more than once. |
|
1572 iServerEntry->ChangeEntry( entry ); |
|
1573 } |
|
1574 } |
|
1575 } |
|
1576 |
|
1577 // --------------------------------------------------------- |
|
1578 // |
|
1579 // --------------------------------------------------------- |
|
1580 // |
|
1581 void CMmsServerMtm::HandleFailedSendsL( TMsvSchedulePackage& aPackage ) |
|
1582 { |
|
1583 TInt count = 0; |
|
1584 TMsvEntry entry; |
|
1585 |
|
1586 count = iSendOperation->Failed().Count(); |
|
1587 #ifndef _NO_MMSS_LOGGING_ |
|
1588 TInt rescheduled = count; |
|
1589 TMmsLogger::Log( _L("- %d failed (not sent) entries"), count ); |
|
1590 #endif |
|
1591 while ( count-- ) |
|
1592 { |
|
1593 if ( iServerEntry->SetEntry( iSendOperation->Failed().At( count ) ) == KErrNone ) |
|
1594 { |
|
1595 entry = iServerEntry->Entry(); |
|
1596 // we set the entry into failed state after we have |
|
1597 // checked if it still can be rescheduled. |
|
1598 entry.SetReadOnly( EFalse ); |
|
1599 iServerEntry->ChangeEntry( entry ); // ignore error |
|
1600 if ( entry.SendingState() == KMsvSendStateSuspended && |
|
1601 entry.iError != KMmsErrorOfflineMode ) |
|
1602 { |
|
1603 // suspended by user, not offline mode |
|
1604 // We remove this just in case. |
|
1605 // If everything has gone well, the error is "KErrNotFound" |
|
1606 // and the entry would not be rescheduled, but this is an |
|
1607 // extra precaution. |
|
1608 iSendOperation->Failed().Delete( count ); |
|
1609 } |
|
1610 } |
|
1611 } |
|
1612 |
|
1613 iServerEntry->SetEntry( KMsvNullIndexEntryId ); |
|
1614 count = iSendOperation->Failed().Count(); |
|
1615 |
|
1616 if ( count > 0 ) |
|
1617 { |
|
1618 // Check needed to avoid a stupid ASSERT_DEBUG |
|
1619 iScheduleSend->ReScheduleL( iSendOperation->Failed(), aPackage ); |
|
1620 } |
|
1621 |
|
1622 // Mark entries that failed to be rescheduled |
|
1623 count = iSendOperation->Failed().Count(); |
|
1624 |
|
1625 while ( count-- ) |
|
1626 { |
|
1627 if ( iServerEntry->SetEntry( iSendOperation->Failed().At( count ) ) == KErrNone ) |
|
1628 { |
|
1629 entry = iServerEntry->Entry(); |
|
1630 if ( entry.SendingState() != KMsvSendStateResend ) |
|
1631 { |
|
1632 #ifndef _NO_MMSS_LOGGING_ |
|
1633 TMmsLogger::Log( _L("- setting state to failed") ); |
|
1634 #endif |
|
1635 entry.SetSendingState( KMsvSendStateFailed ); |
|
1636 iServerEntry->ChangeEntry( entry ); // ignore error |
|
1637 // let go of the entry |
|
1638 iServerEntry->SetEntry( KMsvNullIndexEntryId ); |
|
1639 } |
|
1640 else |
|
1641 { |
|
1642 iSendOperation->Failed().Delete( count ); |
|
1643 } |
|
1644 } |
|
1645 #ifndef _NO_MMSS_LOGGING_ |
|
1646 else |
|
1647 { |
|
1648 TMmsLogger::Log( _L("- could not access entry %d"), count ); |
|
1649 } |
|
1650 #endif |
|
1651 } |
|
1652 |
|
1653 count = iSendOperation->Failed().Count(); |
|
1654 #ifndef _NO_MMSS_LOGGING_ |
|
1655 rescheduled = rescheduled - count; |
|
1656 if ( rescheduled > 0 ) |
|
1657 { |
|
1658 TMmsLogger::Log( _L("- %d rescheduled for sending"), rescheduled ); |
|
1659 } |
|
1660 if ( count > 0 ) |
|
1661 { |
|
1662 TMmsLogger::Log( _L("- %d hopeless, not rescheduled for sending"), count ); |
|
1663 } |
|
1664 #endif |
|
1665 |
|
1666 } |
|
1667 |
|
1668 // --------------------------------------------------------- |
|
1669 // |
|
1670 // --------------------------------------------------------- |
|
1671 // |
|
1672 void CMmsServerMtm::CleanupAfterMessageGenerationL() |
|
1673 { |
|
1674 #ifndef _NO_MMSS_LOGGING_ |
|
1675 TMmsLogger::Log( _L("- Finished message generation") ); |
|
1676 #endif |
|
1677 // we try only once. |
|
1678 // The whole selection must be in the same place. |
|
1679 CMsvEntrySelection* selection = new( ELeave ) CMsvEntrySelection; |
|
1680 CleanupStack::PushL( selection ); |
|
1681 |
|
1682 // everything must go. |
|
1683 if ( iReceiveMessage->BadNotifications().Count() > 0 ) |
|
1684 { |
|
1685 selection->AppendL( iReceiveMessage->BadNotifications().Back( 0 ), |
|
1686 iReceiveMessage->BadNotifications().Count() ); |
|
1687 iReceiveMessage->BadNotifications().Reset(); |
|
1688 } |
|
1689 |
|
1690 if ( iReceiveMessage->Failed().Count() > 0 ) |
|
1691 { |
|
1692 selection->AppendL( iReceiveMessage->Failed().Back( 0 ), |
|
1693 iReceiveMessage->Failed().Count() ); |
|
1694 iReceiveMessage->Failed().Reset(); |
|
1695 } |
|
1696 |
|
1697 if ( iReceiveMessage->Received().Count() > 0 ) |
|
1698 { |
|
1699 selection->AppendL( iReceiveMessage->Received().Back( 0 ), |
|
1700 iReceiveMessage->Received().Count() ); |
|
1701 iReceiveMessage->Received().Reset(); |
|
1702 } |
|
1703 |
|
1704 // If the next loop fails, we don't care: |
|
1705 // The files will be deleted ayway, and the notifications will be orphaned |
|
1706 // If there is something weird going on during the boot, |
|
1707 // the phone won't probably work after this anyway. |
|
1708 if ( selection->Count() > 0 ) |
|
1709 { |
|
1710 if ( iServerEntry->SetEntry( selection->At( 0 ) ) == KErrNone ) |
|
1711 { |
|
1712 if ( iServerEntry->SetEntry( iServerEntry->Entry().Parent() ) == KErrNone ) |
|
1713 { |
|
1714 iServerEntry->DeleteEntries( *selection ); |
|
1715 } |
|
1716 } |
|
1717 iServerEntry->SetEntry( KMsvNullIndexEntryId ); |
|
1718 } |
|
1719 CleanupStack::PopAndDestroy( selection ); |
|
1720 |
|
1721 // Then we delete the files in the directory |
|
1722 // (if anything left) |
|
1723 CFileMan* fileMan = CFileMan::NewL( iFs ); |
|
1724 CleanupStack::PushL( fileMan ); |
|
1725 // Best effort - ignore error |
|
1726 fileMan->RmDir( KMmsMessageVariationDirectory ); |
|
1727 CleanupStack::PopAndDestroy( fileMan ); |
|
1728 |
|
1729 } |
|
1730 |
|
1731 // --------------------------------------------------------- |
|
1732 // |
|
1733 // --------------------------------------------------------- |
|
1734 // |
|
1735 TBool CMmsServerMtm::HandleFailedReceivesL( TMsvSchedulePackage& aPackage, TInt& aFatalError ) |
|
1736 { |
|
1737 TInt count = 0; |
|
1738 TMsvEntry entry; |
|
1739 TInt error = KErrNone; |
|
1740 TBool restartFetch = EFalse; |
|
1741 |
|
1742 iMsvSelection->Reset(); |
|
1743 count = iReceiveMessage->Failed().Count(); |
|
1744 #ifndef _NO_MMSS_LOGGING_ |
|
1745 TMmsLogger::Log( _L("- %d failed (not received) entries"), count ); |
|
1746 #endif |
|
1747 // Check if the current receive mode is manual |
|
1748 TBool manual = EFalse; |
|
1749 if( iReceiveMessage->InForeignNetwork() ) |
|
1750 { |
|
1751 if( iMmsSettings->ReceivingModeForeign() == EMmsReceivingManual ) |
|
1752 { |
|
1753 manual = ETrue; |
|
1754 } |
|
1755 } |
|
1756 else |
|
1757 { |
|
1758 if( iMmsSettings->ReceivingModeHome() == EMmsReceivingManual ) |
|
1759 { |
|
1760 manual = ETrue; |
|
1761 } |
|
1762 } |
|
1763 |
|
1764 TBool inInbox = EFalse; |
|
1765 TBool inMmsFolder = EFalse; |
|
1766 TBool inMmboxFolder = EFalse; |
|
1767 |
|
1768 while ( count-- ) |
|
1769 { |
|
1770 error = iServerEntry->SetEntry( iReceiveMessage->Failed().At( count ) ); |
|
1771 if ( error == KErrNone ) |
|
1772 { |
|
1773 entry = iServerEntry->Entry(); |
|
1774 |
|
1775 if ( entry.iMtmData2 & KMmsDoNotMoveToInbox ) |
|
1776 { |
|
1777 #ifndef _NO_MMSS_LOGGING_ |
|
1778 TMmsLogger::Log( _L("- do not move entry to inbox ")); |
|
1779 #endif |
|
1780 // We do not reschedule this. It will potentially cause problems at mode change |
|
1781 // if it has not been handled by then. |
|
1782 iReceiveMessage->Failed().Delete( count ); |
|
1783 // it is put into bad list and deleted later |
|
1784 iReceiveMessage->BadNotifications().AppendL( entry.Id() ); |
|
1785 } |
|
1786 else |
|
1787 { |
|
1788 if ( entry.Parent() == FindMMSFolderL() ) |
|
1789 { |
|
1790 inMmsFolder = ETrue; |
|
1791 } |
|
1792 else if ( entry.Parent() == KMsvGlobalInBoxIndexEntryIdValue ) |
|
1793 { |
|
1794 inInbox = ETrue; |
|
1795 // inbox entries will not be rescheduled |
|
1796 if ( entry.iError == KMmsErrorApplicationDiskFull ) |
|
1797 { |
|
1798 // This is best effort only - error ignored |
|
1799 iMsvSelection->AppendL( iReceiveMessage->Failed().At( count ) ); |
|
1800 restartFetch = ETrue; |
|
1801 } |
|
1802 iReceiveMessage->Failed().Delete( count ); |
|
1803 } |
|
1804 else |
|
1805 { |
|
1806 inMmboxFolder = ETrue; |
|
1807 if ( entry.iError == KMmsErrorApplicationDiskFull ) |
|
1808 { |
|
1809 // This is best effort only - error ignored |
|
1810 iMsvSelection->AppendL( iReceiveMessage->Failed().At( count ) ); |
|
1811 restartFetch = ETrue; |
|
1812 } |
|
1813 // mmbox entries will not be rescheduled |
|
1814 iReceiveMessage->Failed().Delete( count ); |
|
1815 manual = EFalse; // manual mode must not affect the mmbox notification |
|
1816 } |
|
1817 // We don't have a separate receiving state. |
|
1818 // We just use sending state instead. |
|
1819 // We are the only one that uses scheduled receiving. |
|
1820 #ifndef _NO_MMSS_LOGGING_ |
|
1821 TMmsLogger::Log( _L("- marking sending state as failed ")); |
|
1822 #endif |
|
1823 entry.SetSendingState( KMsvSendStateFailed ); |
|
1824 |
|
1825 if ( manual && inMmsFolder ) |
|
1826 { |
|
1827 // Change the iMtm from KUidMsgTypeMultimedia to |
|
1828 // KUidMsgMMSNotification |
|
1829 entry.iMtm.iUid = KUidMsgMMSNotification.iUid; // this is a notification |
|
1830 |
|
1831 entry.iMtmData2 &= ~KMmsOperationFinished; // clear flag just in case |
|
1832 entry.iMtmData2 &= ~KMmsOperationResult; // clear flag just in case |
|
1833 entry.iMtmData2 &= ~KMmsOperationOngoing; // Fetch operation is not active anymore |
|
1834 entry.iMtmData2 &= ~KMmsNewOperationForbidden; // New operation can be started |
|
1835 entry.iMtmData1 |= KMmsMessageMobileTerminated; |
|
1836 entry.SetReadOnly( ETrue ); |
|
1837 entry.iError = KErrNone; |
|
1838 entry.SetSendingState( KMsvSendStateUnknown ); |
|
1839 } |
|
1840 else if ( inInbox ) |
|
1841 { |
|
1842 // Mark original notification |
|
1843 CMmsBaseOperation::MarkNotificationOperationFailed( entry ); |
|
1844 if ( entry.iError != KMmsErrorApplicationDiskFull ) |
|
1845 { |
|
1846 entry.SetReadOnly( ETrue ); |
|
1847 } |
|
1848 } |
|
1849 else if ( inMmboxFolder ) |
|
1850 { |
|
1851 #ifndef _NO_MMSS_LOGGING_ |
|
1852 TMmsLogger::Log( _L("- in mmbox folder")); |
|
1853 #endif |
|
1854 TRAP( error, CMmsBaseOperation::MarkDuplicateL( |
|
1855 CMmsBaseOperation::EMmsNotificationOperationFailed, |
|
1856 *iServerEntry ) ); |
|
1857 error = KErrNone; // ignore error from trap |
|
1858 entry = iServerEntry->Entry(); |
|
1859 CMmsBaseOperation::MarkNotificationOperationFailed( entry ); |
|
1860 if ( entry.iError != KMmsErrorApplicationDiskFull ) |
|
1861 { |
|
1862 entry.SetReadOnly( ETrue ); |
|
1863 } |
|
1864 #ifndef _NO_MMSS_LOGGING_ |
|
1865 TMmsLogger::Log( _L("- marking original notif failed")); |
|
1866 #endif |
|
1867 } |
|
1868 else |
|
1869 { |
|
1870 // keep LINT happy |
|
1871 } |
|
1872 error = iServerEntry->ChangeEntry( entry ); |
|
1873 |
|
1874 // move the entry from mms folder to the inbox in manual mode. |
|
1875 if ( manual && inMmsFolder ) |
|
1876 { |
|
1877 iError = iServerEntry->SetEntry( entry.Parent() ); |
|
1878 if ( iError == KErrNone ) |
|
1879 { |
|
1880 error = iServerEntry->MoveEntryWithinService( |
|
1881 entry.Id(), KMsvGlobalInBoxIndexEntryIdValue ); |
|
1882 } |
|
1883 else |
|
1884 { |
|
1885 error = iError; |
|
1886 } |
|
1887 if ( error == KErrNone ) |
|
1888 { |
|
1889 inInbox = ETrue; |
|
1890 // This should not be rescheduled as it has moved to inbox |
|
1891 iReceiveMessage->Failed().Delete( count ); |
|
1892 } |
|
1893 } |
|
1894 } |
|
1895 if ( aFatalError == KErrNone ) |
|
1896 { |
|
1897 // if we canot access the entry, tell the caller |
|
1898 aFatalError = error; |
|
1899 } |
|
1900 // let go of the entry |
|
1901 iServerEntry->SetEntry( KMsvNullIndexEntryId ); |
|
1902 #ifndef _NO_MMSS_LOGGING_ |
|
1903 TMmsLogger::Log( _L("UpdateEntriesL: entry #%d, sending state = failed"), count ); |
|
1904 TMmsLogger::Log( _L("UpdateEntriesL: entry #%d, error = %d"), count, entry.iError ); |
|
1905 if ( error != KErrNone ) |
|
1906 { |
|
1907 TMmsLogger::Log( _L("UpdateEntriesL: ChangeEntry failed, error %d"), error ); |
|
1908 } |
|
1909 #endif |
|
1910 } |
|
1911 #ifndef _NO_MMSS_LOGGING_ |
|
1912 else |
|
1913 { |
|
1914 // Not found is not fatal. What is gone is gone. |
|
1915 if ( error != KErrNotFound ) |
|
1916 { |
|
1917 if ( aFatalError == KErrNone ) |
|
1918 { |
|
1919 aFatalError = error; |
|
1920 } |
|
1921 } |
|
1922 TMmsLogger::Log( _L("UpdateEntriesL: could not access entry #%d"), count ); |
|
1923 } |
|
1924 #endif |
|
1925 } |
|
1926 |
|
1927 // only if the notification is in mmsfolder, reschedule the notification |
|
1928 // if the notification is in Inbox or in mmbox folder, do not rescedule. |
|
1929 // We have removed each notification from failed list if it was originally |
|
1930 // in inbox or in MMBox folder or if it was successfully moved to inbox |
|
1931 if( iReceiveMessage->Failed().Count() > 0 ) |
|
1932 { |
|
1933 iScheduleSend->ReScheduleL( iReceiveMessage->Failed(), aPackage ); |
|
1934 } |
|
1935 // The messages that could not be rescheduled anymore, are either deleted, or moved |
|
1936 // to Inbox to be handled manually |
|
1937 count = iReceiveMessage->Failed().Count(); |
|
1938 // we do not delete hopeless entries: |
|
1939 // There is a separate error watcher that decides |
|
1940 // what to do with them. |
|
1941 // For example: If there is no access point, receiving |
|
1942 // fails. The error watcher gives notice to user, and |
|
1943 // when the user has entered the access point, the |
|
1944 // fetch is restarted by the error watcher. |
|
1945 #ifndef _NO_MMSS_LOGGING_ |
|
1946 TInt hopeless = count; |
|
1947 #endif |
|
1948 while ( count-- ) |
|
1949 { |
|
1950 TMsvId failedEntry = iReceiveMessage->Failed().At( count ); |
|
1951 if ( iServerEntry->SetEntry( failedEntry ) == KErrNone ) |
|
1952 { |
|
1953 entry = iServerEntry->Entry(); |
|
1954 // update retry count |
|
1955 TRAP( error, |
|
1956 { |
|
1957 CMsvStore* store = NULL; |
|
1958 store = iServerEntry->ReadStoreL(); |
|
1959 CleanupStack::PushL( store ); |
|
1960 CMmsScheduledEntry* mmsScheduledEntry = |
|
1961 CMmsScheduledEntry::NewL( iServerEntry->Entry() ); |
|
1962 CleanupStack::PushL( mmsScheduledEntry ); |
|
1963 mmsScheduledEntry->RestoreL( *store ); |
|
1964 entry.iMtmData3 &= ~KMmsRetryCountMask; |
|
1965 entry.iMtmData3 |= mmsScheduledEntry->MmsRecipient().Retries(); |
|
1966 iServerEntry->ChangeEntry( entry ); |
|
1967 CleanupStack::PopAndDestroy( mmsScheduledEntry ); |
|
1968 CleanupStack::PopAndDestroy( store ); |
|
1969 } |
|
1970 ); |
|
1971 |
|
1972 if ( entry.SendingState() == KMsvSendStateFailed ) |
|
1973 { |
|
1974 // remove from list just to see what was left over |
|
1975 iReceiveMessage->Failed().Delete( count ); |
|
1976 } |
|
1977 } |
|
1978 } |
|
1979 #ifndef _NO_MMSS_LOGGING_ |
|
1980 count = iReceiveMessage->Failed().Count(); |
|
1981 hopeless = hopeless - count; |
|
1982 if ( count > 0 ) |
|
1983 { |
|
1984 TMmsLogger::Log( _L("- %d rescheduled for receiving"), count ); |
|
1985 } |
|
1986 if ( hopeless > 0 ) |
|
1987 { |
|
1988 TMmsLogger::Log( _L("- %d hopeless, not rescheduled for receiving"), hopeless ); |
|
1989 } |
|
1990 #endif |
|
1991 |
|
1992 return restartFetch; |
|
1993 } |
|
1994 |
|
1995 // --------------------------------------------------------- |
|
1996 // |
|
1997 // --------------------------------------------------------- |
|
1998 // |
|
1999 void CMmsServerMtm::HandleSuccessfulReceivesL() |
|
2000 { |
|
2001 #ifndef _NO_MMSS_LOGGING_ |
|
2002 TMmsLogger::Log( _L("- %d received entries"), iReceiveMessage->Received().Count() ); |
|
2003 #endif |
|
2004 TMsvId parent = KMsvNullIndexEntryId; |
|
2005 // The whole selection must be in the same place. |
|
2006 if ( iServerEntry->SetEntry( iReceiveMessage->Received().At( 0 ) ) == KErrNone ) |
|
2007 { |
|
2008 parent = iServerEntry->Entry().Parent(); |
|
2009 } |
|
2010 |
|
2011 CMsvEntrySelection* selection = new( ELeave ) CMsvEntrySelection; |
|
2012 CleanupStack::PushL( selection ); |
|
2013 selection->AppendL( iReceiveMessage->Received().Back( 0 ), |
|
2014 iReceiveMessage->Received().Count() ); |
|
2015 |
|
2016 // if entry is in inbox or in MMBoxfolder, |
|
2017 // check possible duplicate and mark it "fetched from server" |
|
2018 if ( parent == KMsvGlobalInBoxIndexEntryIdValue || parent == iMmsSettings->MMBoxFolder() ) |
|
2019 { |
|
2020 for ( TInt i = selection->Count(); i > 0; i-- ) |
|
2021 { |
|
2022 if ( iServerEntry->SetEntry( selection->At( i - 1 )) == KErrNone ) |
|
2023 { |
|
2024 #ifndef _NO_MMSS_LOGGING_ |
|
2025 TMmsLogger::Log( _L("- check possible duplicate" )); |
|
2026 #endif |
|
2027 CMsvStore* store = iServerEntry->ReadStoreL(); |
|
2028 CleanupStack::PushL( store ); |
|
2029 iMmsHeaders->RestoreL( *store ); |
|
2030 CleanupStack::PopAndDestroy( store ); |
|
2031 store = NULL; |
|
2032 TMsvId duplicate = KMsvNullIndexEntryId; |
|
2033 |
|
2034 if ( parent == KMsvGlobalInBoxIndexEntryIdValue ) |
|
2035 { |
|
2036 TMsvId mmboxFolder = iMmsSettings->MMBoxFolder(); |
|
2037 if ( mmboxFolder != KMsvNullIndexEntryId ) |
|
2038 { |
|
2039 FindDuplicateNotificationL( mmboxFolder, *iMmsHeaders, duplicate ); |
|
2040 } |
|
2041 } |
|
2042 else // parent is mmbox folder |
|
2043 { |
|
2044 duplicate = iMmsHeaders->RelatedEntry(); |
|
2045 } |
|
2046 if ( duplicate != KMsvNullIndexEntryId ) |
|
2047 { |
|
2048 #ifndef _NO_MMSS_LOGGING_ |
|
2049 TMmsLogger::Log( _L("- duplicate found")); |
|
2050 #endif |
|
2051 if ( iServerEntry->SetEntry( duplicate ) == KErrNone ) |
|
2052 { |
|
2053 // Mark duplicate |
|
2054 TMsvEntry dupEntry = iServerEntry->Entry(); |
|
2055 CMmsBaseOperation::MarkNotificationDeletedFromMmbox( dupEntry ); |
|
2056 iServerEntry->ChangeEntry( dupEntry ); |
|
2057 #ifndef _NO_MMSS_LOGGING_ |
|
2058 TMmsLogger::Log( _L("- duplicate marked as fetched from mmbox")); |
|
2059 #endif |
|
2060 } |
|
2061 } |
|
2062 } |
|
2063 } |
|
2064 } |
|
2065 if ( parent != KMsvNullIndexEntryId && iServerEntry->SetEntry( parent ) == KErrNone ) |
|
2066 { |
|
2067 iServerEntry->DeleteEntries( *selection ); |
|
2068 } |
|
2069 CleanupStack::PopAndDestroy( selection ); |
|
2070 } |
|
2071 |
|
2072 // --------------------------------------------------------- |
|
2073 // |
|
2074 // --------------------------------------------------------- |
|
2075 // |
|
2076 void CMmsServerMtm::HandleBadNotificationsL() |
|
2077 { |
|
2078 #ifndef _NO_MMSS_LOGGING_ |
|
2079 TMmsLogger::Log( _L("- %d bad notification entries"), iReceiveMessage->BadNotifications().Count() ); |
|
2080 #endif |
|
2081 // The whole selection must be in the same place. |
|
2082 if ( iServerEntry->SetEntry( iReceiveMessage->BadNotifications().At( 0 ) ) == KErrNone ) |
|
2083 { |
|
2084 if ( iServerEntry->SetEntry( iServerEntry->Entry().Parent() ) == KErrNone ) |
|
2085 { |
|
2086 CMsvEntrySelection* selection = new( ELeave ) CMsvEntrySelection; |
|
2087 CleanupStack::PushL( selection ); |
|
2088 selection->AppendL( iReceiveMessage->BadNotifications().Back( 0 ), |
|
2089 iReceiveMessage->BadNotifications().Count() ); |
|
2090 iServerEntry->DeleteEntries( *selection ); |
|
2091 CleanupStack::PopAndDestroy( selection ); |
|
2092 } |
|
2093 } |
|
2094 } |
|
2095 |
|
2096 // --------------------------------------------------------- |
|
2097 // |
|
2098 // --------------------------------------------------------- |
|
2099 // |
|
2100 void CMmsServerMtm::UpdateDeliveryReportsL( TMsvSchedulePackage& aPackage ) |
|
2101 { |
|
2102 TInt error = KErrNone; |
|
2103 TMsvEntry entry; |
|
2104 |
|
2105 #ifndef _NO_MMSS_LOGGING_ |
|
2106 TMmsLogger::Log( _L("- logged delivery report" )); |
|
2107 #endif |
|
2108 if ( iError == KErrNone ) |
|
2109 { |
|
2110 // first entry in selection was handled |
|
2111 CMsvEntrySelection* selection = new( ELeave ) CMsvEntrySelection; |
|
2112 CleanupStack::PushL( selection ); |
|
2113 selection->AppendL( iMsvSelection->At( 0 ), 1 ); |
|
2114 if ( selection->Count() > 0 ) |
|
2115 { |
|
2116 error = iServerEntry->SetEntry( selection->At( 0 ) ); |
|
2117 } |
|
2118 else |
|
2119 { |
|
2120 // this will never happen - we are just keeping codescanner happy |
|
2121 error = KErrNotFound; |
|
2122 } |
|
2123 if ( error == KErrNone ) |
|
2124 { |
|
2125 if ( iServerEntry->SetEntry( iServerEntry->Entry().Parent() ) == KErrNone ) |
|
2126 { |
|
2127 iServerEntry->DeleteEntries( *selection ); |
|
2128 } |
|
2129 } |
|
2130 CleanupStack::PopAndDestroy( selection ); |
|
2131 iMsvSelection->Delete( 0 ); |
|
2132 } |
|
2133 |
|
2134 //Now let's set delivery report bits in MtmData |
|
2135 TMsvId link = 0; |
|
2136 if ( iMmsLog ) |
|
2137 { |
|
2138 link = iMmsLog->GetLink(); |
|
2139 } |
|
2140 if (link != 0) |
|
2141 { |
|
2142 error = iServerEntry->SetEntry(link); |
|
2143 if ( error == KErrNone ) |
|
2144 { |
|
2145 entry = iServerEntry->Entry(); |
|
2146 } |
|
2147 } |
|
2148 |
|
2149 // Even if the link exists, the original message may have disappeared already |
|
2150 // (if only 20 messages are saved in outbox, they may start disappearing quite fast) |
|
2151 if ( link != 0 && error == KErrNone && ( entry.iMtmData2 & KMmsDeliveryStatusMask ) != |
|
2152 KMmsDeliveryStatusNotRequested ) |
|
2153 { |
|
2154 TUint temp(0); |
|
2155 TUint total(0); |
|
2156 if (iDeliveryStatus) //Succesfully delivered |
|
2157 { |
|
2158 total = ( entry.iMtmData3 & KMmsSentItemTotalRecipientsMask ) >> |
|
2159 KMmsSentItemTotalRecipientsShift; |
|
2160 |
|
2161 temp = ( entry.iMtmData3 & KMmsSentItemSuccessfullyDeliveredMask ) |
|
2162 >> KMmsSentItemSuccessfullyDeliveredShift; |
|
2163 temp++; |
|
2164 entry.iMtmData3 &= ~KMmsSentItemSuccessfullyDeliveredMask; |
|
2165 entry.iMtmData3 |= temp << KMmsSentItemSuccessfullyDeliveredShift; |
|
2166 |
|
2167 // must make sure that if even one send has been failed the delivery status |
|
2168 // is always failed |
|
2169 if ( temp == total && ( entry.iMtmData2 & KMmsDeliveryStatusMask ) |
|
2170 != KMmsDeliveryStatysFailed ) |
|
2171 { |
|
2172 entry.iMtmData2 &= ~KMmsDeliveryStatusMask; |
|
2173 entry.iMtmData2 |= KMmsDeliveryStatysDelivered; |
|
2174 } |
|
2175 else if (temp < total && ( entry.iMtmData2 & KMmsDeliveryStatusMask ) |
|
2176 != KMmsDeliveryStatysFailed ) |
|
2177 { |
|
2178 entry.iMtmData2 &= ~KMmsDeliveryStatusMask; |
|
2179 entry.iMtmData2 |= KMmsDeliveryStatusPartial; |
|
2180 } |
|
2181 else |
|
2182 { |
|
2183 // keep LINT happy |
|
2184 } |
|
2185 |
|
2186 } |
|
2187 else |
|
2188 { |
|
2189 temp = (entry.iMtmData3 & KMmsSentItemFailedDeliveryMask) >> |
|
2190 KMmsSentItemFailedDeliveryShift; |
|
2191 temp++; |
|
2192 entry.iMtmData3 &= ~KMmsSentItemFailedDeliveryMask; |
|
2193 entry.iMtmData3 |= temp << KMmsSentItemFailedDeliveryShift; |
|
2194 entry.iMtmData2 &= ~KMmsDeliveryStatusMask; |
|
2195 entry.iMtmData2 |= KMmsDeliveryStatysFailed; |
|
2196 |
|
2197 |
|
2198 } |
|
2199 // If we successfully accessed the entry, iServerEntry must still be pointing to the link. |
|
2200 iServerEntry->ChangeEntry(entry); |
|
2201 } |
|
2202 |
|
2203 iError = KErrNone; // we don't care about the error. |
|
2204 // We should normally never be here, delivery reports come |
|
2205 // one at a time... |
|
2206 if ( iMsvSelection->Count() > 0 ) |
|
2207 { |
|
2208 iScheduleSend->ReScheduleL( *iMsvSelection, aPackage ); |
|
2209 } |
|
2210 } |
|
2211 |
|
2212 // --------------------------------------------------------- |
|
2213 // |
|
2214 // --------------------------------------------------------- |
|
2215 // |
|
2216 void CMmsServerMtm::HandleFailedReadReports() |
|
2217 { |
|
2218 TInt error = KErrNone; |
|
2219 if ( iReadReport->Failed().Count() > 0 ) |
|
2220 { |
|
2221 error = iServerEntry->SetEntry( iReadReport->Failed().At( 0 ) ); |
|
2222 } |
|
2223 else |
|
2224 { |
|
2225 error = KErrNotFound; |
|
2226 } |
|
2227 if ( error == KErrNone ) |
|
2228 { |
|
2229 error = iServerEntry->SetEntry( iServerEntry->Entry().Parent() ); |
|
2230 } |
|
2231 if ( error == KErrNone ) |
|
2232 { |
|
2233 TInt i; |
|
2234 for ( i = iReadReport->Failed().Count() - 1; i >= 0; i-- ) |
|
2235 { |
|
2236 iServerEntry->DeleteEntry( iReadReport->Failed().At( i ) ); |
|
2237 } |
|
2238 } |
|
2239 } |
|
2240 |
|
2241 // --------------------------------------------------------- |
|
2242 // |
|
2243 // --------------------------------------------------------- |
|
2244 // |
|
2245 void CMmsServerMtm::MakeDatesIdenticalL( |
|
2246 CMsvEntrySelection& aSelection, |
|
2247 TTimeIntervalSeconds aInterval, |
|
2248 TBool aClearError /* = EFalse */ ) |
|
2249 { |
|
2250 |
|
2251 TInt count = aSelection.Count(); |
|
2252 TTime curTime; |
|
2253 curTime.UniversalTime(); |
|
2254 if ( aInterval > TTimeIntervalSeconds( KMmsDelayInSeconds ) ) |
|
2255 { |
|
2256 curTime += aInterval; |
|
2257 } |
|
2258 else |
|
2259 { |
|
2260 curTime += TTimeIntervalSeconds( KMmsDelayInSeconds ); |
|
2261 } |
|
2262 |
|
2263 while ( count-- ) |
|
2264 { |
|
2265 if ( iServerEntry->SetEntry( aSelection.At( count ) ) == KErrNone ) |
|
2266 { |
|
2267 TMsvEntry entry = iServerEntry->Entry(); |
|
2268 if ( entry.Id() != aSelection.At( count ) || entry.Id() == KMsvNullIndexEntryId ) |
|
2269 { |
|
2270 // The entry is garbage |
|
2271 aSelection.Delete( count, 1 ); |
|
2272 } |
|
2273 else |
|
2274 { |
|
2275 entry.iDate = curTime; |
|
2276 if ( aClearError ) |
|
2277 { |
|
2278 entry.iError = KErrNone; |
|
2279 } |
|
2280 iServerEntry->ChangeEntry( entry ); |
|
2281 } |
|
2282 } |
|
2283 } |
|
2284 |
|
2285 } |
|
2286 |
|
2287 // --------------------------------------------------------- |
|
2288 // CMmsServerMtm::DecodePushedMessageL() |
|
2289 // |
|
2290 // --------------------------------------------------------- |
|
2291 // |
|
2292 void CMmsServerMtm::DecodePushedMessageL() |
|
2293 { |
|
2294 |
|
2295 // Decode the pushed content to see, if it was |
|
2296 // a notification or a delivery report |
|
2297 |
|
2298 #ifndef _NO_MMSS_LOGGING_ |
|
2299 TMmsLogger::Log( _L("MmsServer decoding pushed message") ); |
|
2300 #endif |
|
2301 iNotification = KMsvNullIndexEntryId; |
|
2302 iMmsHeaders->Reset(); |
|
2303 // the possible error from this is not important as the settings are |
|
2304 // now stored in central repository |
|
2305 iServerEntry->SetEntry( iServiceEntryId ); |
|
2306 |
|
2307 // We decode first, and create the entry afterwards. |
|
2308 if ( !iDecoder ) |
|
2309 { |
|
2310 iDecoder = CMmsDecode::NewL( iFs ); |
|
2311 } |
|
2312 |
|
2313 if ( !iEntryWrapper ) |
|
2314 { |
|
2315 iEntryWrapper = CMmsServerEntry::NewL( |
|
2316 iFs, |
|
2317 *iServerEntry, |
|
2318 iServiceEntryId ); |
|
2319 } |
|
2320 |
|
2321 TRAP ( iError, iDecoder->DecodeHeadersL( *iEntryWrapper, *iMmsHeaders, *iEncodeBuffer ) ); |
|
2322 |
|
2323 // If we could not allocate memory to decode, we must try again later. |
|
2324 if ( iError == KErrNoMemory ) |
|
2325 { |
|
2326 return; |
|
2327 } |
|
2328 |
|
2329 if ( iError == KErrCorrupt || |
|
2330 iError == KErrTooBig ) |
|
2331 { |
|
2332 // if the notification has illegal content, |
|
2333 // it is just discarded, we must not tell the |
|
2334 // mmswatcher to resend it. |
|
2335 iError = KErrNone; |
|
2336 return; |
|
2337 } |
|
2338 |
|
2339 // Even if we encounter an error when decoding, we must save |
|
2340 // the message for handling, because we must be able to send |
|
2341 // "unrecognized" status back, if we get an unknown PDU |
|
2342 // If we get a message with different major version number, it |
|
2343 // may be so incompatible that we get an error while decoding. |
|
2344 |
|
2345 // If we get a notification, we make some sanity checks so that |
|
2346 // we can reject malicious notifications right away. |
|
2347 |
|
2348 // mark if this is a notification of a delivery report |
|
2349 // send requests or retrieve confirmations are not pushed |
|
2350 // They are equivalent to unrecognized type |
|
2351 |
|
2352 TUint32 messageType = 0; |
|
2353 switch ( iMmsHeaders->MessageType() ) |
|
2354 { |
|
2355 case KMmsMessageTypeMNotificationInd: |
|
2356 messageType = KMmsMessageMNotificationInd; |
|
2357 break; |
|
2358 case KMmsMessageTypeDeliveryInd: |
|
2359 messageType = KMmsMessageDeliveryInd; |
|
2360 break; |
|
2361 case KMmsMessageTypeReadOrigInd: |
|
2362 messageType = KMmsMessageReadOrigInd; |
|
2363 break; |
|
2364 default: |
|
2365 // unrecognized type. |
|
2366 // We must send response to MMSC |
|
2367 // This includes types that should never be pushed to us. |
|
2368 messageType = KMmsMessageUnrecognized; |
|
2369 break; |
|
2370 } |
|
2371 |
|
2372 // If this is an extended notification, it may already contain the whole message |
|
2373 TBool completeMessage = ( iMmsHeaders->MessageComplete() == KMmsExtendedMessageComplete ); |
|
2374 |
|
2375 TBool passedChecks = ETrue; // we are optimistic |
|
2376 |
|
2377 // If we have a notification, we must do a couple of special tricks. |
|
2378 |
|
2379 if ( messageType == KMmsMessageMNotificationInd ) |
|
2380 { |
|
2381 // Some handling has been moved here from CMmsDecode, |
|
2382 // because it is better to have all notification logic in on place. |
|
2383 |
|
2384 // Expiry interval must be changed to absolute time, |
|
2385 // otherwise it makes no sense. |
|
2386 if ( iMmsHeaders->ExpiryDate() == 0 ) |
|
2387 { |
|
2388 TTime time; |
|
2389 // handle expiry in universal time in case user changes location |
|
2390 time.UniversalTime(); |
|
2391 time += TTimeIntervalSeconds( iMmsHeaders->ExpiryInterval() ); |
|
2392 // we can't use "seconds from" as it only returns a |
|
2393 // 32 bit signed integer. If fails in 2038. |
|
2394 // "microseconds from" returns a 64 bit signed integer |
|
2395 // expiry date in iMmsHeaders in in seconds from 1.1.1970. |
|
2396 // interval must be changed back to seconds |
|
2397 // This way the result may still be a 64bit integer -> |
|
2398 // no overflow in 2038 |
|
2399 iMmsHeaders->SetExpiryDate( |
|
2400 ( time.MicroSecondsFrom( TTime( KMmsYear1970String ) ).Int64() ) / KMmsMillion ); |
|
2401 } |
|
2402 |
|
2403 // Then we must check if the message type is acceptable. |
|
2404 // Rejection based on message type overrides the status |
|
2405 // set above. For example, if fetching is deferred, but |
|
2406 // we get an advertisement, and we don't accept advertisements |
|
2407 // we change the message status from deferred to rejected. |
|
2408 |
|
2409 switch ( iMmsHeaders->MessageClass() ) |
|
2410 { |
|
2411 case EMmsClassPersonal: |
|
2412 if ( iMmsSettings->AcceptPersonalMessages() == EFalse ) |
|
2413 { |
|
2414 iMmsHeaders->SetStatus( KMmsMessageStatusRejected ); |
|
2415 } |
|
2416 break; |
|
2417 case EMmsClassAdvertisement: |
|
2418 if ( iMmsSettings->AcceptAdvertisementMessages() == EFalse ) |
|
2419 { |
|
2420 iMmsHeaders->SetStatus( KMmsMessageStatusRejected ); |
|
2421 } |
|
2422 break; |
|
2423 case EMmsClassInformational: |
|
2424 if ( iMmsSettings->AcceptInformationalMessages() == EFalse ) |
|
2425 { |
|
2426 iMmsHeaders->SetStatus( KMmsMessageStatusRejected ); |
|
2427 } |
|
2428 break; |
|
2429 case EMmsClassAuto: |
|
2430 // We accept automatic messages. The only automatic message we |
|
2431 // know about is a text mode read report. |
|
2432 // As we now handle read reports, we must accept automatic messages |
|
2433 // in case some server has converted a read report into a text message |
|
2434 // (possible if the server does not recognize the phone and know its |
|
2435 // capabilities). |
|
2436 break; |
|
2437 default: |
|
2438 // if we cannot determine the message type, |
|
2439 // we reject it. |
|
2440 // Message class header is mandatory in notification |
|
2441 //iMmsHeaders->SetStatus( KMmsMessageStatusRejected ); |
|
2442 break; |
|
2443 } |
|
2444 // check if we accept anonymous messages |
|
2445 if ( iMmsSettings->AcceptAnonymousMessages() == EFalse && |
|
2446 iMmsHeaders->Sender().Length() == 0 ) |
|
2447 { |
|
2448 #ifndef _NO_MMSS_LOGGING_ |
|
2449 TMmsLogger::Log( _L("- Anonymous message rejected") ); |
|
2450 #endif |
|
2451 iMmsHeaders->SetStatus( KMmsMessageStatusRejected ); |
|
2452 } |
|
2453 |
|
2454 // If the encapsulation version is 1.3, the notification may already |
|
2455 // contain the application id header. |
|
2456 // If the application has not been registered, we reject the message |
|
2457 // (at least until more complex support for the applicatiom message |
|
2458 // handling has been implemented) |
|
2459 if ( iMmsHeaders->ApplicId().Length() > 0 ) |
|
2460 { |
|
2461 if ( !CMmsBaseOperation::RegisteredL( iMmsHeaders->ApplicId() ) ) |
|
2462 { |
|
2463 iMmsHeaders->SetStatus( KMmsMessageStatusRejected ); |
|
2464 } |
|
2465 } |
|
2466 |
|
2467 // if the extended notification contains the whole message |
|
2468 // we must mark it as "retrieved" |
|
2469 // If there is an extended message addressed to an application, |
|
2470 // it is something that cannot be reasonably handled. |
|
2471 // I hope that is an illegal case anyway. |
|
2472 |
|
2473 if ( completeMessage ) |
|
2474 { |
|
2475 iMmsHeaders->SetStatus( 0 ); // not applicable |
|
2476 } |
|
2477 |
|
2478 // legality checks: |
|
2479 // TID is mandatory |
|
2480 if ( iMmsHeaders->Tid().Length() == 0 ) |
|
2481 { |
|
2482 passedChecks = EFalse; |
|
2483 #ifndef _NO_MMSS_LOGGING_ |
|
2484 TMmsLogger::Log( _L("- invalid TID: length = %d"), iMmsHeaders->Tid().Length() ); |
|
2485 #endif |
|
2486 } |
|
2487 // message class is mandatory |
|
2488 if ( iMmsHeaders->MessageClass() == 0 ) |
|
2489 { |
|
2490 passedChecks = EFalse; |
|
2491 #ifndef _NO_MMSS_LOGGING_ |
|
2492 TMmsLogger::Log( _L("- message class not defined") ); |
|
2493 #endif |
|
2494 } |
|
2495 |
|
2496 // Messages with zero length must be accepted if message size may be |
|
2497 // just the size of payload and subject (both may have zero length) |
|
2498 // If headers are not included in calculation, zero length is acceptable here. |
|
2499 |
|
2500 // expiry is mandatory - but it cannot be 0 because we just set it. |
|
2501 // If expiry is not given, the notification expires NOW |
|
2502 |
|
2503 // content location is mandatory |
|
2504 if ( iMmsHeaders->ContentLocation().Length() == 0 ) |
|
2505 { |
|
2506 passedChecks = EFalse; |
|
2507 #ifndef _NO_MMSS_LOGGING_ |
|
2508 TMmsLogger::Log( _L("- no content location") ); |
|
2509 #endif |
|
2510 } |
|
2511 } |
|
2512 |
|
2513 // if we have notification that does not fill our |
|
2514 // criteria, we just throw it away. The purpose of this |
|
2515 // is to discard possible malignant notifications that |
|
2516 // would cause us to contact some unknown server and |
|
2517 // do strange damage - or at least cause unncessary |
|
2518 // network traffic. |
|
2519 |
|
2520 // If the message is complete, we keep it anyway |
|
2521 |
|
2522 if ( passedChecks == EFalse && !completeMessage ) |
|
2523 { |
|
2524 iError = KErrNone; |
|
2525 return; |
|
2526 } |
|
2527 |
|
2528 TMsvEntry tEntry; |
|
2529 tEntry.iType = KUidMsvMessageEntry; |
|
2530 // This may be different for notifications in manual modes |
|
2531 // This is ok, as all notifications are stored first to the internal MMS folder |
|
2532 tEntry.iMtm = KUidMsgTypeMultimedia; |
|
2533 |
|
2534 // use the iRelatedId to bypass queue. |
|
2535 tEntry.iServiceId = KMsvLocalServiceIndexEntryId; |
|
2536 tEntry.iRelatedId = iServiceEntryId; |
|
2537 tEntry.SetUnread( ETrue ); |
|
2538 tEntry.SetNew( ETrue ); |
|
2539 tEntry.SetVisible( EFalse ); |
|
2540 tEntry.SetComplete( EFalse ); |
|
2541 tEntry.SetInPreparation( ETrue ); |
|
2542 tEntry.SetReadOnly( EFalse ); |
|
2543 tEntry.iSize = iMmsHeaders->Size(); |
|
2544 |
|
2545 // |
|
2546 // Setting StoredInMMBox flag correctly |
|
2547 // |
|
2548 HandleMMBoxFlagL( tEntry ); |
|
2549 |
|
2550 // Notifications are always originally children of MMS Folder |
|
2551 // We have decoded our headers already. |
|
2552 // We know if this is a notification or a delivery report, |
|
2553 // and we can decide what to do. |
|
2554 |
|
2555 TMsvId parent = KMsvNullIndexEntryId; |
|
2556 iServerEntry->SetEntry( KMsvNullIndexEntryId ); |
|
2557 TMsvId mmsFolder = FindMMSFolderL(); |
|
2558 if ( mmsFolder == KMsvNullIndexEntryId ) |
|
2559 { |
|
2560 // If the id for our notification folder is 0, we are really in a mess |
|
2561 // and cannot continue |
|
2562 iError = KErrNotFound; |
|
2563 return; |
|
2564 } |
|
2565 parent = mmsFolder; |
|
2566 |
|
2567 if ( messageType != KMmsMessageDeliveryInd && |
|
2568 messageType != KMmsMessageReadOrigInd && |
|
2569 messageType != KMmsMessageReadRecInd ) |
|
2570 { |
|
2571 // Check duplicates from parent folder, from Inbox and from mmbox folder |
|
2572 // no mater which receiving mode is on. |
|
2573 TMsvId mmboxFolder = iMmsSettings->MMBoxFolder(); |
|
2574 if ( PruneDuplicateNotificationsL( parent, *iMmsHeaders ) || |
|
2575 PruneDuplicateNotificationsL( KMsvGlobalInBoxIndexEntryIdValue, *iMmsHeaders ) || |
|
2576 PruneDuplicateNotificationsL( mmboxFolder, *iMmsHeaders )) |
|
2577 { |
|
2578 #ifndef _NO_MMSS_LOGGING_ |
|
2579 TMmsLogger::Log( _L("- duplicate - not stored") ); |
|
2580 #endif |
|
2581 iError = KErrNone; |
|
2582 return; |
|
2583 } |
|
2584 } |
|
2585 |
|
2586 // If this is an extended notification that contains the whole message |
|
2587 // the entry goes to inbox as a message, not a notification. |
|
2588 // The fetching must not be scheduled in this case as we already have the |
|
2589 // message. |
|
2590 // However, if we are in home network, we must send acknowledge back to MMSC |
|
2591 // Besides storing the notification as message entry, we must create another |
|
2592 // entry to serve as base for sending the acknowledgement. Therefore we have |
|
2593 // marked our status as "KMmsMessageStatusRetrieved" |
|
2594 |
|
2595 // this is the size of the attachment if we have an extended notification |
|
2596 TInt attaSize = 0; |
|
2597 |
|
2598 if ( completeMessage ) |
|
2599 { |
|
2600 parent = KMsvGlobalInBoxIndexEntryIdValue; |
|
2601 tEntry.iMtm = KUidMsgTypeMultimedia; |
|
2602 // indicate complete message |
|
2603 iMmsHeaders->SetMessageType( KMmsMessageTypeMRetrieveConf ); |
|
2604 } |
|
2605 |
|
2606 // If we can't access the parent where the notification is to be stored, |
|
2607 // we can do nothing |
|
2608 iError = iServerEntry->SetEntry( parent ); |
|
2609 if ( iError != KErrNone ) |
|
2610 { |
|
2611 return; // cannot continue |
|
2612 } |
|
2613 |
|
2614 // Query about disk space. KMmsIndexEntryExtra is extra for TMsvEntry |
|
2615 // Make one query, we assume no one takes away the disk space this fast. |
|
2616 if ( TMmsGenUtils::DiskSpaceBelowCriticalLevelL( |
|
2617 &iFs, iMmsHeaders->Size() + KMmsIndexEntryExtra + iMmsHeaders->Size(), iMessageDrive ) ) |
|
2618 { |
|
2619 // we use standard error code here |
|
2620 iError = KErrDiskFull; |
|
2621 return; // cannot continue |
|
2622 } |
|
2623 |
|
2624 iError = iServerEntry->CreateEntry( tEntry ); |
|
2625 |
|
2626 if ( iError == KErrNone ) |
|
2627 { |
|
2628 iError = iServerEntry->SetEntry( tEntry.Id() ); |
|
2629 iNotification = tEntry.Id(); |
|
2630 } |
|
2631 |
|
2632 CMsvStore* store = NULL; |
|
2633 HBufC* buffer = NULL; // we need this to generate a description for the entry |
|
2634 TBool attachmentAdded = EFalse; // to track if the extended notification text has been added to the message store or not. |
|
2635 |
|
2636 if ( iError == KErrNone ) |
|
2637 { |
|
2638 // if this is a whole message, create an attachment from the text |
|
2639 if ( completeMessage && iNotification != KMsvNullIndexEntryId ) |
|
2640 { |
|
2641 tEntry = iServerEntry->Entry(); // save the settings we have so far |
|
2642 if ( iMmsHeaders->Subject().Length() > 0 ) |
|
2643 { |
|
2644 tEntry.iDescription.Set( iMmsHeaders->Subject() ); |
|
2645 } |
|
2646 else |
|
2647 { |
|
2648 // Save text as description if we have no subject |
|
2649 TPtrC temp = iMmsHeaders->ExtendedNotification().Left( KMmsMaxDescription ); |
|
2650 buffer = HBufC::NewL( temp.Length() ); |
|
2651 // no need to put buffer onto cleanup stack - we don't leave before we are done |
|
2652 buffer->Des().Copy( temp ); |
|
2653 TPtr pDescription = buffer->Des(); |
|
2654 TMmsGenUtils::ReplaceCRLFAndTrim( pDescription ); |
|
2655 tEntry.iDescription.Set( pDescription ); |
|
2656 } |
|
2657 iServerEntry->ChangeEntry( tEntry ); |
|
2658 // If we have not allocated the buffer, it is NULL, and it is safe to delete. |
|
2659 delete buffer; |
|
2660 buffer = NULL; |
|
2661 |
|
2662 if ( iMmsHeaders->ExtendedNotification().Length() > 0 ) |
|
2663 { |
|
2664 TMsvAttachmentId attachmentId = 0; |
|
2665 CMsvMimeHeaders* mimeHeaders = CMsvMimeHeaders::NewL(); |
|
2666 CleanupStack::PushL( mimeHeaders ); |
|
2667 TPtrC8 temp; |
|
2668 temp.Set( KMmsTextPlain ); |
|
2669 mimeHeaders->SetContentTypeL( temp.Left( temp.Find( KMmsSlash8 ) ) ); |
|
2670 mimeHeaders->SetContentSubTypeL( temp.Mid( temp.Find( KMmsSlash8 ) + 1 ) ); |
|
2671 mimeHeaders->SetMimeCharset( KMmsUtf8 ); // text saved as utf-8 |
|
2672 _LIT( KRelated, "att1.txt"); |
|
2673 mimeHeaders->SetSuggestedFilenameL( KRelated ); |
|
2674 // attaData must point to the text |
|
2675 // buffer long enough for conversion |
|
2676 const TInt KMmsConversionMultiplier = 5; |
|
2677 HBufC8* dataContent = HBufC8::NewL( |
|
2678 iMmsHeaders->ExtendedNotification().Length() * KMmsConversionMultiplier ); |
|
2679 CleanupStack::PushL( dataContent ); |
|
2680 TPtr8 attaData = dataContent->Des(); |
|
2681 CnvUtfConverter::ConvertFromUnicodeToUtf8( |
|
2682 attaData, iMmsHeaders->ExtendedNotification() ); |
|
2683 // set parent |
|
2684 iError = iEntryWrapper->SetCurrentEntry( iNotification ); |
|
2685 |
|
2686 if ( iError == KErrNone ) |
|
2687 { |
|
2688 store = iEntryWrapper->EditStoreL(); |
|
2689 CleanupStack::PushL( store ); |
|
2690 TInt32 drmFlags = 0; //ignored |
|
2691 iError = iEntryWrapper->CreateFileAttachmentL( |
|
2692 *store, |
|
2693 KRelated, |
|
2694 attaData, |
|
2695 *mimeHeaders, |
|
2696 attachmentId, |
|
2697 attaSize, |
|
2698 drmFlags); |
|
2699 //If attachment is added to Message store successfully then attachmentAdded is set |
|
2700 if ( iError == KErrNone ) |
|
2701 { |
|
2702 attachmentAdded = ETrue; |
|
2703 } |
|
2704 store->CommitL(); |
|
2705 CleanupStack::PopAndDestroy( store ); |
|
2706 store = NULL; |
|
2707 } |
|
2708 iMmsHeaders->SetExtendedNotificationL( TPtrC() ); |
|
2709 |
|
2710 CleanupStack::PopAndDestroy( dataContent ); |
|
2711 CleanupStack::PopAndDestroy( mimeHeaders ); |
|
2712 } |
|
2713 } |
|
2714 if ( iServerEntry->SetEntry( iNotification ) == KErrNone && |
|
2715 iNotification != KMsvNullIndexEntryId ) |
|
2716 { |
|
2717 store = iServerEntry->EditStoreL(); |
|
2718 CleanupStack::PushL(store); |
|
2719 iMmsHeaders->StoreL(*store); |
|
2720 store->CommitL(); |
|
2721 CleanupStack::PopAndDestroy( store ); |
|
2722 store = NULL; |
|
2723 } |
|
2724 } |
|
2725 |
|
2726 |
|
2727 if ( ( iError == KErrNone || iMmsHeaders->MessageType() != 0 ) |
|
2728 && iNotification != KMsvNullIndexEntryId ) |
|
2729 { |
|
2730 iError = iServerEntry->SetEntry( iNotification ); |
|
2731 if ( iError != KErrNone ) |
|
2732 { |
|
2733 // If we have an error here, there is something |
|
2734 // seriously wrong with the system |
|
2735 if ( iServerEntry->SetEntry( parent ) == KErrNone ) |
|
2736 { |
|
2737 iServerEntry->DeleteEntry( iNotification ); |
|
2738 } |
|
2739 iNotification = KMsvNullIndexEntryId; |
|
2740 iServerEntry->SetEntry( KMsvNullIndexEntryId ); |
|
2741 return; // cannot continue |
|
2742 } |
|
2743 } |
|
2744 else |
|
2745 { |
|
2746 if ( iServerEntry->SetEntry( parent ) == KErrNone && |
|
2747 iNotification != KMsvNullIndexEntryId ) |
|
2748 { |
|
2749 // We managed to create an entry, but not to decode |
|
2750 // the buffer contents into the entry |
|
2751 iServerEntry->DeleteEntry( iNotification ); |
|
2752 } |
|
2753 iNotification = KMsvNullIndexEntryId; |
|
2754 iServerEntry->SetEntry( KMsvNullIndexEntryId ); |
|
2755 return; |
|
2756 } |
|
2757 |
|
2758 // finish the details, and the notification entry is ready to be used |
|
2759 tEntry = iServerEntry->Entry(); |
|
2760 |
|
2761 if ( messageType == KMmsMessageMNotificationInd ) |
|
2762 { |
|
2763 // If the sender is a phone number, add alias. |
|
2764 // We don't add alias for email addresses here, as the contact |
|
2765 // database search for email addresses is very slow |
|
2766 // if there are lots of contacts. |
|
2767 buffer = HBufC::NewL( KMmsMaxDescription ); |
|
2768 CleanupStack::PushL( buffer ); |
|
2769 |
|
2770 TPtr pBuffer = buffer->Des(); |
|
2771 |
|
2772 if ( TMmsGenUtils::GenerateDetails( iMmsHeaders->Sender(), |
|
2773 pBuffer, KMmsMaxDescription, iFs ) == KErrNone ) |
|
2774 { |
|
2775 tEntry.iDetails.Set( pBuffer ); |
|
2776 } |
|
2777 else |
|
2778 { |
|
2779 // We come here only if there was an fatal error in GenerateDetails. |
|
2780 // Even if we don't find the alias, we have something in the string |
|
2781 tEntry.iDetails.Set( iMmsHeaders->Sender() ); |
|
2782 } |
|
2783 |
|
2784 // set subject if available |
|
2785 if ( iMmsHeaders->Subject().Length() > 0 ) |
|
2786 { |
|
2787 tEntry.iDescription.Set( iMmsHeaders->Subject() ); |
|
2788 } |
|
2789 CleanupStack::Pop( buffer ); |
|
2790 |
|
2791 } |
|
2792 else if ( messageType == KMmsMessageDeliveryInd && |
|
2793 iMmsHeaders->ToRecipients().MdcaCount() > 0 ) |
|
2794 { |
|
2795 tEntry.iDetails.Set( iMmsHeaders->ToRecipients().MdcaPoint( 0 ) ); |
|
2796 } |
|
2797 else |
|
2798 { |
|
2799 // keep LINT happy |
|
2800 } |
|
2801 |
|
2802 tEntry.iMtmData1 &= ~KMmsMessageTypeMask; |
|
2803 tEntry.iMtmData1 |= messageType; |
|
2804 if ( iMmsHeaders->MessageClass() == EMmsClassAdvertisement ) |
|
2805 { |
|
2806 tEntry.iMtmData1 |= KMmsMessageAdvertisement; |
|
2807 } |
|
2808 else if ( iMmsHeaders->MessageClass() == EMmsClassInformational ) |
|
2809 { |
|
2810 tEntry.iMtmData1 |= KMmsMessageInformational; |
|
2811 } |
|
2812 else |
|
2813 { |
|
2814 // keep LINT happy |
|
2815 } |
|
2816 |
|
2817 switch ( iMmsHeaders->MessagePriority() ) |
|
2818 { |
|
2819 case KMmsPriorityNormal: |
|
2820 tEntry.SetPriority( EMsvMediumPriority ); |
|
2821 break; |
|
2822 case KMmsPriorityLow: |
|
2823 tEntry.SetPriority( EMsvLowPriority ); |
|
2824 break; |
|
2825 case KMmsPriorityHigh: |
|
2826 tEntry.SetPriority( EMsvHighPriority ); |
|
2827 break; |
|
2828 default: |
|
2829 // if not defined default is normal |
|
2830 tEntry.SetPriority( EMsvMediumPriority ); |
|
2831 break; |
|
2832 } |
|
2833 |
|
2834 tEntry.SetVisible( ETrue ); |
|
2835 tEntry.SetComplete( ETrue ); |
|
2836 tEntry.SetInPreparation( EFalse ); |
|
2837 tEntry.SetReadOnly( EFalse ); |
|
2838 tEntry.iDate.UniversalTime(); // This is arrival time |
|
2839 tEntry.iSize = iMmsHeaders->Size() + attaSize; // add attachment data + mime headers |
|
2840 |
|
2841 // Set values to correspond to a new message if this was an extended notification |
|
2842 // containing full text. |
|
2843 |
|
2844 if ( completeMessage ) |
|
2845 { |
|
2846 tEntry.iMtmData1 &= ~KMmsMessageTypeMask; |
|
2847 // We override message type. |
|
2848 tEntry.iMtmData1 |= KMmsMessageMRetrieveConf | KMmsMessageMobileTerminated; |
|
2849 tEntry.SetReadOnly( ETrue ); |
|
2850 tEntry.SetSendingState( KMsvSendStateSent ); |
|
2851 tEntry.iServiceId = iServiceEntryId; |
|
2852 if ( attachmentAdded ) |
|
2853 { |
|
2854 tEntry.SetAttachment(ETrue); |
|
2855 } |
|
2856 } |
|
2857 |
|
2858 // we mark delivery reports as already sent so that |
|
2859 // we get rid of them at next garbage collecion, if the phone |
|
2860 // boots or crashes before they are handled. |
|
2861 // Delivery reports are lost if phone crashes. |
|
2862 if ( messageType == KMmsMessageDeliveryInd || |
|
2863 messageType == KMmsMessageReadOrigInd ) |
|
2864 { |
|
2865 tEntry.SetSendingState( KMsvSendStateSent ); |
|
2866 } |
|
2867 |
|
2868 iServerEntry->ChangeEntry( tEntry ); // ignore any error |
|
2869 iServerEntry->SetEntry( KMsvNullIndexEntryId ); |
|
2870 |
|
2871 delete buffer; |
|
2872 buffer = NULL; |
|
2873 |
|
2874 // If the message was complete, we have put our notification to inbox, and it is ready to be used. |
|
2875 // However, we still need an entry for sending back an acknowledgement to the server. |
|
2876 // We must create a new new notification entry for that purpose. |
|
2877 |
|
2878 if ( completeMessage ) |
|
2879 { |
|
2880 // don't schedule the entry that went into inbox |
|
2881 iNotification = KMsvNullIndexEntryId; |
|
2882 TInt error = KErrNone; |
|
2883 tEntry.iType = KUidMsvMessageEntry; // This will never go to inbox |
|
2884 tEntry.iMtm = KUidMsgTypeMultimedia; |
|
2885 tEntry.iServiceId = iServiceEntryId; |
|
2886 tEntry.iRelatedId = iServiceEntryId; |
|
2887 tEntry.SetUnread( ETrue ); |
|
2888 tEntry.SetNew( ETrue ); |
|
2889 tEntry.SetVisible( EFalse ); |
|
2890 tEntry.SetComplete( EFalse ); |
|
2891 tEntry.SetInPreparation( ETrue ); |
|
2892 tEntry.SetReadOnly( EFalse ); |
|
2893 tEntry.iSize = iMmsHeaders->Size(); |
|
2894 tEntry.SetSendingState( KMsvSendStateUnknown ); |
|
2895 tEntry.iDescription.Set( iMmsHeaders->Subject() ); |
|
2896 tEntry.iMtmData1 &= ~KMmsMessageTypeMask; |
|
2897 tEntry.iMtmData1 |= KMmsMessageMNotificationInd; |
|
2898 // even if sending ack fails, this must not be moved to inbox |
|
2899 // because the corresponding message already is there. |
|
2900 tEntry.iMtmData2 |= KMmsDoNotMoveToInbox; |
|
2901 parent = mmsFolder; |
|
2902 error = iServerEntry->SetEntry( parent ); |
|
2903 if ( error == KErrNone ) |
|
2904 { |
|
2905 error = iServerEntry->CreateEntry( tEntry ); |
|
2906 } |
|
2907 if ( error == KErrNone ) |
|
2908 { |
|
2909 iError = iServerEntry->SetEntry( tEntry.Id() ); |
|
2910 if ( iError == KErrNone ) |
|
2911 { |
|
2912 // Now we have a new entry that will be scheduled for sending the acknowledgement |
|
2913 iNotification = tEntry.Id(); |
|
2914 iMmsHeaders->SetStatus( KMmsMessageStatusRetrieved ); |
|
2915 iMmsHeaders->SetMessageType( KMmsMessageTypeMNotificationInd ); |
|
2916 store = iServerEntry->EditStoreL(); |
|
2917 CleanupStack::PushL( store ); |
|
2918 iMmsHeaders->StoreL( *store ); |
|
2919 store->CommitL(); |
|
2920 CleanupStack::PopAndDestroy( store ); |
|
2921 store = NULL; |
|
2922 tEntry.SetVisible( ETrue ); |
|
2923 tEntry.SetComplete( ETrue ); |
|
2924 tEntry.SetInPreparation( EFalse ); |
|
2925 iServerEntry->ChangeEntry( tEntry ); // ignore any error |
|
2926 } |
|
2927 } |
|
2928 } |
|
2929 |
|
2930 #ifndef _NO_MMSS_LOGGING_ |
|
2931 // log a little bit of something |
|
2932 if ( messageType == KMmsMessageDeliveryInd ) |
|
2933 { |
|
2934 TMmsLogger::Log( _L("- delivery report received") ); |
|
2935 } |
|
2936 else if ( messageType == KMmsMessageMNotificationInd ) |
|
2937 { |
|
2938 TMmsLogger::Log( _L("- notification received") ); |
|
2939 } |
|
2940 else |
|
2941 { |
|
2942 TMmsLogger::Log( _L("- pushed message of type %d received"), messageType ); |
|
2943 } |
|
2944 #endif |
|
2945 |
|
2946 } |
|
2947 |
|
2948 // --------------------------------------------------------- |
|
2949 // CMmsServerMtm::HandleNotificationL() |
|
2950 // |
|
2951 // --------------------------------------------------------- |
|
2952 // |
|
2953 void CMmsServerMtm::HandleNotificationL() |
|
2954 { |
|
2955 #ifndef _NO_MMSS_LOGGING_ |
|
2956 TMmsLogger::Log( _L("MmsServer HandleNotification, %d items"), iMsvSelection->Count() ); |
|
2957 #endif |
|
2958 if ( iMsvSelection->Count() < 1 ) |
|
2959 { |
|
2960 // nothing to do, give up |
|
2961 *iRequestStatus = KRequestPending; |
|
2962 User::RequestComplete( iRequestStatus, iError ); |
|
2963 return; |
|
2964 } |
|
2965 |
|
2966 // If both receiving modes in home and foreign network are "reject". |
|
2967 // The notification is deleted. |
|
2968 if( iMmsSettings->ReceivingModeHome() == EMmsReceivingReject && |
|
2969 iMmsSettings->ReceivingModeForeign() == EMmsReceivingReject ) |
|
2970 { |
|
2971 // we play possum and delete the notification without |
|
2972 // sending any response to MMSC. |
|
2973 #ifndef _NO_MMSS_LOGGING_ |
|
2974 TMmsLogger::Log( _L("- playing possum, deleting notifications") ); |
|
2975 #endif |
|
2976 TInt count = iMsvSelection->Count(); |
|
2977 TMsvEntry entry; |
|
2978 TMsvId parent = KMsvNullIndexEntryId; |
|
2979 if ( iServerEntry->SetEntry( iMsvSelection->At( count - 1 ) ) == KErrNone ) |
|
2980 { |
|
2981 entry = iServerEntry->Entry(); |
|
2982 parent = entry.Parent(); |
|
2983 } |
|
2984 while ( count-- && parent != KMsvNullIndexEntryId ) |
|
2985 { |
|
2986 if ( iServerEntry->SetEntry( iMsvSelection->At( count ) ) == KErrNone ) |
|
2987 { |
|
2988 entry = iServerEntry->Entry(); |
|
2989 parent = entry.Parent(); |
|
2990 } |
|
2991 |
|
2992 if ( iServerEntry->SetEntry( parent ) == KErrNone ) |
|
2993 { |
|
2994 iServerEntry->DeleteEntry( iMsvSelection->At( count ) ); |
|
2995 } |
|
2996 } |
|
2997 *iRequestStatus = KRequestPending; |
|
2998 User::RequestComplete( iRequestStatus, iError ); |
|
2999 return; |
|
3000 } |
|
3001 |
|
3002 // When the notificatio arrived, it was checked, and if it was |
|
3003 // a duplicate of an earlier one, it was not saved on disk. |
|
3004 |
|
3005 iCommand = EMmsReceive; |
|
3006 |
|
3007 // ScheduleL completes our caller |
|
3008 // we want to get back to out RunL to check the error |
|
3009 // Query about disk space. |
|
3010 // Subroutine knows how much must be checked for task scheduler |
|
3011 TInt error = KErrNone; |
|
3012 if ( DiskSpaceBelowCriticalForSchedulingL( &iFs, 0, iMessageDrive ) ) |
|
3013 { |
|
3014 // we use standard error code here |
|
3015 #ifndef _NO_MMSS_LOGGING_ |
|
3016 TMmsLogger::Log( _L("HandleNotificationL.. Disk Full") ); |
|
3017 #endif |
|
3018 error = KErrDiskFull; |
|
3019 TInt count = iMsvSelection->Count(); |
|
3020 TMsvEntry entry; |
|
3021 if ( iServerEntry->SetEntry( iMsvSelection->At( count - 1 ) ) == KErrNone ) |
|
3022 { |
|
3023 entry = iServerEntry->Entry(); |
|
3024 entry.iError = error; |
|
3025 iServerEntry->ChangeEntry( entry ); |
|
3026 #ifndef _NO_MMSS_LOGGING_ |
|
3027 TMmsLogger::Log( _L("HandleNotificationL.. Setting ierror to Entry") ); |
|
3028 #endif |
|
3029 } |
|
3030 |
|
3031 } |
|
3032 else |
|
3033 { |
|
3034 // We must set the caller's status to KRequest Pending because |
|
3035 // CScheduleBaseServerMtm::ScheduleL does not do it. |
|
3036 *iRequestStatus = KRequestPending; |
|
3037 TRAP( error, ScheduleL( *iMsvSelection, EFalse, KNullDesC8, *iRequestStatus ) ); |
|
3038 // ScheduleL would complete our caller, but if it leaves, |
|
3039 // we must complete. We don't want to leave... |
|
3040 } |
|
3041 if ( error != KErrNone ) |
|
3042 { |
|
3043 #ifndef _NO_MMSS_LOGGING_ |
|
3044 TMmsLogger::Log( _L("MmsServer HandleNotification status %d"), error ); |
|
3045 #endif |
|
3046 *iRequestStatus = KRequestPending; |
|
3047 User::RequestComplete( iRequestStatus, error ); |
|
3048 } |
|
3049 |
|
3050 } |
|
3051 |
|
3052 // --------------------------------------------------------- |
|
3053 // CMmsServerMtm::HandleDeliveryReportL() |
|
3054 // |
|
3055 // --------------------------------------------------------- |
|
3056 // |
|
3057 void CMmsServerMtm::HandleDeliveryReportL() |
|
3058 { |
|
3059 |
|
3060 if ( iMsvSelection->Count() < 1 ) |
|
3061 { |
|
3062 // nothing to do, give up |
|
3063 *iRequestStatus = KRequestPending; |
|
3064 User::RequestComplete( iRequestStatus, iError ); |
|
3065 return; |
|
3066 } |
|
3067 |
|
3068 iCommand = EMmsLogDeliveryReport; |
|
3069 |
|
3070 // Query about disk space. |
|
3071 // Subroutine knows how much must be checked for task scheduler |
|
3072 TInt error = KErrNone; |
|
3073 if ( DiskSpaceBelowCriticalForSchedulingL( &iFs, 0, iMessageDrive ) ) |
|
3074 { |
|
3075 // we use standard error code here |
|
3076 error = KErrDiskFull; |
|
3077 } |
|
3078 else |
|
3079 { |
|
3080 // ScheduleL completes our caller |
|
3081 // We must set the caller's status to KRequest Pending because |
|
3082 // CScheduleBaseServerMtm::ScheduleL does not do it. |
|
3083 *iRequestStatus = KRequestPending; |
|
3084 TRAP( error, ScheduleL( *iMsvSelection, EFalse, KNullDesC8, *iRequestStatus ) ); |
|
3085 // ScheduleL would complete our caller, but if it leaves, |
|
3086 // we must complete. We don't want to leave... |
|
3087 } |
|
3088 if ( error != KErrNone ) |
|
3089 { |
|
3090 #ifndef _NO_MMSS_LOGGING_ |
|
3091 TMmsLogger::Log( _L("MmsServer HandleDeliveryReport status %d"), error ); |
|
3092 #endif |
|
3093 *iRequestStatus = KRequestPending; |
|
3094 User::RequestComplete( iRequestStatus, error ); |
|
3095 } |
|
3096 } |
|
3097 |
|
3098 |
|
3099 // --------------------------------------------------------- |
|
3100 // CMmsServerMtm::LogDeliveryReportL() |
|
3101 // |
|
3102 // --------------------------------------------------------- |
|
3103 // |
|
3104 void CMmsServerMtm::LogDeliveryReportL() |
|
3105 { |
|
3106 |
|
3107 #ifndef _NO_MMSS_LOGGING_ |
|
3108 TMmsLogger::Log( _L("MmsServer Logging delivery report") ); |
|
3109 #endif |
|
3110 // this subroutine does not do critical disk space level check |
|
3111 // normally we just update an existing entry changing only status |
|
3112 // which does not change disk space usage. |
|
3113 // Only if our previous entry has been deleted, we add something. |
|
3114 // We don't check that. The amount of disk space needed should |
|
3115 // be less than 100 bytes anyway. Large messages are more critical |
|
3116 // than small log entries. |
|
3117 |
|
3118 if ( iMsvSelection->Count() < 1 ) |
|
3119 { |
|
3120 // nothing to do, give up |
|
3121 // we complete our caller |
|
3122 *iRequestStatus = KRequestPending; |
|
3123 User::RequestComplete( iRequestStatus, iError ); |
|
3124 return; |
|
3125 } |
|
3126 |
|
3127 iCommand = EMmsLogDeliveryReport; |
|
3128 TRequestStatus* status = &iStatus; |
|
3129 TBool readReport = EFalse; // first guess - delivery report |
|
3130 |
|
3131 iError = iServerEntry->SetEntry( iMsvSelection->At( 0 ) ); |
|
3132 if ( iError == KErrNotFound ) |
|
3133 { |
|
3134 // The entry we are supposed to handle has disappeared. |
|
3135 // We complete the active object. |
|
3136 // RunL will call UpdateEntriesL, and that function |
|
3137 // will delete the entry from the list, and try the next |
|
3138 // one, if it exists. |
|
3139 // We must set the error to "none" to delete the entry |
|
3140 // instead of retrying. |
|
3141 iError = KErrNone; |
|
3142 // get back to our own RunL, it will complete caller |
|
3143 *iRequestStatus = KRequestPending; |
|
3144 iStatus = KRequestPending; |
|
3145 SetActive(); |
|
3146 User::RequestComplete( status, iError ); |
|
3147 return; |
|
3148 } |
|
3149 |
|
3150 TMsvEntry entry; |
|
3151 if ( iError == KErrNone ) |
|
3152 { |
|
3153 entry = iServerEntry->Entry(); |
|
3154 } |
|
3155 else |
|
3156 { |
|
3157 // cannot access entry. |
|
3158 #ifndef _NO_MMSS_LOGGING_ |
|
3159 TMmsLogger::Log( _L("MmsServer could not access delivery report") ); |
|
3160 #endif |
|
3161 // Retry later. |
|
3162 // now our error is not KErrNone, so we will reschedule |
|
3163 // in UpdateEntriesL |
|
3164 *iRequestStatus = KRequestPending; |
|
3165 iStatus = KRequestPending; |
|
3166 SetActive(); |
|
3167 User::RequestComplete( status, iError ); |
|
3168 } |
|
3169 |
|
3170 if ( ( entry.iMtmData1 & KMmsMessageTypeMask ) == KMmsMessageReadOrigInd ) |
|
3171 { |
|
3172 // The remote party is in "From" field because that's the recipient |
|
3173 // that is sending the read report |
|
3174 readReport = ETrue; |
|
3175 } |
|
3176 else if ( ( entry.iMtmData1 & KMmsMessageTypeMask ) != KMmsMessageDeliveryInd ) |
|
3177 { |
|
3178 iError = KErrNone; |
|
3179 // get back to our own RunL |
|
3180 *iRequestStatus = KRequestPending; |
|
3181 iStatus = KRequestPending; |
|
3182 SetActive(); |
|
3183 User::RequestComplete( status, iError ); |
|
3184 return; |
|
3185 } |
|
3186 |
|
3187 if ( !iMmsLog ) |
|
3188 { |
|
3189 iLogClient = CLogClient::NewL( iFs ); |
|
3190 iLogViewEvent = CLogViewEvent::NewL( *iLogClient ); |
|
3191 iMmsLog = CMmsLog::NewL( *iLogClient, *iLogViewEvent, iFs ); |
|
3192 } |
|
3193 |
|
3194 if ( !iLogEvent ) |
|
3195 { |
|
3196 iLogEvent = CLogEvent::NewL(); |
|
3197 } |
|
3198 |
|
3199 if ( !iRemoteParties ) |
|
3200 { |
|
3201 // We only handle one delivery report at a time |
|
3202 iRemoteParties = new ( ELeave )CDesCArrayFlat( 1 ); |
|
3203 } |
|
3204 else |
|
3205 { |
|
3206 iRemoteParties->Reset(); |
|
3207 } |
|
3208 |
|
3209 // save the items that are the same for all our events |
|
3210 iLogEvent->SetEventType( KLogMmsEventTypeUid ); |
|
3211 iLogClient->GetString( iLogString, R_LOG_DIR_OUT ); |
|
3212 iLogEvent->SetDirection( iLogString ); |
|
3213 iLogEvent->SetDurationType( KLogDurationNone ); |
|
3214 // This should never stay |
|
3215 iLogClient->GetString( iLogString, R_LOG_DEL_SENT ); |
|
3216 iLogEvent->SetStatus( iLogString ); |
|
3217 |
|
3218 CMsvStore* store = NULL; |
|
3219 |
|
3220 TRAP( iError, store = iServerEntry->ReadStoreL(); ) |
|
3221 |
|
3222 if ( iError == KErrNone ) |
|
3223 { |
|
3224 CleanupStack::PushL( store ); |
|
3225 iMmsHeaders->RestoreL( *store ); |
|
3226 CleanupStack::PopAndDestroy( store ); |
|
3227 iLogEvent->SetDataL( iMmsHeaders->MessageId() ); |
|
3228 // Use delivery time from delivery report |
|
3229 iLogEvent->SetTime( TTime( KMmsYear1970String ) + |
|
3230 TTimeIntervalMicroSeconds( iMmsHeaders->Date() * KMmsMillion ) ); |
|
3231 |
|
3232 switch ( iMmsHeaders->Status() ) |
|
3233 { |
|
3234 case KMmsMessageStatusRetrieved: |
|
3235 case KMmsMessageStatusForwarded: // forwarded is delivered from our point of view |
|
3236 iDeliveryStatus = ETrue; |
|
3237 iLogClient->GetString( iLogString, R_LOG_DEL_DONE ); |
|
3238 break; |
|
3239 case KMmsMessageStatusExpired: |
|
3240 case KMmsMessageStatusRejected: |
|
3241 case KMmsMessageStatusUnreachable: |
|
3242 iDeliveryStatus = EFalse; |
|
3243 iLogClient->GetString( iLogString, R_LOG_DEL_FAILED ); |
|
3244 break; |
|
3245 default: |
|
3246 if ( !readReport ) |
|
3247 { |
|
3248 // if status cannot be mapped, it is just "pending" |
|
3249 // KMmsMessageStatusDeferred, KMmsMessageStatusUnrecognized, and KMmsMessageStatusIndeterminate |
|
3250 // map to "pending" state |
|
3251 iLogClient->GetString( iLogString, R_LOG_DEL_PENDING ); |
|
3252 } |
|
3253 else |
|
3254 { |
|
3255 // read report can only have status "read" or |
|
3256 // "deleted without being read" |
|
3257 // We need some string mapping for those... |
|
3258 if ( iMmsHeaders->ReadStatus() == KMmsReadStatusRead ) |
|
3259 { |
|
3260 // read |
|
3261 iLogString.Copy( KLogsMsgReadText ); |
|
3262 } |
|
3263 else |
|
3264 { |
|
3265 // deleted without being read |
|
3266 // This does not change "delivered" status |
|
3267 // But in case the delivery report has not arrived, |
|
3268 // This ensures that the information of delivery gets stored. |
|
3269 // If the user deleted the message without reading it, |
|
3270 // it must have been delivered first. |
|
3271 iLogClient->GetString( iLogString, R_LOG_DEL_DONE ); |
|
3272 } |
|
3273 } |
|
3274 break; |
|
3275 } |
|
3276 |
|
3277 #ifndef _NO_MMSS_LOGGING_ |
|
3278 TMmsLogger::Log( _L("MmsServer delivery status code %d"), iMmsHeaders->Status() ); |
|
3279 TMmsLogger::Log( _L(" - delivery status %S"), &iLogString ); |
|
3280 TMmsLogger::Log( _L(" - delivery datetime:") ); |
|
3281 CMmsBaseOperation::LogDateL( iLogEvent->Time() ); |
|
3282 #endif |
|
3283 iLogEvent->SetStatus( iLogString ); |
|
3284 if ( iMmsHeaders->ToRecipients().MdcaCount() == 0 && |
|
3285 iMmsHeaders->Sender().Length() == 0 ) |
|
3286 { |
|
3287 // No recipient, cannot log |
|
3288 // no use retrying either |
|
3289 *iRequestStatus = KRequestPending; |
|
3290 iStatus = KRequestPending; |
|
3291 SetActive(); |
|
3292 User::RequestComplete( status, KErrNone ); |
|
3293 return; |
|
3294 } |
|
3295 if ( !readReport ) |
|
3296 { |
|
3297 iRemoteParties->AppendL( TMmsGenUtils::PureAddress( |
|
3298 iMmsHeaders->ToRecipients().MdcaPoint( 0 ) ) ); |
|
3299 } |
|
3300 else |
|
3301 { |
|
3302 // If we have a read report, the remote party is the sender |
|
3303 iRemoteParties->AppendL( TMmsGenUtils::PureAddress( |
|
3304 iMmsHeaders->Sender() ) ); |
|
3305 } |
|
3306 |
|
3307 // CMmsLog is responsible for setting our status to "KRequestPending" |
|
3308 // If the status or the entry is already "read" it must not be changed |
|
3309 // back to "delivered" |
|
3310 // CMmsLog must take care of that because it is the component that |
|
3311 // finds the corresponding entry from the log database |
|
3312 iMmsLog->StartL( *iLogEvent, *iRemoteParties, iStatus); |
|
3313 *iRequestStatus = KRequestPending; |
|
3314 SetActive(); |
|
3315 } |
|
3316 else |
|
3317 { |
|
3318 #ifndef _NO_MMSS_LOGGING_ |
|
3319 TMmsLogger::Log( _L("MmsServer could not access delivery report") ); |
|
3320 #endif |
|
3321 // Retry later. |
|
3322 // now our error is not KErrNone, so we will reschedule |
|
3323 // in UpdateEntriesL |
|
3324 *iRequestStatus = KRequestPending; |
|
3325 iStatus = KRequestPending; |
|
3326 SetActive(); |
|
3327 User::RequestComplete( status, iError ); |
|
3328 } |
|
3329 |
|
3330 } |
|
3331 |
|
3332 // --------------------------------------------------------- |
|
3333 // CMmsServerMtm::PruneDuplicateNotificationsL |
|
3334 // |
|
3335 // --------------------------------------------------------- |
|
3336 // |
|
3337 TBool CMmsServerMtm::PruneDuplicateNotificationsL( TMsvId aParent, CMmsHeaders& aNotification ) |
|
3338 { |
|
3339 #ifndef _NO_MMSS_LOGGING_ |
|
3340 TMmsLogger::Log( _L("MmsServer Pruning duplicate notifications") ); |
|
3341 #endif |
|
3342 TInt error = KErrNone; |
|
3343 TBool pruned = EFalse; |
|
3344 TMsvId mmsFolder = FindMMSFolderL(); |
|
3345 |
|
3346 if ( aParent == KMsvNullIndexEntryId ) |
|
3347 { |
|
3348 #ifndef _NO_MMSS_LOGGING_ |
|
3349 TMmsLogger::Log( _L("- no proper parent") ); |
|
3350 #endif |
|
3351 return EFalse; |
|
3352 } |
|
3353 |
|
3354 error = iServerEntry->SetEntry( aParent ); |
|
3355 if ( error != KErrNone ) |
|
3356 { |
|
3357 // cannot access parent, cannot prune. |
|
3358 #ifndef _NO_MMSS_LOGGING_ |
|
3359 TMmsLogger::Log( _L("- cannot access notification parent, error %d "), error ); |
|
3360 #endif |
|
3361 return EFalse; |
|
3362 } |
|
3363 |
|
3364 // show invisible entries |
|
3365 TMsvSelectionOrdering ordering = |
|
3366 TMsvSelectionOrdering( KMsvNoGrouping, EMsvSortByNone, ETrue ); |
|
3367 iServerEntry->SetSort( ordering ); |
|
3368 |
|
3369 CMsvEntrySelection* selection = new( ELeave ) CMsvEntrySelection; |
|
3370 CleanupStack::PushL( selection ); |
|
3371 if ( aParent == mmsFolder ) |
|
3372 { |
|
3373 error = iServerEntry->GetChildrenWithType( KUidMsvMessageEntry, *selection ); |
|
3374 #ifndef _NO_MMSS_LOGGING_ |
|
3375 TMmsLogger::Log( _L("- from MMS Folder") ); |
|
3376 #endif |
|
3377 } |
|
3378 else |
|
3379 { |
|
3380 error = iServerEntry->GetChildrenWithMtm( KUidMsgMMSNotification, *selection ); |
|
3381 #ifndef _NO_MMSS_LOGGING_ |
|
3382 if ( aParent == KMsvGlobalInBoxIndexEntryIdValue ) |
|
3383 { |
|
3384 TMmsLogger::Log( _L("- from Inbox") ); |
|
3385 } |
|
3386 else |
|
3387 { |
|
3388 TMmsLogger::Log( _L("- from mmbox folder") ); |
|
3389 } |
|
3390 #endif |
|
3391 } |
|
3392 |
|
3393 TInt count = selection->Count(); |
|
3394 #ifndef _NO_MMSS_LOGGING_ |
|
3395 TMmsLogger::Log( _L("- %d notifications on disk"), count ); |
|
3396 #endif |
|
3397 if ( error != KErrNone || count == 0 ) |
|
3398 { |
|
3399 // cannot check or no old notifications found, anything goes |
|
3400 CleanupStack::PopAndDestroy( selection ); // selection |
|
3401 return EFalse; |
|
3402 } |
|
3403 |
|
3404 TInt i; |
|
3405 CMmsHeaders* notification = CMmsHeaders::NewL( iMmsSettings->MmsVersion() ); |
|
3406 CleanupStack::PushL( notification ); |
|
3407 CMsvStore* store = NULL; |
|
3408 for ( i = count; i > 0 && !pruned; i-- ) |
|
3409 { |
|
3410 error = iServerEntry->SetEntry( selection->At( i - 1 ) ); |
|
3411 if ( error != KErrNone ) |
|
3412 { |
|
3413 #ifndef _NO_MMSS_LOGGING_ |
|
3414 TMmsLogger::Log( _L("- cannot access notification") ); |
|
3415 #endif |
|
3416 // cannot handle this entry. |
|
3417 continue; |
|
3418 } |
|
3419 if ( ( ( iServerEntry->Entry().iMtmData1 != 0 ) && |
|
3420 ( ( iServerEntry->Entry().iMtmData1 & KMmsMessageTypeMask ) != |
|
3421 KMmsMessageMNotificationInd ) ) || |
|
3422 ( iServerEntry->Entry().iMtmData2 & KMmsNotificationBinary ) ) |
|
3423 { |
|
3424 #ifndef _NO_MMSS_LOGGING_ |
|
3425 TMmsLogger::Log( _L("- not a notification") ); |
|
3426 #endif |
|
3427 continue; |
|
3428 } |
|
3429 |
|
3430 // binary notifications (empty entries) were already handled, so we can delete the rest |
|
3431 if ( iServerEntry->Entry().iMtmData1 == 0 ) |
|
3432 { |
|
3433 // remove garbage. |
|
3434 error = iServerEntry->SetEntry( aParent ); |
|
3435 if ( error == KErrNone ) |
|
3436 { |
|
3437 // never mind the error - we are just doing our best |
|
3438 iServerEntry->DeleteEntry( selection->At( i - 1 ) ); |
|
3439 } |
|
3440 continue; |
|
3441 } |
|
3442 |
|
3443 error = KErrNone; |
|
3444 TRAP( error, |
|
3445 { |
|
3446 store = iServerEntry->ReadStoreL(); |
|
3447 CleanupStack::PushL( store ); |
|
3448 notification->RestoreL( *store ); |
|
3449 CleanupStack::PopAndDestroy( store ); // store |
|
3450 }) |
|
3451 store = NULL; |
|
3452 |
|
3453 if ( error != KErrNone ) |
|
3454 { |
|
3455 #ifndef _NO_MMSS_LOGGING_ |
|
3456 TMmsLogger::Log( _L("- cannot access notification") ); |
|
3457 #endif |
|
3458 // cannot handle this entry. |
|
3459 continue; |
|
3460 } |
|
3461 |
|
3462 // content location is used to identify notifications |
|
3463 // referring to the same message. |
|
3464 // Content location is the only information given back to |
|
3465 // MMSC when fetching a message, therefore it must be unique |
|
3466 if ( notification->ContentLocation().Compare( aNotification.ContentLocation() ) == 0 ) |
|
3467 { |
|
3468 // Identical. This probably means that we have not sent a response yet, |
|
3469 // and MMSC has sent us a new notification. |
|
3470 |
|
3471 #ifndef _NO_MMSS_LOGGING_ |
|
3472 TMmsLogger::Log( _L("- content locations match") ); |
|
3473 #endif |
|
3474 pruned = ETrue; |
|
3475 } |
|
3476 } |
|
3477 |
|
3478 CleanupStack::PopAndDestroy( notification ); |
|
3479 CleanupStack::PopAndDestroy( selection ); |
|
3480 error = iServerEntry->SetEntry( KMsvNullIndexEntryId ); |
|
3481 |
|
3482 return pruned; |
|
3483 } |
|
3484 |
|
3485 // --------------------------------------------------------- |
|
3486 // CMmsServerMtm::CheckNotificationsL |
|
3487 // |
|
3488 // --------------------------------------------------------- |
|
3489 // |
|
3490 void CMmsServerMtm::CheckNotificationsL( CMsvEntrySelection& aSelection ) |
|
3491 { |
|
3492 TInt error = KErrNone; |
|
3493 TMsvId parent = KMsvNullIndexEntryId; |
|
3494 TMsvId mmsFolder = FindMMSFolderL(); |
|
3495 if ( mmsFolder == KMsvNullIndexEntryId ) |
|
3496 { |
|
3497 // no folder... |
|
3498 return; |
|
3499 } |
|
3500 |
|
3501 TInt i; |
|
3502 |
|
3503 // Don't mix notifications from mms folder and inbox, |
|
3504 // in debug mode Symbian scheduler panics. |
|
3505 if ( aSelection.Count() > 0 ) |
|
3506 { |
|
3507 i = aSelection.Count() - 1; |
|
3508 while ( i >= 0 && parent == KMsvNullIndexEntryId ) |
|
3509 { |
|
3510 error = iServerEntry->SetEntry( aSelection.At( 0 ) ); |
|
3511 if ( error == KErrNone ) |
|
3512 { |
|
3513 parent = iServerEntry->Entry().Parent(); |
|
3514 } |
|
3515 else if ( error == KErrNotFound ) |
|
3516 { |
|
3517 // The entry has disappeared already. |
|
3518 aSelection.Delete( i ); |
|
3519 } |
|
3520 else |
|
3521 { |
|
3522 // keep LINT happy |
|
3523 } |
|
3524 i--; |
|
3525 } |
|
3526 } |
|
3527 |
|
3528 if ( parent == KMsvNullIndexEntryId ) |
|
3529 { |
|
3530 parent = mmsFolder; |
|
3531 } |
|
3532 |
|
3533 #ifndef _NO_MMSS_LOGGING_ |
|
3534 TMmsLogger::Log( _L("CheckNotificationsL, got %d entries"), aSelection.Count() ); |
|
3535 #endif |
|
3536 |
|
3537 error = iServerEntry->SetEntry( parent ); |
|
3538 User::LeaveIfError( error ); |
|
3539 |
|
3540 // If no notifications input find notifications from mms folder |
|
3541 if ( parent == mmsFolder && aSelection.Count() == 0 ) |
|
3542 { |
|
3543 error = iServerEntry->GetChildrenWithType( KUidMsvMessageEntry, aSelection ); |
|
3544 #ifndef _NO_MMSS_LOGGING_ |
|
3545 TMmsLogger::Log( _L("Notifications found in mms folder %d "), aSelection.Count() ); |
|
3546 #endif |
|
3547 if ( error != KErrNone ) |
|
3548 { |
|
3549 aSelection.Reset(); // make sure we return no garbage |
|
3550 User::Leave( error ); |
|
3551 } |
|
3552 } |
|
3553 |
|
3554 // notifications in inbox |
|
3555 // If we have a selection, we don't generate new ones, |
|
3556 // An empty selection only lists notifications from MMS folder, we cannot |
|
3557 // touch inbox stuff otherwise. |
|
3558 // MMS Client MTM lists notifications from inbox when mode is changed |
|
3559 // from manual to automatic. |
|
3560 |
|
3561 if ( parent == KMsvGlobalInBoxIndexEntryId ) |
|
3562 { |
|
3563 #ifndef _NO_MMSS_LOGGING_ |
|
3564 TMmsLogger::Log( _L("Notifications found in inbox %d "), aSelection.Count() ); |
|
3565 #endif |
|
3566 TInt j; |
|
3567 for ( j = aSelection.Count() - 1; j >= 0; j-- ) |
|
3568 { |
|
3569 error = iServerEntry->SetEntry( aSelection.At( j ) ); |
|
3570 TMsvEntry entry; |
|
3571 if ( error == KErrNone ) |
|
3572 { |
|
3573 entry = iServerEntry->Entry(); |
|
3574 } |
|
3575 |
|
3576 // Drop notification, if operationForbidden flag is on OR |
|
3577 // if messageexpired flag is on OR |
|
3578 // if notification is not stored in mmbox and forward operation has been succussfull OR |
|
3579 // if notification is deleted succuessfully from mmbox OR |
|
3580 // if notification is fetched successfully from mmbox. |
|
3581 // Or if notification cannot be accessed (used by someone else) |
|
3582 if ( error != KErrNone || |
|
3583 entry.iMtmData2 & KMmsNewOperationForbidden || |
|
3584 entry.iMtmData2 & KMmsMessageExpired || |
|
3585 ( entry.iMtmData2 & KMmsOperationFinished && |
|
3586 !( entry.iMtmData2 & KMmsOperationResult) && |
|
3587 !(entry.iMtmData2 & KMmsStoredInMMBox) ) ) |
|
3588 { |
|
3589 #ifndef _NO_MMSS_LOGGING_ |
|
3590 TMmsLogger::Log( _L(" Dropped " )); |
|
3591 aSelection.Delete( j ); |
|
3592 #endif |
|
3593 } |
|
3594 else |
|
3595 { |
|
3596 // mark this that others can't start do an operation |
|
3597 entry.iMtmData2 |= KMmsNewOperationForbidden; |
|
3598 |
|
3599 // readonly is needed to set EFalse for scheduling |
|
3600 entry.SetReadOnly( EFalse ); |
|
3601 iServerEntry->ChangeEntry( entry ); |
|
3602 // We keep this entry in our selection |
|
3603 } |
|
3604 } |
|
3605 aSelection.Compress(); |
|
3606 } |
|
3607 |
|
3608 error = iServerEntry->SetEntry( parent ); |
|
3609 |
|
3610 // Check the list and see what we got. |
|
3611 // The list may contain both notifications and delivery reports |
|
3612 |
|
3613 TInt count = aSelection.Count(); |
|
3614 #ifndef _NO_MMSS_LOGGING_ |
|
3615 TMmsLogger::Log( _L("Found %d entries altogether"), count ); |
|
3616 #endif |
|
3617 TMsvEntry tEntry; |
|
3618 CMsvEntrySelection* thisNotification = NULL; |
|
3619 TTime now; |
|
3620 TTime entryTime; |
|
3621 |
|
3622 for ( i = count; i > 0; i-- ) |
|
3623 { |
|
3624 error = iServerEntry->SetEntry( aSelection.At( i - 1 ) ); |
|
3625 if ( error == KErrNoMemory ) |
|
3626 { |
|
3627 User::Leave( error ); |
|
3628 } |
|
3629 else if ( error != KErrNone ) |
|
3630 { |
|
3631 continue; |
|
3632 } |
|
3633 else |
|
3634 { |
|
3635 // keep LINT happy |
|
3636 } |
|
3637 tEntry = iServerEntry->Entry(); |
|
3638 parent = tEntry.Parent(); |
|
3639 // We keep only notifications - the rest are removed from the list. |
|
3640 // If we are doing garbage collection, all non-notifications are |
|
3641 // deleted from the disk (because they will never expire). |
|
3642 // See if a notification or dummy entry |
|
3643 if ( iServerEntry->Entry().iMtmData2 & KMmsNotificationBinary && |
|
3644 iCurrentCommand == EMmsGarbageCollection ) |
|
3645 { |
|
3646 // get rid of these as these are empty |
|
3647 #ifndef _NO_MMSS_LOGGING_ |
|
3648 TMmsLogger::Log( _L("- dummy entry - deleting")); |
|
3649 #endif |
|
3650 error = iServerEntry->SetEntry( parent ); |
|
3651 if ( error == KErrNone ) |
|
3652 { |
|
3653 iServerEntry->DeleteEntry( aSelection.At( i - 1 ) ); |
|
3654 } |
|
3655 aSelection.Delete( i - 1 ); |
|
3656 } |
|
3657 else if ( ( tEntry.iMtmData1 & KMmsMessageTypeMask ) != KMmsMessageMNotificationInd ) |
|
3658 { |
|
3659 #ifndef _NO_MMSS_LOGGING_ |
|
3660 TMmsLogger::Log( _L("- not a notification")); |
|
3661 #endif |
|
3662 if ( iCurrentCommand == EMmsGarbageCollection ) |
|
3663 { |
|
3664 // If we are doing garbage collection, these are deleted, too |
|
3665 // If any delivery reports or other non-notification stuff |
|
3666 // is around at garbage collection time, it has become garbage. |
|
3667 |
|
3668 // Garbage collection is called with MMS Service, not with |
|
3669 // local service, so it means that garbage collection cannot |
|
3670 // be called when some other operation is ongoing. |
|
3671 // It should not be possible to delete an entry that is being |
|
3672 // handled already because access to MMS Server MTM is sequential |
|
3673 |
|
3674 // However, a delivery report or read report might just have been |
|
3675 // scheduled for handling. Check that they won't get deleted too soon |
|
3676 |
|
3677 thisNotification = new( ELeave ) CMsvEntrySelection; |
|
3678 CleanupStack::PushL( thisNotification ); |
|
3679 thisNotification->AppendL( aSelection.At( i - 1 ) ); |
|
3680 iScheduleSend->CheckScheduleL( *thisNotification ); |
|
3681 CleanupStack::PopAndDestroy( thisNotification ); |
|
3682 thisNotification = NULL; |
|
3683 |
|
3684 TBool alreadyScheduled = EFalse; |
|
3685 |
|
3686 if ( iServerEntry->Entry().Scheduled() ) |
|
3687 { |
|
3688 // Already scheduled - check, if schedule is valid |
|
3689 // Leave the schedule, if it is in the future - but not too much |
|
3690 now.UniversalTime(); |
|
3691 now += TTimeIntervalSeconds( KMmsScheduleDelay ); |
|
3692 entryTime = iServerEntry->Entry().iDate; |
|
3693 if ( ( ( entryTime - TTimeIntervalHours( KMmsSanityInterval ) ) <= now ) && |
|
3694 ( entryTime > now ) ) |
|
3695 { |
|
3696 // scheduled in the future, we don't touch it |
|
3697 alreadyScheduled = ETrue; |
|
3698 #ifndef _NO_MMSS_LOGGING_ |
|
3699 TMmsLogger::Log( _L("- already scheduled")); |
|
3700 #endif |
|
3701 } |
|
3702 } |
|
3703 |
|
3704 error = iServerEntry->SetEntry( parent ); |
|
3705 if ( error == KErrNone && !alreadyScheduled ) |
|
3706 { |
|
3707 // we delete extra entries - but if they seem to have |
|
3708 // legal schedule we leave them, the scheduling will |
|
3709 // handle them in due time |
|
3710 iServerEntry->DeleteEntry( aSelection.At( i - 1 ) ); |
|
3711 } |
|
3712 } |
|
3713 // We always clear the non-notifications from our list |
|
3714 // Either they were already legally scheduled and were left alone |
|
3715 // or they were gagbage and were deleted |
|
3716 aSelection.Delete( i - 1 ); |
|
3717 } |
|
3718 else |
|
3719 { |
|
3720 // Check if scheduled |
|
3721 |
|
3722 thisNotification = new( ELeave ) CMsvEntrySelection; |
|
3723 CleanupStack::PushL( thisNotification ); |
|
3724 thisNotification->AppendL( aSelection.At( i - 1 ) ); |
|
3725 if ( iCommand != EMmsReceiveForced ) |
|
3726 { |
|
3727 iScheduleSend->CheckScheduleL( *thisNotification ); |
|
3728 } |
|
3729 else |
|
3730 // if we do forced fetch, we clean up old schedules first |
|
3731 { |
|
3732 #ifndef _NO_MMSS_LOGGING_ |
|
3733 TMmsLogger::Log( _L("- cleaning schedules")); |
|
3734 #endif |
|
3735 CleanSchedulesL( *thisNotification ); |
|
3736 tEntry = iServerEntry->Entry(); |
|
3737 } |
|
3738 |
|
3739 if ( iServerEntry->Entry().Scheduled() ) |
|
3740 { |
|
3741 // Already scheduled - check, if schedule is valid |
|
3742 // Reschedule this, if it was scheduled in the past |
|
3743 // The entry is left into the selection list. |
|
3744 // If the list is rescheduled, this entry will |
|
3745 // be rescheduled to a later time. |
|
3746 // Leave the schedule, if it is in the future - but not too much |
|
3747 now.UniversalTime(); |
|
3748 now += TTimeIntervalSeconds( KMmsScheduleDelay ); |
|
3749 entryTime = iServerEntry->Entry().iDate; |
|
3750 if ( ( ( entryTime - TTimeIntervalHours( KMmsSanityInterval ) ) <= now ) && |
|
3751 ( entryTime > now ) ) |
|
3752 { |
|
3753 // scheduled in the future, we don't touch it |
|
3754 #ifndef _NO_MMSS_LOGGING_ |
|
3755 TMmsLogger::Log( _L("- already scheduled")); |
|
3756 #endif |
|
3757 aSelection.Delete( i - 1 ); |
|
3758 } |
|
3759 } |
|
3760 else |
|
3761 { |
|
3762 // Check expiration |
|
3763 CMsvStore * store = NULL; |
|
3764 store = iServerEntry->ReadStoreL(); |
|
3765 CleanupStack::PushL( store ); |
|
3766 iMmsHeaders->RestoreL( *store ); |
|
3767 CleanupStack::PopAndDestroy( store ); |
|
3768 TTime now; |
|
3769 now.UniversalTime(); |
|
3770 #ifndef _NO_MMSS_LOGGING_ |
|
3771 TMmsLogger::Log( _L("MMSserver checking notifications") ); |
|
3772 TMmsLogger::Log( _L("MMS terminal universal datetime: ") ); |
|
3773 CMmsBaseOperation::LogDateL( now ); |
|
3774 TMmsLogger::Log( _L("MMS message expiry datetime:") ); |
|
3775 CMmsBaseOperation::LogNetworkFormatDateL( iMmsHeaders->ExpiryDate() ); |
|
3776 #endif |
|
3777 if ( ( ( iMmsHeaders->ExpiryDate() + iMmsSettings->ExpiryOvershoot() ) * |
|
3778 KMmsMillion ) < now.MicroSecondsFrom( TTime( KMmsYear1970String ) ).Int64() ) |
|
3779 { |
|
3780 // expired |
|
3781 // remove schedule, |
|
3782 iScheduleSend->DeleteScheduleL( *thisNotification ); |
|
3783 |
|
3784 // if the entry is in inbox or in mmbox folder, let it go |
|
3785 if ( parent == KMsvGlobalInBoxIndexEntryIdValue || |
|
3786 parent == iMmsSettings->MMBoxFolder() ) |
|
3787 { |
|
3788 tEntry.SetReadOnly( ETrue ); |
|
3789 // not forbidden for a new operation |
|
3790 tEntry.iMtmData2 &= ~KMmsNewOperationForbidden; |
|
3791 iServerEntry->ChangeEntry( tEntry ); |
|
3792 |
|
3793 } |
|
3794 else // delete the whole entry if it is in mms folder |
|
3795 { |
|
3796 error = iServerEntry->SetEntry( parent ); |
|
3797 if ( error == KErrNone ) |
|
3798 { |
|
3799 iServerEntry->DeleteEntry( aSelection.At( i - 1 ) ); |
|
3800 #ifndef _NO_MMSS_LOGGING_ |
|
3801 TMmsLogger::Log( _L("- whole entry deleted")); |
|
3802 #endif |
|
3803 } |
|
3804 } |
|
3805 #ifndef _NO_MMSS_LOGGING_ |
|
3806 TMmsLogger::Log( _L("- already expired")); |
|
3807 #endif |
|
3808 aSelection.Delete( i - 1 ); |
|
3809 } |
|
3810 } |
|
3811 CleanupStack::PopAndDestroy( thisNotification ); |
|
3812 thisNotification = NULL; |
|
3813 } |
|
3814 } |
|
3815 aSelection.Compress(); |
|
3816 |
|
3817 #ifndef _NO_MMSS_LOGGING_ |
|
3818 TMmsLogger::Log( _L("CheckNotificationsL, %d entries left"), aSelection.Count() ); |
|
3819 #endif |
|
3820 |
|
3821 } |
|
3822 |
|
3823 // --------------------------------------------------------- |
|
3824 // CMmsServerMtm::CreateNotificationsL() |
|
3825 // |
|
3826 // --------------------------------------------------------- |
|
3827 // |
|
3828 void CMmsServerMtm::CreateNotificationsL() |
|
3829 { |
|
3830 // This function is for testing and message variation |
|
3831 |
|
3832 TInt err = KErrNone; |
|
3833 TInt i; |
|
3834 TInt count = 0; |
|
3835 TUint size = 0; |
|
3836 // Include old notifications into the selection |
|
3837 // Except when doing message generation at boot time - |
|
3838 // Then only new notifications are handled |
|
3839 if ( iCurrentCommand != EMmsMessageGeneration ) |
|
3840 { |
|
3841 CheckNotificationsL( *iMsvSelection ); |
|
3842 } |
|
3843 count = iMsvSelection->Count(); |
|
3844 |
|
3845 // If there are notifications to be handled, we don't |
|
3846 // create new ones, because new notification creation |
|
3847 // should be used for testing only |
|
3848 if ( !iMmsSettings->LocalMode() && count > 0 ) |
|
3849 { |
|
3850 #ifndef _NO_MMSS_LOGGING_ |
|
3851 TMmsLogger::Log( _L("CreateNotificationsL - Global mode") ); |
|
3852 TMmsLogger::Log( _L("- %d old notifications, not generating new ones"), count ); |
|
3853 #endif |
|
3854 return; |
|
3855 } |
|
3856 |
|
3857 RFs fs; // We need a separate session to be able to set the session path |
|
3858 err = fs.Connect(); |
|
3859 if ( err != KErrNone ) |
|
3860 { |
|
3861 return; |
|
3862 } |
|
3863 CleanupClosePushL( fs ); |
|
3864 |
|
3865 HBufC8* bufferPointer = HBufC8::NewL( KMaxFileName ); |
|
3866 CleanupStack::PushL( bufferPointer ); |
|
3867 TPtr8 buffer = bufferPointer->Des(); |
|
3868 |
|
3869 CDir* fileList = NULL; |
|
3870 |
|
3871 // create notifications for local messages: |
|
3872 if ( iMmsSettings->LocalMode() ) |
|
3873 { |
|
3874 #ifndef _NO_MMSS_LOGGING_ |
|
3875 TMmsLogger::Log( _L("CreateNotificationsL - Local mode")); |
|
3876 #endif |
|
3877 TEntry* entry = new( ELeave ) TEntry; // allocated from heap to save stack space |
|
3878 CleanupStack::PushL( entry ); |
|
3879 HBufC* filename = HBufC::NewL( iMmsSettings->LocalModeIn().Length() ); |
|
3880 CleanupStack::PushL( filename ); |
|
3881 TPtr fileNamePtr = filename->Des(); |
|
3882 fileNamePtr.Copy( iMmsSettings->LocalModeIn() ); |
|
3883 #ifndef _NO_MMSS_LOGGING_ |
|
3884 TMmsLogger::Log( _L("local mode dir %S "), &fileNamePtr ); |
|
3885 #endif |
|
3886 err = fs.SetSessionPath( fileNamePtr ); |
|
3887 #ifndef _NO_MMSS_LOGGING_ |
|
3888 TMmsLogger::Log( _L("set session path returned: %d"), err ); |
|
3889 HBufC* temp = HBufC::NewL( KMaxPath ); |
|
3890 CleanupStack::PushL( temp ); |
|
3891 TPtr tempPtr = temp->Des(); |
|
3892 fs.SessionPath( tempPtr ); |
|
3893 TMmsLogger::Log( _L("Session path: %S"), &tempPtr ); |
|
3894 CleanupStack::PopAndDestroy( temp ); |
|
3895 temp = NULL; |
|
3896 #endif |
|
3897 err = fs.Entry( fileNamePtr, *entry ); |
|
3898 #ifndef _NO_MMSS_LOGGING_ |
|
3899 TMmsLogger::Log( _L("get path properties returned: %d"), err ); |
|
3900 #endif |
|
3901 if ( err == KErrNone ) |
|
3902 { |
|
3903 TFindFile* finder = new( ELeave ) TFindFile( fs ); // allocated from heap to save stack space |
|
3904 CleanupStack::PushL( finder ); |
|
3905 _LIT( KWild, "*" ); |
|
3906 |
|
3907 err = finder->FindWildByPath( KWild, &fileNamePtr, fileList ); |
|
3908 #ifndef _NO_MMSS_LOGGING_ |
|
3909 TMmsLogger::Log( _L("find files returned: %d"), err ); |
|
3910 #endif |
|
3911 CleanupStack::PopAndDestroy( finder ); |
|
3912 |
|
3913 if ( fileList ) |
|
3914 { |
|
3915 CleanupStack::PushL( fileList ); |
|
3916 } |
|
3917 |
|
3918 if ( err == KErrNone ) |
|
3919 { |
|
3920 count = fileList->Count(); |
|
3921 } |
|
3922 else |
|
3923 { |
|
3924 count = 0; |
|
3925 } |
|
3926 } |
|
3927 |
|
3928 #ifndef _NO_MMSS_LOGGING_ |
|
3929 TMmsLogger::Log( _L("found %d files in %S"), count, &fileNamePtr ); |
|
3930 #endif |
|
3931 for (i = 0; i < count; i++ ) |
|
3932 { |
|
3933 iParse.Set( ( ( *fileList )[i] ).iName, &fileNamePtr, NULL ); |
|
3934 buffer.Copy( iParse.FullName() ); |
|
3935 |
|
3936 size = fs.Entry( iParse.FullName(), *entry ); |
|
3937 size = entry->iSize; |
|
3938 |
|
3939 iNotification = KMsvNullIndexEntryId; |
|
3940 |
|
3941 #ifndef _NO_MMSS_LOGGING_ |
|
3942 TMmsLogger::Log( _L("notification size %d"), size ); |
|
3943 #endif |
|
3944 if ( size > 0 ) |
|
3945 { |
|
3946 if ( !iEncodeBuffer ) |
|
3947 { |
|
3948 iEncodeBuffer = CBufFlat::NewL( 0x400 ); |
|
3949 } |
|
3950 else |
|
3951 { |
|
3952 iEncodeBuffer->Reset(); |
|
3953 } |
|
3954 |
|
3955 CreateNotificationL( buffer, size ); |
|
3956 #ifndef _NO_MMSS_LOGGING_ |
|
3957 TMmsLogger::Log( _L("notification created") ); |
|
3958 #endif |
|
3959 |
|
3960 DecodePushedMessageL(); |
|
3961 #ifndef _NO_MMSS_LOGGING_ |
|
3962 TMmsLogger::Log( _L("notification decoded") ); |
|
3963 #endif |
|
3964 delete iEncodeBuffer; |
|
3965 iEncodeBuffer = NULL; |
|
3966 } |
|
3967 else |
|
3968 { |
|
3969 fs.Delete( iParse.FullName() ); |
|
3970 } |
|
3971 |
|
3972 if ( iNotification != KMsvNullIndexEntryId ) |
|
3973 { |
|
3974 iMsvSelection->AppendL( iNotification ); |
|
3975 } |
|
3976 |
|
3977 } |
|
3978 if ( fileList ) |
|
3979 { |
|
3980 CleanupStack::PopAndDestroy( fileList ); |
|
3981 } |
|
3982 |
|
3983 CleanupStack::PopAndDestroy( filename ); |
|
3984 CleanupStack::PopAndDestroy( entry ); |
|
3985 } |
|
3986 |
|
3987 CleanupStack::PopAndDestroy( bufferPointer ); |
|
3988 CleanupStack::PopAndDestroy( &fs ); // close fs |
|
3989 iServerEntry->SetEntry( iServiceEntryId ); |
|
3990 |
|
3991 #ifndef _NO_MMSS_LOGGING_ |
|
3992 TMmsLogger::Log( _L("CreateNotificationsL - %d notifications"), iMsvSelection->Count() ); |
|
3993 #endif |
|
3994 } |
|
3995 |
|
3996 // --------------------------------------------------------- |
|
3997 // CMmsServerMtm::CreateNotificationL() |
|
3998 // |
|
3999 // --------------------------------------------------------- |
|
4000 // |
|
4001 void CMmsServerMtm::CreateNotificationL( TDesC8& aUrl, TInt aSize ) |
|
4002 { |
|
4003 // for test purposes aUrl will contain the filename. |
|
4004 |
|
4005 // Reset sets the default encapsulation version |
|
4006 // The default version has been set from MmsSettings in NewL |
|
4007 iMmsHeaders->Reset(); |
|
4008 |
|
4009 // construct the notification into iMmsHeaders, and call encode |
|
4010 |
|
4011 iMmsHeaders->SetMessageType( KMmsMessageTypeMNotificationInd ); |
|
4012 |
|
4013 TTime currentTime; |
|
4014 currentTime.UniversalTime(); |
|
4015 currentTime.Int64(); |
|
4016 |
|
4017 TBufC8<KMMSMAXTIDLENGTH> tid; |
|
4018 tid.Des().NumUC( currentTime.Int64(), EHex ); |
|
4019 iMmsHeaders->SetTidL( tid ); |
|
4020 |
|
4021 iMmsHeaders->SetMessageClass( EMmsClassPersonal ); |
|
4022 iMmsHeaders->SetMessageSize( aSize ); |
|
4023 const TInt KTenHours = 10 * 60 * 60; // 10 hours relative expiry |
|
4024 iMmsHeaders->SetExpiryInterval( KTenHours ); |
|
4025 iMmsHeaders->SetContentLocationL( aUrl ); |
|
4026 |
|
4027 CMmsEncode* encoder = CMmsEncode::NewL( iFs ); |
|
4028 CleanupStack::PushL( encoder ); |
|
4029 encoder->EncodeHeadersL( *iMmsHeaders, *iEncodeBuffer ); |
|
4030 CleanupStack::PopAndDestroy( encoder ); // encoder |
|
4031 |
|
4032 } |
|
4033 |
|
4034 // --------------------------------------------------------- |
|
4035 // CMmsServerMtm::GarbageCollectionL |
|
4036 // |
|
4037 // --------------------------------------------------------- |
|
4038 // |
|
4039 void CMmsServerMtm::GarbageCollectionL() |
|
4040 { |
|
4041 #ifndef _NO_MMSS_LOGGING_ |
|
4042 TMmsLogger::Log( _L("MMSServer doing garbage collection") ); |
|
4043 #endif |
|
4044 |
|
4045 // are we in offline mode... |
|
4046 // We use CMmsSendOperation to allow change in the name of the |
|
4047 // base opeation class. The function is in the base class anyway. |
|
4048 if ( !CMmsSendOperation::NetworkOperationsAllowed() ) |
|
4049 { |
|
4050 // not allowed to send or receive anything |
|
4051 User::Leave( KMmsErrorOfflineMode ); |
|
4052 } |
|
4053 |
|
4054 // MMS watcher sends us reason codes with garbage collection parameters. |
|
4055 // paramPack().iReasonFlags will contain the reason flags. |
|
4056 // paramPack().iMediaUnavailableTime tells when the memory card was removed |
|
4057 TMMSGarbageCollectionParameters param; |
|
4058 TPckgC<TMMSGarbageCollectionParameters> paramPack( param ); |
|
4059 paramPack.Set( iParameter ); |
|
4060 |
|
4061 #ifndef _NO_MMSS_LOGGING_ |
|
4062 TMmsLogger::Log( _L("- reason code:") ); |
|
4063 if ( paramPack().iReasonFlags & KMmsReasonBoot ) |
|
4064 { |
|
4065 TMmsLogger::Log( _L(" -- Boot") ); |
|
4066 } |
|
4067 if ( paramPack().iReasonFlags & KMmsReasonMessageStoreChanged ) |
|
4068 { |
|
4069 TMmsLogger::Log( _L(" -- MessageStoreChanged") ); |
|
4070 } |
|
4071 if ( paramPack().iReasonFlags & KMmsReasonNetworkAllowed ) |
|
4072 { |
|
4073 TMmsLogger::Log( _L(" -- Network operations allowed") ); |
|
4074 } |
|
4075 if ( paramPack().iReasonFlags & KMmsReasonBackupEnded ) |
|
4076 { |
|
4077 TMmsLogger::Log( _L(" -- Backup ended") ); |
|
4078 } |
|
4079 if ( paramPack().iReasonFlags & KMmsReasonHotswap ) |
|
4080 { |
|
4081 TMmsLogger::Log( _L(" -- Hotswap") ); |
|
4082 } |
|
4083 if ( paramPack().iReasonFlags & KMmsReasonEnvironmentTimeChanged ) |
|
4084 { |
|
4085 TMmsLogger::Log( _L(" -- Environment time change") ); |
|
4086 } |
|
4087 #endif |
|
4088 |
|
4089 // |
|
4090 // Forward entries left in outbox |
|
4091 // |
|
4092 GcOutBoxNotificationsL(); |
|
4093 |
|
4094 // |
|
4095 // Message entries left in outbox |
|
4096 // |
|
4097 GcOutBoxMessagesL(); |
|
4098 |
|
4099 // |
|
4100 // Notifications in MMSFolder (automatic fetch) |
|
4101 // |
|
4102 GcMmsFolderNotificationsL(); |
|
4103 |
|
4104 // |
|
4105 // Notifications from inbox |
|
4106 // |
|
4107 GcInboxNotifications(); |
|
4108 |
|
4109 // |
|
4110 // Notifications in mmbox folder |
|
4111 // |
|
4112 GcMmboxFolderNotifications(); |
|
4113 |
|
4114 } |
|
4115 |
|
4116 // --------------------------------------------------------- |
|
4117 // CMmsServerMtm::CleanSchedulesL |
|
4118 // |
|
4119 // --------------------------------------------------------- |
|
4120 // |
|
4121 void CMmsServerMtm::CleanSchedulesL( CMsvEntrySelection& aSelection ) |
|
4122 { |
|
4123 // delete old schedules and reset scheduled entry. |
|
4124 // we trap each entry separately, so that we can clean as |
|
4125 // many as possible even if there are errors |
|
4126 |
|
4127 TMsvId oldEntry = iServerEntry->Entry().Id(); |
|
4128 TInt i; |
|
4129 CMsvEntrySelection* thisNotification = new( ELeave ) CMsvEntrySelection; |
|
4130 CleanupStack::PushL( thisNotification ); |
|
4131 TInt error = KErrNone; |
|
4132 |
|
4133 for ( i = 0; i < aSelection.Count(); i++ ) |
|
4134 { |
|
4135 TRAP ( error, |
|
4136 { |
|
4137 error = iServerEntry->SetEntry( aSelection.At( i ) ); |
|
4138 if ( error == KErrNone ) |
|
4139 { |
|
4140 CMmsScheduledEntry* mmsScheduledEntry = |
|
4141 CMmsScheduledEntry::NewL( iServerEntry->Entry() ); |
|
4142 CleanupStack::PushL( mmsScheduledEntry ); |
|
4143 thisNotification->Reset(); |
|
4144 thisNotification->AppendL( aSelection.At( i ) ); |
|
4145 iScheduleSend->DeleteScheduleL( *thisNotification ); |
|
4146 |
|
4147 CMsvStore* store = NULL; |
|
4148 store = iServerEntry->EditStoreL(); |
|
4149 CleanupStack::PushL( store ); |
|
4150 // We clean up the old scheduled entry data |
|
4151 // by storing a new clean scheduled entry |
|
4152 mmsScheduledEntry->StoreL( *store ); |
|
4153 store->CommitL(); |
|
4154 |
|
4155 CleanupStack::PopAndDestroy( store ); |
|
4156 CleanupStack::PopAndDestroy( mmsScheduledEntry ); |
|
4157 } |
|
4158 } |
|
4159 ); |
|
4160 } |
|
4161 CleanupStack::PopAndDestroy( thisNotification ); |
|
4162 // restore the entry we were pointing at |
|
4163 // if this fails, something is seriously wrong. We did not delete anything. |
|
4164 iServerEntry->SetEntry( oldEntry ); |
|
4165 |
|
4166 } |
|
4167 |
|
4168 // --------------------------------------------------------- |
|
4169 // CMmsServerMtm::FindMMSFolderL |
|
4170 // |
|
4171 // --------------------------------------------------------- |
|
4172 // |
|
4173 TMsvId CMmsServerMtm::FindMMSFolderL() |
|
4174 { |
|
4175 // Actually the value in iMmsSettings should be correct |
|
4176 // but we try to really search for the folder in case |
|
4177 // the message store has been moved or something |
|
4178 TMsvId mmsFolderId = iMmsSettings->NotificationFolder(); |
|
4179 TInt error; |
|
4180 |
|
4181 // get a new entry, don't mess up with the original entry. |
|
4182 CMsvServerEntry* workingEntry = NULL; |
|
4183 TRAP( error, workingEntry = iServerEntry->NewEntryL( KMsvLocalServiceIndexEntryId ) ); |
|
4184 CleanupStack::PushL( workingEntry ); |
|
4185 |
|
4186 if ( error == KErrNoMemory ) |
|
4187 { |
|
4188 CleanupStack::PopAndDestroy( workingEntry ); |
|
4189 User::Leave( error ); |
|
4190 } |
|
4191 |
|
4192 if ( error != KErrNone ) |
|
4193 { |
|
4194 // no can do |
|
4195 CleanupStack::PopAndDestroy( workingEntry ); |
|
4196 return mmsFolderId; |
|
4197 } |
|
4198 |
|
4199 // Get List of services |
|
4200 // show invisible entries |
|
4201 TMsvSelectionOrdering ordering = |
|
4202 TMsvSelectionOrdering( KMsvNoGrouping, EMsvSortByIdReverse, ETrue ); |
|
4203 workingEntry->SetSort( ordering ); |
|
4204 CMsvEntrySelection* selection = new( ELeave ) CMsvEntrySelection; |
|
4205 error = workingEntry->GetChildrenWithType( KUidMsvFolderEntry, *selection ); |
|
4206 if ( error != KErrNone ) |
|
4207 { |
|
4208 // no can do |
|
4209 delete selection; |
|
4210 if ( error == KErrNoMemory ) |
|
4211 { |
|
4212 CleanupStack::PopAndDestroy( workingEntry ); |
|
4213 User::Leave( error ); |
|
4214 } |
|
4215 else |
|
4216 { |
|
4217 CleanupStack::PopAndDestroy( workingEntry ); |
|
4218 return mmsFolderId; |
|
4219 } |
|
4220 } |
|
4221 CleanupStack::PushL( selection ); |
|
4222 |
|
4223 // Now we should have a list of all local folders. |
|
4224 // prune away the standard folders. |
|
4225 // They should be at the end of the list |
|
4226 |
|
4227 TInt count = selection->Count(); |
|
4228 TInt i; |
|
4229 |
|
4230 for ( i = count - 1; i >= 0; i-- ) |
|
4231 { |
|
4232 if ( selection->At( i ) <= KMsvDeletedEntryFolderEntryId ) |
|
4233 { |
|
4234 // Anything below this should not be ours |
|
4235 selection->Delete( i ); |
|
4236 } |
|
4237 } |
|
4238 |
|
4239 // anything left... |
|
4240 count = selection->Count(); |
|
4241 |
|
4242 for ( i = 0; i < count && mmsFolderId == KMsvNullIndexEntryId ; i++ ) |
|
4243 { |
|
4244 error = workingEntry->SetEntry( selection->At( i ) ); |
|
4245 if ( error == KErrNoMemory ) |
|
4246 { |
|
4247 CleanupStack::PopAndDestroy( selection ); |
|
4248 CleanupStack::PopAndDestroy( workingEntry ); |
|
4249 User::Leave( error ); |
|
4250 } |
|
4251 // must be exact match |
|
4252 if ( error == KErrNone && |
|
4253 workingEntry->Entry().iDetails.Compare( KMMSNotificationFolder ) == 0 ) |
|
4254 { |
|
4255 mmsFolderId = selection->At( i ); |
|
4256 } |
|
4257 } |
|
4258 CleanupStack::PopAndDestroy( selection ); |
|
4259 CleanupStack::PopAndDestroy( workingEntry ); |
|
4260 |
|
4261 return mmsFolderId; |
|
4262 } |
|
4263 |
|
4264 // --------------------------------------------------------- |
|
4265 // CMmsServerMtm::DiskSpaceBelowCriticalForScheduling |
|
4266 // |
|
4267 // --------------------------------------------------------- |
|
4268 // |
|
4269 TBool CMmsServerMtm::DiskSpaceBelowCriticalForSchedulingL( RFs* aFs, |
|
4270 TInt aBytesToWrite, TInt aMessageDrive) |
|
4271 { |
|
4272 TBool belowCritical = EFalse; // optimistic |
|
4273 // The amount of memory needed depends on the number of messages to handle |
|
4274 belowCritical = TMmsGenUtils::DiskSpaceBelowCriticalLevelL( |
|
4275 aFs, KMmsTaskSpace * iMsvSelection->Count(), EDriveC ); |
|
4276 if ( !belowCritical ) |
|
4277 { |
|
4278 belowCritical = TMmsGenUtils::DiskSpaceBelowCriticalLevelL( |
|
4279 aFs, aBytesToWrite, aMessageDrive ); |
|
4280 } |
|
4281 return belowCritical; |
|
4282 } |
|
4283 |
|
4284 // --------------------------------------------------------- |
|
4285 // CMmsServerMtm::ScheduleSelectionL |
|
4286 // |
|
4287 // --------------------------------------------------------- |
|
4288 // |
|
4289 TInt CMmsServerMtm::ScheduleSelectionL() |
|
4290 { |
|
4291 #ifndef _NO_MMSS_LOGGING_ |
|
4292 TMmsLogger::Log( _L("CMmsServerMtm::ScheduleSelectionL") ); |
|
4293 #endif |
|
4294 |
|
4295 TInt error = KErrNone; |
|
4296 TInt i; |
|
4297 if ( iMsvSelection->Count() > 0 ) |
|
4298 { |
|
4299 TCommandParameters param; |
|
4300 TPckgC<TCommandParameters> paramPack( param ); |
|
4301 paramPack.Set( iParameter ); |
|
4302 |
|
4303 MakeDatesIdenticalL( *iMsvSelection, paramPack().iInitialDelay, ETrue ); |
|
4304 // Query about disk space. |
|
4305 // Subroutine knows how much must be checked for task scheduler |
|
4306 if ( DiskSpaceBelowCriticalForSchedulingL( &iFs, 0, iMessageDrive ) ) |
|
4307 { |
|
4308 // we use standard error code here |
|
4309 error = KErrDiskFull; |
|
4310 } |
|
4311 else |
|
4312 { |
|
4313 // We must set the caller's status to KRequest Pending because |
|
4314 // CScheduleBaseServerMtm::ScheduleL does not do it. |
|
4315 *iRequestStatus = KRequestPending; |
|
4316 TRAP( error, ScheduleL( *iMsvSelection, EFalse, iParameter, *iRequestStatus ) ); |
|
4317 // ScheduleL would complete our caller, but if it leaves, |
|
4318 // we must complete. We don't want to leave without cleaning up first. |
|
4319 #ifndef _NO_MMSS_LOGGING_ |
|
4320 if ( error != KErrNone ) |
|
4321 { |
|
4322 TMmsLogger::Log( _L("- ScheduleL left with error %d"), error ); |
|
4323 } |
|
4324 #endif |
|
4325 } |
|
4326 if ( error != KErrNone ) |
|
4327 { |
|
4328 // Put the entries into failed state because we could not schedule them. |
|
4329 for ( i = 0; i < iMsvSelection->Count(); i++ ) |
|
4330 { |
|
4331 if ( iServerEntry->SetEntry( iMsvSelection->At( i ) ) == KErrNone ) |
|
4332 { |
|
4333 TMsvEntry entry = iServerEntry->Entry(); |
|
4334 TMsvId parent = entry.Parent(); |
|
4335 |
|
4336 TMsvId mmboxFolder = iMmsSettings->MMBoxFolder(); |
|
4337 |
|
4338 if ( entry.iMtm == KUidMsgMMSNotification && |
|
4339 ( parent == KMsvGlobalInBoxIndexEntryIdValue || |
|
4340 parent == mmboxFolder ) ) |
|
4341 { |
|
4342 // if the notification is in mmbox folder and duplicate exists, |
|
4343 // the duplicate has to be marked too. |
|
4344 if ( parent == mmboxFolder ) |
|
4345 { |
|
4346 #ifndef _NO_MMSS_LOGGING_ |
|
4347 TMmsLogger::Log( _L("- parent is mmbox folder") ); |
|
4348 #endif |
|
4349 TRAP_IGNORE( CMmsBaseOperation::MarkDuplicateL( |
|
4350 CMmsBaseOperation::EMmsNotificationOperationFailed, |
|
4351 *iServerEntry ) ); |
|
4352 } |
|
4353 |
|
4354 // Mark original notification |
|
4355 entry = iServerEntry->Entry(); |
|
4356 CMmsBaseOperation::MarkNotificationOperationFailed( entry ); |
|
4357 entry.SetSendingState( KMsvSendStateFailed ); |
|
4358 entry.iError = error; |
|
4359 entry.SetReadOnly( ETrue ); |
|
4360 #ifndef _NO_MMSS_LOGGING_ |
|
4361 TMmsLogger::Log( _L("- marked original notification as failed") ); |
|
4362 #endif |
|
4363 } |
|
4364 iServerEntry->ChangeEntry( entry ); |
|
4365 } |
|
4366 } |
|
4367 *iRequestStatus = KRequestPending; |
|
4368 User::RequestComplete( iRequestStatus, error ); |
|
4369 } |
|
4370 } |
|
4371 return error; |
|
4372 } |
|
4373 |
|
4374 // --------------------------------------------------------- |
|
4375 // CMmsServerMtm::HandleDummyEntryL |
|
4376 // |
|
4377 // --------------------------------------------------------- |
|
4378 // |
|
4379 void CMmsServerMtm::HandleDummyEntryL() |
|
4380 { |
|
4381 // |
|
4382 // Get access to the streamstore of the entry |
|
4383 // |
|
4384 #ifndef _NO_MMSS_LOGGING_ |
|
4385 TMmsLogger::Log( _L("HandleDummyEntryL()") ); |
|
4386 #endif |
|
4387 if ( iMsvSelection->Count() == 0 ) |
|
4388 { |
|
4389 User::Leave( KErrNotFound ); |
|
4390 } |
|
4391 |
|
4392 User::LeaveIfError( iServerEntry->SetEntry( iMsvSelection->At( 0 ) ) ); |
|
4393 CMsvStore* store = iServerEntry->ReadStoreL(); |
|
4394 CleanupStack::PushL( store ); // *** |
|
4395 RMsvReadStream ins; |
|
4396 ins.OpenLC( *store, KUidBinaryNotificationStream ); // *** |
|
4397 |
|
4398 // |
|
4399 // Read first 32 bits into integer. It will tell the length of the data |
|
4400 // |
|
4401 TInt datalength = ins.ReadUint32L(); |
|
4402 #ifndef _NO_MMSS_LOGGING_ |
|
4403 TMmsLogger::Log( _L(" - Streamed %d bytes from dummy-entry's store"), datalength ); |
|
4404 #endif |
|
4405 |
|
4406 // |
|
4407 // Reserve correct size buffer |
|
4408 // |
|
4409 if ( !iEncodeBuffer ) |
|
4410 { |
|
4411 iEncodeBuffer = CBufFlat::NewL( datalength ); |
|
4412 iEncodeBuffer->ResizeL( datalength ); |
|
4413 } |
|
4414 else |
|
4415 { |
|
4416 // Throw away old stuff and resize |
|
4417 iEncodeBuffer->Reset(); |
|
4418 iEncodeBuffer->ResizeL( datalength ); |
|
4419 } |
|
4420 TPtr8 pBuf = iEncodeBuffer->Ptr( 0 ); |
|
4421 |
|
4422 // |
|
4423 // Read the data into buffer |
|
4424 // |
|
4425 ins.ReadL( pBuf ); |
|
4426 CleanupStack::PopAndDestroy( &ins ); // close in |
|
4427 CleanupStack::PopAndDestroy( store ); |
|
4428 |
|
4429 // |
|
4430 // Clean up: the dummy entry is deleted |
|
4431 // |
|
4432 if ( iServerEntry->SetEntry( iServerEntry->Entry().Parent() ) == KErrNone ) |
|
4433 { |
|
4434 iServerEntry->DeleteEntry( iMsvSelection->At( 0 ) ); |
|
4435 } |
|
4436 iServerEntry->SetEntry( KMsvNullIndexEntryId ); |
|
4437 iMsvSelection->Reset(); |
|
4438 } |
|
4439 |
|
4440 // --------------------------------------------------------- |
|
4441 // CMmsServerMtm::HandleMMBoxFlagL |
|
4442 // |
|
4443 // --------------------------------------------------------- |
|
4444 // |
|
4445 void CMmsServerMtm::HandleMMBoxFlagL( TMsvEntry& aEntry ) |
|
4446 { |
|
4447 #ifndef _NO_MMSS_LOGGING_ |
|
4448 TMmsLogger::Log( _L("HandleMMBoxFlagL()") ); |
|
4449 #endif |
|
4450 // Is there an mmbox field in the notification PDU... |
|
4451 if( iMmsHeaders->MMBoxMessageHeadersL().MmsStored() == 0 ) |
|
4452 { |
|
4453 TInt value = 0; |
|
4454 TInt error = KErrNone; |
|
4455 CRepository* repository = NULL; |
|
4456 TRAPD( error2, |
|
4457 // Notification does not contain explicit field, so checking cenrep |
|
4458 repository = CRepository::NewL( KUidMmsServerMtm ) ); // *** |
|
4459 if ( error2 == KErrNone ) |
|
4460 { |
|
4461 CleanupStack::PushL( repository ); |
|
4462 #ifndef _NO_MMSS_LOGGING_ |
|
4463 TMmsLogger::Log( _L("- repository created") ); |
|
4464 #endif |
|
4465 error = repository->Get( KMmsEnginePseudoMMBox, value ); |
|
4466 if( error == KErrNone && value == 1 ) |
|
4467 { |
|
4468 // Assuming MMBox storage in this case |
|
4469 aEntry.iMtmData2 |= KMmsStoredInMMBox; |
|
4470 #ifndef _NO_MMSS_LOGGING_ |
|
4471 TMmsLogger::Log( _L("- Setting MMBox flag based on cenrep data!") ); |
|
4472 #endif |
|
4473 } |
|
4474 else |
|
4475 { |
|
4476 #ifndef _NO_MMSS_LOGGING_ |
|
4477 TMmsLogger::Log( _L("- Key not found from cenrep data, or value != 1") ); |
|
4478 #endif |
|
4479 } |
|
4480 CleanupStack::PopAndDestroy( repository ); |
|
4481 } |
|
4482 } |
|
4483 else if( iMmsHeaders->MMBoxMessageHeadersL().MmsStored() == KMmsYes ) |
|
4484 { |
|
4485 // Notification specifies the flag as 'yes' |
|
4486 #ifndef _NO_MMSS_LOGGING_ |
|
4487 TMmsLogger::Log( _L("- Notification contains stored in mmbox flag!") ); |
|
4488 #endif |
|
4489 aEntry.iMtmData2 |= KMmsStoredInMMBox; |
|
4490 } |
|
4491 else |
|
4492 { |
|
4493 // Keep LINT happy |
|
4494 } |
|
4495 } |
|
4496 |
|
4497 // --------------------------------------------------------- |
|
4498 // CMmsServerMtm::GcOutBoxMessagesL |
|
4499 // |
|
4500 // --------------------------------------------------------- |
|
4501 // |
|
4502 void CMmsServerMtm::GcOutBoxMessagesL() |
|
4503 { |
|
4504 #ifndef _NO_MMSS_LOGGING_ |
|
4505 TMmsLogger::Log( _L("CMmsServerMtm::GcOutBoxMessagesL") ); |
|
4506 #endif |
|
4507 // |
|
4508 // MMS watcher sends us reason codes with garbage collection parameters. |
|
4509 // paramPack().iReasonFlags will contain the reason flags. |
|
4510 // paramPack().iMediaUnavailableTime tells when the memory card was removed |
|
4511 // |
|
4512 TMMSGarbageCollectionParameters param; |
|
4513 TPckgC<TMMSGarbageCollectionParameters> paramPack( param ); |
|
4514 paramPack.Set( iParameter ); |
|
4515 |
|
4516 TMsvEntry entry; |
|
4517 |
|
4518 iMsvSelection->Reset(); |
|
4519 TInt err = iServerEntry->SetEntry( KMsvGlobalOutBoxIndexEntryId ); |
|
4520 // Get entries of type MMS Message |
|
4521 if ( err == KErrNone ) |
|
4522 { |
|
4523 err = iServerEntry->GetChildrenWithMtm( KUidMsgTypeMultimedia, *iMsvSelection ); |
|
4524 } |
|
4525 TInt count = iMsvSelection->Count(); |
|
4526 #ifndef _NO_MMSS_LOGGING_ |
|
4527 TMmsLogger::Log( _L("- found %d message entries from outbox"), count ); |
|
4528 #endif |
|
4529 |
|
4530 if ( err == KErrNone && count > 0 ) |
|
4531 { |
|
4532 // iSendOperation should not be around in this context. |
|
4533 // To avoid possible memory leaks, we clean it away anyway |
|
4534 delete iSendOperation; |
|
4535 iSendOperation = NULL; |
|
4536 iSendOperation = CMmsSendOperation::NewL( iFs, iMmsSettings ); |
|
4537 |
|
4538 iSendOperation->Failed().AppendL( iMsvSelection->Back( 0 ), count ); |
|
4539 iSendOperation->Sent().SetReserveL( count ); |
|
4540 |
|
4541 CMsvEntrySelection* selection = new( ELeave ) CMsvEntrySelection; |
|
4542 CleanupStack::PushL( selection ); |
|
4543 while ( count-- ) |
|
4544 { |
|
4545 // The detailed handling depends both on the state of the entry |
|
4546 // and the event that triggered the garbage collection. |
|
4547 // Some states are handled differently depending on the event, |
|
4548 // some states are always hanldled the same way. |
|
4549 if ( iServerEntry->SetEntry( iMsvSelection->At( count ) ) == KErrNone ) |
|
4550 { |
|
4551 entry = iServerEntry->Entry(); |
|
4552 selection->Reset(); |
|
4553 selection->AppendL( iMsvSelection->At( count ) ); |
|
4554 switch ( entry.SendingState() ) |
|
4555 { |
|
4556 case KMsvSendStateSent: |
|
4557 { |
|
4558 #ifndef _NO_MMSS_LOGGING_ |
|
4559 TMmsLogger::Log( _L("- already sent")); |
|
4560 #endif |
|
4561 // Sent entries are always moved to sent folder (or deleted) |
|
4562 // regardless of trigger event |
|
4563 // A sent message should not be in outbox. It should have already been |
|
4564 // moved to sent folder. However, as it is not moved, we must do it. |
|
4565 if ( iServerEntry->SetEntry( KMsvGlobalOutBoxIndexEntryId ) == KErrNone ) |
|
4566 { |
|
4567 if ( iMmsSettings->MoveToSent() ) |
|
4568 { |
|
4569 // Move entry from Outbox to Sent Folder |
|
4570 // count has originally been set to iMsvSelection->Count(). |
|
4571 iServerEntry->MoveEntryWithinService( |
|
4572 iMsvSelection->At( count ), KMsvSentEntryIdValue ); |
|
4573 // This will not fail |
|
4574 if ( iSendOperation->Failed().Count() > count ) |
|
4575 { |
|
4576 iSendOperation->Sent().AppendL( |
|
4577 iSendOperation->Failed().At( count ) ); |
|
4578 } |
|
4579 } |
|
4580 else |
|
4581 { |
|
4582 // Move entry to Message Heaven |
|
4583 iServerEntry->DeleteEntry( iMsvSelection->At( count ) ); |
|
4584 } |
|
4585 } |
|
4586 iSendOperation->Failed().Delete( count ); |
|
4587 break; |
|
4588 } |
|
4589 case KMsvSendStateWaiting: |
|
4590 case KMsvSendStateSending: |
|
4591 #ifndef _NO_MMSS_LOGGING_ |
|
4592 if ( entry.SendingState() == KMsvSendStateWaiting ) |
|
4593 { |
|
4594 TMmsLogger::Log( _L("- waiting")); |
|
4595 } |
|
4596 else |
|
4597 { |
|
4598 TMmsLogger::Log( _L("- sending")); |
|
4599 } |
|
4600 #endif |
|
4601 if ( paramPack().iReasonFlags & |
|
4602 ( KMmsReasonHotswap | KMmsReasonBackupEnded ) ) |
|
4603 { |
|
4604 // reschedule if last time accessed earlier that media unavailable time stamp |
|
4605 if ( iServerEntry->Entry().iDate > paramPack().iMediaUnavailableTime ) |
|
4606 { |
|
4607 // Access time is after media unavailable, |
|
4608 // It means that something has been done to this entry already. |
|
4609 // Better leave it as is. |
|
4610 #ifndef _NO_MMSS_LOGGING_ |
|
4611 TMmsLogger::Log( _L(" -- accessed after media unavailable - leave as is")); |
|
4612 #endif |
|
4613 iSendOperation->Failed().Delete( count ); |
|
4614 } |
|
4615 } |
|
4616 else |
|
4617 { |
|
4618 iSendOperation->Failed().Delete( count ); |
|
4619 } |
|
4620 break; |
|
4621 case KMsvSendStateUponRequest: |
|
4622 #ifndef _NO_MMSS_LOGGING_ |
|
4623 TMmsLogger::Log( _L("- upon request")); |
|
4624 #endif |
|
4625 // Entries in "upon request" state are not rescheduled |
|
4626 iSendOperation->Failed().Delete( count ); |
|
4627 break; |
|
4628 case KMsvSendStateSuspended: |
|
4629 #ifndef _NO_MMSS_LOGGING_ |
|
4630 TMmsLogger::Log( _L("- suspended")); |
|
4631 #endif |
|
4632 // entries in "upon request" or "suspended" state are not rescheduled |
|
4633 // unless we have switched from offline mode back to online mode |
|
4634 if ( !( ( paramPack().iReasonFlags & KMmsReasonNetworkAllowed ) && |
|
4635 ( entry.SendingState() == KMmsOffLineState ) && |
|
4636 ( entry.iError == KMmsErrorOfflineMode ) ) ) |
|
4637 { |
|
4638 iSendOperation->Failed().Delete( count ); |
|
4639 } |
|
4640 break; |
|
4641 case KMsvSendStateScheduled: |
|
4642 case KMsvSendStateResend: |
|
4643 { |
|
4644 #ifndef _NO_MMSS_LOGGING_ |
|
4645 TMmsLogger::Log( _L("- already scheduled")); |
|
4646 #endif |
|
4647 // These are either rescheduled or scheduled for the first time |
|
4648 // reschedule if the schedule is in the past |
|
4649 // If the scedule is in the past, CheckSchedule moves it forward. |
|
4650 // However, if it is too much in the past, it is moved forward by a year. |
|
4651 // We must do some sanity chaecking about the amount of change |
|
4652 |
|
4653 // we set flag to indicate that our shedule had passed |
|
4654 TInt oldSchedule = EFalse; |
|
4655 TTime now; |
|
4656 now.UniversalTime(); |
|
4657 |
|
4658 if ( iServerEntry->Entry().iDate < now ) |
|
4659 { |
|
4660 oldSchedule = ETrue; |
|
4661 } |
|
4662 |
|
4663 iScheduleSend->CheckScheduleL( *selection ); |
|
4664 if ( iServerEntry->Entry().Scheduled() ) |
|
4665 { |
|
4666 // already scheduled - check, if schedule is valid |
|
4667 TTime scheduleTime = iServerEntry->Entry().iDate; |
|
4668 now += TTimeIntervalSeconds( 1 ); |
|
4669 #ifndef _NO_MMSS_LOGGING_ |
|
4670 TMmsLogger::Log( _L("MMS terminal universal datetime: ") ); |
|
4671 CMmsBaseOperation::LogDateL( now ); |
|
4672 TMmsLogger::Log( _L("Scheduled datetime:") ); |
|
4673 CMmsBaseOperation::LogDateL( scheduleTime ); |
|
4674 #endif |
|
4675 // leave the schedule, if it is in the future - but not too much |
|
4676 TTimeIntervalMinutes allowance = |
|
4677 TTimeIntervalMinutes( KMmsScheduleAllowance ); |
|
4678 if ( ( ( ( scheduleTime - allowance ) <= now ) && ( scheduleTime > now ) ) |
|
4679 || !oldSchedule ) |
|
4680 { |
|
4681 // scheduled in the future, we don't touch it |
|
4682 // or the schedule has been originally set into the future, |
|
4683 // and we don't want to change it |
|
4684 iSendOperation->Failed().Delete( count ); |
|
4685 } |
|
4686 #ifndef _NO_MMSS_LOGGING_ |
|
4687 else |
|
4688 { |
|
4689 TMmsLogger::Log( _L("- bad schedule")); |
|
4690 } |
|
4691 #endif |
|
4692 } |
|
4693 break; |
|
4694 } |
|
4695 case KMsvSendStateNotApplicable: |
|
4696 #ifndef _NO_MMSS_LOGGING_ |
|
4697 TMmsLogger::Log( _L("- not applicable")); |
|
4698 #endif |
|
4699 break; |
|
4700 case KMsvSendStateUnknown: |
|
4701 #ifndef _NO_MMSS_LOGGING_ |
|
4702 TMmsLogger::Log( _L("- unknown")); |
|
4703 #endif |
|
4704 break; |
|
4705 case KMsvSendStateFailed: |
|
4706 #ifndef _NO_MMSS_LOGGING_ |
|
4707 TMmsLogger::Log( _L("- failed")); |
|
4708 #endif |
|
4709 break; |
|
4710 default: |
|
4711 // all entries that are left in the array, are rescheduled in the end |
|
4712 break; |
|
4713 } |
|
4714 } |
|
4715 } |
|
4716 CleanupStack::PopAndDestroy( selection ); |
|
4717 iCommand = EMmsSend; |
|
4718 // whatever was left gets rescheduled |
|
4719 MakeDatesIdenticalL( iSendOperation->Failed(), KMmsGarbageCollectionDelay ); |
|
4720 TRAP( err, UpdateEntriesL() ); |
|
4721 } |
|
4722 } |
|
4723 |
|
4724 // --------------------------------------------------------- |
|
4725 // CMmsServerMtm::GcMmsFolderNotificationsL |
|
4726 // |
|
4727 // --------------------------------------------------------- |
|
4728 // |
|
4729 void CMmsServerMtm::GcMmsFolderNotificationsL() |
|
4730 { |
|
4731 #ifndef _NO_MMSS_LOGGING_ |
|
4732 TMmsLogger::Log( _L("CMmsServerMtm::GcMmsFolderNotificationsL") ); |
|
4733 #endif |
|
4734 // |
|
4735 // MMS watcher sends us reason codes with garbage collection parameters. |
|
4736 // paramPack().iReasonFlags will contain the reason flags. |
|
4737 // paramPack().iMediaUnavailableTime tells when the memory card was removed |
|
4738 // |
|
4739 TMMSGarbageCollectionParameters param; |
|
4740 TPckgC<TMMSGarbageCollectionParameters> paramPack( param ); |
|
4741 paramPack.Set( iParameter ); |
|
4742 |
|
4743 TMsvEntry entry; |
|
4744 iServerEntry->SetEntry( KMsvNullIndexEntryId ); |
|
4745 TMsvId parent = FindMMSFolderL(); |
|
4746 |
|
4747 TInt err = iServerEntry->SetEntry( parent ); |
|
4748 iMsvSelection->Reset(); |
|
4749 // All entries in MMSFolder have the same Uid as messages |
|
4750 // There may be notifications, delivery reports and read reports. |
|
4751 // If the whole notification folder has disappeared we cannot have messages either... |
|
4752 if ( err == KErrNone && parent != KMsvNullIndexEntryId ) |
|
4753 { |
|
4754 err = iServerEntry->GetChildrenWithType( KUidMsvMessageEntry, *iMsvSelection ); |
|
4755 } |
|
4756 TInt count = iMsvSelection->Count(); |
|
4757 #ifndef _NO_MMSS_LOGGING_ |
|
4758 TMmsLogger::Log( _L(" - found %d notification entries"), iMsvSelection->Count() ); |
|
4759 #endif |
|
4760 |
|
4761 if ( err == KErrNone && count > 0 ) |
|
4762 { |
|
4763 // iReceiveMessage should not be around in this context. |
|
4764 // To avoid possible memory leaks, we clean it away anyway |
|
4765 delete iReceiveMessage; |
|
4766 iReceiveMessage = NULL; |
|
4767 iReceiveMessage = CMmsReceiveMessage::NewL( iFs, iMmsSettings ); |
|
4768 |
|
4769 iReceiveMessage->Failed().AppendL( iMsvSelection->Back( 0 ), count ); |
|
4770 iReceiveMessage->Received().SetReserveL( count ); |
|
4771 |
|
4772 while ( count-- ) |
|
4773 { |
|
4774 if ( iServerEntry->SetEntry( iMsvSelection->At( count ) ) == KErrNone ) |
|
4775 { |
|
4776 entry = iServerEntry->Entry(); |
|
4777 if ( entry.SendingState() == KMsvSendStateSent ) |
|
4778 { |
|
4779 // successful entry, delete it |
|
4780 // This will not fail |
|
4781 // Read reports are never marked as "sent" so they should not |
|
4782 // disturb the logic here |
|
4783 if ( iReceiveMessage->Failed().Count() > count ) |
|
4784 { |
|
4785 iReceiveMessage->Received().AppendL( |
|
4786 iReceiveMessage->Failed().At( count ) ); |
|
4787 iReceiveMessage->Failed().Delete( count ); |
|
4788 } |
|
4789 } |
|
4790 else if ( ( ( entry.SendingState() == KMsvSendStateWaiting ) || |
|
4791 ( entry.SendingState() == KMsvSendStateSending ) ) ) |
|
4792 { |
|
4793 if ( paramPack().iReasonFlags & ( KMmsReasonHotswap | KMmsReasonBackupEnded ) ) |
|
4794 { |
|
4795 // These will be rescheduled only if they were accessed the last time |
|
4796 // before the media unavailable event. |
|
4797 // Otherwise they might be a new operation. |
|
4798 #ifndef _NO_MMSS_LOGGING_ |
|
4799 TMmsLogger::Log( _L("- hotswap or backup trigger")); |
|
4800 #endif |
|
4801 if ( entry.iDate > paramPack().iMediaUnavailableTime ) |
|
4802 { |
|
4803 iReceiveMessage->Failed().Delete( count ); |
|
4804 } |
|
4805 } |
|
4806 } |
|
4807 else if ( entry.iError == KErrNone && entry.iMtmData2 & KMmsNotifyResponseSent ) |
|
4808 { |
|
4809 // If this is legally deferred, it will not be rescheduled |
|
4810 CMsvStore* store = iServerEntry->ReadStoreL(); |
|
4811 CleanupStack::PushL( store ); |
|
4812 iMmsHeaders->RestoreL( *store ); |
|
4813 CleanupStack::PopAndDestroy( store ); |
|
4814 if ( iMmsHeaders->Status() == KMmsMessageStatusDeferred ) |
|
4815 { |
|
4816 // this has been deferred legally - do not reschedule |
|
4817 iReceiveMessage->Failed().Delete( count ); |
|
4818 } |
|
4819 } |
|
4820 else |
|
4821 { |
|
4822 // Keep LINT happy |
|
4823 } |
|
4824 } |
|
4825 // Here could be a branch that prevents automatic sending of |
|
4826 // messages that have been suspended by user. However, user can suspend |
|
4827 // fetching only in manual mode, and then the notifications are in inbox |
|
4828 } |
|
4829 // Check notifications will remove expired notifications |
|
4830 if ( iReceiveMessage->Failed().Count() > 0 ) |
|
4831 { |
|
4832 // only check if there was anything left |
|
4833 CheckNotificationsL( iReceiveMessage->Failed() ); |
|
4834 } |
|
4835 iCommand = EMmsReceive; |
|
4836 MakeDatesIdenticalL( iReceiveMessage->Failed(), KMmsGarbageCollectionDelay ); |
|
4837 TRAP( err, UpdateEntriesL() ); |
|
4838 err = KErrNone; // we don't care about the error, we just do our best |
|
4839 } |
|
4840 } |
|
4841 |
|
4842 // --------------------------------------------------------- |
|
4843 // CMmsServerMtm::GcMmsFolderNotificationsL |
|
4844 // |
|
4845 // --------------------------------------------------------- |
|
4846 // |
|
4847 void CMmsServerMtm::GcInboxNotifications() |
|
4848 { |
|
4849 #ifndef _NO_MMSS_LOGGING_ |
|
4850 TMmsLogger::Log( _L("CMmsServerMtm::GcInboxNotifications") ); |
|
4851 #endif |
|
4852 // |
|
4853 // MMS watcher sends us reason codes with garbage collection parameters. |
|
4854 // paramPack().iReasonFlags will contain the reason flags. |
|
4855 // paramPack().iMediaUnavailableTime tells when the memory card was removed |
|
4856 // |
|
4857 TMMSGarbageCollectionParameters param; |
|
4858 TPckgC<TMMSGarbageCollectionParameters> paramPack( param ); |
|
4859 paramPack.Set( iParameter ); |
|
4860 |
|
4861 TMsvEntry entry; |
|
4862 |
|
4863 TInt err = iServerEntry->SetEntry( KMsvGlobalInBoxIndexEntryId ); |
|
4864 iMsvSelection->Reset(); |
|
4865 if ( err == KErrNone ) |
|
4866 { |
|
4867 err = iServerEntry->GetChildrenWithMtm( KUidMsgMMSNotification, *iMsvSelection ); |
|
4868 } |
|
4869 TInt count = iMsvSelection->Count(); |
|
4870 #ifndef _NO_MMSS_LOGGING_ |
|
4871 TMmsLogger::Log( _L(" - found %d notifications in inbox"), iMsvSelection->Count() ); |
|
4872 #endif |
|
4873 TInt i; |
|
4874 if ( err == KErrNone && count > 0 ) |
|
4875 { |
|
4876 for ( i = 0; i < count; i++ ) |
|
4877 { |
|
4878 if ( iServerEntry->SetEntry( iMsvSelection->At( i ) ) == KErrNone ) |
|
4879 { |
|
4880 entry = iServerEntry->Entry(); |
|
4881 |
|
4882 // |
|
4883 // If booting and notif is not allowed to start a new operation -> something wrong |
|
4884 // |
|
4885 if( ( paramPack().iReasonFlags & ( KMmsReasonBoot ) ) && |
|
4886 ( entry.iMtmData2 & KMmsNewOperationForbidden ) ) |
|
4887 { |
|
4888 entry.iError = KMmsGeneralError; |
|
4889 CMmsBaseOperation::MarkNotificationOperationFailed( entry ); |
|
4890 entry.SetReadOnly( ETrue ); |
|
4891 entry.iMtmData2 &= ~KMmsOperationIdentifier; |
|
4892 iServerEntry->ChangeEntry( entry ); |
|
4893 } |
|
4894 } |
|
4895 |
|
4896 } |
|
4897 } |
|
4898 } |
|
4899 |
|
4900 // --------------------------------------------------------- |
|
4901 // CMmsServerMtm::GcOutBoxNotificationsL |
|
4902 // |
|
4903 // --------------------------------------------------------- |
|
4904 // |
|
4905 void CMmsServerMtm::GcOutBoxNotificationsL() |
|
4906 { |
|
4907 #ifndef _NO_MMSS_LOGGING_ |
|
4908 TMmsLogger::Log( _L("CMmsServerMtm::GcOutBoxNotificationsL") ); |
|
4909 #endif |
|
4910 // |
|
4911 // MMS watcher sends us reason codes with garbage collection parameters. |
|
4912 // paramPack().iReasonFlags will contain the reason flags. |
|
4913 // paramPack().iMediaUnavailableTime tells when the memory card was removed |
|
4914 // |
|
4915 TMMSGarbageCollectionParameters param; |
|
4916 TPckgC<TMMSGarbageCollectionParameters> paramPack( param ); |
|
4917 paramPack.Set( iParameter ); |
|
4918 |
|
4919 // |
|
4920 // Get selection of notifications from Outbox |
|
4921 // |
|
4922 TInt err = iServerEntry->SetEntry( KMsvGlobalOutBoxIndexEntryId ); |
|
4923 iMsvSelection->Reset(); |
|
4924 if ( err == KErrNone ) |
|
4925 { |
|
4926 err = iServerEntry->GetChildrenWithMtm( KUidMsgMMSNotification, *iMsvSelection ); |
|
4927 } |
|
4928 TInt count = iMsvSelection->Count(); |
|
4929 #ifndef _NO_MMSS_LOGGING_ |
|
4930 TMmsLogger::Log( _L("- found %d notification entries from Outbox"), count ); |
|
4931 #endif |
|
4932 if( err != KErrNone || count <= 0 ) |
|
4933 { |
|
4934 #ifndef _NO_MMSS_LOGGING_ |
|
4935 TMmsLogger::Log( _L("- no entries to clean up"), count ); |
|
4936 #endif |
|
4937 return; |
|
4938 } |
|
4939 |
|
4940 // |
|
4941 // Creating iForwardOperation that will handle resends |
|
4942 // |
|
4943 delete iForwardOperation; |
|
4944 iForwardOperation = NULL; |
|
4945 iForwardOperation = CMmsForwardOperation::NewL( iFs, iMmsSettings ); |
|
4946 iForwardOperation->Failed().AppendL( iMsvSelection->Back( 0 ), count ); |
|
4947 |
|
4948 CMsvEntrySelection* selection = new( ELeave ) CMsvEntrySelection; |
|
4949 CleanupStack::PushL( selection ); |
|
4950 |
|
4951 // |
|
4952 // Loop through the found notifications (forward entries) |
|
4953 // |
|
4954 while( count-- ) |
|
4955 { |
|
4956 // |
|
4957 // The detailed handling depends both on the state of the entry |
|
4958 // and the event that triggered the garbage collection. |
|
4959 // |
|
4960 TMsvEntry tEntry; |
|
4961 err = iServerEntry->SetEntry( iMsvSelection->At( count ) ); |
|
4962 if( err != KErrNone ) |
|
4963 { |
|
4964 // If entry not accessible, start a new round |
|
4965 continue; |
|
4966 } |
|
4967 tEntry = iServerEntry->Entry(); |
|
4968 selection->Reset(); |
|
4969 selection->AppendL( iMsvSelection->At( count ) ); |
|
4970 |
|
4971 // |
|
4972 // Switch through based on notification entry's state |
|
4973 // |
|
4974 switch ( tEntry.SendingState() ) |
|
4975 { |
|
4976 case KMsvSendStateSuspended: |
|
4977 #ifndef _NO_MMSS_LOGGING_ |
|
4978 TMmsLogger::Log( _L("- KMsvSendStateSuspended")); |
|
4979 #endif |
|
4980 if( tEntry.iError == KMmsErrorOfflineMode ) |
|
4981 { |
|
4982 #ifndef _NO_MMSS_LOGGING_ |
|
4983 TMmsLogger::Log( _L("- entry error == offline")); |
|
4984 #endif |
|
4985 if( paramPack().iReasonFlags & KMmsReasonNetworkAllowed ) |
|
4986 { |
|
4987 #ifndef _NO_MMSS_LOGGING_ |
|
4988 TMmsLogger::Log( _L("- GCreason == back-from-offline: rescheduling entry")); |
|
4989 #endif |
|
4990 // Reschedule entry |
|
4991 // i.e. nothing done here |
|
4992 } |
|
4993 else // GC reason is not "back from offline" |
|
4994 { |
|
4995 #ifndef _NO_MMSS_LOGGING_ |
|
4996 TMmsLogger::Log( _L("- GCreason != back-from-offline: leaving entry suspended")); |
|
4997 #endif |
|
4998 // Leave entry suspended (applies to both entry types) |
|
4999 // i.e. take entryId out from to-be-scheduled list |
|
5000 iForwardOperation->Failed().Delete( count ); |
|
5001 } |
|
5002 } |
|
5003 else // entry.iError not equal to KMmsErrorOfflineMode |
|
5004 { |
|
5005 #ifndef _NO_MMSS_LOGGING_ |
|
5006 TMmsLogger::Log( _L("- entry error != offline, set forward entry as Failed") ); |
|
5007 #endif |
|
5008 // Set forward entry's send-state to failed |
|
5009 tEntry.SetFailed( ETrue ); |
|
5010 |
|
5011 // Clear related notification from Inbox: |
|
5012 // Get the related notification id |
|
5013 CMsvStore* store = NULL; |
|
5014 store = iServerEntry->EditStoreL(); |
|
5015 CleanupStack::PushL( store ); // *** |
|
5016 iMmsHeaders->RestoreL( *store ); |
|
5017 CleanupStack::PopAndDestroy( store ); |
|
5018 TMsvId relatedEntryId = iMmsHeaders->RelatedEntry(); |
|
5019 iMmsHeaders->Reset(); // headers not needed any more |
|
5020 |
|
5021 if( relatedEntryId != KMsvNullIndexEntryId ) |
|
5022 { |
|
5023 #ifndef _NO_MMSS_LOGGING_ |
|
5024 TMmsLogger::Log( _L("- related notification-entry exists, clearing it") ); |
|
5025 #endif |
|
5026 // Set context (iServerEntry and entry) to notification and clear it |
|
5027 err = iServerEntry->SetEntry( relatedEntryId ); |
|
5028 #ifndef _NO_MMSS_LOGGING_ |
|
5029 if( err != KErrNone ) |
|
5030 { |
|
5031 TMmsLogger::Log( _L("- ERROR: Could not set entry") ); |
|
5032 } |
|
5033 #endif |
|
5034 if ( err == KErrNone ) |
|
5035 { |
|
5036 tEntry = iServerEntry->Entry(); |
|
5037 tEntry.iMtmData2 &= ~KMmsNewOperationForbidden; // not forbidden |
|
5038 tEntry.iMtmData2 &= ~KMmsOperationOngoing; // not ongoing |
|
5039 tEntry.iMtmData2 |= KMmsOperationFinished; // finished |
|
5040 tEntry.iMtmData2 |= KMmsOperationResult; // NOK |
|
5041 tEntry.SetReadOnly( ETrue ); |
|
5042 err = iServerEntry->ChangeEntry( tEntry ); |
|
5043 } |
|
5044 #ifndef _NO_MMSS_LOGGING_ |
|
5045 if( err != KErrNone ) |
|
5046 { |
|
5047 TMmsLogger::Log( _L("- ERROR: Could not change related entry") ); |
|
5048 } |
|
5049 TMmsLogger::Log( _L("- Clear the related-entry link itself") ); |
|
5050 #endif |
|
5051 |
|
5052 // Clear related-id link from forward entry |
|
5053 err = iServerEntry->SetEntry( iMsvSelection->At( count ) ); |
|
5054 if ( err == KErrNone ) |
|
5055 { |
|
5056 store = iServerEntry->EditStoreL(); |
|
5057 CleanupStack::PushL( store ); // *** |
|
5058 iMmsHeaders->RestoreL( *store ); |
|
5059 iMmsHeaders->SetRelatedEntry( KMsvNullIndexEntryId ); |
|
5060 iMmsHeaders->StoreL( *store ); |
|
5061 store->CommitL(); |
|
5062 CleanupStack::PopAndDestroy( store ); |
|
5063 } |
|
5064 iMmsHeaders->Reset(); // headers not needed any more |
|
5065 #ifndef _NO_MMSS_LOGGING_ |
|
5066 TMmsLogger::Log( _L("- Related-entry and the link cleared") ); |
|
5067 #endif |
|
5068 } |
|
5069 |
|
5070 // Clean up. |
|
5071 // iServerEntry will be needed and set next time |
|
5072 // at the start of this loop. |
|
5073 iServerEntry->SetEntry( KMsvNullIndexEntryId ); |
|
5074 |
|
5075 // Leave entry suspended (applies to both entry types) |
|
5076 // i.e. take entryId out from to-be-scheduled list |
|
5077 #ifndef _NO_MMSS_LOGGING_ |
|
5078 TMmsLogger::Log( _L("- not scheduling entry") ); |
|
5079 #endif |
|
5080 iForwardOperation->Failed().Delete( count ); |
|
5081 } |
|
5082 break; |
|
5083 default: |
|
5084 #ifndef _NO_MMSS_LOGGING_ |
|
5085 TMmsLogger::Log( _L("- Forward entry's sendState == %d, not scheduling"), tEntry.SendingState() ); |
|
5086 #endif |
|
5087 iForwardOperation->Failed().Delete( count ); |
|
5088 break; |
|
5089 } |
|
5090 } // while loop |
|
5091 |
|
5092 CleanupStack::PopAndDestroy( selection ); |
|
5093 iCommand = EMmsForward; |
|
5094 // whatever was left gets rescheduled |
|
5095 MakeDatesIdenticalL( iForwardOperation->Failed(), KMmsGarbageCollectionDelay ); |
|
5096 TRAP( err, UpdateEntriesL() ); |
|
5097 #ifndef _NO_MMSS_LOGGING_ |
|
5098 if( err != KErrNone ) |
|
5099 { |
|
5100 TMmsLogger::Log( _L("- UpdateEntriesL failed with code %d"), err ); |
|
5101 } |
|
5102 #endif |
|
5103 } |
|
5104 |
|
5105 // --------------------------------------------------------- |
|
5106 // CMmsServerMtm::GcMmboxFolderNotifications |
|
5107 // |
|
5108 // --------------------------------------------------------- |
|
5109 // |
|
5110 void CMmsServerMtm::GcMmboxFolderNotifications() |
|
5111 { |
|
5112 #ifndef _NO_MMSS_LOGGING_ |
|
5113 TMmsLogger::Log( _L("CMmsServerMtm::GcMmboxFolderNotifications") ); |
|
5114 #endif |
|
5115 |
|
5116 TMsvId mmboxFolder = iMmsSettings->MMBoxFolder(); |
|
5117 // if mmbox folder is not found, no need to check notifications from there. |
|
5118 if ( mmboxFolder == KMsvNullIndexEntryId ) |
|
5119 { |
|
5120 return; |
|
5121 } |
|
5122 |
|
5123 TInt error = iServerEntry->SetEntry( mmboxFolder ); |
|
5124 iMsvSelection->Reset(); |
|
5125 if ( error == KErrNone ) |
|
5126 { |
|
5127 error = iServerEntry->GetChildrenWithMtm( KUidMsgMMSNotification, *iMsvSelection ); |
|
5128 } |
|
5129 TInt count = iMsvSelection->Count(); |
|
5130 #ifndef _NO_MMSS_LOGGING_ |
|
5131 TMmsLogger::Log( _L(" - mmbox folder contains %d notifications"), count ); |
|
5132 #endif |
|
5133 if ( error == KErrNone && count > 0 ) |
|
5134 { |
|
5135 |
|
5136 for ( TInt i=0; i < count; i++ ) |
|
5137 { |
|
5138 if ( iServerEntry->SetEntry( iMsvSelection->At( i ) ) == KErrNone ) |
|
5139 { |
|
5140 TMsvEntry entry = iServerEntry->Entry(); |
|
5141 |
|
5142 // If forbidden flag is on, mark as failed. |
|
5143 if( entry.iMtmData2 & KMmsNewOperationForbidden ) |
|
5144 { |
|
5145 entry.iError = KMmsGeneralError; |
|
5146 entry.SetSendingState( KMsvSendStateSuspended ); |
|
5147 CMmsBaseOperation::MarkNotificationOperationFailed( entry ); |
|
5148 entry.SetReadOnly( ETrue ); |
|
5149 entry.iMtmData2 &= ~KMmsOperationIdentifier; |
|
5150 iServerEntry->ChangeEntry( entry ); |
|
5151 } |
|
5152 } |
|
5153 } |
|
5154 } |
|
5155 iServerEntry->SetEntry( KMsvNullIndexEntryId ); |
|
5156 } |
|
5157 |
|
5158 // --------------------------------------------------------- |
|
5159 // CMmsServerMtm::FindDuplicateNotificationL |
|
5160 // |
|
5161 // --------------------------------------------------------- |
|
5162 // |
|
5163 TInt CMmsServerMtm::FindDuplicateNotificationL( |
|
5164 TMsvId aParent, CMmsHeaders& aHeaders, TMsvId& aDuplicate ) |
|
5165 { |
|
5166 #ifndef _NO_MMSS_LOGGING_ |
|
5167 TMmsLogger::Log( _L("CMmsServerMtm::FindDuplicateNotificationL") ); |
|
5168 #endif |
|
5169 |
|
5170 aDuplicate = KMsvNullIndexEntryId; |
|
5171 |
|
5172 if ( aParent == KMsvNullIndexEntryId ) |
|
5173 { |
|
5174 return KErrNotSupported; |
|
5175 } |
|
5176 |
|
5177 TInt error = iServerEntry->SetEntry( aParent ); |
|
5178 if ( error != KErrNone ) |
|
5179 { |
|
5180 iServerEntry->SetEntry( KMsvNullIndexEntryId ); |
|
5181 return error; |
|
5182 } |
|
5183 |
|
5184 CMsvEntrySelection* selection = new ( ELeave ) CMsvEntrySelection; |
|
5185 CleanupStack::PushL( selection ); |
|
5186 |
|
5187 error = iServerEntry->GetChildrenWithMtm( KUidMsgMMSNotification, *selection ); |
|
5188 |
|
5189 TInt count = selection->Count(); |
|
5190 if ( count == 0 ) |
|
5191 { |
|
5192 error = KErrNotSupported; |
|
5193 } |
|
5194 |
|
5195 if ( error != KErrNone ) |
|
5196 { |
|
5197 CleanupStack::PopAndDestroy( selection ); |
|
5198 iServerEntry->SetEntry( KMsvNullIndexEntryId ); |
|
5199 return error; |
|
5200 } |
|
5201 |
|
5202 CMmsHeaders* mmsHeaders = CMmsHeaders::NewL( iMmsSettings->MmsVersion() ); |
|
5203 CleanupStack::PushL( mmsHeaders ); |
|
5204 |
|
5205 for ( TInt i = count; i > 0 && ( aDuplicate == KMsvNullIndexEntryId ); i-- ) |
|
5206 { |
|
5207 error = iServerEntry->SetEntry( selection->At( i - 1 ) ); |
|
5208 if ( error == KErrNone ) |
|
5209 { |
|
5210 CMsvStore* store = iServerEntry->ReadStoreL(); |
|
5211 CleanupStack::PushL( store ); |
|
5212 mmsHeaders->RestoreL( *store ); |
|
5213 CleanupStack::PopAndDestroy( store ); |
|
5214 |
|
5215 // content location must match |
|
5216 if ( mmsHeaders->ContentLocation().Compare( aHeaders.ContentLocation() ) == 0 ) |
|
5217 { |
|
5218 // Identical. This probably means that we have not sent a response yet, |
|
5219 // and MMSC has sent us a new notification. |
|
5220 |
|
5221 #ifndef _NO_MMSS_LOGGING_ |
|
5222 TMmsLogger::Log( _L("- content locations match") ); |
|
5223 #endif |
|
5224 TMsvEntry entry = iServerEntry->Entry(); |
|
5225 aDuplicate = entry.Id(); |
|
5226 } |
|
5227 |
|
5228 } |
|
5229 |
|
5230 } |
|
5231 |
|
5232 CleanupStack::PopAndDestroy( mmsHeaders ); |
|
5233 CleanupStack::PopAndDestroy( selection ); |
|
5234 iServerEntry->SetEntry( KMsvNullIndexEntryId ); |
|
5235 |
|
5236 return error; |
|
5237 } |
|
5238 |
|
5239 // --------------------------------------------------------- |
|
5240 // CMmsServerMtm::SendReadReportL |
|
5241 // |
|
5242 // --------------------------------------------------------- |
|
5243 // |
|
5244 void CMmsServerMtm::SendReadReportL() |
|
5245 { |
|
5246 if ( iMsvSelection->Count() > 0 ) |
|
5247 { |
|
5248 delete iReadReport; |
|
5249 iReadReport = NULL; |
|
5250 iReadReport = CMmsReadReport::NewL( iFs, iMmsSettings ); |
|
5251 |
|
5252 iReadReport->StartL( *iMsvSelection, *iServerEntry, |
|
5253 iServiceEntryId, iStatus ); |
|
5254 *iRequestStatus = KRequestPending; |
|
5255 SetActive(); |
|
5256 } |
|
5257 else |
|
5258 { |
|
5259 *iRequestStatus = KRequestPending; |
|
5260 User::RequestComplete( iRequestStatus, KErrNotFound ); |
|
5261 } |
|
5262 } |
|
5263 |
|
5264 // --------------------------------------------------------- |
|
5265 // |
|
5266 // --------------------------------------------------------- |
|
5267 // |
|
5268 void CMmsServerMtm::LogCommandCode( TInt aCommand ) |
|
5269 { |
|
5270 #ifndef _NO_MMSS_LOGGING_ |
|
5271 switch ( aCommand ) |
|
5272 { |
|
5273 case EMmsSend: |
|
5274 TMmsLogger::Log( _L(" - Send") ); |
|
5275 break; |
|
5276 case EMmsReceive: |
|
5277 TMmsLogger::Log( _L(" - Receive") ); |
|
5278 break; |
|
5279 case EMmsScheduledSend: |
|
5280 TMmsLogger::Log( _L(" - Scheduled send") ); |
|
5281 break; |
|
5282 case EMmsScheduledReceive: |
|
5283 TMmsLogger::Log( _L(" - Scheduled fetch") ); |
|
5284 break; |
|
5285 case EMmsDeleteSchedule: |
|
5286 TMmsLogger::Log( _L(" - Delete schedule") ); |
|
5287 break; |
|
5288 case EMmsDecodePushedMessage: |
|
5289 TMmsLogger::Log( _L(" - Decode pushed message") ); |
|
5290 break; |
|
5291 case EMmsLogDeliveryReport: |
|
5292 TMmsLogger::Log( _L(" - Log delivery report") ); |
|
5293 break; |
|
5294 case EMmsDeleteEntries: |
|
5295 TMmsLogger::Log( _L(" - Delete entries") ); |
|
5296 break; |
|
5297 case EMmsReceiveForced: |
|
5298 TMmsLogger::Log( _L(" - Receive forced") ); |
|
5299 break; |
|
5300 case EMmsScheduledReceiveForced: |
|
5301 TMmsLogger::Log( _L(" - Scheduled receive forced") ); |
|
5302 break; |
|
5303 case EMmsGarbageCollection: |
|
5304 TMmsLogger::Log( _L(" - Garbage collection") ); |
|
5305 break; |
|
5306 case EMmsDeleteExpiredNotifications: |
|
5307 TMmsLogger::Log( _L(" - Delete expired notifications") ); |
|
5308 break; |
|
5309 case EMmsRetryServiceLoading: |
|
5310 TMmsLogger::Log( _L(" - Retry because service loading failed!") ); |
|
5311 break; |
|
5312 case EMmsMessageGeneration: |
|
5313 TMmsLogger::Log( _L(" - Message generation") ); |
|
5314 break; |
|
5315 case EMmsForward: |
|
5316 TMmsLogger::Log( _L(" - EMmsForward") ); |
|
5317 break; |
|
5318 case EMmsScheduledForward: |
|
5319 TMmsLogger::Log( _L(" - EMmsScheduledForward") ); |
|
5320 break; |
|
5321 case EMmsNotificationDelete: |
|
5322 TMmsLogger::Log( _L(" - EMmsNotificationDelete") ); |
|
5323 break; |
|
5324 case EMmsScheduledNotificationDelete: |
|
5325 TMmsLogger::Log( _L(" - EMmsScheduledNotificationDelete") ); |
|
5326 break; |
|
5327 case EMmsUpdateMmboxList: |
|
5328 TMmsLogger::Log( _L(" - EMmsUpdateMmboxList") ); |
|
5329 break; |
|
5330 case EMmsSendReadReport: |
|
5331 TMmsLogger::Log( _L(" - EMmsSendReadReport") ); |
|
5332 break; |
|
5333 case EMmsScheduledReadReport: |
|
5334 TMmsLogger::Log( _L(" - EMmsScheduledReadReport") ); |
|
5335 break; |
|
5336 default: |
|
5337 TMmsLogger::Log( _L(" - Unknown command") ); |
|
5338 break; |
|
5339 } |
|
5340 TMemoryInfoV1Buf memory; |
|
5341 UserHal::MemoryInfo( memory ); |
|
5342 TInt available = memory().iFreeRamInBytes; |
|
5343 TMmsLogger::Log(_L("Free memory %d"), available ); |
|
5344 #endif // _NO_MMSS_LOGGING_ |
|
5345 } |
|
5346 |
|
5347 // --------------------------------------------------------- |
|
5348 // |
|
5349 // --------------------------------------------------------- |
|
5350 // |
|
5351 void CMmsServerMtm::GetRealServiceId( CMsvEntrySelection& aSelection ) |
|
5352 { |
|
5353 TInt error = KErrNone; |
|
5354 TMsvId messageEntryId = KMsvNullIndexEntryId; |
|
5355 // the function cannot be called without a selection so the selection |
|
5356 // array always has at least one item. |
|
5357 if ( aSelection.Count() > 0 && aSelection.At( 0 ) != KMsvLocalServiceIndexEntryId ) |
|
5358 { |
|
5359 messageEntryId = aSelection.At( 0 ); |
|
5360 } |
|
5361 else if ( aSelection.Count() > 1 ) |
|
5362 { |
|
5363 messageEntryId = aSelection.At( 1 ); |
|
5364 } |
|
5365 else |
|
5366 { |
|
5367 // We never get here. This is just a safety valve. |
|
5368 error = KErrNotFound; |
|
5369 } |
|
5370 |
|
5371 // if only a service entry in selection list, |
|
5372 // nothing can be done. If we have only service entry, |
|
5373 // and that is not ours, we won't get here anyway. |
|
5374 |
|
5375 if ( messageEntryId != KMsvNullIndexEntryId ) |
|
5376 { |
|
5377 error = iServerEntry->SetEntry( messageEntryId ); |
|
5378 } |
|
5379 if ( error == KErrNone ) |
|
5380 { |
|
5381 if ( iServerEntry->Entry().iServiceId == KMsvLocalServiceIndexEntryId && |
|
5382 iServerEntry->Entry().iRelatedId != KMsvNullIndexEntryId ) |
|
5383 // This is our actual service. |
|
5384 { |
|
5385 iServiceEntryId = iServerEntry->Entry().iRelatedId; |
|
5386 } |
|
5387 } |
|
5388 } |
|
5389 |
|
5390 // --------------------------------------------------------- |
|
5391 // |
|
5392 // --------------------------------------------------------- |
|
5393 // |
|
5394 void CMmsServerMtm::HandleLoadServiceError( TInt aError ) |
|
5395 { |
|
5396 if ( iCommand == EMmsDecodePushedMessage ) |
|
5397 { |
|
5398 // We must delete the dummy entry given to us, |
|
5399 // otherwise nobody will delete it. |
|
5400 |
|
5401 if ( iMsvSelection->Count() > 0 && iMsvSelection->At( 0 ) == iServiceEntryId ) |
|
5402 { |
|
5403 iMsvSelection->Delete( 0 ); |
|
5404 } |
|
5405 if ( iMsvSelection->Count() > 0 ) |
|
5406 { |
|
5407 if ( iServerEntry->SetEntry( iMsvSelection->At( 0 ) ) == KErrNone ) |
|
5408 { |
|
5409 if ( iServerEntry->SetEntry( iServerEntry->Entry().Parent() ) == KErrNone ) |
|
5410 { |
|
5411 iServerEntry->DeleteEntries( *iMsvSelection ); |
|
5412 } |
|
5413 } |
|
5414 } |
|
5415 iServerEntry->SetEntry( KMsvNullIndexEntryId ); |
|
5416 |
|
5417 // If we are trying to decode a notification from WAP stack |
|
5418 // return error to caller, not to ourselves |
|
5419 *iRequestStatus = KRequestPending; |
|
5420 User::RequestComplete( iRequestStatus, aError ); |
|
5421 return; |
|
5422 } |
|
5423 |
|
5424 if ( aError == KErrNotFound || aError == KErrNoMemory ) |
|
5425 { |
|
5426 // This is a hopeless case. |
|
5427 // It could lead to endless loop. |
|
5428 *iRequestStatus = KRequestPending; |
|
5429 User::RequestComplete( iRequestStatus, aError ); |
|
5430 return; |
|
5431 } |
|
5432 |
|
5433 // We only have to help client mtm when it is trying to start automatic |
|
5434 // fetch after changing fetch mode from "deferred" to "on" |
|
5435 if ( iCurrentCommand == EMmsScheduledReceive || |
|
5436 iCurrentCommand == EMmsScheduledReceiveForced ) |
|
5437 { |
|
5438 iCurrentCommand = EMmsRetryServiceLoading; |
|
5439 TRequestStatus* status = &iStatus; |
|
5440 // caller should be in pending state, too. |
|
5441 *iRequestStatus = KRequestPending; |
|
5442 iStatus = KRequestPending; |
|
5443 SetActive(); |
|
5444 User::RequestComplete( status, aError ); |
|
5445 return; |
|
5446 } |
|
5447 else |
|
5448 { |
|
5449 *iRequestStatus = KRequestPending; |
|
5450 User::RequestComplete( iRequestStatus, aError ); |
|
5451 return; |
|
5452 } |
|
5453 } |
|
5454 |
|
5455 // --------------------------------------------------------- |
|
5456 // |
|
5457 // --------------------------------------------------------- |
|
5458 // |
|
5459 void CMmsServerMtm::LogEntryParent() |
|
5460 { |
|
5461 #ifndef _NO_MMSS_LOGGING_ |
|
5462 TMsvId msgEntryId = KMsvNullIndexEntryId; |
|
5463 TInt error = KErrNone; |
|
5464 if ( iMsvSelection->Count() > 0 ) |
|
5465 { |
|
5466 msgEntryId = iMsvSelection->At( 0 ); |
|
5467 error = iServerEntry->SetEntry( msgEntryId ); |
|
5468 if ( error == KErrNone ) |
|
5469 { |
|
5470 if ( iServerEntry->Entry().Parent() == KMsvGlobalOutBoxIndexEntryId ) |
|
5471 { |
|
5472 TMmsLogger::Log( _L("- EntryParent: Outbox") ); |
|
5473 } |
|
5474 else |
|
5475 { |
|
5476 TMmsLogger::Log( _L("- EntryParent: 0x%08X"), iServerEntry->Entry().Parent() ); |
|
5477 } |
|
5478 } |
|
5479 } |
|
5480 // free whatever entry we are holding |
|
5481 iServerEntry->SetEntry( KMsvNullIndexEntryId ); |
|
5482 #endif |
|
5483 } |
|
5484 |
|
5485 // --------------------------------------------------------- |
|
5486 // |
|
5487 // --------------------------------------------------------- |
|
5488 // |
|
5489 void CMmsServerMtm::RestoreVisibilityAndService() |
|
5490 { |
|
5491 TInt error = KErrNone; |
|
5492 TInt i = 0; |
|
5493 TMsvEntry entry; |
|
5494 |
|
5495 // Make sure that the entries are visible. |
|
5496 // If they are "in preparation" that's the caller's problem |
|
5497 |
|
5498 for ( i = 0; i < iMsvSelection->Count(); i++ ) |
|
5499 { |
|
5500 error = iServerEntry->SetEntry( iMsvSelection->At( 0 ) ); |
|
5501 if ( error == KErrNone ) |
|
5502 { |
|
5503 entry = iServerEntry->Entry(); |
|
5504 if ( entry.Visible() == EFalse && iCurrentCommand != EMmsDeleteSchedule ) |
|
5505 { |
|
5506 entry.SetVisible( ETrue ); |
|
5507 // if this fails we cannot help... |
|
5508 iServerEntry->ChangeEntry( entry ); |
|
5509 } |
|
5510 if ( iCurrentCommand == EMmsDeleteSchedule && |
|
5511 entry.iServiceId == KMsvLocalServiceIndexEntryId && |
|
5512 entry.iRelatedId != KMsvNullIndexEntryId) |
|
5513 { |
|
5514 // restore the correct service id |
|
5515 entry.iServiceId = entry.iRelatedId; |
|
5516 entry.iRelatedId = KMsvNullIndexEntryId; |
|
5517 // if this fails we cannot help... |
|
5518 iServerEntry->ChangeEntry( entry ); |
|
5519 } |
|
5520 } |
|
5521 } |
|
5522 |
|
5523 // free the entry we are holding |
|
5524 iServerEntry->SetEntry( KMsvNullIndexEntryId ); |
|
5525 } |
|
5526 |
|
5527 // ================= OTHER EXPORTED FUNCTIONS ============== |
|
5528 |
|
5529 #ifndef _NO_MMSS_LOGGING_ |
|
5530 const TInt KLogBufferLength = 256; |
|
5531 _LIT(KLogDir, "mmss"); |
|
5532 _LIT(KLogFile, "mmss.txt"); |
|
5533 |
|
5534 void TMmsLogger::Log(TRefByValue<const TDesC> aFmt,...) |
|
5535 { |
|
5536 VA_LIST list; |
|
5537 VA_START(list, aFmt); |
|
5538 |
|
5539 // Print to log file |
|
5540 TBuf<KLogBufferLength> buf; |
|
5541 buf.FormatList(aFmt, list); |
|
5542 |
|
5543 // Write to log file |
|
5544 RFileLogger::Write(KLogDir, KLogFile, EFileLoggingModeAppend, buf); |
|
5545 } |
|
5546 #endif |
|
5547 |
|
5548 // |
|
5549 // --------------------------------------------------------- |
|
5550 // gPanic implements |
|
5551 // panic function, should be used by debug version only |
|
5552 // |
|
5553 GLDEF_C void gPanic( |
|
5554 TMmsPanic aPanic ) // error number enumerations |
|
5555 { |
|
5556 _LIT( KMmsPanic,"MMS" ); |
|
5557 User::Panic( KMmsPanic, aPanic ); |
|
5558 } |
|
5559 |
|
5560 // End of File |