diff -r 65a3ef1d5bd0 -r f742655b05bf voipplugins/sipconnectionprovider/ipvoicemailengine/src/ipvmbxengine.cpp --- a/voipplugins/sipconnectionprovider/ipvoicemailengine/src/ipvmbxengine.cpp Thu Aug 19 09:45:22 2010 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1258 +0,0 @@ -/* -* Copyright (c) 2002-2010 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: Creates SMS message if Event in MailBox has occurred. -* -*/ - - - -// Include hierarchy change can't be done. Smuthdr.h uses -// other files from messaging/sms (smsstd.h and smutset.h). It doesn't seem -// to find them without old way to declare include folder using SYSTEMINCLUDE. -// -#include /*messaging/\sms/\*/ -#include -#include -#include -#include -#include -#include -#include - -#include "ipvmbxengine.h" -#include "ipvmbxeventmonitor.h" -#include "ipvmbxbase.h" -#include "ipvmbxlogger.h" -#include "ipvmbxconstants.h" -#include "ipvmbxpanic.h" - - -const TUid KAppUID = { 0x1020596F }; -const TInt KMaxMessageDigits = 10; -const TInt KAccountTextLength = 21; -const TInt KOneChar = 1; -const TInt KTwoChars = 2; -const TInt KSmsLength = 160; -const TInt KTotalLength = 2; -const TInt KTotalOldLength = 3; -const TInt KMinIpVoiceMailBoxUriLength = 3; -const TInt KSpecialNameCharsCount = 10; -const TInt KMaxMsgDescriptions = 99; - -_LIT( KEndLine, "\n" ); -_LIT( KTotal, "%N" ); -_LIT( KTotalNew, "%0N" ); -_LIT( KIpVmbxAppEngineResourceFileDirectory, "\\resource\\" ); -_LIT( KIpVmbxAppEngineResourceFileName, "ipvoicemailengine.rsc" ); -_LIT( KSipString, "sip:"); -_LIT( KOptionalSeparator, "\n\n" ); -_LIT8( KTotalOld, "%1N" ); -_LIT8( KOneMessage, "1" ); -_LIT8( KNoMessages, "0" ); -_LIT8( KMessagesWaiting8, "messages-waiting" ); -_LIT8( KNewMessages8, "yes" ); -_LIT8( KMessageAccount8, "message-account" ); -_LIT8( KVoiceMessage8, "voice-message" ); -_LIT8( KSlash8, "/" ); -_LIT8( KColon8, ":" ); -_LIT8( KCrlf8, "\r\n" ); -_LIT8( KEndLine8, "\n" ); -_LIT8( KHTab8, "\t"); -_LIT8( KSpace8, " "); - -const TText KNameDigitLowest = '\x30'; -const TText KNameDigitHighest = '\x39'; -const TText KNameCharUpLowest = '\x41'; -const TText KNameCharUpHighest = '\x5a'; -const TText KNameCharLowLowest = '\x61'; -const TText KNameCharLowHighest = '\x7a'; -// Legal characters in name header -// 2d, 2e, 21, 25, 2a, 5f, 2b, 60, 27, 7e -const TText8 KSpecialNameChars[KSpecialNameCharsCount] = - { - '-', - '.', - '!', - '%', - '*', - '_', - '+', - '`', - '\'', - '~' - }; -const TText KSpace = '\x20'; -const TText KValueLowestChar = KSpace; -const TText KValueHighestChar = '\xfd'; -const TText KCr = '\x0d'; -const TText KLf = '\x0a'; -const TText KHTab = '\x09'; - - -// ============================ MEMBER FUNCTIONS ============================== - -// ---------------------------------------------------------------------------- -// C++ default constructor can NOT contain any code, that -// might leave. -// ---------------------------------------------------------------------------- -// -CIpVmbxEngine::CIpVmbxEngine( CIpVmbxInterface& aInterface ): - iEventData(), - iInterface( aInterface ) - { - } - - -// ---------------------------------------------------------------------------- -// Symbian 2nd phase constructor can leave. -// ---------------------------------------------------------------------------- -// -void CIpVmbxEngine::ConstructL() - { - // One manager = one event observer (restricted) - iIpVmbxEventMonitor = new ( ELeave ) TIpVmbxEventMonitor( *this ); - } - - -// ---------------------------------------------------------------------------- -// Two-phased constructor. -// ---------------------------------------------------------------------------- -// -EXPORT_C CIpVmbxEngine* CIpVmbxEngine::NewL( CIpVmbxInterface& aInterface ) - { - IPVMEPRINT( "CIpVmbxEngine::NewL" ); - - CIpVmbxEngine* self = new( ELeave ) CIpVmbxEngine( aInterface ); - CleanupStack::PushL( self ); - self->ConstructL(); - CleanupStack::Pop( self ); - - return self; - } - - -// ---------------------------------------------------------------------------- -// Destructor. -// ---------------------------------------------------------------------------- -// -CIpVmbxEngine::~CIpVmbxEngine() - { - IPVMEPRINT( "CIpVmbxEngine::~CIpVmbxEngine - IN" ); - - iVmbxBaseArray.ResetAndDestroy(); - iVmbxBaseArray.Close(); - - delete iMceManager; - delete iServiceSettings; - delete iIpVmbxEventMonitor; - - IPVMEPRINT( "CIpVmbxEngine::~CIpVmbxEngine - OUT" ); - } - - -// ---------------------------------------------------------------------------- -// Starts subscription to VoiceMailBox -server -// ---------------------------------------------------------------------------- -// -void CIpVmbxEngine::SubscribeProfileL( - TUint32 aServiceProviderId, - CSIPProfile& aSipProfile ) - { - IPVMEPRINT( "CIpVmbxEngine::SubscribeProfileL - IN" ); - - if ( !iBasicServicesRunning ) - { - iServiceSettings = CSPSettings::NewL(); - // one manager recommended for one component - iMceManager = CMceManager::NewL( KAppUID, &iEventData ); - iMceManager->SetEventObserver( iIpVmbxEventMonitor ); - iBasicServicesRunning = ETrue; - } - - HBufC16* voiceMailUri16 = HBufC16::NewLC( KMaxIpVoiceMailBoxUriLength ); - TPtr16 ptrvoiceMailUri16( voiceMailUri16->Des() ); - TInt reSubscribe = 0; - - // Fetch MWI address - CSPProperty* mwiAddress = CSPProperty::NewLC(); - User::LeaveIfError( iServiceSettings->FindPropertyL( - aServiceProviderId, - ESubPropertyVMBXMWIAddress, - *mwiAddress ) ); - User::LeaveIfError( mwiAddress->GetValue( ptrvoiceMailUri16 ) ); - if ( ptrvoiceMailUri16.Length() < KMinIpVoiceMailBoxUriLength ) - { - IPVMEPRINT( "CIpVmbxEngine::SubscribeProfileL - MWI not found, Leaving..." ); - User::Leave( KErrNotFound ); - } - IPVMEPRINT( "CIpVmbxEngine::SubscribeProfileL - MWI found" ); - if ( KErrNotFound == ptrvoiceMailUri16.Find( KSipString ) ) - { - ptrvoiceMailUri16.Insert( 0, KSipString ); - } - CleanupStack::PopAndDestroy( mwiAddress ); - - // Fetch also subscribe interval - CSPProperty* mwiInterval = CSPProperty::NewLC(); - User::LeaveIfError( iServiceSettings->FindPropertyL( - aServiceProviderId, - ESubPropertyVMBXMWISubscribeInterval, - *mwiInterval) ); - User::LeaveIfError( mwiInterval->GetValue( reSubscribe ) ); - CleanupStack::PopAndDestroy( mwiInterval ); - - HBufC8* voiceMailUri8 = CnvUtfConverter::ConvertFromUnicodeToUtf8L( - ptrvoiceMailUri16 ); - CleanupStack::PopAndDestroy( voiceMailUri16 ); - CleanupStack::PushL( voiceMailUri8 ); - - TInt index = iVmbxBaseArray.Count(); - TBool newProfile = ETrue; - if ( index ) - { - // Might be second subscription or pending operation. - // Though IPVME and SCP supports currently only one VMBX connection - for ( TInt i = 0; i < index; i++ ) - { - CIpVmbxBase* const subscription( iVmbxBaseArray[i] ); - if ( *voiceMailUri8 == subscription->VmbxUrl() ) - { - // Subscription already exists - if ( CIpVmbxBase::EDisabled == subscription->State() ) - { - // Subscription was disabled, enable - newProfile = EFalse; - subscription->Initialize( - aServiceProviderId, - aSipProfile ); - - subscription->SubscribeL( reSubscribe ); - } - else - { - User::Leave( KErrAlreadyExists ); - } - } - } - } - if ( newProfile ) - { - // Subscription to new VMBX account - IPVMEPRINT( "CIpVmbxEngine::New AppBase" ); - CIpVmbxBase* app = CIpVmbxBase::NewL( - *this, - *voiceMailUri8, - *iMceManager ); - CleanupStack::PushL( app ); - iVmbxBaseArray.AppendL( app ); - CleanupStack::Pop( app ); - - app->Initialize( aServiceProviderId, aSipProfile ); - app->SubscribeL( reSubscribe ); - } - - CleanupStack::PopAndDestroy( voiceMailUri8 ); - - IPVMEPRINT( "CIpVmbxEngine::SubscribeProfileL - OUT" ); - } - - -// --------------------------------------------------------------------------- -// -// --------------------------------------------------------------------------- -// -TInt CIpVmbxEngine::ProfileSubscribed( - TUint32 aServiceProviderId, - TBool& aProfileSubscribed ) - { - CIpVmbxBase* subscription( SubscriptionByProvider( aServiceProviderId ) ); - TInt err = KErrNotFound; - - if ( subscription ) - { - err = KErrNone; - if ( CIpVmbxBase::ERegistered == subscription->State() ) - { - aProfileSubscribed = ETrue; - } - else - { - aProfileSubscribed = EFalse; - } - } - - return err; - } - - -// --------------------------------------------------------------------------- -// Resolve base class matching to recipient -// --------------------------------------------------------------------------- -// -CIpVmbxBase* CIpVmbxEngine::SubscriptionByRecipient( - const TDesC8& aRecipient8 ) - { - CIpVmbxBase* base( NULL ); - - for ( TInt i = 0; i < iVmbxBaseArray.Count(); i++ ) - { - if ( iVmbxBaseArray[i]->VmbxUrl() == aRecipient8 ) - { - base = iVmbxBaseArray[i]; - } - } - - return base; - } - - -// ---------------------------------------------------------------------------- -// EventMonitor has received event and the event will be gained and checked -// ---------------------------------------------------------------------------- -// -void CIpVmbxEngine::EventReceivedL( const TDesC8& aRecipient8 ) - { - IPVMEPRINT( "CIpVmbxEngine::EventReceivedL - IN" ); - - CIpVmbxBase* subscription( SubscriptionByRecipient( aRecipient8 ) ); - if ( !subscription ) - { - User::Leave( KErrNotFound ); - } - - HBufC8* content8( iEventData.GetContent() ); - CleanupStack::PushL( content8 ); - - HBufC8* totalMessages8 = HBufC8::NewLC( KMaxMessageDigits ); - HBufC8* newMessages8 = HBufC8::NewLC( KMaxMessageDigits ); - HBufC8* from8 = HBufC8::NewLC( - KMaxIpVoiceMailBoxUriLength + KAccountTextLength ); - TPtr8 ptrTotalMessages8( totalMessages8->Des() ); - TPtr8 ptrNewMessages8( newMessages8->Des() ); - TPtr8 ptrFrom8( from8->Des() ); - TPtr8 ptrContent8( content8->Des() ); - - TBool createSMS = EFalse; - // no need to handle errors, returned parameters can still - // be interpreted correctly - // - TRAP_IGNORE( - ParseNotifyContentL( - createSMS, - ptrContent8, - ptrTotalMessages8, - ptrNewMessages8, - ptrFrom8 ) ); - - if ( ptrNewMessages8 == KNoMessages ) - { - // protocol test fix, new message should not be created - // if new message count is 0 - IPVMEPRINT( "CIpVmbxEngine::EventReceivedL - No new messages" ); - createSMS = EFalse; - } - if ( 0 == ptrFrom8.Length() ) - { - ptrFrom8 = subscription->VmbxUrl(); - } - - TInt totalMsgs = 0; - TInt newMsgs = 0; - TLex8 msgsConvert; - msgsConvert.Assign( *totalMessages8 ); - if ( KErrNone == msgsConvert.Val( totalMsgs ) ) - { - msgsConvert.Assign( *newMessages8 ); - if ( KErrNone != msgsConvert.Val( newMsgs ) ) - { - totalMsgs = 0; - } - } - - TInt curTotal = 0; - TInt curNew = 0; - subscription->AccountMessageCount( curTotal, curNew ); - - TBool statusChanged = EFalse; - if ( totalMsgs != curTotal || newMsgs != curNew ) - { - statusChanged = ETrue; - IPVMEPRINT( "CIpVmbxEngine::EventReceivedL - Status changed" ); - subscription->SetAccountMessageCount( totalMsgs, newMsgs ); - } - - if ( createSMS && statusChanged ) - { - IPVMEPRINT( "CIpVmbxEngine::EventReceivedL - Create message body" ); - TBuf8< KSmsLength > messageBody8; - CreateMessageBodyL( - *content8, - ptrTotalMessages8, - ptrNewMessages8, - ptrFrom8, - messageBody8 ); - CreateSMSMessageL( ptrFrom8, messageBody8 ); - } - - CleanupStack::PopAndDestroy( from8 ); - CleanupStack::PopAndDestroy( newMessages8 ); - CleanupStack::PopAndDestroy( totalMessages8 ); - CleanupStack::PopAndDestroy( content8 ); - - IPVMEPRINT( "CIpVmbxEngine::EventReceivedL - OUT" ); - } - - -// --------------------------------------------------------------------------- -// -// --------------------------------------------------------------------------- -// -void CIpVmbxEngine::UnsubscribeProfileL( TUint32 aServiceProviderId ) - { - IPVMEPRINT2( "CIpVmbxEngine::UnsubscribeProfileL: %d - IN", - aServiceProviderId ); - - CIpVmbxBase* subscription( SubscriptionByProvider( aServiceProviderId ) ); - if ( !subscription ) - { - User::Leave( KErrNotFound ); - } - - IPVMEPRINT2( "CIpVmbxEngine::UnsubscribeProfileL: state=%d", - subscription->State() ); - - switch( subscription->State() ) - { - case CIpVmbxBase::ERegistered: - { - subscription->TerminateEventL(); - break; - } - case CIpVmbxBase::EDisabled: - { - CleanVmbxBase(); - break; - } - case CIpVmbxBase::ESubscribing: - { - subscription->Cancel(); - CleanVmbxBase(); - break; - } - case CIpVmbxBase::ETerminating: - { - User::Leave( KErrCancel ); - break; - } - default: - { - IPVMEPRINT( "No implementation" ); - } - } - - } - - -// ---------------------------------------------------------------------------- -// -// ---------------------------------------------------------------------------- -// -void CIpVmbxEngine::CleanVmbxBase() - { - for ( TInt i = 0; i < iVmbxBaseArray.Count(); i++ ) - { - if ( CIpVmbxBase::ETerminating == iVmbxBaseArray[i]->State() || - CIpVmbxBase::EDisabled == iVmbxBaseArray[i]->State() ) - { - delete iVmbxBaseArray[i]; - iVmbxBaseArray.Remove( i ); - } - } - } - - -// ---------------------------------------------------------------------------- -// -// ---------------------------------------------------------------------------- -// -void CIpVmbxEngine::HandleMessage( - TUint32 aServiceProviderId, - CIpVmbxEngine::TIpVmbxMessages aMessage ) - { - IPVMEPRINT2( "CIpVmbxEngine::HandleMessage: %d - IN", aMessage ); - - CIpVmbxBase* subscription( SubscriptionByProvider( aServiceProviderId ) ); - // Save current state because some functions modify states - CIpVmbxBase::TIpVmbxBaseStates baseState = subscription->State(); - MIpVmbxObserver::TVmbxMessage message = - MIpVmbxObserver::EIncorrectSettings; - TBool send = ETrue; - - switch ( aMessage ) - { - case CIpVmbxEngine::EEngineSubscribed: - message = MIpVmbxObserver::ESubscribed; - break; - case CIpVmbxEngine::EEngineTerminated: - { - if ( CIpVmbxBase::EDisabled != baseState ) - { - CleanVmbxBase(); - message = MIpVmbxObserver::EUnsubscribed; - } - else - { - send = EFalse; - } - break; - } - case CIpVmbxEngine::EEngineUndefined: - { - send = EFalse; - break; - } - case CIpVmbxEngine::EEngineSubscribeRejected: - case CIpVmbxEngine::EEngineIncorrectAccount: - { - subscription->Cancel(); - CleanVmbxBase(); - message = MIpVmbxObserver::EIncorrectSettings; - break; - } - case CIpVmbxEngine::EEngineSmsError: - { - subscription->Cancel(); - message = MIpVmbxObserver::ESmsError; - break; - } - case CIpVmbxEngine::EEngineSmsOom: - message = MIpVmbxObserver::ENoMemory; - break; - case CIpVmbxEngine::EEngineNetworkLost: - { - subscription->Cancel(); - subscription->DeleteEvent(); - send = EFalse; - break; - } - case CIpVmbxEngine::EEngineNetworkError: - { - subscription->Cancel(); - subscription->DeleteEvent(); - message = MIpVmbxObserver::ENetworkError; - break; - } - case CIpVmbxEngine::EEngineFatalNetworkError: - { - subscription->Cancel(); - subscription->DeleteEvent(); - message = MIpVmbxObserver::EFatalNetworkError; - break; - } - default: - IPVMEPRINT( "Unhandled message!" ); - } - - if ( send ) - { - iInterface.SendMessage( aServiceProviderId, message ); - } - - IPVMEPRINT( "CIpVmbxEngine::HandleMessage - OUT" ); - } - - -// ---------------------------------------------------------------------------- -// -// ---------------------------------------------------------------------------- -// -CIpVmbxBase* CIpVmbxEngine::SubscriptionByProvider( - TUint32 aServiceProviderId ) - { - CIpVmbxBase* base( NULL ); - for ( TInt i = 0; i < iVmbxBaseArray.Count(); i++ ) - { - if ( iVmbxBaseArray[i]->ServiceProviderId() == aServiceProviderId ) - { - base = iVmbxBaseArray[i]; - } - } - return base; - } - - -// ---------------------------------------------------------------------------- -// From class MMsvSessionObserver. -// Indicates an event has occurred from a Message Server session. -// ---------------------------------------------------------------------------- -// -void CIpVmbxEngine::HandleSessionEventL( - TMsvSessionEvent /*aEvent*/, - TAny* /*aArg1*/, - TAny* /*aArg2*/, - TAny* /*aArg3*/ ) - { - IPVMEPRINT( "CIpVmbxEngine::HandleSessionEventL - Dummy implementation" ); - } - - -// ---------------------------------------------------------------------------- -// Parses critical and important optional parts of content. Already -// processed data is cut from content. -// ---------------------------------------------------------------------------- -// -void CIpVmbxEngine::ParseNotifyContentL( - TBool& aCreateSms, - TDes8& aContent8, - TDes8& aTotalMessages8, - TDes8& aNewMessages8, - TDes8& aFrom8 ) const - { -#ifdef _DEBUG - HBufC* print = HBufC::NewLC( aContent8.Length() ); - print->Des().Copy( aContent8 ); - IPVMEPRINT2( "CIpVmbxEngine::ParseNotifyContentL - aContent8:%S", &print->Des() ) - CleanupStack::PopAndDestroy( print ); -#endif // _DEBUG - aCreateSms = EFalse; - - // check required content - TLex8 analyzer8; - TPtrC8 posPtr8; - TPtrC8 dataPtr8; - TPtrC8 messagePtr8; - - TInt atPosWaiting = aContent8.FindF( KMessagesWaiting8 ); - // check important OPTIONAL fields - TInt atPosAccount = aContent8.FindF( KMessageAccount8 ); - TInt atPosMessage = aContent8.FindF( KVoiceMessage8 ); - - if ( 0 == atPosWaiting ) - { - // data field found from correct place - messagePtr8.Set( FetchMessagePartL( aContent8 ) ); - analyzer8.Assign( - messagePtr8.Mid( messagePtr8.Find( KColon8 ) + KOneChar ) ); - dataPtr8.Set( analyzer8.NextToken() ); - if ( 0 == dataPtr8.CompareF( KNewMessages8 ) ) - { - // message(s) waiting - aCreateSms = ETrue; - } - // cut processed data - posPtr8.Set( aContent8.Mid( messagePtr8.Length() ) ); - analyzer8.Assign( posPtr8 ); - } - else - { - IPVMEPRINT( "CIpVmbxEngine::ParseNotifyContentL - leave with KErrCorrupt" ); - // malformed critical part of message - User::Leave( KErrCorrupt ); - } - - if ( KErrNotFound != atPosAccount && KErrNotFound != atPosMessage ) - { - // both optionals found - if ( !( atPosAccount < atPosMessage ) ) - { - IPVMEPRINT( "CIpVmbxEngine::ParseNotifyContentL - leave with KErrCorrupt 2" ); - // incorrect format - User::Leave( KErrCorrupt ); - } - } - - if ( KErrNotFound != atPosAccount && aCreateSms ) - { - // get account - IPVMEPRINT( "CIpVmbxEngine::ParseNotifyContentL - get account" ); - messagePtr8.Set( FetchMessagePartL( posPtr8 ) ); - analyzer8.Assign( - messagePtr8.Mid( messagePtr8.Find( KColon8 ) + KOneChar ) ); - dataPtr8.Set( analyzer8.NextToken() ); - posPtr8.Set( posPtr8.Mid( messagePtr8.Length() ) ); - analyzer8.Assign( posPtr8 ); - - - aFrom8.Copy( dataPtr8.Left( aFrom8.MaxLength() ) ); - } - - if ( KErrNotFound != atPosMessage ) - { - messagePtr8.Set( FetchMessagePartL( posPtr8 ) ); - analyzer8.Assign( - messagePtr8.Mid( messagePtr8.Find( KColon8 ) + KOneChar ) ); - - // can hold value required by specification - TUint oldMessageCount = 0; - TUint newMessageCount = 0; - TLex8 value; - - analyzer8.SkipSpace(); - User::LeaveIfError( analyzer8.Val( newMessageCount ) ); - analyzer8.SkipSpace(); - User::LeaveIfError( KSlash8().Locate( analyzer8.Get() ) ); - - analyzer8.SkipSpace(); - User::LeaveIfError( analyzer8.Val( oldMessageCount ) ); - - aNewMessages8.Num( newMessageCount ); - aTotalMessages8.Num( ( TInt64 ) oldMessageCount + ( TInt64 ) newMessageCount ); - - posPtr8.Set( posPtr8.Mid( messagePtr8.Length() ) ); - } - - // Clean string off processed data - aContent8.Delete( 0, aContent8.Length() - posPtr8.Length() ); - - IPVMEPRINT( "CIpVmbxEngine::ParseNotifyContentL - OUT" ); - } - - -// ---------------------------------------------------------------------------- -// Creates SMS message and sends it -// ---------------------------------------------------------------------------- -// -void CIpVmbxEngine::CreateSMSMessageL( - const TDesC8& aFrom8, - const TDesC8& aMessageBody8 ) - { - IPVMEPRINT( "CIpVmbxEngine::CreateSMSMessageL - IN" ); - - // Create the SMS header object... - CParaFormatLayer* paraFormatLayer = CParaFormatLayer::NewL(); - CleanupStack::PushL( paraFormatLayer ); - CCharFormatLayer* charFormatLayer = CCharFormatLayer::NewL(); - CleanupStack::PushL( charFormatLayer ); - - CRichText* bodyText = CRichText::NewL( paraFormatLayer, charFormatLayer ); - CleanupStack::PushL( bodyText ); - TInt position = 0; - TBuf< KSmsLength > messageBody; - messageBody.Copy( aMessageBody8.Left( messageBody.MaxLength() ) ); - bodyText->InsertL( position, messageBody ); - - CSmsHeader* header = CSmsHeader::NewL( CSmsPDU::ESmsDeliver, *bodyText ); - CleanupStack::PushL( header ); - TBuf< KMaxIpVoiceMailBoxUriLength > from; - from.Copy( aFrom8 ); - header->SetFromAddressL( from ); - - TMsvEntry entry; - entry.SetVisible(ETrue ); - entry.SetUnread( ETrue ); - entry.SetNew( ETrue ); - entry.iServiceId = KMsvRootIndexEntryId; - entry.iType = KUidMsvMessageEntry; - entry.iMtm = KUidMsgTypeSMS; - entry.iDate.UniversalTime(); - entry.iSize = 0; - entry.iDescription.Set( KNullDesC ); - entry.iDetails.Set( KNullDesC ); - - header->Deliver().SetServiceCenterTimeStamp( entry.iDate ); - - CSmsSettings* smsSettings = CSmsSettings::NewL(); - CleanupStack::PushL( smsSettings ); - smsSettings->SetDelivery( ESmsDeliveryImmediately ); - smsSettings->SetValidityPeriod( ESmsVPWeek ); - smsSettings->SetValidityPeriodFormat( TSmsFirstOctet::ESmsVPFInteger ); - smsSettings->SetReplyQuoted( EFalse ); - smsSettings->SetRejectDuplicate( ETrue ); - smsSettings->SetDelivery( ESmsDeliveryImmediately ); - smsSettings->SetDeliveryReport( ETrue ); - smsSettings->SetReplyPath( EFalse ); - smsSettings->SetMessageConversion( ESmsConvPIDNone ); - smsSettings->SetCanConcatenate( ETrue ); - smsSettings->SetUseServiceCenterTimeStampForDate( ETrue ); - - header->SetSmsSettingsL(*smsSettings ); - - CSmsNumber* rcpt = CSmsNumber::NewL(); - CleanupStack::PushL( rcpt ); - rcpt->SetAddressL( from.Left( KSmcmSmsNumberMaxNumberLength ) ); - header->Recipients().AppendL( rcpt ); - CleanupStack::Pop( rcpt ); - - // Update entry description and details... - CArrayPtrFlat< CSmsNumber >& recipient = header->Recipients(); - entry.iDetails.Set( recipient[0]->Address() ); - entry.iDescription.Set( bodyText->Read( - 0, smsSettings->DescriptionLength() )); - entry.SetInPreparation( EFalse ); - - // Create the entry - set context to the global outbox. - TMsvSelectionOrdering ordering = TMsvSelectionOrdering( - KMsvNoGrouping, - EMsvSortByDescription, - ETrue ); - CMsvSession* session = CMsvSession::OpenSyncL( *this ); - CleanupStack::PushL( session ); - CMsvEntry* centry = CMsvEntry::NewL( - *session, KMsvRootIndexEntryId, ordering ); - CleanupStack::PushL( centry ); - centry->SetEntryL( KMsvGlobalInBoxIndexEntryId ); - centry->CreateL( entry ); - - // Create new store and save header information - centry->SetEntryL( entry.Id() ); - CMsvStore* store = centry->EditStoreL(); - CleanupStack::PushL(store); - header->StoreL( *store ); - store->StoreBodyTextL( *bodyText ); - store->CommitL(); - - CleanupStack::PopAndDestroy( store ); - CleanupStack::PopAndDestroy( centry ); - CleanupStack::PopAndDestroy( session ); - CleanupStack::PopAndDestroy( smsSettings ); - CleanupStack::PopAndDestroy( header ); - CleanupStack::PopAndDestroy( bodyText ); - CleanupStack::PopAndDestroy( charFormatLayer ); - CleanupStack::PopAndDestroy( paraFormatLayer ); - - IPVMEPRINT( "CIpVmbxEngine::CreateSMSMessageL - OUT" ); - } - - -// ---------------------------------------------------------------------------- -// Parse optional headers. Parser must take account various optional -// characters in headers. String lengths are monitored every round to prevent -// panics when setting data. -// ---------------------------------------------------------------------------- -// -void CIpVmbxEngine::ParseOptionalHeadersL( - const TDesC8& aContent8, - TDes8& aMessageBody8 ) const - { - IPVMEPRINT( "CIpVmbxEngine::ParseOptionalHeadersL - IN" ); - - if ( aContent8.Left( KCrlf8().Length() ).Compare( KCrlf8 ) || - aContent8.Length() == KTwoChars ) - { - // Checking if optional message does not exist or its too short. - // Will also fix parsing of non standard basic Pingtel message. - // - User::Leave( KErrNotFound ); - } - - TFileName dll; - Dll::FileName( dll ); - TFileName fileName( TParsePtrC( dll ).Drive() ); - fileName += KIpVmbxAppEngineResourceFileDirectory; - fileName += KIpVmbxAppEngineResourceFileName; - CStringResourceReader* resourceReader = - CStringResourceReader::NewL( fileName ); - CleanupStack::PushL( resourceReader ); - - if ( aMessageBody8.MaxLength() == aMessageBody8.Length() ) - { - User::Leave( KErrOverflow ); - } - else - { - // Add another separator before optional messages - aMessageBody8.Append( KEndLine8 ); - } - - TPtrC8 messagePtr8; - TPtrC8 tagPtr8; - TPtrC8 dataPtr8; - TPtrC8 posPtr8( aContent8 ); - TPtrC8 colon8; - TInt messages = 0; - HBufC* locTemp( HBufC::NewLC( KSmsLength ) ); - TPtr locPtr( locTemp->Des() ); - TPtrC resourcePtr( resourceReader->ReadResourceString( R_VOIP_VM_HEADER_COUNT ) ); - HBufC* variant( NULL ); - TLex8 analyzer8; - HBufC8* partTemp( HBufC8::NewLC( KSmsLength ) ); - TPtr8 partPtr( partTemp->Des() ); - TBool messageEmpty = EFalse; // prevents creation of empty optional message part - TBool appendMsgChange = EFalse; - // Start sorting through message - do - { - if ( ( KErrNotFound != - posPtr8.Left( KCrlf8().Length() ).FindF( KCrlf8 ) || - 0 == messages ) && !messageEmpty ) - { - // beginning of optional messages or another optional message - if ( messages <= KMaxMsgDescriptions ) - { - // add message count for first/next optional message - // count is limited to two numbers = 99 (prevents also overflow when - // KTotal is replaced) - TBuf< KTwoChars > appendNum; - appendNum.AppendNum( ++messages ); - locPtr.Zero(); - locPtr.Append( KOptionalSeparator ); - locPtr.Append( resourcePtr ); - locPtr.Replace( locPtr.Find( KTotal ), KTotal().Length(), appendNum ); - locPtr.Append( KEndLine ); - posPtr8.Set( posPtr8.Mid( KCrlf8().Length() ) ); - messageEmpty = ETrue; - appendMsgChange = ETrue; - } - else - { - User::Leave( KErrOverflow ); - } - } - messagePtr8.Set( FetchMessagePartL( posPtr8 ) ); - analyzer8.Assign( - messagePtr8.Left( messagePtr8.Find( KColon8 ) + KOneChar ) ); - tagPtr8.Set( analyzer8.NextToken() ); - if ( KErrNotFound == tagPtr8.Find( KColon8 ) ) - { - // colon required - colon8.Set( analyzer8.NextToken() ); - } - analyzer8.Assign( - messagePtr8.Mid( messagePtr8.Find( KColon8 ) + KOneChar ) ); - analyzer8.SkipSpace(); // skipping ws's since one newline is added later - if ( analyzer8.Eos() ) - { - // data contained only ws's we must decrease counter by length of CRLF - analyzer8.UnGet(); - analyzer8.UnGet(); - } - dataPtr8.Set( - messagePtr8.Mid( - messagePtr8.Find( KColon8 ) + KOneChar + analyzer8.Offset(), - analyzer8.Remainder().Length() - KCrlf8().Length() ) ); - posPtr8.Set( posPtr8.Mid( messagePtr8.Length() ) ); - analyzer8.Assign( posPtr8 ); - - variant = TranslateTagL( tagPtr8, *resourceReader ); - - if ( variant && - variant->Length() + dataPtr8.Length() + KOneChar < - partPtr.MaxLength() - partPtr.Length() ) - { - // Resource translated to users phone variant language. - // Optional message headers other than these aren't supported - // because language cannot be verified and might differ from phone - // variant language. - partPtr.Append( *variant ); - partPtr.Append( dataPtr8 ); - partPtr.Append( KEndLine8 ); - messageEmpty = EFalse; - } - delete variant; - variant = NULL; - - if ( !appendMsgChange && !messageEmpty && aMessageBody8.MaxLength() - aMessageBody8.Length() >= partPtr.Length() ) - { - aMessageBody8.Append( partPtr ); - partPtr.Zero(); - } - else - if ( !messageEmpty && aMessageBody8.MaxLength() - aMessageBody8.Length() >= partPtr.Length() + locPtr.Length() ) - { - // Content OK, append to actual actual message - aMessageBody8.Append( locPtr ); - aMessageBody8.Append( partPtr ); - partPtr.Zero(); - messageEmpty = EFalse; - appendMsgChange = EFalse; - } - else - { - // partial ptr was too long for message, reset and try next part from content - partPtr.Zero(); - messageEmpty = ETrue; - } - - }while( !analyzer8.Eos() ); - - CleanupStack::PopAndDestroy( partTemp ); - CleanupStack::PopAndDestroy( locTemp ); - CleanupStack::PopAndDestroy( resourceReader ); - - IPVMEPRINT( "CIpVmbxEngine::ParseOptionalHeadersL - OUT" ); - } - - -// ---------------------------------------------------------------------------- -// -// ---------------------------------------------------------------------------- -// -void CIpVmbxEngine::ReadResourcesL( - const TDesC8& aTotalMessages8, - const TDesC8& aNewMessages8, - TDes8& aMessagesBody8 ) - { - IPVMEPRINT( "CIpVmbxEngine::ReadResourcesL - IN" ); - __ASSERT_DEBUG( KSmsLength == aMessagesBody8.MaxLength(), Panic( KErrArgument ) ); - - TFileName dll; - Dll::FileName( dll ); - TFileName fileName( TParsePtrC( dll ).Drive() ); - fileName += KIpVmbxAppEngineResourceFileDirectory; - fileName += KIpVmbxAppEngineResourceFileName; - CStringResourceReader* resourceReader = - CStringResourceReader::NewL( fileName ); - CleanupStack::PushL( resourceReader ); - TPtrC messageText; - - if( !aTotalMessages8.Length() ) - { - messageText.Set( - resourceReader->ReadResourceString( R_VOIP_VM_MSG_SUM_UNKNOWN ) ); - aMessagesBody8.Copy( messageText ); - } - else if( !aNewMessages8.Compare( KOneMessage ) && - !aTotalMessages8.Compare( KOneMessage ) ) - { - messageText.Set( - resourceReader->ReadResourceString( R_VOIP_NEW_VOICE_MESSAGE ) ); - aMessagesBody8.Copy( messageText ); - } - else if( !aNewMessages8.Compare( KOneMessage ) && - aTotalMessages8.Compare( KOneMessage ) ) - { - TBuf< KSmsLength > tempText; - messageText.Set( - resourceReader->ReadResourceString( - R_VOIP_NEW_AND_OLD_VOICE_MSG ) ); - tempText.Copy( messageText ); - TInt atPosFirst = tempText.Find( KTotal ); - TInt messageLength = tempText.Length(); - TPtrC messagePart1 = tempText.Mid( 0 , atPosFirst ); - aMessagesBody8.Copy( messagePart1 ); - aMessagesBody8.Append( aTotalMessages8.Left( KMaxMessageDigits ) ); - TPtrC messagePart2 = tempText.Mid( - atPosFirst + KTotalLength, - messageLength - atPosFirst - KTotalLength ); - aMessagesBody8.Append( messagePart2 ); - } - else if( aNewMessages8.Compare( KOneMessage ) && - aTotalMessages8.Compare( KOneMessage ) ) - { - messageText.Set( - resourceReader->ReadResourceString( R_VOIP_NEW_VOICE_MESSAGES ) ); - - // Search new messages location and replace with real value - TBuf8< KSmsLength > messagePart1; - TInt pos = messageText.Find( KTotalNew ); - messagePart1.Copy( messageText.Left( pos ) ); - messagePart1.Append( aNewMessages8.Left( KMaxMessageDigits ) ); - messagePart1.Append( messageText.Mid( pos + KTotalOldLength ) ); - - // Search total messages location and replace with real value - TBuf8< KSmsLength > messagePart2; - pos = messagePart1.Find( KTotalOld ); - messagePart2.Copy( messagePart1.Left( pos ) ); - messagePart2.Append( aTotalMessages8.Left( KMaxMessageDigits ) ); - messagePart2.Append( messagePart1.Mid( pos + KTotalOldLength ) ); - - aMessagesBody8.Append( messagePart2 ); - } - - aMessagesBody8.Append( KEndLine ); - aMessagesBody8.Append( KEndLine ); - aMessagesBody8.Append( - resourceReader->ReadResourceString( R_VOIP_VM_MSG_ACCOUNT ) ); - - CleanupStack::PopAndDestroy( resourceReader ); - - IPVMEPRINT( "CIpVmbxEngine::ReadResourcesL - OUT" ); - } - -// ---------------------------------------------------------------------------- -// -// ---------------------------------------------------------------------------- -// -void CIpVmbxEngine::CreateMessageBodyL( - const TDesC8& aContent8, - const TDesC8& aTotal8, - const TDesC8& aNew8, - TDes8& aFrom8, - TDes8& aMessageBody8 ) - { - aFrom8.TrimRight(); - if ( 0 == aFrom8.Length() ) - { - User::Leave( KErrArgument ); - } - - ReadResourcesL( - aTotal8, - aNew8, - aMessageBody8 ); - - if( aFrom8.Length() && - aMessageBody8.Length() + aFrom8.Length() < KSmsLength ) - { - aMessageBody8.Append( aFrom8 ); - } - - TRAP_IGNORE( ParseOptionalHeadersL( aContent8, aMessageBody8 ) ); - } - -// ---------------------------------------------------------------------------- -// Creates translated tag from resources -// ---------------------------------------------------------------------------- -// -HBufC* CIpVmbxEngine::TranslateTagL( - const TDesC8& aTagPtr8, - CStringResourceReader& aResourceReader ) const - { - HBufC* locTemp( NULL ); - TLex8 analyzer8( aTagPtr8 ); - TPtrC8 tag( analyzer8.NextToken() ); - if ( KErrNotFound != tag.Find( KColon8 ) ) - { - // remove possible colon char to make tag matching easier - tag.Set( tag.Left( tag.Length() - KOneChar ) ); - } - TIpVmbxParseType::TParseTypes i = TIpVmbxParseType::EDetailTo; - TIpVmbxParseType parseType; - for ( ;i <= TIpVmbxParseType::EDetailId; i++ ) - { - parseType.Set( i ); - if ( 0 == tag.MatchF( parseType.Tag() ) ) - { - i = TIpVmbxParseType::EDetailId; - locTemp = - aResourceReader.ReadResourceString( - parseType.ResourceId() ).AllocL(); - } - }; - - return locTemp; - } - -// ---------------------------------------------------------------------------- -// Gets and validates part of message. -// ---------------------------------------------------------------------------- -// -TPtrC8 CIpVmbxEngine::FetchMessagePartL( const TDesC8& aContent8 ) const - { - IPVMEPRINT( "CIpVmbxEngine::FetchMessagePartL - IN" ); - - TInt crlf = User::LeaveIfError( aContent8.FindF( KCrlf8 ) ) + KCrlf8().Length(); - // check for optional CRLF - while( crlf < aContent8.Length() && - ( KErrNotFound != KHTab8().Locate( aContent8[crlf] ) || - KErrNotFound != KSpace8().Locate( aContent8[crlf] ) ) ) - { - // This was optional CRLF, try next one - crlf += User::LeaveIfError( aContent8.Mid( crlf ).FindF( KCrlf8 ) ) + KTwoChars; - } - // now we should have correct partial data - TPtrC8 part8( aContent8.Left( crlf ) ); - TLex8 analyzer8( part8 ); - - TPtrC8 tagPtr8( - part8.Left( User::LeaveIfError( part8.Find( KColon8 ) ) ) ); - if ( !tagPtr8.Length() ) - { - // At least one character required - User::Leave( KErrCorrupt ); - } - TestNamePartL( tagPtr8 ); - - TPtrC8 dataPtr8( part8.Mid( tagPtr8.Length() ) ); - TestValuePartL( dataPtr8 ); - - IPVMEPRINT( "CIpVmbxEngine::FetchMessagePartL - OUT" ); - return aContent8.Left( part8.Length() ); - } - -// ---------------------------------------------------------------------------- -// Validates name part of message. -// ---------------------------------------------------------------------------- -// -void CIpVmbxEngine::TestNamePartL( const TDesC8& aNameHeader8 ) const - { - // Check legal chars %x41-5A / %x61-7A %x30-39 ( 2d, 2e, 21, 25, 2a, 5f, 2b, 60, 27, 7e) - // from name header - const TFixedArray< TText8, KSpecialNameCharsCount > legalCharsArray( - &KSpecialNameChars[0], KSpecialNameCharsCount ); - TChar curChar; - TLex8 analyzer8( aNameHeader8 ); - curChar = analyzer8.Get(); - TBool valid = ETrue; - while ( !curChar.Eos() && valid ) - { - valid = EFalse; - if ( KNameDigitLowest <= curChar && KNameDigitHighest >= curChar || - KNameCharUpLowest <= curChar && KNameCharUpHighest >= curChar || - KNameCharLowLowest <= curChar && KNameCharLowHighest >= curChar ) - { - valid = ETrue; - } - for ( TInt i = 0; legalCharsArray.Count() > i && !valid; i++ ) - { - if ( curChar == legalCharsArray.At( i ) ) - { - valid = ETrue; - } - } - if ( valid ) - { - curChar = analyzer8.Get(); - } - } - if ( !valid ) - { - valid = ETrue; - while ( !curChar.Eos() && valid ) - { - valid = EFalse; - if ( KSpace == curChar || KHTab == curChar ) - { - valid = ETrue; - } - curChar = analyzer8.Get(); - } - } - if ( !valid ) - { - User::Leave( KErrCorrupt ); - } - } - -// ---------------------------------------------------------------------------- -// Validates value part of message. -// ---------------------------------------------------------------------------- -// -void CIpVmbxEngine::TestValuePartL( const TDesC8& aValueHeader8 ) const - { - TBool valid = ETrue; - TChar curChar; - TLex8 analyzer8( aValueHeader8 ); - curChar = analyzer8.Get(); - - while ( !curChar.Eos() && valid ) - { - valid = EFalse; - if ( KValueLowestChar <= curChar && KValueHighestChar >= curChar ) - { - valid = ETrue; - } - else - if ( KCr == curChar || KLf == curChar || KHTab == curChar ) - { - valid = ETrue; - } - curChar = analyzer8.Get(); - } - if ( !valid ) - { - User::Leave( KErrCorrupt ); - } - } -