--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/messagingfw/biomsgfw/BioWatchers/Src/SmsSocketWatcher.cpp Mon Jan 18 20:36:02 2010 +0200
@@ -0,0 +1,768 @@
+// Copyright (c) 1999-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+#include "SmsSocketWatcher.h"
+#include <e32std.h>
+#include <bsp.h>
+#include <biouids.h>
+#include <biodb.h>
+#include <msvstd.h>
+#include <msventry.h>
+#include <smut.h>
+#include <smuthdr.h>
+#include <msvuids.h>
+#include <watcher.h>
+#include <smutset.h>
+#include <csmsemailfields.h>
+#include <csmsaccount.h>
+#include <e32property.h>
+#include <smsuaddr.h>
+
+#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
+#include <bifchangeobserver.h>
+#include <biomessageuids.h>
+#include <tmsvsmsentry.h>
+#include "cwatcher.h"
+#include "tmsvbioinfo.h"
+#endif
+
+const TInt KSmsThresholdDiskSpaceValue = 125000; // 125 KB
+
+/*
+ * CBaseSmsActiveSocketWatcher
+*/
+
+EXPORT_C CBaseSmsActiveSocketWatcher::CBaseSmsActiveSocketWatcher(CWatcherLog& aWatcherLog, TInt aPriority, TUid aBioID, RFs& aFs)
+: CActive(aPriority),
+ iState(ESmsIsClass0Msg),
+ iBioMsgUID(aBioID),
+ iBioServiceId(KMsvLocalServiceIndexEntryId),
+ iSmsServiceId(KMsvLocalServiceIndexEntryId),
+ iWatcherLog(aWatcherLog),
+ iFs(aFs)
+ {
+ // Add it to the scheduler
+ CActiveScheduler::Add(this);
+ }
+
+EXPORT_C CBaseSmsActiveSocketWatcher::~CBaseSmsActiveSocketWatcher()
+ {
+ iTimer.Close();
+ delete iSettings;
+ delete iGetDetDesc;
+ REComSession::FinalClose();
+ }
+
+EXPORT_C void CBaseSmsActiveSocketWatcher::Complete(TInt aStatus)
+ {
+ DoComplete(aStatus);
+ WatcherComplete(aStatus);
+ }
+
+EXPORT_C TInt CBaseSmsActiveSocketWatcher::RunError(TInt aError)
+ {
+ BIOWATCHERLOG(iWatcherLog.Printf(_L8("Bio: RunL Failed with %d"), aError));
+ Complete(aError);
+ return KErrNone;
+ }
+
+EXPORT_C void CBaseSmsActiveSocketWatcher::RunL()
+//
+// When the AO is state driven, this form of Run() is very effective
+// DoRunL() takes the AO through the states, queuing another asynch step as required
+// if DoRunL() detects the end of the cycle it returns without queuing another cycle.
+//
+// If Run() would exit without queuing another cycle it reports completion to the client.
+// This is true if the asynch step or DoRunL fails, or the state cycle is complete
+//
+ {
+ BIOWATCHERLOG(iWatcherLog.Printf(_L("Bio: DoRunL: %S, iStatus %d"), &iBioMsgText, iStatus.Int()));
+
+ DoRunL();
+ }
+
+EXPORT_C void CBaseSmsActiveSocketWatcher::SetupL()
+ {
+ DoSetupL();
+ // Start the RunL in the WaitForMessage
+ if (iState != ESmsIsClass0Msg)
+ {
+ iState = ESmsWWaitForMsg;
+ }
+ }
+
+EXPORT_C void CBaseSmsActiveSocketWatcher::StartL()
+ {
+ BIOWATCHERLOG(iWatcherLog.Printf(_L("Bio: StartL: %S"), &iBioMsgText));
+
+ TRequestStatus* pS=&iStatus;
+
+ // Nothing Asynchronous, so just throw into the wait state RunL()
+ User::RequestComplete(pS, KErrNone);
+ SetActive();
+ }
+
+EXPORT_C void CBaseSmsActiveSocketWatcher::RestoreSettingsL(CMsvSession& aSession)
+ {
+ SetBioServiceId(aSession);
+
+ // access sms service settings
+ CSmsAccount* smsAccount = CSmsAccount::NewLC();
+ // load settings
+ smsAccount->LoadSettingsL(*iSettings);
+
+ CleanupStack::PopAndDestroy(smsAccount);
+ }
+
+EXPORT_C void CBaseSmsActiveSocketWatcher::RestoreSettingsL(TMsvId aBioServiceId, TMsvId aSmsServiceId)
+ {
+ SetBioServiceId(aBioServiceId, aSmsServiceId);
+
+ // access sms service settings
+ CSmsAccount* smsAccount = CSmsAccount::NewLC();
+ // load settings
+ smsAccount->LoadSettingsL(*iSettings);
+
+ CleanupStack::PopAndDestroy(smsAccount);
+ }
+
+EXPORT_C void CBaseSmsActiveSocketWatcher::StoreMsgL(CSmsMessage* aSmsMessage)
+ {
+ StoreMsgL(aSmsMessage, EFalse);
+ }
+
+EXPORT_C void CBaseSmsActiveSocketWatcher::StoreMsgL(CSmsMessage* aSmsMessage, TBool aCheckForSID)
+ {
+ BIOWATCHERLOG(iWatcherLog.Printf(_L("Bio: StoreMsgL: %S"), &iBioMsgText));
+
+ CleanupStack::PushL(aSmsMessage);
+
+ CMsvSession* session = CMsvSession::OpenSyncL(*this);
+ CleanupStack::PushL(session);
+
+ BIOWATCHERLOG(LogMessageL(*aSmsMessage));
+ // The trap error code is ignored here. We already have loaded the settings
+ // in the SetupL method. Any catastrophic failure would be reported later
+ // when the message store is attempted.
+ TRAP_IGNORE(RestoreSettingsL(*session));
+
+ PreStoreActionL(*session, *aSmsMessage);
+
+ CMsvEntry* msvEntry = session->GetEntryL(KMsvGlobalInBoxIndexEntryId);
+ CleanupStack::PushL(msvEntry);
+ TInt systemDrive = RFs::GetSystemDrive();
+ TInt driveUnit = session->CurrentDriveL();
+
+ TVolumeInfo volumeInfo;
+ User::LeaveIfError(iFs.Volume(volumeInfo, driveUnit));
+
+
+ BIOWATCHERLOG(iWatcherLog.Printf(_L("BioNbs: driveUnit: %d "),driveUnit));
+ BIOWATCHERLOG(iWatcherLog.Printf(_L("BioNbs: volumeInfo : %d"), volumeInfo.iFree));
+ BIOWATCHERLOG(iWatcherLog.Printf(_L("BioNbs: threshold level= : %d"), KSmsThresholdDiskSpaceValue));
+
+
+ //Check if non-system drive has enough space to store the message
+ if (driveUnit != systemDrive )
+ {
+ BIOWATCHERLOG(iWatcherLog.Printf(_L8("Low Memory")));
+
+ TInt value;
+ TInt err = RProperty::Get(KUidSystemCategory,KUidPSDiskSpaceMonitorKeyType, value);
+
+ BIOWATCHERLOG(iWatcherLog.Printf(_L("RProperty Get Value: %d "),err));
+
+ if (volumeInfo.iFree < KSmsThresholdDiskSpaceValue)
+ {
+ if(value == ESmsDiskSpaceAvailable)
+ {
+ User::LeaveIfError(RProperty::Set(KUidSystemCategory,KUidPSDiskSpaceMonitorKeyType, ESmsDiskSpaceFull));
+ }
+ User::Leave(KErrDiskFull);
+ }
+ else
+ {
+ if(value == ESmsDiskSpaceFull)
+ {
+ User::LeaveIfError(RProperty::Set(KUidSystemCategory,KUidPSDiskSpaceMonitorKeyType, ESmsDiskSpaceAvailable));
+ }
+ }
+ }
+
+
+ if( CanStoreMessage() )
+ {
+ TBool retainReplaceMessage = ETrue;
+ ReplaceTypeMessageL(*msvEntry, *aSmsMessage, retainReplaceMessage);
+ CleanupStack::Pop(3, aSmsMessage);
+ CleanupStack::PushL(session); //guaranteed not leave because of the 3 previous POPs
+ CleanupStack::PushL(msvEntry);
+
+ if( retainReplaceMessage )
+ CreateMessageL(*msvEntry, aSmsMessage, aCheckForSID); //destroys the CSmsMessage
+ else
+ delete aSmsMessage; //destroy the CSmsMessage as CreateMessageL() would have done
+
+ CleanupStack::PopAndDestroy(2, session);
+ }
+ else
+ {
+ CleanupStack::PopAndDestroy(3, aSmsMessage);
+ BIOWATCHERLOG(iWatcherLog.Printf(_L8("Not Creating Message")));
+ }
+ }
+
+void CBaseSmsActiveSocketWatcher::ReplaceTypeMessageL(CMsvEntry& aEntry, CSmsMessage& aMessage, TBool& aRetainOriginalMessage)
+ {
+ if (aMessage.Type() == CSmsPDU::ESmsDeliver)
+ {
+ TUint8 pid(0);
+ const CSmsPDU& sms = aMessage.SmsPDU();
+ const CSmsDeliver& smsTemp = STATIC_CAST(const CSmsDeliver&,sms);
+ pid = (TUint8)*smsTemp.ProtocolIdentifier();
+
+ if ((pid & TSmsProtocolIdentifier::ESmsPIDTypeMask) == TSmsProtocolIdentifier::ESmsPIDShortMessageType)
+ {
+ if ( ((pid & TSmsProtocolIdentifier::ESmsShortMessageTypeMask) <= TSmsProtocolIdentifier::ESmsReplaceShortMessageType7)
+ || ((pid & TSmsProtocolIdentifier::ESmsShortMessageTypeMask) == TSmsProtocolIdentifier::ESmsReturnCallMesage) )
+ {
+ DeleteReplaceTypeMessagesL(aEntry, pid, aMessage, aRetainOriginalMessage);
+ }
+ }
+ } // Type()
+ }
+
+
+void CBaseSmsActiveSocketWatcher::DeleteReplaceTypeMessagesL(CMsvEntry& aEntry, TUint8 aPid, CSmsMessage& aMessage, TBool& aRetainOriginalMessage)
+ {
+ CSmsDeliver& smsTemp = STATIC_CAST(CSmsDeliver&, aMessage.SmsPDU());
+ TTime sourceMessageTime;
+ TInt quart;
+ smsTemp.ServiceCenterTimeStamp(sourceMessageTime, quart);
+
+ // get the children
+ TMsvId parentFolder = KMsvGlobalInBoxIndexEntryId;
+
+ // If this is a class2 message, do the replacement in the class2 folder
+ TSmsDataCodingScheme::TSmsClass classTemp(TSmsDataCodingScheme::ESmsClass0);
+ smsTemp.Class(classTemp);
+
+ if (aMessage.Storage() == CSmsMessage::ESmsSIMStorage)
+ {
+ if (CheckMessageExistsL(aEntry.Session(), iSettings->Class2Folder()))
+ {
+ parentFolder = iSettings->Class2Folder();
+ }
+ }
+
+ aEntry.SetEntryL(parentFolder);
+
+ TInt count = aEntry.Count();
+ while (count--)
+ {
+ const TMsvSmsEntry& entry = aEntry[count];
+ if ((entry.iMtm == KUidMsgTypeSMS || entry.iMtm == KUidBIOMessageTypeMtm) && entry.iType == KUidMsvMessageEntry)
+ {
+ const TUint8 entryPID = entry.ProtocolIdentifier();
+
+ if ((entryPID & TSmsProtocolIdentifier::ESmsPIDTypeMask) == TSmsProtocolIdentifier::ESmsPIDShortMessageType)
+ {
+ if ((entryPID & TSmsProtocolIdentifier::ESmsShortMessageTypeMask) == (aPid & TSmsProtocolIdentifier::ESmsShortMessageTypeMask))
+ {
+ CParaFormatLayer* paraLayer = CParaFormatLayer::NewL();
+ CleanupStack::PushL(paraLayer);
+ CCharFormatLayer* charLayer = CCharFormatLayer::NewL();
+ CleanupStack::PushL(charLayer);
+ CRichText* richtext = CRichText::NewL(paraLayer,charLayer);
+ CleanupStack::PushL(richtext);
+
+ CSmsHeader* header = CSmsHeader::NewL(CSmsPDU::ESmsDeliver, *richtext);
+ CleanupStack::PushL(header);
+
+ CMsvEntry* currentEntry = aEntry.ChildEntryL(entry.Id());
+ CleanupStack::PushL(currentEntry);
+
+ CMsvStore* store = NULL;
+ TRAPD(error, store = currentEntry->ReadStoreL());
+
+ //If message arrived with "replace short message functionality", and some how message deleted from Mail2 store
+ //but entry exist in Index file. In such case, need to delete entry from Index file and treat this as a new message.
+ if(error == KErrNotFound)
+ {
+ aRetainOriginalMessage = ETrue;
+ aEntry.DeleteL(entry.Id());
+ CleanupStack::PopAndDestroy(5); //paraLayer, charLayer, richtext, header, currentEntry
+ return;
+ }
+
+ CleanupStack::PushL(store);
+ header->RestoreL(*store);
+ CleanupStack::PopAndDestroy(2); //store, currentEntry
+
+ if ((header->FromAddress().Compare(smsTemp.ToFromAddress()) == 0))
+ {
+ CSmsDeliver& smsDeliver = static_cast<CSmsDeliver&>(header->Message().SmsPDU());
+ TTime foundMessageTime;
+ smsDeliver.ServiceCenterTimeStamp(foundMessageTime, quart);
+
+ if (sourceMessageTime > foundMessageTime)
+ {
+ aRetainOriginalMessage = ETrue;
+ aEntry.DeleteL(entry.Id());
+ }
+ else
+ aRetainOriginalMessage = EFalse;
+ }
+
+ CleanupStack::PopAndDestroy(4); //paraLayer, charLayer, richtext, header
+ }
+ }
+ }
+ }
+ }
+
+TBool CBaseSmsActiveSocketWatcher::CheckForSID(TPtr& aMessage, TSecureId& aSecureId)
+ {
+ _LIT(KSecureIDStr, "//SYM");
+ const TInt KIdLen = 8;
+
+ // Sanity check
+ if (aMessage.Length() < (KIdLen + KSecureIDStr().Length()))
+ return EFalse;
+
+ TBool locatedSecureId = (aMessage.Find(KSecureIDStr) == 0);
+ if (locatedSecureId)
+ {
+ TPtr idPtr = aMessage.MidTPtr(KSecureIDStr().Length(), KIdLen); // Extract the string for the id.
+ TLex numConverter;
+ numConverter.Assign(idPtr.Ptr());
+
+ TUint32 hexId;
+ if (numConverter.Val(hexId, EHex) == KErrNone)
+ aSecureId = TSecureId(hexId); // Convert the string to a number
+ else
+ locatedSecureId = EFalse;
+ }
+ return locatedSecureId;
+ }
+
+
+void CBaseSmsActiveSocketWatcher::CreateMessageL(CMsvEntry& aEntry, CSmsMessage* aMessage, TBool aCheckForSecureId)
+ {
+ // This function destroys CSmsMessage.
+ CleanupStack::PushL(aMessage);
+
+ // Create a CSmsHeader based on this message. smsHdr takes ownership of aMessage
+ CSmsHeader* header = CSmsHeader::NewL(aMessage);
+ CleanupStack::Pop(aMessage);
+ CleanupStack::PushL(header);
+
+ TMsvSmsEntry entry;
+ entry.iType = KUidMsvMessageEntry;
+ entry.SetVisible(EFalse);
+ entry.SetInPreparation(ETrue);
+ entry.SetReadOnly(EFalse);
+ entry.SetUnread(ETrue);
+ entry.SetSendingState(KMsvSendStateNotApplicable);
+
+ TInt length = iSettings->DescriptionLength();
+ HBufC* buf = HBufC::NewLC(length);
+ TPtr description = buf->Des();
+
+ const CSmsEmailFields& fields = header->EmailFields();
+ TBool isEmail = fields.HasAddress();
+
+ TMsvId parentFolder = KMsvGlobalInBoxIndexEntryId;
+ // Fix for INC17771: This defect meant that a message in the outbox, e.g. would be put into the inbox;
+ // therefore, we check the status of the message to see what folder it should go into
+ if( aMessage->Status() == NMobileSmsStore::EStoredMessageUnsent )
+ parentFolder = KMsvGlobalOutBoxIndexEntryId;
+
+ if( iBioMsgUID != KNullUid )
+ {
+ // BioficateEntry!!!
+ // Set up all the needed ids
+ TSmsUtilities::PopulateMsgEntry(entry, *aMessage, iBioServiceId, *iSettings, KUidBIOMessageTypeMtm);
+ entry.iBioType = iBioMsgUID.iUid;
+
+ // Look up and set the description
+ TInt index;
+ CBIODatabase* bioDB = CBIODatabase::NewLC(aEntry.Session().FileSession());
+ bioDB->GetBioIndexWithMsgIDL(iBioMsgUID, index);
+ description.Copy(bioDB->BifReader(index).Description().Left(length));
+ entry.iDescription.Set(description);
+ CleanupStack::PopAndDestroy(bioDB);
+ }
+ else
+ {
+ TSmsUtilities::PopulateMsgEntry(entry, *aMessage, iSmsServiceId, *iSettings);
+
+ if( isEmail && fields.Subject().Length() > 0 )
+ {
+ // For an email SMS should only set the description to be the subject
+ // if there is a subject.
+ entry.iDescription.Set(fields.Subject());
+ }
+ else
+ {
+ // For normal SMS and for email SMS messages that do not have a
+ // subject field, the description is the begining part of the body.
+ User::LeaveIfError(iGetDetDesc->GetDescription(*aMessage, description, length));
+ entry.iDescription.Set(description);
+ }
+
+ TBool classDefined(EFalse);
+ TSmsDataCodingScheme::TSmsClass classTemp(TSmsDataCodingScheme::ESmsClass0);
+
+ if( aMessage->Type() == CSmsPDU::ESmsDeliver )
+ {
+ const CSmsDeliver& deliver = static_cast<const CSmsDeliver&>(aMessage->SmsPDU());
+ entry.SetProtocolIdentifier(*deliver.ProtocolIdentifier());
+ classDefined = deliver.Class(classTemp);
+
+ if( aMessage->Storage() == CSmsMessage::ESmsSIMStorage)
+ {
+ // This is a class 2 message - store the new SMS message in the
+ // folder specified in the SMS service settings (if that folder
+ // exists, other wise default to Inbox).
+ if( CheckMessageExistsL(aEntry.Session(), iSettings->Class2Folder()) )
+ parentFolder = iSettings->Class2Folder();
+ }
+ }
+ entry.SetClass(classDefined, classTemp);
+ // Check the Existing sms message for User Prompt indicator
+ const RPointerArray<const CEmsInformationElement>& emsElements= aMessage->GetEMSInformationElementsL();
+ // Loop through the array checking for a user prompt indicator element
+ TInt count = emsElements.Count();
+ for( TInt i=0; i < count; ++i )
+ {
+ if( emsElements[i]->Identifier() == CSmsInformationElement::ESmsEnhancedUserPromptIndicator )
+ {
+ entry.SetUserPromptIndicator(ETrue);
+ break;
+ }
+ }
+ }
+ // Set the details
+ TInt detailsLen = KSmsDetailsLength;
+ if(isEmail)
+ {
+ detailsLen = fields.Addresses().MdcaPoint(0).Length();
+ }
+ RBuf details;
+ details.CleanupClosePushL() ;
+ details.CreateL(detailsLen);
+ TInt err = KErrNone;
+ if( isEmail )
+ {
+ // For an email SMS, details is taken from the address field.
+ details.Copy(fields.Addresses().MdcaPoint(0));
+ }
+ else
+ {
+ // For normal SMS message details is taken from the info from destination
+ // address in the PDU.
+ err = iGetDetDesc->GetDetails(aEntry.Session().FileSession(), *aMessage, details);
+ }
+ if( err == KErrNone )
+ entry.iDetails.Set(details);
+
+ // Create the entry
+ aEntry.SetEntryL(parentFolder);
+ aEntry.CreateL(entry);
+ aEntry.Session().CleanupEntryPushL(entry.Id());
+ aEntry.SetEntryL(entry.Id());
+
+ // Save the message
+ CMsvStore* store = aEntry.EditStoreL();
+ CleanupStack::PushL(store);
+
+ // Save off the CSmsHdr
+ header->StoreL(*store);
+
+ // Save the body - create and fill a CRichText object.
+ CParaFormatLayer* paraFormatLayer = CParaFormatLayer::NewL();
+ CleanupStack::PushL(paraFormatLayer);
+ CCharFormatLayer* charFormatLayer = CCharFormatLayer::NewL();
+ CleanupStack::PushL(charFormatLayer);
+ CRichText* richText = CRichText::NewL(paraFormatLayer,charFormatLayer);
+ CleanupStack::PushL(richText);
+
+ TInt len= aMessage->Buffer().Length();
+ HBufC* bufBody = HBufC::NewLC(len);
+
+ TPtr bufBodyPtr = bufBody->Des();
+ aMessage->Buffer().Extract(bufBodyPtr, 0, len);
+ richText->InsertL(0, bufBodyPtr);
+ store->StoreBodyTextL(*richText);
+
+ TBool foundSecureId(EFalse);
+ TSecureId secureId;
+ if (aCheckForSecureId)
+ foundSecureId = CheckForSID(bufBodyPtr, secureId); // Check for SID
+
+ CleanupStack::PopAndDestroy(4, paraFormatLayer); //bufBody, richText, charFormatLayer, paraFormatLayer
+ store->CommitL();
+
+ // Update the index...
+ entry.SetReadOnly(ETrue);
+ entry.SetVisible(Visible());
+ entry.SetInPreparation(EFalse);
+ entry.iSize = store->SizeL();
+
+ if (foundSecureId)
+ aEntry.ChangeL(entry, secureId);
+ else
+ aEntry.ChangeL(entry);
+
+ CleanupStack::PopAndDestroy(store);
+ aEntry.Session().CleanupEntryPop(); // entry
+ CleanupStack::PopAndDestroy(&details);
+ CleanupStack::PopAndDestroy(2, header); // this also deletes aMessage, as owned by header
+ }
+
+TBool CBaseSmsActiveSocketWatcher::CheckMessageExistsL(CMsvSession& aSession, TMsvId aId) const
+ {
+ TMsvEntry tempEntry;
+ TMsvId tempService;
+ const TInt err = aSession.GetEntry(aId, tempService, tempEntry);
+
+ if (err != KErrNotFound)
+ User::LeaveIfError(err);
+
+ return (err == KErrNone);
+ }
+
+void CBaseSmsActiveSocketWatcher::SetBioServiceId(CMsvSession& aSession)
+ {
+ TInt err = KErrNone;
+
+ if (iBioServiceId == KMsvLocalServiceIndexEntryId)
+ {
+ TRAP(err, TSmsUtilities::ServiceIdL(aSession, iBioServiceId, KUidBIOMessageTypeMtm));
+ if (err == KErrNotFound)
+ {
+ iBioServiceId = KMsvLocalServiceIndexEntryId;
+ err = KErrNone;
+ }
+ }
+
+ if (err == KErrNone && iSmsServiceId == KMsvLocalServiceIndexEntryId)
+ {
+ TRAP(err, TSmsUtilities::ServiceIdL(aSession, iSmsServiceId));
+ if (err == KErrNotFound)
+ {
+ iSmsServiceId = KMsvLocalServiceIndexEntryId;
+ err = KErrNone;
+ }
+ }
+ }
+
+void CBaseSmsActiveSocketWatcher::SetBioServiceId(TMsvId aBioServiceId, TMsvId aSmsServiceId)
+ {
+ if (iBioServiceId == KMsvLocalServiceIndexEntryId)
+ {
+ iBioServiceId = aBioServiceId;
+ }
+ if (iSmsServiceId == KMsvLocalServiceIndexEntryId)
+ {
+ iSmsServiceId = aSmsServiceId;
+ }
+ }
+
+EXPORT_C void CBaseSmsActiveSocketWatcher::ConstructL(CBIODatabase& aBioDb, TMsvId aBioServiceId, TMsvId aSmsServiceId)
+ {
+ SetBioMsgText(aBioDb);
+ iSettings = CSmsSettings::NewL();
+
+ // load ECOM interface used to create SMS details and description values.
+ iGetDetDesc = CSmsGetDetDescInterface::NewL();
+
+ RestoreSettingsL(aBioServiceId, aSmsServiceId);
+ }
+
+EXPORT_C void CBaseSmsActiveSocketWatcher::SetBioMsgText(CBIODatabase& aBioDb)
+ {
+ TInt index = 0;
+ TRAPD(err, aBioDb.GetBioIndexWithMsgIDL(iBioMsgUID, index));
+
+ if (!err)
+ iBioMsgText = aBioDb.BifReader(index).Description();
+ }
+
+EXPORT_C void CBaseSmsActiveSocketWatcher::PreStoreActionL(CMsvSession& /*aSession*/, CSmsMessage& /*aMessage*/)
+ {
+ }
+
+#ifndef _BIOMSG_NO_LOGGING
+
+void CBaseSmsActiveSocketWatcher::LogMessageL(const CSmsMessage& aSmsMessage)
+ {
+ if (!iWatcherLog.IsLogging())
+ return;
+
+ BIOWATCHERLOG(iWatcherLog.Printf(KNullDesC));
+ TBuf<64> temp;
+
+ switch (aSmsMessage.Type())
+ {
+ case CSmsPDU::ESmsDeliver:
+ temp = _L("[Deliver%S]");
+ break;
+ case CSmsPDU::ESmsStatusReport:
+ temp = _L("[StatusReport%S]");
+ break;
+ default:
+ temp = _L("[Message%S]");
+ break;
+ }
+
+ TInt length = iBioMsgText.Length();
+ HBufC* hBuf = HBufC::NewLC(length);
+ TPtr buf1 = hBuf->Des();
+
+ for (TInt i = 0; i < length; i++)
+ {
+ if (iBioMsgText[i] != ' ' && iBioMsgText[i] != '\n' && iBioMsgText[i] != '\t' && iBioMsgText[i] != '\r')
+ buf1.Append(iBioMsgText[i]);
+ }
+
+ BIOWATCHERLOG(iWatcherLog.Printf(temp, &buf1));
+ CleanupStack::PopAndDestroy(); //hBuf
+ hBuf = NULL;
+
+ length = aSmsMessage.Buffer().Length();
+ hBuf = HBufC::NewLC(32 + length);
+ TPtr buf2 = hBuf->Des();
+ aSmsMessage.Buffer().Extract(buf2, 0, length);
+ buf2.Insert(0, _L("Message= "));
+ LogEachLine(buf2);
+ CleanupStack::PopAndDestroy(); //hBuf
+ hBuf = NULL;
+
+ temp = aSmsMessage.ToFromAddress();
+ BIOWATCHERLOG(iWatcherLog.Printf(_L("Recipients= %S"), &temp));
+
+ temp = aSmsMessage.ServiceCenterAddress();
+ BIOWATCHERLOG(iWatcherLog.Printf(_L("SC= %S"), &temp));
+
+ BIOWATCHERLOG(iWatcherLog.Printf(_L8("BioUid= %d"), iBioMsgUID.iUid));
+
+ if (aSmsMessage.SmsPDU().DataCodingSchemePresent())
+ {
+ temp.Zero();
+ temp.Append(_L("Encoding= "));
+ switch (aSmsMessage.SmsPDU().Alphabet())
+ {
+ case TSmsDataCodingScheme::ESmsAlphabet7Bit:
+ temp.Append(_L("7"));
+ break;
+ case TSmsDataCodingScheme::ESmsAlphabet8Bit:
+ temp.Append(_L("8"));
+ break;
+ case TSmsDataCodingScheme::ESmsAlphabetUCS2:
+ temp.Append(_L("16"));
+ break;
+ default:
+ temp.Append(_L("Unsupported"));
+ break;
+ }
+
+ BIOWATCHERLOG(iWatcherLog.Printf(temp));
+ }
+
+ BIOWATCHERLOG(iWatcherLog.Printf(KNullDesC));
+ }
+
+void CBaseSmsActiveSocketWatcher::Log(const TDesC& aInput)
+ {
+ if (!iWatcherLog.IsLogging())
+ return;
+
+ //This function is required because iWatcherLog.Printf()
+ //will only accept descriptors of max length 255.
+
+ const TInt KSmsLogMaxLength = KLogBufferSize - 22; //max number of characters RFileLogger will display
+ const TInt length = aInput.Length();
+ TInt start = 0;
+
+ while (start < length)
+ {
+ TPtrC buf(aInput.Mid(start, Min(KSmsLogMaxLength, length - start)));
+ BIOWATCHERLOG(iWatcherLog.Printf(KWatcherStringFormat, &buf));
+ start += KSmsLogMaxLength;
+ }
+ }
+
+void CBaseSmsActiveSocketWatcher::Log(const TDesC8& aInput)
+ {
+ if (!iWatcherLog.IsLogging())
+ return;
+
+ //This function is required because iWatcherLog.Printf()
+ //will only accept descriptors of max length 255.
+
+ const TInt KSmsLogMaxLength = KLogBufferSize - 22; //max number of characters RFileLogger will display
+ const TInt length = aInput.Length();
+ TInt start = 0;
+
+ while (start < length)
+ {
+ TPtrC8 buf(aInput.Mid(start, Min(KSmsLogMaxLength, length - start)));
+ BIOWATCHERLOG(iWatcherLog.Printf(KWatcherStringFormat, &buf));
+ start += KSmsLogMaxLength;
+ }
+ }
+
+
+void CBaseSmsActiveSocketWatcher::LogEachLine(const TDesC& aInput)
+ {
+ if (!iWatcherLog.IsLogging())
+ return;
+
+ //LogEachLine() logs each line in aInput separately.
+ //This is required because RFileLogger (used by iWatcherLog.Printf())
+ //will replace all line feeds and carriage returns with a '.'
+
+ TPtrC part(aInput);
+ TInt length = part.Length();
+
+ while (length > 0)
+ {
+ TInt find = part.Locate('\n');
+
+ if (find == KErrNotFound)
+ {
+ Log(part);
+ break;
+ }
+ else
+ {
+ if (find == 0)
+ BIOWATCHERLOG(iWatcherLog.Printf(KNullDesC));
+ else
+ Log(part.Left(find));
+
+ if (find < length - 1)
+ part.Set(part.Mid(find + 1));
+ else
+ break;
+ }
+
+ length = part.Length();
+ }
+ }
+
+#endif