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