voipplugins/sipconnectionprovider/ipvoicemailengine/src/ipvmbxengine.cpp
branchRCL_3
changeset 21 f742655b05bf
parent 20 65a3ef1d5bd0
child 22 d38647835c2e
equal deleted inserted replaced
20:65a3ef1d5bd0 21:f742655b05bf
     1 /*
       
     2 * Copyright (c) 2002-2010 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Creates SMS message if Event in MailBox has occurred.
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 // Include hierarchy change can't be done. Smuthdr.h uses
       
    21 // other files from messaging/sms (smsstd.h and smutset.h). It doesn't seem
       
    22 // to find them without old way to declare include folder using SYSTEMINCLUDE.
       
    23 //
       
    24 #include <smuthdr.h>/*messaging/\sms/\*/
       
    25 #include <msvuids.h>
       
    26 #include <txtrich.h>
       
    27 #include <spsettings.h>
       
    28 #include <spproperty.h>
       
    29 #include <utf.h>
       
    30 #include <mcemanager.h>
       
    31 #include <ipvoicemailengine.rsg>
       
    32 
       
    33 #include "ipvmbxengine.h"
       
    34 #include "ipvmbxeventmonitor.h"
       
    35 #include "ipvmbxbase.h"
       
    36 #include "ipvmbxlogger.h"
       
    37 #include "ipvmbxconstants.h"
       
    38 #include "ipvmbxpanic.h"
       
    39 
       
    40 
       
    41 const TUid KAppUID = { 0x1020596F };
       
    42 const TInt KMaxMessageDigits = 10;
       
    43 const TInt KAccountTextLength = 21;
       
    44 const TInt KOneChar = 1;
       
    45 const TInt KTwoChars = 2;
       
    46 const TInt KSmsLength = 160;
       
    47 const TInt KTotalLength = 2;
       
    48 const TInt KTotalOldLength = 3;
       
    49 const TInt KMinIpVoiceMailBoxUriLength = 3;
       
    50 const TInt KSpecialNameCharsCount = 10;
       
    51 const TInt KMaxMsgDescriptions = 99;
       
    52 
       
    53 _LIT( KEndLine, "\n" );
       
    54 _LIT( KTotal, "%N" );
       
    55 _LIT( KTotalNew, "%0N" );
       
    56 _LIT( KIpVmbxAppEngineResourceFileDirectory, "\\resource\\" );
       
    57 _LIT( KIpVmbxAppEngineResourceFileName, "ipvoicemailengine.rsc" );
       
    58 _LIT( KSipString, "sip:");
       
    59 _LIT( KOptionalSeparator, "\n\n" );
       
    60 _LIT8( KTotalOld, "%1N" );
       
    61 _LIT8( KOneMessage, "1" );
       
    62 _LIT8( KNoMessages, "0" );
       
    63 _LIT8( KMessagesWaiting8, "messages-waiting" );
       
    64 _LIT8( KNewMessages8, "yes" );
       
    65 _LIT8( KMessageAccount8, "message-account" );
       
    66 _LIT8( KVoiceMessage8, "voice-message" );
       
    67 _LIT8( KSlash8, "/" );
       
    68 _LIT8( KColon8, ":" );
       
    69 _LIT8( KCrlf8, "\r\n" );
       
    70 _LIT8( KEndLine8, "\n" );
       
    71 _LIT8( KHTab8, "\t");
       
    72 _LIT8( KSpace8, " ");
       
    73 
       
    74 const TText KNameDigitLowest = '\x30';
       
    75 const TText KNameDigitHighest = '\x39';
       
    76 const TText KNameCharUpLowest = '\x41';
       
    77 const TText KNameCharUpHighest = '\x5a';
       
    78 const TText KNameCharLowLowest = '\x61';
       
    79 const TText KNameCharLowHighest = '\x7a';
       
    80 // Legal characters in name header
       
    81 // 2d, 2e, 21, 25, 2a, 5f, 2b, 60, 27, 7e
       
    82 const TText8 KSpecialNameChars[KSpecialNameCharsCount] =
       
    83     {
       
    84     '-',
       
    85     '.',
       
    86     '!',
       
    87     '%',
       
    88     '*',
       
    89     '_',
       
    90     '+',
       
    91     '`',
       
    92     '\'',
       
    93     '~'
       
    94     };
       
    95 const TText KSpace = '\x20';
       
    96 const TText KValueLowestChar = KSpace;
       
    97 const TText KValueHighestChar = '\xfd';
       
    98 const TText KCr = '\x0d';
       
    99 const TText KLf = '\x0a';
       
   100 const TText KHTab = '\x09';
       
   101 
       
   102 
       
   103 // ============================ MEMBER FUNCTIONS ==============================
       
   104 
       
   105 // ----------------------------------------------------------------------------
       
   106 // C++ default constructor can NOT contain any code, that
       
   107 // might leave.
       
   108 // ----------------------------------------------------------------------------
       
   109 //
       
   110 CIpVmbxEngine::CIpVmbxEngine( CIpVmbxInterface& aInterface ):
       
   111     iEventData(),
       
   112     iInterface( aInterface )
       
   113     {
       
   114     }
       
   115 
       
   116 
       
   117 // ----------------------------------------------------------------------------
       
   118 // Symbian 2nd phase constructor can leave.
       
   119 // ----------------------------------------------------------------------------
       
   120 //
       
   121 void CIpVmbxEngine::ConstructL()
       
   122     {
       
   123     // One manager = one event observer (restricted)
       
   124     iIpVmbxEventMonitor = new ( ELeave ) TIpVmbxEventMonitor( *this );
       
   125     }
       
   126 
       
   127 
       
   128 // ----------------------------------------------------------------------------
       
   129 // Two-phased constructor.
       
   130 // ----------------------------------------------------------------------------
       
   131 //
       
   132 EXPORT_C CIpVmbxEngine* CIpVmbxEngine::NewL( CIpVmbxInterface& aInterface )
       
   133     {
       
   134     IPVMEPRINT( "CIpVmbxEngine::NewL" );
       
   135 
       
   136     CIpVmbxEngine* self = new( ELeave ) CIpVmbxEngine( aInterface );
       
   137     CleanupStack::PushL( self );
       
   138     self->ConstructL();
       
   139     CleanupStack::Pop( self );
       
   140 
       
   141     return self;
       
   142     }
       
   143 
       
   144 
       
   145 // ----------------------------------------------------------------------------
       
   146 // Destructor.
       
   147 // ----------------------------------------------------------------------------
       
   148 //
       
   149 CIpVmbxEngine::~CIpVmbxEngine()
       
   150     {
       
   151     IPVMEPRINT( "CIpVmbxEngine::~CIpVmbxEngine - IN" );
       
   152 
       
   153     iVmbxBaseArray.ResetAndDestroy();
       
   154     iVmbxBaseArray.Close();
       
   155 
       
   156     delete iMceManager;
       
   157     delete iServiceSettings;
       
   158     delete iIpVmbxEventMonitor;
       
   159 
       
   160     IPVMEPRINT( "CIpVmbxEngine::~CIpVmbxEngine - OUT" );
       
   161     }
       
   162 
       
   163 
       
   164 // ----------------------------------------------------------------------------
       
   165 // Starts subscription to VoiceMailBox -server
       
   166 // ----------------------------------------------------------------------------
       
   167 //
       
   168 void CIpVmbxEngine::SubscribeProfileL(
       
   169     TUint32 aServiceProviderId,
       
   170     CSIPProfile& aSipProfile )
       
   171     {
       
   172     IPVMEPRINT( "CIpVmbxEngine::SubscribeProfileL - IN" );
       
   173 
       
   174     if ( !iBasicServicesRunning )
       
   175         {
       
   176         iServiceSettings = CSPSettings::NewL();
       
   177         // one manager recommended for one component
       
   178         iMceManager = CMceManager::NewL( KAppUID, &iEventData );
       
   179         iMceManager->SetEventObserver( iIpVmbxEventMonitor );
       
   180         iBasicServicesRunning = ETrue;
       
   181         }
       
   182 
       
   183     HBufC16* voiceMailUri16 = HBufC16::NewLC( KMaxIpVoiceMailBoxUriLength );
       
   184     TPtr16 ptrvoiceMailUri16( voiceMailUri16->Des() );
       
   185     TInt reSubscribe = 0;
       
   186 
       
   187     // Fetch MWI address
       
   188     CSPProperty* mwiAddress = CSPProperty::NewLC();
       
   189     User::LeaveIfError( iServiceSettings->FindPropertyL(
       
   190         aServiceProviderId,
       
   191         ESubPropertyVMBXMWIAddress,
       
   192         *mwiAddress ) );
       
   193     User::LeaveIfError( mwiAddress->GetValue( ptrvoiceMailUri16 ) );
       
   194     if ( ptrvoiceMailUri16.Length() < KMinIpVoiceMailBoxUriLength )
       
   195         {
       
   196         IPVMEPRINT( "CIpVmbxEngine::SubscribeProfileL - MWI not found, Leaving..." );
       
   197         User::Leave( KErrNotFound );
       
   198         }
       
   199     IPVMEPRINT( "CIpVmbxEngine::SubscribeProfileL - MWI found" );
       
   200     if ( KErrNotFound == ptrvoiceMailUri16.Find( KSipString ) )
       
   201         {
       
   202         ptrvoiceMailUri16.Insert( 0, KSipString );
       
   203         }
       
   204     CleanupStack::PopAndDestroy( mwiAddress );
       
   205 
       
   206     // Fetch also subscribe interval
       
   207     CSPProperty* mwiInterval = CSPProperty::NewLC();
       
   208     User::LeaveIfError( iServiceSettings->FindPropertyL(
       
   209         aServiceProviderId,
       
   210         ESubPropertyVMBXMWISubscribeInterval,
       
   211         *mwiInterval) );
       
   212     User::LeaveIfError( mwiInterval->GetValue( reSubscribe ) );
       
   213     CleanupStack::PopAndDestroy( mwiInterval );
       
   214 
       
   215     HBufC8* voiceMailUri8 = CnvUtfConverter::ConvertFromUnicodeToUtf8L(
       
   216         ptrvoiceMailUri16 );
       
   217     CleanupStack::PopAndDestroy( voiceMailUri16 );
       
   218     CleanupStack::PushL( voiceMailUri8 );
       
   219 
       
   220     TInt index = iVmbxBaseArray.Count();
       
   221     TBool newProfile = ETrue;
       
   222     if ( index )
       
   223         {
       
   224         // Might be second subscription or pending operation.
       
   225         // Though IPVME and SCP supports currently only one VMBX connection
       
   226         for ( TInt i = 0; i < index; i++ )
       
   227             {
       
   228             CIpVmbxBase* const subscription( iVmbxBaseArray[i] );
       
   229             if ( *voiceMailUri8 == subscription->VmbxUrl() )
       
   230                 {
       
   231                 // Subscription already exists
       
   232                 if ( CIpVmbxBase::EDisabled == subscription->State() )
       
   233                     {
       
   234                     // Subscription was disabled, enable
       
   235                     newProfile = EFalse;
       
   236                     subscription->Initialize(
       
   237                         aServiceProviderId,
       
   238                         aSipProfile );
       
   239 
       
   240                     subscription->SubscribeL( reSubscribe );
       
   241                     }
       
   242                 else
       
   243                     {
       
   244                     User::Leave( KErrAlreadyExists );
       
   245                     }
       
   246                 }
       
   247             }
       
   248         }
       
   249     if ( newProfile )
       
   250         {
       
   251         // Subscription to new VMBX account
       
   252         IPVMEPRINT( "CIpVmbxEngine::New AppBase" );
       
   253         CIpVmbxBase* app = CIpVmbxBase::NewL(
       
   254             *this,
       
   255             *voiceMailUri8,
       
   256             *iMceManager );
       
   257         CleanupStack::PushL( app );
       
   258         iVmbxBaseArray.AppendL( app );
       
   259         CleanupStack::Pop( app );
       
   260 
       
   261         app->Initialize( aServiceProviderId, aSipProfile );
       
   262         app->SubscribeL( reSubscribe );
       
   263         }
       
   264 
       
   265     CleanupStack::PopAndDestroy( voiceMailUri8 );
       
   266 
       
   267     IPVMEPRINT( "CIpVmbxEngine::SubscribeProfileL - OUT" );
       
   268     }
       
   269 
       
   270 
       
   271 // ---------------------------------------------------------------------------
       
   272 //
       
   273 // ---------------------------------------------------------------------------
       
   274 //
       
   275 TInt CIpVmbxEngine::ProfileSubscribed(
       
   276     TUint32 aServiceProviderId,
       
   277     TBool& aProfileSubscribed )
       
   278     {
       
   279     CIpVmbxBase* subscription( SubscriptionByProvider( aServiceProviderId ) );
       
   280     TInt err = KErrNotFound;
       
   281 
       
   282     if ( subscription )
       
   283         {
       
   284         err = KErrNone;
       
   285         if ( CIpVmbxBase::ERegistered == subscription->State() )
       
   286             {
       
   287             aProfileSubscribed = ETrue;
       
   288             }
       
   289         else
       
   290             {
       
   291             aProfileSubscribed = EFalse;
       
   292             }
       
   293         }
       
   294 
       
   295     return err;
       
   296     }
       
   297 
       
   298 
       
   299 // ---------------------------------------------------------------------------
       
   300 // Resolve base class matching to recipient
       
   301 // ---------------------------------------------------------------------------
       
   302 //
       
   303 CIpVmbxBase* CIpVmbxEngine::SubscriptionByRecipient(
       
   304     const TDesC8& aRecipient8 )
       
   305     {
       
   306     CIpVmbxBase* base( NULL );
       
   307 
       
   308     for ( TInt i = 0; i < iVmbxBaseArray.Count(); i++ )
       
   309         {
       
   310         if ( iVmbxBaseArray[i]->VmbxUrl() == aRecipient8 )
       
   311             {
       
   312             base = iVmbxBaseArray[i];
       
   313             }
       
   314         }
       
   315 
       
   316     return base;
       
   317     }
       
   318 
       
   319 
       
   320 // ----------------------------------------------------------------------------
       
   321 // EventMonitor has received event and the event will be gained and checked
       
   322 // ----------------------------------------------------------------------------
       
   323 //
       
   324 void CIpVmbxEngine::EventReceivedL( const TDesC8& aRecipient8 )
       
   325     {
       
   326     IPVMEPRINT( "CIpVmbxEngine::EventReceivedL - IN" );
       
   327 
       
   328     CIpVmbxBase* subscription( SubscriptionByRecipient( aRecipient8 ) );
       
   329     if ( !subscription )
       
   330         {
       
   331         User::Leave( KErrNotFound );
       
   332         }
       
   333 
       
   334     HBufC8* content8( iEventData.GetContent() );
       
   335     CleanupStack::PushL( content8 );
       
   336 
       
   337     HBufC8* totalMessages8 = HBufC8::NewLC( KMaxMessageDigits );
       
   338     HBufC8* newMessages8 = HBufC8::NewLC( KMaxMessageDigits );
       
   339     HBufC8* from8 = HBufC8::NewLC(
       
   340         KMaxIpVoiceMailBoxUriLength + KAccountTextLength );
       
   341     TPtr8 ptrTotalMessages8( totalMessages8->Des() );
       
   342     TPtr8 ptrNewMessages8( newMessages8->Des() );
       
   343     TPtr8 ptrFrom8( from8->Des() );
       
   344     TPtr8 ptrContent8( content8->Des() );
       
   345 
       
   346     TBool createSMS = EFalse;
       
   347     // no need to handle errors, returned parameters can still
       
   348     // be interpreted correctly
       
   349     //
       
   350     TRAP_IGNORE(
       
   351         ParseNotifyContentL(
       
   352             createSMS,
       
   353             ptrContent8,
       
   354             ptrTotalMessages8,
       
   355             ptrNewMessages8,
       
   356             ptrFrom8 ) );
       
   357 
       
   358     if ( ptrNewMessages8 == KNoMessages )
       
   359         {
       
   360         // protocol test fix, new message should not be created
       
   361         // if new message count is 0
       
   362         IPVMEPRINT( "CIpVmbxEngine::EventReceivedL - No new messages" );
       
   363         createSMS = EFalse;
       
   364         }
       
   365     if ( 0 == ptrFrom8.Length() )
       
   366         {
       
   367         ptrFrom8 = subscription->VmbxUrl();
       
   368         }
       
   369 
       
   370     TInt totalMsgs = 0;
       
   371     TInt newMsgs = 0;
       
   372     TLex8 msgsConvert;
       
   373     msgsConvert.Assign( *totalMessages8 );
       
   374     if ( KErrNone == msgsConvert.Val( totalMsgs ) )
       
   375         {
       
   376         msgsConvert.Assign( *newMessages8 );
       
   377         if ( KErrNone != msgsConvert.Val( newMsgs ) )
       
   378             {
       
   379             totalMsgs = 0;
       
   380             }
       
   381         }
       
   382 
       
   383     TInt curTotal = 0;
       
   384     TInt curNew = 0;
       
   385     subscription->AccountMessageCount( curTotal, curNew );
       
   386 
       
   387     TBool statusChanged = EFalse;
       
   388     if ( totalMsgs != curTotal || newMsgs != curNew )
       
   389         {
       
   390         statusChanged = ETrue;
       
   391         IPVMEPRINT( "CIpVmbxEngine::EventReceivedL - Status changed" );
       
   392         subscription->SetAccountMessageCount( totalMsgs, newMsgs );
       
   393         }
       
   394 
       
   395     if ( createSMS && statusChanged )
       
   396         {
       
   397         IPVMEPRINT( "CIpVmbxEngine::EventReceivedL - Create message body" );
       
   398         TBuf8< KSmsLength > messageBody8;
       
   399         CreateMessageBodyL(
       
   400             *content8,
       
   401             ptrTotalMessages8,
       
   402             ptrNewMessages8,
       
   403             ptrFrom8,
       
   404             messageBody8 );
       
   405         CreateSMSMessageL( ptrFrom8, messageBody8 );
       
   406         }
       
   407 
       
   408     CleanupStack::PopAndDestroy( from8 );
       
   409     CleanupStack::PopAndDestroy( newMessages8 );
       
   410     CleanupStack::PopAndDestroy( totalMessages8 );
       
   411     CleanupStack::PopAndDestroy( content8 );
       
   412 
       
   413     IPVMEPRINT( "CIpVmbxEngine::EventReceivedL - OUT" );
       
   414     }
       
   415 
       
   416 
       
   417 // ---------------------------------------------------------------------------
       
   418 //
       
   419 // ---------------------------------------------------------------------------
       
   420 //
       
   421 void CIpVmbxEngine::UnsubscribeProfileL( TUint32 aServiceProviderId )
       
   422     {
       
   423     IPVMEPRINT2( "CIpVmbxEngine::UnsubscribeProfileL: %d - IN", 
       
   424 	    aServiceProviderId );
       
   425     
       
   426     CIpVmbxBase* subscription( SubscriptionByProvider( aServiceProviderId ) );
       
   427     if ( !subscription )
       
   428         {
       
   429         User::Leave( KErrNotFound );
       
   430         }
       
   431     
       
   432     IPVMEPRINT2( "CIpVmbxEngine::UnsubscribeProfileL: state=%d",
       
   433 	    subscription->State() );
       
   434 
       
   435     switch( subscription->State() )
       
   436         {
       
   437         case CIpVmbxBase::ERegistered:
       
   438             {
       
   439             subscription->TerminateEventL();
       
   440             break;
       
   441             }
       
   442         case CIpVmbxBase::EDisabled:
       
   443             {
       
   444             CleanVmbxBase();
       
   445             break;
       
   446             }
       
   447         case CIpVmbxBase::ESubscribing:
       
   448             {
       
   449             subscription->Cancel();
       
   450             CleanVmbxBase();
       
   451             break;
       
   452             }
       
   453         case CIpVmbxBase::ETerminating:
       
   454             {
       
   455             User::Leave( KErrCancel );
       
   456             break;
       
   457             }
       
   458         default:
       
   459             {
       
   460             IPVMEPRINT( "No implementation" );
       
   461             }
       
   462         }
       
   463 
       
   464     }
       
   465 
       
   466 
       
   467 // ----------------------------------------------------------------------------
       
   468 //
       
   469 // ----------------------------------------------------------------------------
       
   470 //
       
   471 void CIpVmbxEngine::CleanVmbxBase()
       
   472     {
       
   473     for ( TInt i = 0; i < iVmbxBaseArray.Count(); i++ )
       
   474         {
       
   475         if ( CIpVmbxBase::ETerminating == iVmbxBaseArray[i]->State() ||
       
   476             CIpVmbxBase::EDisabled == iVmbxBaseArray[i]->State() )
       
   477             {
       
   478             delete iVmbxBaseArray[i];
       
   479             iVmbxBaseArray.Remove( i );
       
   480             }
       
   481         }
       
   482     }
       
   483 
       
   484 
       
   485 // ----------------------------------------------------------------------------
       
   486 //
       
   487 // ----------------------------------------------------------------------------
       
   488 //
       
   489 void CIpVmbxEngine::HandleMessage(
       
   490     TUint32 aServiceProviderId,
       
   491     CIpVmbxEngine::TIpVmbxMessages aMessage )
       
   492     {
       
   493     IPVMEPRINT2( "CIpVmbxEngine::HandleMessage: %d - IN", aMessage );
       
   494 
       
   495     CIpVmbxBase* subscription( SubscriptionByProvider( aServiceProviderId ) );
       
   496     // Save current state because some functions modify states
       
   497     CIpVmbxBase::TIpVmbxBaseStates baseState = subscription->State();
       
   498     MIpVmbxObserver::TVmbxMessage message =
       
   499         MIpVmbxObserver::EIncorrectSettings;
       
   500     TBool send = ETrue;
       
   501 
       
   502     switch ( aMessage )
       
   503         {
       
   504         case CIpVmbxEngine::EEngineSubscribed:
       
   505             message = MIpVmbxObserver::ESubscribed;
       
   506             break;
       
   507         case CIpVmbxEngine::EEngineTerminated:
       
   508             {
       
   509             if ( CIpVmbxBase::EDisabled != baseState )
       
   510                 {
       
   511                 CleanVmbxBase();
       
   512                 message = MIpVmbxObserver::EUnsubscribed;
       
   513                 }
       
   514             else
       
   515                 {
       
   516                 send = EFalse;
       
   517                 }
       
   518             break;
       
   519             }
       
   520         case CIpVmbxEngine::EEngineUndefined:
       
   521             {
       
   522             send = EFalse;
       
   523             break;
       
   524             }
       
   525         case CIpVmbxEngine::EEngineSubscribeRejected:
       
   526         case CIpVmbxEngine::EEngineIncorrectAccount:
       
   527             {
       
   528             subscription->Cancel();
       
   529             CleanVmbxBase();
       
   530             message = MIpVmbxObserver::EIncorrectSettings;
       
   531             break;
       
   532             }
       
   533         case CIpVmbxEngine::EEngineSmsError:
       
   534             {
       
   535             subscription->Cancel();
       
   536             message = MIpVmbxObserver::ESmsError;
       
   537             break;
       
   538             }
       
   539         case CIpVmbxEngine::EEngineSmsOom:
       
   540             message = MIpVmbxObserver::ENoMemory;
       
   541             break;
       
   542         case CIpVmbxEngine::EEngineNetworkLost:
       
   543             {
       
   544             subscription->Cancel();
       
   545             subscription->DeleteEvent();
       
   546             send = EFalse;
       
   547             break;
       
   548             }
       
   549         case CIpVmbxEngine::EEngineNetworkError:
       
   550             {
       
   551             subscription->Cancel();
       
   552             subscription->DeleteEvent();
       
   553             message = MIpVmbxObserver::ENetworkError;
       
   554             break;
       
   555             }
       
   556         case CIpVmbxEngine::EEngineFatalNetworkError:
       
   557             {
       
   558             subscription->Cancel();
       
   559             subscription->DeleteEvent();
       
   560             message = MIpVmbxObserver::EFatalNetworkError;
       
   561             break;
       
   562             }
       
   563         default:
       
   564             IPVMEPRINT( "Unhandled message!" );
       
   565         }
       
   566 
       
   567     if ( send )
       
   568         {
       
   569         iInterface.SendMessage( aServiceProviderId, message );
       
   570         }
       
   571 
       
   572     IPVMEPRINT( "CIpVmbxEngine::HandleMessage - OUT" );
       
   573     }
       
   574 
       
   575 
       
   576 // ----------------------------------------------------------------------------
       
   577 //
       
   578 // ----------------------------------------------------------------------------
       
   579 //
       
   580 CIpVmbxBase* CIpVmbxEngine::SubscriptionByProvider(
       
   581     TUint32 aServiceProviderId )
       
   582     {
       
   583     CIpVmbxBase* base( NULL );
       
   584     for ( TInt i = 0; i < iVmbxBaseArray.Count(); i++ )
       
   585         {
       
   586         if ( iVmbxBaseArray[i]->ServiceProviderId() == aServiceProviderId )
       
   587             {
       
   588             base = iVmbxBaseArray[i];
       
   589             }
       
   590         }
       
   591     return base;
       
   592     }
       
   593 
       
   594 
       
   595 // ----------------------------------------------------------------------------
       
   596 // From class MMsvSessionObserver.
       
   597 // Indicates an event has occurred from a Message Server session.
       
   598 // ----------------------------------------------------------------------------
       
   599 //
       
   600 void CIpVmbxEngine::HandleSessionEventL(
       
   601     TMsvSessionEvent /*aEvent*/,
       
   602     TAny* /*aArg1*/,
       
   603     TAny* /*aArg2*/,
       
   604     TAny* /*aArg3*/ )
       
   605     {
       
   606     IPVMEPRINT( "CIpVmbxEngine::HandleSessionEventL - Dummy implementation" );
       
   607     }
       
   608 
       
   609 
       
   610 // ----------------------------------------------------------------------------
       
   611 // Parses critical and important optional parts of content. Already
       
   612 // processed data is cut from content.
       
   613 // ----------------------------------------------------------------------------
       
   614 //
       
   615 void CIpVmbxEngine::ParseNotifyContentL(
       
   616     TBool& aCreateSms,
       
   617     TDes8& aContent8,
       
   618     TDes8& aTotalMessages8,
       
   619     TDes8& aNewMessages8,
       
   620     TDes8& aFrom8 ) const
       
   621     {
       
   622 #ifdef _DEBUG
       
   623     HBufC* print = HBufC::NewLC( aContent8.Length() );
       
   624     print->Des().Copy( aContent8 );
       
   625     IPVMEPRINT2( "CIpVmbxEngine::ParseNotifyContentL - aContent8:%S", &print->Des() )
       
   626     CleanupStack::PopAndDestroy( print );
       
   627 #endif // _DEBUG
       
   628     aCreateSms = EFalse;
       
   629 
       
   630     // check required content
       
   631     TLex8 analyzer8;
       
   632     TPtrC8 posPtr8;
       
   633     TPtrC8 dataPtr8;
       
   634     TPtrC8 messagePtr8;
       
   635 
       
   636     TInt atPosWaiting = aContent8.FindF( KMessagesWaiting8 );
       
   637     // check important OPTIONAL fields
       
   638     TInt atPosAccount = aContent8.FindF( KMessageAccount8 );
       
   639     TInt atPosMessage = aContent8.FindF( KVoiceMessage8 );
       
   640 
       
   641     if ( 0 == atPosWaiting )
       
   642         {
       
   643         // data field found from correct place
       
   644         messagePtr8.Set( FetchMessagePartL( aContent8 ) );
       
   645         analyzer8.Assign(
       
   646             messagePtr8.Mid( messagePtr8.Find( KColon8 ) + KOneChar ) );
       
   647         dataPtr8.Set( analyzer8.NextToken() );
       
   648         if ( 0 == dataPtr8.CompareF( KNewMessages8 ) )
       
   649             {
       
   650             // message(s) waiting
       
   651             aCreateSms = ETrue;
       
   652             }
       
   653         // cut processed data
       
   654         posPtr8.Set( aContent8.Mid( messagePtr8.Length() ) );
       
   655         analyzer8.Assign( posPtr8 );
       
   656         }
       
   657     else
       
   658         {
       
   659         IPVMEPRINT( "CIpVmbxEngine::ParseNotifyContentL - leave with KErrCorrupt" );
       
   660         // malformed critical part of message
       
   661         User::Leave( KErrCorrupt );
       
   662         }
       
   663 
       
   664     if ( KErrNotFound != atPosAccount && KErrNotFound != atPosMessage )
       
   665         {
       
   666         // both optionals found
       
   667         if ( !( atPosAccount < atPosMessage ) )
       
   668             {
       
   669             IPVMEPRINT( "CIpVmbxEngine::ParseNotifyContentL - leave with KErrCorrupt 2" );
       
   670             // incorrect format
       
   671             User::Leave( KErrCorrupt );
       
   672             }
       
   673         }
       
   674 
       
   675     if ( KErrNotFound != atPosAccount && aCreateSms )
       
   676         {
       
   677         // get account
       
   678         IPVMEPRINT( "CIpVmbxEngine::ParseNotifyContentL - get account" );
       
   679         messagePtr8.Set( FetchMessagePartL( posPtr8 ) );
       
   680         analyzer8.Assign(
       
   681             messagePtr8.Mid( messagePtr8.Find( KColon8 ) + KOneChar ) );
       
   682         dataPtr8.Set( analyzer8.NextToken() );
       
   683         posPtr8.Set( posPtr8.Mid( messagePtr8.Length() ) );
       
   684         analyzer8.Assign( posPtr8 );
       
   685 
       
   686 
       
   687         aFrom8.Copy( dataPtr8.Left( aFrom8.MaxLength() ) );
       
   688         }
       
   689 
       
   690     if ( KErrNotFound != atPosMessage )
       
   691         {
       
   692         messagePtr8.Set( FetchMessagePartL( posPtr8 ) );
       
   693         analyzer8.Assign(
       
   694             messagePtr8.Mid( messagePtr8.Find( KColon8 ) + KOneChar ) );
       
   695 
       
   696         // can hold value required by specification
       
   697         TUint oldMessageCount = 0;
       
   698         TUint newMessageCount = 0;
       
   699         TLex8 value;
       
   700 
       
   701         analyzer8.SkipSpace();
       
   702         User::LeaveIfError( analyzer8.Val( newMessageCount ) );
       
   703         analyzer8.SkipSpace();
       
   704         User::LeaveIfError( KSlash8().Locate( analyzer8.Get() ) );
       
   705 
       
   706         analyzer8.SkipSpace();
       
   707         User::LeaveIfError( analyzer8.Val( oldMessageCount ) );
       
   708 
       
   709         aNewMessages8.Num( newMessageCount );
       
   710         aTotalMessages8.Num( ( TInt64 ) oldMessageCount + ( TInt64 ) newMessageCount );
       
   711 
       
   712         posPtr8.Set( posPtr8.Mid( messagePtr8.Length() ) );
       
   713         }
       
   714 
       
   715     // Clean string off processed data
       
   716     aContent8.Delete( 0, aContent8.Length() - posPtr8.Length() );
       
   717 
       
   718     IPVMEPRINT( "CIpVmbxEngine::ParseNotifyContentL - OUT" );
       
   719     }
       
   720 
       
   721 
       
   722 // ----------------------------------------------------------------------------
       
   723 // Creates SMS message and sends it
       
   724 // ----------------------------------------------------------------------------
       
   725 //
       
   726 void CIpVmbxEngine::CreateSMSMessageL(
       
   727     const TDesC8& aFrom8,
       
   728     const TDesC8& aMessageBody8 )
       
   729     {
       
   730     IPVMEPRINT( "CIpVmbxEngine::CreateSMSMessageL - IN" );
       
   731 
       
   732     // Create the SMS header object...
       
   733     CParaFormatLayer* paraFormatLayer = CParaFormatLayer::NewL();
       
   734     CleanupStack::PushL( paraFormatLayer );
       
   735     CCharFormatLayer* charFormatLayer = CCharFormatLayer::NewL();
       
   736     CleanupStack::PushL( charFormatLayer );
       
   737 
       
   738     CRichText* bodyText = CRichText::NewL( paraFormatLayer, charFormatLayer );
       
   739     CleanupStack::PushL( bodyText );
       
   740     TInt position = 0;
       
   741     TBuf< KSmsLength > messageBody;
       
   742     messageBody.Copy( aMessageBody8.Left( messageBody.MaxLength() ) );
       
   743     bodyText->InsertL( position, messageBody );
       
   744 
       
   745     CSmsHeader* header = CSmsHeader::NewL( CSmsPDU::ESmsDeliver, *bodyText );
       
   746     CleanupStack::PushL( header );
       
   747     TBuf< KMaxIpVoiceMailBoxUriLength > from;
       
   748     from.Copy( aFrom8 );
       
   749     header->SetFromAddressL( from );
       
   750 
       
   751     TMsvEntry entry;
       
   752     entry.SetVisible(ETrue );
       
   753     entry.SetUnread( ETrue );
       
   754     entry.SetNew( ETrue );
       
   755     entry.iServiceId = KMsvRootIndexEntryId;
       
   756     entry.iType = KUidMsvMessageEntry;
       
   757     entry.iMtm = KUidMsgTypeSMS;
       
   758     entry.iDate.UniversalTime();
       
   759     entry.iSize = 0;
       
   760     entry.iDescription.Set( KNullDesC );
       
   761     entry.iDetails.Set( KNullDesC );
       
   762 
       
   763     header->Deliver().SetServiceCenterTimeStamp( entry.iDate );
       
   764 
       
   765     CSmsSettings* smsSettings = CSmsSettings::NewL();
       
   766     CleanupStack::PushL( smsSettings );
       
   767     smsSettings->SetDelivery( ESmsDeliveryImmediately );
       
   768     smsSettings->SetValidityPeriod( ESmsVPWeek );
       
   769     smsSettings->SetValidityPeriodFormat( TSmsFirstOctet::ESmsVPFInteger );
       
   770     smsSettings->SetReplyQuoted( EFalse );
       
   771     smsSettings->SetRejectDuplicate( ETrue );
       
   772     smsSettings->SetDelivery( ESmsDeliveryImmediately );
       
   773     smsSettings->SetDeliveryReport( ETrue );
       
   774     smsSettings->SetReplyPath( EFalse );
       
   775     smsSettings->SetMessageConversion( ESmsConvPIDNone );
       
   776     smsSettings->SetCanConcatenate( ETrue );
       
   777     smsSettings->SetUseServiceCenterTimeStampForDate( ETrue );
       
   778 
       
   779     header->SetSmsSettingsL(*smsSettings );
       
   780 
       
   781     CSmsNumber* rcpt = CSmsNumber::NewL();
       
   782     CleanupStack::PushL( rcpt );
       
   783     rcpt->SetAddressL( from.Left( KSmcmSmsNumberMaxNumberLength ) );
       
   784     header->Recipients().AppendL( rcpt );
       
   785     CleanupStack::Pop( rcpt );
       
   786 
       
   787     // Update entry description and details...
       
   788     CArrayPtrFlat< CSmsNumber >& recipient = header->Recipients();
       
   789     entry.iDetails.Set( recipient[0]->Address() );
       
   790     entry.iDescription.Set( bodyText->Read(
       
   791         0, smsSettings->DescriptionLength() ));
       
   792     entry.SetInPreparation( EFalse );
       
   793 
       
   794     // Create the entry - set context to the global outbox.
       
   795     TMsvSelectionOrdering ordering = TMsvSelectionOrdering(
       
   796         KMsvNoGrouping,
       
   797         EMsvSortByDescription,
       
   798         ETrue );
       
   799         CMsvSession* session = CMsvSession::OpenSyncL( *this );
       
   800         CleanupStack::PushL( session );
       
   801     CMsvEntry* centry = CMsvEntry::NewL(
       
   802         *session, KMsvRootIndexEntryId, ordering );
       
   803     CleanupStack::PushL( centry );
       
   804     centry->SetEntryL( KMsvGlobalInBoxIndexEntryId );
       
   805     centry->CreateL( entry );
       
   806 
       
   807     // Create new store and save header information
       
   808     centry->SetEntryL( entry.Id() );
       
   809     CMsvStore* store = centry->EditStoreL();
       
   810     CleanupStack::PushL(store);
       
   811     header->StoreL( *store );
       
   812     store->StoreBodyTextL( *bodyText );
       
   813     store->CommitL();
       
   814 
       
   815     CleanupStack::PopAndDestroy( store );
       
   816     CleanupStack::PopAndDestroy( centry );
       
   817     CleanupStack::PopAndDestroy( session );
       
   818     CleanupStack::PopAndDestroy( smsSettings );
       
   819     CleanupStack::PopAndDestroy( header );
       
   820     CleanupStack::PopAndDestroy( bodyText );
       
   821     CleanupStack::PopAndDestroy( charFormatLayer );
       
   822     CleanupStack::PopAndDestroy( paraFormatLayer );
       
   823 
       
   824     IPVMEPRINT( "CIpVmbxEngine::CreateSMSMessageL - OUT" );
       
   825     }
       
   826 
       
   827 
       
   828 // ----------------------------------------------------------------------------
       
   829 // Parse optional headers. Parser must take account various optional
       
   830 // characters in headers. String lengths are monitored every round to prevent
       
   831 // panics when setting data.
       
   832 // ----------------------------------------------------------------------------
       
   833 //
       
   834 void CIpVmbxEngine::ParseOptionalHeadersL(
       
   835     const TDesC8& aContent8,
       
   836     TDes8& aMessageBody8 ) const
       
   837     {
       
   838     IPVMEPRINT( "CIpVmbxEngine::ParseOptionalHeadersL - IN" );
       
   839 
       
   840     if ( aContent8.Left( KCrlf8().Length() ).Compare( KCrlf8  ) ||
       
   841         aContent8.Length() == KTwoChars )
       
   842         {
       
   843         // Checking if optional message does not exist or its too short.
       
   844         // Will also fix parsing of non standard basic Pingtel message.
       
   845         //
       
   846         User::Leave( KErrNotFound );
       
   847         }
       
   848 
       
   849     TFileName dll;
       
   850     Dll::FileName( dll );
       
   851     TFileName fileName( TParsePtrC( dll ).Drive() );
       
   852     fileName += KIpVmbxAppEngineResourceFileDirectory;
       
   853     fileName += KIpVmbxAppEngineResourceFileName;
       
   854     CStringResourceReader* resourceReader =
       
   855         CStringResourceReader::NewL( fileName );
       
   856     CleanupStack::PushL( resourceReader );
       
   857 
       
   858     if ( aMessageBody8.MaxLength() == aMessageBody8.Length() )
       
   859         {
       
   860         User::Leave( KErrOverflow );
       
   861         }
       
   862     else
       
   863         {
       
   864         // Add another separator before optional messages
       
   865         aMessageBody8.Append( KEndLine8 );
       
   866         }
       
   867 
       
   868     TPtrC8 messagePtr8;
       
   869     TPtrC8 tagPtr8;
       
   870     TPtrC8 dataPtr8;
       
   871     TPtrC8 posPtr8( aContent8 );
       
   872     TPtrC8 colon8;
       
   873     TInt messages = 0;
       
   874     HBufC* locTemp( HBufC::NewLC( KSmsLength ) );
       
   875     TPtr locPtr( locTemp->Des() );
       
   876     TPtrC resourcePtr( resourceReader->ReadResourceString( R_VOIP_VM_HEADER_COUNT ) );
       
   877     HBufC* variant( NULL );
       
   878     TLex8 analyzer8;
       
   879     HBufC8* partTemp( HBufC8::NewLC( KSmsLength ) );
       
   880     TPtr8 partPtr( partTemp->Des() );
       
   881     TBool messageEmpty = EFalse; // prevents creation of empty optional message part
       
   882     TBool appendMsgChange = EFalse;
       
   883     // Start sorting through message
       
   884     do
       
   885         {
       
   886         if ( ( KErrNotFound !=
       
   887             posPtr8.Left( KCrlf8().Length() ).FindF( KCrlf8 ) ||
       
   888             0 == messages ) && !messageEmpty )
       
   889             {
       
   890             // beginning of optional messages or another optional message
       
   891             if ( messages <= KMaxMsgDescriptions )
       
   892                 {
       
   893                 // add message count for first/next optional message
       
   894                 // count is limited to two numbers = 99 (prevents also overflow when
       
   895                 // KTotal is replaced)
       
   896                 TBuf< KTwoChars > appendNum;
       
   897                 appendNum.AppendNum( ++messages );
       
   898                 locPtr.Zero();
       
   899                 locPtr.Append( KOptionalSeparator );
       
   900                 locPtr.Append( resourcePtr );
       
   901                 locPtr.Replace( locPtr.Find( KTotal ), KTotal().Length(), appendNum );
       
   902                 locPtr.Append( KEndLine );
       
   903                 posPtr8.Set( posPtr8.Mid( KCrlf8().Length() ) );
       
   904                 messageEmpty = ETrue;
       
   905                 appendMsgChange = ETrue;
       
   906                 }
       
   907             else
       
   908                 {
       
   909                 User::Leave( KErrOverflow );
       
   910                 }
       
   911             }
       
   912         messagePtr8.Set( FetchMessagePartL( posPtr8 ) );
       
   913         analyzer8.Assign(
       
   914             messagePtr8.Left( messagePtr8.Find( KColon8 ) + KOneChar ) );
       
   915         tagPtr8.Set( analyzer8.NextToken() );
       
   916         if ( KErrNotFound == tagPtr8.Find( KColon8 ) )
       
   917             {
       
   918             // colon required
       
   919             colon8.Set( analyzer8.NextToken() );
       
   920             }
       
   921         analyzer8.Assign(
       
   922             messagePtr8.Mid( messagePtr8.Find( KColon8 ) + KOneChar ) );
       
   923         analyzer8.SkipSpace(); // skipping ws's since one newline is added later
       
   924         if ( analyzer8.Eos() )
       
   925             {
       
   926             // data contained only ws's we must decrease counter by length of CRLF
       
   927             analyzer8.UnGet();
       
   928             analyzer8.UnGet();
       
   929             }
       
   930         dataPtr8.Set(
       
   931             messagePtr8.Mid(
       
   932                 messagePtr8.Find( KColon8 ) + KOneChar + analyzer8.Offset(),
       
   933                 analyzer8.Remainder().Length() - KCrlf8().Length() ) );
       
   934         posPtr8.Set( posPtr8.Mid( messagePtr8.Length() ) );
       
   935         analyzer8.Assign( posPtr8 );
       
   936 
       
   937         variant = TranslateTagL( tagPtr8, *resourceReader );
       
   938 
       
   939         if ( variant &&
       
   940             variant->Length() + dataPtr8.Length() + KOneChar <
       
   941             partPtr.MaxLength() - partPtr.Length() )
       
   942             {
       
   943             // Resource translated to users phone variant language.
       
   944             // Optional message headers other than these aren't supported
       
   945             // because language cannot be verified and might differ from phone
       
   946             // variant language.
       
   947             partPtr.Append( *variant );
       
   948             partPtr.Append(  dataPtr8 );
       
   949             partPtr.Append( KEndLine8 );
       
   950             messageEmpty = EFalse;
       
   951             }
       
   952         delete variant;
       
   953         variant = NULL;
       
   954 
       
   955         if ( !appendMsgChange && !messageEmpty && aMessageBody8.MaxLength() - aMessageBody8.Length() >= partPtr.Length() )
       
   956             {
       
   957             aMessageBody8.Append( partPtr );
       
   958             partPtr.Zero();
       
   959             }
       
   960         else
       
   961             if ( !messageEmpty && aMessageBody8.MaxLength() - aMessageBody8.Length() >= partPtr.Length() + locPtr.Length() )
       
   962                 {
       
   963                 // Content OK, append to actual actual message
       
   964                 aMessageBody8.Append( locPtr );
       
   965                 aMessageBody8.Append( partPtr );
       
   966                 partPtr.Zero();
       
   967                 messageEmpty = EFalse;
       
   968                 appendMsgChange = EFalse;
       
   969                 }
       
   970             else
       
   971                 {
       
   972                 // partial ptr was too long for message, reset and try next part from content
       
   973                 partPtr.Zero();
       
   974                 messageEmpty = ETrue;
       
   975                 }
       
   976 
       
   977         }while( !analyzer8.Eos() );
       
   978 
       
   979     CleanupStack::PopAndDestroy( partTemp );
       
   980     CleanupStack::PopAndDestroy( locTemp );
       
   981     CleanupStack::PopAndDestroy( resourceReader );
       
   982 
       
   983     IPVMEPRINT( "CIpVmbxEngine::ParseOptionalHeadersL - OUT" );
       
   984     }
       
   985 
       
   986 
       
   987 // ----------------------------------------------------------------------------
       
   988 //
       
   989 // ----------------------------------------------------------------------------
       
   990 //
       
   991 void CIpVmbxEngine::ReadResourcesL(
       
   992     const TDesC8& aTotalMessages8,
       
   993     const TDesC8& aNewMessages8,
       
   994     TDes8& aMessagesBody8 )
       
   995     {
       
   996     IPVMEPRINT( "CIpVmbxEngine::ReadResourcesL - IN" );
       
   997     __ASSERT_DEBUG( KSmsLength == aMessagesBody8.MaxLength(), Panic( KErrArgument ) );
       
   998 
       
   999     TFileName dll;
       
  1000     Dll::FileName( dll );
       
  1001     TFileName fileName( TParsePtrC( dll ).Drive() );
       
  1002     fileName += KIpVmbxAppEngineResourceFileDirectory;
       
  1003     fileName += KIpVmbxAppEngineResourceFileName;
       
  1004     CStringResourceReader* resourceReader =
       
  1005         CStringResourceReader::NewL( fileName );
       
  1006     CleanupStack::PushL( resourceReader );
       
  1007     TPtrC messageText;
       
  1008 
       
  1009     if( !aTotalMessages8.Length() )
       
  1010         {
       
  1011         messageText.Set(
       
  1012             resourceReader->ReadResourceString( R_VOIP_VM_MSG_SUM_UNKNOWN ) );
       
  1013         aMessagesBody8.Copy( messageText );
       
  1014         }
       
  1015     else if( !aNewMessages8.Compare( KOneMessage ) &&
       
  1016         !aTotalMessages8.Compare( KOneMessage ) )
       
  1017         {
       
  1018         messageText.Set(
       
  1019             resourceReader->ReadResourceString( R_VOIP_NEW_VOICE_MESSAGE ) );
       
  1020         aMessagesBody8.Copy( messageText );
       
  1021         }
       
  1022     else if( !aNewMessages8.Compare( KOneMessage ) &&
       
  1023         aTotalMessages8.Compare( KOneMessage ) )
       
  1024         {
       
  1025         TBuf< KSmsLength > tempText;
       
  1026         messageText.Set(
       
  1027             resourceReader->ReadResourceString(
       
  1028                 R_VOIP_NEW_AND_OLD_VOICE_MSG ) );
       
  1029         tempText.Copy( messageText );
       
  1030         TInt atPosFirst = tempText.Find( KTotal );
       
  1031         TInt messageLength = tempText.Length();
       
  1032         TPtrC messagePart1 = tempText.Mid( 0 , atPosFirst );
       
  1033         aMessagesBody8.Copy( messagePart1 );
       
  1034         aMessagesBody8.Append( aTotalMessages8.Left( KMaxMessageDigits ) );
       
  1035         TPtrC messagePart2 = tempText.Mid(
       
  1036             atPosFirst + KTotalLength,
       
  1037             messageLength - atPosFirst - KTotalLength );
       
  1038         aMessagesBody8.Append( messagePart2 );
       
  1039         }
       
  1040     else if( aNewMessages8.Compare( KOneMessage ) &&
       
  1041         aTotalMessages8.Compare( KOneMessage ) )
       
  1042         {
       
  1043         messageText.Set(
       
  1044             resourceReader->ReadResourceString( R_VOIP_NEW_VOICE_MESSAGES ) );
       
  1045 
       
  1046         // Search new messages location and replace with real value
       
  1047         TBuf8< KSmsLength > messagePart1;
       
  1048         TInt pos = messageText.Find( KTotalNew );
       
  1049         messagePart1.Copy( messageText.Left( pos ) );
       
  1050         messagePart1.Append( aNewMessages8.Left( KMaxMessageDigits ) );
       
  1051         messagePart1.Append( messageText.Mid( pos + KTotalOldLength ) );
       
  1052 
       
  1053         // Search total messages location and replace with real value
       
  1054         TBuf8< KSmsLength > messagePart2;
       
  1055         pos = messagePart1.Find( KTotalOld );
       
  1056         messagePart2.Copy( messagePart1.Left( pos ) );
       
  1057         messagePart2.Append( aTotalMessages8.Left( KMaxMessageDigits ) );
       
  1058         messagePart2.Append( messagePart1.Mid( pos + KTotalOldLength ) );
       
  1059 
       
  1060         aMessagesBody8.Append( messagePart2 );
       
  1061         }
       
  1062 
       
  1063     aMessagesBody8.Append( KEndLine );
       
  1064     aMessagesBody8.Append( KEndLine );
       
  1065     aMessagesBody8.Append(
       
  1066         resourceReader->ReadResourceString( R_VOIP_VM_MSG_ACCOUNT ) );
       
  1067 
       
  1068     CleanupStack::PopAndDestroy( resourceReader );
       
  1069 
       
  1070     IPVMEPRINT( "CIpVmbxEngine::ReadResourcesL - OUT" );
       
  1071     }
       
  1072 
       
  1073 // ----------------------------------------------------------------------------
       
  1074 //
       
  1075 // ----------------------------------------------------------------------------
       
  1076 //
       
  1077 void CIpVmbxEngine::CreateMessageBodyL(
       
  1078     const TDesC8& aContent8,
       
  1079     const TDesC8& aTotal8,
       
  1080     const TDesC8& aNew8,
       
  1081     TDes8& aFrom8,
       
  1082     TDes8& aMessageBody8 )
       
  1083     {
       
  1084     aFrom8.TrimRight();
       
  1085     if ( 0 == aFrom8.Length() )
       
  1086         {
       
  1087         User::Leave( KErrArgument );
       
  1088         }
       
  1089 
       
  1090     ReadResourcesL(
       
  1091         aTotal8,
       
  1092         aNew8,
       
  1093         aMessageBody8 );
       
  1094 
       
  1095     if( aFrom8.Length() &&
       
  1096         aMessageBody8.Length() + aFrom8.Length() < KSmsLength )
       
  1097         {
       
  1098         aMessageBody8.Append( aFrom8 );
       
  1099         }
       
  1100 
       
  1101     TRAP_IGNORE( ParseOptionalHeadersL( aContent8, aMessageBody8 ) );
       
  1102     }
       
  1103 
       
  1104 // ----------------------------------------------------------------------------
       
  1105 // Creates translated tag from resources
       
  1106 // ----------------------------------------------------------------------------
       
  1107 //
       
  1108 HBufC* CIpVmbxEngine::TranslateTagL(
       
  1109     const TDesC8& aTagPtr8,
       
  1110     CStringResourceReader& aResourceReader ) const
       
  1111     {
       
  1112     HBufC* locTemp( NULL );
       
  1113     TLex8 analyzer8( aTagPtr8 );
       
  1114     TPtrC8 tag( analyzer8.NextToken() );
       
  1115     if ( KErrNotFound != tag.Find( KColon8 ) )
       
  1116         {
       
  1117         // remove possible colon char to make tag matching easier
       
  1118         tag.Set( tag.Left( tag.Length() - KOneChar ) );
       
  1119         }
       
  1120     TIpVmbxParseType::TParseTypes i = TIpVmbxParseType::EDetailTo;
       
  1121     TIpVmbxParseType parseType;
       
  1122     for ( ;i <= TIpVmbxParseType::EDetailId; i++ )
       
  1123         {
       
  1124         parseType.Set( i );
       
  1125         if ( 0 == tag.MatchF( parseType.Tag() ) )
       
  1126             {
       
  1127             i = TIpVmbxParseType::EDetailId;
       
  1128             locTemp =
       
  1129                 aResourceReader.ReadResourceString(
       
  1130                     parseType.ResourceId() ).AllocL();
       
  1131             }
       
  1132         };
       
  1133 
       
  1134     return locTemp;
       
  1135     }
       
  1136 
       
  1137 // ----------------------------------------------------------------------------
       
  1138 // Gets and validates part of message.
       
  1139 // ----------------------------------------------------------------------------
       
  1140 //
       
  1141 TPtrC8 CIpVmbxEngine::FetchMessagePartL( const TDesC8& aContent8 ) const
       
  1142     {
       
  1143     IPVMEPRINT( "CIpVmbxEngine::FetchMessagePartL - IN" );
       
  1144 
       
  1145     TInt crlf = User::LeaveIfError( aContent8.FindF( KCrlf8 ) ) + KCrlf8().Length();
       
  1146     // check for optional CRLF
       
  1147     while( crlf < aContent8.Length() &&
       
  1148         ( KErrNotFound != KHTab8().Locate( aContent8[crlf] ) ||
       
  1149         KErrNotFound != KSpace8().Locate( aContent8[crlf] ) ) )
       
  1150         {
       
  1151         // This was optional CRLF, try next one
       
  1152         crlf += User::LeaveIfError( aContent8.Mid( crlf ).FindF( KCrlf8 ) ) + KTwoChars;
       
  1153         }
       
  1154     // now we should have correct partial data
       
  1155     TPtrC8 part8( aContent8.Left( crlf ) );
       
  1156     TLex8 analyzer8( part8 );
       
  1157 
       
  1158     TPtrC8 tagPtr8(
       
  1159         part8.Left( User::LeaveIfError( part8.Find( KColon8 ) ) ) );
       
  1160     if ( !tagPtr8.Length() )
       
  1161         {
       
  1162         // At least one character required
       
  1163         User::Leave( KErrCorrupt );
       
  1164         }
       
  1165     TestNamePartL( tagPtr8 );
       
  1166 
       
  1167     TPtrC8 dataPtr8( part8.Mid( tagPtr8.Length() ) );
       
  1168     TestValuePartL( dataPtr8 );
       
  1169 
       
  1170     IPVMEPRINT( "CIpVmbxEngine::FetchMessagePartL - OUT" );
       
  1171     return aContent8.Left( part8.Length() );
       
  1172     }
       
  1173 
       
  1174 // ----------------------------------------------------------------------------
       
  1175 // Validates name part of message.
       
  1176 // ----------------------------------------------------------------------------
       
  1177 //
       
  1178 void CIpVmbxEngine::TestNamePartL( const TDesC8& aNameHeader8 ) const
       
  1179     {
       
  1180     // Check legal chars %x41-5A / %x61-7A %x30-39 ( 2d, 2e, 21, 25, 2a, 5f, 2b, 60, 27, 7e)
       
  1181     // from name header
       
  1182     const TFixedArray< TText8, KSpecialNameCharsCount > legalCharsArray(
       
  1183         &KSpecialNameChars[0], KSpecialNameCharsCount );
       
  1184     TChar curChar;
       
  1185     TLex8 analyzer8( aNameHeader8 );
       
  1186     curChar = analyzer8.Get();
       
  1187     TBool valid = ETrue;
       
  1188     while ( !curChar.Eos() && valid )
       
  1189         {
       
  1190         valid = EFalse;
       
  1191         if ( KNameDigitLowest <= curChar && KNameDigitHighest >= curChar ||
       
  1192             KNameCharUpLowest <= curChar && KNameCharUpHighest >= curChar ||
       
  1193             KNameCharLowLowest <= curChar && KNameCharLowHighest >= curChar )
       
  1194             {
       
  1195             valid = ETrue;
       
  1196             }
       
  1197         for ( TInt i = 0; legalCharsArray.Count() > i && !valid; i++ )
       
  1198             {
       
  1199             if ( curChar == legalCharsArray.At( i ) )
       
  1200                 {
       
  1201                 valid = ETrue;
       
  1202                 }
       
  1203             }
       
  1204         if ( valid )
       
  1205             {
       
  1206             curChar = analyzer8.Get();
       
  1207             }
       
  1208         }
       
  1209     if ( !valid )
       
  1210         {
       
  1211         valid = ETrue;
       
  1212         while ( !curChar.Eos() && valid )
       
  1213             {
       
  1214             valid = EFalse;
       
  1215             if ( KSpace == curChar || KHTab == curChar )
       
  1216                 {
       
  1217                 valid = ETrue;
       
  1218                 }
       
  1219             curChar = analyzer8.Get();
       
  1220             }
       
  1221         }
       
  1222     if ( !valid )
       
  1223         {
       
  1224         User::Leave( KErrCorrupt );
       
  1225         }
       
  1226     }
       
  1227 
       
  1228 // ----------------------------------------------------------------------------
       
  1229 // Validates value part of message.
       
  1230 // ----------------------------------------------------------------------------
       
  1231 //
       
  1232 void CIpVmbxEngine::TestValuePartL( const TDesC8& aValueHeader8 ) const
       
  1233     {
       
  1234     TBool valid = ETrue;
       
  1235     TChar curChar;
       
  1236     TLex8 analyzer8( aValueHeader8 );
       
  1237     curChar = analyzer8.Get();
       
  1238 
       
  1239     while ( !curChar.Eos() && valid  )
       
  1240         {
       
  1241         valid = EFalse;
       
  1242         if ( KValueLowestChar <= curChar && KValueHighestChar >= curChar )
       
  1243             {
       
  1244             valid = ETrue;
       
  1245             }
       
  1246         else
       
  1247             if ( KCr == curChar || KLf == curChar || KHTab == curChar )
       
  1248                 {
       
  1249                 valid = ETrue;
       
  1250                 }
       
  1251         curChar = analyzer8.Get();
       
  1252         }
       
  1253     if ( !valid )
       
  1254         {
       
  1255         User::Leave( KErrCorrupt );
       
  1256         }
       
  1257     }
       
  1258