--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mobilemessaging/smsmtm/clientmtm/src/SMSCLNT.CPP Thu Dec 17 08:44:11 2009 +0200
@@ -0,0 +1,1678 @@
+// 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:
+// SMSCLNT.CPP
+//
+
+#include <txtrich.h> // CRichText
+
+#include <msvuids.h> // KUidMsvRootEntry etc.
+#include <mtmdef.hrh> // KUidMtmQuerySupports etc.
+#include <mtmdef.h> // KMsvMessagePartRecipient etc.
+#include <msvids.h> // KMsvGlobalOutBoxIndexEntryId etc.
+#include <msvftext.h> // CMsvFindText
+#include <biodb.h> // CBIODatabase
+#include <smss.rsg>
+#include <barsc.h>
+#include <barsread.h>
+
+#include "SMSCLNT.H" // smsclntmtm
+#include "SMCMMAIN.H" // panics
+#include "smscmds.h" // ESmsMtmCommandReadServiceCenter etc.
+#include "smut.h" // TSmsUtilities
+#include "SMUTHDR.H" // CSmsHeader
+#include "SMUTSET.H" // CSmsSettings
+#include <smutsimparam.h>
+#include <csmsemailfields.h>
+#include <csmsaccount.h>
+#include "csmssendmessageoperation.h"
+
+#include <msvenhancesearchsortutil.h>
+
+#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
+#include "msvconsts.h"
+#include <mtmuidsdef.hrh>
+#include <tmsvsmsentry.h>
+#endif
+
+
+
+/**
+The maximum number of SMS PDUs allowed in a concatenated SMS message.
+Together with KSmcmMaxCharsInMessageConcatenated7Bit, this is the response to
+the query for the KUidMtmQueryMaxTotalMsgSizeValue capability.
+@see CSmsClientMtm::QueryCapability
+@see KSmcmMaxCharsInMessageConcatenated7Bit
+*/
+const TInt KSmcmMaxMessageNumber=0x32;
+
+/**
+The maximum number of characters in a concatenated SMS PDU.
+Together with KSmcmMaxMessageNumber, this is the response to the query for the
+KUidMtmQueryMaxTotalMsgSizeValue capability.
+@see CSmsClientMtm::QueryCapability
+@see KSmcmMaxCharsInMessageConcatenated7Bit
+*/
+const TInt KSmcmMaxCharsInMessageConcatenated7Bit=0x99;
+
+/**
+The maximum number of characters in a non-concatenated SMS PDU.
+This is the response to the query for the KUidMtmQueryMaxBodySizeValue
+capability.
+@see CSmsClientMtm::QueryCapability
+*/
+const TInt KSmcmMaxTotalMsgSize=160;
+
+/**
+The granularity of the in-memory buffer for CRichText objects.
+@see CRichText::NewL
+*/
+const TInt KSmcmRichTextConstant=256;
+
+
+// These default subject formats are used if the resource field has not been
+// migrated to include a localised set of subject formats.
+_LIT(KSmsDefaultForwardSubjectFormat, "Fw: %S");
+_LIT(KSmsDefaultReplySubjectFormat, "Re: %S");
+
+/**
+Static factory constuctor.
+
+@param aRegisteredMtmDll
+The registry information for the SMS MTM.
+
+@param aSession
+The message server session
+
+@leave KErrArgument
+Invalid data read from the SMS resource file
+
+@internalTechnology
+
+@see CRegisteredMtmDll
+*/
+EXPORT_C CSmsClientMtm* CSmsClientMtm::NewL(CRegisteredMtmDll& aRegisteredMtmDll,CMsvSession& aSession)
+ {
+ CSmsClientMtm* self=new(ELeave) CSmsClientMtm(aRegisteredMtmDll,aSession);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+/**
+Destructor.
+*/
+CSmsClientMtm::~CSmsClientMtm()
+ {
+ delete iServiceSettings;
+ delete iSmsHeader;
+ delete iEmailForwardSubjectFormat;
+ delete iEmailReplySubjectFormat;
+ }
+
+void CSmsClientMtm::HandleEntryEvent(enum MMsvEntryObserver::TMsvEntryEvent /*aEvent*/,TAny* ,TAny* ,TAny* )
+ {
+ }
+
+/**
+Reads SMS parameters from the SIM.
+
+It starts a new CSmsSimParamOperation, which uses the SMS Server MTM to read the
+SMS parameters from the SIM.
+
+If the phone is unable to supply the SMS parameters from the SIM, then the progress
+information of the CSmsSimParamOperation operation will contain an error.
+
+@param aObserverRequestStatus
+The request status to be completed when the read operation has completed.
+
+@return
+A SIM parameter reader operation. The read SIM parameters are stored in
+CSmsSimParamOperation::iSimParams.
+*/
+EXPORT_C CSmsSimParamOperation* CSmsClientMtm::ReadSimParamsL(TRequestStatus& aObserverRequestStatus)
+ {
+ RestoreServiceAndSettingsL();
+
+ CMsvEntry* entry = Session().GetEntryL(iServiceId);
+ CleanupStack::PushL(entry);
+
+ CSmsSimParamOperation* op = CSmsSimParamOperation::ReadSimParamsL(entry->Entry().iMtm, iServiceId, Session(), aObserverRequestStatus);
+
+ CleanupStack::PopAndDestroy(entry);
+ return op;
+ }
+
+/**
+Writes SMS parameters to the SIM.
+
+It starts a new CSmsSimParamOperation, which uses the SMS Server to write the
+specified SIM parameters to the SIM.
+
+If the phone is unable to write the SMS parameters to the SIM, then the progress
+information of the CSmsSimParamOperation operation will contain an error.
+
+@param aList
+The SIM parameters to be written.
+
+@param aObserverRequestStatus
+The request status to be completed when the write operation has completed.
+
+@return
+A SIM parameter writer operation.
+*/
+EXPORT_C CSmsSimParamOperation* CSmsClientMtm::WriteSimParamsL(const CMobilePhoneSmspList& aList, TRequestStatus& aObserverRequestStatus)
+ {
+ RestoreServiceAndSettingsL();
+
+ CMsvEntry* entry = Session().GetEntryL(iServiceId);
+ CleanupStack::PushL(entry);
+
+ CSmsSimParamOperation* op = CSmsSimParamOperation::WriteSimParamsL(aList, entry->Entry().iMtm, iServiceId, Session(), aObserverRequestStatus);
+
+ CleanupStack::PopAndDestroy(entry);
+
+ return op;
+ }
+
+/**
+Restores the SMS service ID and SMS service settings.
+
+The SMS service ID is obtained. The service settings for the obtained ID are
+restored from the message server. The SMS service ID can be obtained using the
+CSmsClientMtm::ServiceId API and the SMS settings are accessed via the two
+CSmsClientMtm::ServiceSettings API overloads.
+
+This API should be used before using any of the other APIs that required the SMS
+service ID and SMS service settings to be set.
+
+@see CSmsClientMtm::ServiceId
+@see CSmsClientMtm::ServiceSettings
+*/
+EXPORT_C void CSmsClientMtm::RestoreServiceAndSettingsL()
+ {
+ if (iServiceSettings == NULL)
+ {
+ iServiceSettings = CSmsSettings::NewL();
+ }
+
+ // Let's find the right service entry!
+ TSmsUtilities::ServiceIdL(Session(), iServiceId, KUidMsgTypeSMS);
+
+ CSmsAccount* account = CSmsAccount::NewLC();
+ // just v2
+ account->LoadSettingsL(*iServiceSettings);
+ CleanupStack::PopAndDestroy(account);
+ }
+
+
+CSmsClientMtm::CSmsClientMtm(CRegisteredMtmDll& aRegisteredMtmDll,CMsvSession& aSession)
+: CBaseMtm(aRegisteredMtmDll,aSession)
+ {
+ }
+
+void CSmsClientMtm::ConstructL()
+ {
+ SwitchCurrentEntryL(KMsvRootIndexEntryId); // Creates rich text
+
+ RFs& fileSession = Session().FileSession();
+
+ iSmsHeader=CSmsHeader::NewL(CSmsPDU::ESmsSubmit,Body(),fileSession);
+
+ TRAPD(err, RestoreServiceAndSettingsL());
+
+ if (err)
+ {
+ if (err != KErrNotFound)
+ {
+ User::Leave(err);
+ }
+
+ iServiceId = 0;
+ }
+
+ //Initialise iRealAddressOpen and iRealAddressClose from the SMS resouce file
+ RResourceFile resFile = TSmsUtilities::OpenResourceFileL(fileSession);
+ CleanupClosePushL(resFile);
+ TBuf<4> buf;
+ TSmsUtilities::ReadResourceStringL(resFile, R_ADDRESSEE_TELEPHONE_OPEN, buf);
+ if (buf.Length() > 0)
+ {
+ iRealAddressOpen = buf[0];
+ }
+ else
+ {
+ User::Leave(KErrArgument);
+ }
+
+ TSmsUtilities::ReadResourceStringL(resFile, R_ADDRESSEE_TELEPHONE_CLOSE, buf);
+ if (buf.Length() > 0)
+ {
+ iRealAddressClose = buf[0];
+ }
+ else
+ {
+ User::Leave(KErrArgument);
+ }
+ iEmailForwardSubjectFormat = ReadEmailSubjectFormatL(resFile, R_SMS_EMAIL_FORWARD_SUBJECT_FORMAT, KSmsDefaultForwardSubjectFormat);
+ iEmailReplySubjectFormat = ReadEmailSubjectFormatL(resFile, R_SMS_EMAIL_REPLY_SUBJECT_FORMAT, KSmsDefaultReplySubjectFormat);
+
+ CleanupStack::PopAndDestroy(&resFile);
+ }
+
+HBufC* CSmsClientMtm::ReadEmailSubjectFormatL(RResourceFile& aResourceFile, TInt aResourceId, const TDesC& aDefaultFormat)
+ {
+ HBufC* format = NULL;
+ if( aResourceFile.OwnsResourceId(aResourceId) )
+ {
+ HBufC8* buf = aResourceFile.AllocReadLC(aResourceId);
+ TResourceReader reader;
+ reader.SetBuffer(buf);
+ format = (reader.ReadTPtrC()).AllocL();
+ CleanupStack::PopAndDestroy(buf);
+ }
+ else
+ {
+ format = aDefaultFormat.AllocL();
+ }
+ return format;
+ }
+
+CMsvOperation* CSmsClientMtm::CreateNewEntryL(TMsvEntry& aNewEntry, TMsvId aDestination,CSmsHeader& aSmsHeader,const CRichText& aBody,TRequestStatus& aCompletionStatus)
+ {
+ RestoreServiceAndSettingsL();
+
+ CMsvEntry* cEntry = CMsvEntry::NewL(Session(), aDestination, TMsvSelectionOrdering());
+ CleanupStack::PushL(cEntry);
+
+ cEntry->CreateL(aNewEntry);
+
+ const TMsvId msvid = aNewEntry.Id();
+ Session().CleanupEntryPushL(msvid);
+
+ // switch context to the new entry
+ cEntry->SetEntryL(msvid);
+ aNewEntry = cEntry->Entry(); //for the description and details fields
+
+ aSmsHeader.SetSmsSettingsL(*iServiceSettings);
+
+ // service centre was not being set
+ //If we haven't been provided with a service centre address then use the default one
+ if(!aSmsHeader.ReplyPathProvided())
+ {
+ TInt defaultSC = iServiceSettings->DefaultServiceCenter();
+ if(defaultSC > -1)
+ {
+ aSmsHeader.SetServiceCenterAddressL( iServiceSettings->GetServiceCenter(defaultSC).Address() );
+ }
+ }
+
+ // Check the context header to see an email message...
+ if( iSmsHeader->EmailFields().Length() > 0 )
+ {
+ // Yep - update the message as follows
+ // 1. Add the email <-> SMS gateway as the recipient of the new message.
+ // 2. Set the PID for interworking with email.
+ // 3. Set the entry description to be the email subject (if there is one).
+ // 4. Set the entry details to be the email address (if there is one).
+ DoAddRecipientL(&aSmsHeader, iSmsHeader->FromAddress(), KNullDesC);
+
+ CSmsPDU& pdu = aSmsHeader.Message().SmsPDU();
+ if( pdu.ProtocolIdentifierPresent() )
+ {
+ pdu.SetPIDType(TSmsProtocolIdentifier::ESmsPIDTelematicInterworking);
+ pdu.SetTelematicDeviceIndicator(TSmsProtocolIdentifier::ESmsTelematicDevice);
+ pdu.SetTelematicDeviceType(TSmsProtocolIdentifier::ESmsInternetElectronicMail);
+ }
+
+ const CSmsEmailFields& fields = aSmsHeader.EmailFields();
+ if( fields.Subject().Length() > 0 )
+ {
+ // There is a subject - use this as the description
+ aNewEntry.iDescription.Set(fields.Subject());
+ }
+ if( fields.HasAddress() )
+ {
+ // There is an address - use first address as the details.
+ aNewEntry.iDetails.Set(fields.Addresses().MdcaPoint(0));
+ }
+ }
+
+
+ CMsvStore* msvstore=cEntry->EditStoreL();
+ CleanupStack::PushL(msvstore);
+
+ aSmsHeader.StoreL(*msvstore);
+ msvstore->StoreBodyTextL(aBody);
+ msvstore->CommitL();
+
+ aNewEntry.iSize = msvstore->SizeL();
+ cEntry->ChangeL(aNewEntry);
+
+ CleanupStack::PopAndDestroy(msvstore);
+
+
+ TPckg<TMsvId> prog(msvid);
+ CMsvOperation* op = CMsvCompletedOperation::NewL(Session(), KUidMsgTypeSMS, prog, aNewEntry.iServiceId, aCompletionStatus);
+
+ // Now safe to pop the entry off the message server cleanup stack, and any
+ // other remaining resources.
+ Session().CleanupEntryPop();
+ CleanupStack::PopAndDestroy(cEntry);
+
+ return op;
+ }
+
+TBool CSmsClientMtm::ValidRecipients() const
+ {
+ TInt numrecipients = iSmsHeader->Recipients().Count();
+ TBool valid=numrecipients;
+
+ while (numrecipients-- && valid)
+ valid=ValidNumber(iSmsHeader->Recipients()[numrecipients]->Address());
+
+ return valid;
+ }
+
+TBool CSmsClientMtm::ValidNumber(const TDesC& aNumber) const
+ {
+ TBool valid=EFalse;
+ for (TInt i=0; i<aNumber.Length() && !valid; i++) // valid if at least one number in string
+ valid=(aNumber[i]>='0') && (aNumber[i]<='9');
+ return valid;
+ }
+
+void CSmsClientMtm::DoAddAddresseeL(const TDesC& aRealAddress, const TDesC& aAlias)
+ {
+ if (aAlias.Length())
+ {
+ HBufC* buf=HBufC::NewLC(aAlias.Length()+aRealAddress.Length()+3);
+ TPtr ptr = buf->Des();
+ ptr.Copy(aAlias);
+ ptr.Append(_L(" "));
+ ptr.Append(iRealAddressOpen);
+ ptr.Append(aRealAddress);
+ ptr.Append(iRealAddressClose);
+ iAddresseeList->AppendL(ptr);
+ CleanupStack::PopAndDestroy(buf);
+ }
+ else
+ iAddresseeList->AppendL(aRealAddress);
+ }
+
+void CSmsClientMtm::AddRecipientL(const TDesC& aRealAddress, const TDesC& aAlias)
+ {
+ DoAddRecipientL(iSmsHeader, aRealAddress, aAlias);
+ }
+
+void CSmsClientMtm::DoAddRecipientL(CSmsHeader* aSmsHeader, const TDesC& aRealAddress, const TDesC& aAlias)
+ {
+ CSmsNumber* recipient=CSmsNumber::NewL();
+ CleanupStack::PushL(recipient);
+ if ( aRealAddress.Locate('@') != KErrNotFound )
+ {
+ CSmsEmailFields* emailFields = NULL;
+ if ( aSmsHeader->EmailFields().Length() > 0 )
+ {
+ emailFields = CSmsEmailFields::NewL( aSmsHeader->EmailFields() );
+ }
+ else
+ {
+ emailFields = CSmsEmailFields::NewL();
+ }
+ CleanupStack::PushL( emailFields );
+
+ recipient->SetEmailAddressL(aRealAddress, emailFields, aAlias);
+
+ // Clears the CSmsHeaders EmailFields for non Email addresses
+ aSmsHeader->SetEmailFieldsL( *emailFields );
+ CleanupStack::PopAndDestroy( emailFields );
+ }
+ else
+ {
+ recipient->SetAddressL(aRealAddress);
+ if (aAlias.Length() > 0)
+ {
+ recipient->SetNameL(aAlias);
+ }
+ }
+ aSmsHeader->Recipients().AppendL(recipient);
+ CleanupStack::Pop(recipient);
+ }
+
+void CSmsClientMtm::ResetHeader()
+ {
+ if (iSmsHeader)
+ iSmsHeader->Recipients().ResetAndDestroy();
+
+ if (iAddresseeList)
+ iAddresseeList->Reset();
+ }
+
+void CSmsClientMtm::FindInBodyL(const TDesC& aTextToFind, const TMsvPartList& aFoundList, TMsvPartList& aResult)
+ {
+ CMsvFindText* text=CMsvFindText::NewL();
+ CleanupStack::PushL(text);
+ if (text->FindRichTextL(aTextToFind,Body(),aFoundList))
+ aResult|=KMsvMessagePartBody;
+ CleanupStack::PopAndDestroy(text);
+ }
+
+void CSmsClientMtm::FindL(const TDesC& aTextToFind, const TMsvPartList aPartList, TMsvPartList& aFoundList)
+ {
+
+ CMsvFindText* text=CMsvFindText::NewL();
+ CleanupStack::PushL(text);
+
+ // Enhance search and sort
+ // The setting variables are accessed by getting an instance to TMsvEnhanceSearchSortUtil class
+ // This is accessed here by using GetExtensionData() defined in CBaseMtm which refers
+ // to iExtensionData member variable
+ TMsvEnhanceSearchSortUtil* searchsortutil = (TMsvEnhanceSearchSortUtil*)(GetExtensionData());
+
+ if(searchsortutil != NULL)
+ {
+ // For callees other than CMsvSearchsortOpOnHeaderBody class, searchsortutil pointer will be NULL
+
+ TInt index=0;
+ TBool foundinname = EFalse;
+ TBool foundinaddress = EFalse;
+
+ // Retrieve the search sort setting flags
+ TUint32 searchsortsetting=searchsortutil->GetSearchSortSetting();
+
+ if(aPartList & KMsvMessagePartTo)
+ {
+ TInt count=iSmsHeader->Recipients().Count();
+ /*
+ Search for the To field in the the SMS header
+ First it looks in the Senders name
+ if not found, it tries to find it in the senders numbers
+ */
+
+ for(TInt i=0;i<count;i++)
+ {
+ if ((text->FindTextL(aTextToFind,(iSmsHeader->Recipients()).operator[](i)->Name(),aPartList)))
+ {
+ aFoundList|=KMsvMessagePartTo;
+ foundinname = ETrue;
+ index = i;
+ }
+ if(!foundinname)
+ {
+ if ((text->FindTextL(aTextToFind,(iSmsHeader->Recipients()).operator[](i)->Address(),aPartList)))
+ {
+ aFoundList|=KMsvMessagePartTo;
+ foundinaddress = ETrue;
+ index = i;
+ }
+ }
+ }
+ }
+ // Search for the From field
+ else if(aPartList & KMsvMessagePartFrom)
+ {
+ if ((text->FindTextL(aTextToFind,iSmsHeader->FromAddress(),aPartList))
+ || (text->FindTextL(aTextToFind,iMsvEntry->Entry().iDetails,aPartList)))
+ {
+ aFoundList|=KMsvMessagePartFrom;
+ }
+ }
+ // Search for the Subject
+ else if (aPartList & KMsvMessagePartSubject)
+ {
+ if (text->FindTextL(aTextToFind,iMsvEntry->Entry().iDescription,aPartList))
+ {
+ aFoundList|=KMsvMessagePartDescription;
+ }
+ }
+ /* Copy the sort data if sorting is specified.
+ The operations being performed could be only be sort or it could be search and sort
+ If the operation is search and sort than copy the sort data only if the
+ search operation succeeded */
+
+ if ((aPartList & EMessagePartSort ) || ((aPartList & EMessagePartSearchSort) && (aPartList & EMessagePartLastQueryOption) && aFoundList))
+ {
+ if (aPartList & EMessagePartToSort )
+ {
+ if(foundinname) // Copy the sort data form the senders name
+ {
+ TPtrC ptr((iSmsHeader->Recipients()).operator[](index)->Name());
+ SetExtensionData(&ptr);
+ }
+ if(foundinaddress) // Copy data from senders Address
+ {
+ TPtrC ptr((iSmsHeader->Recipients()).operator[](index)->Address());
+ SetExtensionData(&ptr);
+ }
+ }
+ else if(aPartList & EMessagePartFromSort )
+ {
+ SetExtensionData((TAny*)(iSmsHeader->FromAddress().Ptr()));
+ }
+ else if(aPartList & EMessagePartSubjectSort )
+ {
+ SetExtensionData((TAny*)&iMsvEntry->Entry().iDescription);
+ }
+ else
+ // Fix for DEF124605. If a different sort field is specified than
+ // sets setting flag to EMessagePartInvalidSortField
+ {
+ searchsortutil->SetSearchSortSetting(EMessagePartInvalidSortField);
+ }
+ }
+ }
+ else
+ {
+
+ // Implementation prior to PREQ1667
+ if (aPartList & KMsvMessagePartRecipient)
+ {
+ TInt count=iSmsHeader->Recipients().Count();
+
+ for(TInt i=0;i<count;i++)
+ {
+ if ((text->FindTextL(aTextToFind,(iSmsHeader->Recipients()).operator[](i)->Name(),aPartList))
+ || (text->FindTextL(aTextToFind,(iSmsHeader->Recipients()).operator[](i)->Address(),aPartList)))
+ {
+ aFoundList|=KMsvMessagePartRecipient;
+ }
+ }
+ }
+ else if(aPartList & KMsvMessagePartOriginator)
+ {
+ if((text->FindTextL(aTextToFind,iSmsHeader->FromAddress(),aPartList))
+ || (text->FindTextL(aTextToFind,iMsvEntry->Entry().iDetails,aPartList)))
+ {
+ aFoundList|=KMsvMessagePartOriginator;
+ }
+ }
+ else if (aPartList & KMsvMessagePartDescription)
+ {
+ if (text->FindTextL(aTextToFind,iMsvEntry->Entry().iDescription,aPartList))
+ {
+ aFoundList|=KMsvMessagePartDescription;
+ }
+ }
+ }
+ CleanupStack::PopAndDestroy(text);
+ }
+
+
+TMsvPartList CSmsClientMtm::DoFindL(const TDesC& aTextToFind, TMsvPartList aPartList)
+ {
+ __ASSERT_DEBUG(iMsvEntry, Panic(ESmscEntryNotSet));
+
+ TMsvPartList retList = 0;
+
+ // Enhance search and sort
+ // The setting variables are accessed by getting an instance to TMsvEnhanceSearchSortUtil class
+ // This is accessed here by using GetExtensionData() defined in CBaseMtm which refers
+ // to iExtensionData member variable
+
+ TMsvEnhanceSearchSortUtil* searchsortutil = (TMsvEnhanceSearchSortUtil*)(GetExtensionData());
+
+ // For callees other than CMsvSearchsortOpOnHeaderBody class, searchsortutil pointer will be NULL
+ if(searchsortutil !=NULL)
+ {
+ TUint32 searchsortsetting=searchsortutil->GetSearchSortSetting();
+ if ((aPartList & KMsvMessagePartBody) && !(searchsortsetting & EMessagePartBodyLoaded))
+ {
+ CMsvStore* msvstore=iMsvEntry->ReadStoreL();
+ CleanupStack::PushL(msvstore);
+ msvstore->RestoreBodyTextL(Body());
+ FindInBodyL(aTextToFind,aPartList,retList); // Find in body
+ CleanupStack::PopAndDestroy(msvstore);
+
+ // The message body is loaded.Set the setting variable to specify that the body is loaded
+ // If the next search is also on body, than it wont be loaded next time around
+
+ searchsortutil->SetSearchSortSetting(EMessagePartBodyLoaded);
+ }
+ else if( (aPartList & KMsvMessagePartTo ) || (aPartList & KMsvMessagePartFrom ) || (aPartList & KMsvMessagePartSubject))
+ {
+ // Search for To, From and Subject
+ FindL(aTextToFind,aPartList,retList); // Find in header
+ }
+ }
+ else
+ {
+ // Search implementation Prior to PREQ1667
+ if( (aPartList & KMsvMessagePartRecipient) || (aPartList & KMsvMessagePartOriginator) || (aPartList & KMsvMessagePartDescription))
+ {
+ FindL(aTextToFind,aPartList,retList); // Find in header
+ }
+ else if(aPartList & KMsvMessagePartBody)
+ {
+ FindInBodyL(aTextToFind,aPartList,retList); // Find in body
+ }
+
+ }
+ return retList;
+ }
+
+/*
+Used by ForwardL() and ReplyL() for initialising the contents of the new message
+*/
+void CSmsClientMtm::BasicReplyForwardEntry(TMsvEntry& aNewEntry) const
+ {
+ aNewEntry.iMtm = KUidMsgTypeSMS;
+ // Fix for DEF000924: Need to be able to send/cancel an sms while another is being sent
+ aNewEntry.iRelatedId = Entry().Entry().iServiceId;
+ aNewEntry.iServiceId = KMsvLocalServiceIndexEntryId;
+ // End of fix
+ aNewEntry.iType = KUidMsvMessageEntry;
+ aNewEntry.iDate.UniversalTime();
+ }
+
+/*
+ * Methods from CBaseMtm
+ */
+
+/**
+Commits cached changes to the current message context to the message store.
+
+The current context must be set to a message entry with type KUidMsvServiceEntryValue,
+KUidMsvFolderEntryValue or KUidMsvMessageEntryValue. If the current context is
+not set, or is set to an entry with a type that is not supported by this function
+then a panic will occur.
+
+Both the SMS service ID and SMS service settings must have been set or a panic
+will occur. The CSmsClientMtm::RestoreServiceAndSettingsL API can restore both
+of these items.
+
+@panic SMCM 1
+The current context has not been set (debug only).
+
+@panic SMCM 4
+The type of the current context is not supported.
+
+@panic SMCM 11
+The SMS Service settings have not been set (debug only).
+
+@panic SMCM 12
+The ID for SMS Service has not been set (debug only).
+
+@see CSmsClientMtm::RestoreServiceAndSettingsL
+*/
+void CSmsClientMtm::SaveMessageL()
+ {
+ __ASSERT_DEBUG(iMsvEntry,Panic(ESmscEntryNotSet));
+
+ CMsvStore* msvstore=iMsvEntry->EditStoreL();
+ CleanupStack::PushL(msvstore);
+
+ TMsvEntry entry(iMsvEntry->Entry());
+ TBool entryChanged = EFalse;
+
+ switch (iMsvEntry->Entry().iType.iUid)
+ {
+ case KUidMsvServiceEntryValue:
+ {
+ __ASSERT_DEBUG(iServiceSettings, Panic(ESmscSettingsNotSet));
+ __ASSERT_DEBUG(iServiceId, Panic(ESmscServiceIdNotSet));
+
+ CSmsAccount* account = CSmsAccount::NewLC();
+ //just v2
+ account->SaveSettingsL(*iServiceSettings);
+ CleanupStack::PopAndDestroy(account);
+ break;
+ }
+ case KUidMsvFolderEntryValue:
+ {
+ break;
+ }
+ case KUidMsvMessageEntryValue:
+ {
+ // since CreateMessageL creates message as in preparation and non-visible, the SaveMessageL
+ // must now make it visible and not in preparation
+
+ // If iDetails is empty, set it to be the first recipient in the header
+ if ((0 >= entry.iDetails.Length()) && (iSmsHeader->Recipients().Count() > 0))
+ {
+ CSmsNumber* recipient = iSmsHeader->Recipients().At(0);
+ if(recipient->Name().Length() > 0)
+ entry.iDetails.Set(recipient->Name());
+ else
+ entry.iDetails.Set(recipient->Address());
+ }
+
+ // If iDescription is empty, set it to be the first part of the body text
+ if(Body().DocumentLength()>0 && 0 >= entry.iDescription.Length())
+ {
+ entry.iDescription.Set(Body().Read(0,iServiceSettings->DescriptionLength()));
+ }
+ entry.SetVisible(ETrue);
+ entry.SetInPreparation(EFalse);
+ entry.SetMultipleRecipients(iSmsHeader->Recipients().Count() > 1);
+ entryChanged = ETrue;
+
+ iSmsHeader->StoreL(*msvstore);
+ StoreBodyL(*msvstore);
+ break;
+ }
+ default:
+ Panic(ESmscUnrecognizedEntryType);
+ }
+ msvstore->CommitL();
+
+ // Set the iSize member of the TMsvEntry
+ if (iMsvEntry->HasStoreL())
+ {
+ const TInt size = msvstore->SizeL();
+ if (entry.iSize != size)
+ {
+ entry.iSize = size;
+ entryChanged = ETrue;
+ }
+ }
+
+ CleanupStack::PopAndDestroy(msvstore);
+
+ if ( entryChanged )
+ {
+ // The entry info has been updated - commit to the store.
+ iMsvEntry->ChangeL(entry);
+ }
+ }
+
+/**
+Loads the cache with the message data for the current context.
+
+The current context must be set to a message entry with type KUidMsvServiceEntryValue,
+KUidMsvFolderEntryValue or KUidMsvMessageEntryValue. If the current context is
+not set, or is set to an entry with a type that is not supported by this function
+then a panic will occur.
+
+If the current context is of type KUidMsvServiceEntryValue then the SMS service
+settings are restore from the context. The SMS service settings can be accessed
+using the overloaded CSmsClientMtm::ServiceSettings APIs .
+
+If the current context is of type KUidMsvMessageEntryValue then the SMS message
+object is restore from the context. This can be accessed using the overloaded
+CSmsClientMtm::SmsHeader APIs.
+
+If the current context is of type KUidMsvFolderEntryValue then this function
+does nothing.
+
+@panic SMCM 1
+The current context has not been set (debug only).
+
+@panic SMCM 4
+The entry type of the current context was not recognised.
+
+@see CSmsClientMtm::SmsHeader
+@see CSmsClientMtm::ServiceSettings
+*/
+void CSmsClientMtm::LoadMessageL()
+ {
+ __ASSERT_DEBUG(iMsvEntry,Panic(ESmscEntryNotSet));
+
+ RestoreServiceAndSettingsL();
+
+ ResetHeader();
+ Body().Reset();
+ CMsvStore* msvstore=iMsvEntry->ReadStoreL();
+ CleanupStack::PushL(msvstore);
+ switch (iMsvEntry->Entry().iType.iUid)
+ {
+ case KUidMsvServiceEntryValue:
+ {
+ CSmsAccount* account = CSmsAccount::NewLC();
+ // just v2
+ account->LoadSettingsL(*iServiceSettings);
+ CleanupStack::PopAndDestroy(account);
+ break;
+ }
+ case KUidMsvFolderEntryValue:
+ {
+ break;
+ }
+ case KUidMsvMessageEntryValue:
+ {
+ CSmsHeader* smsheader=CSmsHeader::NewL(CSmsPDU::ESmsSubmit,Body());
+ CleanupStack::PushL(smsheader);
+ smsheader->RestoreL(*msvstore);
+ // the following part inserts the recipients from header also to the smsclient
+ // the recipients are restored inside the csmsheader already
+ if (smsheader->Type()==CSmsPDU::ESmsSubmit)
+ {
+ for (TInt i=0; i<smsheader->Recipients().Count(); ++i)
+ {
+ CSmsNumber* recipient=smsheader->Recipients()[i];
+ DoAddAddresseeL(recipient->Address(),recipient->Name());
+ }
+ }
+
+ // Get a reference to TMsvEnhanceSearchSortUtil instance set by CMsvSearchsortOpOnHeaderBody class
+ // If advanced search and sort is being performed than do not load the body here
+ // For API's other than CMsvSearchsortOpOnHeaderBody-> FindInHeaderBodyL(), a call to LoadMessageL()
+ // loads the body.
+
+ TMsvEnhanceSearchSortUtil* searchsortutil = (TMsvEnhanceSearchSortUtil*)(GetExtensionData());
+ if ( searchsortutil == NULL )
+ {
+ msvstore->RestoreBodyTextL(Body()); // Restore Body text
+ }
+ CleanupStack::Pop(smsheader);
+ delete iSmsHeader;
+ iSmsHeader=smsheader;
+ break;
+ }
+ default:
+ Panic(ESmscUnrecognizedEntryType);
+ }
+ CleanupStack::PopAndDestroy(msvstore);
+ }
+/**
+Validates the current message context.
+
+The addresses for the message are checked to be well-formed SMS addresses.
+
+The current context must be set. If the current context is not set then a panic
+will occur.
+
+@param aPartList
+Indicates the message parts for which the validation has been requested.
+
+@return
+If valid KErrNone is returned. If invalid, the invalid parts of the message are
+identified. The return error value is the bitmask of the TMsvPartList IDs for
+each invalid part
+
+@panic SMCM 1
+The current context has not been set (debug only).
+
+@panic SMCM 6
+The addressee list and recipient list do not match (debug only).
+*/
+TMsvPartList CSmsClientMtm::ValidateMessage(TMsvPartList aPartList)
+ {
+ __ASSERT_DEBUG(iMsvEntry, Panic(ESmscEntryNotSet));
+ __ASSERT_DEBUG(iSmsHeader->Recipients().Count()==iAddresseeList->Count(), Panic(ESmscRecpAddresseeMiscount));
+
+ TMsvPartList partlist=TMsvPartList(0);
+ if (aPartList&KMsvMessagePartRecipient)
+ if (!ValidRecipients())
+ partlist|=KMsvMessagePartRecipient;
+
+ return partlist;
+ }
+
+/**
+Searches the specified message part(s) for the plain-text version of the text
+to be found.
+
+@param aTextToFind
+The plain-text version of the text to be found.
+
+@param aPartList
+Indicates the message parts which should be searched.
+
+@return
+If the text was not found, or searching is unsupported, 0. If the text was found,
+a bitmask of the TMsvPartList IDs for each part in which the text was present.
+*/
+TMsvPartList CSmsClientMtm::Find(const TDesC& aTextToFind,TMsvPartList aPartList)
+ {
+ TMsvPartList retList = 0;
+ TRAP_IGNORE(retList = DoFindL(aTextToFind, aPartList));
+ return retList;
+ }
+
+/**
+Creates a new SMS message as a reply to the current message context.
+
+The SMS in the current context must be of type SMS-DELIVER, indicating a mobile
+terminated message.
+
+The current context must be set to a message entry with type KUidMsvMessageEntryValue.
+If the current context is not set, or is set to an entry not of type
+KUidMsvMessageEntryValuethen a panic will occur.
+
+The new SMS message has the recipient set to the sender of the message in the
+current context. It has a type SMS-SUBMIT, indicating a mobile originated meesage.
+If the SMS service settings CSmsSettings::ReplyQuoted is true then the reply
+message will contain the body of the original message, including any EMS elements.
+
+@param aDestination
+The message entry (folder) under which to create the new message.
+
+@param aPartList
+Ignored.
+
+@param aCompletionStatus
+The request status to be completed when the operation has finished.
+
+@return
+An operation object. If the relpy email is successful created, the operation will
+complete with KErrNone. The operation's progress information is a TPckg<TMsvId>,
+containing the TMsvId of the new SMS message. If the reply message fails to be
+created, the operation completes with the relevant error code.
+
+@leave KErrNotSupported
+The current context does not have a PDU type of SMS-DELIVER.
+
+@panic SMCM 1
+The current context has not been set (debug only).
+
+@panic SMCM 2
+The current context was not of type KUidMsvMessageEntry (debug only).
+*/
+CMsvOperation* CSmsClientMtm::ReplyL(TMsvId aDestination,TMsvPartList /*aPartList*/, TRequestStatus& aCompletionStatus)
+ {
+ LoadMessageL();
+
+ __ASSERT_DEBUG(iMsvEntry, Panic(ESmscEntryNotSet));
+ __ASSERT_DEBUG(iMsvEntry->Entry().iType==KUidMsvMessageEntry, Panic(ESmscWrongContextType));
+
+ if (iSmsHeader->Type()!=CSmsPDU::ESmsDeliver)
+ {
+ User::Leave(KErrNotSupported);
+ }
+
+ CRichText* body = CRichText::NewL(iParaFormatLayer, iCharFormatLayer,CEditableText::EFlatStorage,KSmcmRichTextConstant);
+ CleanupStack::PushL(body);
+
+ CSmsHeader* smsheader=CSmsHeader::NewL(CSmsPDU::ESmsSubmit,Body());
+ CleanupStack::PushL(smsheader);
+
+ // Check to see if we are copying the contents of the original message
+ if(iServiceSettings->ReplyQuoted() && iMsvEntry->Entry().iBioType==NULL)
+ {
+ // Copy original rich text
+ body->AppendTakingSolePictureOwnershipL(Body());
+ // Copy ems elements from original message to new message
+ iSmsHeader->Message().CopyEmsElementsL(smsheader->Message());
+ }
+
+ if( iSmsHeader->EmailFields().Length() > 0 )
+ {
+ // The context message is an email message - set the email fields for
+ // the new message.
+ smsheader->SetReplyEmailFieldsL(iSmsHeader->EmailFields(), *iEmailReplySubjectFormat);
+ }
+ else
+ {
+ // Get the reply to address if there is one else the from address.
+ DoAddRecipientL(smsheader, iSmsHeader->ReplyAddressL(), iMsvEntry->Entry().iDetails);
+ }
+
+ if(iSmsHeader->Deliver().ReplyPath())
+ {
+ smsheader->Submit().SetServiceCenterAddressL(iSmsHeader->Deliver().ServiceCenterAddress());
+ smsheader->SetReplyPathProvided(ETrue);
+ }
+ else smsheader->SetReplyPathProvided(EFalse);
+
+ TMsvEntry entry;
+ BasicReplyForwardEntry(entry);
+
+ CMsvOperation* operation = CreateNewEntryL(entry, aDestination, *smsheader, *body, aCompletionStatus);
+
+ CleanupStack::PopAndDestroy(2, body);
+ return operation;
+ }
+
+/**
+Creates a SMS forwarded message from the current message context.
+
+The SMS in the current context must be of type SMS-DELIVER, a mobile terminated
+message, or SMS-SUBMIT, a mobile originated message.
+
+The current context must be set to a message entry with type KUidMsvMessageEntryValue.
+If the current context is not set, or is set to an entry not of type
+KUidMsvMessageEntryValuethen a panic will occur.
+
+The new SMS message will have type SMS-SUBMIT, a mobile originated message. The
+recipient is left blank. The contents that are copied to the new message include
+the message body, iBioType and description. Also, any EMS components are also
+copied.
+
+@param aDestination
+The message entry (folder) under which to create the new message.
+
+@param aPartList
+Ignored.
+
+@param aCompletionStatus
+The request status to be completed when the operation has finished.
+
+@return
+An operation object. If the forward email is successful created, the operation
+will complete with KErrNone. The operation's progress information is a
+TPckg<TMsvId>, containing the TMsvId of the new SMS message. If the forward
+message fails to be created, the operation completes with the relevant error code.
+
+@leave KErrNotSupported
+The current context has a PDU type that is neither SMS-SUBMIT nor SMS-DELIVER.
+
+@panic SMCM 1
+The current context has not been set (debug only).
+
+@panic SMCM 2
+The current context was not of type KUidMsvMessageEntry (debug only).
+*/
+CMsvOperation* CSmsClientMtm::ForwardL(TMsvId aDestination,TMsvPartList /*aPartList*/, TRequestStatus& aCompletionStatus)
+ {
+ LoadMessageL();
+
+ __ASSERT_DEBUG(iMsvEntry, Panic(ESmscEntryNotSet));
+ __ASSERT_DEBUG(iMsvEntry->Entry().iType==KUidMsvMessageEntry, Panic(ESmscWrongContextType));
+
+ // Only forwarding of Submitted or Delivered Messages is supported - ie only
+ // SMS messages that either been sent or received.
+ CSmsPDU::TSmsPDUType smsType = iSmsHeader->Type();
+ if (smsType!=CSmsPDU::ESmsSubmit && smsType!=CSmsPDU::ESmsDeliver)
+ User::Leave(KErrNotSupported);
+
+ CRichText* body = CRichText::NewL(iParaFormatLayer, iCharFormatLayer,CEditableText::EFlatStorage,KSmcmRichTextConstant);
+ CleanupStack::PushL(body);
+ body->AppendTakingSolePictureOwnershipL(Body());
+
+ CSmsHeader* smsheader=CSmsHeader::NewL(CSmsPDU::ESmsSubmit,Body());
+ CleanupStack::PushL(smsheader);
+
+ smsheader->SetReplyPathProvided(EFalse);
+
+ // Copy any EMS elements
+ iSmsHeader->Message().CopyEmsElementsL(smsheader->Message());
+
+ if( iSmsHeader->EmailFields().Length() > 0 )
+ {
+ // The context message is an email message - set the email fields for
+ // the new message.
+ smsheader->SetForwardEmailFieldsL(iSmsHeader->EmailFields(), *iEmailForwardSubjectFormat);
+ }
+
+ // Set the contents of the new TMsvEntry
+ const TMsvEntry& originalEntry = Entry().Entry();
+ TMsvEntry entry;
+ BasicReplyForwardEntry(entry);
+ entry.iBioType = originalEntry.iBioType; // added since 6.1
+ entry.iDescription.Set(originalEntry.iDescription); // added since 6.1
+
+ CMsvOperation* operation = CreateNewEntryL(entry, aDestination,*smsheader,*body,aCompletionStatus);
+
+ CleanupStack::PopAndDestroy(2, body);
+ return operation;
+ }
+
+/**
+Adds an addressee to the current context.
+
+The current context must be an SMS messge of type SMS-SUBMIT, indicating a
+mobile originated message. The address is added to the recipient list for the
+message.
+
+For SMS an address is a telephone number. There is no validation done on the
+input argument aRealAddress to ensure that it is a valid telephone number.
+
+The TSmsUtilities::GetDetails API can be used prior to this API to find the if
+a unique alias exists in the contacts database for this particular telephone
+number.
+
+The current context must be set to a message entry with type KUidMsvMessageEntryValue.
+If the current context is set to an entry not of type KUidMsvMessageEntryValuethen
+a panic will occur.
+
+The SMS MTM maintains an addressee list that matches the recipient list in the
+SMS message header object. If the two list cannot be maintained together then
+this function will leave and both lists are unchanged.
+
+@param aRealAddress
+A string representing the address to be added to the recipient list for the
+current context.
+
+@leave KErrNotSupported
+The current contxt PDU type is not SMS-SUBMIT.
+
+@panic SMCM 2
+The current context was not of type KUidMsvMessageEntry (debug only).
+
+@panic SMCM 6
+The addressee list and recipient list do not match (debug only).
+*/
+void CSmsClientMtm::AddAddresseeL(const TDesC& aRealAddress)
+ {
+ __ASSERT_DEBUG(iMsvEntry->Entry().iType==KUidMsvMessageEntry, Panic(ESmscWrongContextType));
+ if (iSmsHeader->Type()!=CSmsPDU::ESmsSubmit)
+ User::Leave(KErrNotSupported);
+ __ASSERT_DEBUG(iAddresseeList->Count()==iSmsHeader->Recipients().Count(),Panic(ESmscRecpAddresseeMiscount));
+ TPtr ptr(NULL,0);
+ DoAddAddresseeL(aRealAddress,ptr);
+ TRAPD(ret,AddRecipientL(aRealAddress,ptr));
+ if (ret!=KErrNone)
+ {
+ iAddresseeList->Delete(iAddresseeList->Count()-1);
+ User::Leave(ret);
+ }
+ }
+
+/**
+Adds an addressee with an alias to the current context.
+
+The SMS message in the current context must be of type SMS-SUBMIT, indicating a
+mobile originated message. The address is added to the recipient list for the
+message.
+
+For SMS an address is a telephone number. There is no validation done on the
+input argument aRealAddress to ensure that it is a valid telephone number.
+
+The TSmsUtilities::GetDetails API can be used prior to this API to find the if
+a unique alias exists in the contacts database for this particular telephone
+number.
+
+The current context must be set to a message entry with type KUidMsvMessageEntryValue.
+If the current context is set to an entry not of type KUidMsvMessageEntryValuethen
+a panic will occur.
+
+The SMS MTM maintains an addressee list that matches the recipient list in the
+SMS message header object. If the two list cannot be maintained together then
+this function will leave and both lists are unchanged.
+
+@param aRealAddress
+A string representing the address to be added to the recipient list for the
+current message.
+
+@param aAlias
+The alias information for the address.
+
+@leave KErrNotSupported
+The current contxt PDU type is not SMS-SUBMIT.
+
+@panic SMCM 2
+The current context was not of type KUidMsvMessageEntry (debug only).
+
+@panic SMCM 6
+The addressee list and recipient list do not match (debug only).
+*/
+void CSmsClientMtm::AddAddresseeL(const TDesC& aRealAddress, const TDesC& aAlias)
+ {
+ __ASSERT_DEBUG(iMsvEntry->Entry().iType==KUidMsvMessageEntry, Panic(ESmscWrongContextType));
+ if (iSmsHeader->Type()!=CSmsPDU::ESmsSubmit)
+ User::Leave(KErrNotSupported);
+ __ASSERT_DEBUG(iAddresseeList->Count()==iSmsHeader->Recipients().Count(),Panic(ESmscRecpAddresseeMiscount));
+ DoAddAddresseeL(aRealAddress,aAlias);
+ TRAPD(ret,AddRecipientL(aRealAddress,aAlias));
+ if (ret!=KErrNone)
+ {
+ iAddresseeList->Delete(iAddresseeList->Count()-1);
+ User::Leave(ret);
+ }
+ }
+
+/**
+Removes a recipient from the current address list.
+
+The recipient to be removed is specified by its index in the list of recipients.
+This function can only be used when the current context is a mobile-originated
+message (is a SMS-SUBMIT type message).
+
+The index must be valid or a panic will occur. A valid index is not negative and
+does not exceed the upper bounds of the list.
+
+The current context must be set to a message entry with type KUidMsvMessageEntryValue.
+If the current context is set to an entry not of type KUidMsvMessageEntryValuethen
+a panic will occur.
+
+The SMS MTM maintains an addressee list that matches the recipient list in the
+SMS message header object. The address is removed from both lists.
+
+@param aIndex
+The index of recipient to be removed.
+
+@panic SMCM 0
+The current contxt PDU type is not SMS-SUBMIT (debug only).
+
+@panic SMCM 2
+The current context was not a mesasge type context (debug only).
+
+@panic SMCM 5
+The specified index exceeds the recipient list range (debug only).
+
+@panic SMCM 6
+The addressee list and recipient list do not match (debug only).
+*/
+void CSmsClientMtm::RemoveAddressee(TInt aIndex)
+ {
+ __ASSERT_DEBUG(iMsvEntry->Entry().iType==KUidMsvMessageEntry, Panic(ESmscWrongContextType));
+ __ASSERT_DEBUG(iSmsHeader->Type() == CSmsPDU::ESmsSubmit, Panic(ESmutPanicUnsupportedMsgType));
+ __ASSERT_DEBUG((aIndex>=0) && (aIndex<iAddresseeList->Count()),Panic(ESmscAddresseeIndexOutOfRange));
+ __ASSERT_DEBUG(iAddresseeList->Count()==iSmsHeader->Recipients().Count(),Panic(ESmscRecpAddresseeMiscount));
+ delete iSmsHeader->Recipients()[aIndex];
+ iSmsHeader->Recipients().Delete(aIndex);
+ iAddresseeList->Delete(aIndex);
+ }
+
+/**
+Queries if the MTM supports the capability specified by the supplied UID.
+
+@param aCapability
+The UID of capability to be queried.
+
+@param aResponse
+An output argument for the response value. The format of the response varies
+according to the capability.
+
+@return
+A value of KErrNone if the specified capability is recognised and a response
+is returned. KErrNotSupported indicates that the capability is not recognised.
+
+@see mtmuids.h
+*/
+TInt CSmsClientMtm::QueryCapability(TUid aCapability, TInt& aResponse)
+ {
+ TInt error=KErrNone;
+ aResponse=ETrue;
+ switch (aCapability.iUid)
+ {
+ case KUidMtmQueryMaxBodySizeValue:
+ {
+ aResponse=KSmcmMaxTotalMsgSize;
+ break;
+ }
+ case KUidMtmQueryMaxTotalMsgSizeValue:
+ {
+ aResponse = KSmcmMaxMessageNumber*KSmcmMaxCharsInMessageConcatenated7Bit;
+ break;
+ }
+ case KUidMtmQuerySupportedBodyValue:
+ {
+ aResponse = KMtm7BitBody + KMtm8BitBody + KMtm16BitBody;
+ break;
+ }
+ case KUidMtmQueryCanSendMsgValue:
+ case KUidMtmQueryCanReceiveMsgValue:
+ case KUidMtmQuerySupportsBioMsgValue:
+ case KUidMtmQuerySupportsSchedulingValue:
+ case KUidMtmQuerySendAsMessageSendSupportValue:
+ break;
+ case KUidMtmQueryMaxRecipientCountValue:
+ {
+ aResponse=KErrNotFound; // not limited
+ break;
+ }
+ case KUidMsvMtmQueryEditorUidValue:
+ {
+ aResponse=KUidMsgSmsEditorAppVal;
+ break;
+ }
+ case KUidMtmQuerySupportAttachmentsValue:
+ case KUidMtmQueryOffLineAllowedValue:
+ case KUidMtmQuerySupportSubjectValue:
+ case KUidMtmQuerySendAsRequiresRenderedImageValue:
+ case KUidMtmQuerySendAsRenderingUidValue:
+ case KUidMtmQuerySupportsFolderValue:
+ case KUidMtmQuerySupportsRecipientTypeValue:
+ default:
+ error=KErrNotSupported;
+ }
+ return error;
+ }
+
+/**
+Unused for SMS.
+
+This function should not be used as it will cause a panic.
+
+@param aFunctionId
+Unused.
+
+@param aSelection
+Unused.
+
+@param aParameter
+Unused.
+
+@panic SMCM 3
+This command is not supported in SMS and should not be used.
+
+@internalComponent
+*/
+void CSmsClientMtm::InvokeSyncFunctionL(TInt /*aFunctionId*/,const CMsvEntrySelection& /*aSelection*/, TDes8& /*aParameter*/)
+ {
+ Panic(ESmscPanicUnexpectedCommand);
+ }
+
+/**
+Invokes asynchronous SMS-specific operations.
+
+The specified operation is performed by the SMS server MTM.
+
+If the requested command is not supported then a panic will occur. The list of
+supported commands is given by TSmsMtmCommand.
+
+The current context must be set. If the current context is not set then a panic
+will occur.
+
+@param aFunctionId
+The ID of the operation to perform. The specific operations are defined by the
+TSmsMtmCommand enumeration.
+
+@param aSelection
+A selection of messages, the use of which is specific to the selected operation.
+
+@param aParameter
+A packaged object, the use of which is specific to the selected operation.
+
+@param aCompletionStatus
+The request status to be notified when the operation completes.
+
+@return
+An object encapsulating the requested operation if the specified operation was
+successfully started. If the operation failed to be started an completing
+operation is returned with its status set to the relevant error code.
+
+@see TSmsMtmCommand
+
+@panic SMCM 1
+The message entry has not been set (debug only).
+
+@panic SMCM 3
+The specified operation is not supported in SMS.
+*/
+CMsvOperation* CSmsClientMtm::InvokeAsyncFunctionL(TInt aFunctionId, const CMsvEntrySelection& aSelection, TDes8& aParameter, TRequestStatus& aCompletionStatus)
+ {
+ __ASSERT_DEBUG(iMsvEntry,Panic(ESmscEntryNotSet));
+ switch (aFunctionId)
+ {
+ case KMTMStandardFunctionsSendMessage:
+ // perform a regular send with standardised progress information for SendAs2
+ return CSmsSendMessageOperation::NewL(Session(), aSelection, aParameter, aCompletionStatus);
+ case ESmsMtmCommandScheduleCopy:
+ case ESmsMtmCommandScheduleMove:
+ case ESmsMtmCommandDeleteSchedule:
+ case ESmsMtmCommandCheckSchedule:
+ case ESmsMtmCommandSendScheduledCopy:
+ case ESmsMtmCommandSendScheduledMove:
+ case ESmsMtmCommandEnumeratePhoneStores:
+ case ESmsMtmCommandDeleteFromPhoneStore:
+ case ESmsMtmCommandCopyFromPhoneStore:
+ case ESmsMtmCommandMoveFromPhoneStore:
+ case ESmsMtmCommandCopyToPhoneStore:
+ case ESmsMtmCommandMoveToPhoneStore:
+ break;
+ default:
+ Panic(ESmscPanicUnexpectedCommand);
+ }
+ return Session().TransferCommandL(aSelection,aFunctionId,(TDesC8&)aParameter, aCompletionStatus);
+ }
+
+
+/**
+Informs the MTM that the context's BIO field is being changed.
+
+The change is as a result of a call to CSendAs::SetBioTypeL(). This function is
+used by CSendAs::CreateMessageL to create a new outgoing SMS message
+
+@param aBioTypeUid
+The new value for the BIO field.
+
+@panic SMCM 10
+The BIO field contains the wrong value (debug only).
+*/
+EXPORT_C void CSmsClientMtm::BioTypeChangedL(TUid aBioTypeUid)
+ {
+ // Looks up the default send bearer and sets the
+ // character encoding of the Submit() accordingly.
+ RestoreServiceAndSettingsL();
+
+ CBIODatabase* bdb = CBIODatabase::NewLC(Session().FileSession());
+ TBioMsgId bioMsgId;
+ bdb->GetDefaultSendBearerL(aBioTypeUid, bioMsgId);
+
+ CSmsSettings* settings = CSmsSettings::NewL();
+ CleanupStack::PushL(settings);
+
+ settings->CopyL(*iServiceSettings);
+
+ iSmsHeader->SetBioMsgIdType(bioMsgId.iType);
+
+ TSmsDataCodingScheme::TSmsAlphabet alpha = TSmsDataCodingScheme::ESmsAlphabet8Bit;
+
+ // Set the SMS Data Encoding Scheme
+ switch (bioMsgId.iType)
+ {
+ case EBioMsgIdNbs:
+ {
+ switch (bioMsgId.iCharacterSet.iUid)
+ {
+// case KCharacterSetIdentifierIso88591:
+ case KCharacterSetIdentifierCodePage1252:
+ {
+ alpha = TSmsDataCodingScheme::ESmsAlphabet8Bit;
+ break;
+ }
+ case KCharacterSetIdentifierSms7Bit:
+ {
+ alpha = TSmsDataCodingScheme::ESmsAlphabet7Bit;
+ break;
+ }
+ default:
+ {
+ alpha = TSmsDataCodingScheme::ESmsAlphabetUCS2;
+ break;
+ }
+ }
+ break;
+ }
+ case EBioMsgIdWap:
+ case EBioMsgIdWapSecure:
+ default:
+ {
+ //ESmsAlphabet8Bit;
+ break;
+ }
+ };
+
+ settings->SetCharacterSet(alpha);
+ iSmsHeader->SetSmsSettingsL(*settings);
+
+ // service centre was not being set
+ TInt defaultSC = iServiceSettings->DefaultServiceCenter();
+ if(defaultSC > -1)
+ {
+ iSmsHeader->SetServiceCenterAddressL( iServiceSettings->GetServiceCenter(defaultSC).Address() );
+ }
+
+ __ASSERT_DEBUG(iSmsHeader->BioMsgIdType() == bioMsgId.iType, Panic(ESmscBioMsgIdTypeError));
+
+ CleanupStack::PopAndDestroy(2, bdb);
+ }
+
+/**
+Creates a new outgoing SMS message entry as a child of the current context.
+
+Used by CSendAs::CreateMessageL to create an outgoing SMS message.
+
+@param aServiceId
+The ID of the service to own the entry (not used).
+
+@see CSendAs::CreateMessageL
+*/
+EXPORT_C void CSmsClientMtm::CreateMessageL(TMsvId /*aServiceId*/)
+ {
+ RestoreServiceAndSettingsL();
+
+ // Fix for DEF000924: Need to be able to send/cancel an sms while another
+ // is being sent create an invisible blank entry.
+ TMsvEntry entry;
+ entry.iType = KUidMsvMessageEntry;
+ entry.iRelatedId = iServiceId;
+ entry.iServiceId = KMsvLocalServiceIndexEntryId;
+ entry.iMtm = Type();
+ entry.SetVisible(EFalse);
+ entry.SetInPreparation(ETrue);
+
+ // Fix for DEF061945: Need to initialise the iDate member of the new entry
+ entry.iDate.UniversalTime();
+ // store entry in folder
+ iMsvEntry->CreateL(entry);
+ SwitchCurrentEntryL(entry.Id());
+ // End of fix
+
+ delete iSmsHeader;
+ iSmsHeader=NULL;
+ iSmsHeader=CSmsHeader::NewL(CSmsPDU::ESmsSubmit,Body());
+ iSmsHeader->SetSmsSettingsL(*iServiceSettings);
+
+ // service centre was not being set
+ TInt defaultSC = iServiceSettings->DefaultServiceCenter();
+ if(defaultSC > -1)
+ {
+ if (iServiceSettings->ServiceCenterCount() > defaultSC )
+ {
+ iSmsHeader->SetServiceCenterAddressL( iServiceSettings->GetServiceCenter(defaultSC).Address() );
+ }
+ }
+ }
+
+/**
+Resets the current SMS message.
+
+The recipient list in the SMS message header object is emptied. As the SMS MTM
+maintains an addressee list that matches the recipient list in the SMS message
+header object, this addressee list is also emptied.
+*/
+void CSmsClientMtm::ContextEntrySwitched()
+ {
+ ResetHeader();
+ }
+
+/**
+This method is from CBaseMtm, The default implementation is available in CBaseMtm.
+The implementation of this function assumes that the new service for setting the
+charset encoding value for a SMS message is supported.
+TAny* is equivalent to void*.
+@param a0 The collective parameters of TAny*
+@param a1 The collective parameters of TAny*,Charset encoding value is actually extracted from a1.
+@param aExtensionId Uid of the extension interface.
+@return KErrNone If charset is changed successfully in SMS settings for a message.
+@return KErrExtensionNotSupported If the message is other than SMS.
+@return Other Standard system-wide error codes.
+*/
+
+EXPORT_C TInt CSmsClientMtm::Extension_(TUint aExtensionId, TAny*& a0, TAny* a1)
+ {
+ TInt ret=KErrNone;
+ switch(aExtensionId)
+ {
+ case KUIDCharacterSet:
+ {
+ TSmsDataCodingScheme::TSmsAlphabet tsmsAlphabet = (TSmsDataCodingScheme::TSmsAlphabet)(TUint)*(TUint*)a1;
+ TRAP(ret,SetMessageCharacterSetL(tsmsAlphabet));
+ return ret;
+ }
+ default:
+ {
+ // Chain to base class
+ return CBaseMtm::Extension_(aExtensionId, a0, a1);
+ }
+ }
+ }
+
+/**
+This is the actual functionality for setting the character encoding value other than 7-bit ASCII.
+TSmsDataCodingScheme is used for collecting the encoding value for setting the charset for a message.
+This setting is for per-message basis.
+@param aTsmsAlphabet Enum of Sms datacoding scheme for the character encoding value.
+@return void.
+*/
+
+void CSmsClientMtm::SetMessageCharacterSetL(TSmsDataCodingScheme::TSmsAlphabet aTsmsAlphabet)
+ {
+ CSmsSettings* settings = CSmsSettings::NewL();
+ CleanupStack::PushL(settings);
+
+ settings->CopyL(*iServiceSettings);
+ settings->SetCharacterSet(aTsmsAlphabet);
+ iSmsHeader->SetSmsSettingsL(*settings);
+ CleanupStack::PopAndDestroy(settings);
+ }
+
+/**
+Commits cached changes to the current message context to the message store.
+
+The current context must be set to a message entry with type KUidMsvServiceEntryValue,
+KUidMsvFolderEntryValue or KUidMsvMessageEntryValue. If the current context is
+not set, or is set to an entry with a type that is not supported by this function
+then a panic will occur.
+
+Both the SMS service ID and SMS service settings must have been set or a panic
+will occur. The CSmsClientMtm::RestoreServiceAndSettingsL API can restore both
+of these items.
+
+@panic SMCM 1
+The current context has not been set (debug only).
+
+@panic SMCM 4
+The type of the current context is not supported.
+
+@panic SMCM 11
+The SMS Service settings have not been set (debug only).
+
+@panic SMCM 12
+The ID for SMS Service has not been set (debug only).
+
+@see CSmsClientMtm::RestoreServiceAndSettingsL
+*/
+EXPORT_C void CSmsClientMtm::SaveMessageL(CMsvStore& aEditStore, TMsvEntry& aEntry)
+ {
+ switch (aEntry.iType.iUid)
+ {
+ case KUidMsvServiceEntryValue:
+ {
+ __ASSERT_DEBUG(iServiceSettings, Panic(ESmscSettingsNotSet));
+ __ASSERT_DEBUG(iServiceId, Panic(ESmscServiceIdNotSet));
+ CSmsAccount* account = CSmsAccount::NewLC();
+ account->SaveSettingsL(*iServiceSettings);
+ CleanupStack::PopAndDestroy(account);
+ break;
+ }
+ case KUidMsvFolderEntryValue:
+ {
+ break;
+ }
+ case KUidMsvMessageEntryValue:
+ {
+ if ((0 >= aEntry.iDetails.Length()) && (iSmsHeader->Recipients().Count() > 0))
+ {
+ CSmsNumber* recipient = iSmsHeader->Recipients().At(0);
+ if(recipient->Name().Length() > 0)
+ aEntry.iDetails.Set(recipient->Name());
+ else
+ aEntry.iDetails.Set(recipient->Address());
+ }
+ if(Body().DocumentLength()>0 && 0 >= aEntry.iDescription.Length())
+ {
+ aEntry.iDescription.Set(Body().Read(0,iServiceSettings->DescriptionLength()));
+ }
+ aEntry.SetVisible(ETrue);
+ aEntry.SetInPreparation(EFalse);
+ aEntry.SetMultipleRecipients(iSmsHeader->Recipients().Count() > 1);
+ iSmsHeader->StoreL(aEditStore);
+ StoreBodyL(aEditStore);
+ break;
+ }
+ default:
+ Panic(ESmscUnrecognizedEntryType);
+ }
+
+ const TInt size = aEditStore.SizeL();
+ if (aEntry.iSize != size)
+ {
+ aEntry.iSize = size;
+ }
+ }