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