mmsengine/clientmtm/src/mmsclient.cpp
changeset 0 72b543305e3a
child 23 238255e8b033
equal deleted inserted replaced
-1:000000000000 0:72b543305e3a
       
     1 /*
       
     2 * Copyright (c) 2002-2007 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: mmsclient implementation
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 // INCLUDE FILES
       
    21 #include    <txtrich.h>
       
    22 #include    <msvids.h>
       
    23 #include    <badesca.h>
       
    24 #include    <msvstore.h>
       
    25 #include    <mtmuids.h> 
       
    26 #include    <mtclbase.h>
       
    27 #include    <mtmdef.h>
       
    28 #include    <logcli.h>
       
    29 #include    <msvftext.h>       // CMsvFindText 
       
    30 #include    <cmsvmimeheaders.h>
       
    31 #include    <mmsvattachmentmanager.h>
       
    32 #include    <mmsvattachmentmanagersync.h>
       
    33 #include    <charconv.h>
       
    34 #include    <msgtextutils.h>
       
    35 
       
    36 // mms headers
       
    37 #include    "mmsheaders.h"
       
    38 #include    "mmssettings.h"
       
    39 #include    "mmsclient.h"
       
    40 #include    "mmsmessageoperation.h"
       
    41 #include    "mmsgenutils.h"
       
    42 #include    "mmscmds.h"
       
    43 #include    "mmsattachmenthandler.h"
       
    44 #include    "mmssendingchain.h"
       
    45 #include    "mmsattachmentwaiter.h"
       
    46 #include    "mmssendmessageoperation.h"
       
    47 
       
    48 // EXTERNAL DATA STRUCTURES
       
    49 
       
    50 // EXTERNAL FUNCTION PROTOTYPES  
       
    51 
       
    52 // CONSTANTS
       
    53 #ifdef _DEBUG
       
    54 #undef _NO_MMSC_LOGGING_
       
    55 #endif
       
    56 
       
    57 _LIT( K1970, "19700000:000000.000000" );    // 1-Jan 1970 0:00:00
       
    58 
       
    59 // MACROS
       
    60 
       
    61 // LOCAL CONSTANTS AND MACROS
       
    62 const TInt KMmsAttributeArrayGranularity = 8;
       
    63 
       
    64 // MODULE DATA STRUCTURES
       
    65 
       
    66 // LOCAL FUNCTION PROTOTYPES
       
    67 
       
    68 // ==================== LOCAL FUNCTIONS ====================
       
    69 
       
    70 
       
    71 // ================= MEMBER FUNCTIONS =======================
       
    72 
       
    73 // Factory function.
       
    74 EXPORT_C CMmsClientMtm* CMmsClientMtm::NewL(
       
    75     CRegisteredMtmDll& aRegisteredMtmDll,
       
    76     CMsvSession& aSession )
       
    77     {
       
    78     CMmsClientMtm* self=new( ELeave ) CMmsClientMtm(
       
    79         aRegisteredMtmDll, aSession );
       
    80     
       
    81     CleanupStack::PushL( self );
       
    82     self->ConstructL();
       
    83     CleanupStack::Pop( self );
       
    84 
       
    85     return self;
       
    86     }
       
    87 
       
    88 
       
    89 // Constructor
       
    90 // Notice that CMmsNotificationClientMtm constructor calls this.
       
    91 CMmsClientMtm::CMmsClientMtm(
       
    92     CRegisteredMtmDll& aRegisteredMtmDll,
       
    93     CMsvSession& aSession )
       
    94     : CBaseMtm( aRegisteredMtmDll, aSession ),
       
    95     iMmsSettings ( NULL ),
       
    96     iMmsHeaders ( NULL ),
       
    97     iServiceId ( KMsvNullIndexEntryId ),
       
    98     iFetchAll( EFalse ),
       
    99     iFetchOverride( ETrue ),
       
   100     iOwnSession( aSession ),
       
   101     iAttaWaiter( NULL )
       
   102     {
       
   103     }
       
   104 
       
   105     
       
   106 // Destructor
       
   107 CMmsClientMtm::~CMmsClientMtm()
       
   108     {
       
   109     delete iAttaWaiter;
       
   110     // We created the settings, it is ours to delete
       
   111     delete iMmsSettings;
       
   112     delete iMmsHeaders;
       
   113     if ( iAttributes != 0 )
       
   114         {
       
   115         iAttributes->Reset();
       
   116         }
       
   117     delete iAttributes;
       
   118     }
       
   119 
       
   120 // ---------------------------------------------------------
       
   121 // CMmsClientMtm::CreateNewEntryL
       
   122 // ---------------------------------------------------------
       
   123 //
       
   124 CMsvOperation* CMmsClientMtm::CreateNewEntryL(
       
   125             TMsvId aDestination, 
       
   126             TRequestStatus& aCompletionStatus)
       
   127     {
       
   128 
       
   129     return CMmsMessageOperation::CreateNewL(
       
   130             aCompletionStatus,
       
   131             Session(),
       
   132             aDestination,
       
   133             iServiceId );
       
   134     }
       
   135 
       
   136 // DEPRECATED - TO BE REMOVED IN THE FUTURE
       
   137 // ---------------------------------------------------------
       
   138 // CMmsClientMtm::CreateServiceL
       
   139 // ---------------------------------------------------------
       
   140 //
       
   141 void CMmsClientMtm::CreateServiceL()
       
   142     {
       
   143     TMsvId service = KMsvNullIndexEntryId;
       
   144     // load settings in order to be sure the old ones are deleted
       
   145     iMmsSettings->LoadSettingsL();
       
   146     // creates new service entry + new notification and mmbox folder entries
       
   147     iMmsSettings->CreateNewServiceL( Session() );
       
   148     // save the new entry ids into cenrep immediatedly
       
   149     iMmsSettings->SaveSettingsL();
       
   150     // Get the base values to detect changes
       
   151     // This function should not be idly called, so this should be safe.
       
   152     iHomeMode = iMmsSettings->ReceivingModeHome();
       
   153     iRoamingMode = iMmsSettings->ReceivingModeForeign();
       
   154     iAccessPointCount = iMmsSettings->AccessPointCount();
       
   155     // service id must be returned
       
   156     service = iMmsSettings->Service();
       
   157     
       
   158     if ( service == KMsvNullIndexEntryId )
       
   159         {
       
   160         // No new entry created
       
   161         User::Leave( KErrNotSupported );
       
   162         }
       
   163     SwitchCurrentEntryL( service );
       
   164     }
       
   165     
       
   166 // ---------------------------------------------------------
       
   167 // CMmsClientMtm::MmsSettings()
       
   168 // ---------------------------------------------------------
       
   169 //
       
   170 const CMmsSettings& CMmsClientMtm::MmsSettings()
       
   171     {
       
   172     return *iMmsSettings;
       
   173     }
       
   174     
       
   175 // ---------------------------------------------------------
       
   176 // CMmsClientMtm::SetSettingsL
       
   177 // ---------------------------------------------------------
       
   178 //
       
   179 void CMmsClientMtm::SetSettingsL( const CMmsSettings& aSettings )
       
   180     {
       
   181     // copy caller's settings to our member
       
   182     iMmsSettings->CopyL( aSettings );
       
   183     }
       
   184     
       
   185 // ---------------------------------------------------------
       
   186 // CMmsClientMtm::StoreSettingsL()
       
   187 // ---------------------------------------------------------
       
   188 //
       
   189 void CMmsClientMtm::StoreSettingsL()
       
   190     {
       
   191     // Check that sufficient disk space available
       
   192     
       
   193     if ( iAccessPointCount < iMmsSettings->AccessPointCount() )
       
   194         {
       
   195         // Disk space checked only if the file size increases.
       
   196         // And the file size increases only when access points are added.
       
   197         if ( TMmsGenUtils::DiskSpaceBelowCriticalLevelL( 
       
   198             &Session().FileSession(), 
       
   199             KMmsAccessPointDiskSpaceNeed,
       
   200             EDriveC ) )
       
   201             {
       
   202             // we use standard error code here
       
   203             User::Leave( KErrDiskFull );
       
   204             }
       
   205         }
       
   206     iMmsSettings->SaveSettingsL();
       
   207 
       
   208     // if one of the receiving modes have changed to automatic,
       
   209     // start fetching deferred messages 
       
   210     TInt homeMode = iMmsSettings->ReceivingModeHome();
       
   211     TInt roamMode = iMmsSettings->ReceivingModeForeign();
       
   212     
       
   213     if ( ( homeMode != iHomeMode && homeMode == EMmsReceivingAutomatic ) ||
       
   214         ( roamMode != iRoamingMode && roamMode == EMmsReceivingAutomatic ))
       
   215         {
       
   216         // fetch all, but only if fetching mode allows it.
       
   217         iFetchAll = ETrue;
       
   218         iFetchOverride = EFalse;
       
   219         }
       
   220     else
       
   221         {
       
   222         iFetchAll = EFalse;
       
   223         iFetchOverride = ETrue;
       
   224         }
       
   225 
       
   226     // We don't leave the settings store function just because the automatic
       
   227     // fetch operation leaves. Some entry may be locked and cannot be fetched
       
   228     // or some other problem may prevent the fetch.
       
   229     // Settings are stored anyway.
       
   230     TInt error = KErrNone;
       
   231     TRAP( error,
       
   232         if ( iFetchAll )
       
   233             {
       
   234             // Implicit fetch of messages, wrap asynch method to make it synch.
       
   235             CMsvOperation* myOperation;
       
   236             myOperation = NULL;        
       
   237             CMsvOperationActiveSchedulerWait* wait = 
       
   238                CMsvOperationActiveSchedulerWait::NewLC();
       
   239             // FetchAllL only schedules notifications in mms folder
       
   240             myOperation = FetchAllL( wait->iStatus, iFetchOverride );
       
   241             // temporary.
       
   242             CleanupStack::PushL( myOperation );
       
   243             wait->Start();
       
   244             CleanupStack::PopAndDestroy( myOperation );
       
   245             CleanupStack::PopAndDestroy( wait );
       
   246             // Then the notifications in inbox
       
   247             wait = CMsvOperationActiveSchedulerWait::NewLC();
       
   248             wait->iStatus = KRequestPending;
       
   249             // FetchAllFromInboxL only schedules notifications in inbox
       
   250             myOperation = FetchAllFromInboxL( wait->iStatus, iFetchOverride );
       
   251             CleanupStack::PushL( myOperation );
       
   252             wait->Start();
       
   253 
       
   254             CleanupStack::PopAndDestroy( myOperation );
       
   255             CleanupStack::PopAndDestroy( wait );
       
   256             iFetchAll = EFalse; // don't do this next time unless needed...
       
   257             }
       
   258         );
       
   259        
       
   260     // Reset the remembered values
       
   261     iHomeMode = iMmsSettings->ReceivingModeHome();
       
   262     iRoamingMode = iMmsSettings->ReceivingModeForeign();
       
   263     iAccessPointCount = iMmsSettings->AccessPointCount();
       
   264     }
       
   265     
       
   266 // ---------------------------------------------------------
       
   267 // CMmsClientMtm::RestoreSettingsL()
       
   268 // ---------------------------------------------------------
       
   269 //
       
   270 void CMmsClientMtm::RestoreSettingsL()
       
   271     {
       
   272     // The settings may have been changed without us knowing it.
       
   273     // We do not reset saved mode values here, because we try to
       
   274     // detect if receiving mode has change since we last checked
       
   275     // in StoreSettingsL() function.
       
   276     iMmsSettings->LoadSettingsL();
       
   277     }   
       
   278 
       
   279 
       
   280 // DEPRECATED - TO BE REMOVED IN THE FUTURE
       
   281 // ---------------------------------------------------------
       
   282 // CMmsClientMtm::RestoreFactorySettingsL
       
   283 // ---------------------------------------------------------
       
   284 //
       
   285 void CMmsClientMtm::RestoreFactorySettingsL( TMmsFactorySettingsLevel aLevel )
       
   286     {
       
   287     iMmsSettings->LoadSettingsL();
       
   288     iMmsSettings->RestoreFactorySettingsL( Session(), aLevel );
       
   289     // StoreSettingsL triggers the fetching of messages if the receiving mode
       
   290     // has changed in a way that requires it.
       
   291     StoreSettingsL();
       
   292     }
       
   293 
       
   294 
       
   295 //----------------------------------------------------------
       
   296 // MMS HEADER HANDLING METHODS
       
   297 //---------------------------------------------------------- 
       
   298 
       
   299 // ---------------------------------------------------------
       
   300 // CMmsClientMtm::SetSenderL
       
   301 // ---------------------------------------------------------
       
   302 //
       
   303 void CMmsClientMtm::SetSenderL( const TDesC& aAlias )
       
   304     {
       
   305     iMmsHeaders->SetSenderL( aAlias );
       
   306     }
       
   307 
       
   308 // ---------------------------------------------------------
       
   309 // CMmsClientMtm::Sender
       
   310 // ---------------------------------------------------------
       
   311 //
       
   312 const TPtrC CMmsClientMtm::Sender( ) const
       
   313     {
       
   314     return iMmsHeaders->Sender();
       
   315     }
       
   316 
       
   317 // ---------------------------------------------------------
       
   318 // CMmsClientMtm::MessageClass
       
   319 // ---------------------------------------------------------
       
   320 //
       
   321 void CMmsClientMtm::SetMessageClass( TMmsMessageClass aMessageClass )
       
   322     {
       
   323     iMmsHeaders->SetMessageClass( aMessageClass );
       
   324     }
       
   325 
       
   326 // ---------------------------------------------------------
       
   327 // CMmsClientMtm::MessageClass
       
   328 // ---------------------------------------------------------
       
   329 //
       
   330 TInt CMmsClientMtm::MessageClass() const
       
   331     {
       
   332     return iMmsHeaders->MessageClass();
       
   333     }
       
   334 
       
   335 // ---------------------------------------------------------
       
   336 // CMmsClientMtm::SetMessagePriority
       
   337 // ---------------------------------------------------------
       
   338 //
       
   339 void CMmsClientMtm::SetMessagePriority( TMmsMessagePriority aPriority )
       
   340     {
       
   341     iMmsHeaders->SetMessagePriority(aPriority);
       
   342     }
       
   343 
       
   344 // ---------------------------------------------------------
       
   345 // CMmsClientMtm::MessagePriority
       
   346 // ---------------------------------------------------------
       
   347 //
       
   348 TInt CMmsClientMtm::MessagePriority() const
       
   349     {
       
   350     return iMmsHeaders->MessagePriority();
       
   351     }
       
   352 
       
   353 // ---------------------------------------------------------
       
   354 // CMmsClientMtm::SetSenderVisibility
       
   355 // ---------------------------------------------------------
       
   356 //
       
   357 void CMmsClientMtm::SetSenderVisibility( TMmsMessageSenderVisibility aVisibility )
       
   358     {
       
   359     iMmsHeaders->SetSenderVisibility(aVisibility);
       
   360     }
       
   361 
       
   362 // ---------------------------------------------------------
       
   363 // CMmsClientMtm::SenderVisibility
       
   364 // ---------------------------------------------------------
       
   365 //
       
   366 TInt CMmsClientMtm::SenderVisibility() const
       
   367     {
       
   368     return iMmsHeaders->SenderVisibility();
       
   369     }
       
   370 
       
   371 // ---------------------------------------------------------
       
   372 // CMmsClientMtm::SetDeliveryReport
       
   373 // ---------------------------------------------------------
       
   374 //
       
   375 void CMmsClientMtm::SetDeliveryReport( TMmsMessageDeliveryReport aVisibility )
       
   376     {
       
   377     iMmsHeaders->SetDeliveryReport(aVisibility);
       
   378     }
       
   379 
       
   380 // ---------------------------------------------------------
       
   381 // CMmsClientMtm::DeliveryReport
       
   382 // ---------------------------------------------------------
       
   383 //
       
   384 TInt CMmsClientMtm::DeliveryReport() const
       
   385     {
       
   386     return iMmsHeaders->DeliveryReport();
       
   387     }
       
   388 
       
   389 // ---------------------------------------------------------
       
   390 // CMmsClientMtm::SetReadReply
       
   391 // ---------------------------------------------------------
       
   392 //
       
   393 void CMmsClientMtm::SetReadReply( TMmsMessageReadReply aRequest )
       
   394     {
       
   395     iMmsHeaders->SetReadReply(aRequest);
       
   396     }
       
   397 
       
   398 // ---------------------------------------------------------
       
   399 // CMmsClientMtm::ReadReply
       
   400 // ---------------------------------------------------------
       
   401 //
       
   402 TInt CMmsClientMtm::ReadReply() const
       
   403     {
       
   404     return iMmsHeaders->ReadReply();
       
   405     }
       
   406 
       
   407 // ---------------------------------------------------------
       
   408 // CMmsClientMtm::SetMessageRootL
       
   409 // ---------------------------------------------------------
       
   410 //
       
   411 
       
   412 void CMmsClientMtm::SetMessageRootL( const TMsvAttachmentId aId )
       
   413     {
       
   414     // We cannot check if the attachent id is legal because Symbian
       
   415     // message server panics if the store is already open.
       
   416     // We must just trust the caller.
       
   417     iMmsHeaders->SetMessageRoot( aId );
       
   418     }
       
   419 
       
   420 // ---------------------------------------------------------
       
   421 // CMmsClientMtm::MessageRootAttachment
       
   422 // ---------------------------------------------------------
       
   423 //
       
   424 TMsvAttachmentId CMmsClientMtm::MessageRootAttachment() const
       
   425     {
       
   426     // This function only returns what has been set earlier by the caller.
       
   427     // As the caller can manipulate the attachments without calling
       
   428     // MMS Client MTM, we cannot keep track of the presence of the root
       
   429     // attachment. It is up to the user to handle the case where the root
       
   430     // has been deleted.
       
   431     return iMmsHeaders->MessageRoot();
       
   432     }
       
   433     
       
   434 // ---------------------------------------------------------
       
   435 // CMmsClientMtm::SendingDate
       
   436 // ---------------------------------------------------------
       
   437 //
       
   438 TTime CMmsClientMtm::SendingDate() const
       
   439     {
       
   440 
       
   441     TInt64 inSeconds = iMmsHeaders->Date();
       
   442 
       
   443     TTime y1970( K1970 );
       
   444 
       
   445     // 1970 presented as microseconds after January 1st, 0 AD Gregorian.
       
   446     TInt64 ms1970 = y1970.Int64();
       
   447 
       
   448     // If not defined in message headers return 0
       
   449     if ( inSeconds == 0 )
       
   450         {
       
   451         return TTime( 0 );
       
   452         }
       
   453 
       
   454     return TTime( ms1970 + ( inSeconds * KMmsMillion ) );
       
   455 
       
   456     }
       
   457 
       
   458 // ---------------------------------------------------------
       
   459 // CMmsClientMtm::SetMaximumImage
       
   460 // ---------------------------------------------------------
       
   461 //
       
   462 void CMmsClientMtm::SetMaximumImage( TInt aHigh, TInt aWidth )
       
   463     {
       
   464     iMmsHeaders->SetMaximumImage( aHigh, aWidth );
       
   465     }
       
   466 
       
   467 // ---------------------------------------------------------
       
   468 // CMmsClientMtm::GetMaximumImage
       
   469 // ---------------------------------------------------------
       
   470 //
       
   471 void CMmsClientMtm::GetMaximumImage( TInt& aHeight, TInt& aWidth ) const
       
   472     {
       
   473     iMmsHeaders->GetMaximumImage( aHeight, aWidth );
       
   474     }
       
   475 
       
   476 // ---------------------------------------------------------
       
   477 // CMmsClientMtm::SetExpiryInterval
       
   478 // ---------------------------------------------------------
       
   479 //       
       
   480 void CMmsClientMtm::SetExpiryInterval( 
       
   481     TTimeIntervalSeconds aInterval )
       
   482     {
       
   483     iMmsHeaders->SetExpiryInterval(aInterval.Int());
       
   484     }
       
   485 
       
   486 // ---------------------------------------------------------
       
   487 // CMmsClientMtm::ExpiryInterval
       
   488 // ---------------------------------------------------------
       
   489 //
       
   490 TTimeIntervalSeconds CMmsClientMtm::ExpiryInterval() const
       
   491     {
       
   492     TTimeIntervalSeconds seconds(iMmsHeaders->ExpiryInterval());
       
   493 
       
   494     return seconds;
       
   495     }
       
   496 
       
   497 // ---------------------------------------------------------
       
   498 // CMmsClientMtm::SetExpiryDate
       
   499 // ---------------------------------------------------------
       
   500 //
       
   501 void CMmsClientMtm::SetExpiryDate( TTime aDate )
       
   502     {
       
   503 
       
   504     TTime y1970( K1970 );
       
   505     TTimeIntervalMicroSeconds interval;
       
   506     // we can't use "seconds from" as it only returns a
       
   507     // 32 bit signed integer. If fails in 2038.
       
   508     // "microseconds from" returns a 64 bit signed integer
       
   509     interval = aDate.MicroSecondsFrom( y1970 );
       
   510     if ( interval.Int64() > 0 )
       
   511         {
       
   512         // expiry date in iMmsHeaders() in seconds from 1.1.1970.
       
   513         iMmsHeaders->SetExpiryDate( ( interval.Int64() ) / KMmsMillion );
       
   514         }
       
   515     }
       
   516 
       
   517 // ---------------------------------------------------------
       
   518 // CMmsClientMtm::ExpiryDate
       
   519 // ---------------------------------------------------------
       
   520 //
       
   521 TTime CMmsClientMtm::ExpiryDate() const
       
   522     {
       
   523 
       
   524     TTime y1970( K1970 );
       
   525 
       
   526     // 1970 presented as microseconds after January 1st, 0 AD Gregorian.
       
   527     TInt64 ms1970 = y1970.Int64();
       
   528 
       
   529     // Expiry in Seconds after 1.1. 1970
       
   530     TInt64 sAfter1970 = iMmsHeaders->ExpiryDate();
       
   531 
       
   532     // If not defined in message headers return 0
       
   533     if ( sAfter1970 == 0 )
       
   534         {
       
   535         return TTime(0);
       
   536         }
       
   537 
       
   538     // Expiry in microseconds after 1.1. 1970
       
   539     TInt64 msAfter1970;
       
   540     msAfter1970 = sAfter1970;
       
   541     msAfter1970 *= KMmsMillion;
       
   542 
       
   543     return TTime( ms1970 + msAfter1970 );
       
   544 
       
   545     }
       
   546 
       
   547 // ---------------------------------------------------------
       
   548 // CMmsClientMtm::SetDeliveryTimeInterval
       
   549 // ---------------------------------------------------------
       
   550 //       
       
   551 void CMmsClientMtm::SetDeliveryTimeInterval( 
       
   552     TTimeIntervalSeconds aInterval )
       
   553     {
       
   554     iMmsHeaders->SetDeliveryTimeInterval( aInterval.Int() );
       
   555     }
       
   556 
       
   557 // ---------------------------------------------------------
       
   558 // CMmsClientMtm::DeliveryTimeInterval
       
   559 // ---------------------------------------------------------
       
   560 //
       
   561 TTimeIntervalSeconds CMmsClientMtm::DeliveryTimeInterval() const
       
   562     {
       
   563     TTimeIntervalSeconds seconds( iMmsHeaders->DeliveryTimeInterval() );
       
   564     return seconds;
       
   565     }
       
   566 
       
   567 // ---------------------------------------------------------
       
   568 // CMmsClientMtm::SetDeliveryDate
       
   569 // ---------------------------------------------------------
       
   570 //
       
   571 void CMmsClientMtm::SetDeliveryDate( TTime aDate )
       
   572     {
       
   573 
       
   574     TTime y1970( K1970 );
       
   575     TTimeIntervalMicroSeconds interval;
       
   576     // we can't use "seconds from" as it only returns a
       
   577     // 32 bit signed integer. If fails in 2038.
       
   578     // "microseconds from" returns a 64 bit signed integer
       
   579     interval = aDate.MicroSecondsFrom( y1970 );
       
   580     if (interval.Int64() > 0 )
       
   581         {
       
   582         // Delivery date in iMmsHeaders() in seconds from 1.1.1970.
       
   583         iMmsHeaders->SetDeliveryDate( (interval.Int64() ) / KMmsMillion );
       
   584         }
       
   585     }
       
   586 
       
   587 // ---------------------------------------------------------
       
   588 // CMmsClientMtm::DeliveryDate
       
   589 // ---------------------------------------------------------
       
   590 //
       
   591 TTime CMmsClientMtm::DeliveryDate() const
       
   592     {
       
   593 
       
   594     TTime y1970( K1970 );
       
   595 
       
   596     // 1970 presented as microseconds after January 1st, 0 AD Gregorian.
       
   597     TInt64 ms1970 = y1970.Int64();
       
   598 
       
   599     // Expiry in Seconds after 1.1. 1970
       
   600     TInt64 sAfter1970 = iMmsHeaders->DeliveryDate();
       
   601 
       
   602     // If not defined in message headers return 0
       
   603     if ( sAfter1970 == 0 )
       
   604         {
       
   605         return TTime(0);
       
   606         }
       
   607 
       
   608     // Expiry in microseconds after 1.1. 1970 
       
   609     TInt64 msAfter1970;
       
   610     msAfter1970 = sAfter1970;
       
   611     msAfter1970 *= KMmsMillion;
       
   612 
       
   613     return TTime( ms1970 + msAfter1970 );
       
   614 
       
   615     }
       
   616 
       
   617 // ---------------------------------------------------------
       
   618 // CMmsClientMtm::SendL
       
   619 // ---------------------------------------------------------
       
   620 //
       
   621 CMsvOperation* CMmsClientMtm::SendL( TRequestStatus& aCompletionStatus,
       
   622     const TTime aSendingTime /* = TTime( 0 ) */  )
       
   623     {
       
   624     
       
   625     CMsvEntrySelection* selection = new( ELeave ) CMsvEntrySelection;
       
   626     CleanupStack::PushL( selection );       // ***
       
   627 
       
   628     // Current entry will be the one to send
       
   629     selection->AppendL( iMsvEntry->Entry().Id() );
       
   630     
       
   631     // aSendingTime is passed on "as is".
       
   632     // SendL with selection makes the conversion if needed
       
   633     CMsvOperation* op = SendL( *selection, aCompletionStatus, aSendingTime );
       
   634 
       
   635     CleanupStack::PopAndDestroy( selection );
       
   636     
       
   637     return op;
       
   638 
       
   639     }
       
   640 
       
   641 // ---------------------------------------------------------
       
   642 // CMmsClientMtm::SendL
       
   643 // ---------------------------------------------------------
       
   644 //
       
   645 CMsvOperation* CMmsClientMtm::SendL(
       
   646             CMsvEntrySelection& aSelection,
       
   647             TRequestStatus& aCompletionStatus,
       
   648             TTime aSendingTime )
       
   649     {
       
   650 
       
   651     if ( aSelection.Count() == 0 )
       
   652         {
       
   653         User::Leave( KErrNotFound );
       
   654         }
       
   655     
       
   656     CMsvEntrySelection* selection = new( ELeave ) CMsvEntrySelection;
       
   657     CleanupStack::PushL( selection );       // ***
       
   658     
       
   659     // Move the messages to OUTBOX synchronously
       
   660     // Parent should be the parent of the first entry in the selection
       
   661     CMsvEntry* cEntry = NULL;
       
   662     TMsvId currentParent = iMsvEntry->Entry().Parent();
       
   663     cEntry = Session().GetEntryL( aSelection.At( 0 ) );
       
   664     CleanupStack::PushL( cEntry );
       
   665     currentParent = cEntry->Entry().Parent();
       
   666     cEntry->SetEntryL( currentParent );
       
   667     
       
   668 #ifndef _NO_MMSC_LOGGING_
       
   669     _LIT( KMmsBefore, "MMSC: Entry parent before move 0x%08X");
       
   670     TMmsGenUtils::Log( KMmsBefore, currentParent );
       
   671 #endif
       
   672     if ( currentParent != KMsvGlobalOutBoxIndexEntryId )
       
   673         {
       
   674         TMsvLocalOperationProgress progress;
       
   675         cEntry->MoveL( aSelection, KMsvGlobalOutBoxIndexEntryId, progress );
       
   676         }
       
   677 
       
   678 #ifndef _NO_MMSC_LOGGING_
       
   679     cEntry->SetEntryL( aSelection.At( 0 ) );
       
   680     currentParent = cEntry->Entry().Parent();
       
   681     _LIT( KMmsAfter, "MMSC: Entry parent after move 0x%08X");
       
   682     TMmsGenUtils::Log( KMmsAfter, currentParent );
       
   683 #endif
       
   684     CleanupStack::PopAndDestroy( cEntry );
       
   685     
       
   686     selection->AppendL( aSelection.Back( 0 ), aSelection.Count() );
       
   687 
       
   688     // Call Server MTM
       
   689     TCommandParameters parameters; // initialized to zero
       
   690     TTime now;
       
   691     // All times in message entries are now UTC time
       
   692     now.UniversalTime();
       
   693     TInt error = KErrNone;
       
   694     if ( aSendingTime > now )
       
   695         {
       
   696         error = aSendingTime.SecondsFrom( now, parameters.iInitialDelay );
       
   697         }
       
   698     if ( error != KErrNone )
       
   699         {
       
   700         User::Leave( error );
       
   701         }
       
   702 
       
   703     TCommandParametersBuf paramPack( parameters );
       
   704 
       
   705     CMsvOperation* op = InvokeAsyncFunctionL(
       
   706         EMmsScheduledSend,
       
   707         *selection,
       
   708         paramPack,
       
   709         aCompletionStatus );
       
   710  
       
   711     CleanupStack::PopAndDestroy( selection );
       
   712     
       
   713     return op;
       
   714 
       
   715     }
       
   716 
       
   717 
       
   718 // ---------------------------------------------------------
       
   719 // CMmsClientMtm::FetchAllL
       
   720 // ---------------------------------------------------------
       
   721 //
       
   722 CMsvOperation* CMmsClientMtm::FetchAllL( TRequestStatus& aCompletionStatus,
       
   723     TBool aForced )
       
   724     {
       
   725     
       
   726     iFetchOverride = aForced;
       
   727     
       
   728     CMsvEntrySelection* selection = ListMmsFolderNotificationsL();
       
   729     CleanupStack::PushL( selection );
       
   730 
       
   731     if ( selection->Count() == 0 )
       
   732         {
       
   733         CleanupStack::PopAndDestroy( selection );
       
   734         TPckgC < TMsvId > progress = 0;
       
   735         aCompletionStatus = KRequestPending;
       
   736         return  CMsvCompletedOperation::NewL( Session(), Type(), progress,
       
   737             KMsvLocalServiceIndexEntryId, aCompletionStatus );
       
   738         }
       
   739 
       
   740     TCommandParameters parameters; // initialized to zero
       
   741     TCommandParametersBuf paramPack( parameters );
       
   742 
       
   743     CMsvOperation* op = NULL;
       
   744     if ( iFetchOverride )
       
   745         {
       
   746         op = InvokeAsyncFunctionL(
       
   747             EMmsScheduledReceiveForced,
       
   748             *selection,
       
   749             paramPack,
       
   750             aCompletionStatus );
       
   751         }
       
   752     else
       
   753         {
       
   754         op = InvokeAsyncFunctionL(
       
   755             EMmsScheduledReceive,
       
   756             *selection,
       
   757             paramPack,
       
   758             aCompletionStatus );
       
   759         // reset override to default value
       
   760         iFetchOverride = ETrue;
       
   761         }
       
   762 
       
   763     CleanupStack::PopAndDestroy( selection );
       
   764     return op;
       
   765     }
       
   766     
       
   767 // ---------------------------------------------------------
       
   768 // CMmsClientMtm::SendReadReportL
       
   769 // ---------------------------------------------------------
       
   770 //
       
   771 CMsvOperation* CMmsClientMtm::SendReadReportL( TMsvId aReadMessageId,
       
   772     TRequestStatus& aCompletionStatus,
       
   773     TMmsReadStatus aReadStatus /*= EMmsReadStatusRead*/ )
       
   774     {
       
   775     // Get the entry for which the report will be sent
       
   776     
       
   777     CMmsHeaders* reportHeaders = CMmsHeaders::NewL( iMmsSettings->MmsVersion() );
       
   778     CleanupStack::PushL( reportHeaders );
       
   779     CMmsHeaders* originalHeaders = CMmsHeaders::NewL( iMmsSettings->MmsVersion() );
       
   780     CleanupStack::PushL( originalHeaders );
       
   781     
       
   782     CMsvEntry* cEntry = NULL;
       
   783     CMsvStore* store = NULL;
       
   784     // Restore original headers.
       
   785     // If we are sending the report to current context, use our own entry
       
   786     if ( aReadMessageId == iMsvEntry->Entry().Id() &&
       
   787         aReadMessageId != KMsvNullIndexEntryId )
       
   788         {
       
   789         store = iMsvEntry->ReadStoreL();
       
   790         CleanupStack::PushL( store );
       
   791         originalHeaders->RestoreL( *store );
       
   792         CleanupStack::PopAndDestroy( store );
       
   793         store = NULL;
       
   794         }
       
   795     else
       
   796         {
       
   797         // If we cannot get the entry, the function leaves
       
   798         cEntry = Session().GetEntryL( aReadMessageId );
       
   799         CleanupStack::PushL( cEntry );
       
   800         store = cEntry->ReadStoreL();
       
   801         CleanupStack::PushL( store );
       
   802         originalHeaders->RestoreL( *store );
       
   803         CleanupStack::PopAndDestroy( store );
       
   804         store = NULL;
       
   805         CleanupStack::PopAndDestroy( cEntry );
       
   806         cEntry = NULL;
       
   807         }
       
   808     
       
   809     if ( !iMmsSettings->ReadReplyReportSendingAllowed() ||
       
   810         originalHeaders->ReadReply() != EMmsYes ||
       
   811         originalHeaders->Sender().Length() == 0 ||
       
   812         iMmsHeaders->MessageClass() == EMmsClassAuto )
       
   813         {
       
   814         // We are not allowed to send a read reply, or the sender of the
       
   815         // original message has not requested a read reply - do not send one.
       
   816         // We are also not allowed to send a read report to automatic messages.
       
   817         CleanupStack::PopAndDestroy( originalHeaders );
       
   818         originalHeaders = NULL;
       
   819         CleanupStack::PopAndDestroy( reportHeaders );
       
   820         reportHeaders = NULL;
       
   821         
       
   822         TPckgC < TMsvId > progress = 0;
       
   823         return  CMsvCompletedOperation::NewL( Session(), Type(), progress,
       
   824             KMsvLocalServiceIndexEntryId, aCompletionStatus, KErrGeneral );
       
   825         }
       
   826     
       
   827     // Now we have loaded the original headers and decided that a read
       
   828     // report really must be sent.
       
   829     // We create a new message entry in the MMS Notification folder to keep
       
   830     // it invisible.
       
   831     
       
   832     reportHeaders->SetMessageIdL( originalHeaders->MessageId() );
       
   833     reportHeaders->SetMessageType( KMmsMessageTypeReadRecInd );
       
   834     reportHeaders->AddTypedAddresseeL( TMmsGenUtils::PureAddress( originalHeaders->Sender() ),
       
   835         EMsvRecipientTo );
       
   836     // sender must be insert-address-token because we don't know our own number
       
   837     // And if there are many recipients we cannot be sure which one is our own number
       
   838     
       
   839     // We are through with the original headers
       
   840     CleanupStack::PopAndDestroy( originalHeaders );
       
   841     originalHeaders = NULL; 
       
   842     
       
   843     TTime now;
       
   844     now.UniversalTime();
       
   845     
       
   846     TTime y1970( K1970 );
       
   847     TTimeIntervalMicroSeconds interval;
       
   848     // we can't use "seconds from" as it only returns a
       
   849     // 32 bit signed integer. If fails in 2038.
       
   850     // "microseconds from" returns a 64 bit signed integer
       
   851     interval = now.MicroSecondsFrom( y1970 );
       
   852     // date in iMmsHeaders() in seconds from 1.1.1970.
       
   853     reportHeaders->SetDate( ( interval.Int64() ) / KMmsMillion );
       
   854     reportHeaders->SetReadStatus( aReadStatus );
       
   855 
       
   856     TMsvId mmsFolderId = iMmsSettings->NotificationFolder();
       
   857     cEntry = Session().GetEntryL( mmsFolderId );
       
   858     CleanupStack::PushL( cEntry );
       
   859 
       
   860     // We create the entry immediately as complete because we store the data immediately
       
   861     // If the battery runs out at the wrong moment, garbage collection will throw the
       
   862     // extra entry away as it is marked as read rec ind.
       
   863     TMsvEntry entry;
       
   864     entry.iType = KUidMsvMessageEntry;
       
   865     entry.iMtm = KUidMsgTypeMultimedia;
       
   866     entry.SetVisible( ETrue );
       
   867     entry.SetInPreparation( EFalse );
       
   868     // We set the service as local service to get past the line
       
   869     // in case sending or receiving is ongoing
       
   870     entry.iServiceId = KMsvLocalServiceIndexEntryId;
       
   871     entry.iRelatedId = iServiceId;
       
   872     entry.iMtmData1 = KMmsMessageReadRecInd;
       
   873     cEntry->CreateL( entry );
       
   874     
       
   875     TMsvId entryId = entry.Id();
       
   876     
       
   877     cEntry->SetEntryL( entryId ); 
       
   878 
       
   879     store = cEntry->EditStoreL();
       
   880     CleanupStack::PushL( store );
       
   881     reportHeaders->StoreL( *store );
       
   882     store->CommitL();
       
   883     CleanupStack::PopAndDestroy( store );
       
   884     store = NULL;
       
   885 
       
   886     // These can go now. Our entry is ready to be sent
       
   887     CleanupStack::PopAndDestroy( cEntry );
       
   888     cEntry = NULL;
       
   889     CleanupStack::PopAndDestroy( reportHeaders );
       
   890     reportHeaders = NULL;
       
   891     
       
   892     CMsvEntrySelection* selection = new ( ELeave ) CMsvEntrySelection;
       
   893     CleanupStack::PushL( selection );
       
   894     selection->InsertL( 0, entryId );
       
   895 
       
   896     CMsvOperation * op = NULL;
       
   897     TCommandParameters parameters; // initialized to zero
       
   898     TCommandParametersBuf paramPack( parameters );
       
   899     
       
   900     op = Session().TransferCommandL( *selection, 
       
   901         EMmsScheduledReadReport,
       
   902         paramPack,
       
   903         aCompletionStatus );
       
   904     
       
   905     CleanupStack::PopAndDestroy( selection );
       
   906 
       
   907     return op;
       
   908     }
       
   909 
       
   910 // ---------------------------------------------------------
       
   911 // CMmsClientMtm::ResponseText
       
   912 // ---------------------------------------------------------
       
   913 //
       
   914 TPtrC CMmsClientMtm::ResponseText() const
       
   915     {
       
   916     return iMmsHeaders->ResponseText( );
       
   917     }
       
   918     
       
   919 // ---------------------------------------------------------
       
   920 // CMmsClientMtm::ResponseStatus
       
   921 // ---------------------------------------------------------
       
   922 //
       
   923 TInt CMmsClientMtm::ResponseStatus() const
       
   924     {
       
   925     return iMmsHeaders->ResponseStatus();
       
   926     }
       
   927     
       
   928 // ---------------------------------------------------------
       
   929 // CMmsClientMtm::NumberOfPreviousSenders
       
   930 // ---------------------------------------------------------
       
   931 //
       
   932 TInt CMmsClientMtm::NumberOfPreviousSenders() const
       
   933     {
       
   934     return iMmsHeaders->PreviouslySentList().Count();
       
   935     }
       
   936     
       
   937 // ---------------------------------------------------------
       
   938 // CMmsClientMtm::
       
   939 // ---------------------------------------------------------
       
   940 //
       
   941 TPtrC CMmsClientMtm::PreviousSender( TInt aSequenceNumber ) const
       
   942     {
       
   943     if ( aSequenceNumber > iMmsHeaders->PreviouslySentList().Count() ||
       
   944         aSequenceNumber < 1 )
       
   945         {
       
   946         return TPtrC();
       
   947         }
       
   948     return iMmsHeaders->PreviouslySentList()[aSequenceNumber - 1]->Sender();
       
   949     }
       
   950     
       
   951 // ---------------------------------------------------------
       
   952 // CMmsClientMtm::
       
   953 // ---------------------------------------------------------
       
   954 //
       
   955 TTime CMmsClientMtm::PreviousSendingDate( TInt aSequenceNumber ) const
       
   956     {
       
   957     if ( aSequenceNumber > iMmsHeaders->PreviouslySentList().Count() ||
       
   958         aSequenceNumber < 1 )
       
   959         {
       
   960         return TTime( 0 );
       
   961         }
       
   962         
       
   963     TInt64 inSeconds;
       
   964     inSeconds = iMmsHeaders->PreviouslySentList()[aSequenceNumber - 1]->Date();
       
   965 
       
   966     // If not defined in message headers return 0
       
   967     if ( inSeconds == 0 )
       
   968         {
       
   969         return TTime(0);
       
   970         }
       
   971 
       
   972     TTime y1970( K1970 );
       
   973     // 1970 presented as microseconds after January 1st, 0 AD Gregorian.
       
   974     TInt64 ms1970 = y1970.Int64();
       
   975 
       
   976     return TTime( ms1970 + ( KMmsMillion * inSeconds ) );
       
   977     
       
   978     }
       
   979     
       
   980 // ---------------------------------------------------------
       
   981 // CMmsClientMtm::MessageReceiveTime
       
   982 // ---------------------------------------------------------
       
   983 //
       
   984 TTime CMmsClientMtm::MessageReceiveTime() const
       
   985     {
       
   986     return iMmsHeaders->ReceivingTime();
       
   987     }
       
   988 
       
   989 // ---------------------------------------------------------
       
   990 // CMmsClientMtm::MessageTransferSize
       
   991 // ---------------------------------------------------------
       
   992 //
       
   993 TInt CMmsClientMtm::MessageTransferSize() const
       
   994     {
       
   995     return iMmsHeaders->MessageSize();
       
   996     }
       
   997 
       
   998 // ---------------------------------------------------------
       
   999 // CMmsClientMtm::MessageContentLocation
       
  1000 // ---------------------------------------------------------
       
  1001 //
       
  1002 TPtrC8 CMmsClientMtm::MessageContentLocation() const
       
  1003     {
       
  1004     return iMmsHeaders->ContentLocation();
       
  1005     }   
       
  1006 
       
  1007 //----------------------------------------------------------
       
  1008 // METHODS FROM BASE CLASS
       
  1009 //----------------------------------------------------------
       
  1010 
       
  1011 // ---------------------------------------------------------
       
  1012 // CMmsClientMtm::SaveMessageL
       
  1013 // Stores the multimedia message
       
  1014 // ---------------------------------------------------------
       
  1015 //
       
  1016 void CMmsClientMtm::SaveMessageL()
       
  1017     {
       
  1018     // First we should assert that iMsvEntry is not NULL, and panic, if it is
       
  1019     __ASSERT_DEBUG( iMsvEntry, gPanic( EMmsNoCMsvEntrySet ));
       
  1020     // SaveMessageL should only be supported for message entries.
       
  1021     __ASSERT_DEBUG( iMsvEntry->Entry().iType.iUid == KUidMsvMessageEntryValue,
       
  1022         gPanic( EMmsNotAMessageEntry ) );
       
  1023 
       
  1024     TMsvEntry indexEntry = iMsvEntry->Entry();
       
  1025 
       
  1026     // Store headers of a multimedia message
       
  1027 
       
  1028     // Because of the way the attachments are handled using the new
       
  1029     // attacment manager, the caller must store and commit the attachments
       
  1030     // either one by one or after all have been added.
       
  1031     // After saving all attachments the edit store used for that purpose
       
  1032     // must be freed.
       
  1033     // The store must be freed because all attachment info and MMS headers
       
  1034     // are saved in the actual message entry, there are no separate 
       
  1035     // attachment entries anymore.
       
  1036 
       
  1037     // When a message is saved in client, the possible transaction ID is cleared
       
  1038     // because when the message is changed, it must get a new TID in MMS server 
       
  1039     // when it is sent.
       
  1040     iMmsHeaders->SetTidL( TPtrC8() );
       
  1041 
       
  1042     CMsvStore* store = iMsvEntry->EditStoreL();
       
  1043     CleanupStack::PushL( store );
       
  1044     // Check that sufficient disk space available
       
  1045     if ( TMmsGenUtils::DiskSpaceBelowCriticalLevelL( 
       
  1046         &Session().FileSession(), 
       
  1047         iMmsHeaders->Size(),
       
  1048         iMessageDrive ) )
       
  1049         {
       
  1050         User::Leave( KErrDiskFull );
       
  1051         }
       
  1052         
       
  1053     // Note: Body text not supported.
       
  1054     
       
  1055     iMmsHeaders->StoreL( *store );
       
  1056     
       
  1057     StoreAttributesL( *store );
       
  1058     
       
  1059     // Commit the stream store
       
  1060     store->CommitL();
       
  1061     CleanupStack::PopAndDestroy( store );
       
  1062 
       
  1063     // Start to update index entry 
       
  1064     // If the caller has not set the description, we set it to messge subject -
       
  1065     // if subject is available.
       
  1066     if ( indexEntry.iDescription.Length() == 0 )
       
  1067         {
       
  1068         indexEntry.iDescription.Set( iMmsHeaders->Subject() );
       
  1069         }
       
  1070     // The caller must set the message to complete and visible when it is ready:
       
  1071     /*
       
  1072        indexEntry.SetInPreparation( EFalse );
       
  1073        indexEntry.SetVisible( ETrue );
       
  1074        indexEntry.iDate.UniversalTime();
       
  1075     */
       
  1076 
       
  1077     // attachment size
       
  1078     TInt32 totalSizeOfAllAttachments = AttachmentsSizeL();
       
  1079     indexEntry.iSize = iMmsHeaders->Size() + totalSizeOfAllAttachments;
       
  1080 
       
  1081     // If there are multiple recipients then set the flag
       
  1082     if (( iMmsHeaders->ToRecipients().Count() +
       
  1083         iMmsHeaders->CcRecipients().Count() +
       
  1084         iMmsHeaders->BccRecipients().Count() ) > 1 )
       
  1085         {
       
  1086         indexEntry.SetMultipleRecipients( ETrue );
       
  1087         }
       
  1088     else
       
  1089         {
       
  1090         // clear multiple recipients in case recipients have
       
  1091         // been deleted after the message was saved the last time
       
  1092         indexEntry.SetMultipleRecipients( EFalse );
       
  1093         }
       
  1094 
       
  1095     // Set iDetails (recipient)
       
  1096     // Check that MT message's details not updated,
       
  1097     // although this should not be possible in UI.
       
  1098     if ( !( indexEntry.iMtmData1 & KMmsMessageMobileTerminated ) )
       
  1099         {
       
  1100         TPtrC to;
       
  1101         if ( iMmsHeaders->ToRecipients().Count() )
       
  1102             {
       
  1103             to.Set( TMmsGenUtils::Alias( iMmsHeaders->ToRecipients()[0] ) );
       
  1104             if ( to.Length() <= 0 )
       
  1105                 {
       
  1106                 // If no alias part then set the real address in details
       
  1107                 to.Set( iMmsHeaders->ToRecipients()[0] );
       
  1108                 }
       
  1109             }
       
  1110         indexEntry.iDetails.Set( to );
       
  1111         }
       
  1112 
       
  1113     if ( totalSizeOfAllAttachments > 0 )
       
  1114         {
       
  1115         indexEntry.SetAttachment( ETrue );
       
  1116         }
       
  1117         
       
  1118     if ( iAttributes->MdcaCount() > 0 )
       
  1119         {
       
  1120         indexEntry.iMtmData1 |= KMmsAttributeStreamPresent;
       
  1121         }
       
  1122     else
       
  1123         {
       
  1124         indexEntry.iMtmData1 &= ~KMmsAttributeStreamPresent;
       
  1125         }
       
  1126         
       
  1127     switch ( iMmsHeaders->MessagePriority() )
       
  1128         {
       
  1129         case KMmsPriorityNormal:
       
  1130             indexEntry.SetPriority( EMsvMediumPriority );
       
  1131             break;
       
  1132         case KMmsPriorityLow:
       
  1133             indexEntry.SetPriority( EMsvLowPriority );
       
  1134             break;
       
  1135         case KMmsPriorityHigh:
       
  1136             indexEntry.SetPriority( EMsvHighPriority );
       
  1137             break;
       
  1138         default:            
       
  1139             // if not defined default is normal
       
  1140             indexEntry.SetPriority( EMsvMediumPriority );
       
  1141             break;
       
  1142         }
       
  1143 
       
  1144     // commit the index changes.
       
  1145     iMsvEntry->ChangeL( indexEntry );
       
  1146     }
       
  1147 
       
  1148 // ---------------------------------------------------------
       
  1149 // CMmsClientMtm::LoadMessageL
       
  1150 // Loads the multimedia message
       
  1151 // ---------------------------------------------------------
       
  1152 //
       
  1153 void CMmsClientMtm::LoadMessageL()
       
  1154     {
       
  1155     // First we should assert that iMsvEntry is not NULL, and panic, if it is
       
  1156     __ASSERT_DEBUG( iMsvEntry, gPanic( EMmsNoCMsvEntrySet ) );
       
  1157     // LoadMessageL should only be supported for message entries.
       
  1158     if ( iMsvEntry->Entry().iType.iUid != KUidMsvMessageEntryValue )
       
  1159         {
       
  1160         iAttributes->Reset();
       
  1161         iMmsHeaders->Reset();
       
  1162         iAddresseeList->Reset();
       
  1163         return;        
       
  1164         }
       
  1165     
       
  1166     // Old data must be reset first....
       
  1167     iAttributes->Reset();
       
  1168 
       
  1169     // load the correct data
       
  1170     // get read-only message store
       
  1171     CMsvStore* store = iMsvEntry->ReadStoreL();
       
  1172     CleanupStack::PushL( store );
       
  1173 
       
  1174     // restore headers of multimedia message
       
  1175     // Attachment info is not restored.
       
  1176     // It makes no sense to cache the attachment info as new attachments
       
  1177     // can be added with the help of the attachment magager without 
       
  1178     // informing MMS Client MTM of the additions.
       
  1179     // Caller must use attachment manager to get attachment info.
       
  1180     iMmsHeaders->RestoreL( *store );
       
  1181     
       
  1182     RestoreAttributesL( *store );
       
  1183     
       
  1184     CleanupStack::PopAndDestroy( store );
       
  1185     store = NULL;
       
  1186 
       
  1187     // Build the iAddresseeList up
       
  1188     BuildAddresseeListL();
       
  1189 
       
  1190     }
       
  1191 
       
  1192 // ---------------------------------------------------------
       
  1193 // CMmsClientmtm::ReplyL
       
  1194 // Send a reply to current message
       
  1195 // ---------------------------------------------------------
       
  1196 //
       
  1197 CMsvOperation* CMmsClientMtm::ReplyL(
       
  1198     TMsvId aDestination,
       
  1199     TMsvPartList aPartList,
       
  1200     TRequestStatus& aCompletionStatus )
       
  1201     {
       
  1202 
       
  1203     return CMmsMessageOperation::CreateReplyL(
       
  1204             aCompletionStatus,
       
  1205             Session(),
       
  1206             iMsvEntry->EntryId(),
       
  1207             aDestination,
       
  1208             aPartList,
       
  1209             iServiceId );
       
  1210     }
       
  1211 
       
  1212 // ---------------------------------------------------------
       
  1213 // CMmsClientMtm::ForwardL
       
  1214 // Forward current message
       
  1215 // ---------------------------------------------------------
       
  1216 //
       
  1217 CMsvOperation* CMmsClientMtm::ForwardL(
       
  1218     TMsvId aDestination,
       
  1219     TMsvPartList aPartList,
       
  1220     TRequestStatus& aCompletionStatus )
       
  1221     {
       
  1222 
       
  1223     return CMmsMessageOperation::CreateForwardL(
       
  1224             aCompletionStatus,
       
  1225             Session(),
       
  1226             iMsvEntry->EntryId(),
       
  1227             aDestination,
       
  1228             aPartList,
       
  1229             iServiceId );
       
  1230     }
       
  1231 
       
  1232 // ---------------------------------------------------------
       
  1233 // CMmsClientMtm::ValidateMessage
       
  1234 // Validate selected parts of current message
       
  1235 // ---------------------------------------------------------
       
  1236 //
       
  1237 TMsvPartList CMmsClientMtm::ValidateMessage(
       
  1238     TMsvPartList aPartList )
       
  1239     {
       
  1240     __ASSERT_DEBUG( iMsvEntry, gPanic( EMmsNoCMsvEntrySet ));
       
  1241     
       
  1242     TMsvPartList retVal = 0;
       
  1243     if ( iMsvEntry->Entry().iType.iUid != KUidMsvMessageEntryValue )
       
  1244         {
       
  1245         // not a message, no part is valid
       
  1246         retVal = aPartList;
       
  1247         }
       
  1248 
       
  1249     if ( aPartList & KMsvMessagePartRecipient )
       
  1250         {
       
  1251         if ( iAddresseeList->Count() == 0)
       
  1252             {
       
  1253             retVal |= KMsvMessagePartRecipient;
       
  1254             }
       
  1255         else
       
  1256             {
       
  1257             // check the recipient list for valid 'addresses'
       
  1258             for (TInt ii=0; ii < iAddresseeList->Count(); ++ii)
       
  1259                 {
       
  1260                 TPtrC oneAddress = (*iAddresseeList)[ii];
       
  1261                 TPtrC pureAddress = TMmsGenUtils::PureAddress( oneAddress );
       
  1262                 if ( ( pureAddress.Length() == 0 ) || 
       
  1263                     !TMmsGenUtils::IsValidAddress( pureAddress, ETrue ) )
       
  1264                     {
       
  1265                     retVal |= KMsvMessagePartRecipient;
       
  1266                     break;
       
  1267                     }
       
  1268                 }
       
  1269             }
       
  1270         }
       
  1271 
       
  1272     // all attachments are considered valid - even no attachments
       
  1273 
       
  1274     return retVal;
       
  1275 
       
  1276     }
       
  1277 
       
  1278 // ---------------------------------------------------------
       
  1279 // CMmsClientMtm::Find
       
  1280 // Find text in selected message parts
       
  1281 // ---------------------------------------------------------
       
  1282 //
       
  1283 TMsvPartList CMmsClientMtm::Find(
       
  1284     const TDesC& aTextToFind,
       
  1285     TMsvPartList aPartList )
       
  1286     {
       
  1287     // The final version will not have a rich text body, but we could
       
  1288     // search for example the originator and description.
       
  1289 
       
  1290     __ASSERT_DEBUG( iMsvEntry, gPanic( EMmsNoCMsvEntrySet ) );
       
  1291     TMsvPartList foundList = KMsvMessagePartNone;
       
  1292     
       
  1293     TRAP_IGNORE(
       
  1294         {
       
  1295         TMsvEntry entry = iMsvEntry->Entry();
       
  1296 
       
  1297         CMsvFindText* findText = CMsvFindText::NewL();
       
  1298         
       
  1299         CleanupStack::PushL( findText );
       
  1300 
       
  1301         if ( aPartList & KMsvMessagePartRecipient )
       
  1302             {
       
  1303             // Find from To, Cc and Bcc fields
       
  1304             if ( FindInRecipientL( aTextToFind, 
       
  1305                 aPartList, iMmsHeaders->ToRecipients(), *findText))
       
  1306                 {
       
  1307                 foundList |= KMsvMessagePartRecipient;
       
  1308                 }
       
  1309             else if ( FindInRecipientL( aTextToFind, 
       
  1310                 aPartList, iMmsHeaders->CcRecipients(), *findText ))
       
  1311                 {
       
  1312                 foundList |= KMsvMessagePartRecipient;
       
  1313                 }
       
  1314             else if ( FindInRecipientL( aTextToFind, 
       
  1315                 aPartList, iMmsHeaders->BccRecipients(), *findText ))
       
  1316                 {
       
  1317                 foundList |= KMsvMessagePartRecipient;
       
  1318                 }
       
  1319             else
       
  1320                 {
       
  1321                 // keep LINT happy
       
  1322                 }
       
  1323             }
       
  1324 
       
  1325         if ( aPartList & KMsvMessagePartOriginator )
       
  1326             {
       
  1327             if ( findText->FindTextL( aTextToFind, iMmsHeaders->Sender(), 
       
  1328                 aPartList ) )
       
  1329                 {
       
  1330                 foundList |= KMsvMessagePartOriginator;
       
  1331                 }
       
  1332             }
       
  1333 
       
  1334         if ( aPartList & KMsvMessagePartDescription )
       
  1335             {
       
  1336             if ( findText->FindTextL( aTextToFind, entry.iDescription, 
       
  1337                 aPartList ) )
       
  1338                 {
       
  1339                 foundList |= KMsvMessagePartDescription;
       
  1340                 }
       
  1341             }
       
  1342 
       
  1343         CleanupStack::PopAndDestroy( findText );
       
  1344         });
       
  1345     return foundList;
       
  1346 
       
  1347     }
       
  1348 
       
  1349 // ---------------------------------------------------------
       
  1350 // CMmsClientMtm::AddAddresseeL
       
  1351 // ---------------------------------------------------------
       
  1352 //
       
  1353 void CMmsClientMtm::AddAddresseeL( const TDesC& aRealAddress )
       
  1354     {
       
  1355     // Add to general list
       
  1356     // When no type is specified, the address will have type "to"
       
  1357     iAddresseeList->AppendL( EMsvRecipientTo, aRealAddress );
       
  1358     
       
  1359     // Add to "To" recipient list
       
  1360     iMmsHeaders->AddTypedAddresseeL( aRealAddress, EMsvRecipientTo );
       
  1361 
       
  1362     }
       
  1363 
       
  1364 // ---------------------------------------------------------
       
  1365 // CMmsClientMtm::AddAddresseeL
       
  1366 // ---------------------------------------------------------
       
  1367 //
       
  1368 void CMmsClientMtm::AddAddresseeL(
       
  1369     const TDesC& aRealAddress,
       
  1370     const TDesC& aAlias )
       
  1371     {
       
  1372 
       
  1373     if ( aAlias.Length() > 0 )
       
  1374         {
       
  1375         HBufC* buf = TMmsGenUtils::GenerateAddressL( aRealAddress, aAlias );
       
  1376         CleanupStack::PushL( buf );
       
  1377         AddAddresseeL( buf->Des() );
       
  1378         CleanupStack::PopAndDestroy( buf );
       
  1379         }
       
  1380     else
       
  1381         {        
       
  1382         AddAddresseeL( aRealAddress );
       
  1383         }
       
  1384     }
       
  1385     
       
  1386 // ---------------------------------------------------------
       
  1387 // CMmsClientMtm::AddAddresseeL
       
  1388 // ---------------------------------------------------------
       
  1389 //
       
  1390 void CMmsClientMtm::AddAddresseeL( TMsvRecipientType aType,
       
  1391     const TDesC& aRealAddress )
       
  1392     {
       
  1393     // Add to general list
       
  1394     // When no type is specified, the address will have type "to"
       
  1395     iAddresseeList->AppendL( aType, aRealAddress );
       
  1396     
       
  1397     // Add to recipient list
       
  1398     iMmsHeaders->AddTypedAddresseeL( aRealAddress, aType );
       
  1399 
       
  1400     }
       
  1401 
       
  1402 // ---------------------------------------------------------
       
  1403 // CMmsClientMtm::AddAddresseeL
       
  1404 // ---------------------------------------------------------
       
  1405 //
       
  1406 void CMmsClientMtm::AddAddresseeL(
       
  1407     TMsvRecipientType aType,
       
  1408     const TDesC& aRealAddress,
       
  1409     const TDesC& aAlias )
       
  1410     {
       
  1411 
       
  1412     if ( aAlias.Length() > 0 )
       
  1413         {
       
  1414         HBufC* buf = TMmsGenUtils::GenerateAddressL( aRealAddress, aAlias );
       
  1415         CleanupStack::PushL( buf );
       
  1416         AddAddresseeL(aType, buf->Des());
       
  1417         CleanupStack::PopAndDestroy( buf );
       
  1418         }
       
  1419     else
       
  1420         {        
       
  1421         AddAddresseeL( aType, aRealAddress );
       
  1422         }
       
  1423     }
       
  1424 
       
  1425 // ---------------------------------------------------------
       
  1426 // CMmsClientMtm::RemoveAddressee
       
  1427 // ---------------------------------------------------------
       
  1428 //
       
  1429 void CMmsClientMtm::RemoveAddressee( TInt aIndex )
       
  1430     {
       
  1431 
       
  1432     if ( iAddresseeList->Count() > aIndex )
       
  1433         {
       
  1434         // Delete from typed list
       
  1435         TPtrC address = (*iAddresseeList)[ aIndex ];
       
  1436         iMmsHeaders->RemoveAddressee( address );
       
  1437         // delete from untyped list
       
  1438         iAddresseeList->Delete( aIndex );
       
  1439         }
       
  1440         
       
  1441     }
       
  1442 
       
  1443 // ---------------------------------------------------------
       
  1444 // CMmsClientMtm::SetSubjectL
       
  1445 // ---------------------------------------------------------
       
  1446 //
       
  1447 void CMmsClientMtm::SetSubjectL( const TDesC& aSubject )
       
  1448     {
       
  1449     iMmsHeaders->SetSubjectL( aSubject );
       
  1450     }
       
  1451 
       
  1452 // ---------------------------------------------------------
       
  1453 // CMmsClientMtm::SubjectL
       
  1454 // ---------------------------------------------------------
       
  1455 //
       
  1456 const TPtrC CMmsClientMtm::SubjectL() const
       
  1457     {
       
  1458     return iMmsHeaders->Subject();
       
  1459     }
       
  1460 
       
  1461 // ---------------------------------------------------------
       
  1462 // CMmsClientMtm::AddAttachmentL
       
  1463 // ---------------------------------------------------------
       
  1464 //
       
  1465 void CMmsClientMtm::AddAttachmentL( const TDesC& aFilePath,
       
  1466     const TDesC8& aMimeType, TUint aCharset, TRequestStatus& aStatus )
       
  1467     {
       
  1468     
       
  1469     TInt error = KErrNone;
       
  1470     TUint charset = aCharset;
       
  1471     RFile file;
       
  1472     if ( aMimeType.CompareF( KMmsTextPlain ) == 0 && charset == 0 )
       
  1473         {
       
  1474         // try to recognize character set
       
  1475         // We trap the recognization process
       
  1476         // If cannot recognize, the result will be 0 and default to us-ascii
       
  1477         TRAP ( error,
       
  1478             {
       
  1479             error = file.Open( Session().FileSession(), aFilePath,
       
  1480                 EFileRead|EFileShareReadersOnly );
       
  1481             if ( error == KErrNone )
       
  1482                 {
       
  1483                 CleanupClosePushL( file );
       
  1484                 charset = RecognizeCharSetL( file );
       
  1485                 CleanupStack::PopAndDestroy( &file ); // close file
       
  1486                 }
       
  1487             }
       
  1488             );
       
  1489         }
       
  1490         
       
  1491     // if the attachment character set is unicode, it should be converted to utf-8
       
  1492     // (see MMS conformance document)
       
  1493     
       
  1494     if ( aMimeType.CompareF( KMmsTextPlain ) == 0 &&
       
  1495         ( charset == KMmsUTF16  ||
       
  1496         charset == KMmsIso10646Ucs2 ||
       
  1497         charset == KMmsUTF16BE ||
       
  1498         charset == KMmsUTF16LE ) )
       
  1499         {
       
  1500         // If we have unicode character set, we must convert the file to utf8
       
  1501         error = file.Open( Session().FileSession(), aFilePath,
       
  1502             EFileRead|EFileShareReadersOnly );
       
  1503         if ( error == KErrNone )
       
  1504             {
       
  1505             CleanupClosePushL( file );
       
  1506               CMsvStore* store = iMsvEntry->EditStoreL();
       
  1507             CleanupStack::PushL( store );
       
  1508             TMsvAttachmentId attaId = 0;
       
  1509             CMmsAttachmentHandler::CreateUTF8TextAttachmentFromFileL(
       
  1510                 *store, attaId, file, Session().FileSession(),
       
  1511                 Session().CurrentDriveL() );
       
  1512             store->CommitL();
       
  1513             CleanupStack::PopAndDestroy( store );
       
  1514             CleanupStack::PopAndDestroy( &file ); // close file
       
  1515             }
       
  1516         TRequestStatus* status = &aStatus;
       
  1517         aStatus = KRequestPending;
       
  1518         User::RequestComplete( status, error );
       
  1519         return;    
       
  1520         }
       
  1521     else
       
  1522         {
       
  1523         // Disk space is checked in AddFilePathAttachmentL after everything has been initialized
       
  1524         AddFilePathAttachmentL( aFilePath, aMimeType, CMsvAttachment::EMsvFile, aStatus, charset );
       
  1525         }
       
  1526     }
       
  1527     
       
  1528 // ---------------------------------------------------------
       
  1529 // CMmsClientMtm::AddAttachmentL
       
  1530 // ---------------------------------------------------------
       
  1531 //
       
  1532 void CMmsClientMtm::AddAttachmentL( RFile& aFile, const TDesC8& aMimeType,
       
  1533     TUint aCharset, TRequestStatus& aStatus )
       
  1534     {
       
  1535 
       
  1536     TInt charset = aCharset;
       
  1537     if ( aMimeType.CompareF( KMmsTextPlain ) == 0  && charset == 0 )
       
  1538         {
       
  1539         // If no character set defined for a plain text attachment
       
  1540         // we try to recognize the character set.
       
  1541         // But if recoginzation fails, we say 0 (us-ascii)
       
  1542         TRAP_IGNORE ( 
       
  1543             {
       
  1544             charset = RecognizeCharSetL( aFile );
       
  1545             });
       
  1546         }
       
  1547         
       
  1548     if ( aMimeType.CompareF( KMmsTextPlain ) == 0 )
       
  1549         {
       
  1550         // If we have unicode character set, we must convert the file to utf8
       
  1551         if ( ( charset == KMmsUTF16 ) ||
       
  1552             ( charset == KMmsIso10646Ucs2 ) ||
       
  1553             ( charset == KMmsUTF16BE ) ||
       
  1554             ( charset == KMmsUTF16LE ) )
       
  1555             {
       
  1556               CMsvStore* store = iMsvEntry->EditStoreL();
       
  1557             CleanupStack::PushL( store );
       
  1558             TMsvAttachmentId attaId = 0;
       
  1559             CMmsAttachmentHandler::CreateUTF8TextAttachmentFromFileL( *store,
       
  1560                 attaId, aFile, Session().FileSession(),
       
  1561                 Session().CurrentDriveL() );
       
  1562             store->CommitL();
       
  1563             CleanupStack::PopAndDestroy( store ); // store
       
  1564             // We must close the file handle because the attachment manager will also
       
  1565             // close the handle.
       
  1566             // The open file handle is always closed unless the funtion leaves
       
  1567             aFile.Close();
       
  1568             TRequestStatus* status = &aStatus;
       
  1569             aStatus = KRequestPending;
       
  1570             User::RequestComplete( status, KErrNone );
       
  1571             return;
       
  1572             }
       
  1573         }
       
  1574     
       
  1575     if( !iAttaWaiter )
       
  1576         {
       
  1577         iAttaWaiter = CMmsAttachmentWaiter::NewL();
       
  1578         }
       
  1579 
       
  1580     // store must be the first item allocated because it is the last one to be popped
       
  1581     CMsvStore* store = iMsvEntry->EditStoreL();
       
  1582     CleanupStack::PushL( store );
       
  1583     
       
  1584     CMsvAttachment* attachment = CMsvAttachment::NewL( CMsvAttachment::EMsvFile );
       
  1585     CleanupStack::PushL( attachment );
       
  1586     
       
  1587     CMsvMimeHeaders* mimeHeaders = CMsvMimeHeaders::NewL();
       
  1588     CleanupStack::PushL( mimeHeaders );
       
  1589     
       
  1590     // set the size
       
  1591     TInt size = 0;
       
  1592     User::LeaveIfError( aFile.Size( size ) );
       
  1593     attachment->SetSize( size );
       
  1594     
       
  1595     // set the mime-type if provided
       
  1596     if( aMimeType.Length() > 0 )
       
  1597         {
       
  1598         attachment->SetMimeTypeL( aMimeType );
       
  1599         TInt position = aMimeType.Find( KMmsSlash8 );
       
  1600         if ( position > 0 )
       
  1601             {
       
  1602             mimeHeaders->SetContentTypeL( aMimeType.Left( position ) );
       
  1603             }
       
  1604         if ( position < aMimeType.Length() - 1 )
       
  1605             {
       
  1606             mimeHeaders->SetContentSubTypeL( aMimeType.Mid( position + 1 ) );
       
  1607             }
       
  1608         }
       
  1609         
       
  1610     TFileName fileName;
       
  1611     User::LeaveIfError( aFile.Name( fileName ) );
       
  1612     attachment->SetAttachmentNameL( fileName );
       
  1613 
       
  1614     mimeHeaders->SetSuggestedFilenameL( attachment->AttachmentName() );
       
  1615     mimeHeaders->SetMimeCharset( charset );
       
  1616 
       
  1617     size += KMmsIndexEntryExtra + mimeHeaders->Size();    
       
  1618     mimeHeaders->StoreL( *attachment );
       
  1619     
       
  1620     // mime headers have been streamed to CMsvAttachment, they can go now
       
  1621     CleanupStack::PopAndDestroy( mimeHeaders );
       
  1622     
       
  1623     // Check that sufficient disk space available
       
  1624     if ( TMmsGenUtils::DiskSpaceBelowCriticalLevelL( 
       
  1625         &Session().FileSession(), 
       
  1626         size,
       
  1627         iMessageDrive ) )
       
  1628             {
       
  1629             CleanupStack::PopAndDestroy( attachment );
       
  1630             User::Leave( KErrDiskFull );
       
  1631             }
       
  1632 
       
  1633     // attachment is initialised, pass to the attachment manager
       
  1634     MMsvAttachmentManager& manager = store->AttachmentManagerL();
       
  1635     if ( iAttaWaiter->IsActive() )
       
  1636         {
       
  1637         // can't start an active operation because already active
       
  1638         User::Leave(KErrInUse);
       
  1639         }
       
  1640     manager.AddAttachmentL( aFile, attachment, iAttaWaiter->iStatus ); 
       
  1641     CleanupStack::Pop( attachment ); // ownership passed to manager
       
  1642     // We cannot start waiting before we know that the function we are waiting for
       
  1643     // did not leave. If we become active, and the function leaves, we are in trouble    
       
  1644     iAttaWaiter->StartWaitingL( aStatus, store, &manager );
       
  1645     CleanupStack::Pop( store ); // ownership passed
       
  1646     }
       
  1647 
       
  1648 // ---------------------------------------------------------
       
  1649 // CMmsClientMtm::AddLinkedAttachmentL
       
  1650 // ---------------------------------------------------------
       
  1651 //
       
  1652 void CMmsClientMtm::AddLinkedAttachmentL( const TDesC& aFilePath,
       
  1653     const TDesC8& aMimeType, TUint aCharset, TRequestStatus& aStatus )
       
  1654     {
       
  1655     TInt error = KErrNone;
       
  1656     TUint charset = aCharset;
       
  1657     if ( aMimeType.CompareF( KMmsTextPlain ) == 0 && aCharset == 0 )
       
  1658         {
       
  1659         // try to recognize character set
       
  1660         // We trap the recognization process
       
  1661         // If cannot recognize, the result will be 0 and default to us-ascii
       
  1662         TRAP ( error,
       
  1663             {
       
  1664             RFile file;
       
  1665             error = file.Open( Session().FileSession(), aFilePath,
       
  1666                 EFileRead|EFileShareReadersOnly);
       
  1667             if ( error == KErrNone )
       
  1668                 {
       
  1669                 CleanupClosePushL( file );
       
  1670                 charset = RecognizeCharSetL( file );
       
  1671                 CleanupStack::PopAndDestroy( &file ); // close file
       
  1672                 }
       
  1673             }
       
  1674             );
       
  1675         }
       
  1676     // Linked files cannot be converted to utf8. They must be sent as is no
       
  1677     // matter what the character set is.
       
  1678     
       
  1679     // Disk space is checked in AddFilePathAttachmentL after everything has
       
  1680     // been initialized.
       
  1681     
       
  1682     
       
  1683     if ( aMimeType.CompareF( KMmsTextPlain ) == 0 &&
       
  1684         ( charset == KMmsUTF16 ||
       
  1685         charset == KMmsIso10646Ucs2 ||
       
  1686         charset == KMmsUTF16LE ||
       
  1687         charset == KMmsUTF16BE ) )
       
  1688         {
       
  1689         AddAttachmentL( aFilePath, aMimeType, charset, aStatus );
       
  1690         }
       
  1691     else
       
  1692         {
       
  1693         AddFilePathAttachmentL( aFilePath, aMimeType,
       
  1694             CMsvAttachment::EMsvLinkedFile, aStatus, charset );
       
  1695         }
       
  1696     }
       
  1697 
       
  1698 // ---------------------------------------------------------
       
  1699 // CMmsClientMtm::AddEntryAsAttachmentL
       
  1700 // ---------------------------------------------------------
       
  1701 //
       
  1702 void CMmsClientMtm::AddEntryAsAttachmentL( TMsvId /*aAttachmentId*/,
       
  1703     TRequestStatus& /*aStatus*/ )
       
  1704     {
       
  1705     User::Leave( KErrNotSupported );
       
  1706     }
       
  1707 
       
  1708 // ---------------------------------------------------------
       
  1709 // CMmsClientMtm::CreateAttachmentL
       
  1710 // ---------------------------------------------------------
       
  1711 //
       
  1712 void CMmsClientMtm::CreateAttachmentL( const TDesC& aFileName,
       
  1713     RFile& aAttachmentFile, const TDesC8& aMimeType,
       
  1714     TUint aCharset, TRequestStatus& aStatus )
       
  1715     {
       
  1716     // Character set cannot be checked here because the file does not exist yet
       
  1717     // The caller gets an open file handle and is supposed to write data into
       
  1718     // the file.
       
  1719     if( !iAttaWaiter )
       
  1720         {
       
  1721         iAttaWaiter = CMmsAttachmentWaiter::NewL();
       
  1722         }
       
  1723 
       
  1724     // store must be the first item allocated because it is the last one to be popped
       
  1725     CMsvStore* store = iMsvEntry->EditStoreL();
       
  1726     CleanupStack::PushL( store );
       
  1727     
       
  1728     CMsvAttachment* attachmentInfo = 
       
  1729         CMsvAttachment::NewL( CMsvAttachment::EMsvFile );
       
  1730     CleanupStack::PushL( attachmentInfo );
       
  1731     
       
  1732     CMsvMimeHeaders* mimeHeaders = CMsvMimeHeaders::NewL();
       
  1733     CleanupStack::PushL( mimeHeaders );
       
  1734 
       
  1735     attachmentInfo->SetAttachmentNameL( aFileName );
       
  1736     
       
  1737     // set the mime-type if provided
       
  1738     if( aMimeType.Length() > 0 )
       
  1739         {
       
  1740         attachmentInfo->SetMimeTypeL( aMimeType );
       
  1741         TInt position = aMimeType.Find( KMmsSlash8 );
       
  1742         if ( position > 0 )
       
  1743             {
       
  1744             mimeHeaders->SetContentTypeL( aMimeType.Left( position ) );
       
  1745             }
       
  1746         if ( position < aMimeType.Length() - 1 )
       
  1747             {
       
  1748             mimeHeaders->SetContentSubTypeL( aMimeType.Mid( position + 1 ) );
       
  1749             }
       
  1750         }
       
  1751         
       
  1752     // save the character set        
       
  1753     mimeHeaders->SetMimeCharset( aCharset );
       
  1754 
       
  1755     mimeHeaders->SetSuggestedFilenameL( attachmentInfo->AttachmentName() );
       
  1756     
       
  1757     TInt size = 0;
       
  1758     size = KMmsIndexEntryExtra + mimeHeaders->Size();    
       
  1759     mimeHeaders->StoreL( *attachmentInfo );
       
  1760     
       
  1761     // mime headers have been streamed to CMsvAttachment, they can go now
       
  1762     CleanupStack::PopAndDestroy( mimeHeaders );
       
  1763     
       
  1764     // Check that sufficient disk space available
       
  1765     if ( TMmsGenUtils::DiskSpaceBelowCriticalLevelL( 
       
  1766         &Session().FileSession(), 
       
  1767         size,
       
  1768         iMessageDrive ) )
       
  1769             {
       
  1770             CleanupStack::PopAndDestroy( attachmentInfo );
       
  1771             User::Leave( KErrDiskFull );
       
  1772             }
       
  1773 
       
  1774     MMsvAttachmentManager& manager = store->AttachmentManagerL();
       
  1775     if ( iAttaWaiter->IsActive() )
       
  1776         {
       
  1777         // can't start an active operation because already active
       
  1778         User::Leave(KErrInUse);
       
  1779         }
       
  1780     manager.CreateAttachmentL( aFileName, aAttachmentFile, attachmentInfo,
       
  1781         iAttaWaiter->iStatus );
       
  1782     CleanupStack::Pop( attachmentInfo ); // ownership passed to manager
       
  1783     iAttaWaiter->StartWaitingL( aStatus, store, &manager );
       
  1784     CleanupStack::Pop( store ); // ownership passed
       
  1785     }
       
  1786 
       
  1787 // ---------------------------------------------------------
       
  1788 // CMmsClientMtm::CancelAttachmentOperation
       
  1789 // ---------------------------------------------------------
       
  1790 //
       
  1791 void CMmsClientMtm::CancelAttachmentOperation()
       
  1792     {
       
  1793     
       
  1794     if ( iAttaWaiter )
       
  1795         {
       
  1796         iAttaWaiter->Cancel();
       
  1797         delete iAttaWaiter;
       
  1798         iAttaWaiter = NULL;
       
  1799         }
       
  1800     }
       
  1801 
       
  1802 // ---------------------------------------------------------
       
  1803 // CMmsClientMtm::CreateAttachment2L
       
  1804 // ---------------------------------------------------------
       
  1805 //
       
  1806 void CMmsClientMtm::CreateAttachment2L(
       
  1807     CMsvStore& aStore,
       
  1808     RFile& aFile,
       
  1809     TDesC8& aMimeType,
       
  1810     CMsvMimeHeaders& aMimeHeaders,
       
  1811     CMsvAttachment* aAttachmentInfo,
       
  1812     TMsvAttachmentId& aAttaId)
       
  1813     {
       
  1814     _LIT8( KMmsText, "text" );
       
  1815     _LIT8( KMmsPlain, "plain" );
       
  1816     
       
  1817     if ( ( aMimeType.CompareF( KMmsTextPlain ) == 0  ||
       
  1818         ( aMimeHeaders.ContentType().CompareF( KMmsText ) == 0 && 
       
  1819         aMimeHeaders.ContentSubType().CompareF( KMmsPlain ) == 0 ) ) &&
       
  1820         aMimeHeaders.MimeCharset() == 0 )
       
  1821         {
       
  1822         // If no character set defined for a plain text attachment
       
  1823         // we try to recognize the character set.
       
  1824         // But if recoginzation fails, we say 0 (us-ascii)
       
  1825         TInt charset = 0;
       
  1826         TRAP_IGNORE ( 
       
  1827             {
       
  1828             charset = RecognizeCharSetL( aFile );
       
  1829             });
       
  1830         aMimeHeaders.SetMimeCharset( charset );
       
  1831         }
       
  1832     
       
  1833     return CMmsAttachmentHandler::CreateAttachmentL(
       
  1834         aStore,
       
  1835         aFile,
       
  1836         Session().FileSession(),
       
  1837         Session().CurrentDriveL(),
       
  1838         aMimeType,
       
  1839         aMimeHeaders,
       
  1840         aAttachmentInfo,
       
  1841         aAttaId );
       
  1842   
       
  1843     }
       
  1844     
       
  1845 // ---------------------------------------------------------
       
  1846 // CMmsClientMtm::CreateTextAttachmentL
       
  1847 // ---------------------------------------------------------
       
  1848 //
       
  1849 void CMmsClientMtm::CreateTextAttachmentL(
       
  1850             CMsvStore& aStore,
       
  1851             TMsvAttachmentId& aAttachmentId,
       
  1852             const TDesC& aText,
       
  1853             const TDesC& aFile,
       
  1854             TBool aConvertParagraphSeparator )
       
  1855     {
       
  1856 
       
  1857     CMmsAttachmentHandler::CreateTextAttachmentL( aStore,
       
  1858         aAttachmentId,
       
  1859         aText,
       
  1860         aFile,
       
  1861         Session().FileSession(),
       
  1862         Session().CurrentDriveL(),
       
  1863         aConvertParagraphSeparator );
       
  1864  
       
  1865     }
       
  1866     
       
  1867 // ---------------------------------------------------------
       
  1868 // CMmsClientMtm::CreateMessageL
       
  1869 // ---------------------------------------------------------
       
  1870 //
       
  1871 void CMmsClientMtm::CreateMessageL(
       
  1872     TMsvId aServiceId )
       
  1873     {
       
  1874     // Check that sufficient disk space available
       
  1875     // for index entry
       
  1876     if ( TMmsGenUtils::DiskSpaceBelowCriticalLevelL( 
       
  1877         &Session().FileSession(), 
       
  1878         KMmsIndexEntryExtra,
       
  1879         iMessageDrive ) )
       
  1880             {
       
  1881             // we use standard error code here
       
  1882             User::Leave( KErrDiskFull );
       
  1883             }
       
  1884 
       
  1885     // just call the base class function
       
  1886     CBaseMtm::CreateMessageL( aServiceId );
       
  1887     
       
  1888     iMmsHeaders->Reset( iMmsSettings );
       
  1889     }
       
  1890     
       
  1891 // ---------------------------------------------------------
       
  1892 // CMmsClientMtm::BioTypeChangedL
       
  1893 // ---------------------------------------------------------
       
  1894 //
       
  1895 void CMmsClientMtm::BioTypeChangedL( TUid /*aBioTypeUid*/ )
       
  1896     {
       
  1897     // Do nothing. MMS does not support BIO type.
       
  1898     }
       
  1899     
       
  1900 // ---------------------------------------------------------
       
  1901 // CMmsClientMtm::DefaultServiceL
       
  1902 // ---------------------------------------------------------
       
  1903 //
       
  1904 TMsvId CMmsClientMtm::DefaultServiceL() const
       
  1905     {
       
  1906     // Override base implementation so that we always use MMS service
       
  1907     // even when called by Postcard or Audio Message which have different MTM tyoe
       
  1908     
       
  1909     if ( iServiceId != KMsvNullIndexEntryId ) 
       
  1910         {
       
  1911         return iServiceId;
       
  1912         }
       
  1913     
       
  1914     // Create a new entry, showing invisible entries (because the service entry is invisible)
       
  1915     
       
  1916     TMsvSelectionOrdering ordering( KMsvNoGrouping, EMsvSortByNone, ETrue );
       
  1917     CMsvEntry* entry = CMsvEntry::NewL( iOwnSession, KMsvRootIndexEntryId, ordering );
       
  1918     CleanupStack::PushL( entry );
       
  1919 	
       
  1920  	CMsvEntrySelection *sel=entry->ChildrenWithMtmL( KUidMsgTypeMultimedia );
       
  1921 	CleanupStack::PushL( sel );
       
  1922 	if( sel->Count() == 0 )
       
  1923 	    {
       
  1924 	    User::Leave(KErrNotFound);
       
  1925 	    } 
       
  1926 	TMsvId service=sel->At( 0 );
       
  1927  	CleanupStack::PopAndDestroy( sel );
       
  1928  	CleanupStack::PopAndDestroy( entry );
       
  1929 	return service;
       
  1930     }
       
  1931 
       
  1932 // ---------------------------------------------------------
       
  1933 // CMmsClientMtm::RemoveDefaultServiceL
       
  1934 // ---------------------------------------------------------
       
  1935 //
       
  1936 void CMmsClientMtm::RemoveDefaultServiceL()
       
  1937     {
       
  1938     // not supported
       
  1939     }
       
  1940 
       
  1941 // ---------------------------------------------------------
       
  1942 // CMmsClientMtm::ChangeDefaultServiceL
       
  1943 // ---------------------------------------------------------
       
  1944 //
       
  1945 void CMmsClientMtm::ChangeDefaultServiceL( const TMsvId& /*aService*/ )
       
  1946     {
       
  1947     // not supported
       
  1948     }
       
  1949 
       
  1950 // ---------------------------------------------------------
       
  1951 // CMmsClientMtm::QueryCapability
       
  1952 // ---------------------------------------------------------
       
  1953 //
       
  1954 TInt CMmsClientMtm::QueryCapability(
       
  1955     TUid aCapability,
       
  1956     TInt& aResponse )
       
  1957     {
       
  1958     TInt error = KErrNone;
       
  1959     switch ( aCapability.iUid )
       
  1960         {
       
  1961         // Supported:
       
  1962         case KUidMtmQueryMaxTotalMsgSizeValue:
       
  1963             aResponse = KMaxTInt;
       
  1964             break;
       
  1965         case KUidMsvMtmQueryEditorUidValue:
       
  1966             aResponse = KUidMsgMmsEditor;
       
  1967             break;
       
  1968         case KUidMtmQueryMaxRecipientCountValue:
       
  1969         // According to conformance document we must support at least 20
       
  1970             aResponse = -1; // unlimited number
       
  1971             break;
       
  1972         case KUidMtmQuerySendAsMessageSendSupportValue:
       
  1973             aResponse = ETrue;
       
  1974             break;           
       
  1975         case KUidMtmQuerySupportSubjectValue:
       
  1976         case KUidMtmQuerySupportAttachmentsValue:
       
  1977         case KUidMtmQueryCanSendMsgValue:
       
  1978         case KUidMtmQueryCanReceiveMsgValue:
       
  1979         case KUidMtmQuerySupportsRecipientTypeValue:
       
  1980             // returns KErrNone
       
  1981             break;
       
  1982         // All others - Not Supported:
       
  1983         default:
       
  1984             error = KErrNotSupported;
       
  1985             break;
       
  1986         }
       
  1987     return error;
       
  1988 
       
  1989     }
       
  1990 
       
  1991 // ---------------------------------------------------------
       
  1992 // CClientMtm::InvokeSyncFunctionL
       
  1993 // ---------------------------------------------------------
       
  1994 //
       
  1995 void CMmsClientMtm::InvokeSyncFunctionL(
       
  1996     TInt /*aFunctionId*/,
       
  1997     const CMsvEntrySelection& /*aSelection*/,
       
  1998     TDes8& /*aParameter*/ )
       
  1999     {
       
  2000 
       
  2001     User::Leave( KErrNotSupported );
       
  2002 
       
  2003     }
       
  2004 
       
  2005 // ---------------------------------------------------------
       
  2006 // CMmsClientMtm::InvokeAsyncFunctionL
       
  2007 // ---------------------------------------------------------
       
  2008 //
       
  2009 CMsvOperation* CMmsClientMtm::InvokeAsyncFunctionL(
       
  2010     TInt aFunctionId,
       
  2011     const CMsvEntrySelection& aSelection,
       
  2012     TDes8& aParameter,
       
  2013     TRequestStatus& aCompletionStatus )
       
  2014     {
       
  2015     
       
  2016     CMsvOperation* op = NULL;
       
  2017     
       
  2018     if ( aSelection.Count() == 0 )
       
  2019         {
       
  2020         User::Leave( KErrArgument );
       
  2021         }
       
  2022         
       
  2023     // make a copy of the selection just in case    
       
  2024     CMsvEntrySelection* selection = aSelection.CopyL();
       
  2025     CleanupStack::PushL( selection );
       
  2026 
       
  2027     // Change service id to related id
       
  2028     // for the scheduled commands
       
  2029     CMsvEntry* cEntry = NULL;
       
  2030     TInt error = KErrNone;
       
  2031 
       
  2032     if ( aFunctionId == EMmsScheduledSend ||
       
  2033         aFunctionId == EMmsScheduledReceive ||
       
  2034         aFunctionId == EMmsScheduledReceiveForced ||
       
  2035         aFunctionId == EMmsDeleteSchedule ||
       
  2036         aFunctionId == EMmsScheduledForward ||
       
  2037         aFunctionId == EMmsScheduledNotificationDelete ||
       
  2038         aFunctionId == KMTMStandardFunctionsSendMessage )
       
  2039         {
       
  2040         TInt j = 0;
       
  2041         TInt i;
       
  2042         cEntry = Session().GetEntryL( KMsvRootIndexEntryId );
       
  2043         CleanupStack::PushL( cEntry );
       
  2044 
       
  2045         if ( aSelection.At( 0 ) == iServiceId )
       
  2046             {
       
  2047             // skip service
       
  2048             j++;
       
  2049             }
       
  2050 
       
  2051         for ( i = aSelection.Count() - 1; i >=j;  i-- )
       
  2052             {
       
  2053             TRAP( error, 
       
  2054                 {
       
  2055                 cEntry->SetEntryL( aSelection.At( i ) );
       
  2056                 TMsvEntry entry = cEntry->Entry();
       
  2057                 // check first to be sure you don't lose the original
       
  2058                 // service id
       
  2059                 if ( entry.iServiceId != KMsvLocalServiceIndexEntryId )
       
  2060                     {
       
  2061                     entry.iRelatedId = entry.iServiceId;
       
  2062                     }
       
  2063                 entry.iServiceId = KMsvLocalServiceIndexEntryId;
       
  2064                 cEntry->ChangeL( entry );
       
  2065                 });
       
  2066             if ( error == KErrNotFound )
       
  2067                 {
       
  2068                 selection->Delete( i );
       
  2069                 }
       
  2070             }
       
  2071 
       
  2072         CleanupStack::PopAndDestroy( cEntry );
       
  2073         cEntry = NULL;
       
  2074         }
       
  2075     
       
  2076     if ( aFunctionId == KMTMStandardFunctionsSendMessage && selection->Count() > 0 )
       
  2077         {
       
  2078         // This is the SendAs send command. Ignore parameter
       
  2079         TCommandParameters parameters; // initialized to zero
       
  2080         TCommandParametersBuf paramPack( parameters );
       
  2081         // Move the messages to OUTBOX synchronously
       
  2082         cEntry = Session().GetEntryL( KMsvLocalServiceIndexEntryIdValue );
       
  2083         CleanupStack::PushL( cEntry );
       
  2084         cEntry->SetEntryL( selection->At( 0 ) );
       
  2085         TMsvId currentParent = cEntry->Entry().Parent();
       
  2086         TMsvLocalOperationProgress progress;
       
  2087         if ( currentParent != KMsvGlobalOutBoxIndexEntryId )
       
  2088             {
       
  2089             cEntry->MoveL( *selection, KMsvGlobalOutBoxIndexEntryId, progress );
       
  2090             }
       
  2091         CleanupStack::PopAndDestroy( cEntry );
       
  2092         cEntry = NULL;
       
  2093         }
       
  2094       
       
  2095     if ( selection->Count() == 0 )
       
  2096         {
       
  2097         // we are given a selection of entries that were not found.
       
  2098         User::Leave( KErrNotFound );
       
  2099         }
       
  2100         
       
  2101     //
       
  2102     // Pass all commands onto the server MTM
       
  2103     //
       
  2104     if ( aFunctionId == KMTMStandardFunctionsSendMessage )
       
  2105         {
       
  2106         // no need to put op on cleanup stack because
       
  2107         // its ownership will be transferred to caller in a moment
       
  2108         op = CMmsSendMessageOperation::NewL( Session(),
       
  2109             *selection,
       
  2110             aParameter,
       
  2111             aCompletionStatus );
       
  2112         }
       
  2113     else
       
  2114         {
       
  2115         op =  Session().TransferCommandL(
       
  2116             *selection, aFunctionId, aParameter, aCompletionStatus );
       
  2117         }
       
  2118     CleanupStack::PopAndDestroy( selection );
       
  2119     return op;    
       
  2120     }
       
  2121 
       
  2122 // ---------------------------------------------------------
       
  2123 // CMmsClientMtm::ListNotificationsInInboxL
       
  2124 // ---------------------------------------------------------
       
  2125 //
       
  2126 CMsvEntrySelection* CMmsClientMtm::ListNotificationsInInboxL()
       
  2127     {
       
  2128     CMsvEntry* cEntry = Session().GetEntryL( KMsvGlobalInBoxIndexEntryId );
       
  2129     CleanupStack::PushL( cEntry );
       
  2130 
       
  2131     CMsvEntrySelection* notifications = 
       
  2132         cEntry->ChildrenWithMtmL( KUidMsgMMSNotification );
       
  2133     CleanupStack::PushL( notifications );
       
  2134 
       
  2135     // Count only notifications that are free for a new operation
       
  2136     for ( TInt i = notifications->Count() - 1 ; i >= 0; i-- ) 
       
  2137         {
       
  2138         TMsvId notifId = notifications->At( i );
       
  2139         cEntry->SetEntryL( notifId );
       
  2140     
       
  2141         TMsvEntry tEntry = cEntry->Entry();
       
  2142         if ( tEntry.iMtmData2 & KMmsNewOperationForbidden )
       
  2143             {
       
  2144             // Delete notification from the notifications array.
       
  2145             notifications->Delete( i );
       
  2146             }
       
  2147         }
       
  2148 
       
  2149     notifications->Compress();
       
  2150     CleanupStack::Pop( notifications ); // ownership transferred to caller
       
  2151     CleanupStack::PopAndDestroy( cEntry );
       
  2152     return notifications;
       
  2153     }
       
  2154     
       
  2155 // ---------------------------------------------------------
       
  2156 // CMmsClientMtm::ContextEntrySwitched
       
  2157 // ---------------------------------------------------------
       
  2158 //
       
  2159 void CMmsClientMtm::ContextEntrySwitched()
       
  2160     {
       
  2161     // Context change notification.
       
  2162     // Reset data.
       
  2163 
       
  2164     // Note: Body text reset would be here if supported.
       
  2165     
       
  2166     iAddresseeList->Reset();
       
  2167     iMmsHeaders->Reset( iMmsSettings );
       
  2168     iFetchAll = EFalse;
       
  2169     iFetchOverride = ETrue;
       
  2170     iAttributes->Reset();
       
  2171     }
       
  2172 
       
  2173 // ---------------------------------------------------------
       
  2174 // CMmsClientMtm::HandleEntryEventL
       
  2175 // ---------------------------------------------------------
       
  2176 //
       
  2177 void CMmsClientMtm::HandleEntryEventL(
       
  2178     TMsvEntryEvent /*aEvent*/,
       
  2179     TAny* /*arg1*/,
       
  2180     TAny* /*arg2*/,
       
  2181     TAny* /*arg3*/ )
       
  2182     {
       
  2183     // No operation
       
  2184     }
       
  2185 
       
  2186 // ---------------------------------------------------------
       
  2187 // CMmsClientMtm::ConstructL
       
  2188 // ---------------------------------------------------------
       
  2189 //
       
  2190 void CMmsClientMtm::ConstructL()
       
  2191     {
       
  2192     // First loading settings
       
  2193     iMmsSettings = CMmsSettings::NewL();
       
  2194     iMmsSettings->LoadSettingsL();
       
  2195     // Get the base values to detect changes
       
  2196     iHomeMode = iMmsSettings->ReceivingModeHome();
       
  2197     iRoamingMode = iMmsSettings->ReceivingModeForeign();
       
  2198     iAccessPointCount = iMmsSettings->AccessPointCount();
       
  2199     
       
  2200     iMessageDrive = EDriveC;
       
  2201     TInt error = KErrNone;
       
  2202 
       
  2203     TRAP ( error, { iMessageDrive = Session().CurrentDriveL(); } );
       
  2204 
       
  2205     if ( error != KErrNone )
       
  2206         {
       
  2207         // if cannot ask, use default
       
  2208         iMessageDrive = EDriveC;
       
  2209         }
       
  2210 
       
  2211     // if no service, creating one
       
  2212     TMsvId tempServiceId = KMsvNullIndexEntryId;
       
  2213     TRAP( error, tempServiceId = DefaultServiceL() )
       
  2214         {
       
  2215         if ( error == KErrNotFound )
       
  2216             {
       
  2217             tempServiceId = KMsvNullIndexEntryId;
       
  2218             }
       
  2219         }
       
  2220     
       
  2221     // service id is set after call to DefaultServiceL(), otherwise
       
  2222     // DefaultServiceL() will just return iServiceId
       
  2223     iServiceId = iMmsSettings->Service();
       
  2224     if ( iServiceId == KMsvNullIndexEntryId ||
       
  2225          iServiceId != tempServiceId )
       
  2226         {
       
  2227         // If there was no default service, a new one must be created.
       
  2228         
       
  2229         // If the service id saved in the settings differs from
       
  2230         // the one read from disk, we call create service.
       
  2231         // The create service function should check the actual
       
  2232         // values of MMS service and MMS private folders and
       
  2233         // ensure that the values in central repository and mail store match.
       
  2234         
       
  2235         // Check that sufficient disk space available
       
  2236         // for service entry
       
  2237         if ( TMmsGenUtils::DiskSpaceBelowCriticalLevelL( 
       
  2238             &Session().FileSession(), 
       
  2239             KMmsIndexEntryExtra, // Service entry has no extra data
       
  2240             iMessageDrive ) )
       
  2241             {
       
  2242             // we use standard error code here
       
  2243             User::Leave( KErrDiskFull );
       
  2244             }
       
  2245         // creates new service entry + notification and mmbox folder entries
       
  2246         iMmsSettings->CreateNewServiceL( Session() ); 
       
  2247         // Save settings is not needed - service creation saves the settings.
       
  2248         iServiceId = iMmsSettings->Service();
       
  2249         }
       
  2250 
       
  2251     iMmsHeaders = CMmsHeaders::NewL( iMmsSettings->MmsVersion() );
       
  2252 
       
  2253     // Address alias separators no longer read from resoure.
       
  2254     // Standard MIME separators < and > always used.
       
  2255     
       
  2256     iAttributes  = new(ELeave) CDesCArrayFlat( KMmsAttributeArrayGranularity );
       
  2257 
       
  2258     // Set the original context to the service entry
       
  2259     SwitchCurrentEntryL( iServiceId );
       
  2260 
       
  2261     }
       
  2262 
       
  2263 // ---------------------------------------------------------
       
  2264 // CMmsClientMtm::ValidateService
       
  2265 // ---------------------------------------------------------
       
  2266 //
       
  2267 TInt CMmsClientMtm::ValidateService( TMsvId aServiceId )
       
  2268     {
       
  2269     TInt error = KErrNone;
       
  2270     // There should be only one service,
       
  2271     // and it must match with the one that is in settings
       
  2272     if( aServiceId != iMmsSettings->Service() )
       
  2273         {
       
  2274         return KErrNotFound;
       
  2275         }
       
  2276     
       
  2277     // Check settings
       
  2278     error = iMmsSettings->ValidateSettings();
       
  2279     return error;
       
  2280     }
       
  2281 
       
  2282 // ---------------------------------------------------------
       
  2283 // CMmsClientMtm::MessageSize
       
  2284 // ---------------------------------------------------------
       
  2285 //
       
  2286 TInt32 CMmsClientMtm::MessageSize()
       
  2287     {
       
  2288     // First we should assert that iMsvEntry is not NULL, and panic, if it is
       
  2289     __ASSERT_DEBUG( iMsvEntry, gPanic( EMmsNoCMsvEntrySet ));
       
  2290     TUint size = 0;
       
  2291     TRAP_IGNORE({size = AttachmentsSizeL() + iMmsHeaders->Size();} );
       
  2292     return size;
       
  2293     }
       
  2294 
       
  2295 // ---------------------------------------------------------
       
  2296 // CMmsClientMtm::SetMessageDescriptionL
       
  2297 // ---------------------------------------------------------
       
  2298 //
       
  2299 void CMmsClientMtm::SetMessageDescriptionL( const TDesC& aText )
       
  2300     {
       
  2301     // First we should assert that iMsvEntry is not NULL, and panic, if it is
       
  2302     __ASSERT_DEBUG( iMsvEntry, gPanic( EMmsNoCMsvEntrySet ));
       
  2303     TMsvEntry entry = iMsvEntry->Entry();
       
  2304     entry.iDescription.Set( aText );
       
  2305     iMsvEntry->ChangeL( entry );
       
  2306     }
       
  2307     
       
  2308 // ---------------------------------------------------------
       
  2309 // CMmsClientMtm::AddAttributeL
       
  2310 // ---------------------------------------------------------
       
  2311 //
       
  2312 void CMmsClientMtm::AddAttributeL( const TDesC& aName, const TDesC& aValue )
       
  2313     {
       
  2314     if ( aName.Length() == 0 || aValue.Length() == 0 )
       
  2315         {
       
  2316         User::Leave( KErrArgument );
       
  2317         }
       
  2318     TMmsGenUtils::AddAttributeL( aName, aValue, *iAttributes );
       
  2319     }
       
  2320     
       
  2321 // ---------------------------------------------------------
       
  2322 // CMmsClientMtm::GetAttributeL
       
  2323 // ---------------------------------------------------------
       
  2324 //
       
  2325 TPtrC CMmsClientMtm::GetAttributeL( const TDesC& aName )
       
  2326     {
       
  2327     if ( aName.Length() == 0 )
       
  2328         {
       
  2329         User::Leave( KErrArgument );
       
  2330         }
       
  2331     return TMmsGenUtils::GetAttributeL( aName, *iAttributes );
       
  2332     }
       
  2333     
       
  2334 // ---------------------------------------------------------
       
  2335 // CMmsClientMtm::FindAttribute
       
  2336 // ---------------------------------------------------------
       
  2337 //
       
  2338 TBool CMmsClientMtm::FindAttribute( const TDesC& aName )
       
  2339     {
       
  2340     if ( aName.Length() == 0 )
       
  2341         {
       
  2342         return EFalse;
       
  2343         }
       
  2344     return TMmsGenUtils::FindAttribute( aName, *iAttributes );
       
  2345     }
       
  2346     
       
  2347 // ---------------------------------------------------------
       
  2348 // CMmsClientMtm::DeleteAttribute
       
  2349 // ---------------------------------------------------------
       
  2350 //
       
  2351 void CMmsClientMtm::DeleteAttribute( const TDesC& aName )
       
  2352     {
       
  2353     if ( aName.Length() == 0 )
       
  2354         {
       
  2355         return;
       
  2356         }
       
  2357     TMmsGenUtils::DeleteAttribute( aName, *iAttributes );
       
  2358     }
       
  2359     
       
  2360 // ---------------------------------------------------------
       
  2361 // CMmsClientMtm::ResetAttributes
       
  2362 // ---------------------------------------------------------
       
  2363 //
       
  2364 void CMmsClientMtm::ResetAttributes()
       
  2365     {
       
  2366     iAttributes->Reset();
       
  2367     }
       
  2368 
       
  2369 // ---------------------------------------------------------
       
  2370 // CMmsClientMtm::BuildAddresseeListL
       
  2371 // ---------------------------------------------------------
       
  2372 //
       
  2373 void CMmsClientMtm::BuildAddresseeListL() 
       
  2374     {
       
  2375 
       
  2376     iAddresseeList->Reset();
       
  2377 
       
  2378     const CDesCArray& array1 = iMmsHeaders->ToRecipients();
       
  2379     const CDesCArray& array2 = iMmsHeaders->CcRecipients();
       
  2380     const CDesCArray& array3 = iMmsHeaders->BccRecipients();
       
  2381 
       
  2382     BuildAddresseeListL( array1, EMsvRecipientTo );
       
  2383     BuildAddresseeListL( array2, EMsvRecipientCc );
       
  2384     BuildAddresseeListL( array3, EMsvRecipientBcc );
       
  2385 
       
  2386     }
       
  2387 
       
  2388 // ---------------------------------------------------------
       
  2389 // CMmsClientMtm::BuildAddresseeListL
       
  2390 // ---------------------------------------------------------
       
  2391 //
       
  2392 void CMmsClientMtm::BuildAddresseeListL(
       
  2393     const CDesCArray& aArray, TMsvRecipientType aValue ) 
       
  2394     {
       
  2395 
       
  2396     TInt size;
       
  2397     size = aArray.Count();
       
  2398     for ( TInt i=0; i < size; i++ )
       
  2399         {
       
  2400         iAddresseeList->AppendL( aValue, aArray[i] );
       
  2401         }
       
  2402     }
       
  2403 
       
  2404 // ---------------------------------------------------------
       
  2405 // CMmsClientMtm::AttachmentsSizeL
       
  2406 // ---------------------------------------------------------
       
  2407 //
       
  2408 TInt32 CMmsClientMtm::AttachmentsSizeL()
       
  2409     {
       
  2410     TInt32 size = 0;
       
  2411     // We need to have store. If the caller is keeping edit store open,
       
  2412     // this function leaves.
       
  2413     // That makes sense, because in that case the user might have
       
  2414     // uncommitted attachments, and the total size would be incorrect anyway.
       
  2415     CMsvStore* store = iMsvEntry->ReadStoreL();
       
  2416     CleanupStack::PushL( store );
       
  2417     size = CMmsAttachmentHandler::AttachmentsSizeL( *store );
       
  2418     CleanupStack::PopAndDestroy( store );
       
  2419     store = NULL;    
       
  2420     return size;
       
  2421     }
       
  2422 
       
  2423 // ---------------------------------------------------------
       
  2424 // CMmsClientMtm::ListMmsFolderNotificationsL()
       
  2425 // ---------------------------------------------------------
       
  2426 //
       
  2427 CMsvEntrySelection* CMmsClientMtm::ListMmsFolderNotificationsL() 
       
  2428     {
       
  2429 
       
  2430     // list notifications in private invisible folder
       
  2431 
       
  2432     TMsvId notificationParent = iMmsSettings->NotificationFolder();
       
  2433 
       
  2434     CMsvEntrySelection* notifications = NULL;
       
  2435     if ( notificationParent == KMsvNullIndexEntryId )
       
  2436         {
       
  2437         notifications = new ( ELeave ) CMsvEntrySelection();
       
  2438         return notifications; // empty selection
       
  2439         }
       
  2440         
       
  2441     CMsvEntry* cEntry = NULL;
       
  2442     cEntry = Session().GetEntryL( notificationParent );
       
  2443     CleanupStack::PushL( cEntry );
       
  2444 
       
  2445     // show invisible entries
       
  2446     cEntry->SetSortTypeL( TMsvSelectionOrdering( KMsvNoGrouping,
       
  2447         EMsvSortByNone, ETrue ) );
       
  2448     notifications = cEntry->ChildrenWithMtmL( KUidMsgTypeMultimedia );
       
  2449     CleanupStack::PushL( notifications );
       
  2450 
       
  2451     // strip off stuff other than notifications
       
  2452     // We are handling the invisible MMS folder now
       
  2453     // There may be delivery reports or binary notifications besides
       
  2454     // the normal notifications
       
  2455 
       
  2456     for ( TInt i = notifications->Count() - 1; i >= 0; i-- ) 
       
  2457         {
       
  2458         cEntry->SetEntryL( notifications->At( i ));
       
  2459         
       
  2460         TMsvEntry myEntry = cEntry->Entry();
       
  2461         if ( !( ( myEntry.iMtmData1 & KMmsMessageTypeMask ) == 
       
  2462             KMmsMessageMNotificationInd ) )
       
  2463             {
       
  2464             // this is not notification
       
  2465             notifications->Delete( i );
       
  2466             }
       
  2467         }
       
  2468 
       
  2469     notifications->Compress();
       
  2470         
       
  2471     CleanupStack::Pop( notifications ); // ownership transferred to caller
       
  2472     CleanupStack::PopAndDestroy( cEntry );
       
  2473 
       
  2474     return notifications;
       
  2475     
       
  2476     }
       
  2477     
       
  2478 // ---------------------------------------------------------
       
  2479 // CMmsClientMtm::ListInboxNotificationsL()
       
  2480 // ---------------------------------------------------------
       
  2481 //
       
  2482 CMsvEntrySelection* CMmsClientMtm::ListInboxNotificationsL()
       
  2483     {
       
  2484     CMsvEntry* cEntry = NULL;
       
  2485     cEntry = Session().GetEntryL( KMsvGlobalInBoxIndexEntryId );
       
  2486     CleanupStack::PushL( cEntry );
       
  2487     
       
  2488     CMsvEntrySelection* notifications = new( ELeave )CMsvEntrySelection;
       
  2489     CleanupStack::PushL( notifications );
       
  2490     
       
  2491     // Notifications from inbox - but not in offline state if the user has not
       
  2492     // initiated the fetch (iFetchOeverride = ETrue)
       
  2493     // If the user initiates the fetch in offline mode, the entry goes to
       
  2494     // failed state because the use must see why the fetching fails.
       
  2495     // CMmsNotificationClientMtm overrides the FetchAllL function so that
       
  2496     // we should get here only when the receiving mode changes.
       
  2497     if ( iFetchOverride || TMmsGenUtils::NetworkOperationsAllowed() )
       
  2498         {
       
  2499         CMsvEntrySelection* notificationsInInbox = ListNotificationsInInboxL();
       
  2500         CleanupStack::PushL( notificationsInInbox );
       
  2501     
       
  2502         // The readOnly flag has to be set on for notifications in inbox
       
  2503         // in order to schedule notifications.
       
  2504         for ( TInt j = notificationsInInbox->Count() - 1; j >= 0; j-- )
       
  2505             {
       
  2506             cEntry->SetEntryL( notificationsInInbox->At( j ) );
       
  2507             TMsvEntry entry = cEntry->Entry();
       
  2508             entry.SetReadOnly( EFalse ); 
       
  2509             cEntry->ChangeL( entry );
       
  2510 
       
  2511             notifications->AppendL( notificationsInInbox->At( j ) );
       
  2512             }
       
  2513 
       
  2514         CleanupStack::PopAndDestroy( notificationsInInbox );
       
  2515         }
       
  2516         
       
  2517     CleanupStack::Pop( notifications ); // ownership transferred to caller
       
  2518     CleanupStack::PopAndDestroy( cEntry );
       
  2519     
       
  2520     return notifications;
       
  2521     }
       
  2522     
       
  2523 // ---------------------------------------------------------
       
  2524 // CMmsClientMtm::FetchAllFromInboxL
       
  2525 // ---------------------------------------------------------
       
  2526 //
       
  2527 CMsvOperation* CMmsClientMtm::FetchAllFromInboxL( TRequestStatus& aCompletionStatus,
       
  2528     TBool aForced )
       
  2529     {
       
  2530     
       
  2531     iFetchOverride = aForced;
       
  2532     
       
  2533     CMsvEntrySelection* selection = ListInboxNotificationsL();
       
  2534     CleanupStack::PushL( selection );
       
  2535 
       
  2536     if ( selection->Count() == 0 )
       
  2537         {
       
  2538         CleanupStack::PopAndDestroy( selection );
       
  2539         TPckgC < TMsvId > progress = 0;
       
  2540         aCompletionStatus = KRequestPending;
       
  2541         return  CMsvCompletedOperation::NewL( Session(), Type(), progress,
       
  2542             KMsvLocalServiceIndexEntryId, aCompletionStatus );
       
  2543         }
       
  2544 
       
  2545     TCommandParameters parameters; // initialized to zero
       
  2546     TCommandParametersBuf paramPack( parameters );
       
  2547 
       
  2548     CMsvOperation* op = NULL;
       
  2549     if ( iFetchOverride )
       
  2550         {
       
  2551         op = InvokeAsyncFunctionL(
       
  2552             EMmsScheduledReceiveForced,
       
  2553             *selection,
       
  2554             paramPack,
       
  2555             aCompletionStatus );
       
  2556         }
       
  2557     else
       
  2558         {
       
  2559         op = InvokeAsyncFunctionL(
       
  2560             EMmsScheduledReceive,
       
  2561             *selection,
       
  2562             paramPack,
       
  2563             aCompletionStatus );
       
  2564         // reset override to default value
       
  2565         iFetchOverride = ETrue;
       
  2566         }
       
  2567 
       
  2568     CleanupStack::PopAndDestroy( selection );
       
  2569     return op;
       
  2570     }
       
  2571     
       
  2572 
       
  2573 // ---------------------------------------------------------
       
  2574 // CMmsClientMtm::ConvertUTCDateToLocal
       
  2575 // ---------------------------------------------------------
       
  2576 //
       
  2577 /*
       
  2578 TInt64 CMmsClientMtm::ConvertUTCDateToLocal( TInt64 aDate ) const
       
  2579     {
       
  2580 
       
  2581     TLocale locale;
       
  2582     locale.Refresh();
       
  2583     TInt64 localDate;
       
  2584     TTimeIntervalSeconds universalTimeOffset( locale.UniversalTimeOffset() );
       
  2585 
       
  2586     localDate = aDate + universalTimeOffset.Int();
       
  2587 
       
  2588     if ( locale.QueryHomeHasDaylightSavingOn() )
       
  2589         {
       
  2590         TTimeIntervalSeconds daylightSaving( 60 * 60 );
       
  2591         localDate += daylightSaving.Int();
       
  2592         }
       
  2593     
       
  2594     return localDate;
       
  2595 
       
  2596     }
       
  2597 */    
       
  2598 
       
  2599 // ---------------------------------------------------------
       
  2600 // CMmsClientMtm::FindInRecipientL
       
  2601 // ---------------------------------------------------------
       
  2602 //
       
  2603 TBool CMmsClientMtm::FindInRecipientL( 
       
  2604     const TDesC& aTextToFind,
       
  2605     TMsvPartList aPartlist,
       
  2606     const CDesCArray& aRecipients,
       
  2607     CMsvFindText& aFindText )
       
  2608     {
       
  2609     TInt count = aRecipients.Count();
       
  2610     TBool found = EFalse;
       
  2611     for  (TInt i=0; i < count; i++ )
       
  2612         {
       
  2613         // Check alias and real address parts
       
  2614         // separately. Otherwise separator character could 
       
  2615         // spoil the check.
       
  2616         if ( aFindText.FindTextL( aTextToFind, 
       
  2617             TMmsGenUtils::Alias( aRecipients[i] ), aPartlist ) )
       
  2618             {
       
  2619             found = ETrue;
       
  2620             break;
       
  2621             }
       
  2622         else if ( aFindText.FindTextL( aTextToFind, 
       
  2623             TMmsGenUtils::PureAddress( aRecipients[i] ), aPartlist ) )
       
  2624             {
       
  2625             found = ETrue;
       
  2626             break;
       
  2627             }
       
  2628         else
       
  2629             {
       
  2630             // keep LINT happy
       
  2631             }
       
  2632         }
       
  2633     return found;
       
  2634     }
       
  2635 
       
  2636 // ---------------------------------------------------------
       
  2637 // CMmsClientMtm::AddFilePathAttachmentL
       
  2638 // ---------------------------------------------------------
       
  2639 //
       
  2640 void CMmsClientMtm::AddFilePathAttachmentL(
       
  2641     const TDesC& aFilePath,
       
  2642     const TDesC8& aMimeType,
       
  2643     CMsvAttachment::TMsvAttachmentType aType,
       
  2644     TRequestStatus& aStatus,
       
  2645     const TUint aCharacterSet /* = 0 */ )
       
  2646     {
       
  2647     __ASSERT_DEBUG( aType != CMsvAttachment::EMsvMessageEntry,
       
  2648         User::Invariant() );
       
  2649 
       
  2650     if( !iAttaWaiter )
       
  2651         {
       
  2652         iAttaWaiter = CMmsAttachmentWaiter::NewL();
       
  2653         }
       
  2654     
       
  2655     // store must be the first item allocated because it is the last one to be popped
       
  2656     CMsvStore* store = iMsvEntry->EditStoreL();
       
  2657     CleanupStack::PushL( store );
       
  2658     
       
  2659     CMsvAttachment* attachment = CMsvAttachment::NewL( aType );
       
  2660     CleanupStack::PushL( attachment );
       
  2661     
       
  2662     CMsvMimeHeaders* mimeHeaders = CMsvMimeHeaders::NewL();
       
  2663     CleanupStack::PushL( mimeHeaders );
       
  2664 
       
  2665     // set the size
       
  2666     TEntry fileEntry;
       
  2667     RFs& fs = Session().FileSession();
       
  2668     User::LeaveIfError( fs.Entry( aFilePath, fileEntry ) );
       
  2669     attachment->SetSize( fileEntry.iSize );
       
  2670     
       
  2671     // set attachment name
       
  2672     TParse fileNameParser;
       
  2673     User::LeaveIfError( fileNameParser.Set( aFilePath, NULL, NULL) );
       
  2674     
       
  2675     attachment->SetAttachmentNameL( fileNameParser.NameAndExt() );
       
  2676     // set the mime-type if provided
       
  2677     if( aMimeType.Length() > 0 )
       
  2678         {
       
  2679         attachment->SetMimeTypeL( aMimeType );
       
  2680         TInt position = aMimeType.Find( KMmsSlash8 );
       
  2681         if ( position > 0 )
       
  2682             {
       
  2683             mimeHeaders->SetContentTypeL( aMimeType.Left( position ) );
       
  2684             }
       
  2685         if ( position < aMimeType.Length() - 1 )
       
  2686             {
       
  2687             mimeHeaders->SetContentSubTypeL( aMimeType.Mid( position + 1 ) );
       
  2688             }
       
  2689         }
       
  2690 
       
  2691     mimeHeaders->SetSuggestedFilenameL( attachment->AttachmentName() );
       
  2692     
       
  2693     mimeHeaders->SetMimeCharset( aCharacterSet );
       
  2694     mimeHeaders->StoreL( *attachment );
       
  2695     
       
  2696     TInt diskSpace = 0;
       
  2697     diskSpace = KMmsIndexEntryExtra + mimeHeaders->Size();
       
  2698     
       
  2699     // mime headers have been streamed to CMsvAttachment, they can go now
       
  2700     CleanupStack::PopAndDestroy( mimeHeaders );
       
  2701     
       
  2702     // now we know how much disk space we need
       
  2703     if ( aType == CMsvAttachment::EMsvFile )
       
  2704         {
       
  2705         diskSpace += attachment->Size();
       
  2706         }
       
  2707         
       
  2708     // Check that sufficient disk space available
       
  2709     if ( TMmsGenUtils::DiskSpaceBelowCriticalLevelL( 
       
  2710         &Session().FileSession(), 
       
  2711         diskSpace,
       
  2712         iMessageDrive ) )
       
  2713             {
       
  2714             // we use standard error code here
       
  2715             CleanupStack::PopAndDestroy( attachment );
       
  2716             User::Leave( KErrDiskFull );
       
  2717             }
       
  2718     
       
  2719     // attachment is initialised, pass to the attachment manager
       
  2720     MMsvAttachmentManager& manager = store->AttachmentManagerL();
       
  2721     if ( iAttaWaiter->IsActive() )
       
  2722         {
       
  2723         // can't start an active operation because already active
       
  2724         User::Leave(KErrInUse);
       
  2725         }
       
  2726     switch( aType )
       
  2727         {
       
  2728         case CMsvAttachment::EMsvLinkedFile:
       
  2729             manager.AddLinkedAttachmentL( aFilePath, attachment,
       
  2730                 iAttaWaiter->iStatus );
       
  2731             break;
       
  2732         default: // CMsvAttachment::EMsvFile
       
  2733             manager.AddAttachmentL( aFilePath, attachment,
       
  2734                 iAttaWaiter->iStatus );
       
  2735             break;
       
  2736         }
       
  2737 
       
  2738     CleanupStack::Pop( attachment ); // ownership passed to manager
       
  2739     // We cannot start waiting before we know that the function we are waiting for
       
  2740     // did not leave. If we become active, and the function leaves, we are in trouble    
       
  2741     iAttaWaiter->StartWaitingL( aStatus, store, &manager );
       
  2742     CleanupStack::Pop( store ); // ownership passed to iAttaWaiter
       
  2743     }
       
  2744     
       
  2745     
       
  2746 // ---------------------------------------------------------
       
  2747 // CMmsClientMtm::StoreAttributesL
       
  2748 // ---------------------------------------------------------
       
  2749 //
       
  2750 void CMmsClientMtm::StoreAttributesL( CMsvStore& aStore )
       
  2751     {
       
  2752     
       
  2753     if ( iAttributes->MdcaCount() == 0 )
       
  2754         {
       
  2755         if ( aStore.IsPresentL( KUidMmsAttributeStream ) )
       
  2756             {
       
  2757             aStore.RemoveL( KUidMmsAttributeStream );
       
  2758             }
       
  2759         return;
       
  2760         }
       
  2761     
       
  2762     RMsvWriteStream writeStream;
       
  2763     // pushes 'writeStream' to the stack
       
  2764     writeStream.AssignLC( aStore, KUidMmsAttributeStream );
       
  2765     
       
  2766     writeStream.WriteInt32L( iAttributes->MdcaCount() );
       
  2767     
       
  2768     TInt i;
       
  2769     for ( i = 0; i < iAttributes->MdcaCount(); i++ )
       
  2770         {
       
  2771         writeStream << (*iAttributes)[i];
       
  2772         }
       
  2773 
       
  2774     writeStream.CommitL();
       
  2775     writeStream.Close();
       
  2776     CleanupStack::PopAndDestroy( &writeStream );   // close writeStream
       
  2777     }
       
  2778     
       
  2779 // ---------------------------------------------------------
       
  2780 // CMmsClientMtm::RestoreAttributesL
       
  2781 // ---------------------------------------------------------
       
  2782 //
       
  2783 void CMmsClientMtm::RestoreAttributesL( CMsvStore& aStore )
       
  2784     {
       
  2785     iAttributes->Reset();
       
  2786     if ( !aStore.IsPresentL( KUidMmsAttributeStream ) )
       
  2787         {
       
  2788         return;
       
  2789         }
       
  2790         
       
  2791     RMsvReadStream readStream;
       
  2792     // pushes readStream to clenaup stack
       
  2793     readStream.OpenLC( aStore, KUidMmsAttributeStream );
       
  2794     
       
  2795     TInt count = 0;
       
  2796     
       
  2797     count = readStream.ReadInt32L();
       
  2798     TInt i;
       
  2799     HBufC* desBuffer;
       
  2800     
       
  2801     for ( i = 0; i < count; i++ )
       
  2802         {
       
  2803         desBuffer = HBufC::NewLC( readStream, KMaxTInt );
       
  2804         iAttributes->AppendL( *desBuffer );
       
  2805         CleanupStack::PopAndDestroy( desBuffer );
       
  2806         }
       
  2807         
       
  2808     readStream.Close();
       
  2809     CleanupStack::PopAndDestroy( &readStream );   // close readStream
       
  2810     }
       
  2811     
       
  2812 // ---------------------------------------------------------
       
  2813 // CMmsClientMtm::RecognizeCharSetL
       
  2814 // ---------------------------------------------------------
       
  2815 //
       
  2816 TUint CMmsClientMtm::RecognizeCharSetL( RFile& aFile )
       
  2817     {
       
  2818     TUint charset = 0;
       
  2819     
       
  2820     // Use CMsgTextUtils for character conversion
       
  2821     CMsgTextUtils* msgTextUtils = CMsgTextUtils::NewL( Session().FileSession() );
       
  2822     CleanupStack::PushL( msgTextUtils );
       
  2823     
       
  2824     charset = msgTextUtils->RecognizeCharSetL( Session().FileSession(), aFile );
       
  2825     if ( charset == 0 )
       
  2826         {
       
  2827         charset = KMmsUTF16; // utf16 with explicit byte order mark
       
  2828         CleanupStack::PopAndDestroy( msgTextUtils );
       
  2829         return charset; // unicode little endian or big endian
       
  2830         }
       
  2831     
       
  2832     charset = msgTextUtils->CharconvIdToMibIdL( charset );
       
  2833     CleanupStack::PopAndDestroy( msgTextUtils );
       
  2834     return charset;
       
  2835     }
       
  2836 
       
  2837 
       
  2838 
       
  2839 // ---------------------------------------------------------
       
  2840 // CMmsClientMtm::
       
  2841 // ---------------------------------------------------------
       
  2842 //
       
  2843 
       
  2844 
       
  2845 // ================= OTHER EXPORTED FUNCTIONS ==============
       
  2846 
       
  2847 //
       
  2848 // ---------------------------------------------------------
       
  2849 // gPanic implements
       
  2850 // panic function, should be used by debug version only
       
  2851 //
       
  2852 GLDEF_C void gPanic( TMmsPanic aPanic ) // error number enumerations
       
  2853     {
       
  2854     _LIT(KMmsPanic,"MMS");
       
  2855     User::Panic( KMmsPanic, aPanic );
       
  2856     }
       
  2857 
       
  2858 //  End of File