--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mobilemessaging/unieditor/smsplugin/src/UniSmsPlugin.cpp Thu Dec 17 08:44:11 2009 +0200
@@ -0,0 +1,1841 @@
+/*
+* Copyright (c) 2005-2008 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:
+* Provides UniEditor SMS Plugin methods.
+*
+*/
+
+
+
+
+// INCLUDE FILES
+
+// Symbian:
+#include <e32base.h>
+#include <implementationproxy.h>
+#include <ecom.h>
+#include <txtetext.h>
+#include <txtrich.h>
+
+#include <mmsvattachmentmanager.h>
+#include <mmsvattachmentmanagersync.h>
+#include <gsmerror.h> // KErrGsmOfflineOpNotAllowed
+#include <featmgr.h>
+
+#include <mtclreg.h>
+#include <smsclnt.h>
+#include <smscmds.h>
+#include <smuthdr.h>
+#include <csmsemailfields.h>
+#include <csmsaccount.h>
+#include <charconv.h>
+#include <smut.h>
+#include <smumutil.h>
+#include <cmsvmimeheaders.h>
+#include <badesca.h>
+#include <e32cmn.h>
+#include <muiumsvuiserviceutilitiesinternal.h>
+#include <gsmuset.h>
+
+// S60
+#include <mmsgenutils.h>
+#include <MuiuOperationWait.h>
+#include <vcard.h>
+#include <SenduiMtmUids.h>
+#include <MsgBioUids.h>
+#include <MsgMimeTypes.h>
+#include "UniSendingSettings.h"
+#include "UniClientMtm.h"
+#include "UniEditorUids.hrh"
+#include "messagingvariant.hrh"
+#include "UniSmsPlugin.h"
+#include "UniSmsUtils.h"
+#include "MsgAttachmentUtils.h"
+#include "UniMsvEntry.h"
+
+// resources
+#include <UniSmsPluginD.rsg>
+#include <avkon.rsg>
+
+//LOGGING
+#include "UniEditorLogging.h"
+
+// CONSTANTS
+const TImplementationProxy KImplementationTable[] =
+ {
+ IMPLEMENTATION_PROXY_ENTRY( KUidUniEditorSmsPlugin, CUniSmsPlugin::NewL)
+ };
+
+// Used to set msg in unparsed state
+const TInt KSmsPluginBioMsgUnparsed = 0;
+
+// Description length for sms messages
+const TInt KSmsMessageEntryDescriptionAmountOfChars = 60;
+
+//used for descriptor array containing recipients
+const TInt KRecipientsArrayGranularity = 8;
+
+// For address information separation (start)
+const TUint KMsgSmsAddressStartChar ('<');
+
+// For address information separation (end)
+const TUint KMsgSmsAddressEndChar ('>');
+
+const TUint KUniSmsStartParenthesis ('(');
+const TUint KUniSmsEndParenthesis (')');
+
+// String length for Service centre name
+const TInt KUniSmsSCStringLength = 50;
+
+const TUid KUidMsvSMSHeaderStream_COPY_FROM_SMUTHDR_CPP = {0x10001834};
+
+// Amount of to be converted chars during extracting description
+const TInt KSmsEdExtrDescReplaceCharacterCount = 3;
+
+// Unicode char for linefeed regocnised by basic phones
+const TUint KSmsEdUnicodeLFSupportedByBasicPhones = 0x000A;
+// ========== LOCAL FUNCTIONS ==================================================
+GLDEF_C void Panic( TInt aCategory );
+
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CUniSmsPlugin* CUniSmsPlugin::NewL( TAny* aConstructionParameters )
+ {
+ TUniPluginParams* params = reinterpret_cast<TUniPluginParams*>( aConstructionParameters );
+ CUniSmsPlugin* self = new ( ELeave ) CUniSmsPlugin( params->iSession, params->iUniMtm );
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+// -----------------------------------------------------------------------------
+// Destructor
+// -----------------------------------------------------------------------------
+//
+CUniSmsPlugin::~CUniSmsPlugin()
+ {
+ delete iRichText;
+ delete iParaFormatLayer;
+ delete iCharFormatLayer;
+ delete iSmsHeader;
+ delete iSmsMtm;
+ delete iMtmRegistry;
+ delete iEmailOverSmsC;
+ delete iRecipients;
+ }
+
+// -----------------------------------------------------------------------------
+// C++ default constructor
+// -----------------------------------------------------------------------------
+//
+CUniSmsPlugin::CUniSmsPlugin( CMsvSession& aSession, CUniClientMtm& aUniMtm )
+ : iSession( aSession ),
+ iUniMtm( aUniMtm ),
+ iBioMsg( EFalse ),
+ iOfflineSupported( EFalse )
+ {
+ }
+
+// -----------------------------------------------------------------------------
+// Symbian 2nd phase constructor
+// -----------------------------------------------------------------------------
+//
+void CUniSmsPlugin::ConstructL()
+ {
+ UNILOGGER_ENTERFN("CUniSmsPlugin::ConstructL");
+ iParaFormatLayer = CParaFormatLayer::NewL();
+ iCharFormatLayer = CCharFormatLayer::NewL();
+ iRichText = CRichText::NewL( iParaFormatLayer, iCharFormatLayer );
+ iEmailOverSmsC = CSmsNumber::NewL();
+
+ CMsvEntry& entry = SmsMtmL()->Entry();
+ entry.SetEntryL( KMsvRootIndexEntryId );
+
+ TSmsUtilities::ServiceIdL( entry, iSmsServiceId );
+
+ FeatureManager::InitializeLibL();
+ if ( FeatureManager::FeatureSupported( KFeatureIdOfflineMode ) )
+ {
+ iOfflineSupported = ETrue;
+ }
+ else
+ {
+ iOfflineSupported = EFalse;
+ }
+
+ //Turkish SMS-PREQ2265 Specific
+ if ( FeatureManager::FeatureSupported( KFeatureIdNltSupport ) )
+ {
+ iNLTFeatureSupport = ETrue;
+ }
+ else
+ {
+ iNLTFeatureSupport = EFalse;
+ }
+
+ FeatureManager::UnInitializeLib();
+
+ UNILOGGER_LEAVEFN("CUniSmsPlugin::ConstructL");
+ }
+
+// -----------------------------------------------------------------------------
+// LoadHeadersL
+// -----------------------------------------------------------------------------
+//
+void CUniSmsPlugin::LoadHeadersL( CMsvStore* aStore )
+ {
+ UNILOGGER_ENTERFN("CUniSmsPlugin::LoadHeadersL");
+ delete iSmsHeader;
+ iSmsHeader = NULL;
+
+ if ( aStore && aStore->HasBodyTextL() )
+ {
+ aStore->RestoreBodyTextL( *iRichText );
+ }
+
+ iSmsHeader = CSmsHeader::NewL( CSmsPDU::ESmsSubmit, *iRichText );
+
+ if ( aStore && aStore->IsPresentL( KUidMsvSMSHeaderStream_COPY_FROM_SMUTHDR_CPP ) )
+ {
+ iSmsHeader->RestoreL( *aStore );
+ }
+ else
+ {
+ CSmsSettings* settings = CSmsSettings::NewLC();
+ CSmsAccount* account = CSmsAccount::NewLC();
+ account->LoadSettingsL( *settings );
+ CleanupStack::PopAndDestroy( account );
+ iSmsHeader->SetSmsSettingsL( *settings );
+ CleanupStack::PopAndDestroy( settings );
+ }
+ TSmsUserDataSettings smsSettings;
+ smsSettings.SetTextCompressed( EFalse );
+ TRAP_IGNORE(iSmsHeader->Message().SetUserDataSettingsL( smsSettings ));
+ UNILOGGER_LEAVEFN("CUniSmsPlugin::LoadHeadersL");
+ }
+
+// -----------------------------------------------------------------------------
+// SaveHeadersL
+// -----------------------------------------------------------------------------
+//
+void CUniSmsPlugin::SaveHeadersL( CMsvStore& aStore )
+ {
+ if ( iSmsHeader )
+ {
+ iSmsHeader->StoreL( aStore );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// ConvertFromL
+// -----------------------------------------------------------------------------
+//
+TMsvId CUniSmsPlugin::ConvertFromL( TMsvId aId )
+ {
+ return DoConvertFromL( aId, EFalse );
+ }
+
+// -----------------------------------------------------------------------------
+// DoConvertFromL
+// -----------------------------------------------------------------------------
+//
+TMsvId CUniSmsPlugin::DoConvertFromL( TMsvId aId, TBool aIsForward )
+ {
+ UNILOGGER_ENTERFN("CUniSmsPlugin::ConvertFromL");
+ UNILOGGER_WRITE_TIMESTAMP("CUniSmsPlugin::ConvertFromL start");
+ SmsMtmL()->SwitchCurrentEntryL( aId );
+ SmsMtmL()->LoadMessageL();
+ iUniMtm.SwitchCurrentEntryL( aId );
+ iUniMtm.LoadMessageL();
+
+ TPtrC name;
+ TPtrC address;
+
+ const CSmsEmailFields& emailFields = SmsMtmL( )->SmsHeader( ).EmailFields();
+
+ if( emailFields.HasAddress( ) && !aIsForward )
+ { // If email address set -> copy them here
+ const MDesCArray& emailRecipients = emailFields.Addresses();
+ for( TInt id = 0; id < emailRecipients.MdcaCount( ); id++ )
+ {
+ NameAndAddress( emailRecipients.MdcaPoint( id ), name, address );
+ iUniMtm.AddAddresseeL(
+ EMsvRecipientTo,
+ address,
+ name );
+ }
+ }
+
+ // Copy non-email over sms addresses if needed
+ const CMsvRecipientList& smsRecipients = SmsMtmL()->AddresseeList();
+
+ while ( smsRecipients.Count() )
+ { // Go thru all the recipients
+ if( !emailFields.HasAddress( ) && !aIsForward )
+ { // and copy them only if email addresses did not exist
+ NameAndAddress( smsRecipients[ 0 ], name, address );
+ iUniMtm.AddAddresseeL(
+ EMsvRecipientTo,
+ address,
+ name );
+ }
+ SmsMtmL()->RemoveAddressee( 0 );
+ }
+
+ if( emailFields.Subject( ).Length( ) )
+ { // If email subject exists -> copy it
+ iUniMtm.SetSubjectL( emailFields.Subject( ) );
+ }
+
+ //Get sms entry
+ TMsvEntry smsTEntry = SmsMtmL()->Entry().Entry();
+
+ if ( smsTEntry.iBioType == KMsgBioUidVCard.iUid
+ || smsTEntry.iBioType == KMsgBioUidVCalendar.iUid )
+ {
+ //We must check here if there is two attachments. This happens in case
+ //if sending fails and message opened from drafts
+ CMsvStore* store = iUniMtm.Entry().EditStoreL();
+ CleanupStack::PushL( store );
+ MMsvAttachmentManagerSync& managerSync = store->AttachmentManagerExtensionsL();
+ MMsvAttachmentManager& manager = store->AttachmentManagerL();
+ if ( manager.AttachmentCount() == 2)
+ {
+ managerSync.RemoveAttachmentL( 1 );
+ }
+ store->CommitL();
+ CleanupStack::PopAndDestroy( store );
+ }
+ else //plain text
+ {
+ TInt totalLength( SmsMtmL()->Body().DocumentLength() );
+ if ( totalLength > 0 )
+ {
+ HBufC* bodyText = HBufC::NewLC ( totalLength );
+ TPtr bodyTextPtr ( bodyText->Des() );
+
+ SmsMtmL()->Body().Extract( bodyTextPtr, 0, totalLength );
+
+ iUniMtm.Body().InsertL( 0, bodyTextPtr );
+
+ CleanupStack::PopAndDestroy( bodyText );
+ }
+ }
+
+ SmsMtmL()->Body().Reset();
+
+ SmsMtmL()->SaveMessageL();
+ TMsvEntry uniTEntry = iUniMtm.Entry().Entry();
+
+ iUniMtm.SaveMessageL();
+
+ // Lets convert the bits to Uni mode
+ TUniMsvEntry::SetForwardedMessage( uniTEntry, aIsForward );
+
+ uniTEntry.iMtm.iUid = KUidUniMtm;
+ iUniMtm.Entry().ChangeL( uniTEntry );
+ UNILOGGER_LEAVEFN("CUniSmsPlugin::ConvertFromL");
+ UNILOGGER_WRITE_TIMESTAMP("CUniSmsPlugin::ConvertFromL end");
+ return aId;
+ }
+
+// -----------------------------------------------------------------------------
+// ConvertToL
+// -----------------------------------------------------------------------------
+//
+TMsvId CUniSmsPlugin::ConvertToL( TMsvId aId )
+ {
+ UNILOGGER_ENTERFN("CUniSmsPlugin::ConvertToL");
+ SmsMtmL()->SwitchCurrentEntryL( aId );
+ SmsMtmL()->LoadMessageL();
+ iUniMtm.SwitchCurrentEntryL( aId );
+ iUniMtm.LoadMessageL();
+
+ const CMsvRecipientList& uniRecipients = iUniMtm.AddresseeList();
+
+ //Save for email over sms
+ if ( iRecipients )
+ {
+ delete iRecipients;
+ iRecipients = NULL;
+ }
+ iRecipients = new ( ELeave ) CDesCArrayFlat( KRecipientsArrayGranularity );
+
+ CSmsEmailFields *emailFields = CSmsEmailFields::NewL();
+ CleanupStack::PushL( emailFields );
+
+ while ( uniRecipients.Count() )
+ {
+ if ( IsEmailAddress( TMmsGenUtils::PureAddress( uniRecipients[ 0 ] )))
+ {
+ emailFields->AddAddressL( TMmsGenUtils::PureAddress( uniRecipients[ 0 ] ) );
+ }
+ else
+ {
+ SmsMtmL()->AddAddresseeL(
+ TMmsGenUtils::PureAddress( uniRecipients[ 0 ] ),
+ TMmsGenUtils::Alias( uniRecipients[ 0 ] ) );
+ }
+
+ iRecipients->AppendL( uniRecipients[ 0 ] );
+ iUniMtm.RemoveAddressee( 0 );
+ }
+ if ( iUniMtm.SubjectL().Length() )
+ {
+ emailFields->SetSubjectL( iUniMtm.SubjectL() );
+ }
+
+ SmsMtmL()->SmsHeader().SetEmailFieldsL( *emailFields );
+ CleanupStack::PopAndDestroy( emailFields );
+
+ CMsvStore* store = iUniMtm.Entry().EditStoreL();
+ CleanupStack::PushL( store );
+ MMsvAttachmentManager& manager = store->AttachmentManagerL();
+ MMsvAttachmentManagerSync& managerSync = store->AttachmentManagerExtensionsL();
+ TUid bioType =
+ {
+ 0
+ };
+
+ CMsvAttachment* atta ( NULL );
+ switch ( manager.AttachmentCount() )
+ {
+ case 0:
+ {
+ //In case of empty message.
+ //There is not even smil.
+ SmsMtmL()->Body().Reset();
+ break;
+ }
+ case 1:
+ {
+ atta = manager.GetAttachmentInfoL( 0 );
+ if ( atta->MimeType() == KMsgMimeSmil )
+ {
+ managerSync.RemoveAttachmentL( 0 );
+ delete atta;
+ atta= NULL;
+ }
+ else
+ CleanupStack::PushL(atta);
+ break;
+ }
+ case 2: //There is usually a SMIL also.
+ {
+ //In these case branch we assume that there is only one text atta
+ //or one text atta and a SMIL
+ //Everything else is a programming error in the caller
+
+ CMsvAttachment* tempAtta1 = manager.GetAttachmentInfoL( 0 );
+ CleanupStack::PushL(tempAtta1);
+ CMsvAttachment* tempAtta2 = manager.GetAttachmentInfoL( 1 );
+ CleanupStack::PushL(tempAtta2);
+
+ if ( tempAtta1->MimeType() == KMsgMimeSmil )
+ {
+ CleanupStack::Pop( tempAtta2 );
+ CleanupStack::PopAndDestroy( tempAtta1 );
+ CleanupStack::PushL( tempAtta2 );
+
+ managerSync.RemoveAttachmentL( 0 );
+ atta=tempAtta2;
+ }
+ else if ( tempAtta2->MimeType() == KMsgMimeSmil )
+ {
+ CleanupStack::PopAndDestroy( tempAtta2 );
+ managerSync.RemoveAttachmentL( 1 );
+ atta=tempAtta1;
+ }
+ else
+ {
+ //Programming error in caller code
+#ifdef _DEBUG
+ UNILOGGER_WRITEF(_L("PANIC: Two attas but no smil"));
+ Panic ( EIllegalArguments );
+#endif
+ User::Leave( KErrArgument );
+
+ }
+ break;
+ }
+ default:
+ {
+ //Programming error in caller code
+#ifdef _DEBUG
+ UNILOGGER_WRITEF(_L("PANIC: Two many attas"));
+ Panic ( EIllegalArguments );
+#endif
+ User::Leave( KErrArgument );
+ break;
+ }
+ }
+
+ if ( atta )
+ {
+ UNILOGGER_WRITEF8(_L8("Mime Type: %S"),&(atta->MimeType()));
+ UNILOGGER_WRITEF(_L("Atta Name: %S"),&(atta->AttachmentName()));
+
+ RFile file = manager.GetAttachmentFileL( 0 );
+ CleanupClosePushL( file );
+
+ //Note that the attachments is not removed in case of smart messaging
+ if ( atta->MimeType().CompareF( KMsgMimeTextPlain ) == 0 )
+ {
+ iBioMsg=EFalse;
+ CreatePlainTextSMSL( file );
+ managerSync.RemoveAttachmentL( 0 );
+ }
+ else if ( atta->MimeType().CompareF(KMsgMimeVCard) == 0 )
+ {
+ iBioMsg=ETrue;
+ CreateVCardSMSL( file );
+ bioType = KMsgBioUidVCard;
+ SmsMtmL()->BioTypeChangedL( bioType );
+ //Do not remove vCard atta here.
+ }
+ else if ( atta->MimeType().CompareF(KMsgMimeVCal ) == 0 ||
+ atta->MimeType().CompareF(KMsgMimeICal ) == 0 )
+ {
+ iBioMsg=ETrue;
+ CreateVCalSMSL( file );
+ bioType = KMsgBioUidVCalendar;
+ SmsMtmL()->BioTypeChangedL( bioType );
+ //Do not remove vCal atta here.
+ }
+ else
+ {
+ User::Leave( KErrArgument );
+ }
+ CleanupStack::PopAndDestroy( &file );
+ CleanupStack::PopAndDestroy( atta );
+ }
+
+ TMsvEntry tEntry = SmsMtmL()->Entry().Entry();
+ tEntry.SetAttachment( EFalse );
+ tEntry.iMtm = KSenduiMtmSmsUid;
+ tEntry.iType = KUidMsvMessageEntry;
+ tEntry.iRelatedId = iSmsServiceId;
+ tEntry.iServiceId = KMsvLocalServiceIndexEntryId;
+ tEntry.iDate.UniversalTime();
+ tEntry.SetInPreparation( ETrue );
+ tEntry.SetVisible( EFalse );
+
+ CSmsSettings* sendOptions = CSmsSettings::NewL();
+ CleanupStack::PushL( sendOptions );
+
+ // "ConvertToL" might be called right after constructor.
+ // In this case iSmsHeader is still NULL. Need to initialise.
+ if ( !iSmsHeader )
+ {
+ LoadHeadersL( store );
+ }
+ iSmsHeader->GetSmsSettingsL( *sendOptions );
+
+ sendOptions->CopyL( *sendOptions );
+
+ if ( !iBioMsg )
+ {
+ if( iUnicodeMode )
+ {
+ sendOptions->SetCharacterSet( TSmsDataCodingScheme::ESmsAlphabetUCS2 );
+ }
+ else
+ {
+ sendOptions->SetCharacterSet( TSmsDataCodingScheme::ESmsAlphabet7Bit );
+ }
+ }
+ else
+ {
+ // make sure bio messages have no conversion
+ tEntry.iBioType = bioType.iUid;
+ sendOptions->SetMessageConversion( ESmsConvPIDNone );
+ sendOptions->SetCharacterSet( TSmsDataCodingScheme::ESmsAlphabet8Bit );
+ }
+
+ // Update some global SMS settings affecting all messages.
+ // These might have changed from the ones retrieved when
+ // the message was created and so needs to be updated.
+ CSmsSettings* defaultSettings = CSmsSettings::NewLC();
+
+ CSmsAccount* account = CSmsAccount::NewLC();
+ account->LoadSettingsL( *defaultSettings );
+ CleanupStack::PopAndDestroy( account );
+
+ sendOptions->SetDeliveryReport( defaultSettings->DeliveryReport() );
+ sendOptions->SetSmsBearer( defaultSettings->SmsBearer() );
+ sendOptions->SetValidityPeriod( defaultSettings->ValidityPeriod() );
+ sendOptions->SetReplyPath( defaultSettings->ReplyPath() );
+
+ CleanupStack::PopAndDestroy( defaultSettings );
+
+ iSmsHeader->SetSmsSettingsL( *sendOptions );
+
+ // Move all the stuff from iSmsHeader::SmsSettings to SmsMtm::SmsHeader::SmsSettings
+ SmsMtmL()->SmsHeader( ).SetSmsSettingsL( *sendOptions );
+ SmsMtmL()->SmsHeader( ).Message( ).
+ SetServiceCenterAddressL( iSmsHeader->Message( ).ServiceCenterAddress( ) );
+
+ if(iNLTFeatureSupport)
+ {
+ //Turkish SMS-PREQ2265 Specific
+ TSmsEncoding currAlternateEncoding = iSmsHeader->Message().Alternative7bitEncoding();
+ SmsMtmL()->SmsHeader().Message().SetAlternative7bitEncoding(currAlternateEncoding);
+ }
+
+ CleanupStack::PopAndDestroy( sendOptions );
+
+ SmsMtmL()->Entry().ChangeL( tEntry );
+
+ store->CommitL();
+ CleanupStack::PopAndDestroy( store );
+
+ iUniMtm.SaveMessageL();
+ SmsMtmL()->SaveMessageL();
+ UNILOGGER_LEAVEFN("CUniSmsPlugin::ConvertToL");
+ return aId;
+ }
+
+// -----------------------------------------------------------------------------
+// CreateReplyL
+// -----------------------------------------------------------------------------
+//
+TMsvId CUniSmsPlugin::CreateReplyL( TMsvId aSrc, TMsvId aDest, TMsvPartList aParts )
+ {
+ return DoCreateReplyOrForwardL( ETrue, aSrc, aDest, aParts );
+ }
+
+// -----------------------------------------------------------------------------
+// CreateForwardL
+// -----------------------------------------------------------------------------
+//
+TMsvId CUniSmsPlugin::CreateForwardL( TMsvId aSrc, TMsvId aDest, TMsvPartList aParts )
+ {
+ return DoCreateReplyOrForwardL( EFalse, aSrc, aDest, aParts );
+ }
+
+// -----------------------------------------------------------------------------
+// SendL
+// -----------------------------------------------------------------------------
+//
+void CUniSmsPlugin::SendL( TMsvId aId )
+ {
+ UNILOGGER_ENTERFN("CUniSmsPlugin::SendL");
+ SmsMtmL()->SwitchCurrentEntryL( aId );
+ SmsMtmL()->LoadMessageL();
+ MoveMessagesToOutboxL();
+ UNILOGGER_LEAVEFN("CUniSmsPlugin::SendL");
+ }
+
+// -----------------------------------------------------------------------------
+// ValidateServiceL
+// -----------------------------------------------------------------------------
+//
+TBool CUniSmsPlugin::ValidateServiceL( TBool aEmailOverSms )
+ {
+ TBool valid = ValidateSCNumberL();
+
+ if ( aEmailOverSms )
+ {
+ valid = ValidateSCNumberForEmailOverSmsL();
+ }
+
+ return valid;
+ }
+
+// -----------------------------------------------------------------------------
+// GetSendingSettingsL
+// -----------------------------------------------------------------------------
+//
+void CUniSmsPlugin::GetSendingSettingsL( TUniSendingSettings& aSettings )
+ {
+ // Modify only the settings this mtm plugin supports
+ CSmsSettings* smsSettings = CSmsSettings::NewLC();
+ iSmsHeader->GetSmsSettingsL( *smsSettings );
+
+ switch ( smsSettings->ValidityPeriod().Int() )
+ {
+ case ESmsVPHour:
+ aSettings.iValidityPeriod = TUniSendingSettings::EUniValidityPeriod1h;
+ break;
+ case ESmsVPSixHours:
+ aSettings.iValidityPeriod = TUniSendingSettings::EUniValidityPeriod6h;
+ break;
+ case (3 * (TInt) ESmsVP24Hours):
+ aSettings.iValidityPeriod = TUniSendingSettings::EUniValidityPeriod3Days;
+ break;
+ case ESmsVPWeek:
+ aSettings.iValidityPeriod = TUniSendingSettings::EUniValidityPeriodWeek;
+ break;
+ case ESmsVPMaximum:
+ aSettings.iValidityPeriod = TUniSendingSettings::EUniValidityPeriodMax;
+ break;
+ default: // default to 24h
+ case ESmsVP24Hours:
+ aSettings.iValidityPeriod = TUniSendingSettings::EUniValidityPeriod24h;
+ break;
+ }
+
+ switch( smsSettings->MessageConversion( ) )
+ {
+ case ESmsConvFax:
+ aSettings.iMessageType = TUniSendingSettings::EUniMessageTypeFax;
+ break;
+ case ESmsConvPaging:
+ aSettings.iMessageType = TUniSendingSettings::EUniMessageTypePaging;
+ break;
+ default: // any other is text
+ aSettings.iMessageType = TUniSendingSettings::EUniMessageTypeText;
+ break;
+ }
+
+ aSettings.iDeliveryReport = smsSettings->DeliveryReport();
+ aSettings.iReplyViaSameCentre = smsSettings->ReplyPath();
+ CleanupStack::PopAndDestroy( smsSettings );
+ }
+
+
+
+
+// -----------------------------------------------------------------------------
+// SetSendingSettingsL
+// -----------------------------------------------------------------------------
+//
+void CUniSmsPlugin::SetSendingSettingsL( TUniSendingSettings& aSettings )
+ {
+ CSmsSettings* smsSettings = CSmsSettings::NewLC();
+ iSmsHeader->GetSmsSettingsL( *smsSettings );
+
+ TTimeIntervalMinutes validityPeriod = smsSettings->ValidityPeriod().Int();
+ switch ( aSettings.iValidityPeriod )
+ {
+ case TUniSendingSettings::EUniValidityPeriod1h:
+ validityPeriod = ( TInt ) ESmsVPHour;
+ break;
+ case TUniSendingSettings::EUniValidityPeriod6h:
+ validityPeriod = ( TInt ) ESmsVPSixHours;
+ break;
+ case TUniSendingSettings::EUniValidityPeriod3Days:
+ validityPeriod = ( 3 * ( TInt ) ESmsVP24Hours );// Instead of modifying smutset.h
+ break;
+ case TUniSendingSettings::EUniValidityPeriodWeek:
+ validityPeriod = ( TInt ) ESmsVPWeek;
+ break;
+ case TUniSendingSettings::EUniValidityPeriodMax:
+ validityPeriod = ( TInt ) ESmsVPMaximum;
+ break;
+ default: // default to 24h
+ case TUniSendingSettings::EUniValidityPeriod24h:
+ validityPeriod = ( TInt ) ESmsVP24Hours;
+ break;
+ }
+ switch( aSettings.iMessageType )
+ {
+ case TUniSendingSettings::EUniMessageTypeFax:
+ smsSettings->SetMessageConversion( ESmsConvFax );
+ break;
+ case TUniSendingSettings::EUniMessageTypePaging:
+ smsSettings->SetMessageConversion( ESmsConvPaging );
+ break;
+ default: // any other is text
+ smsSettings->SetMessageConversion( ESmsConvPIDNone );
+ break;
+ }
+
+ smsSettings->SetValidityPeriod( validityPeriod );
+ smsSettings->SetDeliveryReport( aSettings.iDeliveryReport );
+ smsSettings->SetReplyPath( aSettings.iReplyViaSameCentre );
+
+ iSmsHeader->SetSmsSettingsL( *smsSettings );
+ CleanupStack::PopAndDestroy( smsSettings );
+ }
+
+// -----------------------------------------------------------------------------
+// IsServiceValidL
+// -----------------------------------------------------------------------------
+//
+TBool CUniSmsPlugin::IsServiceValidL()
+ {
+ // Not implemented.
+ return ETrue;
+ }
+
+
+// -----------------------------------------------------------------------------
+// SmsMtmL
+// -----------------------------------------------------------------------------
+//
+CSmsClientMtm* CUniSmsPlugin::SmsMtmL()
+ {
+ if ( !iSmsMtm )
+ {
+ if ( !iMtmRegistry )
+ {
+ iMtmRegistry = CClientMtmRegistry::NewL( iSession );
+ }
+ iSmsMtm = static_cast<CSmsClientMtm*>( iMtmRegistry->NewMtmL( KSenduiMtmSmsUid ) );
+ }
+ return iSmsMtm;
+ }
+
+// -----------------------------------------------------------------------------
+// DoCreateReplyOrForwardL
+// -----------------------------------------------------------------------------
+//
+TMsvId CUniSmsPlugin::DoCreateReplyOrForwardL(
+ TBool aReply,
+ TMsvId aSrc,
+ TMsvId aDest,
+ TMsvPartList aParts )
+ {
+ SmsMtmL()->SwitchCurrentEntryL( aSrc );
+
+ CMuiuOperationWait* wait = CMuiuOperationWait::NewLC();
+
+ CMsvOperation* oper = aReply
+ ? SmsMtmL()->ReplyL( aDest, aParts, wait->iStatus )
+ : SmsMtmL()->ForwardL( aDest, aParts, wait->iStatus );
+
+ CleanupStack::PushL( oper );
+ wait->Start();
+
+ TMsvId newId;
+ TPckgC<TMsvId> paramPack( newId );
+ const TDesC8& progress = oper->FinalProgress();
+ paramPack.Set( progress );
+ newId = paramPack();
+ CleanupStack::PopAndDestroy( oper );
+ CleanupStack::PopAndDestroy( wait );
+
+ return DoConvertFromL( newId, !aReply );
+ }
+
+// ----------------------------------------------------------------------------
+// MoveMessagesToOutboxL
+// ----------------------------------------------------------------------------
+void CUniSmsPlugin::MoveMessagesToOutboxL()
+ {
+ if ( !iRecipients || !iRecipients->Count() )
+ {
+ User::Leave( KErrGeneral );
+ }
+
+ //we must create an entry selection for message copies
+ CMsvEntrySelection* selection = new ( ELeave ) CMsvEntrySelection;
+ CleanupStack::PushL( selection );
+
+ CMsvEntry& entry = SmsMtmL()->Entry();
+ TMsvEntry msvEntry( entry.Entry() );
+
+ if ( iOfflineSupported && MsvUiServiceUtilitiesInternal::IsPhoneOfflineL() )
+ {
+ msvEntry.SetSendingState( KMsvSendStateSuspended );
+ msvEntry.iError = KErrGsmOfflineOpNotAllowed;
+ }
+ else
+ {
+ msvEntry.SetSendingState( KMsvSendStateWaiting );
+ }
+
+ CSmsHeader& header = SmsMtmL()->SmsHeader();
+ TBuf<KSmsMessageEntryDescriptionAmountOfChars> buf;
+
+ if (!iBioMsg )
+ {
+ ExtractDescriptionFromMessageL(
+ header.Message(),
+ buf,
+ KSmsMessageEntryDescriptionAmountOfChars );
+ msvEntry.iDescription.Set( buf );
+ }
+
+ CSmsNumber* rcpt = CSmsNumber::NewL();
+ CleanupStack::PushL( rcpt );
+
+ TPtrC name;
+ TPtrC address;
+ TBool cantExit = ETrue;
+ while ( cantExit )
+ {
+ HBufC* addressBuf = NULL;
+ TPtr addressPtr( 0, 0);
+
+ NameAndAddress( iRecipients->MdcaPoint(0) , name, address );
+ UNILOGGER_WRITEF( _L("iRecipients: %S"), &iRecipients->MdcaPoint(0) );
+
+ // set To-field stuff into the Details of the entry
+ if ( name.Length() )
+ {
+ msvEntry.iDetails.Set( name );
+ }
+ else
+ {
+ // Internal data structures always holds the address data in western format.
+ // UI is responsible of doing language specific conversions.
+ addressBuf = HBufC::NewLC( address.Length() );
+ addressPtr.Set( addressBuf->Des() );
+ addressPtr.Copy( address );
+
+ AknTextUtils::ConvertDigitsTo( addressPtr, EDigitTypeWestern );
+ msvEntry.iDetails.Set( addressPtr );
+ }
+ UNILOGGER_WRITEF( _L("TMsvEntry::iDetails: %S"), &msvEntry.iDetails );
+ UNILOGGER_WRITEF( _L("TMsvEntry::iDescription: %S"), &msvEntry.iDescription );
+ TMsvId copyId;
+
+ if ( iRecipients->Count() == 1 )
+ {
+ //Note that we came here also in case of many recipients. ...eventually.
+
+ if ( IsEmailAddress( address ) )
+ {
+ FillEmailInformationDataL( header, address );
+ //Let's remove the recipient and replace it with Email over SMS gateway address
+ //But let's first cehck if it exists
+ if( SmsMtmL( )->AddresseeList().Count() )
+ {
+ SmsMtmL( )->RemoveAddressee( 0 );
+ }
+ SmsMtmL()->AddAddresseeL(
+ iEmailOverSmsC->Address( ) ,
+ KNullDesC( ) );
+ }
+ else
+ {
+ InsertSubjectL( header, SmsMtmL()->Body() );
+ }
+
+ entry.ChangeL( msvEntry );
+ SmsMtmL()->SaveMessageL();
+ // Move it
+ copyId = MoveMessageEntryL( KMsvGlobalOutBoxIndexEntryId );
+ cantExit = EFalse;
+ }
+ else
+ {// Many recipients in array
+
+ // Own copy function for Emails
+ // This is because EmailOverSms messages can
+ // contain adresses longer than 21 digits
+ if ( IsEmailAddress( address ) )
+ {
+ copyId = CreateMessageInOutboxL(
+ msvEntry, address );
+
+ }
+ else // For MSISDN's
+ {
+ rcpt->SetAddressL( address );
+ if ( name.Length() )
+ { // add name only if we have alias
+ rcpt->SetNameL( name );
+ }
+
+ copyId = CreateMessageInOutboxL(
+ msvEntry, *rcpt, SmsMtmL()->Body());
+
+ SmsMtmL()->RemoveAddressee( 0 );
+ }
+ //If hundreds of recipient, make sure viewserver
+ //timers are reseted
+ if ( iRecipients->Count() > 100 && ( iRecipients->Count() ) % 30 == 0 )
+ {
+ User::ResetInactivityTime();
+ }
+
+ iRecipients->Delete(0);
+ }
+ if ( addressBuf )
+ {
+ CleanupStack::PopAndDestroy( addressBuf );
+ }
+
+ // let's add the entry id into the cmsventryselection
+ selection->AppendL( copyId );
+ }
+ CleanupStack::PopAndDestroy( rcpt );
+
+#ifdef USE_LOGGER
+ for ( TInt i=0; i<selection->Count(); i++ )
+ {
+ SmsMtmL()->SwitchCurrentEntryL( selection->At(i) );
+ SmsMtmL()->LoadMessageL();
+ const CMsvRecipientList& testRecipients = SmsMtmL()->AddresseeList();
+ UNILOGGER_WRITEF( _L("Recipient: %S"), &(testRecipients[ 0 ]) );
+ UNILOGGER_WRITEF( _L("Body: %S"), &(SmsMtmL()->Body().Read( 0,80 ) ));
+ UNILOGGER_WRITEF( _L("EmailOverSMS address: %S"), &iEmailOverSmsC->Address( ) );
+ UNILOGGER_WRITEF( _L("EmailOverSMS name : %S"), &iEmailOverSmsC->Name( ) );
+
+ CSmsHeader& testHeader = SmsMtmL()->SmsHeader();
+ const CSmsEmailFields& testEmailFields = testHeader.EmailFields();
+
+ if ( testEmailFields.Addresses().MdcaCount() )
+ {
+ UNILOGGER_WRITEF( _L("CSmsEmailFields::iAddresses: %S"), &(testEmailFields.Addresses().MdcaPoint(0) ));
+ }
+ else
+ {
+ UNILOGGER_WRITEF(_L("CSmsEmailFields::iAddresses is empty"));
+ }
+
+
+ UNILOGGER_WRITEF( _L("CSmsEmailFields::iSubject : %S"), &testEmailFields.Subject() );
+
+ }
+#endif
+
+ //Let's free some memory
+ if ( iRecipients )
+ {
+ delete iRecipients;
+ iRecipients = NULL;
+ }
+
+ SetScheduledSendingStateL( selection );
+ CleanupStack::PopAndDestroy( selection );
+ }
+
+
+// ----------------------------------------------------------------------------
+// MoveMessageEntryL
+// ----------------------------------------------------------------------------
+TMsvId CUniSmsPlugin::MoveMessageEntryL( TMsvId aTarget )
+ {
+ TMsvEntry msvEntry( SmsMtmL()->Entry().Entry() );
+ TMsvId id = msvEntry.Id();
+
+ if ( msvEntry.Parent() != aTarget )
+ {
+ TMsvSelectionOrdering sort;
+ sort.SetShowInvisibleEntries( ETrue );
+ CMsvEntry* parentEntry= CMsvEntry::NewL( iSession, msvEntry.Parent(), sort );
+ CleanupStack::PushL( parentEntry );
+
+ // Copy original from the parent to the new location
+ CMuiuOperationWait* wait = CMuiuOperationWait::NewLC();
+
+ CMsvOperation* op = parentEntry->MoveL(
+ msvEntry.Id(),
+ aTarget,
+ wait->iStatus );
+
+ CleanupStack::PushL( op );
+ wait->Start();
+ TMsvLocalOperationProgress prog = McliUtils::GetLocalProgressL( *op );
+ User::LeaveIfError( prog.iError );
+
+ id = prog.iId;
+
+ CleanupStack::PopAndDestroy( op );
+ CleanupStack::PopAndDestroy( wait );
+ CleanupStack::PopAndDestroy( parentEntry );
+ }
+
+ return id;
+ }
+
+// ----------------------------------------------------------------------------
+// CreateMessageInOutboxL
+// Use this function for non-email messages
+// ----------------------------------------------------------------------------
+TMsvId CUniSmsPlugin::CreateMessageInOutboxL(
+ const TMsvEntry& aEntry,
+ const CSmsNumber& aRecipient,
+ const CRichText& aBody )
+ {
+ // Initialize the richtext object
+ CRichText* richText = CRichText::NewL( iParaFormatLayer, iCharFormatLayer );
+ CleanupStack::PushL( richText );
+
+ // Initialise header and store
+ CSmsHeader* header = CSmsHeader::NewL( CSmsPDU::ESmsSubmit, *richText );
+ CleanupStack::PushL( header );
+ CMsvStore* sourceStore = SmsMtmL()->Entry().ReadStoreL();
+ CleanupStack::PushL( sourceStore );
+
+ // Read store
+ header->RestoreL( *sourceStore );
+
+ // Initialise number with parameters
+ CSmsNumber* rcpt = CSmsNumber::NewL( aRecipient );
+ CleanupStack::PushL( rcpt );
+ header->Recipients().ResetAndDestroy();
+ header->Recipients().AppendL( rcpt );
+ CleanupStack::Pop( rcpt );
+
+ // Create entry to Outbox
+ TMsvEntry entry( aEntry );
+ entry.iMtmData3 = KSmsPluginBioMsgUnparsed;
+ CMsvEntry* outbox = iSession.GetEntryL( KMsvGlobalOutBoxIndexEntryId );
+ CleanupStack::PushL( outbox );
+ outbox->CreateL( entry );
+ iSession.CleanupEntryPushL( entry.Id() );
+ outbox->SetEntryL( entry.Id());
+
+ //Initialize target store
+ CMsvStore* targetStore;
+ targetStore = outbox->EditStoreL();
+ CleanupStack::PushL( targetStore );
+
+ //Add attachment
+ MMsvAttachmentManager& attaManager = sourceStore->AttachmentManagerL();
+ RFile tmpFile;
+
+ //Check if attachment exists and add it
+ if( sourceStore->AttachmentManagerL().AttachmentCount() )
+ {
+ tmpFile = attaManager.GetAttachmentFileL( 0 );
+ CleanupClosePushL( tmpFile );
+
+ MMsvAttachmentManager& targetAttaMan = targetStore->AttachmentManagerL();
+ CMsvAttachment* targetAtta = CMsvAttachment::NewL( CMsvAttachment::EMsvFile );
+ CleanupStack::PushL( targetAtta );
+
+ CMuiuOperationWait* waiter = CMuiuOperationWait::NewLC();
+ targetAttaMan.AddAttachmentL( tmpFile, targetAtta, waiter->iStatus );
+ waiter->Start();
+
+ CleanupStack::PopAndDestroy( waiter ); //waiter
+ CleanupStack::Pop(targetAtta );// targetAtta
+ CleanupStack::Pop( &tmpFile );//tmpFile
+ }
+
+ TInt totalLength( aBody.DocumentLength() );
+ HBufC* bodyText = HBufC::NewLC ( totalLength );
+ TPtr bodyTextPtr ( bodyText->Des() );
+
+ aBody.Extract( bodyTextPtr, 0, totalLength );
+ richText->InsertL( 0, bodyTextPtr );
+ CleanupStack::PopAndDestroy( bodyText );
+
+ InsertSubjectL( *header, *richText );
+
+ targetStore->StoreBodyTextL( *richText );
+
+ header->StoreL( *targetStore );
+ targetStore->CommitL();
+
+ // Usually SMCM takes care of updating iSize, but now when msg is
+ // created to Outbox for several recipients this has to be done manually.
+ entry.iSize = targetStore->SizeL();
+ entry.iRelatedId = iSmsServiceId;
+ entry.iServiceId = KMsvLocalServiceIndexEntryId;
+ outbox->ChangeL( entry );
+ CleanupStack::PopAndDestroy( targetStore );
+
+ iSession.CleanupEntryPop();
+ CleanupStack::PopAndDestroy( outbox );
+ CleanupStack::PopAndDestroy( sourceStore );
+ CleanupStack::PopAndDestroy( header );
+ CleanupStack::PopAndDestroy( richText );
+ return entry.Id();
+ }
+
+// ---------------------------------------------------------
+// CMsgSmsEditorAppUi::CreateMessageInOutboxL
+// Creates message in outbox in case of multiple recipients
+// with some e-mail over SMS addresses
+// ---------------------------------------------------------
+TMsvId CUniSmsPlugin::CreateMessageInOutboxL(
+ const TMsvEntry& aEntry,
+ const TDesC& aAddress )
+ {
+ CRichText* richText = CRichText::NewL( iParaFormatLayer, iCharFormatLayer );
+ CleanupStack::PushL( richText );
+ // Initialise header and store
+ CSmsHeader* header = CSmsHeader::NewL( CSmsPDU::ESmsSubmit, *richText );
+ CleanupStack::PushL( header );
+ CMsvStore* store = SmsMtmL()->Entry().ReadStoreL();
+
+ CleanupStack::PushL( store );
+ // Read store
+ header->RestoreL( *store );
+ CleanupStack::PopAndDestroy( store );
+ // Initialise number
+ CSmsNumber* rcpt = CSmsNumber::NewL();
+ CleanupStack::PushL( rcpt );
+ header->Recipients().ResetAndDestroy();
+ // Save Email specific information in header
+ FillEmailInformationDataL( *header, aAddress );
+ // Fill the recipient data for Email
+ // Address = Email gateway
+ // Alias = The real address
+ rcpt->SetAddressL( iEmailOverSmsC->Address() );
+ rcpt->SetNameL( aAddress ); // This takes only 21 chars
+
+ header->Recipients().AppendL( rcpt );
+ CleanupStack::Pop( rcpt );
+ // Create entry to Outbox
+ TMsvEntry entry( aEntry );
+ entry.iMtmData3 = KSmsPluginBioMsgUnparsed;
+
+ CMsvEntry* outbox = iSession.GetEntryL( KMsvGlobalOutBoxIndexEntryId );
+ CleanupStack::PushL( outbox );
+ outbox->CreateL( entry );
+ iSession.CleanupEntryPushL( entry.Id());
+ outbox->SetEntryL( entry.Id());
+ // Save
+ store = outbox->EditStoreL();
+ CleanupStack::PushL( store );
+ header->StoreL( *store );
+
+ richText->Reset();
+ richText->InsertL( 0 , SmsMtmL()->Body().Read( 0 ) );
+
+ store->StoreBodyTextL( *richText );
+ store->CommitL();
+ // Usually SMCM takes care of updating iSize, but now when msg is
+ // created to Outbox for several recipients this has to be done manually.
+ entry.iSize = store->SizeL();
+ entry.iRelatedId = iSmsServiceId;
+ entry.iServiceId = KMsvLocalServiceIndexEntryId;
+ outbox->ChangeL( entry );
+
+ CleanupStack::PopAndDestroy( store );
+ iSession.CleanupEntryPop();
+ CleanupStack::PopAndDestroy( outbox );
+ CleanupStack::PopAndDestroy( header );
+ CleanupStack::PopAndDestroy( richText );
+ return entry.Id();
+ }
+
+// ----------------------------------------------------------------------------
+// SetScheduledSendingStateL
+// ----------------------------------------------------------------------------
+void CUniSmsPlugin::SetScheduledSendingStateL( CMsvEntrySelection* aSelection )
+ {
+ const TMsvEntry msvEntry = SmsMtmL()->Entry().Entry();
+ if ( msvEntry.SendingState() == KMsvSendStateWaiting )
+ {
+ // Add entry to task scheduler
+ TBuf8<1> dummyParams;
+
+ CMuiuOperationWait* waiter = CMuiuOperationWait::NewLC();
+ waiter->iStatus = KRequestPending;
+
+ CMsvOperation* op= SmsMtmL()->InvokeAsyncFunctionL(
+ ESmsMtmCommandScheduleCopy,
+ *aSelection,
+ dummyParams,
+ waiter->iStatus );
+ CleanupStack::PushL( op );
+ waiter->Start();
+
+ CleanupStack::PopAndDestroy( op );
+ CleanupStack::PopAndDestroy( waiter );
+ }
+ }
+
+// ----------------------------------------------------------------------------
+// NameAndAddress
+// ----------------------------------------------------------------------------
+void CUniSmsPlugin::NameAndAddress( const TDesC& aMsvAddress, TPtrC& aName, TPtrC& aAddress )
+ {
+ TInt addressStart = aMsvAddress.LocateReverse( KMsgSmsAddressStartChar );
+ TInt addressEnd = aMsvAddress.LocateReverse( KMsgSmsAddressEndChar );
+
+ if ( addressStart != KErrNotFound && addressEnd != KErrNotFound
+ && addressEnd > addressStart )
+ {
+ // verified address, will be used as selected from contacts manager
+ aName.Set( aMsvAddress.Ptr(), addressStart );
+ aAddress.Set(
+ aMsvAddress.Mid( addressStart + 1 ).Ptr(),
+ ( addressEnd - addressStart ) -1 );
+ if ( !aAddress.Length())
+ {
+ aAddress.Set( aName );
+ aName.Set( KNullDesC ); // empty string
+ }
+ }
+ else
+ {
+ // unverified string, will be used as entered in the header field
+ aName.Set( KNullDesC ); // empty string
+ aAddress.Set( aMsvAddress.Ptr(), aMsvAddress.Length() ); // a whole string to address
+ }
+
+ if ( aName.CompareF( aAddress ) == 0 )
+ {
+ aName.Set( KNullDesC ); // empty string
+ }
+ }
+
+// ----------------------------------------------------------------------------
+// CUniSmsPlugin::ExtractDescriptionFromMessageL
+// ----------------------------------------------------------------------------
+void CUniSmsPlugin::ExtractDescriptionFromMessageL(
+ const CSmsMessage& aMessage,
+ TDes& aDescription,
+ TInt aMaxLength)
+ {
+ if ( iUniMtm.SubjectL().Length() )
+ {
+ aDescription.Copy( iUniMtm.SubjectL() );
+ }
+ else
+ {// Extract from message body
+ aMessage.Buffer().Extract(
+ aDescription,
+ 0,
+ Min(
+ aMaxLength,
+ aMessage.Buffer().Length()));
+ }
+
+ //replace paragraphs with spaces.
+ TBuf<KSmsEdExtrDescReplaceCharacterCount> replaceChars;
+ replaceChars.Zero();
+ replaceChars.Append( CEditableText::EParagraphDelimiter );
+ replaceChars.Append( KSmsEdUnicodeLFSupportedByBasicPhones );
+ replaceChars.Append( CEditableText::ELineBreak );
+ AknTextUtils::ReplaceCharacters(
+ aDescription,
+ replaceChars,
+ CEditableText::ESpace );
+
+ aDescription.Trim();
+ }
+
+// ----------------------------------------------------------------------------
+// CreatePlainTextSMSL
+// ----------------------------------------------------------------------------
+void CUniSmsPlugin::CreatePlainTextSMSL( RFile& aFile)
+ {
+ RFileReadStream stream( aFile );
+ CleanupClosePushL( stream );
+
+ CPlainText::TImportExportParam param;
+ param.iForeignEncoding = KCharacterSetIdentifierUtf8;
+ param.iOrganisation = CPlainText::EOrganiseByParagraph;
+
+ CPlainText::TImportExportResult result;
+
+ SmsMtmL()->Body().ImportTextL( 0, stream, param, result );
+
+ CleanupStack::PopAndDestroy( &stream );
+ }
+
+// ----------------------------------------------------------------------------
+// InsertSubjectL
+// Insert subject for non email addresses into the body
+// ----------------------------------------------------------------------------
+void CUniSmsPlugin::InsertSubjectL( CSmsHeader& aHeader, CRichText& aText )
+ {
+ if ( iUniMtm.SubjectL().Length() && !iBioMsg )
+ {
+ TPtrC subject = iUniMtm.SubjectL();
+ TInt writePosition = subject.Length()+2;//+2 for the parentesis
+
+ if ( subject.Locate( KUniSmsStartParenthesis )!= KErrNotFound ||
+ subject.Locate( KUniSmsEndParenthesis ) != KErrNotFound)
+ {
+ HBufC* modifiableSubject = subject.Alloc();
+ CleanupStack::PushL(modifiableSubject);
+ TPtr ptr = modifiableSubject->Des();
+
+ TBuf<1> replaceChars;
+ replaceChars.Zero();
+ replaceChars.Append( KUniSmsStartParenthesis );
+ // Replace '(' chars with '<'
+ AknTextUtils::ReplaceCharacters(
+ ptr,
+ replaceChars,
+ TChar('<') );
+
+ replaceChars.Zero();
+ replaceChars.Append( KUniSmsEndParenthesis );
+
+ // Replace ')' chars with '>'
+ AknTextUtils::ReplaceCharacters(
+ ptr,
+ replaceChars,
+ TChar('>') );
+
+ aText.InsertL( 0, KUniSmsStartParenthesis );
+ aText.InsertL( 1, ptr );
+ aText.InsertL( writePosition-1, KUniSmsEndParenthesis );
+ CleanupStack::PopAndDestroy( modifiableSubject );
+ }
+
+ else
+ {
+ aText.InsertL( 0, KUniSmsStartParenthesis );
+ aText.InsertL( 1, subject );
+ aText.InsertL( writePosition-1, KUniSmsEndParenthesis );
+ }
+ }
+
+ // Clears the CSmsHeaders EmailFields for non Email addresses
+ CSmsEmailFields* emailFields = CSmsEmailFields::NewL();
+ CleanupStack::PushL( emailFields );
+ aHeader.SetEmailFieldsL( *emailFields );
+ CleanupStack::PopAndDestroy( emailFields );
+ }
+
+// ----------------------------------------------------------------------------
+// CreateVCardSMS
+// ----------------------------------------------------------------------------
+void CUniSmsPlugin::CreateVCardSMSL( RFile& aFile )
+ {
+ TInt fileSize;
+ TInt err ( aFile.Size( fileSize ) );
+ User::LeaveIfError(err);
+
+ // Create two buffers: 8-bit for reading from file and 16-bit for
+ // converting to 16-bit format
+ HBufC8* buf8 = HBufC8::NewLC( fileSize );
+ TPtr8 ptr8 = buf8->Des();
+ HBufC16* buf16 = HBufC16::NewLC( fileSize );
+ TPtr16 ptr16 = buf16->Des();
+
+ for (TInt err = aFile.Read(ptr8);
+ ptr8.Length() > 0;
+ err = aFile.Read(ptr8))
+ {
+ User::LeaveIfError(err);
+ ptr16.Copy(ptr8);
+ SmsMtmL()->Body().InsertL(SmsMtmL()->Body().DocumentLength(), ptr16);
+ }
+
+ // Cleanup and return
+ CleanupStack::PopAndDestroy( buf16 );
+ CleanupStack::PopAndDestroy( buf8 );
+ }
+
+// ----------------------------------------------------------------------------
+// CreateVCalSMS
+// ----------------------------------------------------------------------------
+void CUniSmsPlugin::CreateVCalSMSL( RFile& aFile )
+ {
+ TInt err (KErrNone);
+ TInt fileSize;
+ err = aFile.Size( fileSize );
+ User::LeaveIfError(err);
+
+ HBufC8* buf8 = HBufC8::NewLC( fileSize );
+ TPtr8 ptr8 = buf8->Des();
+
+ err = aFile.Read( ptr8 );
+ User::LeaveIfError(err);
+
+ HBufC16* buf16 = HBufC16::NewLC( fileSize );
+ TPtr16 ptr16 = buf16->Des();
+
+ ptr16.Copy(ptr8);
+ SmsMtmL()->Body().InsertL(0, ptr16);
+
+ CleanupStack::PopAndDestroy( buf16 );
+ CleanupStack::PopAndDestroy( buf8 );
+ }
+
+// ----------------------------------------------------------------------------
+// CUniSmsPlugin::ValidateSCNumberL
+// ----------------------------------------------------------------------------
+TBool CUniSmsPlugin::ValidateSCNumberL()
+ {
+ TBool valid( ETrue );
+ if ( iSmsHeader->Message().ServiceCenterAddress().Length() == 0 ||
+ !iSmsHeader->ReplyPathProvided() )
+ {
+ if ( !SmsMtmL()->ServiceSettings().ServiceCenterCount() )
+ {
+ if ( !SmsScDialogL())
+ {
+ valid = EFalse;
+ }
+ else
+ {
+ valid = ETrue;
+ CSmsServiceCenter& sc = SmsMtmL()->ServiceSettings().GetServiceCenter( 0 );
+
+ // Update service settings' sc address list and set it to default.
+ SmsMtmL()->ServiceSettings().SetDefaultServiceCenter( 0 );
+
+ CSmsAccount* smsAccount = CSmsAccount::NewLC();
+ smsAccount->SaveSettingsL( SmsMtmL()->ServiceSettings() );
+ CleanupStack::PopAndDestroy( smsAccount );
+
+ // Set the SC addres for this message
+ iSmsHeader->Message().SetServiceCenterAddressL(
+ sc.Address() );
+ }
+ }
+ else
+ {
+ //Else use the default - or then the first one on the sc address list.
+ TInt index = Max( 0, SmsMtmL()->ServiceSettings().DefaultServiceCenter() );
+ CSmsServiceCenter& sc = SmsMtmL()->ServiceSettings().GetServiceCenter( index );
+ iSmsHeader->Message().SetServiceCenterAddressL( sc.Address() );
+ }
+ }
+ return valid;
+ }
+
+// ---------------------------------------------------------
+// CUniSmsPlugin::ValidateSCNumberForEmailOverSmsL
+// ---------------------------------------------------------
+TBool CUniSmsPlugin::ValidateSCNumberForEmailOverSmsL()
+ {
+ TBool confNeeded( EFalse );
+ // Read the email settings
+ TBuf<KUniSmsSCStringLength> emailSmscNumber;
+ TBuf<KUniSmsSCStringLength> emailGateWayNumber;
+ TBool notUsed( EFalse );
+ // The file may not exist
+ TInt readResult = SmumUtil::ReadEmailOverSmsSettingsL(
+ emailSmscNumber,
+ emailGateWayNumber,
+ notUsed );
+ if ( KErrNone == readResult )
+ {
+ // Check that both have valid values
+ // In any otther case we need to show the conf pop-up window
+ if ( emailSmscNumber == KNullDesC )
+ {
+ // Use the sms smsc as default
+ CSmsSettings* serviceSettings = &( SmsMtmL()->ServiceSettings() );
+
+ if ( SmsMtmL()->ServiceSettings().DefaultServiceCenter() > 0 )
+ {
+ emailSmscNumber =
+ serviceSettings->GetServiceCenter(
+ SmsMtmL()->ServiceSettings().DefaultServiceCenter() ).Address();
+ }
+ else
+ {
+ emailSmscNumber =
+ serviceSettings->GetServiceCenter( 0 ).Address();
+ }
+ confNeeded = ETrue;
+ }
+ if ( emailGateWayNumber == KNullDesC )
+ {
+ confNeeded = ETrue;
+ }
+ }
+ else
+ {
+ confNeeded = ETrue;
+ }
+ if ( confNeeded ) // Show the query
+ {
+ CUniSmsEMultilineQueryDialog* dlg =
+ CUniSmsEMultilineQueryDialog::NewL(
+ emailGateWayNumber,
+ emailSmscNumber,
+ ETrue );
+ if ( dlg->ExecuteLD( R_ADDEMAILSC_QUERY ) )
+ {
+ // Save settings to Smum
+ SmumUtil::WriteEmailOverSmsSettingsL(
+ emailSmscNumber,
+ emailGateWayNumber,
+ ETrue );
+ }
+ else
+ {
+ return EFalse;
+ }
+ }
+ // Use them
+ iEmailOverSmsC->SetNameL( emailSmscNumber );
+ iEmailOverSmsC->SetAddressL( emailGateWayNumber );
+ return ETrue;
+ }
+
+// ----------------------------------------------------------------------------
+// CUniSmsPlugin::SmsScDialogL
+// ----------------------------------------------------------------------------
+TBool CUniSmsPlugin::SmsScDialogL()
+ {
+ TBuf<KUniSmsSCStringLength> name;
+ TBuf<KUniSmsSCStringLength> number;
+ TBool retVal = EFalse;
+
+ // Read the default name
+ SmumUtil::FindDefaultNameForSCL( name, EFalse );
+ CUniSmsEMultilineQueryDialog* dlg =
+ CUniSmsEMultilineQueryDialog::NewL( name, number );
+ if ( dlg->ExecuteLD( R_ADDSC_QUERY ) )
+ {
+ retVal = ETrue;
+ if ( !name.Length())
+ {
+ // read default name again
+ SmumUtil::FindDefaultNameForSCL( name, EFalse );
+ }
+ SmsMtmL()->ServiceSettings().AddServiceCenterL( name, number );
+ }
+ return retVal;
+ }
+
+// ---------------------------------------------------------
+// CUniSmsPlugin::FillEmailInformationDataL
+// ---------------------------------------------------------
+void CUniSmsPlugin::FillEmailInformationDataL(
+ CSmsHeader& aHeader,
+ const TPtrC& aAddress )
+ {
+ UNILOGGER_ENTERFN( "CUniSmsPlugin::FillEmailInformationDataL()" )
+
+ CSmsEmailFields* emailFields = CSmsEmailFields::NewL();
+ CleanupStack::PushL( emailFields );
+
+ // The Email SMSC may differ from sms SMSC
+ UNILOGGER_WRITEF( _L("Set EMailOverSMS SC: %S"), &iEmailOverSmsC->Name() );
+ aHeader.Message().SetServiceCenterAddressL( iEmailOverSmsC->Name() );
+
+ // Check if there is need to save as EmailFieds with header
+ if ( aAddress.Length() )
+ {
+ // Set the address
+ UNILOGGER_WRITEF( _L("Recipient: %S"), &aAddress );
+ emailFields->AddAddressL( aAddress );
+ }
+
+ if ( iUniMtm.SubjectL().Length() )
+ { // Handle the subject
+ HBufC* buf = iUniMtm.SubjectL().AllocL();
+ CleanupStack::PushL( buf );
+ TPtr text = buf->Des();
+
+ TBuf<1> replaceChars;
+ replaceChars.Zero();
+ replaceChars.Append( KUniSmsStartParenthesis );
+ // Replace '(' chars with '<'
+ AknTextUtils::ReplaceCharacters(
+ text,
+ replaceChars,
+ TChar('<') );
+
+ replaceChars.Zero();
+ replaceChars.Append( KUniSmsEndParenthesis );
+ // Replace ')' chars with '>'
+ AknTextUtils::ReplaceCharacters(
+ text,
+ replaceChars,
+ TChar('>') );
+
+ // For Emails save it to CSmsEmailFields
+ emailFields->SetSubjectL( text );
+ CleanupStack::PopAndDestroy( buf );
+ }
+
+
+ aHeader.SetEmailFieldsL( *emailFields );
+ CleanupStack::PopAndDestroy( emailFields );
+ UNILOGGER_LEAVEFN( "CUniSmsPlugin::FillEmailInformationDataL()" )
+ }
+
+
+
+// ----------------------------------------------------
+// CUniSmsPlugin::IsEmailAddress()
+// ----------------------------------------------------
+TBool CUniSmsPlugin::IsEmailAddress( const TPtrC& aAddress ) const
+ {
+ UNILOGGER_ENTERFN( "CMsgSmsEmailOverSmsFunc::IsEmailAddress()" )
+ TBool isEmailAddress( EFalse );
+ if ( aAddress.Locate('@') != KErrNotFound)
+ {
+ UNILOGGER_WRITEF(
+ _L("IsEmailAddress - Address: %s"), aAddress.Ptr() );
+ isEmailAddress = ETrue;
+ }
+ UNILOGGER_LEAVEFN( "CMsgSmsEmailOverSmsFunc::IsEmailAddress()" )
+ return isEmailAddress;
+ }
+
+// ----------------------------------------------------------------------------
+// Panic
+// ----------------------------------------------------------------------------
+GLDEF_C void Panic( TInt aCategory )
+ {
+ _LIT( KUniSmsPluginPanic, "CUniSmsPlugin-Panic" );
+ User::Panic( KUniSmsPluginPanic, aCategory );
+ }
+
+// ========================== OTHER EXPORTED FUNCTIONS =========================
+
+// ------------------------------------------------------------------------------------------------
+// ImplementationProxy
+// -----------------------------------------------------------------------------
+//
+EXPORT_C const TImplementationProxy* ImplementationGroupProxy( TInt& aTableCount )
+ {
+ aTableCount = sizeof( KImplementationTable ) / sizeof( TImplementationProxy );
+ return KImplementationTable;
+ }
+
+//------------------------------------------------------------------------------
+// CUniSmsPlugin::SetEncodingSetings
+// Turkish SMS-PREQ2265 Specific
+// To Set encoding settings like encoding type, character support
+// and alternative encoding if any
+//
+// IMPORTANT NOTE:
+// This function is usually called from UniEditorAppUI to reset/set alternative encoding or char support
+// when corresponding feilds change. Hence aUnicodeMode is always set to false
+//------------------------------------------------------------------------------
+void CUniSmsPlugin::SetEncodingSettings( TBool aUnicodeMode, TSmsEncoding aAlternativeEncodingType, TInt aCharSupportType)
+ {
+ UNILOGGER_WRITE_TIMESTAMP("CUniSmsPlugin::SetEncodingSettings Start <<<---- ");
+ TSmsUserDataSettings smsSettings;
+ CSmsMessage& smsMsg = iSmsHeader->Message();
+ TBool settingsChanged = EFalse;
+
+ iCharSupportType = aCharSupportType;
+ iAlternativeEncodingType = aAlternativeEncodingType;
+ if( iUnicodeMode != aUnicodeMode )
+ {
+ iUnicodeMode = aUnicodeMode;
+ if(iUnicodeMode)
+ {
+ smsSettings.SetAlphabet( TSmsDataCodingScheme::ESmsAlphabetUCS2 );
+ }
+ else
+ {
+ smsSettings.SetAlphabet( TSmsDataCodingScheme::ESmsAlphabet7Bit );
+ }
+ settingsChanged = ETrue;
+ }
+ if( smsSettings.TextCompressed())
+ {
+ smsSettings.SetTextCompressed( EFalse );
+ settingsChanged = ETrue;
+ }
+ if( settingsChanged )
+ {
+ TRAP_IGNORE(smsMsg.SetUserDataSettingsL( smsSettings ));
+#ifdef USE_LOGGER
+ UNILOGGER_WRITE("SetEncodingSettings: SetUserDataSettingsL");
+#endif /* USE_LOGGER */
+ }
+ //First try without any alternate encoding
+ if( aAlternativeEncodingType != smsMsg.Alternative7bitEncoding() )
+ {
+ smsMsg.SetAlternative7bitEncoding( aAlternativeEncodingType );// Optimal
+#ifdef USE_LOGGER
+ UNILOGGER_WRITEF(_L("SetEncodingSettings: aAlternativeEncodingType-> %d"), aAlternativeEncodingType);
+#endif /* USE_LOGGER */
+ }
+ UNILOGGER_WRITE_TIMESTAMP("CUniSmsPlugin::SetEncodingSettings End ---->>> ");
+ }
+//------------------------------------------------------------------------------
+// CUniSmsPlugin::GetNumPDUsL
+// Turkish SMS-PREQ2265 Specific
+// To get PDU Info: extracts details of number of PDUs, number of remaining chars in last PDU
+// and encoding types used.
+//------------------------------------------------------------------------------
+void CUniSmsPlugin::GetNumPDUsL(
+ TDesC& aBuf,
+ TInt& aNumOfRemainingChars,
+ TInt& aNumOfPDUs,
+ TBool& aUnicodeMode,
+ TSmsEncoding & aAlternativeEncodingType )
+ {
+ UNILOGGER_WRITE_TIMESTAMP("<<<<<<<<---------------------CUniSmsPlugin::GetNumPDUsL Start: ");
+ TInt numOfUnconvChars, numOfDowngradedChars, isAltEncSupported;
+ TSmsEncoding currentAlternativeEncodingType;
+
+ CSmsMessage& smsMsg = iSmsHeader->Message();
+
+#ifdef USE_LOGGER
+ HBufC* tempBuff = HBufC::NewL( aBuf.Length() + 2 );
+ tempBuff->Des().Copy( aBuf );
+ UNILOGGER_WRITEF(_L("GetNumPDUsL:->> Buf Length: %d"), aBuf.Length() );
+ UNILOGGER_WRITEF(_L("GetNumPDUsL:->> buffer : %s"), tempBuff->Des().PtrZ() );
+ delete tempBuff;
+#endif /* USE_LOGGER */
+ // need to set the input buffer to SMS buffer through iRichText(which is reference to SMS Buffer object)
+ iRichText->Reset();
+ iRichText->InsertL(0, aBuf);
+
+ //call SMS stack API to get PDU info
+ smsMsg.GetEncodingInfoL( aNumOfPDUs, numOfUnconvChars, numOfDowngradedChars, aNumOfRemainingChars );
+
+#ifdef USE_LOGGER
+ UNILOGGER_WRITE(" ---Get Encoding Info details:--- ");
+ UNILOGGER_WRITEF(_L(" aNumPdus : %d"), aNumOfPDUs);
+ UNILOGGER_WRITEF(_L(" numOfUnconvChars : %d"), numOfUnconvChars);
+ UNILOGGER_WRITEF(_L(" numOfDowngradedChars: %d"), numOfDowngradedChars);
+ UNILOGGER_WRITEF(_L(" aNumOfRemainingChars: %d"), aNumOfRemainingChars);
+#endif /* USE_LOGGER */
+ //Algo to switch to Unicode if required
+ while( (numOfUnconvChars || numOfDowngradedChars) && !iUnicodeMode )
+ {
+ currentAlternativeEncodingType = smsMsg.Alternative7bitEncoding();
+#ifdef USE_LOGGER
+ UNILOGGER_WRITEF(_L("GetNumPDUsL: currAltEnc -> %d"), currentAlternativeEncodingType);
+#endif /* USE_LOGGER */
+ if( currentAlternativeEncodingType != iAlternativeEncodingType )
+ {
+ //try with this new alternative encoding type
+ isAltEncSupported = smsMsg.SetAlternative7bitEncoding( iAlternativeEncodingType );
+ if( isAltEncSupported == KErrNotSupported )
+ {
+ // if required alternative encoding plugin is not supported, retain the existing encoding mechanism.
+ iAlternativeEncodingType = currentAlternativeEncodingType;
+ continue;
+ }
+ }
+ else if( numOfUnconvChars || (TUniSendingSettings::TUniCharSupport)iCharSupportType == TUniSendingSettings::EUniCharSupportFull)
+ {
+ //switch to Unicode
+ //iUnicodeMode = ETrue;
+ SetEncodingSettings( ETrue, /*ESmsEncodingNone*/ iAlternativeEncodingType, iCharSupportType);
+ }
+ else
+ {
+ //Get out of while loop and return the results
+ break;
+ }
+ //get the PDU info with new settings
+ iRichText->Reset();
+ iRichText->InsertL(0, aBuf);
+ smsMsg.GetEncodingInfoL( aNumOfPDUs, numOfUnconvChars, numOfDowngradedChars, aNumOfRemainingChars );
+#ifdef USE_LOGGER
+ UNILOGGER_WRITE("******* Get Encoding Info details (Again):***** ");
+ UNILOGGER_WRITEF(_L(" aNumPdus : %d"), aNumOfPDUs);
+ UNILOGGER_WRITEF(_L(" numOfUnconvChars : %d"), numOfUnconvChars);
+ UNILOGGER_WRITEF(_L(" numOfDowngradedChars: %d"), numOfDowngradedChars);
+ UNILOGGER_WRITEF(_L(" aNumOfRemainingChars: %d"), aNumOfRemainingChars);
+#endif /* USE_LOGGER */
+ }
+
+ /*
+ * Enable the below code to debug if something wrong with characters sent even in unicode mode
+ */
+ /*
+ If((numOfUnconvChars || numOfDowngradedChars) && iUnicodeMode)
+ UNILOGGER_WRITEF("GOTCHA... some chars are not convertable in unicode mode as well...????");
+ */
+ aUnicodeMode = iUnicodeMode;
+ aAlternativeEncodingType = iAlternativeEncodingType;
+ if(iUnicodeMode)
+ {
+ //In case of Unicode mode, SMS Stack returns number of available free User Data units.
+ //Need to convert them w.r.t characters(each char takse 2 UD units).
+ aNumOfRemainingChars = aNumOfRemainingChars/2;
+ }
+ UNILOGGER_WRITE_TIMESTAMP("CUniSmsPlugin::GetNumPDUsL End -------------------->>>>>>>>>>> ");
+ }
+
+// End of File