--- a/voipplugins/sipconnectionprovider/ipvoicemailengine/src/ipvmbxengine.cpp Tue Feb 02 00:05:57 2010 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1256 +0,0 @@
-/*
-* Copyright (c) 2002-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: 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 <smuthdr.h>/*messaging/\sms/\*/
-#include <msvuids.h>
-#include <txtrich.h>
-#include <spsettings.h>
-#include <spproperty.h>
-#include <utf.h>
-#include <mcemanager.h>
-#include <ipvoicemailengine.rsg>
-
-#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( KLParen8, "(" );
-_LIT8( KRParen8, ")" );
-_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 )
- {
- User::Leave( KErrNotFound );
- }
- IPVMEPRINT( "CIpVmbxEngine::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
- 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;
- subscription->SetAccountMessageCount( totalMsgs, newMsgs );
- }
-
- if ( createSMS && statusChanged )
- {
- 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 )
- {
- CIpVmbxBase* subscription( SubscriptionByProvider( aServiceProviderId ) );
- if ( !subscription )
- {
- User::Leave( KErrNotFound );
- }
-
- 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;
- }
- 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
- {
- IPVMEPRINT( "CIpVmbxEngine::ParseNotifyContentL - IN" );
- 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
- {
- // malformed critical part of message
- User::Leave( KErrCorrupt );
- }
-
- if ( KErrNotFound != atPosAccount && KErrNotFound != atPosMessage )
- {
- // both optionals found
- if ( !( atPosAccount < atPosMessage ) )
- {
- // incorrect format
- User::Leave( KErrCorrupt );
- }
- }
-
- if ( KErrNotFound != atPosAccount && aCreateSms )
- {
- // 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 && aCreateSms )
- {
- 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 ) );
- // save result here because of leaving parts above
- aNewMessages8.Num( newMessageCount );
- // result saved here in case of leave from optional parsing of optional part below
- aTotalMessages8.Num( ( TInt64 ) oldMessageCount + ( TInt64 ) newMessageCount );
-
- analyzer8.SkipSpace();
- if ( KErrNotFound != KLParen8().Locate( analyzer8.Get() ) )
- {
- // urgent messages found
- TUint urgentNew = 0;
- TUint urgentOld = 0;
- User::LeaveIfError( analyzer8.Val( urgentNew ) );
- analyzer8.SkipSpace();
- User::LeaveIfError( KSlash8().Locate( analyzer8.Get() ) );
-
- User::LeaveIfError( analyzer8.Val( urgentOld ) );
- newMessageCount += urgentNew;
- oldMessageCount += urgentOld;
- analyzer8.SkipSpace();
- User::LeaveIfError( KRParen8().Locate( analyzer8.Get() ) );
- }
- // save status again, might have updated
- 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 );
- }
- }
-