|
1 /* |
|
2 * Copyright (c) 2002-2006 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 * State machine for handling MMS log entries |
|
16 * (sent messages and delivery reports) |
|
17 * |
|
18 */ |
|
19 |
|
20 |
|
21 |
|
22 // INCLUDE FILES |
|
23 #include <badesca.h> |
|
24 #include <msvids.h> |
|
25 #include <logcli.h> |
|
26 #include <logview.h> |
|
27 // common component |
|
28 #include <sysutil.h> |
|
29 #include "LogsApiConsts.h" |
|
30 |
|
31 // MMS specific |
|
32 #include "mmsconst.h" |
|
33 #include "mmslog.h" |
|
34 #include "mmsgenutils.h" |
|
35 #include "mmsservercommon.h" // needed for logging |
|
36 |
|
37 // EXTERNAL DATA STRUCTURES |
|
38 |
|
39 // EXTERNAL FUNCTION PROTOTYPES |
|
40 extern void gPanic(TMmsPanic aPanic); |
|
41 |
|
42 // CONSTANTS |
|
43 _LIT(KMmsLogEventTypeName, "MMS"); |
|
44 |
|
45 // MACROS |
|
46 |
|
47 // LOCAL CONSTANTS AND MACROS |
|
48 |
|
49 // MODULE DATA STRUCTURES |
|
50 |
|
51 // LOCAL FUNCTION PROTOTYPES |
|
52 |
|
53 // ==================== LOCAL FUNCTIONS ==================== |
|
54 |
|
55 // ================= MEMBER FUNCTIONS ======================= |
|
56 |
|
57 // C++ default constructor can NOT contain any code, that |
|
58 // might leave. |
|
59 // |
|
60 CMmsLog::CMmsLog( CLogClient& aLogClient, CLogViewEvent& aLogViewEvent ) |
|
61 :CMsgActive( EPriorityStandard ), |
|
62 iState( EMmsLogIdle ), |
|
63 iError( KErrNone ), |
|
64 iLogClient( aLogClient ), |
|
65 iLogViewEvent( aLogViewEvent ), |
|
66 iLastMatchedLink( KLogNullLink ) |
|
67 { |
|
68 } |
|
69 |
|
70 // Symbian OS default constructor can leave. |
|
71 void CMmsLog::ConstructL( RFs& aFs ) |
|
72 { |
|
73 |
|
74 iFs = aFs; |
|
75 iEntryId = KMsvNullIndexEntryId; |
|
76 iLogUpdatedEvent = CLogEvent::NewL(); |
|
77 iFilterList = new ( ELeave ) CLogFilterList; |
|
78 |
|
79 CActiveScheduler::Add(this); |
|
80 |
|
81 } |
|
82 |
|
83 // Two-phased constructor. |
|
84 CMmsLog* CMmsLog::NewL( CLogClient& aLogClient, CLogViewEvent& aLogViewEvent, RFs& aFs ) |
|
85 { |
|
86 CMmsLog* self = new (ELeave) CMmsLog( aLogClient, aLogViewEvent ); |
|
87 |
|
88 CleanupStack::PushL( self ); |
|
89 self->ConstructL( aFs ); |
|
90 CleanupStack::Pop( self ); |
|
91 |
|
92 return self; |
|
93 } |
|
94 |
|
95 |
|
96 // Destructor |
|
97 CMmsLog::~CMmsLog() |
|
98 { |
|
99 Cancel(); |
|
100 // we don't delete those pointers that the caller owns. |
|
101 if( iFilterList ) |
|
102 { |
|
103 iFilterList->ResetAndDestroy(); |
|
104 delete iFilterList; |
|
105 } |
|
106 delete iLogUpdatedEvent; |
|
107 delete iLogEventType; |
|
108 } |
|
109 |
|
110 // --------------------------------------------------------- |
|
111 // CMmsLog::StartL |
|
112 // |
|
113 // --------------------------------------------------------- |
|
114 // |
|
115 void CMmsLog::StartL( |
|
116 CLogEvent& aLogEvent, |
|
117 CDesCArray& aRemoteParties, |
|
118 TRequestStatus& aStatus) |
|
119 { |
|
120 __ASSERT_DEBUG(iState==EMmsLogIdle,gPanic(EMmsAlreadyBusy)); |
|
121 |
|
122 // We must save this because we are a state machine, |
|
123 // and we keep running around in circles ... |
|
124 iLastMatchedLink = KLogNullLink; |
|
125 iLogEvent = &aLogEvent; |
|
126 iRemoteParties = &aRemoteParties; |
|
127 iCurrentRemoteParty = iRemoteParties->MdcaCount() - 1; |
|
128 if ( iCurrentRemoteParty < 0 ) |
|
129 { |
|
130 // if no entries nothing to do |
|
131 TRequestStatus* status = &aStatus; |
|
132 aStatus = KRequestPending; |
|
133 User::RequestComplete( status, KErrNone ); |
|
134 return; |
|
135 } |
|
136 |
|
137 TTime now; |
|
138 // the dates in log must be in universal time, not local time |
|
139 now.UniversalTime(); |
|
140 if ( iLogEvent->Time().Int64() == 0 ) |
|
141 { |
|
142 iLogEvent->SetTime( now ); |
|
143 } |
|
144 |
|
145 iFilterList->ResetAndDestroy(); // Clear old filters - just in case |
|
146 |
|
147 // try adding event type only once |
|
148 iEventTypeAdded = EFalse; |
|
149 |
|
150 // Unfortunately neither Link nor Data (message id) can be used |
|
151 // in the filter. |
|
152 // We must filter for each remote party and match the id's separately |
|
153 |
|
154 Queue( aStatus ); |
|
155 iStatus=KRequestPending; |
|
156 |
|
157 SetActive(); |
|
158 |
|
159 // Pretend that we called an asynchronous service |
|
160 // in order to get into the state machine loop |
|
161 TRequestStatus* status = &iStatus; |
|
162 User::RequestComplete( status, KErrNone ); |
|
163 |
|
164 } |
|
165 |
|
166 |
|
167 // --------------------------------------------------------- |
|
168 // CMmsLog::GetLink() |
|
169 // Returns the link id which is the same as TMsvId of the |
|
170 // related message |
|
171 // --------------------------------------------------------- |
|
172 // |
|
173 TLogLink CMmsLog::GetLink() |
|
174 { |
|
175 return iLastMatchedLink; |
|
176 } |
|
177 |
|
178 // --------------------------------------------------------- |
|
179 // CMmsLog::RunL() |
|
180 // |
|
181 // --------------------------------------------------------- |
|
182 // |
|
183 void CMmsLog::RunL() |
|
184 // |
|
185 // When the AO is state driven, this form of Run() is very effective |
|
186 // DoRunL() takes the AO through the states, queuing another asynch step as required |
|
187 // if DoRunL() detects the end of the cycle it returns without queuing another cycle. |
|
188 // |
|
189 // If Run() would exit without queuing another cycle it reports completion to the client. |
|
190 // This is true if the asynch step or DoRunL() fails, or the state cycle is complete |
|
191 // |
|
192 { |
|
193 iError = iStatus.Int(); |
|
194 |
|
195 #ifndef _NO_MMSS_LOGGING_ |
|
196 if ( iError != KErrNone ) |
|
197 { |
|
198 TMmsLogger::Log( _L("CMmsLog RunL iError = %d"), iError); |
|
199 } |
|
200 #endif |
|
201 |
|
202 if ( iError >= KErrNone || |
|
203 ( iError == KErrNotFound && iState == EMmsLogCreatingEntry ) ) |
|
204 { |
|
205 TRAPD( error,DoRunL() ); // continue operations, may re-queue |
|
206 __ASSERT_DEBUG( error==KErrNone || !IsActive(),User::Invariant() ); // must not requeue in error situations |
|
207 if ( IsActive() ) // requeued |
|
208 return; |
|
209 iError = error; |
|
210 } |
|
211 Complete( iError ); |
|
212 } |
|
213 |
|
214 // --------------------------------------------------------- |
|
215 // CMmsLog::DoRunL() |
|
216 // |
|
217 // --------------------------------------------------------- |
|
218 // |
|
219 void CMmsLog::DoRunL() |
|
220 { |
|
221 |
|
222 // This routine takes the state machine through the states |
|
223 // until an error is encountered or the cycle completes. |
|
224 |
|
225 if ( iError != KErrNone && |
|
226 !( iState == EMmsLogCreatingEntry && iError == KErrNotFound |
|
227 && iEventTypeAdded == EFalse ) ) |
|
228 { |
|
229 // We encountered an error, and cannot continue |
|
230 iStatus = iError; |
|
231 iState = EMmsLogIdle; |
|
232 // If we return from DoRunL without becoming active again, |
|
233 // RunL completes. |
|
234 return; |
|
235 } |
|
236 |
|
237 if ( iError == KErrNotFound && iState == EMmsLogCreatingEntry ) |
|
238 { |
|
239 iState = EMmsLogAddingEventType; |
|
240 iError = KErrNone; |
|
241 iEventTypeAdded = ETrue; |
|
242 // CreateEntryL decrements remote party |
|
243 // We get here only if we have tried creating entry and failed |
|
244 // after we have tried adding the event type, we retry |
|
245 // creating log entry |
|
246 iCurrentRemoteParty++; |
|
247 } |
|
248 else |
|
249 { |
|
250 SelectNextState(); |
|
251 } |
|
252 |
|
253 if ( iState != EMmsLogFinal ) |
|
254 { |
|
255 // If appropriate, ChangeState makes us active again |
|
256 ChangeStateL(); |
|
257 // If we return from DoRunL without becoming active again, |
|
258 // RunL completes. |
|
259 } |
|
260 else |
|
261 { |
|
262 iState = EMmsLogIdle; |
|
263 // If we return from DoRunL without becoming active again, |
|
264 // RunL completes. |
|
265 } |
|
266 |
|
267 } |
|
268 |
|
269 // --------------------------------------------------------- |
|
270 // CMmsLog::DoComplete |
|
271 // |
|
272 // --------------------------------------------------------- |
|
273 // |
|
274 void CMmsLog::DoComplete( TInt& /* aStatus */ ) |
|
275 { |
|
276 // We are exiting the loop - we say we are idle now |
|
277 // This is needed when the mms event type does not exist |
|
278 // in the log database. |
|
279 // In that case the entries cannot be logged, and the |
|
280 // state machine exits before reaching the final state. |
|
281 iState = EMmsLogIdle; |
|
282 } |
|
283 |
|
284 // --------------------------------------------------------- |
|
285 // CMmsLog::SelectNextState |
|
286 // |
|
287 // --------------------------------------------------------- |
|
288 // |
|
289 void CMmsLog::SelectNextState() |
|
290 { |
|
291 |
|
292 // If appropriate, the functions called within the switch statement |
|
293 // will make us active again. If all is done, the asynchronous request |
|
294 // will complete |
|
295 |
|
296 switch ( iState ) |
|
297 { |
|
298 case EMmsLogIdle: |
|
299 iState = EMmsLogFiltering; |
|
300 break; |
|
301 case EMmsLogFiltering: |
|
302 if ( iEvents ) |
|
303 { |
|
304 // Check if any of found entries matches our criteria |
|
305 iState = EMmsLogMatchingEntry; |
|
306 #ifndef _NO_MMSS_LOGGING_ |
|
307 TMmsLogger::Log( _L("CMmsLog matching log entry")); |
|
308 #endif |
|
309 } |
|
310 else |
|
311 { |
|
312 iState = EMmsLogCreatingEntry; |
|
313 } |
|
314 break; |
|
315 case EMmsLogMatchingEntry: |
|
316 if ( iEventMatched ) |
|
317 { |
|
318 iState = EMmsLogUpdatingEntry; |
|
319 } |
|
320 else if ( iEvents ) |
|
321 { |
|
322 // Something found from the database |
|
323 // Check if any of found entries matches our criteria |
|
324 iState = EMmsLogMatchingEntry; |
|
325 } |
|
326 else |
|
327 { |
|
328 // no match, create new entry |
|
329 iState = EMmsLogCreatingEntry; |
|
330 } |
|
331 break; |
|
332 case EMmsLogUpdatingEntry: |
|
333 if ( iCurrentRemoteParty >= 0 ) |
|
334 { |
|
335 iState = EMmsLogFiltering; |
|
336 } |
|
337 else |
|
338 { |
|
339 // done |
|
340 iState = EMmsLogFinal; |
|
341 } |
|
342 break; |
|
343 case EMmsLogCreatingEntry: |
|
344 if ( iCurrentRemoteParty >= 0 ) |
|
345 { |
|
346 iState = EMmsLogFiltering; |
|
347 } |
|
348 else |
|
349 { |
|
350 // done |
|
351 iState = EMmsLogFinal; |
|
352 } |
|
353 break; |
|
354 case EMmsLogAddingEventType: |
|
355 iState = EMmsLogCreatingEntry; |
|
356 break; |
|
357 case EMmsLogFinal: |
|
358 break; |
|
359 default: |
|
360 break; |
|
361 } |
|
362 |
|
363 } |
|
364 |
|
365 // --------------------------------------------------------- |
|
366 // CMmsLog::ChangeState |
|
367 // |
|
368 // --------------------------------------------------------- |
|
369 // |
|
370 void CMmsLog::ChangeStateL() |
|
371 { |
|
372 |
|
373 switch ( iState ) |
|
374 { |
|
375 case EMmsLogIdle: |
|
376 break; |
|
377 case EMmsLogFiltering: |
|
378 FilterL(); |
|
379 break; |
|
380 case EMmsLogMatchingEntry: |
|
381 MatchEntryL(); |
|
382 break; |
|
383 case EMmsLogUpdatingEntry: |
|
384 UpdateEntryL(); |
|
385 break; |
|
386 case EMmsLogCreatingEntry: |
|
387 CreateEntryL(); |
|
388 break; |
|
389 case EMmsLogAddingEventType: |
|
390 AddEventTypeL(); |
|
391 break; |
|
392 case EMmsLogFinal: |
|
393 break; |
|
394 default: |
|
395 break; |
|
396 } |
|
397 |
|
398 } |
|
399 |
|
400 // --------------------------------------------------------- |
|
401 // CMmsLog::Filter |
|
402 // |
|
403 // --------------------------------------------------------- |
|
404 // |
|
405 void CMmsLog::FilterL() |
|
406 { |
|
407 |
|
408 iEvents = EFalse; |
|
409 iEventMatched = EFalse; |
|
410 |
|
411 // Try filtering by status |
|
412 // We cannot filter by remote party as it may be either a phone number |
|
413 // or an email address. |
|
414 // The best filter would be message id but it is stored in data field |
|
415 // and events cannot be filtered by data field. |
|
416 |
|
417 // We need to use several statuses depending on what we are doing |
|
418 // - If we are adding an entry in pending state, we only search pending entries |
|
419 // - If we are handling a delivery or read report, we must use all states |
|
420 |
|
421 TLogString logString; |
|
422 iLogClient.GetString( logString, R_LOG_DEL_PENDING ); |
|
423 |
|
424 iFilterList->ResetAndDestroy(); // Clear old filters - just in case |
|
425 |
|
426 CLogFilter* filter = CLogFilter::NewL(); |
|
427 CleanupStack::PushL( filter ); |
|
428 filter->SetEventType( iLogEvent->EventType() ); |
|
429 // We always filter with pending entries |
|
430 iLogClient.GetString( logString, R_LOG_DEL_PENDING ); |
|
431 filter->SetStatus( logString ); |
|
432 iFilterList->AppendL(filter); |
|
433 // Filter is now in the list - popped from cleanup stack |
|
434 CleanupStack::Pop( filter ); |
|
435 #ifndef _NO_MMSS_LOGGING_ |
|
436 TMmsLogger::Log( _L("CMmsLog Filtering with status %S"), &filter->Status() ); |
|
437 #endif |
|
438 filter = NULL; // this is out of our hands now |
|
439 |
|
440 // If we are handling reports, we must filter other statuses, too |
|
441 // logstring was set to pending, and that is the state when |
|
442 // creating new entries after sending. |
|
443 // If we are handling a delivery report or a read report, the status is |
|
444 // R_LOG_DEL_DONE, R_LOG_DEL_FAILED, or KLogsMsgReadText |
|
445 // We don't care about the failed ones. |
|
446 // If the entry has gone into failed state, we create a new one. |
|
447 // That should never happen - no new reports should arrive once something has |
|
448 // been put into failed state. |
|
449 |
|
450 if ( iLogEvent->Status().CompareF( logString ) != 0 ) |
|
451 { |
|
452 // Filter entries that are already in delivered state |
|
453 filter = CLogFilter::NewL(); |
|
454 CleanupStack::PushL( filter ); |
|
455 filter->SetEventType( iLogEvent->EventType() ); |
|
456 iLogClient.GetString( logString, R_LOG_DEL_DONE ); |
|
457 filter->SetStatus( logString ); |
|
458 iFilterList->AppendL(filter); |
|
459 // Filter is now in the list - popped from cleanup stack |
|
460 CleanupStack::Pop( filter ); |
|
461 #ifndef _NO_MMSS_LOGGING_ |
|
462 TMmsLogger::Log( _L("CMmsLog Filtering with status %S"), &filter->Status() ); |
|
463 #endif |
|
464 filter = NULL; // this is out of our hands now |
|
465 |
|
466 // Filter entries in "read" state just to prevent creation of a new one |
|
467 filter = CLogFilter::NewL(); |
|
468 CleanupStack::PushL( filter ); |
|
469 filter->SetEventType( iLogEvent->EventType() ); |
|
470 logString.Copy( KLogsMsgReadText ); |
|
471 filter->SetStatus( logString ); |
|
472 iFilterList->AppendL(filter); |
|
473 // Filter is now in the list - popped from cleanup stack |
|
474 CleanupStack::Pop( filter ); |
|
475 #ifndef _NO_MMSS_LOGGING_ |
|
476 TMmsLogger::Log( _L("CMmsLog Filtering with status %S"), &filter->Status() ); |
|
477 #endif |
|
478 filter = NULL; // this is out of our hands now |
|
479 } |
|
480 |
|
481 #ifndef _NO_MMSS_LOGGING_ |
|
482 if ( iLogEvent->EventType() == KLogMmsEventTypeUid ) |
|
483 { |
|
484 TMmsLogger::Log( _L(" - and event type MMS") ); |
|
485 } |
|
486 else |
|
487 { |
|
488 TMmsLogger::Log( _L("wrong event type %d"), iLogEvent->EventType() ); |
|
489 } |
|
490 #endif |
|
491 |
|
492 iEvents = iLogViewEvent.SetFilterL( *iFilterList, iStatus ); |
|
493 |
|
494 if ( iEvents ) |
|
495 { |
|
496 SetActive(); |
|
497 } |
|
498 else |
|
499 { |
|
500 // If there are no events, CLogViewEvent will not issue an asynchronous request |
|
501 // In that case we must complete ourselves |
|
502 #ifndef _NO_MMSS_LOGGING_ |
|
503 TMmsLogger::Log( _L("CMmsLog found no MMS events in any state searched") ); |
|
504 #endif |
|
505 iStatus = KRequestPending; |
|
506 SetActive(); |
|
507 TRequestStatus* status = &iStatus; |
|
508 User::RequestComplete( status, KErrNone ); |
|
509 } |
|
510 } |
|
511 |
|
512 // --------------------------------------------------------- |
|
513 // CMmsLog::MatchEntryL |
|
514 // |
|
515 // --------------------------------------------------------- |
|
516 // |
|
517 void CMmsLog::MatchEntryL() |
|
518 { |
|
519 |
|
520 iEventMatched = EFalse; |
|
521 // When a view is created, it is positioned on the first event |
|
522 // If we know our message entry id, we try to match it |
|
523 if ( iLogEvent->Link() != KLogNullLink ) |
|
524 { |
|
525 if ( iLogEvent->Link() == iLogViewEvent.Event().Link() ) |
|
526 { |
|
527 iEventMatched = ETrue; |
|
528 } |
|
529 } |
|
530 else |
|
531 { |
|
532 // Our message id (returned by MMSC) is stored to Data field. |
|
533 if ( iLogEvent->Data().Compare( iLogViewEvent.Event().Data() ) == 0 ) |
|
534 { |
|
535 iEventMatched = ETrue; |
|
536 } |
|
537 } |
|
538 |
|
539 TPtrC dummy; |
|
540 TPtrC remoteParty; |
|
541 dummy.Set( iRemoteParties->MdcaPoint( iCurrentRemoteParty ) ); |
|
542 if ( TMmsGenUtils::IsValidMMSPhoneAddress( dummy, ETrue ) ) |
|
543 { |
|
544 dummy.Set( dummy.Right( Min( KMmsNumberOfDigitsToMatch, dummy.Length() ) ) ); |
|
545 remoteParty.Set( iLogViewEvent.Event().Number().Right( |
|
546 Min ( dummy.Length(), iLogViewEvent.Event().Number().Length() ) ) ); |
|
547 } |
|
548 else |
|
549 { |
|
550 dummy.Set( dummy.Right( Min( KLogMaxRemotePartyLength, dummy.Length() ) ) ); |
|
551 remoteParty.Set( iLogViewEvent.Event().RemoteParty() ); |
|
552 } |
|
553 |
|
554 if ( dummy.Compare( remoteParty ) != 0 ) |
|
555 { |
|
556 iEventMatched = EFalse; |
|
557 } |
|
558 |
|
559 iStatus = KRequestPending; |
|
560 if ( iEventMatched ) |
|
561 { |
|
562 iLastMatchedLink = iLogViewEvent.Event().Link(); |
|
563 |
|
564 // found matching event, switch state to updating |
|
565 iLogUpdatedEvent->CopyL( iLogViewEvent.Event() ); |
|
566 SetActive(); |
|
567 TRequestStatus* status = &iStatus; |
|
568 User::RequestComplete( status, KErrNone ); |
|
569 } |
|
570 else |
|
571 { |
|
572 // get next entry |
|
573 iEvents = iLogViewEvent.NextL( iStatus ); |
|
574 SetActive(); |
|
575 if ( iEvents == EFalse ) |
|
576 { |
|
577 // If the LogViewEvent did not issue an asynchronous |
|
578 // request, we must complete ourselves |
|
579 TRequestStatus* status = &iStatus; |
|
580 User::RequestComplete( status, KErrNone ); |
|
581 } |
|
582 } |
|
583 } |
|
584 |
|
585 // --------------------------------------------------------- |
|
586 // CMmsLog::UpdateEntryL |
|
587 // |
|
588 // --------------------------------------------------------- |
|
589 // |
|
590 void CMmsLog::UpdateEntryL() |
|
591 { |
|
592 |
|
593 // Update status and message id |
|
594 // If contact database id is not defined, try to update it too |
|
595 |
|
596 // We update the date only if it is later than what is already in the log |
|
597 // Otherwise we take the date that is already in the log |
|
598 if ( iLogUpdatedEvent->Time() < iLogEvent->Time() ) |
|
599 { |
|
600 iLogUpdatedEvent->SetTime( iLogEvent->Time() ); |
|
601 } |
|
602 |
|
603 #ifndef _NO_MMSS_LOGGING_ |
|
604 TMmsLogger::Log( _L("CMmsLog updating log")); |
|
605 TTime time = iLogUpdatedEvent->Time(); |
|
606 TBuf<KMmsDateBufferLength> dateString; |
|
607 time.FormatL(dateString,(_L("%*E%*D%X%*N%*Y %1 %2 '%3"))); |
|
608 TMmsLogger::Log( _L(" - event date %S"), &dateString ); |
|
609 time.FormatL(dateString,(_L("%-B%:0%J%:1%T%:2%S%:3%+B"))); |
|
610 TMmsLogger::Log( _L(" - event time %S"), &dateString ); |
|
611 #endif |
|
612 |
|
613 // This will mark the entry as "sent" or "delivered" or "failed" |
|
614 // or something similar... |
|
615 TBool doNotUpdate = EFalse; |
|
616 if ( iLogUpdatedEvent->Status().CompareF( KLogsMsgReadText ) == 0 ) |
|
617 { |
|
618 // If the status is already "read" we don't change it |
|
619 // This is a case where a delivery report arrives after a read report. |
|
620 // Highly unlikely, but possible |
|
621 doNotUpdate = ETrue; |
|
622 #ifndef _NO_MMSS_LOGGING_ |
|
623 TMmsLogger::Log( _L("Status already updated to read - do not update again")); |
|
624 #endif |
|
625 } |
|
626 else |
|
627 { |
|
628 iLogUpdatedEvent->SetStatus( iLogEvent->Status() ); |
|
629 // Clear the event read flag in case the user has cleared the log view |
|
630 // We want this to become visible again. |
|
631 iLogUpdatedEvent->ClearFlags( KLogEventRead ); |
|
632 } |
|
633 // if we have a message id, store it |
|
634 if ( ( iLogUpdatedEvent->Data().Length() <= 0 ) && |
|
635 ( iLogEvent->Data().Length() > 0 ) ) |
|
636 { |
|
637 iLogUpdatedEvent->SetDataL( iLogEvent->Data() ); |
|
638 } |
|
639 |
|
640 // done with this remote party |
|
641 iCurrentRemoteParty--; |
|
642 |
|
643 if ( !doNotUpdate ) |
|
644 { |
|
645 // update the entry |
|
646 iLogClient.ChangeEvent( *iLogUpdatedEvent, iStatus ); |
|
647 SetActive(); |
|
648 } |
|
649 else |
|
650 { |
|
651 // backward change - do not touch |
|
652 iStatus = KRequestPending; |
|
653 TRequestStatus* status = &iStatus; |
|
654 SetActive(); |
|
655 User::RequestComplete( status, KErrNone ); |
|
656 } |
|
657 |
|
658 } |
|
659 |
|
660 // --------------------------------------------------------- |
|
661 // CMmsLog::CreateEntry |
|
662 // |
|
663 // --------------------------------------------------------- |
|
664 // |
|
665 void CMmsLog::CreateEntryL() |
|
666 { |
|
667 |
|
668 TPtrC dummy; |
|
669 iLogUpdatedEvent->CopyL( *iLogEvent ); |
|
670 dummy.Set( iRemoteParties->MdcaPoint( iCurrentRemoteParty ) ); |
|
671 iLogUpdatedEvent->SetRemoteParty( dummy.Left( |
|
672 Min( dummy.Length(), KLogMaxRemotePartyLength ) ) ); |
|
673 |
|
674 #ifndef _NO_MMSS_LOGGING_ |
|
675 TMmsLogger::Log( _L("CMmsLog creating log entry")); |
|
676 #endif |
|
677 |
|
678 TInt error = KErrNone; |
|
679 |
|
680 // search contact database only if remote party is phone number |
|
681 // we don't log email recipients when sending. |
|
682 // However, if we get a delivery report from an email address, we log it. |
|
683 |
|
684 if ( TMmsGenUtils::IsValidMMSPhoneAddress( dummy, ETrue ) ) |
|
685 { |
|
686 iLogUpdatedEvent->SetNumber( dummy.Right( |
|
687 Min( dummy.Length(), KLogMaxRemotePartyLength ) ) ); |
|
688 error = TMmsGenUtils::GetAlias( |
|
689 iRemoteParties->MdcaPoint( iCurrentRemoteParty ), |
|
690 iAlias, |
|
691 KLogMaxRemotePartyLength, |
|
692 iFs ); |
|
693 |
|
694 if ( error == KErrNone ) |
|
695 { |
|
696 if ( iAlias.Length() > 0 ) |
|
697 { |
|
698 iLogUpdatedEvent->SetRemoteParty( iAlias ); |
|
699 } |
|
700 } |
|
701 } |
|
702 |
|
703 // done with this remote party |
|
704 TInt size = KMmsIntegerSize; // room for integer types - estimate - 32 bytes |
|
705 size += iLogUpdatedEvent->RemoteParty().Size(); |
|
706 size += iLogUpdatedEvent->Direction().Size(); |
|
707 size += iLogUpdatedEvent->Status().Size(); |
|
708 size += iLogUpdatedEvent->Number().Size(); |
|
709 size += iLogUpdatedEvent->Description().Size(); |
|
710 size += iLogUpdatedEvent->Data().Size(); |
|
711 iCurrentRemoteParty--; |
|
712 |
|
713 // Query about disk space. |
|
714 if ( TMmsGenUtils::DiskSpaceBelowCriticalLevelL( &iFs, size, EDriveC ) ) |
|
715 { |
|
716 // we use standard error code here |
|
717 iError = KErrDiskFull; |
|
718 } |
|
719 if ( iError != KErrDiskFull ) |
|
720 { |
|
721 iLogClient.AddEvent( *iLogUpdatedEvent, iStatus ); |
|
722 SetActive(); |
|
723 } |
|
724 else |
|
725 { |
|
726 User::Leave( iError ); |
|
727 } |
|
728 } |
|
729 |
|
730 // --------------------------------------------------------- |
|
731 // CMmsLog::AddEventTypeL |
|
732 // |
|
733 // --------------------------------------------------------- |
|
734 // |
|
735 void CMmsLog::AddEventTypeL() |
|
736 { |
|
737 // Event type is added if create event returns KErrNotFound |
|
738 iLogEventType = CLogEventType::NewL(); |
|
739 iLogEventType->SetUid( KLogMmsEventTypeUid ); |
|
740 iLogEventType->SetDescription( KMmsLogEventTypeName ); |
|
741 iLogEventType->SetLoggingEnabled( ETrue ); |
|
742 iLogClient.AddEventType( *iLogEventType, iStatus ); |
|
743 SetActive(); |
|
744 } |
|
745 |
|
746 // ================= OTHER EXPORTED FUNCTIONS ============== |
|
747 |
|
748 // End of File |
|
749 |