|
1 // Copyright (c) 1999-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // |
|
15 |
|
16 #include "SmsSocketWatcher.h" |
|
17 #include <e32std.h> |
|
18 #include <bsp.h> |
|
19 #include <biouids.h> |
|
20 #include <biodb.h> |
|
21 #include <msvstd.h> |
|
22 #include <msventry.h> |
|
23 #include <smut.h> |
|
24 #include <smuthdr.h> |
|
25 #include <msvuids.h> |
|
26 #include <watcher.h> |
|
27 #include <smutset.h> |
|
28 #include <csmsemailfields.h> |
|
29 #include <csmsaccount.h> |
|
30 #include <e32property.h> |
|
31 #include <smsuaddr.h> |
|
32 |
|
33 #ifdef SYMBIAN_ENABLE_SPLIT_HEADERS |
|
34 #include <bifchangeobserver.h> |
|
35 #include <biomessageuids.h> |
|
36 #include <tmsvsmsentry.h> |
|
37 #include "cwatcher.h" |
|
38 #include "tmsvbioinfo.h" |
|
39 #endif |
|
40 |
|
41 const TInt KSmsThresholdDiskSpaceValue = 125000; // 125 KB |
|
42 |
|
43 /* |
|
44 * CBaseSmsActiveSocketWatcher |
|
45 */ |
|
46 |
|
47 EXPORT_C CBaseSmsActiveSocketWatcher::CBaseSmsActiveSocketWatcher(CWatcherLog& aWatcherLog, TInt aPriority, TUid aBioID, RFs& aFs) |
|
48 : CActive(aPriority), |
|
49 iState(ESmsIsClass0Msg), |
|
50 iBioMsgUID(aBioID), |
|
51 iBioServiceId(KMsvLocalServiceIndexEntryId), |
|
52 iSmsServiceId(KMsvLocalServiceIndexEntryId), |
|
53 iWatcherLog(aWatcherLog), |
|
54 iFs(aFs) |
|
55 { |
|
56 // Add it to the scheduler |
|
57 CActiveScheduler::Add(this); |
|
58 } |
|
59 |
|
60 EXPORT_C CBaseSmsActiveSocketWatcher::~CBaseSmsActiveSocketWatcher() |
|
61 { |
|
62 iTimer.Close(); |
|
63 delete iSettings; |
|
64 delete iGetDetDesc; |
|
65 REComSession::FinalClose(); |
|
66 } |
|
67 |
|
68 EXPORT_C void CBaseSmsActiveSocketWatcher::Complete(TInt aStatus) |
|
69 { |
|
70 DoComplete(aStatus); |
|
71 WatcherComplete(aStatus); |
|
72 } |
|
73 |
|
74 EXPORT_C TInt CBaseSmsActiveSocketWatcher::RunError(TInt aError) |
|
75 { |
|
76 BIOWATCHERLOG(iWatcherLog.Printf(_L8("Bio: RunL Failed with %d"), aError)); |
|
77 Complete(aError); |
|
78 return KErrNone; |
|
79 } |
|
80 |
|
81 EXPORT_C void CBaseSmsActiveSocketWatcher::RunL() |
|
82 // |
|
83 // When the AO is state driven, this form of Run() is very effective |
|
84 // DoRunL() takes the AO through the states, queuing another asynch step as required |
|
85 // if DoRunL() detects the end of the cycle it returns without queuing another cycle. |
|
86 // |
|
87 // If Run() would exit without queuing another cycle it reports completion to the client. |
|
88 // This is true if the asynch step or DoRunL fails, or the state cycle is complete |
|
89 // |
|
90 { |
|
91 BIOWATCHERLOG(iWatcherLog.Printf(_L("Bio: DoRunL: %S, iStatus %d"), &iBioMsgText, iStatus.Int())); |
|
92 |
|
93 DoRunL(); |
|
94 } |
|
95 |
|
96 EXPORT_C void CBaseSmsActiveSocketWatcher::SetupL() |
|
97 { |
|
98 DoSetupL(); |
|
99 // Start the RunL in the WaitForMessage |
|
100 if (iState != ESmsIsClass0Msg) |
|
101 { |
|
102 iState = ESmsWWaitForMsg; |
|
103 } |
|
104 } |
|
105 |
|
106 EXPORT_C void CBaseSmsActiveSocketWatcher::StartL() |
|
107 { |
|
108 BIOWATCHERLOG(iWatcherLog.Printf(_L("Bio: StartL: %S"), &iBioMsgText)); |
|
109 |
|
110 TRequestStatus* pS=&iStatus; |
|
111 |
|
112 // Nothing Asynchronous, so just throw into the wait state RunL() |
|
113 User::RequestComplete(pS, KErrNone); |
|
114 SetActive(); |
|
115 } |
|
116 |
|
117 EXPORT_C void CBaseSmsActiveSocketWatcher::RestoreSettingsL(CMsvSession& aSession) |
|
118 { |
|
119 SetBioServiceId(aSession); |
|
120 |
|
121 // access sms service settings |
|
122 CSmsAccount* smsAccount = CSmsAccount::NewLC(); |
|
123 // load settings |
|
124 smsAccount->LoadSettingsL(*iSettings); |
|
125 |
|
126 CleanupStack::PopAndDestroy(smsAccount); |
|
127 } |
|
128 |
|
129 EXPORT_C void CBaseSmsActiveSocketWatcher::RestoreSettingsL(TMsvId aBioServiceId, TMsvId aSmsServiceId) |
|
130 { |
|
131 SetBioServiceId(aBioServiceId, aSmsServiceId); |
|
132 |
|
133 // access sms service settings |
|
134 CSmsAccount* smsAccount = CSmsAccount::NewLC(); |
|
135 // load settings |
|
136 smsAccount->LoadSettingsL(*iSettings); |
|
137 |
|
138 CleanupStack::PopAndDestroy(smsAccount); |
|
139 } |
|
140 |
|
141 EXPORT_C void CBaseSmsActiveSocketWatcher::StoreMsgL(CSmsMessage* aSmsMessage) |
|
142 { |
|
143 StoreMsgL(aSmsMessage, EFalse); |
|
144 } |
|
145 |
|
146 EXPORT_C void CBaseSmsActiveSocketWatcher::StoreMsgL(CSmsMessage* aSmsMessage, TBool aCheckForSID) |
|
147 { |
|
148 BIOWATCHERLOG(iWatcherLog.Printf(_L("Bio: StoreMsgL: %S"), &iBioMsgText)); |
|
149 |
|
150 CleanupStack::PushL(aSmsMessage); |
|
151 |
|
152 CMsvSession* session = CMsvSession::OpenSyncL(*this); |
|
153 CleanupStack::PushL(session); |
|
154 |
|
155 BIOWATCHERLOG(LogMessageL(*aSmsMessage)); |
|
156 // The trap error code is ignored here. We already have loaded the settings |
|
157 // in the SetupL method. Any catastrophic failure would be reported later |
|
158 // when the message store is attempted. |
|
159 TRAP_IGNORE(RestoreSettingsL(*session)); |
|
160 |
|
161 PreStoreActionL(*session, *aSmsMessage); |
|
162 |
|
163 CMsvEntry* msvEntry = session->GetEntryL(KMsvGlobalInBoxIndexEntryId); |
|
164 CleanupStack::PushL(msvEntry); |
|
165 TInt systemDrive = RFs::GetSystemDrive(); |
|
166 TInt driveUnit = session->CurrentDriveL(); |
|
167 |
|
168 TVolumeInfo volumeInfo; |
|
169 User::LeaveIfError(iFs.Volume(volumeInfo, driveUnit)); |
|
170 |
|
171 |
|
172 BIOWATCHERLOG(iWatcherLog.Printf(_L("BioNbs: driveUnit: %d "),driveUnit)); |
|
173 BIOWATCHERLOG(iWatcherLog.Printf(_L("BioNbs: volumeInfo : %d"), volumeInfo.iFree)); |
|
174 BIOWATCHERLOG(iWatcherLog.Printf(_L("BioNbs: threshold level= : %d"), KSmsThresholdDiskSpaceValue)); |
|
175 |
|
176 |
|
177 //Check if non-system drive has enough space to store the message |
|
178 if (driveUnit != systemDrive ) |
|
179 { |
|
180 BIOWATCHERLOG(iWatcherLog.Printf(_L8("Low Memory"))); |
|
181 |
|
182 TInt value; |
|
183 TInt err = RProperty::Get(KUidSystemCategory,KUidPSDiskSpaceMonitorKeyType, value); |
|
184 |
|
185 BIOWATCHERLOG(iWatcherLog.Printf(_L("RProperty Get Value: %d "),err)); |
|
186 |
|
187 if (volumeInfo.iFree < KSmsThresholdDiskSpaceValue) |
|
188 { |
|
189 if(value == ESmsDiskSpaceAvailable) |
|
190 { |
|
191 User::LeaveIfError(RProperty::Set(KUidSystemCategory,KUidPSDiskSpaceMonitorKeyType, ESmsDiskSpaceFull)); |
|
192 } |
|
193 User::Leave(KErrDiskFull); |
|
194 } |
|
195 else |
|
196 { |
|
197 if(value == ESmsDiskSpaceFull) |
|
198 { |
|
199 User::LeaveIfError(RProperty::Set(KUidSystemCategory,KUidPSDiskSpaceMonitorKeyType, ESmsDiskSpaceAvailable)); |
|
200 } |
|
201 } |
|
202 } |
|
203 |
|
204 |
|
205 if( CanStoreMessage() ) |
|
206 { |
|
207 TBool retainReplaceMessage = ETrue; |
|
208 ReplaceTypeMessageL(*msvEntry, *aSmsMessage, retainReplaceMessage); |
|
209 CleanupStack::Pop(3, aSmsMessage); |
|
210 CleanupStack::PushL(session); //guaranteed not leave because of the 3 previous POPs |
|
211 CleanupStack::PushL(msvEntry); |
|
212 |
|
213 if( retainReplaceMessage ) |
|
214 CreateMessageL(*msvEntry, aSmsMessage, aCheckForSID); //destroys the CSmsMessage |
|
215 else |
|
216 delete aSmsMessage; //destroy the CSmsMessage as CreateMessageL() would have done |
|
217 |
|
218 CleanupStack::PopAndDestroy(2, session); |
|
219 } |
|
220 else |
|
221 { |
|
222 CleanupStack::PopAndDestroy(3, aSmsMessage); |
|
223 BIOWATCHERLOG(iWatcherLog.Printf(_L8("Not Creating Message"))); |
|
224 } |
|
225 } |
|
226 |
|
227 void CBaseSmsActiveSocketWatcher::ReplaceTypeMessageL(CMsvEntry& aEntry, CSmsMessage& aMessage, TBool& aRetainOriginalMessage) |
|
228 { |
|
229 if (aMessage.Type() == CSmsPDU::ESmsDeliver) |
|
230 { |
|
231 TUint8 pid(0); |
|
232 const CSmsPDU& sms = aMessage.SmsPDU(); |
|
233 const CSmsDeliver& smsTemp = STATIC_CAST(const CSmsDeliver&,sms); |
|
234 pid = (TUint8)*smsTemp.ProtocolIdentifier(); |
|
235 |
|
236 if ((pid & TSmsProtocolIdentifier::ESmsPIDTypeMask) == TSmsProtocolIdentifier::ESmsPIDShortMessageType) |
|
237 { |
|
238 if ( ((pid & TSmsProtocolIdentifier::ESmsShortMessageTypeMask) <= TSmsProtocolIdentifier::ESmsReplaceShortMessageType7) |
|
239 || ((pid & TSmsProtocolIdentifier::ESmsShortMessageTypeMask) == TSmsProtocolIdentifier::ESmsReturnCallMesage) ) |
|
240 { |
|
241 DeleteReplaceTypeMessagesL(aEntry, pid, aMessage, aRetainOriginalMessage); |
|
242 } |
|
243 } |
|
244 } // Type() |
|
245 } |
|
246 |
|
247 |
|
248 void CBaseSmsActiveSocketWatcher::DeleteReplaceTypeMessagesL(CMsvEntry& aEntry, TUint8 aPid, CSmsMessage& aMessage, TBool& aRetainOriginalMessage) |
|
249 { |
|
250 CSmsDeliver& smsTemp = STATIC_CAST(CSmsDeliver&, aMessage.SmsPDU()); |
|
251 TTime sourceMessageTime; |
|
252 TInt quart; |
|
253 smsTemp.ServiceCenterTimeStamp(sourceMessageTime, quart); |
|
254 |
|
255 // get the children |
|
256 TMsvId parentFolder = KMsvGlobalInBoxIndexEntryId; |
|
257 |
|
258 // If this is a class2 message, do the replacement in the class2 folder |
|
259 TSmsDataCodingScheme::TSmsClass classTemp(TSmsDataCodingScheme::ESmsClass0); |
|
260 smsTemp.Class(classTemp); |
|
261 |
|
262 if (aMessage.Storage() == CSmsMessage::ESmsSIMStorage) |
|
263 { |
|
264 if (CheckMessageExistsL(aEntry.Session(), iSettings->Class2Folder())) |
|
265 { |
|
266 parentFolder = iSettings->Class2Folder(); |
|
267 } |
|
268 } |
|
269 |
|
270 aEntry.SetEntryL(parentFolder); |
|
271 |
|
272 TInt count = aEntry.Count(); |
|
273 while (count--) |
|
274 { |
|
275 const TMsvSmsEntry& entry = aEntry[count]; |
|
276 if ((entry.iMtm == KUidMsgTypeSMS || entry.iMtm == KUidBIOMessageTypeMtm) && entry.iType == KUidMsvMessageEntry) |
|
277 { |
|
278 const TUint8 entryPID = entry.ProtocolIdentifier(); |
|
279 |
|
280 if ((entryPID & TSmsProtocolIdentifier::ESmsPIDTypeMask) == TSmsProtocolIdentifier::ESmsPIDShortMessageType) |
|
281 { |
|
282 if ((entryPID & TSmsProtocolIdentifier::ESmsShortMessageTypeMask) == (aPid & TSmsProtocolIdentifier::ESmsShortMessageTypeMask)) |
|
283 { |
|
284 CParaFormatLayer* paraLayer = CParaFormatLayer::NewL(); |
|
285 CleanupStack::PushL(paraLayer); |
|
286 CCharFormatLayer* charLayer = CCharFormatLayer::NewL(); |
|
287 CleanupStack::PushL(charLayer); |
|
288 CRichText* richtext = CRichText::NewL(paraLayer,charLayer); |
|
289 CleanupStack::PushL(richtext); |
|
290 |
|
291 CSmsHeader* header = CSmsHeader::NewL(CSmsPDU::ESmsDeliver, *richtext); |
|
292 CleanupStack::PushL(header); |
|
293 |
|
294 CMsvEntry* currentEntry = aEntry.ChildEntryL(entry.Id()); |
|
295 CleanupStack::PushL(currentEntry); |
|
296 |
|
297 CMsvStore* store = NULL; |
|
298 TRAPD(error, store = currentEntry->ReadStoreL()); |
|
299 |
|
300 //If message arrived with "replace short message functionality", and some how message deleted from Mail2 store |
|
301 //but entry exist in Index file. In such case, need to delete entry from Index file and treat this as a new message. |
|
302 if(error == KErrNotFound) |
|
303 { |
|
304 aRetainOriginalMessage = ETrue; |
|
305 aEntry.DeleteL(entry.Id()); |
|
306 CleanupStack::PopAndDestroy(5); //paraLayer, charLayer, richtext, header, currentEntry |
|
307 return; |
|
308 } |
|
309 |
|
310 CleanupStack::PushL(store); |
|
311 header->RestoreL(*store); |
|
312 CleanupStack::PopAndDestroy(2); //store, currentEntry |
|
313 |
|
314 if ((header->FromAddress().Compare(smsTemp.ToFromAddress()) == 0)) |
|
315 { |
|
316 CSmsDeliver& smsDeliver = static_cast<CSmsDeliver&>(header->Message().SmsPDU()); |
|
317 TTime foundMessageTime; |
|
318 smsDeliver.ServiceCenterTimeStamp(foundMessageTime, quart); |
|
319 |
|
320 if (sourceMessageTime > foundMessageTime) |
|
321 { |
|
322 aRetainOriginalMessage = ETrue; |
|
323 aEntry.DeleteL(entry.Id()); |
|
324 } |
|
325 else |
|
326 aRetainOriginalMessage = EFalse; |
|
327 } |
|
328 |
|
329 CleanupStack::PopAndDestroy(4); //paraLayer, charLayer, richtext, header |
|
330 } |
|
331 } |
|
332 } |
|
333 } |
|
334 } |
|
335 |
|
336 TBool CBaseSmsActiveSocketWatcher::CheckForSID(TPtr& aMessage, TSecureId& aSecureId) |
|
337 { |
|
338 _LIT(KSecureIDStr, "//SYM"); |
|
339 const TInt KIdLen = 8; |
|
340 |
|
341 // Sanity check |
|
342 if (aMessage.Length() < (KIdLen + KSecureIDStr().Length())) |
|
343 return EFalse; |
|
344 |
|
345 TBool locatedSecureId = (aMessage.Find(KSecureIDStr) == 0); |
|
346 if (locatedSecureId) |
|
347 { |
|
348 TPtr idPtr = aMessage.MidTPtr(KSecureIDStr().Length(), KIdLen); // Extract the string for the id. |
|
349 TLex numConverter; |
|
350 numConverter.Assign(idPtr.Ptr()); |
|
351 |
|
352 TUint32 hexId; |
|
353 if (numConverter.Val(hexId, EHex) == KErrNone) |
|
354 aSecureId = TSecureId(hexId); // Convert the string to a number |
|
355 else |
|
356 locatedSecureId = EFalse; |
|
357 } |
|
358 return locatedSecureId; |
|
359 } |
|
360 |
|
361 |
|
362 void CBaseSmsActiveSocketWatcher::CreateMessageL(CMsvEntry& aEntry, CSmsMessage* aMessage, TBool aCheckForSecureId) |
|
363 { |
|
364 // This function destroys CSmsMessage. |
|
365 CleanupStack::PushL(aMessage); |
|
366 |
|
367 // Create a CSmsHeader based on this message. smsHdr takes ownership of aMessage |
|
368 CSmsHeader* header = CSmsHeader::NewL(aMessage); |
|
369 CleanupStack::Pop(aMessage); |
|
370 CleanupStack::PushL(header); |
|
371 |
|
372 TMsvSmsEntry entry; |
|
373 entry.iType = KUidMsvMessageEntry; |
|
374 entry.SetVisible(EFalse); |
|
375 entry.SetInPreparation(ETrue); |
|
376 entry.SetReadOnly(EFalse); |
|
377 entry.SetUnread(ETrue); |
|
378 entry.SetSendingState(KMsvSendStateNotApplicable); |
|
379 |
|
380 TInt length = iSettings->DescriptionLength(); |
|
381 HBufC* buf = HBufC::NewLC(length); |
|
382 TPtr description = buf->Des(); |
|
383 |
|
384 const CSmsEmailFields& fields = header->EmailFields(); |
|
385 TBool isEmail = fields.HasAddress(); |
|
386 |
|
387 TMsvId parentFolder = KMsvGlobalInBoxIndexEntryId; |
|
388 // Fix for INC17771: This defect meant that a message in the outbox, e.g. would be put into the inbox; |
|
389 // therefore, we check the status of the message to see what folder it should go into |
|
390 if( aMessage->Status() == NMobileSmsStore::EStoredMessageUnsent ) |
|
391 parentFolder = KMsvGlobalOutBoxIndexEntryId; |
|
392 |
|
393 if( iBioMsgUID != KNullUid ) |
|
394 { |
|
395 // BioficateEntry!!! |
|
396 // Set up all the needed ids |
|
397 TSmsUtilities::PopulateMsgEntry(entry, *aMessage, iBioServiceId, *iSettings, KUidBIOMessageTypeMtm); |
|
398 entry.iBioType = iBioMsgUID.iUid; |
|
399 |
|
400 // Look up and set the description |
|
401 TInt index; |
|
402 CBIODatabase* bioDB = CBIODatabase::NewLC(aEntry.Session().FileSession()); |
|
403 bioDB->GetBioIndexWithMsgIDL(iBioMsgUID, index); |
|
404 description.Copy(bioDB->BifReader(index).Description().Left(length)); |
|
405 entry.iDescription.Set(description); |
|
406 CleanupStack::PopAndDestroy(bioDB); |
|
407 } |
|
408 else |
|
409 { |
|
410 TSmsUtilities::PopulateMsgEntry(entry, *aMessage, iSmsServiceId, *iSettings); |
|
411 |
|
412 if( isEmail && fields.Subject().Length() > 0 ) |
|
413 { |
|
414 // For an email SMS should only set the description to be the subject |
|
415 // if there is a subject. |
|
416 entry.iDescription.Set(fields.Subject()); |
|
417 } |
|
418 else |
|
419 { |
|
420 // For normal SMS and for email SMS messages that do not have a |
|
421 // subject field, the description is the begining part of the body. |
|
422 User::LeaveIfError(iGetDetDesc->GetDescription(*aMessage, description, length)); |
|
423 entry.iDescription.Set(description); |
|
424 } |
|
425 |
|
426 TBool classDefined(EFalse); |
|
427 TSmsDataCodingScheme::TSmsClass classTemp(TSmsDataCodingScheme::ESmsClass0); |
|
428 |
|
429 if( aMessage->Type() == CSmsPDU::ESmsDeliver ) |
|
430 { |
|
431 const CSmsDeliver& deliver = static_cast<const CSmsDeliver&>(aMessage->SmsPDU()); |
|
432 entry.SetProtocolIdentifier(*deliver.ProtocolIdentifier()); |
|
433 classDefined = deliver.Class(classTemp); |
|
434 |
|
435 if( aMessage->Storage() == CSmsMessage::ESmsSIMStorage) |
|
436 { |
|
437 // This is a class 2 message - store the new SMS message in the |
|
438 // folder specified in the SMS service settings (if that folder |
|
439 // exists, other wise default to Inbox). |
|
440 if( CheckMessageExistsL(aEntry.Session(), iSettings->Class2Folder()) ) |
|
441 parentFolder = iSettings->Class2Folder(); |
|
442 } |
|
443 } |
|
444 entry.SetClass(classDefined, classTemp); |
|
445 // Check the Existing sms message for User Prompt indicator |
|
446 const RPointerArray<const CEmsInformationElement>& emsElements= aMessage->GetEMSInformationElementsL(); |
|
447 // Loop through the array checking for a user prompt indicator element |
|
448 TInt count = emsElements.Count(); |
|
449 for( TInt i=0; i < count; ++i ) |
|
450 { |
|
451 if( emsElements[i]->Identifier() == CSmsInformationElement::ESmsEnhancedUserPromptIndicator ) |
|
452 { |
|
453 entry.SetUserPromptIndicator(ETrue); |
|
454 break; |
|
455 } |
|
456 } |
|
457 } |
|
458 // Set the details |
|
459 TInt detailsLen = KSmsDetailsLength; |
|
460 if(isEmail) |
|
461 { |
|
462 detailsLen = fields.Addresses().MdcaPoint(0).Length(); |
|
463 } |
|
464 RBuf details; |
|
465 details.CleanupClosePushL() ; |
|
466 details.CreateL(detailsLen); |
|
467 TInt err = KErrNone; |
|
468 if( isEmail ) |
|
469 { |
|
470 // For an email SMS, details is taken from the address field. |
|
471 details.Copy(fields.Addresses().MdcaPoint(0)); |
|
472 } |
|
473 else |
|
474 { |
|
475 // For normal SMS message details is taken from the info from destination |
|
476 // address in the PDU. |
|
477 err = iGetDetDesc->GetDetails(aEntry.Session().FileSession(), *aMessage, details); |
|
478 } |
|
479 if( err == KErrNone ) |
|
480 entry.iDetails.Set(details); |
|
481 |
|
482 // Create the entry |
|
483 aEntry.SetEntryL(parentFolder); |
|
484 aEntry.CreateL(entry); |
|
485 aEntry.Session().CleanupEntryPushL(entry.Id()); |
|
486 aEntry.SetEntryL(entry.Id()); |
|
487 |
|
488 // Save the message |
|
489 CMsvStore* store = aEntry.EditStoreL(); |
|
490 CleanupStack::PushL(store); |
|
491 |
|
492 // Save off the CSmsHdr |
|
493 header->StoreL(*store); |
|
494 |
|
495 // Save the body - create and fill a CRichText object. |
|
496 CParaFormatLayer* paraFormatLayer = CParaFormatLayer::NewL(); |
|
497 CleanupStack::PushL(paraFormatLayer); |
|
498 CCharFormatLayer* charFormatLayer = CCharFormatLayer::NewL(); |
|
499 CleanupStack::PushL(charFormatLayer); |
|
500 CRichText* richText = CRichText::NewL(paraFormatLayer,charFormatLayer); |
|
501 CleanupStack::PushL(richText); |
|
502 |
|
503 TInt len= aMessage->Buffer().Length(); |
|
504 HBufC* bufBody = HBufC::NewLC(len); |
|
505 |
|
506 TPtr bufBodyPtr = bufBody->Des(); |
|
507 aMessage->Buffer().Extract(bufBodyPtr, 0, len); |
|
508 richText->InsertL(0, bufBodyPtr); |
|
509 store->StoreBodyTextL(*richText); |
|
510 |
|
511 TBool foundSecureId(EFalse); |
|
512 TSecureId secureId; |
|
513 if (aCheckForSecureId) |
|
514 foundSecureId = CheckForSID(bufBodyPtr, secureId); // Check for SID |
|
515 |
|
516 CleanupStack::PopAndDestroy(4, paraFormatLayer); //bufBody, richText, charFormatLayer, paraFormatLayer |
|
517 store->CommitL(); |
|
518 |
|
519 // Update the index... |
|
520 entry.SetReadOnly(ETrue); |
|
521 entry.SetVisible(Visible()); |
|
522 entry.SetInPreparation(EFalse); |
|
523 entry.iSize = store->SizeL(); |
|
524 |
|
525 if (foundSecureId) |
|
526 aEntry.ChangeL(entry, secureId); |
|
527 else |
|
528 aEntry.ChangeL(entry); |
|
529 |
|
530 CleanupStack::PopAndDestroy(store); |
|
531 aEntry.Session().CleanupEntryPop(); // entry |
|
532 CleanupStack::PopAndDestroy(&details); |
|
533 CleanupStack::PopAndDestroy(2, header); // this also deletes aMessage, as owned by header |
|
534 } |
|
535 |
|
536 TBool CBaseSmsActiveSocketWatcher::CheckMessageExistsL(CMsvSession& aSession, TMsvId aId) const |
|
537 { |
|
538 TMsvEntry tempEntry; |
|
539 TMsvId tempService; |
|
540 const TInt err = aSession.GetEntry(aId, tempService, tempEntry); |
|
541 |
|
542 if (err != KErrNotFound) |
|
543 User::LeaveIfError(err); |
|
544 |
|
545 return (err == KErrNone); |
|
546 } |
|
547 |
|
548 void CBaseSmsActiveSocketWatcher::SetBioServiceId(CMsvSession& aSession) |
|
549 { |
|
550 TInt err = KErrNone; |
|
551 |
|
552 if (iBioServiceId == KMsvLocalServiceIndexEntryId) |
|
553 { |
|
554 TRAP(err, TSmsUtilities::ServiceIdL(aSession, iBioServiceId, KUidBIOMessageTypeMtm)); |
|
555 if (err == KErrNotFound) |
|
556 { |
|
557 iBioServiceId = KMsvLocalServiceIndexEntryId; |
|
558 err = KErrNone; |
|
559 } |
|
560 } |
|
561 |
|
562 if (err == KErrNone && iSmsServiceId == KMsvLocalServiceIndexEntryId) |
|
563 { |
|
564 TRAP(err, TSmsUtilities::ServiceIdL(aSession, iSmsServiceId)); |
|
565 if (err == KErrNotFound) |
|
566 { |
|
567 iSmsServiceId = KMsvLocalServiceIndexEntryId; |
|
568 err = KErrNone; |
|
569 } |
|
570 } |
|
571 } |
|
572 |
|
573 void CBaseSmsActiveSocketWatcher::SetBioServiceId(TMsvId aBioServiceId, TMsvId aSmsServiceId) |
|
574 { |
|
575 if (iBioServiceId == KMsvLocalServiceIndexEntryId) |
|
576 { |
|
577 iBioServiceId = aBioServiceId; |
|
578 } |
|
579 if (iSmsServiceId == KMsvLocalServiceIndexEntryId) |
|
580 { |
|
581 iSmsServiceId = aSmsServiceId; |
|
582 } |
|
583 } |
|
584 |
|
585 EXPORT_C void CBaseSmsActiveSocketWatcher::ConstructL(CBIODatabase& aBioDb, TMsvId aBioServiceId, TMsvId aSmsServiceId) |
|
586 { |
|
587 SetBioMsgText(aBioDb); |
|
588 iSettings = CSmsSettings::NewL(); |
|
589 |
|
590 // load ECOM interface used to create SMS details and description values. |
|
591 iGetDetDesc = CSmsGetDetDescInterface::NewL(); |
|
592 |
|
593 RestoreSettingsL(aBioServiceId, aSmsServiceId); |
|
594 } |
|
595 |
|
596 EXPORT_C void CBaseSmsActiveSocketWatcher::SetBioMsgText(CBIODatabase& aBioDb) |
|
597 { |
|
598 TInt index = 0; |
|
599 TRAPD(err, aBioDb.GetBioIndexWithMsgIDL(iBioMsgUID, index)); |
|
600 |
|
601 if (!err) |
|
602 iBioMsgText = aBioDb.BifReader(index).Description(); |
|
603 } |
|
604 |
|
605 EXPORT_C void CBaseSmsActiveSocketWatcher::PreStoreActionL(CMsvSession& /*aSession*/, CSmsMessage& /*aMessage*/) |
|
606 { |
|
607 } |
|
608 |
|
609 #ifndef _BIOMSG_NO_LOGGING |
|
610 |
|
611 void CBaseSmsActiveSocketWatcher::LogMessageL(const CSmsMessage& aSmsMessage) |
|
612 { |
|
613 if (!iWatcherLog.IsLogging()) |
|
614 return; |
|
615 |
|
616 BIOWATCHERLOG(iWatcherLog.Printf(KNullDesC)); |
|
617 TBuf<64> temp; |
|
618 |
|
619 switch (aSmsMessage.Type()) |
|
620 { |
|
621 case CSmsPDU::ESmsDeliver: |
|
622 temp = _L("[Deliver%S]"); |
|
623 break; |
|
624 case CSmsPDU::ESmsStatusReport: |
|
625 temp = _L("[StatusReport%S]"); |
|
626 break; |
|
627 default: |
|
628 temp = _L("[Message%S]"); |
|
629 break; |
|
630 } |
|
631 |
|
632 TInt length = iBioMsgText.Length(); |
|
633 HBufC* hBuf = HBufC::NewLC(length); |
|
634 TPtr buf1 = hBuf->Des(); |
|
635 |
|
636 for (TInt i = 0; i < length; i++) |
|
637 { |
|
638 if (iBioMsgText[i] != ' ' && iBioMsgText[i] != '\n' && iBioMsgText[i] != '\t' && iBioMsgText[i] != '\r') |
|
639 buf1.Append(iBioMsgText[i]); |
|
640 } |
|
641 |
|
642 BIOWATCHERLOG(iWatcherLog.Printf(temp, &buf1)); |
|
643 CleanupStack::PopAndDestroy(); //hBuf |
|
644 hBuf = NULL; |
|
645 |
|
646 length = aSmsMessage.Buffer().Length(); |
|
647 hBuf = HBufC::NewLC(32 + length); |
|
648 TPtr buf2 = hBuf->Des(); |
|
649 aSmsMessage.Buffer().Extract(buf2, 0, length); |
|
650 buf2.Insert(0, _L("Message= ")); |
|
651 LogEachLine(buf2); |
|
652 CleanupStack::PopAndDestroy(); //hBuf |
|
653 hBuf = NULL; |
|
654 |
|
655 temp = aSmsMessage.ToFromAddress(); |
|
656 BIOWATCHERLOG(iWatcherLog.Printf(_L("Recipients= %S"), &temp)); |
|
657 |
|
658 temp = aSmsMessage.ServiceCenterAddress(); |
|
659 BIOWATCHERLOG(iWatcherLog.Printf(_L("SC= %S"), &temp)); |
|
660 |
|
661 BIOWATCHERLOG(iWatcherLog.Printf(_L8("BioUid= %d"), iBioMsgUID.iUid)); |
|
662 |
|
663 if (aSmsMessage.SmsPDU().DataCodingSchemePresent()) |
|
664 { |
|
665 temp.Zero(); |
|
666 temp.Append(_L("Encoding= ")); |
|
667 switch (aSmsMessage.SmsPDU().Alphabet()) |
|
668 { |
|
669 case TSmsDataCodingScheme::ESmsAlphabet7Bit: |
|
670 temp.Append(_L("7")); |
|
671 break; |
|
672 case TSmsDataCodingScheme::ESmsAlphabet8Bit: |
|
673 temp.Append(_L("8")); |
|
674 break; |
|
675 case TSmsDataCodingScheme::ESmsAlphabetUCS2: |
|
676 temp.Append(_L("16")); |
|
677 break; |
|
678 default: |
|
679 temp.Append(_L("Unsupported")); |
|
680 break; |
|
681 } |
|
682 |
|
683 BIOWATCHERLOG(iWatcherLog.Printf(temp)); |
|
684 } |
|
685 |
|
686 BIOWATCHERLOG(iWatcherLog.Printf(KNullDesC)); |
|
687 } |
|
688 |
|
689 void CBaseSmsActiveSocketWatcher::Log(const TDesC& aInput) |
|
690 { |
|
691 if (!iWatcherLog.IsLogging()) |
|
692 return; |
|
693 |
|
694 //This function is required because iWatcherLog.Printf() |
|
695 //will only accept descriptors of max length 255. |
|
696 |
|
697 const TInt KSmsLogMaxLength = KLogBufferSize - 22; //max number of characters RFileLogger will display |
|
698 const TInt length = aInput.Length(); |
|
699 TInt start = 0; |
|
700 |
|
701 while (start < length) |
|
702 { |
|
703 TPtrC buf(aInput.Mid(start, Min(KSmsLogMaxLength, length - start))); |
|
704 BIOWATCHERLOG(iWatcherLog.Printf(KWatcherStringFormat, &buf)); |
|
705 start += KSmsLogMaxLength; |
|
706 } |
|
707 } |
|
708 |
|
709 void CBaseSmsActiveSocketWatcher::Log(const TDesC8& aInput) |
|
710 { |
|
711 if (!iWatcherLog.IsLogging()) |
|
712 return; |
|
713 |
|
714 //This function is required because iWatcherLog.Printf() |
|
715 //will only accept descriptors of max length 255. |
|
716 |
|
717 const TInt KSmsLogMaxLength = KLogBufferSize - 22; //max number of characters RFileLogger will display |
|
718 const TInt length = aInput.Length(); |
|
719 TInt start = 0; |
|
720 |
|
721 while (start < length) |
|
722 { |
|
723 TPtrC8 buf(aInput.Mid(start, Min(KSmsLogMaxLength, length - start))); |
|
724 BIOWATCHERLOG(iWatcherLog.Printf(KWatcherStringFormat, &buf)); |
|
725 start += KSmsLogMaxLength; |
|
726 } |
|
727 } |
|
728 |
|
729 |
|
730 void CBaseSmsActiveSocketWatcher::LogEachLine(const TDesC& aInput) |
|
731 { |
|
732 if (!iWatcherLog.IsLogging()) |
|
733 return; |
|
734 |
|
735 //LogEachLine() logs each line in aInput separately. |
|
736 //This is required because RFileLogger (used by iWatcherLog.Printf()) |
|
737 //will replace all line feeds and carriage returns with a '.' |
|
738 |
|
739 TPtrC part(aInput); |
|
740 TInt length = part.Length(); |
|
741 |
|
742 while (length > 0) |
|
743 { |
|
744 TInt find = part.Locate('\n'); |
|
745 |
|
746 if (find == KErrNotFound) |
|
747 { |
|
748 Log(part); |
|
749 break; |
|
750 } |
|
751 else |
|
752 { |
|
753 if (find == 0) |
|
754 BIOWATCHERLOG(iWatcherLog.Printf(KNullDesC)); |
|
755 else |
|
756 Log(part.Left(find)); |
|
757 |
|
758 if (find < length - 1) |
|
759 part.Set(part.Mid(find + 1)); |
|
760 else |
|
761 break; |
|
762 } |
|
763 |
|
764 length = part.Length(); |
|
765 } |
|
766 } |
|
767 |
|
768 #endif |