--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/messagingappbase/smsmtm/clientmtm/src/SMUTHDR.CPP Fri Apr 16 14:56:15 2010 +0300
@@ -0,0 +1,1075 @@
+// 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 <smuthdr.h>
+#include <csmsemailfields.h>
+#include <gsmuieoperations.h>
+
+#include <gsmumsg.h>
+#include <msvstore.h>
+#include <cntdb.h>
+#include <gsmunonieoperations.h>
+#include <gsmuelem.h>
+#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
+#include <tmsvsmsentry.h>
+#endif
+
+#if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)
+#include <msvrcpt.h>
+#endif
+
+const TUid KUidMsvSMSHeaderStream = {0x10001834};
+const TInt16 KMsvSmsHeaderVersion = 1;
+const TInt KSmcmRecipientsGranularity = 8;
+#if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)
+_LIT16(KComma, ",");
+_LIT16(KDelimiter, ";");
+#endif
+
+/**
+Allocates and constructs a new CSmsHeader object.
+
+Use this function to create a new SMS-SUBMIT, SMS-COMMAND, SMS-DELIVER or
+SMS-STATUS-REPORT type message.
+
+@param aType
+The Protocol Data Unit (PDU) type for the SMS message.
+
+@param aText
+The message text.
+
+@return
+A new CSmsHeader object.
+*/
+EXPORT_C CSmsHeader* CSmsHeader::NewL(CSmsPDU::TSmsPDUType aType, CEditableText& aText)
+ {
+ CSmsHeader* self = new(ELeave) CSmsHeader();
+ CleanupStack::PushL(self);
+ self->ConstructL(aType, aText);
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+/**
+Allocates and constructs a new CSmsHeader object.
+
+Use this function to create a new SMS-SUBMIT, SMS-COMMAND, SMS-DELIVER or
+SMS-STATUS-REPORT type message. This version uses a previously connected
+file server session handle.
+
+@param aType
+The Protocol Data Unit (PDU) type for the SMS message.
+
+@param aText
+The message text.
+
+@param aFs
+Handle to an open file server session. CSmsHeader will not close the file session.
+
+@return
+A new CSmsHeader object.
+*/
+EXPORT_C CSmsHeader* CSmsHeader::NewL(CSmsPDU::TSmsPDUType aType, CEditableText& aText, RFs& aFs)
+ {
+ CSmsHeader* self = new(ELeave) CSmsHeader();
+ CleanupStack::PushL(self);
+ self->ConstructL(aType, aText, aFs);
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+/**
+Allocates and constructs a new CSmsHeader object.
+
+Use this function to create a new SMS-DELIVER type message.
+
+@param aMessage
+The SMS message encapsulation from the SMS stack.
+
+@return
+A new CSmsHeader object.
+*/
+EXPORT_C CSmsHeader* CSmsHeader::NewL(CSmsMessage* aMessage)
+ {
+ CSmsHeader* self = new(ELeave) CSmsHeader(aMessage);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+/**
+Destructor.
+*/
+EXPORT_C CSmsHeader::~CSmsHeader()
+ {
+ iRecipients.ResetAndDestroy();
+ delete iMessage;
+ delete iEmailFields;
+ if(iCloseFs)
+ {
+ iFs.Close();
+ }
+ }
+
+/**
+Sets the SMS message settings for the message.
+
+This can only be used on SMS-SUBMIT, SMS-COMMAND, SMS-DELIVER or SMS-STATUS-REPORT
+type messages.
+
+NOTE - if this is an Email over SMS message then the PID of is not changed. The
+PID would have been set correctly when the email fields were set.
+
+@param aSmsSettings
+The SMS message settings for the message
+
+@leave KErrNotSupported
+The message PDU type was not supported, or the message conversion value was not
+supported.
+
+@panic SMCM 0
+The message PDU is not supported (debug only).
+*/
+EXPORT_C void CSmsHeader::SetSmsSettingsL(const CSmsMessageSettings& aSmsSettings)
+ {
+ __ASSERT_DEBUG( (Type()==CSmsPDU::ESmsSubmit) || (Type()==CSmsPDU::ESmsDeliver) || (Type()==CSmsPDU::ESmsStatusReport) || (Type()==CSmsPDU::ESmsCommand), Panic(ESmutPanicUnsupportedMsgType));
+
+ switch(Type())
+ {
+ case(CSmsPDU::ESmsSubmit):
+ {
+ Submit().SetRejectDuplicates(aSmsSettings.RejectDuplicate());
+ Submit().SetReplyPath(aSmsSettings.ReplyPath());
+
+ //Check if delivery report for the last segment only is required .
+ if(aSmsSettings.LastSegmentDeliveryReport())
+ {
+ CSmsTPSRROperations& tpSRROperations = static_cast<CSmsTPSRROperations&>(iMessage->GetOperationsForNonIEL(ESmsTPSRRParameter));
+ tpSRROperations.SetSchemeL();
+ tpSRROperations.SetLastSegmentStatusReportL(ETrue);
+ }
+ else
+ {
+ Submit().SetStatusReportRequest(aSmsSettings.DeliveryReport());
+ }
+ Submit().SetValidityPeriod(aSmsSettings.ValidityPeriod());
+ Submit().SetValidityPeriodFormat(aSmsSettings.ValidityPeriodFormat());
+ break;
+ }
+ case(CSmsPDU::ESmsCommand):
+ {
+ Command().SetStatusReportRequest(aSmsSettings.DeliveryReport());
+ break;
+ }
+ case(CSmsPDU::ESmsDeliver):
+ case(CSmsPDU::ESmsStatusReport):
+ break;
+ default:
+ {
+ User::Leave(KErrNotSupported);
+ break;
+ }
+ };
+
+ if (Message().TextPresent())
+ SetCanConcatenate(aSmsSettings.CanConcatenate());
+
+ CSmsPDU& pdu=Message().SmsPDU();
+ if (pdu.DataCodingSchemePresent())
+ pdu.SetAlphabet(aSmsSettings.CharacterSet());
+ if (pdu.ProtocolIdentifierPresent() && iEmailFields->Length() == 0 )
+ {
+ // The email fields object for this message is empty - therefore the
+ // PID can be set. With a non-empty email fields object the PID would
+ // have been set for interworking with email and MUST not be changed.
+ pdu.SetPIDType(TSmsProtocolIdentifier::ESmsPIDTelematicInterworking);
+
+ // MessageConversion
+ switch(aSmsSettings.MessageConversion())
+ {
+ case(ESmsConvPIDNone):
+ {
+ pdu.SetTelematicDeviceIndicator(TSmsProtocolIdentifier::ESmsNoTelematicDevice);
+ break;
+ }
+ case ESmsConvFax:
+ case ESmsConvX400:
+ case ESmsConvPaging:
+ case ESmsConvMail:
+ case ESmsConvErmes:
+ case ESmsConvSpeech:
+ {
+ pdu.SetTelematicDeviceIndicator(TSmsProtocolIdentifier::ESmsTelematicDevice);
+ pdu.SetTelematicDeviceType((TSmsProtocolIdentifier::TSmsTelematicDeviceType) aSmsSettings.MessageConversion());
+ break;
+ }
+ default:
+ {
+ User::Leave(KErrNotSupported);
+ break;
+ }
+ };
+ }
+ }
+
+/**
+Gets the SMS message settings for the message.
+
+This can only be used on SMS-SUBMIT type messages.
+
+@param aSmsSettings
+The output argument with the SMS message settings.
+
+@leave KErrNotSupoprted
+The Telematic Device type is not supported.
+
+@panic SMCM 0
+The message PDU is not supported (debug only).
+*/
+EXPORT_C void CSmsHeader::GetSmsSettingsL(CSmsMessageSettings& aSmsSettings) const
+ {
+ __ASSERT_DEBUG( Type()==CSmsPDU::ESmsSubmit, Panic(ESmutPanicUnsupportedMsgType));
+ switch(Type())
+ {
+ case(CSmsPDU::ESmsSubmit):
+ {
+ aSmsSettings.SetRejectDuplicate(Submit().RejectDuplicates());
+ aSmsSettings.SetReplyPath(Submit().ReplyPath());
+ TSmsStatusReportScheme scheme = iMessage->Scheme();
+ if (scheme == ETPSRRScheme)
+ {
+ aSmsSettings.SetLastSegmentDeliveryReport(ETrue);
+ }
+ else
+ {
+ aSmsSettings.SetDeliveryReport(Submit().StatusReportRequest());
+ }
+ aSmsSettings.SetValidityPeriod(Submit().ValidityPeriod());
+ aSmsSettings.SetValidityPeriodFormat(Submit().ValidityPeriodFormat());
+ aSmsSettings.SetCharacterSet(Submit().Alphabet());
+
+ if (iMessage->SmsPDU().PIDType() == TSmsProtocolIdentifier::ESmsPIDTelematicInterworking)
+ {
+ if (iMessage->SmsPDU().TelematicDeviceIndicator() == TSmsProtocolIdentifier::ESmsNoTelematicDevice)
+ {
+ aSmsSettings.SetMessageConversion(ESmsConvPIDNone);
+ }
+ else //if (iMessage->SmsPDU().TelematicDeviceIndicator() == TSmsProtocolIdentifier::ESmsTelematicDevice)
+ {
+ switch (iMessage->SmsPDU().TelematicDeviceType())
+ {
+ case TSmsProtocolIdentifier::ESmsGroup3TeleFax:
+ case TSmsProtocolIdentifier::ESmsX400MessageHandlingSystem:
+ case TSmsProtocolIdentifier::ESmsNationalPagingSystem:
+ case TSmsProtocolIdentifier::ESmsInternetElectronicMail:
+ case TSmsProtocolIdentifier::ESmsERMES:
+ case TSmsProtocolIdentifier::ESmsVoiceTelephone:
+ aSmsSettings.SetMessageConversion((TSmsPIDConversion) iMessage->SmsPDU().TelematicDeviceType());
+ break;
+ default:
+ User::Leave(KErrNotSupported);
+ break;
+ }
+ }
+ }
+
+ aSmsSettings.SetCanConcatenate(CanConcatenate());
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+ }
+
+/**
+Sets the email fields for the message.
+
+If the supplied email fields is not empty then the PID of the PDU of the message
+is set for interworking with email.
+
+If the supplied email fields is empty and the PID of the PDU of the message is
+set for interworking with email then the PID is set to the default value that
+indicates no telematic device. If the PID was not set for interworking with
+email then it is left unchanged.
+
+@param aEmailFields
+The email fields object. A copy is made of this object.
+*/
+EXPORT_C void CSmsHeader::SetEmailFieldsL(const CSmsEmailFields& aEmailFields)
+ {
+ __ASSERT_DEBUG( Type()==CSmsPDU::ESmsSubmit, Panic(ESmutPanicUnsupportedMsgType));
+
+ CSmsEmailFields* temp = CSmsEmailFields::NewL(aEmailFields);
+ delete iEmailFields;
+ iEmailFields = temp;
+
+ CSmsPDU& pdu = Message().SmsPDU();
+ if( pdu.ProtocolIdentifierPresent() )
+ {
+ if( iEmailFields->Length() > 0 )
+ {
+ // Set the PID for interworking with email.
+ pdu.SetPIDType(TSmsProtocolIdentifier::ESmsPIDTelematicInterworking);
+ pdu.SetTelematicDeviceIndicator(TSmsProtocolIdentifier::ESmsTelematicDevice);
+ pdu.SetTelematicDeviceType(TSmsProtocolIdentifier::ESmsInternetElectronicMail);
+ }
+ else
+ {
+ // The email fields are empty - if the PID is set for interworking
+ // with email, set to indicate no telematic device.
+ if( pdu.PIDType() == TSmsProtocolIdentifier::ESmsPIDTelematicInterworking &&
+ pdu.TelematicDeviceIndicator() == TSmsProtocolIdentifier::ESmsTelematicDevice &&
+ pdu.TelematicDeviceType() == TSmsProtocolIdentifier::ESmsInternetElectronicMail )
+ {
+ pdu.SetTelematicDeviceIndicator(TSmsProtocolIdentifier::ESmsNoTelematicDevice);
+ }
+ }
+ }
+ }
+
+/**
+Sets the email fields for a reply message.
+
+The address field is copied from the specified email fields. The subject field
+is formatted according to the specified subject format using the subject from
+the specified email fields.
+
+The PID of the PDU of the message is set for interworking with email.
+
+@param aEmailFields
+The email fields object.
+
+@param aReplySubjectFormat
+The format of the subject field.
+
+@internalComponent
+*/
+void CSmsHeader::SetReplyEmailFieldsL(const CSmsEmailFields& aEmailFields, const TDesC& aReplySubjectFormat)
+ {
+ // Create the reply email fields - copy address and then format the subject,
+ // if one exists according to the reply prefix.
+ CSmsEmailFields* temp = CSmsEmailFields::NewL();
+ CleanupStack::PushL(temp);
+ temp->AddAddressL(aEmailFields.Addresses().MdcaPoint(0));
+
+ SetEmailReplyForwardSubjectL(temp, aEmailFields.Subject(), aReplySubjectFormat);
+
+ CleanupStack::Pop(temp);
+ delete iEmailFields;
+ iEmailFields = temp;
+
+ // Set the PID for interworking with email.
+ CSmsPDU& pdu = Message().SmsPDU();
+ if( pdu.ProtocolIdentifierPresent() )
+ {
+ pdu.SetPIDType(TSmsProtocolIdentifier::ESmsPIDTelematicInterworking);
+ pdu.SetTelematicDeviceIndicator(TSmsProtocolIdentifier::ESmsTelematicDevice);
+ pdu.SetTelematicDeviceType(TSmsProtocolIdentifier::ESmsInternetElectronicMail);
+ }
+ }
+
+/**
+Sets the email fields for a forward message.
+
+The address field is left empty. The subject field is formatted according to the
+specified subject format using the subject from the specified email fields.
+
+The PID of the PDU of the message is set for interworking with email.
+
+@param aEmailFields
+The email fields object.
+
+@param aForwardSubjectFormat
+The format of the subject field.
+
+@internalComponent
+*/
+void CSmsHeader::SetForwardEmailFieldsL(const CSmsEmailFields& aEmailFields, const TDesC& aForwardSubjectFormat)
+ {
+ // Create the reply email fields - copy address and then format the subject,
+ // if one exists according to the reply prefix.
+ CSmsEmailFields* temp = CSmsEmailFields::NewL();
+ CleanupStack::PushL(temp);
+
+ SetEmailReplyForwardSubjectL(temp, aEmailFields.Subject(), aForwardSubjectFormat);
+
+ CleanupStack::Pop(temp);
+ delete iEmailFields;
+ iEmailFields = temp;
+
+ // Set the PID for interworking with email.
+ CSmsPDU& pdu = Message().SmsPDU();
+ if( pdu.ProtocolIdentifierPresent() )
+ {
+ pdu.SetPIDType(TSmsProtocolIdentifier::ESmsPIDTelematicInterworking);
+ pdu.SetTelematicDeviceIndicator(TSmsProtocolIdentifier::ESmsTelematicDevice);
+ pdu.SetTelematicDeviceType(TSmsProtocolIdentifier::ESmsInternetElectronicMail);
+ }
+ }
+
+void CSmsHeader::SetEmailReplyForwardSubjectL(CSmsEmailFields* aEmailFields, const TDesC& aSubject, const TDesC& aSubjectFormat)
+ {
+ TInt length = aSubject.Length();
+ if( length > 0 )
+ {
+ // Prevent a chain of the format string appearing in the subject - check
+ // to see if the format string is already the prefix of the subject.
+ TInt formatPosInSubject = KErrNotFound;
+
+ _LIT(KFormatStringSpecifier, "%S");
+ TInt formatPos = aSubjectFormat.Find(KFormatStringSpecifier);
+ if( formatPos > 0 )
+ {
+ // Look in current subject for the format string - avoid the '%'.
+ formatPosInSubject = aSubject.FindF(aSubjectFormat.Left(formatPos - 1));
+ }
+
+ // Need to format the string if the format string is not at the start of
+ // the current subject.
+ if( formatPosInSubject != 0 )
+ {
+ // Create a buffer large enough to hold re-formated subject - need
+ // to subtract two from the prefix length (the %S).
+ length += aSubjectFormat.Length() - 2;
+ HBufC* buf = HBufC::NewLC(length);
+ TPtr ptr(buf->Des());
+
+ // Format the reply subject and set in the email fields.
+ ptr.Format(aSubjectFormat, &aSubject);
+ aEmailFields->SetSubjectL(*buf);
+
+ CleanupStack::PopAndDestroy(buf);
+ }
+ else
+ {
+ // Subject already contains the format string - use it.
+ aEmailFields->SetSubjectL(aSubject);
+ }
+ }
+ }
+
+/**
+The email fields object for this message.
+
+@return
+The email fields object for this message.
+*/
+EXPORT_C const CSmsEmailFields& CSmsHeader::EmailFields() const
+ {
+ return *iEmailFields;
+ }
+
+/**
+Internalises the object from the specified stream.
+
+@param aStream
+The stream to be read from.
+*/
+EXPORT_C void CSmsHeader::InternalizeL(RMsvReadStream& aStream)
+ {
+#if (!defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)
+
+ aStream.ReadInt16L(); //version. Not used yet
+
+ iRecipients.ResetAndDestroy();
+ TInt count=aStream.ReadInt32L();
+ while(count--)
+ {
+ CSmsNumber* recipient=CSmsNumber::NewL();
+ CleanupStack::PushL(recipient);
+ recipient->InternalizeL(aStream);
+ iRecipients.AppendL(recipient);
+ CleanupStack::Pop(recipient);
+ }
+
+ iFlags = aStream.ReadUint32L();
+ iBioMsgIdType = (TBioMsgIdType) aStream.ReadInt8L();
+ iMessage->InternalizeWithoutBufferL(aStream);
+#else
+ iMessage->InternalizeWithoutBufferL(aStream);
+#endif
+ }
+
+/**
+Externalises the object to the specified stream.
+
+@param aStream
+The stream to be writen to.
+*/
+EXPORT_C void CSmsHeader::ExternalizeL(RMsvWriteStream& aStream) const
+ {
+#if (!defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)
+
+ aStream.WriteInt16L(KMsvSmsHeaderVersion);
+
+ TInt count=iRecipients.Count();
+ aStream.WriteInt32L(count);
+
+ for (TInt i=0; i<count; i++)
+ iRecipients[i]->ExternalizeL(aStream);
+
+ aStream.WriteUint32L(iFlags);
+ aStream.WriteInt8L(iBioMsgIdType);
+ iMessage->ExternalizeWithoutBufferL(aStream);
+#else
+ iMessage->ExternalizeWithoutBufferL(aStream);
+#endif
+ }
+
+/**
+Restores the object from the message entry store.
+
+The SMS object is restored from the KUidMsvSMSHeaderStream in the supplied store.
+
+@param aStore
+The store from which the object is restored.
+
+@leave KErrNotFound
+The stream KUidMsvSMSHeaderStream does not exist in aStore.
+*/
+EXPORT_C void CSmsHeader::RestoreL(CMsvStore& aStore)
+ {
+#if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)
+ ReStoreDBL(aStore);
+ RMsvReadStream in;
+ in.OpenLC(aStore,KUidMsvSMSHeaderStream);
+ InternalizeL(in);
+ CleanupStack::PopAndDestroy(&in);
+#else
+
+ RMsvReadStream in;
+ in.OpenLC(aStore,KUidMsvSMSHeaderStream);
+ InternalizeL(in);
+ CleanupStack::PopAndDestroy(&in);
+
+ iEmailFields->RestoreL(aStore);
+
+#endif
+ }
+
+
+/**
+Stores the object in the message entry store.
+
+The object is written to the KUidMsvSMSHeaderStream stream. Any previous content
+is overwritten.
+
+@param aStore
+The store to hold the stream into which the object is written.
+*/
+EXPORT_C void CSmsHeader::StoreL(CMsvStore& aStore) const
+ {
+#if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)
+ StoreDbL(aStore);
+ RMsvWriteStream out;
+ out.AssignLC(aStore,KUidMsvSMSHeaderStream);
+ ExternalizeL(out);
+ out.CommitL();
+ CleanupStack::PopAndDestroy(&out);
+
+#else
+ RMsvWriteStream out;
+ out.AssignLC(aStore,KUidMsvSMSHeaderStream);
+ ExternalizeL(out);
+ out.CommitL();
+ CleanupStack::PopAndDestroy(&out);
+
+ iEmailFields->StoreL(aStore);
+#endif
+ }
+
+
+/**
+Check whether a CMsvStore contains an SMS header stream.
+
+@param aStore The store.
+@return ETrue if there is a SMS header
+*/
+EXPORT_C TBool CSmsHeader::ContainsSmsHeaderL(const CMsvStore& aStore)
+ {
+ return aStore.IsPresentL(KUidMsvSMSHeaderStream);
+ }
+
+CSmsHeader::CSmsHeader(CSmsMessage* aSmsMessage)
+: iRecipients(KSmcmRecipientsGranularity),
+ iMessage(aSmsMessage),
+ iFlags(ESmsHeaderNoFlags),
+ iBioMsgIdType(EBioMsgIdNbs),
+ iCloseFs(ETrue)
+ {
+ }
+
+void CSmsHeader::ConstructL(CSmsPDU::TSmsPDUType aType, CEditableText& aText)
+ {
+ User::LeaveIfError(iFs.Connect());
+ iMessage=CSmsMessage::NewL(iFs, aType, CSmsEditorBuffer::NewL(aText), EFalse);
+ iEmailFields = CSmsEmailFields::NewL();
+ }
+
+void CSmsHeader::ConstructL(CSmsPDU::TSmsPDUType aType, CEditableText& aText, RFs& aFs)
+ {
+ iFs=aFs;
+ iCloseFs = EFalse;
+ iMessage=CSmsMessage::NewL(iFs, aType, CSmsEditorBuffer::NewL(aText), EFalse);
+ iEmailFields = CSmsEmailFields::NewL();
+ }
+
+void CSmsHeader::ConstructL()
+ {
+ iEmailFields = CSmsEmailFields::NewL();
+
+ // Check the PID of the SMS PDU to see if set for interworking with email.
+ CSmsPDU& pdu = Message().SmsPDU();
+ if( pdu.ProtocolIdentifierPresent() &&
+ pdu.PIDType() == TSmsProtocolIdentifier::ESmsPIDTelematicInterworking &&
+ pdu.TelematicDeviceIndicator() == TSmsProtocolIdentifier::ESmsTelematicDevice &&
+ pdu.TelematicDeviceType() == TSmsProtocolIdentifier::ESmsInternetElectronicMail )
+ {
+ __ASSERT_DEBUG( pdu.Type() == CSmsPDU::ESmsDeliver, User::Invariant() );
+
+ // Ok, this is an email SMS - parse out the address and the optional
+ // subject fields.
+ CSmsBufferBase& message = Message().Buffer();
+ TInt length = message.Length();
+ HBufC* buf = HBufC::NewLC(length);
+ TPtr bufPtr(buf->Des());
+ message.Extract(bufPtr, 0, length);
+
+ TInt end = iEmailFields->ParseL(*buf);
+
+ if( end > 0 )
+ {
+ TPtrC body((*buf).Mid(end));
+ message.Reset();
+ message.InsertL(0, body);
+ }
+ CleanupStack::PopAndDestroy(buf);
+ }
+ }
+
+void CSmsHeader::SetCanConcatenate(TBool aCanConcatenate)
+ {
+ iFlags = (iFlags & ~ESmsHeaderCanConcatenate) | (aCanConcatenate ? ESmsHeaderCanConcatenate : ESmsHeaderNoFlags);
+ }
+
+TBool CSmsHeader::CanConcatenate() const
+ {
+ return iFlags & ESmsHeaderCanConcatenate;
+ }
+
+/**
+Gets the summary information for the specified acknowledgement.
+
+If the specified acknowledgement is not recognised, then this function returns
+the default value of TMsvSmsEntryAckSummary::ENoAckSummary.
+nothing.
+
+@param
+aAckType The requested acknowledgement summary.
+
+@return
+The acknowledgement summary information.
+
+@see
+TMsvSmsEntry::TMsvSmsEntryAckSummary
+*/
+EXPORT_C TMsvSmsEntry::TMsvSmsEntryAckSummary TMsvSmsEntry::AckSummary(TSmsAckType aAckType) const
+ {
+ TMsvSmsEntryAckSummary summary = ENoAckSummary;
+ switch( aAckType )
+ {
+ case ESmsAckTypeDelivery:
+ summary = static_cast<TMsvSmsEntryAckSummary>((iMtmData2 & EMsvSmsEntryDeliveryAckSummary) >> EMsvSmsEntryDeliveryAckSummaryShift);
+ break;
+ default:
+ // Use default summary - fail gracefully.
+ break;
+ }
+ return summary;
+ }
+
+/**
+Sets the summary information for the specified acknowlwdgement.
+
+If the specified acknowledgement is not recognised, then this function does
+nothing.
+
+@param
+aAckType The acknowledgement summary to be set.
+
+@param
+aAckSummary The summary information.
+
+@see
+TMsvSmsEntry::TMsvSmsEntryAckSummary
+*/
+EXPORT_C void TMsvSmsEntry::SetAckSummary(TSmsAckType aAckType, TMsvSmsEntryAckSummary aAckSummary)
+ {
+ switch( aAckType )
+ {
+ case ESmsAckTypeDelivery:
+ iMtmData2 = (iMtmData2 & ~EMsvSmsEntryDeliveryAckSummary) | ((aAckSummary << EMsvSmsEntryDeliveryAckSummaryShift) & EMsvSmsEntryDeliveryAckSummary);
+ break;
+ default:
+ // Do nothing - fail gracefully.
+ break;
+ }
+ }
+
+/**
+Gets the message log ID and a flag indicating if it is valid.
+
+The returned flag indicates whether the message log ID is valid. If it is valid
+then the message has only a single recipient that is pending a status report. In
+this case the returned message log ID refers to the recipient that is pending.
+
+If it is not valid then the message has more than one recipient that is pending
+a status report. The message log ID should is not valid and should not be used.
+
+@param
+aMessageId An output argument for the message log ID.
+
+@return
+A flag indicating whether the message log ID aMessageId is valid or not.
+*/
+EXPORT_C TBool TMsvSmsEntry::MessageId(TInt32& aMessageId) const
+ {
+ aMessageId = iMtmData3;
+ return iMtmData2 & EMsvSmsMessageValid;
+ }
+
+/**
+Sets the message log ID and a flag indicating if it is valid.
+
+If the message has only a single recipient that is pending a status report then
+the message log ID for that recipient can be set in the index. The flag must be
+set to true.
+
+If the message has more than one recipient that is pending a status report then
+the message log ID must not be used. The flag must be set to false.
+
+This functionality cannot be used with bio-messages. This function will panic if
+used with a bio-message.
+
+@param
+aMessageId The message log ID. Should only be used if aIsValid is true. It has
+ a default value of zero.
+
+@param
+aIsValid A flag indicating if the message log ID is valid. This should have
+ a value or true if the message has only a single recipient pending
+ a status report.
+
+@panic USER 0
+This message is a bio-message and therefore the message ID field cannot be used.
+*/
+EXPORT_C void TMsvSmsEntry::SetMessageId(TInt32 aMessageId, TBool aIsValid)
+ {
+ __ASSERT_ALWAYS( iBioType == 0, User::Invariant() );
+
+ aIsValid ? (iMtmData2 |= EMsvSmsMessageValid) : (iMtmData2 &= ~EMsvSmsMessageValid);
+ iMtmData3 = aMessageId;
+ }
+
+/**
+Gets the reply to address if it exists, otherwise calls FromAddress().
+
+Only valid for SMS-DELIVER type messages.
+@return
+The reply to address if it exists, otherwise the originator address as returned by FromAddress().
+*/
+TPtrC CSmsHeader::ReplyAddressL() const
+ {
+
+ if(Type()==CSmsPDU::ESmsDeliver)
+ {
+ //Check for a reply address field
+ CSmsReplyAddressOperations& operations = STATIC_CAST(CSmsReplyAddressOperations&,Message().GetOperationsForIEL(CSmsInformationElement::ESmsReplyAddressFormat));
+ if(!operations.ContainsReplyAddressIEL())
+ {
+ //if there is no reply to field call FromAddress()
+ return FromAddress();
+ }
+ //return the reply to address
+ HBufC* replyAddressHBuf=operations.GetReplyAddressL();
+ return replyAddressHBuf->Des();
+ }
+ else
+ {
+ return FromAddress();
+ }
+ }
+
+#if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)
+
+/**
+Stores the object in the message entry store in SQL DB.
+
+The object is written to the KUidMsvSMSHeaderStream stream. Any previous content
+is overwritten.
+
+@param aStore
+The store to hold the stream into which the object is written.
+*/
+
+void CSmsHeader::StoreDbL(CMsvStore& aStore) const
+ {
+ _LIT(KDetails,"");
+
+ CHeaderFields* smsHeaderFields = new(ELeave) CHeaderFields();
+ CleanupStack::PushL(smsHeaderFields);
+ smsHeaderFields->iUid = KUidMsvSMSHeaderStream;
+
+ // 1. Header version field.
+ CFieldPair* smsHeaderVersionfield = new(ELeave) CFieldPair();
+ CleanupStack::PushL(smsHeaderVersionfield);
+ smsHeaderVersionfield->iFieldNumValue = KMsvSmsHeaderVersion;
+ smsHeaderFields->iFieldPairList.AppendL(smsHeaderVersionfield);
+ CleanupStack::Pop(smsHeaderVersionfield);
+
+ // 2. Recipient count field.
+ CFieldPair* smsRecipientCountField = new(ELeave) CFieldPair();
+ CleanupStack::PushL(smsRecipientCountField);
+ smsRecipientCountField->iFieldNumValue = iRecipients.Count();
+ smsHeaderFields->iFieldPairList.AppendL(smsRecipientCountField);
+ CleanupStack::Pop(smsRecipientCountField);
+
+ // 3. Recipients field.
+ TInt size = 0;
+ for (TInt i=0; i < iRecipients.Count(); i++)
+ {
+ size += sizeof(CMsvRecipient::TRecipientStatus);
+ size += 16; // CMsvRecipient::iError (4), iRetries(4) and iTime (8)
+ size += Align4(iRecipients[i]->Address().Size()); // CSmsNumber::iNumber
+ size += Align4(iRecipients[i]->Name().Size()); // CSmsNumber::iName
+ size += sizeof(TLogId); // CSmsNumber::iLogId
+ size += sizeof(CSmsNumber::TSmsAckStatus); // CSmsNumber::iDeliveryStatus
+ size += 10; // For delimiters
+ }
+
+ RBuf recipients;
+ CleanupClosePushL(recipients);
+ recipients.CreateL(size);
+
+ for (TInt i=0; i<iRecipients.Count(); i++)
+ {
+ recipients.AppendNum(iRecipients[i]->Status()); //0
+ recipients.Append(KComma);
+ recipients.AppendNum(iRecipients[i]->Error()); //1
+ recipients.Append(KComma);
+ recipients.AppendNum(iRecipients[i]->Retries()); //2
+ recipients.Append(KComma);
+ recipients.AppendNum(iRecipients[i]->Time().Int64()); //3
+ recipients.Append(KComma);
+
+ recipients.Append(iRecipients[i]->Address()); //4
+ recipients.Append(KComma);
+ recipients.Append(iRecipients[i]->Name()); //5
+ recipients.Append(KComma);
+ recipients.AppendNum(iRecipients[i]->LogId()); //6
+ recipients.Append(KComma);
+ recipients.AppendNum(iRecipients[i]->AckStatus(ESmsAckTypeDelivery)); //7
+ recipients.Append(KDelimiter);
+ }
+
+ CFieldPair* smsRecipientsField = new(ELeave) CFieldPair();
+ CleanupStack::PushL(smsRecipientsField);
+ smsRecipientsField->iFieldTextValue = recipients.AllocL();
+ smsHeaderFields->iFieldPairList.AppendL(smsRecipientsField);
+
+ CleanupStack::Pop(smsRecipientsField); // smsRecipientsField
+ CleanupStack::PopAndDestroy(); // recipients
+
+ // 4. SMS Flag
+ CFieldPair* smsSmsFlags = new(ELeave) CFieldPair();
+ CleanupStack::PushL(smsSmsFlags);
+ smsSmsFlags->iFieldNumValue = iFlags;
+ smsHeaderFields->iFieldPairList.AppendL(smsSmsFlags);
+ CleanupStack::Pop(smsSmsFlags);
+
+ // 5. BIO Msg Id
+ CFieldPair* smsBioMsgIdType = new(ELeave) CFieldPair();
+ CleanupStack::PushL(smsBioMsgIdType);
+ smsBioMsgIdType->iFieldNumValue = iBioMsgIdType;
+ smsHeaderFields->iFieldPairList.AppendL(smsBioMsgIdType);
+ CleanupStack::Pop(smsBioMsgIdType);
+
+
+ CFieldPair* smsdetailField = new (ELeave)CFieldPair();
+ CleanupStack::PushL(smsdetailField);
+ smsdetailField->iFieldName = KDetails().AllocL();
+ smsdetailField->iFieldType = ETextField;
+ smsdetailField->iFieldTextValue = KNullDesC().AllocL();
+ smsHeaderFields->iFieldPairList.AppendL(smsdetailField);
+ CleanupStack::Pop(smsdetailField);
+
+ TMsvWriteStore storeWriter(aStore);
+ storeWriter.AssignL(smsHeaderFields);
+ storeWriter.CommitL();
+
+ CleanupStack::Pop(smsHeaderFields);
+
+ // 6. SMS-Email UID
+ // 7. SMS-EMail HeaderVersion
+ // 8. Subject
+ // 9. AddressCount
+ // 10. Addresses
+
+ iEmailFields->StoreDBL(aStore);
+
+ }
+
+/**
+Restores the object from the message entry store in SQL DB.
+
+The SMS object is restored from the KUidMsvSMSHeaderStream in the supplied store.
+
+@param aStore
+The store from which the object is restored.
+
+@leave KErrNotFound
+The stream KUidMsvSMSHeaderStream does not exist in aStore.
+*/
+
+void CSmsHeader::ReStoreDBL(CMsvStore& aStore)
+ {
+
+ CHeaderFields* rcvHeaderRow = NULL;
+ TMsvReadStore storeReader(aStore, KUidMsvSMSHeaderStream);
+ storeReader.LoadL(rcvHeaderRow);
+
+
+ iRecipients.ResetAndDestroy();
+
+ TInt i = 0;
+ CFieldPair* rcvHeader = rcvHeaderRow->iFieldPairList[i];
+
+ TInt16 headerversion = rcvHeaderRow->iFieldPairList[i++]->iFieldNumValue; // header version.
+ TInt count = rcvHeaderRow->iFieldPairList[i++]->iFieldNumValue;
+
+ HBufC* receipientList = rcvHeaderRow->iFieldPairList[i++]->iFieldTextValue->Des().AllocL();
+ CleanupStack::PushL(receipientList);
+
+ TPtrC receipientListPtr = receipientList->Des();
+ GetRecipientL(receipientListPtr);
+
+ iFlags = rcvHeaderRow->iFieldPairList[i++]->iFieldNumValue;
+ iBioMsgIdType = (TBioMsgIdType)rcvHeaderRow->iFieldPairList[i++]->iFieldNumValue ;
+
+ CleanupStack::PopAndDestroy(receipientList);
+
+ iEmailFields->ReStoreDBL(aStore);
+
+ }
+
+/**
+Get the recipient strring and Create the recipient.
+
+@param : aRecipientStr A TPtrC16.
+@return None.
+*/
+void CSmsHeader::GetRecipientL(TDesC16& aRecipientStrList)
+ {
+ TPtrC16 aRecipientStr = aRecipientStrList.Left(aRecipientStrList.Length());
+
+ if(aRecipientStr.Length()>0)
+ {
+ RArray<TPtrC16> smsNumberData;
+ TInt startPos = 0;
+ TInt firstSemiColonPos = aRecipientStr.Locate(';');
+ TInt lastSemiColonPos = aRecipientStr.LocateReverse(';');
+
+ do
+ {
+ CSmsNumber* recipientNumber=CSmsNumber::NewL();
+ TPtrC16 str1 = aRecipientStr.Left(firstSemiColonPos+1); // First recipient
+ startPos = str1.Locate(',') ;
+
+ while(startPos != KErrNotFound )
+ {
+ TPtrC16 str2 = str1.Left(startPos);
+ smsNumberData.Append(str2);
+
+ startPos++;
+ str1.Set(str1.Mid(startPos, str1.Length()- startPos));
+
+ startPos = str1.Locate(',');
+ if(startPos == KErrNotFound)
+ {
+ TPtrC16 str3;
+ str3.Set(str1.Mid(0,str1.Length()-1));
+ smsNumberData.Append(str3);
+ break;
+ }
+
+ }
+
+ recipientNumber->SetStatus((CMsvRecipient::TRecipientStatus)ConvertToTInt(smsNumberData[0]));
+ recipientNumber->SetError(ConvertToTInt(smsNumberData[1]));
+ recipientNumber->SetRetries(ConvertToTInt(smsNumberData[2]));
+ TInt64 time = ConvertToTInt(smsNumberData[3]);
+ recipientNumber->SetTimeValue(time);
+
+ //CSmsNumber
+ recipientNumber->SetAddressL(smsNumberData[4]);
+ recipientNumber->SetNameL(smsNumberData[5]);
+
+ TLex logId(smsNumberData[6]);
+ TInt32 logIdNum;
+ logId.Val(logIdNum);
+ recipientNumber->SetLogId(logIdNum);
+
+ TLex ackStatus(smsNumberData[7]);
+ TInt32 ackStatusNum;
+ recipientNumber->SetAckStatus( (TSmsAckType) ackStatus.Val(ackStatusNum), CSmsNumber::ENoAckRequested);
+
+ iRecipients.AppendL(recipientNumber);
+ smsNumberData.Reset();
+
+ if(firstSemiColonPos != lastSemiColonPos)
+ {
+ aRecipientStr.Set(aRecipientStr.Mid(firstSemiColonPos+1,aRecipientStr.Length()-firstSemiColonPos-1));
+ firstSemiColonPos = aRecipientStr.Locate(';');
+ lastSemiColonPos = aRecipientStr.LocateReverse(';');
+ }
+ else
+ {
+ break;
+ }
+
+ }while(1);
+
+ smsNumberData.Close();
+ }
+ }
+
+
+/**
+ * Convert a String to an Integer.
+ * @param aStr A string to make Integer.
+ * @return TInt A integer value
+ */
+ TInt CSmsHeader::ConvertToTInt(TDesC16& aStr)
+ {
+ TLex str(aStr);
+ TInt32 string;
+ str.Val(string);
+ return string;
+ }
+
+#endif