src/messaging/qmtmengine_symbian.cpp
changeset 0 876b1a06bc25
child 5 603d3f8b6302
equal deleted inserted replaced
-1:000000000000 0:876b1a06bc25
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the Qt Mobility Components.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "qmessagestore_symbian_p.h"
       
    43 #include "qmtmengine_symbian_p.h"
       
    44 #include "qmessage_symbian_p.h"
       
    45 #include "qmessagesortorder_p.h"
       
    46 #include "qmessageaccount.h"
       
    47 #include "qmessageaccount_p.h"
       
    48 #include "qmessageaccountfilter.h"
       
    49 #include "qmessageaccountfilter_p.h"
       
    50 #include "qmessageaccountsortorder_p.h"
       
    51 #include "qmessagefoldersortorder_p.h"
       
    52 #include "qmessagesortorder_p.h"
       
    53 #include "qmessagefolder.h"
       
    54 #include "qmessagefolder_p.h"
       
    55 #include "qmessagefolderfilter.h"
       
    56 #include "qmessagefolderfilter_p.h"
       
    57 #include "qmessageservice_symbian_p.h"
       
    58 #include "qmessagecontentcontainer_symbian_p.h"
       
    59 #include "qmessagecontentcontainer_p.h"
       
    60 
       
    61 #include <msvstd.h>
       
    62 #include <msvids.h> // TMsvId's
       
    63 #include <mtclreg.h>   // CClientMtmRegistry
       
    64 #include <smsclnt.h>   // CSmsClientMtm
       
    65 #include <mmsclient.h> // CMmsClientMtm
       
    66 #include <smtcmtm.h>   // CSmtpClientMtm
       
    67 #include <impcmtm.h>   // CImap4ClientMtm
       
    68 #include <popcmtm.h>   // CPop3ClientMtm
       
    69 #include <cemailaccounts.h> //CEmailAccounts
       
    70 #include <msvfind.h>   // CMsvFindOperation  
       
    71 #include <mtmdef.h>    // TMsvPartList
       
    72 #include <utf.h>       // CnvUtfConverter
       
    73 #include <mmsvattachmentmanager.h>
       
    74 #include <cmsvmimeheaders.h> // Attachemt mimeheader
       
    75 #include <eikenv.h>
       
    76 #include <smut.h>
       
    77 #include <smuthdr.h>
       
    78 #include <mtuireg.h> // CMtmUiRegistry
       
    79 #include <mtmuibas.h> // CBaseMtmUi
       
    80 #include <SendUiConsts.h>
       
    81 #include <sendui.h>    // SendUi API
       
    82 #include <CMessageData.h> //CMessageData
       
    83 #include <apgcli.h>
       
    84 #include <rsendas.h>
       
    85 #include <rsendasmessage.h>
       
    86 #include <cmsvrecipientlist.h>
       
    87 #include <imapset.h>
       
    88 #include <miutmsg.h>
       
    89 #include <charconv.h>
       
    90 #include <imcvtext.h> // KImcvMultipart declaration
       
    91 #include <smscmds.h>
       
    92 
       
    93 #include <QTextCodec>
       
    94 #include <messagingutil_p.h>
       
    95 
       
    96 
       
    97 QTM_BEGIN_NAMESPACE
       
    98 
       
    99 const TInt KWaitAfterReceivedMessage = 100000; // = 0.1 seconds
       
   100 #define KDocumentsEntryIdValue    0x1008
       
   101 
       
   102 Q_GLOBAL_STATIC(CMTMEngine,mtmEngine);
       
   103 
       
   104 CMTMEngine::CMTMEngine()
       
   105  : CActive(EPriorityStandard)
       
   106 {
       
   107     connect(QCoreApplication::instance(), SIGNAL(aboutToQuit()), this, SLOT(cleanupMTMBackend()));
       
   108     
       
   109     iFsSession.Connect();
       
   110     CActiveScheduler::Add(this);
       
   111     iTimer.CreateLocal();
       
   112 
       
   113     TRAPD(err,
       
   114         ipMsvSession = CMsvSession::OpenSyncL(*this);
       
   115         iSessionReady = ETrue;
       
   116         ipClientMtmReg = CClientMtmRegistry::NewL(*ipMsvSession);
       
   117         ipSmsMtm = static_cast<CSmsClientMtm*>(ipClientMtmReg->NewMtmL(KUidMsgTypeSMS));
       
   118         ipMmsMtm = static_cast<CMmsClientMtm*>(ipClientMtmReg->NewMtmL(KUidMsgTypeMultimedia));
       
   119         ipSmtpMtm = static_cast<CSmtpClientMtm*>(ipClientMtmReg->NewMtmL(KUidMsgTypeSMTP));
       
   120         ipImap4Mtm = static_cast<CImap4ClientMtm*>(ipClientMtmReg->NewMtmL(KUidMsgTypeIMAP4));
       
   121         ipPop3Mtm = static_cast<CPop3ClientMtm*>(ipClientMtmReg->NewMtmL(KUidMsgTypePOP3));
       
   122         );
       
   123     Q_UNUSED(err)
       
   124 
       
   125     // Create & Add SMS Account
       
   126     TRAPD(accountError,
       
   127         iSMSAccountidAsString = SymbianHelpers::addIdPrefix(QString::number(mtmServiceEntryIdL(CMTMEngine::MTMTypeSMS)),SymbianHelpers::EngineTypeMTM);
       
   128         QMessageAccount smsAcc = QMessageAccountPrivate::from(QMessageAccountId(iSMSAccountidAsString),
       
   129                                                               QString("SMS"),
       
   130                                                               mtmServiceEntryIdL(CMTMEngine::MTMTypeSMS),
       
   131                                                               0,
       
   132                                                               QMessage::Sms);
       
   133         iAccounts.insert(iSMSAccountidAsString, smsAcc);
       
   134 
       
   135 
       
   136         // Create & Add MMS Account
       
   137         iMMSAccountidAsString = SymbianHelpers::addIdPrefix(QString::number(mtmServiceEntryIdL(CMTMEngine::MTMTypeMMS)),SymbianHelpers::EngineTypeMTM);
       
   138         QMessageAccount mmsAcc = QMessageAccountPrivate::from(QMessageAccountId(iMMSAccountidAsString),
       
   139                                                               QString("MMS"),
       
   140                                                               mtmServiceEntryIdL(CMTMEngine::MTMTypeMMS),
       
   141                                                               0,
       
   142                                                               QMessage::Mms | QMessage::Email);
       
   143         iAccounts.insert(iMMSAccountidAsString, mmsAcc);
       
   144         updateEmailAccountsL();
       
   145         );
       
   146     Q_UNUSED(accountError)
       
   147     
       
   148     TRAPD(err2,
       
   149         TBuf<KMaxPath> privatePath;
       
   150         FsSession().CreatePrivatePath(EDriveC);
       
   151         FsSession().PrivatePath(privatePath);
       
   152         iPath.Append(_L("c:"));
       
   153         iPath.Append(privatePath);
       
   154         iPath.Append(_L("tempattachments\\"));                         
       
   155         CFileMan* pFileMan = CFileMan::NewL(FsSession());
       
   156         CleanupStack::PushL(pFileMan);
       
   157         pFileMan->RmDir(iPath);
       
   158         FsSession().MkDirAll(iPath);
       
   159         CleanupStack::PopAndDestroy(pFileMan);
       
   160     );
       
   161     Q_UNUSED(err2)
       
   162 }
       
   163 
       
   164 CMTMEngine::~CMTMEngine()
       
   165 {
       
   166 
       
   167 }
       
   168 
       
   169 void CMTMEngine::cleanupMTMBackend()
       
   170 {
       
   171     iCmsvEntryPoolFree.ResetAndDestroy();
       
   172     iCmsvEntryPoolInUse.ResetAndDestroy();
       
   173 
       
   174     delete ipPop3Mtm;
       
   175     delete ipImap4Mtm;
       
   176     delete ipSmtpMtm;
       
   177     delete ipMmsMtm;
       
   178     delete ipSmsMtm;
       
   179 
       
   180     delete ipClientMtmReg;
       
   181     delete ipMsvSession;
       
   182 
       
   183     TRAPD(error,
       
   184         TBuf<KMaxPath> privatePath;
       
   185         FsSession().CreatePrivatePath(EDriveC);
       
   186         FsSession().PrivatePath(privatePath);
       
   187         TBuf<KMaxPath> path;
       
   188         path.Append(_L("c:"));
       
   189         path.Append(privatePath);
       
   190         path.Append(_L("tempattachments\\"));                         
       
   191         CFileMan* pFileMan=CFileMan::NewL(FsSession());
       
   192         CleanupStack::PushL(pFileMan);
       
   193         pFileMan->RmDir(path);
       
   194         CleanupStack::PopAndDestroy(pFileMan);
       
   195         );
       
   196     Q_UNUSED(error)
       
   197 
       
   198     Cancel();
       
   199     iTimer.Close();
       
   200     iFsSession.Close();
       
   201 
       
   202 }
       
   203 
       
   204 CMTMEngine* CMTMEngine::instance()
       
   205 {
       
   206     return mtmEngine();
       
   207 }
       
   208 
       
   209 bool CMTMEngine::accountLessThan(const QMessageAccountId accountId1, const QMessageAccountId accountId2)
       
   210 {
       
   211     CMTMEngine* pMTMEngine = mtmEngine();
       
   212     return QMessageAccountSortOrderPrivate::lessThan(pMTMEngine->iCurrentAccountOrdering,
       
   213                                                     pMTMEngine->account(accountId1),
       
   214                                                     pMTMEngine->account(accountId2));
       
   215 }
       
   216 
       
   217 void CMTMEngine::orderAccounts(QMessageAccountIdList& accountIds, const QMessageAccountSortOrder &sortOrder) const
       
   218 {
       
   219     iCurrentAccountOrdering = sortOrder;
       
   220     qSort(accountIds.begin(), accountIds.end(), CMTMEngine::accountLessThan);
       
   221 }
       
   222 
       
   223 bool CMTMEngine::folderLessThan(const QMessageFolderId folderId1, const QMessageFolderId folderId2)
       
   224 {
       
   225     CMTMEngine* pMTMEngine = mtmEngine();
       
   226     return QMessageFolderSortOrderPrivate::lessThan(pMTMEngine->iCurrentFolderOrdering,
       
   227                                                    pMTMEngine->folder(folderId1),
       
   228                                                    pMTMEngine->folder(folderId2));
       
   229 }
       
   230 
       
   231 void CMTMEngine::orderFolders(QMessageFolderIdList& folderIds,  const QMessageFolderSortOrder &sortOrder) const
       
   232 {
       
   233     iCurrentFolderOrdering = sortOrder;
       
   234     qSort(folderIds.begin(), folderIds.end(), CMTMEngine::folderLessThan);
       
   235 }
       
   236 
       
   237 bool CMTMEngine::messageLessThan(const QMessage& message1, const QMessage& message2)
       
   238 {
       
   239     CMTMEngine* pMTMEngine = mtmEngine();
       
   240     return QMessageSortOrderPrivate::lessThan(pMTMEngine->iCurrentMessageOrdering, message1, message2);
       
   241 }
       
   242 
       
   243 void CMTMEngine::orderMessages(QMessageIdList& messageIds, const QMessageSortOrder &sortOrder) const
       
   244 {
       
   245     iCurrentMessageOrdering = sortOrder;
       
   246     QList<QMessage> messages;
       
   247     for (int i=0; i < messageIds.count(); i++) {
       
   248         messages.append(message(messageIds[i]));
       
   249     }
       
   250     qSort(messages.begin(), messages.end(), CMTMEngine::messageLessThan);
       
   251     messageIds.clear();
       
   252     for (int i=0; i < messages.count(); i++) {
       
   253         messageIds.append(messages[i].id());
       
   254     }
       
   255 }
       
   256 
       
   257 QMessageAccountIdList CMTMEngine::queryAccounts(const QMessageAccountFilter &filter, const QMessageAccountSortOrder &sortOrder, uint limit, uint offset) const
       
   258 {
       
   259     QMessageAccountIdList accountIds;
       
   260 
       
   261     TRAPD(err, updateEmailAccountsL());
       
   262     Q_UNUSED(err)
       
   263     
       
   264     QMessageAccountFilterPrivate* privateMessageAccountFilter = QMessageAccountFilterPrivate::implementation(filter);
       
   265     if (filter.isEmpty()) {
       
   266         if (!privateMessageAccountFilter->_notFilter) {
       
   267             // All accounts are returned for empty filter
       
   268             foreach (QMessageAccount value, iAccounts) {
       
   269                 accountIds.append(value.id());
       
   270             }
       
   271         }
       
   272     } else {
       
   273         if (privateMessageAccountFilter->_valid) {
       
   274             foreach (QMessageAccount value, iAccounts) {
       
   275                 if (privateMessageAccountFilter->filter(value)) {
       
   276                     accountIds.append(value.id());
       
   277                 }
       
   278             }
       
   279         } else {
       
   280             foreach (QMessageAccount value, iAccounts) {
       
   281                 if (privateMessageAccountFilter->filter(value)) {
       
   282                     accountIds.append(value.id());
       
   283                 }
       
   284             }
       
   285         }
       
   286     }
       
   287 
       
   288     if (!sortOrder.isEmpty()) {
       
   289         orderAccounts(accountIds, sortOrder);
       
   290     }
       
   291 
       
   292     applyOffsetAndLimitToAccountIds(accountIds, offset, limit);
       
   293     
       
   294     return accountIds;
       
   295 }
       
   296 
       
   297 void CMTMEngine::applyOffsetAndLimitToAccountIds(QMessageAccountIdList& idList, int offset, int limit) const
       
   298 {
       
   299     if (offset > 0) {
       
   300         if (offset > idList.count()) {
       
   301             idList.clear();
       
   302         } else {
       
   303             for (int i = 0; i < offset; i++) {
       
   304                 idList.removeFirst();
       
   305             }
       
   306         }
       
   307     }
       
   308     if (limit > 0) {
       
   309         for (int i = idList.count()-1; i >= limit; i--) {
       
   310             idList.removeAt(i);
       
   311         }
       
   312     }
       
   313 }
       
   314 
       
   315 int CMTMEngine::countAccounts(const QMessageAccountFilter &filter) const
       
   316 {
       
   317     return queryAccounts(filter, QMessageAccountSortOrder(), 0, 0).count();
       
   318 }
       
   319 
       
   320 QMessageAccount CMTMEngine::account(const QMessageAccountId &id) const
       
   321 {
       
   322     TRAPD(err, updateEmailAccountsL());
       
   323     Q_UNUSED(err)
       
   324     return iAccounts[id.toString()];
       
   325 }
       
   326 
       
   327 QMessageAccountId CMTMEngine::accountIdByServiceId(TMsvId serviceId) const
       
   328 {
       
   329     TRAPD(err, updateEmailAccountsL());
       
   330     Q_UNUSED(err)
       
   331 
       
   332     foreach (QMessageAccount value, iAccounts) {
       
   333         if (value.d_ptr->_service1EntryId == serviceId ||
       
   334             value.d_ptr->_service2EntryId == serviceId) {
       
   335             return value.id();
       
   336         }
       
   337     }
       
   338 
       
   339     return QMessageAccountId();
       
   340 }
       
   341 
       
   342 QMessageAccountId CMTMEngine::defaultAccount(QMessage::Type type) const
       
   343 {
       
   344     TRAPD(err, updateEmailAccountsL());
       
   345     Q_UNUSED(err)
       
   346 
       
   347     if (type == QMessage::Email) {
       
   348         // Email
       
   349         return idefaultEmailAccountId;
       
   350     } else {
       
   351         // Sms & Mms
       
   352         foreach (QMessageAccount value, iAccounts) {
       
   353             if ((value.messageTypes() & type) == (int)type) {
       
   354                 return value.id();
       
   355             }
       
   356         }
       
   357     }
       
   358 
       
   359     return QMessageAccountId();
       
   360 }
       
   361 
       
   362 QMessageAccountIdList CMTMEngine::accountsByType(QMessage::Type type) const
       
   363 {
       
   364     QMessageAccountIdList accountIds;
       
   365     
       
   366     foreach (QMessageAccount value, iAccounts) {
       
   367         if ((value.messageTypes() & type) == (int)type) {
       
   368             accountIds.append(value.id());
       
   369         }
       
   370     }
       
   371     
       
   372     return accountIds;
       
   373 }
       
   374 
       
   375 void CMTMEngine::updateEmailAccountsL() const
       
   376 {
       
   377     QStringList keys = iAccounts.keys();
       
   378     keys.removeOne(iSMSAccountidAsString);
       
   379     keys.removeOne(iMMSAccountidAsString);
       
   380     
       
   381     CEmailAccounts* pEmailAccounts = CEmailAccounts::NewLC();
       
   382 
       
   383     // Default Email account will be the first Email account in the iAccounts list
       
   384     TSmtpAccount defaultAccount;
       
   385     TInt err = pEmailAccounts->DefaultSmtpAccountL(defaultAccount);    
       
   386     if (err == KErrNone) {
       
   387         QString idAsString;
       
   388         if (defaultAccount.iRelatedService != 0) {
       
   389             idAsString = SymbianHelpers::addIdPrefix(QString::number(defaultAccount.iRelatedService),SymbianHelpers::EngineTypeMTM);
       
   390         } else {
       
   391             idAsString = SymbianHelpers::addIdPrefix(QString::number(defaultAccount.iSmtpService),SymbianHelpers::EngineTypeMTM);
       
   392         }
       
   393         if (!iAccounts.contains(idAsString)) {
       
   394             QMessageAccount account = QMessageAccountPrivate::from(QMessageAccountId(idAsString),
       
   395                                                                    QString::fromUtf16(defaultAccount.iSmtpAccountName.Ptr(), defaultAccount.iSmtpAccountName.Length()),
       
   396                                                                    defaultAccount.iRelatedService,
       
   397                                                                    defaultAccount.iSmtpService,
       
   398                                                                    QMessage::Email);
       
   399             iAccounts.insert(idAsString, account);
       
   400             idefaultEmailAccountId = account.id();
       
   401         } else {
       
   402             keys.removeOne(idAsString);
       
   403         }
       
   404     } else {
       
   405         idefaultEmailAccountId = QMessageAccountId();
       
   406     }
       
   407 
       
   408     RArray<TImapAccount> imapAccounts(10);
       
   409     pEmailAccounts->GetImapAccountsL(imapAccounts);
       
   410     CleanupClosePushL(imapAccounts);
       
   411     for (int i=0; i < imapAccounts.Count(); i++) {
       
   412         QString idAsString = SymbianHelpers::addIdPrefix(QString::number(imapAccounts[i].iImapService),SymbianHelpers::EngineTypeMTM);
       
   413         if (!iAccounts.contains(idAsString)) {
       
   414             QMessageAccount account = QMessageAccountPrivate::from(QMessageAccountId(idAsString),
       
   415                                                                    QString::fromUtf16(imapAccounts[i].iImapAccountName.Ptr(), imapAccounts[i].iImapAccountName.Length()),
       
   416                                                                    imapAccounts[i].iImapService,
       
   417                                                                    imapAccounts[i].iSmtpService,
       
   418                                                                    QMessage::Email);
       
   419             iAccounts.insert(idAsString, account);
       
   420         } else {
       
   421             keys.removeOne(idAsString);
       
   422         }
       
   423     }
       
   424     CleanupStack::PopAndDestroy(&imapAccounts);
       
   425     
       
   426     RArray<TPopAccount> popAccounts(10);
       
   427     pEmailAccounts->GetPopAccountsL(popAccounts);
       
   428     CleanupClosePushL(popAccounts);
       
   429     for (int i=0; i < popAccounts.Count(); i++) {
       
   430         QString idAsString = SymbianHelpers::addIdPrefix(QString::number(popAccounts[i].iPopService),SymbianHelpers::EngineTypeMTM);
       
   431         if (!iAccounts.contains(idAsString)) {
       
   432             QMessageAccount account = QMessageAccountPrivate::from(QMessageAccountId(SymbianHelpers::addIdPrefix(QString::number(popAccounts[i].iPopService),SymbianHelpers::EngineTypeMTM)),
       
   433                                                                    QString::fromUtf16(popAccounts[i].iPopAccountName.Ptr(), popAccounts[i].iPopAccountName.Length()),
       
   434                                                                    popAccounts[i].iPopService,
       
   435                                                                    popAccounts[i].iSmtpService,
       
   436                                                                    QMessage::Email);
       
   437             iAccounts.insert(idAsString, account);
       
   438         } else {
       
   439             keys.removeOne(idAsString);
       
   440         }
       
   441     }
       
   442     CleanupStack::PopAndDestroy(&popAccounts);
       
   443 
       
   444     RArray<TSmtpAccount> smtpAccounts(10);
       
   445     pEmailAccounts->GetSmtpAccountsL(smtpAccounts);
       
   446     CleanupClosePushL(smtpAccounts);
       
   447     for (int i=0; i < smtpAccounts.Count(); i++) {
       
   448         if (smtpAccounts[i].iRelatedService == 0) {
       
   449             QString idAsString = SymbianHelpers::addIdPrefix(QString::number(smtpAccounts[i].iSmtpService),SymbianHelpers::EngineTypeMTM);
       
   450             if (!iAccounts.contains(idAsString)) {
       
   451                 QMessageAccount account = QMessageAccountPrivate::from(QMessageAccountId(SymbianHelpers::addIdPrefix(QString::number(smtpAccounts[i].iSmtpService),SymbianHelpers::EngineTypeMTM)),
       
   452                                                                        QString::fromUtf16(smtpAccounts[i].iSmtpAccountName.Ptr(), smtpAccounts[i].iSmtpAccountName.Length()),
       
   453                                                                        smtpAccounts[i].iRelatedService,
       
   454                                                                        smtpAccounts[i].iSmtpService,
       
   455                                                                        QMessage::Email);
       
   456                 iAccounts.insert(idAsString, account);
       
   457             } else {
       
   458                 keys.removeOne(idAsString);
       
   459             }
       
   460         }
       
   461     }
       
   462     CleanupStack::PopAndDestroy(&smtpAccounts);
       
   463     
       
   464     for (int i=0; i < keys.count(); i++) {
       
   465         iAccounts.remove(keys[i]);
       
   466     }
       
   467     
       
   468     CleanupStack::PopAndDestroy(pEmailAccounts);
       
   469 }
       
   470 
       
   471 TUid CMTMEngine::mtmUidByType(MTMType aMTMType)
       
   472 {
       
   473     switch(aMTMType) {
       
   474     case CMTMEngine::MTMTypeSMS:  return KUidMsgTypeSMS;
       
   475     case CMTMEngine::MTMTypeMMS:  return KUidMsgTypeMultimedia;
       
   476     case CMTMEngine::MTMTypeSMTP: return KUidMsgTypeSMTP;
       
   477     case CMTMEngine::MTMTypeIMAP: return KUidMsgTypeIMAP4;
       
   478     case CMTMEngine::MTMTypePOP3: return KUidMsgTypePOP3;
       
   479     }
       
   480     
       
   481     return TUid();
       
   482 }
       
   483 
       
   484 CBaseMtm* CMTMEngine::mtmByUid(TUid aMTMUid)
       
   485 {
       
   486     if (aMTMUid == KUidMsgTypeSMS) {
       
   487         return ipSmsMtm;
       
   488     } else if (aMTMUid == KUidMsgTypeMultimedia) {
       
   489         return ipMmsMtm;
       
   490     } else if (aMTMUid == KUidMsgTypeSMTP) {
       
   491         return ipSmtpMtm;
       
   492     } else if (aMTMUid == KUidMsgTypeIMAP4) {
       
   493         return ipImap4Mtm;
       
   494     } else if (aMTMUid == KUidMsgTypePOP3) {
       
   495         return ipPop3Mtm;
       
   496     }
       
   497 
       
   498     return 0;
       
   499 }
       
   500 
       
   501 TMsvId CMTMEngine::mtmServiceEntryIdL(MTMType aMTMType) const
       
   502 {
       
   503     TUid mtmUID;
       
   504     switch(aMTMType) {
       
   505     case CMTMEngine::MTMTypeSMS:
       
   506         mtmUID = KUidMsgTypeSMS;
       
   507         break;
       
   508     case CMTMEngine::MTMTypeMMS:
       
   509         mtmUID = KUidMsgTypeMultimedia;
       
   510         break;
       
   511     case CMTMEngine::MTMTypeSMTP:
       
   512         mtmUID = KUidMsgTypeSMTP;
       
   513         break;
       
   514     case CMTMEngine::MTMTypeIMAP:
       
   515         mtmUID = KUidMsgTypeIMAP4;
       
   516         break;
       
   517     case CMTMEngine::MTMTypePOP3:
       
   518         mtmUID = KUidMsgTypePOP3;
       
   519         break;
       
   520     }
       
   521     
       
   522     CMsvEntry* pCurrentEntry = ipMsvSession->GetEntryL(KMsvRootIndexEntryId);
       
   523     CleanupStack::PushL(pCurrentEntry);
       
   524     
       
   525     // Sorting or grouping is not needed
       
   526     pCurrentEntry->SetSortTypeL(TMsvSelectionOrdering(KMsvNoGrouping,EMsvSortByNone, ETrue));
       
   527     
       
   528     // Loop through child entries until MTM specific
       
   529     // root entry has been found 
       
   530     TMsvId mtmRootEntryId = KMsvRootIndexEntryId;
       
   531     TInt count = pCurrentEntry->Count();
       
   532     for(TInt i = 0; i<count; i++) {
       
   533         const TMsvEntry& child = (*pCurrentEntry)[i];
       
   534         if (child.iMtm == mtmUID) {
       
   535             mtmRootEntryId = child.Id();
       
   536             break;
       
   537         }
       
   538     }
       
   539     CleanupStack::PopAndDestroy(pCurrentEntry);
       
   540     
       
   541     if (mtmRootEntryId == KMsvRootIndexEntryId) {
       
   542         // MTM specific root entry was not found
       
   543         return 0;
       
   544     }
       
   545     
       
   546     TMsvEntry indexEntry;
       
   547     TMsvId mtmServiceEntryId;
       
   548     TInt error = ipMsvSession->GetEntry(mtmRootEntryId, mtmServiceEntryId, indexEntry);
       
   549     if (error != KErrNone) {
       
   550         // MTM specific service entry Id was not found
       
   551         return 0;
       
   552     }
       
   553     
       
   554     return mtmServiceEntryId;
       
   555 }
       
   556 
       
   557 bool CMTMEngine::switchToMTMRootEntry(MTMType aMTMType)
       
   558 {
       
   559     TRAPD(err,
       
   560         CBaseMtm* pMTM = mtmByType(aMTMType);
       
   561         TMsvId mtmEntryId = mtmServiceEntryIdL(aMTMType);
       
   562         
       
   563         CMsvEntry* pMTMServiceEntry = ipMsvSession->GetEntryL(mtmEntryId);
       
   564         CleanupStack::PushL(pMTMServiceEntry);
       
   565         // Set service entry as current entry of ClientMTM class
       
   566         pMTM->SetCurrentEntryL(pMTMServiceEntry); // Takes ownership of pMTMServiceEntry
       
   567         CleanupStack::Pop(pMTMServiceEntry);
       
   568     );
       
   569     if (err != KErrNone)
       
   570         return false;
       
   571     else
       
   572         return true;
       
   573 }
       
   574 
       
   575 CBaseMtm* CMTMEngine::mtmByType(MTMType aMTMType)
       
   576 {
       
   577     switch(aMTMType) {
       
   578     case CMTMEngine::MTMTypeSMS: return ipSmsMtm;
       
   579     case CMTMEngine::MTMTypeMMS: return ipMmsMtm;
       
   580     case CMTMEngine::MTMTypeSMTP: return ipSmtpMtm;
       
   581     case CMTMEngine::MTMTypeIMAP: return ipImap4Mtm;
       
   582     case CMTMEngine::MTMTypePOP3: return ipPop3Mtm;
       
   583     }
       
   584     
       
   585     return 0;
       
   586 }
       
   587 
       
   588 TMsvId CMTMEngine::standardFolderId(QMessage::StandardFolder standardFolder)
       
   589 {
       
   590     switch(standardFolder) {
       
   591     case QMessage::InboxFolder:  return KMsvGlobalInBoxIndexEntryIdValue;
       
   592     case QMessage::OutboxFolder: return KMsvGlobalOutBoxIndexEntryIdValue;
       
   593     case QMessage::DraftsFolder: return KMsvDraftEntryIdValue;
       
   594     case QMessage::SentFolder:   return KMsvSentEntryIdValue;
       
   595     case QMessage::TrashFolder:  return KMsvDeletedEntryFolderEntryIdValue;
       
   596     }
       
   597     
       
   598     return TMsvId();
       
   599 }
       
   600 
       
   601 bool CMTMEngine::addMessage(QMessage* message)
       
   602 {
       
   603     bool retVal = false;
       
   604     
       
   605     if (message->type() == QMessage::NoType) {
       
   606         if (message->parentAccountId().isValid()){    
       
   607             QMessageAccount account = QMessageAccount(message->parentAccountId());
       
   608             QMessage::TypeFlags types = account.messageTypes();
       
   609             if (types & QMessage::Sms) {
       
   610                 message->setType(QMessage::Sms);
       
   611             } else if (types & QMessage::Mms) {
       
   612                 message->setType(QMessage::Mms);
       
   613             } else if (types & QMessage::Email) {
       
   614                 message->setType(QMessage::Email);
       
   615             }
       
   616         } else {
       
   617             return false;
       
   618         }
       
   619     }
       
   620 
       
   621     if (!message->parentAccountId().isValid() && message->type() != QMessage::NoType) {
       
   622         message->setParentAccountId(QMessageAccount::defaultAccount(message->type()));
       
   623     }
       
   624     
       
   625     if (message->type() == QMessage::Sms){
       
   626         retVal = storeSMS(*message);
       
   627     }
       
   628     else if (message->type() == QMessage::Mms){
       
   629         retVal = storeMMS(*message);
       
   630     }
       
   631     else if (message->type() == QMessage::Email){
       
   632         retVal = storeEmail(*message);
       
   633     }
       
   634     
       
   635     return retVal;
       
   636 }
       
   637 
       
   638 bool CMTMEngine::updateMessage(QMessage* m)
       
   639 {
       
   640     bool retVal = true;
       
   641     
       
   642     if (m->parentAccountId().isValid()){    
       
   643         QMessageAccount account = QMessageAccount(m->parentAccountId());
       
   644         QMessage::TypeFlags types = account.messageTypes();
       
   645         if (types & QMessage::Sms){
       
   646             m->setType(QMessage::Sms);
       
   647         } else if (types & QMessage::Mms){
       
   648             m->setType(QMessage::Mms);
       
   649         } else if (types & QMessage::Email){
       
   650             m->setType(QMessage::Email);
       
   651         }
       
   652     } 
       
   653     
       
   654     if (m->type() == QMessage::Sms){
       
   655         TRAPD(err, updateSMSL(*m));
       
   656         if (err != KErrNone)
       
   657             retVal = false;
       
   658     } else if (m->type() == QMessage::Mms){
       
   659         TRAPD(err, updateMMSL(*m));
       
   660         if (err != KErrNone)
       
   661             retVal = false;
       
   662     }  else if (m->type() == QMessage::Email){
       
   663         TRAPD(err, updateEmailL(*m));
       
   664         if (err != KErrNone)
       
   665             retVal = false;
       
   666     }
       
   667 
       
   668     return retVal;
       
   669 }
       
   670 
       
   671 // Copy message to another folder.
       
   672 void CMTMEngine::copyMessageL(TMsvId aMessageId, TMsvId aFolder)
       
   673 {
       
   674     ipSmsMtm->SwitchCurrentEntryL(aMessageId);
       
   675     TMsvSelectionOrdering selection;
       
   676     selection.SetShowInvisibleEntries(ETrue);
       
   677     CMsvEntry* pParentEntry = CMsvEntry::NewL(ipSmsMtm->Session(),
       
   678                                              ipSmsMtm->Entry().Entry().Parent(),
       
   679                                              selection);
       
   680     CleanupStack::PushL(pParentEntry);
       
   681     // iSmsMtm points to the parent
       
   682     pParentEntry->CopyL(aMessageId, aFolder);
       
   683     CleanupStack::PopAndDestroy(); // parentEntry
       
   684 }
       
   685 
       
   686 bool CMTMEngine::removeMessage(const QMessageId &id, QMessageManager::RemovalOption option)
       
   687 {
       
   688     if (!iSessionReady)
       
   689         return false;
       
   690     
       
   691     bool retVal = false;
       
   692     TRAPD(err, retVal = removeMessageL(id, option));
       
   693     if (err != KErrNone)
       
   694         retVal = false;
       
   695     
       
   696     return retVal;
       
   697 }
       
   698 
       
   699 bool CMTMEngine::showMessage(const QMessageId &id)
       
   700 {
       
   701     if (!iSessionReady)
       
   702         return false;
       
   703     
       
   704     TRAPD(err, showMessageL(id));
       
   705     if (err != KErrNone)
       
   706         return false;
       
   707     else
       
   708         return true;
       
   709 }
       
   710 
       
   711 void CMTMEngine::showMessageL(const QMessageId &id)
       
   712 {
       
   713     long int messageId = SymbianHelpers::stripIdPrefix(id.toString()).toLong();
       
   714 
       
   715     CMsvEntry* pEntry = ipMsvSession->GetEntryL(messageId);
       
   716     CleanupStack::PushL(pEntry);
       
   717 
       
   718     CBaseMtm* pMtm = ipClientMtmReg->NewMtmL(pEntry->Entry().iMtm);
       
   719     CleanupStack::PushL(pMtm);
       
   720     
       
   721     CMtmUiRegistry* pMtmUiRegistry = CMtmUiRegistry::NewL(*ipMsvSession);
       
   722     CleanupStack::PushL(pMtmUiRegistry); 
       
   723 
       
   724     CBaseMtmUi* pMtmUi = pMtmUiRegistry->NewMtmUiL(*pMtm); 
       
   725     CleanupStack::PushL(pMtmUi);
       
   726     
       
   727     pMtmUi->BaseMtm().SwitchCurrentEntryL(messageId);
       
   728 
       
   729     QMTMWait mtmWait;
       
   730     
       
   731     CMsvOperation* pMsvOperation = pMtmUi->OpenL(mtmWait.iStatus);
       
   732     
       
   733     mtmWait.start();
       
   734 
       
   735     delete pMsvOperation;
       
   736     
       
   737     CleanupStack::PopAndDestroy(pMtmUi);
       
   738     CleanupStack::PopAndDestroy(pMtmUiRegistry);
       
   739     CleanupStack::PopAndDestroy(pMtm);
       
   740     CleanupStack::PopAndDestroy(pEntry);
       
   741 }
       
   742 
       
   743 bool CMTMEngine::composeMessage(const QMessage &message)
       
   744 {
       
   745     bool retVal = true;
       
   746     
       
   747     if (message.parentAccountId().isValid()){    
       
   748         QMessageAccount account = QMessageAccount(message.parentAccountId());
       
   749         QMessage::TypeFlags types = account.messageTypes();
       
   750         if (types & QMessage::Sms){
       
   751             TRAPD(err, retVal = composeSMSL(message));
       
   752             if (err != KErrNone)
       
   753                 retVal = false;
       
   754         } else if (types & QMessage::Mms){
       
   755             TRAPD(err, retVal = composeMMSL(message));
       
   756             if (err != KErrNone)
       
   757                 retVal = false;
       
   758         } else if (types & QMessage::Email){
       
   759             TRAPD(err, retVal = composeEmailL(message));
       
   760             if (err != KErrNone)
       
   761                 retVal = false;
       
   762         }
       
   763     } else {
       
   764         if (message.type() == QMessage::Sms){
       
   765             TRAPD(err, retVal = composeSMSL(message));
       
   766             if (err != KErrNone)
       
   767                 retVal = false;
       
   768         }
       
   769         else if (message.type() == QMessage::Mms){
       
   770             TRAPD(err, retVal = composeMMSL(message));
       
   771             if (err != KErrNone)
       
   772                 retVal = false;
       
   773         }
       
   774         else if (message.type() == QMessage::Email){
       
   775             TRAPD(err, retVal = composeEmailL(message));
       
   776             if (err != KErrNone)
       
   777                 retVal = false;
       
   778         }
       
   779     }
       
   780     
       
   781     return retVal;
       
   782 }
       
   783 
       
   784 bool CMTMEngine::composeSMSL(const QMessage &message)
       
   785 {
       
   786     CSendUi *sendUi = CSendUi::NewL();
       
   787     CleanupStack::PushL(sendUi);
       
   788     CMessageData* messageData = CMessageData::NewLC();    
       
   789     // Add receivers
       
   790     QList<QMessageAddress> list(message.to());
       
   791     TPtrC16 receiver(KNullDesC);
       
   792     QString qreceiver;
       
   793     for (int i = 0; i < list.size(); ++i) {
       
   794         qreceiver = list.at(i).addressee();
       
   795         receiver.Set(reinterpret_cast<const TUint16*>(qreceiver.utf16()));
       
   796         messageData->AppendToAddressL(receiver, KNullDesC);
       
   797     }
       
   798     // Set Body text
       
   799     QString body = message.textContent();
       
   800     TPtrC16 msg(reinterpret_cast<const TUint16*>(body.utf16()));
       
   801     HBufC* bd = msg.AllocLC();
       
   802     TPtr ptr(bd->Des());
       
   803 
       
   804     ipParaFormatLayer = CParaFormatLayer::NewL();
       
   805     ipCharFormatLayer = CCharFormatLayer::NewL();   
       
   806     ipRichText = CRichText::NewL(ipParaFormatLayer,ipCharFormatLayer);
       
   807     TInt pos = 0; // Insertion position of text will be zero
       
   808     ipRichText->Reset();
       
   809     ipRichText->InsertL(pos, ptr);
       
   810     messageData->SetBodyTextL(ipRichText);
       
   811     
       
   812     sendUi->CreateAndSendMessageL(KSenduiMtmSmsUid, messageData, KNullUid, ETrue);
       
   813     CleanupStack::PopAndDestroy(3); //bd, messageData and sendUi
       
   814     return true;
       
   815 }
       
   816 
       
   817 bool CMTMEngine::composeMMSL(const QMessage &message)
       
   818 {
       
   819     CSendUi *sendUi = CSendUi::NewL();
       
   820     CleanupStack::PushL(sendUi);
       
   821     TUid bioTypeUid = KNullUid; 
       
   822     CMessageData* messageData = CMessageData::NewLC();
       
   823     
       
   824     // Add receivers
       
   825     QList<QMessageAddress> list(message.to());
       
   826     TPtrC16 receiver(KNullDesC);
       
   827     QString qreceiver;
       
   828     for (int i = 0; i < list.size(); ++i) {
       
   829         qreceiver = list.at(i).addressee();
       
   830         receiver.Set(reinterpret_cast<const TUint16*>(qreceiver.utf16()));
       
   831         messageData->AppendToAddressL(receiver, KNullDesC);
       
   832     }
       
   833     
       
   834     // Set Subject
       
   835     QString subject = message.subject();
       
   836     TPtrC16 sbj(reinterpret_cast<const TUint16*>(subject.utf16()));
       
   837     messageData->SetSubjectL(&sbj); 
       
   838     
       
   839     QByteArray filePath;
       
   840     QMessageContentContainerIdList contentIds = message.contentIds();
       
   841     foreach (QMessageContentContainerId id, contentIds){
       
   842         QMessageContentContainer container = message.find(id);
       
   843         QByteArray filePath = QMessageContentContainerPrivate::attachmentFilename(container);
       
   844         QString fileName = QString(filePath);
       
   845         QString body = container.textContent();
       
   846         if (!fileName.isEmpty()){ // content is attachment
       
   847             filePath.replace(QByteArray("/"), QByteArray("\\"));
       
   848             QString temp_path = QString(filePath);
       
   849             TPtrC16 attachmentPath(KNullDesC);
       
   850             attachmentPath.Set(reinterpret_cast<const TUint16*>(temp_path.utf16()));
       
   851             messageData->AppendAttachmentL(attachmentPath);
       
   852         }
       
   853         else if (!body.isEmpty()) { // content is Body text
       
   854             TPtrC16 msg(reinterpret_cast<const TUint16*>(body.utf16()));
       
   855             HBufC* bd = msg.AllocLC();
       
   856             TPtr ptr(bd->Des());
       
   857             ipParaFormatLayer = CParaFormatLayer::NewL();
       
   858             ipCharFormatLayer = CCharFormatLayer::NewL();   
       
   859             ipRichText = CRichText::NewL(ipParaFormatLayer, ipCharFormatLayer);
       
   860             TInt pos = 0; // Insertion position of text will be zero
       
   861             ipRichText->Reset();
       
   862             ipRichText->InsertL(pos, ptr);
       
   863             messageData->SetBodyTextL(ipRichText);
       
   864             CleanupStack::PopAndDestroy(bd);
       
   865         }
       
   866     }
       
   867     QString messageBody = message.textContent();
       
   868     if (!messageBody.isEmpty()) { // no contents, only body text
       
   869         TPtrC16 msg(reinterpret_cast<const TUint16*>(messageBody.utf16()));
       
   870         HBufC* bd = msg.AllocLC();
       
   871         TPtr ptr(bd->Des());
       
   872         ipParaFormatLayer = CParaFormatLayer::NewL();
       
   873         ipCharFormatLayer = CCharFormatLayer::NewL();   
       
   874         ipRichText = CRichText::NewL(ipParaFormatLayer, ipCharFormatLayer);
       
   875         TInt pos = 0; // Insertion position of text will be zero
       
   876         ipRichText->Reset();
       
   877         ipRichText->InsertL(pos, ptr);
       
   878         messageData->SetBodyTextL(ipRichText);
       
   879         CleanupStack::PopAndDestroy(bd);
       
   880     }
       
   881       
       
   882     sendUi->CreateAndSendMessageL(KSenduiMtmMmsUid, messageData, KNullUid, ETrue);
       
   883     CleanupStack::PopAndDestroy(2); //messageData and sendUi
       
   884     return true;
       
   885 }
       
   886 
       
   887 bool CMTMEngine::composeEmailL(const QMessage &message)
       
   888 {
       
   889     CSendUi *sendUi = CSendUi::NewL();
       
   890     CleanupStack::PushL(sendUi);
       
   891     CMessageData* messageData = CMessageData::NewLC();
       
   892     
       
   893     // Add receivers
       
   894     QList<QMessageAddress> list(message.to());
       
   895     TPtrC16 receiver(KNullDesC);
       
   896     QString qreceiver;
       
   897     for (int i = 0; i < list.size(); ++i) {
       
   898         qreceiver = list.at(i).addressee();
       
   899         receiver.Set(reinterpret_cast<const TUint16*>(qreceiver.utf16()));
       
   900         messageData->AppendToAddressL(receiver, KNullDesC);
       
   901     }
       
   902     //cc
       
   903     QList<QMessageAddress> ccList(message.cc());
       
   904     TPtrC16 ccReceiver(KNullDesC);
       
   905     QString ccQreceiver;
       
   906     for (int i = 0; i < ccList.size(); ++i) {
       
   907         ccQreceiver = ccList.at(i).addressee();
       
   908         ccReceiver.Set(reinterpret_cast<const TUint16*>(ccQreceiver.utf16()));
       
   909         messageData->AppendCcAddressL(ccReceiver, KNullDesC);
       
   910     }
       
   911     //bcc
       
   912     QList<QMessageAddress> bccList(message.bcc());
       
   913     TPtrC16 bccReceiver(KNullDesC);
       
   914     QString bccQreceiver;
       
   915     for (int i = 0; i < bccList.size(); ++i) {
       
   916         bccQreceiver = bccList.at(i).addressee();
       
   917         bccReceiver.Set(reinterpret_cast<const TUint16*>(bccQreceiver.utf16()));
       
   918         messageData->AppendBccAddressL(bccReceiver, KNullDesC);
       
   919     }
       
   920     
       
   921     // Set Subject
       
   922     QString subject = message.subject();
       
   923     TPtrC16 sbj(reinterpret_cast<const TUint16*>(subject.utf16()));
       
   924     messageData->SetSubjectL(&sbj); 
       
   925     
       
   926     QByteArray filePath;
       
   927     QMessageContentContainerIdList contentIds = message.contentIds();
       
   928     foreach (QMessageContentContainerId id, contentIds){
       
   929         QMessageContentContainer container = message.find(id);
       
   930         QByteArray filePath = QMessageContentContainerPrivate::attachmentFilename(container);
       
   931         QString body = container.textContent();
       
   932         QString fileName = QString(filePath);
       
   933         if (!fileName.isEmpty()){ // content is attachment
       
   934             filePath.replace(QByteArray("/"), QByteArray("\\"));
       
   935             QString temp_path = QString(filePath);
       
   936             TPtrC16 attachmentPath(KNullDesC);
       
   937             attachmentPath.Set(reinterpret_cast<const TUint16*>(temp_path.utf16()));
       
   938             messageData->AppendAttachmentL(attachmentPath);
       
   939         }
       
   940         else if (!body.isEmpty()) { // content is Body text
       
   941             TPtrC16 msg(reinterpret_cast<const TUint16*>(body.utf16()));
       
   942             HBufC* bd = msg.AllocLC();
       
   943             TPtr ptr(bd->Des());
       
   944             ipParaFormatLayer = CParaFormatLayer::NewL();
       
   945             ipCharFormatLayer = CCharFormatLayer::NewL();   
       
   946             ipRichText = CRichText::NewL(ipParaFormatLayer, ipCharFormatLayer);
       
   947             TInt pos = 0; // Insertion position of text will be zero
       
   948             ipRichText->Reset();
       
   949             ipRichText->InsertL(pos, ptr);
       
   950             messageData->SetBodyTextL(ipRichText);
       
   951             CleanupStack::PopAndDestroy(bd);
       
   952         }
       
   953     }
       
   954     QString messageBody = message.textContent();
       
   955     if (!messageBody.isEmpty()) { // no contents, only body text
       
   956         TPtrC16 msg(reinterpret_cast<const TUint16*>(messageBody.utf16()));
       
   957         HBufC* bd = msg.AllocLC();
       
   958         TPtr ptr(bd->Des());
       
   959         ipParaFormatLayer = CParaFormatLayer::NewL();
       
   960         ipCharFormatLayer = CCharFormatLayer::NewL();   
       
   961         ipRichText = CRichText::NewL(ipParaFormatLayer, ipCharFormatLayer);
       
   962         TInt pos = 0; // Insertion position of text will be zero
       
   963         ipRichText->Reset();
       
   964         ipRichText->InsertL(pos, ptr);
       
   965         messageData->SetBodyTextL(ipRichText);
       
   966         CleanupStack::PopAndDestroy(bd);
       
   967     }
       
   968     
       
   969     sendUi->CreateAndSendMessageL(KSenduiMtmSmtpUid, messageData, KNullUid, ETrue);
       
   970     CleanupStack::PopAndDestroy(2); //messageData and sendUi
       
   971     return true;
       
   972 }
       
   973 
       
   974 bool CMTMEngine::retrieve(QMessageServicePrivate& privateService, const QMessageId &messageId, const QMessageContentContainerId& id)
       
   975 {
       
   976     TRAPD(err, retrieveL(privateService, messageId, id));
       
   977         if (err != KErrNone)
       
   978             return false;
       
   979         else
       
   980             return true;
       
   981 }
       
   982 
       
   983 void CMTMEngine::retrieveL(QMessageServicePrivate& privateService, const QMessageId &messageId, const QMessageContentContainerId& id)
       
   984 {
       
   985     Q_UNUSED(id); // all attachments are retrieved (cannot retrieve only one)
       
   986     
       
   987     long int msgId = SymbianHelpers::stripIdPrefix(messageId.toString()).toLong();
       
   988     
       
   989     CMsvEntry* pEntry = ipMsvSession->GetEntryL(msgId);
       
   990     CleanupStack::PushL(pEntry);
       
   991     
       
   992     CAsynchronousMTMOperation* pMTMOperation = NULL;
       
   993     if (pEntry->Entry().iMtm == KUidMsgTypeIMAP4){    
       
   994         pMTMOperation = createAsynchronousMTMOperation(privateService,
       
   995                                                        ipImap4Mtm,
       
   996                                                        pEntry->OwningService());
       
   997     } else if (pEntry->Entry().iMtm == KUidMsgTypePOP3){
       
   998         pMTMOperation = createAsynchronousMTMOperation(privateService,
       
   999                                                        ipPop3Mtm,
       
  1000                                                        pEntry->OwningService());
       
  1001     }
       
  1002 
       
  1003     if (pMTMOperation) {
       
  1004         if (!pMTMOperation->retrieveMessageAttachments(msgId)) {
       
  1005             User::Leave(KErrAccessDenied);
       
  1006         }
       
  1007     } else {
       
  1008         User::Leave(KErrArgument);
       
  1009     }
       
  1010     
       
  1011     CleanupStack::PopAndDestroy(pEntry);
       
  1012 }
       
  1013 
       
  1014 bool CMTMEngine::retrieveBody(QMessageServicePrivate& privateService, const QMessageId& id)
       
  1015 {
       
  1016     TRAPD(err, retrieveBodyL(privateService, id));
       
  1017         if (err != KErrNone)
       
  1018             return false;
       
  1019         else
       
  1020             return true;
       
  1021 }
       
  1022 
       
  1023 void CMTMEngine::retrieveBodyL(QMessageServicePrivate& privateService, const QMessageId& id)
       
  1024 {
       
  1025     long int msgId = SymbianHelpers::stripIdPrefix(id.toString()).toLong();
       
  1026     
       
  1027     CMsvEntry* pEntry = ipMsvSession->GetEntryL(msgId);
       
  1028     CleanupStack::PushL(pEntry);
       
  1029     
       
  1030     CAsynchronousMTMOperation* pMTMOperation = NULL;
       
  1031     if (pEntry->Entry().iMtm == KUidMsgTypeIMAP4){    
       
  1032         pMTMOperation = createAsynchronousMTMOperation(privateService,
       
  1033                                                        ipImap4Mtm,
       
  1034                                                        pEntry->OwningService());
       
  1035     } else if (pEntry->Entry().iMtm == KUidMsgTypePOP3){
       
  1036         pMTMOperation = createAsynchronousMTMOperation(privateService,
       
  1037                                                        ipPop3Mtm,
       
  1038                                                        pEntry->OwningService());
       
  1039     }
       
  1040 
       
  1041     if (pMTMOperation) {
       
  1042         if (!pMTMOperation->retrieveMessageBody(msgId)) {
       
  1043             User::Leave(KErrAccessDenied);
       
  1044         }
       
  1045     } else {
       
  1046         User::Leave(KErrArgument);
       
  1047     }
       
  1048     
       
  1049     CleanupStack::PopAndDestroy(pEntry);
       
  1050 }
       
  1051 
       
  1052 bool CMTMEngine::retrieveHeader(QMessageServicePrivate& privateService, const QMessageId& id)
       
  1053 {
       
  1054     TRAPD(err, retrieveHeaderL(privateService, id));
       
  1055         if (err != KErrNone)
       
  1056             return false;
       
  1057         else
       
  1058             return true;
       
  1059 }
       
  1060 
       
  1061 void CMTMEngine::retrieveHeaderL(QMessageServicePrivate& privateService, const QMessageId& id)
       
  1062 {
       
  1063     long int msgId = SymbianHelpers::stripIdPrefix(id.toString()).toLong();
       
  1064     
       
  1065     CMsvEntry* pEntry = ipMsvSession->GetEntryL(msgId);
       
  1066     CleanupStack::PushL(pEntry);
       
  1067     
       
  1068     CAsynchronousMTMOperation* pMTMOperation = NULL;
       
  1069     if (pEntry->Entry().iMtm == KUidMsgTypeIMAP4){    
       
  1070         pMTMOperation = createAsynchronousMTMOperation(privateService,
       
  1071                                                        ipImap4Mtm,
       
  1072                                                        pEntry->OwningService());
       
  1073     } else if (pEntry->Entry().iMtm == KUidMsgTypePOP3){
       
  1074         pMTMOperation = createAsynchronousMTMOperation(privateService,
       
  1075                                                        ipPop3Mtm,
       
  1076                                                        pEntry->OwningService());
       
  1077     }
       
  1078     
       
  1079     if (pMTMOperation) {
       
  1080         if (!pMTMOperation->retrieveMessageHeader(msgId)) {
       
  1081             User::Leave(KErrAccessDenied);
       
  1082         }
       
  1083     } else {
       
  1084         User::Leave(KErrArgument);
       
  1085     }
       
  1086     
       
  1087     CleanupStack::PopAndDestroy(pEntry);
       
  1088 }
       
  1089 
       
  1090 bool CMTMEngine::exportUpdates(QMessageServicePrivate& privateService, const QMessageAccountId &id)
       
  1091 {
       
  1092     TRAPD(err, exportUpdatesL(privateService, id));
       
  1093     if (err != KErrNone) {
       
  1094         return false;
       
  1095     } else {
       
  1096         return true;
       
  1097     }
       
  1098 }
       
  1099 
       
  1100 void CMTMEngine::exportUpdatesL(QMessageServicePrivate& privateService, const QMessageAccountId &id)
       
  1101 {
       
  1102     CAsynchronousMTMOperation* pMTMOperation = NULL;
       
  1103     QMessageAccount account = this->account(id);
       
  1104     CMsvEntry* pEntry = retrieveCMsvEntryAndPushToCleanupStack(account.d_ptr->_service1EntryId);
       
  1105     if (!pEntry) {
       
  1106         User::Leave(KErrNotFound);
       
  1107     }
       
  1108     if (pEntry->Entry().iMtm == KUidMsgTypeIMAP4) {
       
  1109         pMTMOperation = createAsynchronousMTMOperation(privateService,
       
  1110                                                        ipImap4Mtm,
       
  1111                                                        account.d_ptr->_service1EntryId);
       
  1112         pMTMOperation->doFullSync();
       
  1113     }
       
  1114     releaseCMsvEntryAndPopFromCleanupStack(pEntry);
       
  1115     
       
  1116     if (!pMTMOperation) {
       
  1117         User::Leave(KErrArgument);
       
  1118     }
       
  1119 }
       
  1120 
       
  1121 bool CMTMEngine::removeMessageL(const QMessageId &id, QMessageManager::RemovalOption /*option*/)
       
  1122 {
       
  1123     long int messageId = SymbianHelpers::stripIdPrefix(id.toString()).toLong();
       
  1124     CMsvEntry* pEntry = ipMsvSession->GetEntryL(messageId);
       
  1125     CleanupStack::PushL(pEntry);
       
  1126     
       
  1127     if (pEntry->Entry().iMtm == KUidMsgTypeSMS) {
       
  1128         if (!ipSmsMtm)
       
  1129             return false;
       
  1130         ipSmsMtm->SwitchCurrentEntryL(messageId);
       
  1131         TMsvId parent = ipSmsMtm->Entry().Entry().Parent();
       
  1132         ipSmsMtm->SwitchCurrentEntryL(parent);
       
  1133         ipSmsMtm->Entry().DeleteL(messageId);
       
  1134     } else if (pEntry->Entry().iMtm == KUidMsgTypeMultimedia) {
       
  1135         if (!ipMmsMtm)
       
  1136             return false;
       
  1137         ipMmsMtm->SwitchCurrentEntryL(messageId);
       
  1138         TMsvId parent = ipMmsMtm->Entry().Entry().Parent();
       
  1139         ipMmsMtm->SwitchCurrentEntryL(parent);
       
  1140         ipMmsMtm->Entry().DeleteL(messageId);
       
  1141     }  else if (pEntry->Entry().iMtm == KUidMsgTypeSMTP) {
       
  1142         if (!ipSmtpMtm)
       
  1143             return false;
       
  1144         ipSmtpMtm->SwitchCurrentEntryL(messageId);
       
  1145         TMsvId parent = ipSmtpMtm->Entry().Entry().Parent();
       
  1146         ipSmtpMtm->SwitchCurrentEntryL(parent);
       
  1147         ipSmtpMtm->Entry().DeleteL(messageId);
       
  1148     } else if (pEntry->Entry().iMtm == KUidMsgTypeIMAP4) {
       
  1149         if (!ipImap4Mtm)
       
  1150             return false;
       
  1151         ipImap4Mtm->SwitchCurrentEntryL(messageId);
       
  1152         TMsvId parent = ipImap4Mtm->Entry().Entry().Parent();
       
  1153         ipImap4Mtm->SwitchCurrentEntryL(parent);
       
  1154         QMTMWait mtmWait;
       
  1155         CMsvOperation* pMsvOperation = ipImap4Mtm->Entry().DeleteL(messageId, mtmWait.iStatus);
       
  1156         mtmWait.start();
       
  1157         delete pMsvOperation;
       
  1158     } else if (pEntry->Entry().iMtm == KUidMsgTypePOP3) {
       
  1159         if (!ipPop3Mtm)
       
  1160             return false;
       
  1161         ipPop3Mtm->SwitchCurrentEntryL(messageId);
       
  1162         TMsvId parent = ipPop3Mtm->Entry().Entry().Parent();
       
  1163         ipPop3Mtm->SwitchCurrentEntryL(parent);
       
  1164         QMTMWait mtmWait;
       
  1165         CMsvOperation* pMsvOperation = ipPop3Mtm->Entry().DeleteL(messageId, mtmWait.iStatus);
       
  1166         mtmWait.start();
       
  1167         delete pMsvOperation;
       
  1168     } 
       
  1169     
       
  1170     CleanupStack::PopAndDestroy(pEntry);
       
  1171 
       
  1172     return true;
       
  1173 }
       
  1174 
       
  1175 bool CMTMEngine::removeMessages(const QMessageFilter& /*filter*/, QMessageManager::RemovalOption /*option*/)
       
  1176 {
       
  1177     return false;
       
  1178 }
       
  1179 
       
  1180 void CMTMEngine::handleNestedFiltersFromMessageFilter(QMessageFilter &filter) const
       
  1181 {
       
  1182     QMessageFilterPrivate* pMFFilter = QMessageFilterPrivate::implementation(filter);
       
  1183     if (pMFFilter->_filterList.count() > 0) {
       
  1184         int filterListCount = pMFFilter->_filterList.count();
       
  1185         for (int i=0; i < filterListCount; i++) {
       
  1186             for (int j=0; j < pMFFilter->_filterList[i].count(); j++) {
       
  1187                 QMessageFilterPrivate* pMFFilter2 = QMessageFilterPrivate::implementation(pMFFilter->_filterList[i][j]);
       
  1188                 if (pMFFilter2->_field == QMessageFilterPrivate::ParentAccountIdFilter) {
       
  1189                     QMessageAccountIdList accountIds = queryAccounts(*pMFFilter2->_accountFilter, QMessageAccountSortOrder(), 0, 0);
       
  1190                     QMessageDataComparator::InclusionComparator cmp(static_cast<QMessageDataComparator::InclusionComparator>(pMFFilter2->_comparatorValue));
       
  1191                     if (accountIds.count() > 0) {
       
  1192                         pMFFilter->_filterList[i].removeAt(j);
       
  1193                         if (cmp == QMessageDataComparator::Includes) {
       
  1194                             for (int x = 0; x < accountIds.count(); x++) {
       
  1195                                 if (x == 0) {
       
  1196                                     if (x+1 < accountIds.count()) {
       
  1197                                         pMFFilter->_filterList.append(pMFFilter->_filterList[i]);
       
  1198                                     }
       
  1199                                     pMFFilter->_filterList[i].append(QMessageFilter::byParentAccountId(accountIds[x],QMessageDataComparator::Equal));
       
  1200                                     qSort(pMFFilter->_filterList[i].begin(), pMFFilter->_filterList[i].end(), QMessageFilterPrivate::lessThan);
       
  1201                                 } else {
       
  1202                                     if (x+1 < accountIds.count()) {
       
  1203                                         pMFFilter->_filterList.append(pMFFilter->_filterList[pMFFilter->_filterList.count()-1]);
       
  1204                                         pMFFilter->_filterList[pMFFilter->_filterList.count()-2].append(QMessageFilter::byParentAccountId(accountIds[x],QMessageDataComparator::Equal));
       
  1205                                         qSort(pMFFilter->_filterList[pMFFilter->_filterList.count()-2].begin(), pMFFilter->_filterList[pMFFilter->_filterList.count()-2].end(), QMessageFilterPrivate::lessThan);
       
  1206                                     } else {
       
  1207                                         pMFFilter->_filterList[pMFFilter->_filterList.count()-1].append(QMessageFilter::byParentAccountId(accountIds[x],QMessageDataComparator::Equal));
       
  1208                                         qSort(pMFFilter->_filterList[pMFFilter->_filterList.count()-1].begin(), pMFFilter->_filterList[pMFFilter->_filterList.count()-1].end(), QMessageFilterPrivate::lessThan);
       
  1209                                     }
       
  1210                                 }
       
  1211                             }
       
  1212                         } else { // Excludes
       
  1213                             for (int x = 0; x < accountIds.count(); x++) {
       
  1214                                 pMFFilter->_filterList[i].append(QMessageFilter::byParentAccountId(accountIds[x],QMessageDataComparator::NotEqual));
       
  1215                             }
       
  1216                             qSort(pMFFilter->_filterList[i].begin(), pMFFilter->_filterList[i].end(), QMessageFilterPrivate::lessThan);
       
  1217                         }
       
  1218                     } else {
       
  1219                         delete pMFFilter2->_accountFilter;
       
  1220                         pMFFilter2->_accountFilter = 0;
       
  1221                         pMFFilter2->_field = QMessageFilterPrivate::Id;
       
  1222                         qSort(pMFFilter->_filterList[i].begin(), pMFFilter->_filterList[i].end(), QMessageFilterPrivate::lessThan);
       
  1223                     }
       
  1224                 } else if (pMFFilter2->_field == QMessageFilterPrivate::ParentFolderIdFilter) { 
       
  1225                     QMessageFolderIdList folderIds = queryFolders(*pMFFilter2->_folderFilter, QMessageFolderSortOrder(), 0, 0);
       
  1226                     QMessageDataComparator::InclusionComparator cmp(static_cast<QMessageDataComparator::InclusionComparator>(pMFFilter2->_comparatorValue));
       
  1227                     if (folderIds.count() > 0) {
       
  1228                         pMFFilter->_filterList[i].removeAt(j);
       
  1229                         if (cmp == QMessageDataComparator::Includes) {
       
  1230                             for (int x = 0; x < folderIds.count(); x++) {
       
  1231                                 if (x == 0) {
       
  1232                                     if (x+1 < folderIds.count()) {
       
  1233                                         pMFFilter->_filterList.append(pMFFilter->_filterList[i]);
       
  1234                                     }
       
  1235                                     pMFFilter->_filterList[i].append(QMessageFilter::byParentFolderId(folderIds[x],QMessageDataComparator::Equal));
       
  1236                                     qSort(pMFFilter->_filterList[i].begin(), pMFFilter->_filterList[i].end(), QMessageFilterPrivate::lessThan);
       
  1237                                 } else {
       
  1238                                     if (x+1 < folderIds.count()) {
       
  1239                                         pMFFilter->_filterList.append(pMFFilter->_filterList[pMFFilter->_filterList.count()-1]);
       
  1240                                         pMFFilter->_filterList[pMFFilter->_filterList.count()-2].append(QMessageFilter::byParentFolderId(folderIds[x],QMessageDataComparator::Equal));
       
  1241                                         qSort(pMFFilter->_filterList[pMFFilter->_filterList.count()-2].begin(), pMFFilter->_filterList[pMFFilter->_filterList.count()-2].end(), QMessageFilterPrivate::lessThan);
       
  1242                                     } else {
       
  1243                                         pMFFilter->_filterList[pMFFilter->_filterList.count()-1].append(QMessageFilter::byParentFolderId(folderIds[x],QMessageDataComparator::Equal));
       
  1244                                         qSort(pMFFilter->_filterList[pMFFilter->_filterList.count()-1].begin(), pMFFilter->_filterList[pMFFilter->_filterList.count()-1].end(), QMessageFilterPrivate::lessThan);
       
  1245                                     }
       
  1246                                 }
       
  1247                             }
       
  1248                         } else { // Excludes
       
  1249                             for (int x = 0; x < folderIds.count(); x++) {
       
  1250                                 pMFFilter->_filterList[i].append(QMessageFilter::byParentFolderId(folderIds[x],QMessageDataComparator::NotEqual));
       
  1251                             }
       
  1252                             qSort(pMFFilter->_filterList[i].begin(), pMFFilter->_filterList[i].end(), QMessageFilterPrivate::lessThan);
       
  1253                         }
       
  1254                     } else {
       
  1255                         delete pMFFilter2->_folderFilter;
       
  1256                         pMFFilter2->_folderFilter = 0;
       
  1257                         pMFFilter2->_field = QMessageFilterPrivate::Id;
       
  1258                         qSort(pMFFilter->_filterList[i].begin(), pMFFilter->_filterList[i].end(), QMessageFilterPrivate::lessThan);
       
  1259                     }
       
  1260                 } else {
       
  1261                     break;
       
  1262                 }
       
  1263             }
       
  1264         }
       
  1265     } else {
       
  1266         if (pMFFilter->_field == QMessageFilterPrivate::ParentAccountIdFilter) {
       
  1267             QMessageAccountIdList accountIds = queryAccounts(*pMFFilter->_accountFilter, QMessageAccountSortOrder(), 0, 0);
       
  1268             QMessageDataComparator::InclusionComparator cmp(static_cast<QMessageDataComparator::InclusionComparator>(pMFFilter->_comparatorValue));
       
  1269             if (accountIds.count() > 0) {
       
  1270                 for (int i=0; i < accountIds.count(); i++) {
       
  1271                     if (i == 0) {
       
  1272                         delete pMFFilter->_accountFilter;
       
  1273                         pMFFilter->_accountFilter = 0;
       
  1274                         pMFFilter->_field = QMessageFilterPrivate::ParentAccountId;
       
  1275                         pMFFilter->_value = accountIds[0].toString();
       
  1276                         pMFFilter->_comparatorType = QMessageFilterPrivate::Equality;
       
  1277                         if (cmp == QMessageDataComparator::Includes) {
       
  1278                             pMFFilter->_comparatorValue = static_cast<int>(QMessageDataComparator::Equal);
       
  1279                         } else { // Excludes
       
  1280                             pMFFilter->_comparatorValue = static_cast<int>(QMessageDataComparator::NotEqual);
       
  1281                         }
       
  1282                     } else {
       
  1283                         if (cmp == QMessageDataComparator::Includes) {
       
  1284                             filter |= QMessageFilter::byParentAccountId(accountIds[i],QMessageDataComparator::Equal);
       
  1285                         } else { // Excludes
       
  1286                             filter &= QMessageFilter::byParentAccountId(accountIds[i],QMessageDataComparator::NotEqual);
       
  1287                         }
       
  1288                     }
       
  1289                 }
       
  1290             } else {
       
  1291                 delete pMFFilter->_accountFilter;
       
  1292                 pMFFilter->_accountFilter = 0;
       
  1293                 pMFFilter->_field = QMessageFilterPrivate::Id;
       
  1294             }
       
  1295         } else if (pMFFilter->_field == QMessageFilterPrivate::ParentFolderIdFilter) {
       
  1296             QMessageFolderIdList folderIds = queryFolders(*pMFFilter->_folderFilter, QMessageFolderSortOrder(), 0, 0);
       
  1297             QMessageDataComparator::InclusionComparator cmp(static_cast<QMessageDataComparator::InclusionComparator>(pMFFilter->_comparatorValue));
       
  1298             if (folderIds.count() > 0) {
       
  1299                 for (int i=0; i < folderIds.count(); i++) {
       
  1300                     if (i == 0) {
       
  1301                         delete pMFFilter->_folderFilter;
       
  1302                         pMFFilter->_folderFilter = 0;
       
  1303                         pMFFilter->_field = QMessageFilterPrivate::ParentFolderId;
       
  1304                         pMFFilter->_value = folderIds[0].toString();
       
  1305                         pMFFilter->_comparatorType = QMessageFilterPrivate::Equality;
       
  1306                         if (cmp == QMessageDataComparator::Includes) {
       
  1307                             pMFFilter->_comparatorValue = static_cast<int>(QMessageDataComparator::Equal);
       
  1308                         } else { // Excludes
       
  1309                             pMFFilter->_comparatorValue = static_cast<int>(QMessageDataComparator::NotEqual);
       
  1310                         }
       
  1311                     } else {
       
  1312                         if (cmp == QMessageDataComparator::Includes) {
       
  1313                             filter |= QMessageFilter::byParentFolderId(folderIds[i],QMessageDataComparator::Equal);
       
  1314                         } else { // Excludes
       
  1315                             filter &= QMessageFilter::byParentFolderId(folderIds[i],QMessageDataComparator::NotEqual);
       
  1316                         }
       
  1317                     }
       
  1318                 }
       
  1319             } else {
       
  1320                 delete pMFFilter->_folderFilter;
       
  1321                 pMFFilter->_folderFilter = 0;
       
  1322                 pMFFilter->_field = QMessageFilterPrivate::Id;
       
  1323             }
       
  1324         }
       
  1325     }
       
  1326 }
       
  1327 
       
  1328 bool CMTMEngine::queryMessages(QMessageServicePrivate& privateService, const QMessageFilter &filter, const QMessageSortOrder &sortOrder, uint limit, uint offset) const
       
  1329 {
       
  1330     TRAPD(err, queryMessagesL(privateService, filter, sortOrder, limit, offset));
       
  1331     if (err != KErrNone) {
       
  1332         return false;
       
  1333     }
       
  1334     return true;
       
  1335 }
       
  1336 
       
  1337 void CMTMEngine::queryMessagesL(QMessageServicePrivate& privateService, const QMessageFilter &filter, const QMessageSortOrder &sortOrder, uint limit, uint offset) const
       
  1338 {
       
  1339     MessageQueryInfo queryInfo;
       
  1340     queryInfo.operationId = ++iOperationIds;
       
  1341     if (queryInfo.operationId == 100000) {
       
  1342         queryInfo.operationId = 1;
       
  1343     }
       
  1344     queryInfo.isQuery = true;
       
  1345     queryInfo.filter = filter;
       
  1346     queryInfo.sortOrder = sortOrder;
       
  1347     queryInfo.offset = offset;
       
  1348     queryInfo.limit = limit;
       
  1349     queryInfo.findOperation = new CMessagesFindOperation((CMTMEngine&)*this, ipMsvSession, queryInfo.operationId);
       
  1350     queryInfo.privateService = &privateService;
       
  1351     queryInfo.currentFilterListIndex = 0;
       
  1352     iMessageQueries.append(queryInfo);
       
  1353     
       
  1354     handleNestedFiltersFromMessageFilter(iMessageQueries[iMessageQueries.count()-1].filter);
       
  1355     
       
  1356     QMessageFilterPrivate* pf = QMessageFilterPrivate::implementation(iMessageQueries[iMessageQueries.count()-1].filter);
       
  1357     if (pf->_filterList.count() == 0) {
       
  1358         queryInfo.findOperation->filterAndOrderMessages(iMessageQueries[iMessageQueries.count()-1].filter,
       
  1359                                                         iMessageQueries[iMessageQueries.count()-1].sortOrder);
       
  1360     } else {
       
  1361         queryInfo.findOperation->filterAndOrderMessages(pf->_filterList[0], iMessageQueries[iMessageQueries.count()-1].sortOrder);
       
  1362     }
       
  1363 }
       
  1364 
       
  1365 bool CMTMEngine::queryMessages(QMessageServicePrivate& privateService, const QMessageFilter &filter, const QString &body, QMessageDataComparator::MatchFlags matchFlags, const QMessageSortOrder &sortOrder, uint limit, uint offset) const
       
  1366 {
       
  1367     TRAPD(err, queryMessagesL(privateService, filter, body, matchFlags, sortOrder, limit, offset));
       
  1368     if (err != KErrNone) {
       
  1369         return false;
       
  1370     }
       
  1371     return true;
       
  1372 }
       
  1373 
       
  1374 void CMTMEngine::queryMessagesL(QMessageServicePrivate& privateService, const QMessageFilter &filter, const QString &body, QMessageDataComparator::MatchFlags matchFlags, const QMessageSortOrder &sortOrder, uint limit, uint offset) const
       
  1375 {
       
  1376     MessageQueryInfo queryInfo;
       
  1377     queryInfo.operationId = ++iOperationIds;
       
  1378     if (queryInfo.operationId == 100000) {
       
  1379         queryInfo.operationId = 1;
       
  1380     }
       
  1381     queryInfo.isQuery = true;
       
  1382     queryInfo.body = body;
       
  1383     queryInfo.matchFlags = matchFlags;
       
  1384     queryInfo.filter = filter;
       
  1385     queryInfo.sortOrder = sortOrder;
       
  1386     queryInfo.offset = offset;
       
  1387     queryInfo.limit = limit;
       
  1388     queryInfo.findOperation = new CMessagesFindOperation((CMTMEngine&)*this, ipMsvSession, queryInfo.operationId);
       
  1389     queryInfo.privateService = &privateService;
       
  1390     queryInfo.currentFilterListIndex = 0;
       
  1391     iMessageQueries.append(queryInfo);
       
  1392     
       
  1393     handleNestedFiltersFromMessageFilter(iMessageQueries[iMessageQueries.count()-1].filter);
       
  1394     
       
  1395     QMessageFilterPrivate* pf = QMessageFilterPrivate::implementation(iMessageQueries[iMessageQueries.count()-1].filter);
       
  1396     if (pf->_filterList.count() == 0) {
       
  1397         queryInfo.findOperation->filterAndOrderMessages(iMessageQueries[iMessageQueries.count()-1].filter,
       
  1398                                                         iMessageQueries[iMessageQueries.count()-1].sortOrder,
       
  1399                                                         body,
       
  1400                                                         matchFlags);
       
  1401     } else {
       
  1402         queryInfo.findOperation->filterAndOrderMessages(pf->_filterList[0],
       
  1403                                                         iMessageQueries[iMessageQueries.count()-1].sortOrder,
       
  1404                                                         body,
       
  1405                                                         matchFlags);
       
  1406     }
       
  1407 }
       
  1408 
       
  1409 bool CMTMEngine::countMessages(QMessageServicePrivate& privateService, const QMessageFilter &filter)
       
  1410 {
       
  1411     TRAPD(err, countMessagesL(privateService, filter));
       
  1412     if (err != KErrNone) {
       
  1413         return false;
       
  1414     }
       
  1415     return true;
       
  1416 }
       
  1417 
       
  1418 void CMTMEngine::countMessagesL(QMessageServicePrivate& privateService, const QMessageFilter &filter)
       
  1419 {
       
  1420     MessageQueryInfo queryInfo;
       
  1421     queryInfo.operationId = ++iOperationIds;
       
  1422     if (queryInfo.operationId == 100000) {
       
  1423         queryInfo.operationId = 1;
       
  1424     }
       
  1425     queryInfo.isQuery = false;
       
  1426     queryInfo.matchFlags = 0;
       
  1427     queryInfo.filter = filter;
       
  1428     queryInfo.sortOrder = QMessageSortOrder();
       
  1429     queryInfo.offset = 0;
       
  1430     queryInfo.limit = 0;
       
  1431     queryInfo.findOperation = new CMessagesFindOperation((CMTMEngine&)*this, ipMsvSession, queryInfo.operationId);
       
  1432     queryInfo.privateService = &privateService;
       
  1433     queryInfo.currentFilterListIndex = 0;
       
  1434     queryInfo.count = 0;
       
  1435     iMessageQueries.append(queryInfo);
       
  1436     
       
  1437     handleNestedFiltersFromMessageFilter(iMessageQueries[iMessageQueries.count()-1].filter);
       
  1438     
       
  1439     QMessageFilterPrivate* pf = QMessageFilterPrivate::implementation(iMessageQueries[iMessageQueries.count()-1].filter);
       
  1440     if (pf->_filterList.count() == 0) {
       
  1441         queryInfo.findOperation->filterAndOrderMessages(iMessageQueries[iMessageQueries.count()-1].filter,
       
  1442                                                         iMessageQueries[iMessageQueries.count()-1].sortOrder);
       
  1443     } else {
       
  1444         queryInfo.findOperation->filterAndOrderMessages(pf->_filterList[0], iMessageQueries[iMessageQueries.count()-1].sortOrder);
       
  1445     }
       
  1446 }
       
  1447 
       
  1448 void CMTMEngine::filterAndOrderMessagesReady(bool success, int operationId, QMessageIdList ids, int numberOfHandledFilters,
       
  1449                                              bool resultSetOrdered)
       
  1450 {
       
  1451     int index=0;
       
  1452     for (; index < iMessageQueries.count(); index++) {
       
  1453         if (iMessageQueries[index].operationId == operationId) {
       
  1454             break;
       
  1455         }
       
  1456     }
       
  1457 
       
  1458     if (success) {
       
  1459         // If there are unhandled filters, loop through all filters and do filtering for ids using unhandled filters.
       
  1460         QMessageFilterPrivate* pf = QMessageFilterPrivate::implementation(iMessageQueries[index].filter);
       
  1461         if (pf->_filterList.count() > 0) {
       
  1462             if (pf->_filterList[iMessageQueries[index].currentFilterListIndex].count() > numberOfHandledFilters) {
       
  1463                 for (int i=0; i < ids.count(); i++) {
       
  1464                     QMessage msg = message(ids[i]);
       
  1465                     for (int j=numberOfHandledFilters; j < pf->_filterList[iMessageQueries[index].currentFilterListIndex].count(); j++) {
       
  1466                         QMessageFilterPrivate* pf2 = QMessageFilterPrivate::implementation(pf->_filterList[iMessageQueries[index].currentFilterListIndex][j]);
       
  1467                         if (!pf2->filter(msg)) {
       
  1468                             ids.removeAt(i);
       
  1469                             i--;
       
  1470                             break;
       
  1471                         }
       
  1472                     }
       
  1473                 }
       
  1474             }
       
  1475         }
       
  1476 
       
  1477         if (pf->_filterList.count() > 0) {
       
  1478             // Filter contains filterlist (or filterlists), not just one single filter 
       
  1479             if (iMessageQueries[index].currentFilterListIndex == 0) {
       
  1480                 iMessageQueries[index].ids << ids;
       
  1481                 iMessageQueries[index].count = ids.count(); 
       
  1482             } else {
       
  1483                 // Append new ids to resultset
       
  1484                 for (int i=0; i < ids.count(); i++) {
       
  1485                     if (!iMessageQueries[index].ids.contains(ids[i])) {
       
  1486                         iMessageQueries[index].ids.append(ids[i]);
       
  1487                         iMessageQueries[index].count++;; 
       
  1488                     }
       
  1489                 }
       
  1490             }
       
  1491             
       
  1492             iMessageQueries[index].currentFilterListIndex++;
       
  1493             if (iMessageQueries[index].currentFilterListIndex < pf->_filterList.count()) {
       
  1494                 // There are still unhandled filter lists left
       
  1495                 iMessageQueries[index].findOperation->filterAndOrderMessages(pf->_filterList[iMessageQueries[index].currentFilterListIndex],
       
  1496                                                                              iMessageQueries[index].sortOrder,
       
  1497                                                                              iMessageQueries[index].body,
       
  1498                                                                              iMessageQueries[index].matchFlags);
       
  1499                 return;
       
  1500             } else {
       
  1501                 // All filters successfully handled
       
  1502                 if (iMessageQueries[index].isQuery) {
       
  1503                     if (!iMessageQueries[index].sortOrder.isEmpty()) {
       
  1504                         // Make sure that messages are correctly ordered
       
  1505                         orderMessages(iMessageQueries[index].ids, iMessageQueries[index].sortOrder);
       
  1506                     }
       
  1507                     applyOffsetAndLimitToMsgIds(iMessageQueries[index].ids,
       
  1508                                                 iMessageQueries[index].offset,
       
  1509                                                 iMessageQueries[index].limit);
       
  1510                     iMessageQueries[index].privateService->messagesFound(iMessageQueries[index].ids, true, true);
       
  1511                 } else {
       
  1512                     iMessageQueries[index].privateService->messagesCounted(iMessageQueries[index].count);
       
  1513                 }
       
  1514             }
       
  1515         } else {
       
  1516             // There was only one single filter to handle
       
  1517             if (numberOfHandledFilters == 0) {
       
  1518                 // The one and only filter was not handled
       
  1519                 // => Do filtering for all returned messages
       
  1520                 for (int i=ids.count()-1; i >= 0; i--) {
       
  1521                     QMessage msg = message(ids[i]);
       
  1522                     if (!pf->filter(msg)) {
       
  1523                         ids.removeAt(i);
       
  1524                     }
       
  1525                 }
       
  1526             }
       
  1527             // => All filters successfully handled
       
  1528             if (iMessageQueries[index].isQuery) {
       
  1529                 // Make sure that messages are correctly ordered
       
  1530                 if (!iMessageQueries[index].sortOrder.isEmpty() && !resultSetOrdered) {
       
  1531                     orderMessages(ids, iMessageQueries[index].sortOrder);
       
  1532                 }
       
  1533                 // Handle offest & limit
       
  1534                 applyOffsetAndLimitToMsgIds(ids, iMessageQueries[index].offset, iMessageQueries[index].limit);
       
  1535                 iMessageQueries[index].privateService->messagesFound(ids, true, true);
       
  1536             } else {
       
  1537                 iMessageQueries[index].privateService->messagesCounted(ids.count());
       
  1538             }
       
  1539         }
       
  1540     } else {
       
  1541         iMessageQueries[index].privateService->_active = false;
       
  1542         if (iMessageQueries[index].privateService->_error == QMessageManager::NoError) {
       
  1543             iMessageQueries[index].privateService->_error = QMessageManager::RequestIncomplete;
       
  1544         }
       
  1545     }
       
  1546 
       
  1547     delete iMessageQueries[index].findOperation;
       
  1548     iMessageQueries.removeAt(index);
       
  1549 }
       
  1550 
       
  1551 
       
  1552 void CMTMEngine::applyOffsetAndLimitToMsgIds(QMessageIdList& idList, int offset, int limit) const
       
  1553 {
       
  1554     if (offset > 0) {
       
  1555         if (offset > idList.count()) {
       
  1556             idList.clear();
       
  1557         } else {
       
  1558             for (int i = 0; i < offset; i++) {
       
  1559                 idList.removeFirst();
       
  1560             }
       
  1561         }
       
  1562     }
       
  1563     if (limit > 0) {
       
  1564         for (int i = idList.count()-1; i >= limit; i--) {
       
  1565             idList.removeAt(i);
       
  1566         }
       
  1567     }
       
  1568 }
       
  1569 
       
  1570 QMessageFolderIdList CMTMEngine::filterMessageFolders(const QMessageFolderFilter& filter, bool& filterHandled) const
       
  1571 {
       
  1572     QMessageFolderIdList ids;
       
  1573     TRAPD(err, ids = filterMessageFoldersL(filter, filterHandled));
       
  1574     Q_UNUSED(err)
       
  1575     return ids;
       
  1576 }
       
  1577 
       
  1578 QMessageFolderIdList CMTMEngine::filterMessageFoldersL(const QMessageFolderFilter& filter, bool& filterHandled) const
       
  1579 {
       
  1580     filterHandled = false;
       
  1581     QMessageFolderIdList ids;
       
  1582     
       
  1583     if (filter.isEmpty()) {
       
  1584         QMessageFolderFilterPrivate* pf = QMessageFolderFilterPrivate::implementation(filter);
       
  1585         if (!pf->_notFilter) {
       
  1586             ids = allFolders();
       
  1587         }
       
  1588         filterHandled = true;
       
  1589     } else {
       
  1590         QMessageFolderFilterPrivate* pf = QMessageFolderFilterPrivate::implementation(filter);
       
  1591         if (!pf->_valid) {
       
  1592             return QMessageFolderIdList();
       
  1593         }
       
  1594     
       
  1595         switch (pf->_field) {
       
  1596         case QMessageFolderFilterPrivate::Id:
       
  1597             {
       
  1598             if (pf->_comparatorType == QMessageFolderFilterPrivate::Equality) {
       
  1599                 QMessageDataComparator::EqualityComparator cmp(static_cast<QMessageDataComparator::EqualityComparator>(pf->_comparatorValue));
       
  1600                 if (pf->_value.toString().length() > QString(SymbianHelpers::mtmPrefix).length()) {
       
  1601                     bool folderOk = false;
       
  1602                     long int folderId = folderIdFromQMessageFolderId(QMessageFolderId(pf->_value.toString()));
       
  1603                     CMsvEntry* pEntry = retrieveCMsvEntryAndPushToCleanupStack(folderId);
       
  1604                     if (pEntry) {
       
  1605                         if (pEntry->Entry().iType == KUidMsvFolderEntry) {
       
  1606                             folderOk = true;
       
  1607                         }
       
  1608                         releaseCMsvEntryAndPopFromCleanupStack(pEntry);
       
  1609                     }
       
  1610                     if (cmp == QMessageDataComparator::Equal) {
       
  1611                         if (folderOk) {
       
  1612                             ids.append(QMessageFolderId(pf->_value.toString()));
       
  1613                         }
       
  1614                     } else { // NotEqual
       
  1615                         ids = allFolders();
       
  1616                         if (folderOk) {
       
  1617                             ids.removeOne(QMessageFolderId(pf->_value.toString()));
       
  1618                         }
       
  1619                     }
       
  1620                 } else {
       
  1621                     if (cmp == QMessageDataComparator::NotEqual) {
       
  1622                         ids = allFolders();
       
  1623                     }
       
  1624                 }
       
  1625                 filterHandled = true;
       
  1626             } else if (pf->_comparatorType == QMessageFolderFilterPrivate::Inclusion) {
       
  1627                 QMessageDataComparator::InclusionComparator cmp(static_cast<QMessageDataComparator::InclusionComparator>(pf->_comparatorValue));
       
  1628                 if (pf->_ids.count() > 0) { // QMessageIdList
       
  1629                     QMessageFolderIdList ids2;
       
  1630                     for (int i=0; i < pf->_ids.count(); i++) {
       
  1631                         long int folderId = folderIdFromQMessageFolderId(QMessageFolderId(pf->_ids[i].toString()));
       
  1632                         CMsvEntry* pEntry = retrieveCMsvEntryAndPushToCleanupStack(folderId);
       
  1633                         if (pEntry) {
       
  1634                             const TMsvEntry& entry = pEntry->Entry();
       
  1635                             if (entry.iType == KUidMsvFolderEntry) {
       
  1636                                 ids2.append(pf->_ids[i]);
       
  1637                             }
       
  1638                             releaseCMsvEntryAndPopFromCleanupStack(pEntry);
       
  1639                         }
       
  1640                     }
       
  1641                     if (cmp == QMessageDataComparator::Includes) {
       
  1642                         ids << ids2;
       
  1643                     } else { // Excludes
       
  1644                         ids = allFolders();
       
  1645                         for (int i=0; i < ids2.count(); i++) {
       
  1646                             ids.removeOne(ids2[i]);
       
  1647                         }
       
  1648                     }
       
  1649                     filterHandled = true;
       
  1650                 } else {
       
  1651                     // Empty QMessageIdList as a list
       
  1652                     if (cmp == QMessageDataComparator::Excludes) {
       
  1653                         ids = allFolders();
       
  1654                     }
       
  1655                     filterHandled = true;
       
  1656                 
       
  1657                     // QMessageFilter 
       
  1658                     /*if (cmp == QMessageDataComparator::Includes) {
       
  1659                         // TODO:
       
  1660                     } else { // Excludes
       
  1661                         // TODO:
       
  1662                     }*/
       
  1663                 }
       
  1664             }
       
  1665             break;
       
  1666             }
       
  1667         case QMessageFolderFilterPrivate::Name:
       
  1668             {
       
  1669             if (pf->_comparatorType == QMessageFolderFilterPrivate::Equality) {
       
  1670                 QMessageDataComparator::EqualityComparator cmp(static_cast<QMessageDataComparator::EqualityComparator>(pf->_comparatorValue));
       
  1671                 if (cmp == QMessageDataComparator::Equal) {
       
  1672                     // TODO:
       
  1673                 } else { // NotEqual
       
  1674                     // TODO:
       
  1675                 }
       
  1676             } else if (pf->_comparatorType == QMessageFolderFilterPrivate::Inclusion) {
       
  1677                 QMessageDataComparator::InclusionComparator cmp(static_cast<QMessageDataComparator::InclusionComparator>(pf->_comparatorValue));
       
  1678                 if (cmp == QMessageDataComparator::Includes) {
       
  1679                     // TODO:
       
  1680                 } else { // Excludes
       
  1681                     if (pf->_value.toString().isEmpty() || pf->_value.toString().length() == 0) {
       
  1682                         filterHandled = true;
       
  1683                     }
       
  1684                 }
       
  1685             }
       
  1686             break;
       
  1687             }
       
  1688         case QMessageFolderFilterPrivate::Path:
       
  1689             {
       
  1690             if (pf->_comparatorType == QMessageFolderFilterPrivate::Equality) {
       
  1691                 QMessageDataComparator::EqualityComparator cmp(static_cast<QMessageDataComparator::EqualityComparator>(pf->_comparatorValue));
       
  1692                 if (cmp == QMessageDataComparator::Equal) {
       
  1693                     // TODO:
       
  1694                 } else { // NotEqual
       
  1695                     // TODO:
       
  1696                 }
       
  1697             } else if (pf->_comparatorType == QMessageFolderFilterPrivate::Inclusion) {
       
  1698                 QMessageDataComparator::InclusionComparator cmp(static_cast<QMessageDataComparator::InclusionComparator>(pf->_comparatorValue));
       
  1699                 if (cmp == QMessageDataComparator::Includes) {
       
  1700                     // TODO:
       
  1701                 } else { // Excludes
       
  1702                     if (pf->_value.toString().isEmpty() || pf->_value.toString().length() == 0) {
       
  1703                         filterHandled = true;
       
  1704                     }
       
  1705                 }
       
  1706             }
       
  1707             break;
       
  1708             }
       
  1709         case QMessageFolderFilterPrivate::ParentAccountId:
       
  1710             {
       
  1711             if (pf->_comparatorType == QMessageFolderFilterPrivate::Equality) {
       
  1712                 QMessageDataComparator::EqualityComparator cmp(static_cast<QMessageDataComparator::EqualityComparator>(pf->_comparatorValue));
       
  1713                 if (cmp == QMessageDataComparator::Equal) {
       
  1714                     if (pf->_value.toString().length() > QString(SymbianHelpers::mtmPrefix).length()) {
       
  1715                         ids = folderIdsByAccountId(QMessageAccountId(pf->_value.toString()));
       
  1716                     }
       
  1717                 } else { // NotEqual
       
  1718                     ids = allFolders();
       
  1719                     if (pf->_value.toString().length() > QString(SymbianHelpers::mtmPrefix).length()) {
       
  1720                         QMessageFolderIdList ids2 = folderIdsByAccountId(QMessageAccountId(pf->_value.toString()));
       
  1721                         for (int i = 0; i < ids2.count(); i++) {
       
  1722                             ids.removeOne(ids2[i]);
       
  1723                         }
       
  1724                     }
       
  1725                 }
       
  1726                 filterHandled = true;
       
  1727             } else if (pf->_comparatorType == QMessageFolderFilterPrivate::Inclusion) {
       
  1728                 QMessageDataComparator::InclusionComparator cmp(static_cast<QMessageDataComparator::InclusionComparator>(pf->_comparatorValue));
       
  1729                 if (cmp == QMessageDataComparator::Includes) {
       
  1730                     // TODO:
       
  1731                 } else { // Excludes
       
  1732                     // TODO:
       
  1733                 }
       
  1734             }
       
  1735             break;
       
  1736             }
       
  1737         case QMessageFolderFilterPrivate::ParentFolderId:
       
  1738             {
       
  1739             if (pf->_comparatorType == QMessageFolderFilterPrivate::Equality) {
       
  1740                 QMessageDataComparator::EqualityComparator cmp(static_cast<QMessageDataComparator::EqualityComparator>(pf->_comparatorValue));
       
  1741                 if (cmp == QMessageDataComparator::Equal) {
       
  1742                     long int folderId = pf->_value.toString().toLong();
       
  1743                     CMsvEntry* pEntry = retrieveCMsvEntryAndPushToCleanupStack(folderId);
       
  1744                     if (pEntry) {
       
  1745                         const TMsvEntry& entry = pEntry->Entry();
       
  1746                         if (entry.iType == KUidMsvFolderEntry) {
       
  1747                             CMsvEntrySelection* pSelection = pEntry->ChildrenWithTypeL(KUidMsvFolderEntry);
       
  1748                             CleanupStack::PushL(pSelection);
       
  1749                             if (pSelection->Count() > 0) {
       
  1750                                 for(TInt i = 0; i < pSelection->Count(); i++) {
       
  1751                                     ids.append(QMessageFolderId(SymbianHelpers::addIdPrefix(QString::number(pSelection->At(i)),SymbianHelpers::EngineTypeMTM)));
       
  1752                                 }
       
  1753                             }
       
  1754                             CleanupStack::PopAndDestroy(pSelection);
       
  1755                         }
       
  1756                         releaseCMsvEntryAndPopFromCleanupStack(pEntry);
       
  1757                     }
       
  1758                 } else { // NotEqual
       
  1759                     // TODO:
       
  1760                 }
       
  1761             } else if (pf->_comparatorType == QMessageFolderFilterPrivate::Inclusion) {
       
  1762                 QMessageDataComparator::InclusionComparator cmp(static_cast<QMessageDataComparator::InclusionComparator>(pf->_comparatorValue));
       
  1763                 if (cmp == QMessageDataComparator::Includes) {
       
  1764                     // TODO:
       
  1765                 } else { // Excludes
       
  1766                     // TODO:
       
  1767                 }
       
  1768             }
       
  1769             break;
       
  1770             }
       
  1771         case QMessageFolderFilterPrivate::AncestorFolderIds:
       
  1772             {
       
  1773             if (pf->_comparatorType == QMessageFolderFilterPrivate::Inclusion) {
       
  1774                 QMessageDataComparator::InclusionComparator cmp(static_cast<QMessageDataComparator::InclusionComparator>(pf->_comparatorValue));
       
  1775                 if (!pf->_value.isNull()) { // QMessageFolderId
       
  1776                     if (cmp == QMessageDataComparator::Includes) {
       
  1777                         // TODO:
       
  1778                     } else { // Excludes
       
  1779                         // TODO:
       
  1780                     }
       
  1781                 } else { // QMessageFolderFilter
       
  1782                     if (cmp == QMessageDataComparator::Includes) {
       
  1783                         // TODO:
       
  1784                     } else { // Excludes
       
  1785                         // TODO:
       
  1786                     }
       
  1787                 }
       
  1788             }
       
  1789             break;
       
  1790             }
       
  1791     	case QMessageFolderFilterPrivate::ParentAccountIdFilter:
       
  1792         case QMessageFolderFilterPrivate::None:
       
  1793             break;        
       
  1794         }
       
  1795     }
       
  1796     
       
  1797     if (!filterHandled) {
       
  1798         ids = allFolders();
       
  1799     }
       
  1800 
       
  1801     return ids;
       
  1802 }
       
  1803 
       
  1804 QMessageFolderIdList CMTMEngine::allFolders() const
       
  1805 {
       
  1806     QMessageFolderIdList ids;
       
  1807     TRAPD(err, updateEmailAccountsL());
       
  1808     Q_UNUSED(err)
       
  1809     foreach (QMessageAccount value, iAccounts) {
       
  1810         QMessageFolderIdList ids2 = folderIdsByAccountId(value.id());
       
  1811         ids << ids2;
       
  1812     }
       
  1813     return ids;
       
  1814 }
       
  1815 
       
  1816 QMessageFolderIdList CMTMEngine::folderIdsByAccountId(const QMessageAccountId& accountId) const
       
  1817 {
       
  1818     QMessageAccount messageAccount = account(accountId);
       
  1819     QMessageFolderIdList ids = folderIdsByServiceEntryId(messageAccount.d_ptr->_service1EntryId,
       
  1820                                                          messageAccount.d_ptr->_service1EntryId);
       
  1821     if (messageAccount.d_ptr->_service2EntryId) {
       
  1822         QMessageFolderIdList ids2 = folderIdsByServiceEntryId(messageAccount.d_ptr->_service2EntryId,
       
  1823                                                               messageAccount.d_ptr->_service1EntryId);
       
  1824         ids << ids2;
       
  1825     }
       
  1826     return ids;
       
  1827 }
       
  1828 
       
  1829 QMessageFolderIdList CMTMEngine::folderIdsByServiceEntryId(const TMsvId& serviceEntryId,
       
  1830                                                            const TMsvId& folderServiceEntryId) const
       
  1831 {
       
  1832     QMessageFolderIdList ids;
       
  1833 
       
  1834     CMsvEntry* pEntry = retrieveCMsvEntryAndPushToCleanupStack(serviceEntryId);
       
  1835     if (pEntry) {
       
  1836         const TMsvEntry& entry = pEntry->Entry();
       
  1837         if (entry.iMtm == KUidMsgTypeSMS || entry.iMtm == KUidMsgTypeMultimedia || entry.iMtm == KUidMsgTypeSMTP) {
       
  1838             // Add all Standard Folders to FolderIdList
       
  1839             if (entry.iMtm != KUidMsgTypeSMTP) {
       
  1840                 // SMTP is for sending only => Don't add Inbox for SMTP
       
  1841                 ids.append(createQMessageFolderId(folderServiceEntryId, KMsvGlobalInBoxIndexEntryId));
       
  1842             }
       
  1843             ids.append(createQMessageFolderId(folderServiceEntryId, KMsvGlobalOutBoxIndexEntryId));
       
  1844             ids.append(createQMessageFolderId(folderServiceEntryId, KMsvDraftEntryId));
       
  1845             ids.append(createQMessageFolderId(folderServiceEntryId, KMsvSentEntryId));
       
  1846             ids.append(createQMessageFolderId(folderServiceEntryId, KMsvDeletedEntryFolderEntryId));
       
  1847             pEntry->SetEntryL(KDocumentsEntryIdValue);
       
  1848         }
       
  1849     
       
  1850         if (entry.iMtm == KUidMsgTypePOP3) {
       
  1851             ids.append(createQMessageFolderId(folderServiceEntryId, serviceEntryId));
       
  1852         } else {
       
  1853             CMsvEntryFilter* pFilter = CMsvEntryFilter::NewLC();
       
  1854             pFilter->SetService(serviceEntryId);
       
  1855             pFilter->SetType(KUidMsvFolderEntry);
       
  1856             CMsvEntrySelection* pSelection = new(ELeave) CMsvEntrySelection;
       
  1857             CleanupStack::PushL(pSelection);
       
  1858             ipMsvSession->GetChildIdsL(pEntry->Entry().Id(), *pFilter, *pSelection);
       
  1859             if (pSelection->Count() > 0) {
       
  1860                 for(TInt i = 0; i < pSelection->Count(); i++) {
       
  1861                     ids.append(createQMessageFolderId(folderServiceEntryId, pSelection->At(i)));
       
  1862                 }
       
  1863             }
       
  1864             CleanupStack::PopAndDestroy(pSelection);
       
  1865             CleanupStack::PopAndDestroy(pFilter);
       
  1866         }
       
  1867         releaseCMsvEntryAndPopFromCleanupStack(pEntry);
       
  1868     }
       
  1869     
       
  1870     return ids;
       
  1871 }
       
  1872 
       
  1873 QMessageFolderId CMTMEngine::createQMessageFolderId(const TMsvId& serviceEntryId, const TMsvId& folderId) const
       
  1874 {
       
  1875     QString nullString = "00000000";
       
  1876     QString serviceEntryIdString = QString::number(serviceEntryId);
       
  1877     serviceEntryIdString = nullString.left(8-serviceEntryIdString.length()) + serviceEntryIdString;
       
  1878     QString folderIdString = QString::number(folderId);
       
  1879     folderIdString = nullString.left(8-folderIdString.length()) + folderIdString;
       
  1880     return SymbianHelpers::addIdPrefix(serviceEntryIdString+folderIdString,SymbianHelpers::EngineTypeMTM);
       
  1881 }
       
  1882 
       
  1883 TMsvId CMTMEngine::serviceEntryIdFromQMessageFolderId(const QMessageFolderId& folderId) const
       
  1884 {
       
  1885     return SymbianHelpers::stripIdPrefix(folderId.toString()).left(8).toLong(); 
       
  1886 }
       
  1887 
       
  1888 TMsvId CMTMEngine::folderIdFromQMessageFolderId(const QMessageFolderId& folderId) const
       
  1889 {
       
  1890     return SymbianHelpers::stripIdPrefix(folderId.toString()).right(8).toLong(); 
       
  1891 }
       
  1892 
       
  1893 void CMTMEngine::handleNestedFiltersFromFolderFilter(QMessageFolderFilter &filter) const
       
  1894 {
       
  1895     QMessageFolderFilterPrivate* pMFFilter = QMessageFolderFilterPrivate::implementation(filter);
       
  1896     if (pMFFilter->_filterList.count() > 0) {
       
  1897         int filterListCount = pMFFilter->_filterList.count();
       
  1898         for (int i=0; i < filterListCount; i++) {
       
  1899             for (int j=0; j < pMFFilter->_filterList[i].count(); j++) {
       
  1900                 QMessageFolderFilterPrivate* pMFFilter2 = QMessageFolderFilterPrivate::implementation(pMFFilter->_filterList[i][j]);
       
  1901                 if (pMFFilter2->_field == QMessageFolderFilterPrivate::ParentAccountIdFilter) {
       
  1902                     QMessageAccountIdList accountIds = queryAccounts(*pMFFilter2->_accountFilter, QMessageAccountSortOrder(), 0, 0);
       
  1903                     QMessageDataComparator::InclusionComparator cmp(static_cast<QMessageDataComparator::InclusionComparator>(pMFFilter2->_comparatorValue));
       
  1904                     if (accountIds.count() > 0) {
       
  1905                         pMFFilter->_filterList[i].removeAt(j);
       
  1906                         if (cmp == QMessageDataComparator::Includes) {
       
  1907                             for (int x = 0; x < accountIds.count(); x++) {
       
  1908                                 if (x == 0) {
       
  1909                                     if (x+1 < accountIds.count()) {
       
  1910                                         pMFFilter->_filterList.append(pMFFilter->_filterList[i]);
       
  1911                                     }
       
  1912                                     pMFFilter->_filterList[i].append(QMessageFolderFilter::byParentAccountId(accountIds[x],QMessageDataComparator::Equal));
       
  1913                                     qSort(pMFFilter->_filterList[i].begin(), pMFFilter->_filterList[i].end(), QMessageFolderFilterPrivate::lessThan);
       
  1914                                 } else {
       
  1915                                     if (x+1 < accountIds.count()) {
       
  1916                                         pMFFilter->_filterList.append(pMFFilter->_filterList[pMFFilter->_filterList.count()-1]);
       
  1917                                         pMFFilter->_filterList[pMFFilter->_filterList.count()-2].append(QMessageFolderFilter::byParentAccountId(accountIds[x],QMessageDataComparator::Equal));
       
  1918                                         qSort(pMFFilter->_filterList[pMFFilter->_filterList.count()-2].begin(), pMFFilter->_filterList[pMFFilter->_filterList.count()-2].end(), QMessageFolderFilterPrivate::lessThan);
       
  1919                                     } else {
       
  1920                                         pMFFilter->_filterList[pMFFilter->_filterList.count()-1].append(QMessageFolderFilter::byParentAccountId(accountIds[x],QMessageDataComparator::Equal));
       
  1921                                         qSort(pMFFilter->_filterList[pMFFilter->_filterList.count()-1].begin(), pMFFilter->_filterList[pMFFilter->_filterList.count()-1].end(), QMessageFolderFilterPrivate::lessThan);
       
  1922                                     }
       
  1923                                 }
       
  1924                             }
       
  1925                         } else { // Excludes
       
  1926                             for (int x = 0; x < accountIds.count(); x++) {
       
  1927                                 pMFFilter->_filterList[i].append(QMessageFolderFilter::byParentAccountId(accountIds[x],QMessageDataComparator::NotEqual));
       
  1928                             }
       
  1929                             qSort(pMFFilter->_filterList[i].begin(), pMFFilter->_filterList[i].end(), QMessageFolderFilterPrivate::lessThan);
       
  1930                         }
       
  1931                     } else {
       
  1932                         delete pMFFilter2->_accountFilter;
       
  1933                         pMFFilter2->_accountFilter = 0;
       
  1934                         pMFFilter2->_field = QMessageFolderFilterPrivate::Id;
       
  1935                         qSort(pMFFilter->_filterList[i].begin(), pMFFilter->_filterList[i].end(), QMessageFolderFilterPrivate::lessThan);
       
  1936                     }
       
  1937                 } else {
       
  1938                     break;
       
  1939                 }
       
  1940             }
       
  1941         }
       
  1942     } else {
       
  1943         if (pMFFilter->_field == QMessageFolderFilterPrivate::ParentAccountIdFilter) {
       
  1944             QMessageAccountIdList accountIds = queryAccounts(*pMFFilter->_accountFilter, QMessageAccountSortOrder(), 0, 0);
       
  1945             QMessageDataComparator::InclusionComparator cmp(static_cast<QMessageDataComparator::InclusionComparator>(pMFFilter->_comparatorValue));
       
  1946             if (accountIds.count() > 0) {
       
  1947                 for (int i=0; i < accountIds.count(); i++) {
       
  1948                     if (i == 0) {
       
  1949                         delete pMFFilter->_accountFilter;
       
  1950                         pMFFilter->_accountFilter = 0;
       
  1951                         pMFFilter->_field = QMessageFolderFilterPrivate::ParentAccountId;
       
  1952                         pMFFilter->_value = accountIds[0].toString();
       
  1953                         pMFFilter->_comparatorType = QMessageFolderFilterPrivate::Equality;
       
  1954                         if (cmp == QMessageDataComparator::Includes) {
       
  1955                             pMFFilter->_comparatorValue = static_cast<int>(QMessageDataComparator::Equal);
       
  1956                         } else { // Excludes
       
  1957                             pMFFilter->_comparatorValue = static_cast<int>(QMessageDataComparator::NotEqual);
       
  1958                         }
       
  1959                     } else {
       
  1960                         if (cmp == QMessageDataComparator::Includes) {
       
  1961                             filter |= QMessageFolderFilter::byParentAccountId(accountIds[i],QMessageDataComparator::Equal);
       
  1962                         } else { // Excludes
       
  1963                             filter &= QMessageFolderFilter::byParentAccountId(accountIds[i],QMessageDataComparator::NotEqual);
       
  1964                         }
       
  1965                     }
       
  1966                 }
       
  1967             } else {
       
  1968                 delete pMFFilter->_accountFilter;
       
  1969                 pMFFilter->_accountFilter = 0;
       
  1970                 pMFFilter->_field = QMessageFolderFilterPrivate::Id;
       
  1971             }
       
  1972         }
       
  1973     }
       
  1974 }
       
  1975 
       
  1976 QMessageFolderIdList CMTMEngine::queryFolders(const QMessageFolderFilter &filter, const QMessageFolderSortOrder &sortOrder, uint limit, uint offset) const
       
  1977 {
       
  1978     QMessageFolderIdList ids;
       
  1979     
       
  1980     QMessageFolderFilter copyOfFilter = filter;
       
  1981     handleNestedFiltersFromFolderFilter(copyOfFilter);
       
  1982     
       
  1983     QMessageFolderFilterPrivate* pMFFilter = QMessageFolderFilterPrivate::implementation(copyOfFilter);
       
  1984 
       
  1985     if (pMFFilter->_filterList.count() > 0) {
       
  1986         for (int i=0; i < pMFFilter->_filterList.count(); i++) {
       
  1987             bool filterHandled;
       
  1988             QMessageFolderIdList ids2 = filterMessageFolders(pMFFilter->_filterList[i][0], filterHandled);
       
  1989             for (int x=ids2.count()-1; x >= 0; x--) {
       
  1990                 QMessageFolder mf = folder(ids2[x]);
       
  1991                 int j = filterHandled ? 1 : 0;
       
  1992                 for (; j < pMFFilter->_filterList[i].count(); j++) {
       
  1993                     if (!QMessageFolderFilterPrivate::implementation(pMFFilter->_filterList[i][j])->filter(mf)) {
       
  1994                         ids2.removeAt(x);
       
  1995                         break;
       
  1996                     }
       
  1997                 }
       
  1998             }
       
  1999             for (int j=0; j < ids2.count(); j++) {
       
  2000                 if (!ids.contains(ids2[j])) {
       
  2001                    ids.append(ids2[j]);
       
  2002                 }
       
  2003             }
       
  2004         }
       
  2005     } else {
       
  2006         bool filterHandled;
       
  2007         ids = filterMessageFolders(copyOfFilter, filterHandled);
       
  2008         if (!filterHandled) {
       
  2009             for (int i=ids.count()-1; i >= 0; i--) {
       
  2010                 if (!QMessageFolderFilterPrivate::implementation(copyOfFilter)->filter(ids[i])) {
       
  2011                     ids.removeAt(i);
       
  2012                 }
       
  2013             }
       
  2014         }
       
  2015     }
       
  2016     
       
  2017     if (!sortOrder.isEmpty()) {
       
  2018         orderFolders(ids, sortOrder);
       
  2019     }
       
  2020     
       
  2021     applyOffsetAndLimitToMsgFolderIds(ids, offset, limit);
       
  2022     
       
  2023     return ids;
       
  2024 }
       
  2025 
       
  2026 void CMTMEngine::applyOffsetAndLimitToMsgFolderIds(QMessageFolderIdList& idList, int offset, int limit) const
       
  2027 {
       
  2028     if (offset > 0) {
       
  2029         if (offset > idList.count()) {
       
  2030             idList.clear();
       
  2031         } else {
       
  2032             for (int i = 0; i < offset; i++) {
       
  2033                 idList.removeFirst();
       
  2034             }
       
  2035         }
       
  2036     }
       
  2037     if (limit > 0) {
       
  2038         for (int i = idList.count()-1; i >= limit; i--) {
       
  2039             idList.removeAt(i);
       
  2040         }
       
  2041     }
       
  2042 }
       
  2043 
       
  2044 int CMTMEngine::countFolders(const QMessageFolderFilter &filter) const
       
  2045 {
       
  2046     return queryFolders(filter, QMessageFolderSortOrder(), 0, 0).count();
       
  2047 }
       
  2048 
       
  2049 QMessageFolder CMTMEngine::folder(const QMessageFolderId &id) const
       
  2050 {
       
  2051     if (!iSessionReady)
       
  2052         return QMessageFolder();
       
  2053     
       
  2054     QMessageFolder folder;
       
  2055     TRAPD(err, folder = folderL(id));
       
  2056     Q_UNUSED(err)
       
  2057        
       
  2058     return folder;
       
  2059 }
       
  2060 
       
  2061 QMessageFolder CMTMEngine::folderL(const QMessageFolderId &id) const
       
  2062 {
       
  2063     QMessageFolder folder;
       
  2064 
       
  2065     TMsvId folderId = folderIdFromQMessageFolderId(id);
       
  2066     TMsvId serviceId = serviceEntryIdFromQMessageFolderId(id);
       
  2067     CMsvEntry* pEntry = retrieveCMsvEntryAndPushToCleanupStack(folderId);
       
  2068     if (pEntry) {
       
  2069         if (pEntry->Entry().iMtm == KUidMsgTypePOP3) {
       
  2070             pEntry->SetEntryL(KMsvGlobalInBoxIndexEntryId);
       
  2071         } 
       
  2072         QMessageAccountId accountId(accountIdByServiceId(serviceId));
       
  2073         QMessageFolderId parentId;
       
  2074         QString name = QString::fromUtf16(pEntry->Entry().iDetails.Ptr(), pEntry->Entry().iDetails.Length());
       
  2075         folder = QMessageFolderPrivate::from(id, accountId, parentId, name, name);
       
  2076         releaseCMsvEntryAndPopFromCleanupStack(pEntry);
       
  2077     }
       
  2078     
       
  2079     return folder;
       
  2080 }
       
  2081 
       
  2082 QMessage CMTMEngine::message(const QMessageId& id) const
       
  2083 {
       
  2084     if (!iSessionReady)
       
  2085         return QMessage();
       
  2086     
       
  2087     QMessage message;
       
  2088     TRAPD(err, message = messageL(id));
       
  2089     Q_UNUSED(err)
       
  2090 
       
  2091     return message;
       
  2092 }
       
  2093 
       
  2094 QMessage CMTMEngine::messageL(const QMessageId& id) const
       
  2095 {
       
  2096     QMessage message;
       
  2097 
       
  2098     long int messageId = SymbianHelpers::stripIdPrefix(id.toString()).toLong();
       
  2099     CMsvEntry* pEntry = ipMsvSession->GetEntryL(messageId);
       
  2100     CleanupStack::PushL(pEntry);
       
  2101     
       
  2102     if (pEntry->Entry().iMtm == KUidMsgTypeSMS) {
       
  2103         if (ipSmsMtm)
       
  2104             message = smsMessageL(*pEntry, messageId);
       
  2105     } else if (pEntry->Entry().iMtm == KUidMsgTypeMultimedia) {
       
  2106         if (ipMmsMtm)
       
  2107             message = mmsMessageL(*pEntry, messageId);
       
  2108     }  else if (pEntry->Entry().iMtm == KUidMsgTypeSMTP) {
       
  2109         if (ipSmtpMtm)
       
  2110             message = emailMessageL(*pEntry, messageId);
       
  2111     } else if (pEntry->Entry().iMtm == KUidMsgTypeIMAP4) {
       
  2112         if (ipImap4Mtm)
       
  2113             message = emailMessageL(*pEntry, messageId);
       
  2114     } else if (pEntry->Entry().iMtm == KUidMsgTypePOP3) {
       
  2115         if (ipPop3Mtm)
       
  2116             message = emailMessageL(*pEntry, messageId);
       
  2117     }
       
  2118 
       
  2119     CleanupStack::PopAndDestroy(pEntry);
       
  2120 
       
  2121     QMessagePrivate* privateMessage = QMessagePrivate::implementation(message);
       
  2122     privateMessage->_id = id; 
       
  2123     privateMessage->_modified = false;
       
  2124     
       
  2125     return message;
       
  2126 }
       
  2127 
       
  2128 bool CMTMEngine::storeMMS(QMessage &message)
       
  2129 {
       
  2130     if (!iSessionReady) {
       
  2131         return false;
       
  2132     }
       
  2133     
       
  2134     TRAPD(err, storeMMSL(message));
       
  2135     if (err != KErrNone) {
       
  2136         return false;
       
  2137     }
       
  2138     
       
  2139     return true;
       
  2140 }
       
  2141 
       
  2142 bool CMTMEngine::sendMMS(QMessage &message)
       
  2143 {
       
  2144     if (!iSessionReady) {
       
  2145         return false;
       
  2146     }
       
  2147 
       
  2148     TRAPD(err, sendMMSL(message));
       
  2149     if (err != KErrNone) {
       
  2150         return false;
       
  2151     }
       
  2152     
       
  2153     return true;
       
  2154 }
       
  2155 
       
  2156 bool CMTMEngine::storeEmail(QMessage &message)
       
  2157 {
       
  2158     if (!iSessionReady) {
       
  2159         return false;
       
  2160     }
       
  2161     
       
  2162     TRAPD(err, storeEmailL(message));
       
  2163     if (err != KErrNone) {
       
  2164         return false;
       
  2165     }
       
  2166     
       
  2167     return true;
       
  2168 }
       
  2169 
       
  2170 bool CMTMEngine::sendEmail(QMessage &message)
       
  2171 {
       
  2172     if (!iSessionReady) {
       
  2173         return false;
       
  2174     }
       
  2175 
       
  2176     TRAPD(err, sendEmailL(message));
       
  2177     if (err != KErrNone) {
       
  2178         return false;
       
  2179     }
       
  2180     
       
  2181     return true;
       
  2182 }
       
  2183 
       
  2184 bool CMTMEngine::storeSMS(QMessage &message)
       
  2185 {
       
  2186     if (!iSessionReady)
       
  2187         return false;
       
  2188     
       
  2189     TRAPD(err, storeSMSL(message));
       
  2190     if (err != KErrNone) {
       
  2191         return false;
       
  2192     }
       
  2193     
       
  2194     return true;
       
  2195 }
       
  2196 
       
  2197 void CMTMEngine::storeSMSL(QMessage &message)
       
  2198 {
       
  2199     if (!iSessionReady) {
       
  2200         User::Leave(KErrNotReady);
       
  2201     }
       
  2202     
       
  2203     TMsvId destinationFolderId;
       
  2204     if (message.parentFolderId().isValid()) {
       
  2205         destinationFolderId = folderIdFromQMessageFolderId(message.parentFolderId());
       
  2206     } else {
       
  2207         // parentFolderId was not defined for new Message
       
  2208         // => Message will be created into defined standard Folder (Default value is Drafts Folder)
       
  2209         destinationFolderId =  standardFolderId(message.standardFolder());
       
  2210     }
       
  2211     
       
  2212     // Switch current SMS MTM context to folder entry    
       
  2213     ipSmsMtm->SwitchCurrentEntryL(destinationFolderId);
       
  2214 
       
  2215     // Create a new SMS message entry as a child of the current context
       
  2216     //
       
  2217     // Note: CreateMessageL sets following values to new message entry:
       
  2218     //       entry.iType = KUidMsvMessageEntry;
       
  2219     //       entry.iRelatedId = <ID of the current SMS service>;
       
  2220     //       entry.iServiceId = KMsvLocalServiceIndexEntryId;
       
  2221     //       entry.iMtm = <SMS Message Type UID>;
       
  2222     //       entry.SetVisible(EFalse);
       
  2223     //       entry.SetInPreparation(ETrue);
       
  2224     //       entry.iDate.UniversalTime(); <= Not set in older platforms
       
  2225     //
       
  2226     // Note: CreateMessageL automatically creates SMS header
       
  2227     //       that contains default service settings & default
       
  2228     //       service center address
       
  2229     //
       
  2230     // Note: CreateMessageL switches current SMS MTM context to
       
  2231     //       a new SMS message context
       
  2232     ipSmsMtm->CreateMessageL(KUidMsgTypeSMS.iUid);
       
  2233     
       
  2234     // Get the current context (new message context)
       
  2235     CMsvEntry& newMessageContext = ipSmsMtm->Entry();
       
  2236     
       
  2237     // Copy entry values from the new message context index entry
       
  2238     TMsvEntry entry = newMessageContext.Entry();
       
  2239     
       
  2240     // Set priority values to message entry
       
  2241     switch (message.priority()) {
       
  2242     case QMessage::HighPriority:
       
  2243         entry.SetPriority(EMsvHighPriority);
       
  2244         break;
       
  2245     case QMessage::NormalPriority:
       
  2246         entry.SetPriority(EMsvMediumPriority);
       
  2247         break;
       
  2248     case QMessage::LowPriority:
       
  2249         entry.SetPriority(EMsvLowPriority);
       
  2250         break;
       
  2251     }
       
  2252     
       
  2253     // Set message read status to message entry
       
  2254     if (message.status() & QMessage::Read) { 
       
  2255         entry.SetUnread(false);
       
  2256         entry.SetNew(false);
       
  2257     } else {
       
  2258         entry.SetUnread(true);
       
  2259         entry.SetNew(true);
       
  2260     }
       
  2261     
       
  2262     // Set first message addressee to message entry
       
  2263     // and all message addressees to SMS message
       
  2264     QList<QMessageAddress> list(message.to());
       
  2265     if (!list.empty()){
       
  2266         TPtrC16 receiver(KNullDesC);
       
  2267         QString qreceiver;
       
  2268         for (int i = 0; i < list.size(); ++i) {
       
  2269             qreceiver = list.at(i).addressee();
       
  2270             receiver.Set(reinterpret_cast<const TUint16*>(qreceiver.utf16()));
       
  2271             if (i == 0) {
       
  2272                 // Set addressee to message entry 
       
  2273                 entry.iDetails.Set(receiver);
       
  2274             }
       
  2275             // Add addressee to SMS message
       
  2276             ipSmsMtm->AddAddresseeL(receiver); 
       
  2277         }
       
  2278     }
       
  2279     
       
  2280     // Set body to message entry and SMS message
       
  2281     QString body = message.textContent();
       
  2282     if (!body.isEmpty()){
       
  2283         TPtrC16 msg(reinterpret_cast<const TUint16*>(body.utf16()));
       
  2284 
       
  2285         // Set body to message entry 
       
  2286         entry.iDescription.Set(msg);
       
  2287 
       
  2288         // Set body to SMS message
       
  2289         CRichText& body = ipSmsMtm->Body();
       
  2290         body.Reset();
       
  2291         body.InsertL(0, msg);
       
  2292     }
       
  2293 
       
  2294     // Set date to message entry
       
  2295     if (!message.receivedDate().isNull() || !message.date().isNull()) {
       
  2296         if (!message.date().isNull()) {
       
  2297             entry.iDate = qDateTimeToSymbianTTime(message.date());
       
  2298         } else {
       
  2299             entry.iDate = qDateTimeToSymbianTTime(message.receivedDate());
       
  2300         }
       
  2301     }
       
  2302     
       
  2303     // Set new message's context's index entry to the specified values.
       
  2304     // <=> Changes are set into cache only
       
  2305     newMessageContext.ChangeL(entry);
       
  2306     
       
  2307     // Commit cached changes to the storage
       
  2308     // Note: SaveMessageL sets following values to message entry:
       
  2309     //       entry.SetVisible(ETrue);
       
  2310     //       entry.SetInPreparation(EFalse);
       
  2311     ipSmsMtm->SaveMessageL();  
       
  2312 
       
  2313     // Get message id from new SMS message index entry 
       
  2314     QMessagePrivate* privateMessage = QMessagePrivate::implementation(message);
       
  2315     privateMessage->_id = QMessageId(SymbianHelpers::addIdPrefix(QString::number(entry.Id()), SymbianHelpers::EngineTypeMTM));
       
  2316 }
       
  2317 
       
  2318 bool CMTMEngine::sendSMS(QMessage &message)
       
  2319 {
       
  2320     if (!iSessionReady) {
       
  2321         return false;
       
  2322     }
       
  2323     
       
  2324     TRAPD(err, sendSMSL(message));
       
  2325     if (err != KErrNone) {
       
  2326         return false;
       
  2327     }
       
  2328     
       
  2329     return true;
       
  2330 }
       
  2331 
       
  2332 bool CMTMEngine::validateSMS()
       
  2333 {
       
  2334     
       
  2335     // Validate SMS body.
       
  2336     TMsvPartList result(KMsvMessagePartNone);
       
  2337     result = ipSmsMtm->ValidateMessage(KMsvMessagePartBody);
       
  2338     if (result != KMsvMessagePartNone ) {
       
  2339         return false;
       
  2340     }
       
  2341     
       
  2342     // Validate SMS recipient
       
  2343     result = ipSmsMtm->ValidateMessage(KMsvMessagePartRecipient);
       
  2344     if ( result != KMsvMessagePartNone ) {
       
  2345         return false;
       
  2346     }
       
  2347     
       
  2348     return true;
       
  2349 }
       
  2350 
       
  2351 void CMTMEngine::sendSMSL(QMessage &message)
       
  2352 {
       
  2353     if (!iSessionReady) {
       
  2354         User::Leave(KErrNotReady);
       
  2355     }
       
  2356 
       
  2357     if (!message.id().isValid()) {
       
  2358         QMessagePrivate::setStandardFolder(message, QMessage::DraftsFolder);
       
  2359         storeSMSL(message);
       
  2360     }
       
  2361 
       
  2362     long int messageId = SymbianHelpers::stripIdPrefix(message.id().toString()).toLong();
       
  2363     if (messageId == 0) {
       
  2364         User::Leave(KErrNotReady);
       
  2365     }
       
  2366 
       
  2367     // Switch current SMS MTM context to message entry    
       
  2368     ipSmsMtm->SwitchCurrentEntryL(messageId);
       
  2369     
       
  2370     // Load the cache with the message data 
       
  2371     ipSmsMtm->LoadMessageL(); 
       
  2372     
       
  2373     // Copy entry values from the message context index entry
       
  2374     TMsvEntry entry = ipSmsMtm->Entry().Entry();    
       
  2375 
       
  2376     // Update date to UniversalTime
       
  2377     // <=> Date field is used to control message send time
       
  2378     entry.iDate.UniversalTime();
       
  2379 
       
  2380     // Update message sending state
       
  2381     entry.SetSendingState(KMsvSendStateWaiting);
       
  2382 
       
  2383     // Set SMS Service & delivery settings to the SMS header
       
  2384     CSmsHeader& smsHeader = ipSmsMtm->SmsHeader();
       
  2385     CSmsSettings* pSmsSettings = CSmsSettings::NewL();
       
  2386     CleanupStack::PushL(pSmsSettings);
       
  2387  
       
  2388     pSmsSettings->CopyL(ipSmsMtm->ServiceSettings());
       
  2389     pSmsSettings->SetDelivery(ESmsDeliveryImmediately);
       
  2390     pSmsSettings->SetDeliveryReport(EFalse);
       
  2391     smsHeader.SetSmsSettingsL(*pSmsSettings);
       
  2392  
       
  2393     if (smsHeader.Message().ServiceCenterAddress().Length() == 0) {
       
  2394         CSmsSettings* pSmsServiceSettings = &(ipSmsMtm->ServiceSettings());
       
  2395         if (!pSmsServiceSettings->ServiceCenterCount()) {
       
  2396 #ifndef Q_CC_NOKIAX86
       
  2397             User::Leave(KErrNotReady);
       
  2398 #endif
       
  2399         } else {
       
  2400             CSmsNumber* pSmsCenterNumber = CSmsNumber::NewL();
       
  2401             CleanupStack::PushL(pSmsCenterNumber);
       
  2402             pSmsCenterNumber->SetAddressL((pSmsServiceSettings->GetServiceCenter(pSmsServiceSettings->DefaultServiceCenter())).Address());
       
  2403             smsHeader.Message().SetServiceCenterAddressL(pSmsCenterNumber->Address());
       
  2404             CleanupStack::PopAndDestroy(pSmsCenterNumber);
       
  2405         }
       
  2406     }
       
  2407  
       
  2408     CleanupStack::PopAndDestroy(pSmsSettings);    
       
  2409 
       
  2410     // Update message's context's index entry to the new values.
       
  2411     // <=> Changes are set into cache only
       
  2412     ipSmsMtm->Entry().ChangeL(entry);
       
  2413     
       
  2414     // Commit cached changes to the storage
       
  2415     ipSmsMtm->SaveMessageL();
       
  2416     
       
  2417     if (validateSMS()) {
       
  2418         // Switch current SMS MTM context to SMS message parent folder entry
       
  2419         ipSmsMtm->SwitchCurrentEntryL(ipSmsMtm->Entry().Entry().Parent());
       
  2420         
       
  2421         QMTMWait mtmWait;
       
  2422     
       
  2423         // Move SMS Message to Outbox
       
  2424         CMsvOperation* pMsvOperation = ipSmsMtm->Entry().MoveL(messageId,
       
  2425                                                                KMsvGlobalOutBoxIndexEntryId,
       
  2426                                                                mtmWait.iStatus);
       
  2427         mtmWait.start();
       
  2428         delete pMsvOperation;
       
  2429         
       
  2430         // Send SMS Message
       
  2431         CMsvEntrySelection* pMsvEntrySelection = new(ELeave) CMsvEntrySelection;
       
  2432         CleanupStack::PushL(pMsvEntrySelection);
       
  2433     
       
  2434         // Add SMS Message Id to selection
       
  2435         pMsvEntrySelection->AppendL(messageId); 
       
  2436      
       
  2437         // Add selection (containing SMS Message Id) to task scheduler
       
  2438         TBuf8<1> dummyParams;
       
  2439         pMsvOperation = ipSmsMtm->InvokeAsyncFunctionL(ESmsMtmCommandScheduleCopy,
       
  2440                                                        *pMsvEntrySelection,
       
  2441                                                        dummyParams,
       
  2442                                                        mtmWait.iStatus);
       
  2443         mtmWait.start();
       
  2444         delete pMsvOperation;    
       
  2445      
       
  2446         CleanupStack::PopAndDestroy(pMsvEntrySelection);    
       
  2447     } else {
       
  2448         User::Leave(KErrCorrupt);
       
  2449     }
       
  2450 }
       
  2451 
       
  2452 void CMTMEngine::storeMMSL(QMessage &message)
       
  2453 {
       
  2454     if (!iSessionReady) {
       
  2455         User::Leave(KErrNotReady);
       
  2456     }
       
  2457     
       
  2458     TMsvId destinationFolderId;
       
  2459     if (message.parentFolderId().isValid()) {
       
  2460         destinationFolderId = folderIdFromQMessageFolderId(message.parentFolderId());
       
  2461     } else {
       
  2462         // parentFolderId was not defined for new Message
       
  2463         // => Message will be created into defined standard Folder (Default value is Drafts Folder)
       
  2464         destinationFolderId =  standardFolderId(message.standardFolder());
       
  2465     }
       
  2466     
       
  2467     // Switch current MMS MTM context to folder entry    
       
  2468     ipMmsMtm->SwitchCurrentEntryL(destinationFolderId);
       
  2469 
       
  2470     // Create a new MMS message entry as a child of the current context
       
  2471     // Note: CreateMessageL switches current MMS MTM context to
       
  2472     //       a new MMS message context
       
  2473     ipMmsMtm->CreateMessageL(ipMmsMtm->DefaultServiceL());    
       
  2474 
       
  2475     // Get the current context (new message context)
       
  2476     CMsvEntry& newMessageContext = ipMmsMtm->Entry();
       
  2477 
       
  2478     // Copy entry values from the new message context index entry
       
  2479     TMsvEntry entry = newMessageContext.Entry();
       
  2480 
       
  2481     // Add receivers
       
  2482     QList<QMessageAddress> list(message.to());
       
  2483     TPtrC16 receiver(KNullDesC);
       
  2484     QString qreceiver;
       
  2485     for (int i = 0; i < list.size(); ++i) {
       
  2486         qreceiver = list.at(i).addressee();
       
  2487         receiver.Set(reinterpret_cast<const TUint16*>(qreceiver.utf16()));
       
  2488         ipMmsMtm->AddAddresseeL(receiver); 
       
  2489         }
       
  2490     
       
  2491     // Set Subject
       
  2492     QString subject = message.subject();
       
  2493     TPtrC16 sbj(reinterpret_cast<const TUint16*>(subject.utf16()));
       
  2494     ipMmsMtm->SetSubjectL(sbj); 
       
  2495     
       
  2496     entry.SetInPreparation(EFalse); 
       
  2497     entry.SetVisible(ETrue);
       
  2498     
       
  2499     switch (message.priority()) {
       
  2500     case QMessage::HighPriority:
       
  2501         entry.SetPriority(EMsvHighPriority);
       
  2502         break;
       
  2503     case QMessage::NormalPriority:
       
  2504         entry.SetPriority(EMsvMediumPriority);
       
  2505         break;
       
  2506     case QMessage::LowPriority:
       
  2507         entry.SetPriority(EMsvLowPriority);
       
  2508         break;
       
  2509     }
       
  2510     if (message.status() & QMessage::Read) { 
       
  2511         entry.SetUnread(false);
       
  2512         entry.SetNew(false);
       
  2513     } else {
       
  2514         entry.SetUnread(true);
       
  2515         entry.SetNew(true);
       
  2516     }
       
  2517     
       
  2518     // Set new message's context's index entry to the specified values.
       
  2519     // <=> Changes are set into cache only
       
  2520     newMessageContext.ChangeL(entry);
       
  2521 
       
  2522     // Commit cached changes to the storage
       
  2523     ipMmsMtm->SaveMessageL();
       
  2524     
       
  2525     CMsvStore* store = ipMmsMtm->Entry().EditStoreL();    
       
  2526     CleanupStack::PushL(store); 
       
  2527     
       
  2528     // attachments.
       
  2529     QByteArray filePath;
       
  2530     QMessageContentContainerIdList contentIds = message.contentIds();
       
  2531     foreach (QMessageContentContainerId id, contentIds){
       
  2532         QMessageContentContainer container = message.find(id);
       
  2533         filePath = QMessageContentContainerPrivate::attachmentFilename(container);
       
  2534         QString body = container.textContent();
       
  2535         if (!filePath.isEmpty()) { // content is attachment
       
  2536             int last = filePath.lastIndexOf("/");
       
  2537             int count = filePath.count();
       
  2538             QByteArray name = filePath.right(count-last-1);
       
  2539             QString fileName = QString(name);
       
  2540             filePath.replace(QByteArray("/"), QByteArray("\\"));
       
  2541             QString temp_path = QString(filePath);
       
  2542             TPtrC16 attachmentPath(KNullDesC);
       
  2543             attachmentPath.Set(reinterpret_cast<const TUint16*>(temp_path.utf16()));
       
  2544             TFileName attachmentFile;
       
  2545             attachmentFile.Append(attachmentPath);    
       
  2546         
       
  2547             RFile attachment;    
       
  2548             User::LeaveIfError(attachment.Open(FsSession(),attachmentFile, EFileShareReadersOnly | EFileRead));    
       
  2549             CleanupClosePushL(attachment);  
       
  2550             
       
  2551             TInt fileSize;
       
  2552             attachment.Size(fileSize);
       
  2553             TInt maxFileSize = 600000;
       
  2554             if (fileSize > maxFileSize){
       
  2555                 return;
       
  2556             }
       
  2557             
       
  2558             HBufC8* pFileContent = HBufC8::NewL(fileSize);
       
  2559             TPtr8 fileContent(pFileContent->Des());
       
  2560             attachment.Read(fileContent);
       
  2561             attachment.Close();
       
  2562             CleanupStack::PushL(pFileContent);
       
  2563             RFile file2;
       
  2564             TFileName tempFileName;
       
  2565             RFs fileServer;
       
  2566             User::LeaveIfError(fileServer.Connect());
       
  2567             CleanupClosePushL(fileServer);
       
  2568             TInt err = file2.Temp(fileServer,iPath,tempFileName,EFileWrite);
       
  2569             if (err != KErrNone){
       
  2570                 return;
       
  2571             }
       
  2572             CleanupClosePushL(file2);
       
  2573             err = file2.Write(*pFileContent);
       
  2574             if (err != KErrNone){
       
  2575                 return;
       
  2576             }
       
  2577             file2.Close();
       
  2578             User::LeaveIfError(file2.Open(FsSession(),tempFileName, EFileShareAny|EFileRead));
       
  2579             // Mime header    
       
  2580             CMsvMimeHeaders* mimeHeaders = CMsvMimeHeaders::NewL();    
       
  2581             CleanupStack::PushL(mimeHeaders); 
       
  2582             TPtrC16 suggestedName(reinterpret_cast<const TUint16*>(fileName.utf16()));
       
  2583             mimeHeaders->SetSuggestedFilenameL(suggestedName);     
       
  2584             // Represents a single attachment and information about the attachment    
       
  2585             CMsvAttachment* attaInfo = CMsvAttachment::NewL(CMsvAttachment::EMsvFile);    
       
  2586             CleanupStack::PushL(attaInfo); 
       
  2587             
       
  2588             // Mime Type    
       
  2589             QByteArray content = container.contentType();
       
  2590             if (content.isEmpty()){
       
  2591                 RApaLsSession session;
       
  2592                 //TPtrC16 filePtr(reinterpret_cast<const TUint16*>(fileString.utf16()));
       
  2593                 TBuf8<20> fileType;
       
  2594                 if(session.Connect() == KErrNone){                        
       
  2595                     TDataRecognitionResult fileDataType;                     
       
  2596                     session.RecognizeData(tempFileName, *pFileContent, *&fileDataType);                                         
       
  2597                     fileType.Copy(fileDataType.iDataType.Des8());
       
  2598                     content = QByteArray((const char*)fileType.Ptr(), fileType.Length());
       
  2599                     session.Close();                
       
  2600                 }
       
  2601             }
       
  2602             else{
       
  2603                 content.append("/");
       
  2604                 content.append(container.contentSubType());       
       
  2605             }
       
  2606            
       
  2607             QString mime = QString(content);
       
  2608             TPtrC16 mType(reinterpret_cast<const TUint16*>(mime.utf16()));
       
  2609             HBufC8* mimeType = CnvUtfConverter::ConvertFromUnicodeToUtf8L(mType);
       
  2610             
       
  2611             TMsvAttachmentId attachId = KMsvNullIndexEntryId;        
       
  2612             ipMmsMtm->CreateAttachment2L(*store, file2, *mimeType, *mimeHeaders, attaInfo, attachId);
       
  2613             store->CommitL();
       
  2614             file2.Close();
       
  2615             
       
  2616             CleanupStack::Pop(attaInfo);    
       
  2617             CleanupStack::PopAndDestroy(mimeHeaders);  
       
  2618             CleanupStack::Pop(&file2);
       
  2619             CleanupStack::PopAndDestroy(&fileServer);
       
  2620             CleanupStack::PopAndDestroy(pFileContent);
       
  2621             CleanupStack::PopAndDestroy(); //attachment
       
  2622         }
       
  2623         else if (!body.isEmpty()) { // Add body
       
  2624             TPtrC16 msg(reinterpret_cast<const TUint16*>(body.utf16()));
       
  2625             TMsvAttachmentId attachmentid = KMsvNullIndexEntryId;
       
  2626             TFileName bodyFile( _L("body.txt") );
       
  2627             ipMmsMtm->CreateTextAttachmentL(*store, attachmentid, msg, bodyFile, ETrue); 
       
  2628             store->CommitL();
       
  2629         }
       
  2630 
       
  2631     }
       
  2632     QString messageBody = message.textContent();
       
  2633     if (!messageBody.isEmpty()) { // no contents, only body text
       
  2634         TPtrC16 msg(reinterpret_cast<const TUint16*>(messageBody.utf16()));
       
  2635         TMsvAttachmentId attachmentid = KMsvNullIndexEntryId;
       
  2636         TFileName bodyFile( _L("body.txt") );
       
  2637         ipMmsMtm->CreateTextAttachmentL(*store, attachmentid, msg, bodyFile, ETrue); 
       
  2638         store->CommitL();
       
  2639     }
       
  2640          
       
  2641     CleanupStack::PopAndDestroy(); // store    
       
  2642     
       
  2643     QMessagePrivate* privateMessage = QMessagePrivate::implementation(message);
       
  2644     privateMessage->_id = QMessageId(SymbianHelpers::addIdPrefix(QString::number(entry.Id()),SymbianHelpers::EngineTypeMTM));
       
  2645     // Save the changes
       
  2646     ipMmsMtm->SaveMessageL();
       
  2647     
       
  2648     if (!message.receivedDate().isNull() || !message.date().isNull()) {
       
  2649         // Change the date to given date
       
  2650         CMsvEntry* pEntry = ipMsvSession->GetEntryL(entry.Id());
       
  2651         CleanupStack::PushL(pEntry);
       
  2652         TMsvEntry changedEntry = pEntry->Entry();
       
  2653         if (!message.date().isNull()) {
       
  2654             changedEntry.iDate = qDateTimeToSymbianTTime(message.date());
       
  2655         } else {
       
  2656             changedEntry.iDate = qDateTimeToSymbianTTime(message.receivedDate());
       
  2657         }
       
  2658         pEntry->ChangeL(changedEntry);
       
  2659         CleanupStack::PopAndDestroy(pEntry);
       
  2660     }
       
  2661 }
       
  2662 
       
  2663 void CMTMEngine::updateSMSL(QMessage &message)
       
  2664 {
       
  2665     if (!iSessionReady) {
       
  2666         User::Leave(KErrNotReady);
       
  2667     }
       
  2668     
       
  2669     QMessageId id = message.id();
       
  2670     long int messageId = SymbianHelpers::stripIdPrefix(id.toString()).toLong();
       
  2671     if (messageId == 0)
       
  2672         return;
       
  2673     
       
  2674     CMsvEntry* entry = ipMsvSession->GetEntryL(messageId);
       
  2675     CleanupStack::PushL(entry);
       
  2676     
       
  2677     ipSmsMtm->SwitchCurrentEntryL(messageId);
       
  2678     ipSmsMtm->LoadMessageL();
       
  2679     
       
  2680     TMsvEntry tEntry = ipSmsMtm->Entry().Entry();
       
  2681     switch (message.priority()) {
       
  2682     case QMessage::HighPriority:
       
  2683         tEntry.SetPriority(EMsvHighPriority);
       
  2684         break;
       
  2685     case QMessage::NormalPriority:
       
  2686         tEntry.SetPriority(EMsvMediumPriority);
       
  2687         break;
       
  2688     case QMessage::LowPriority:
       
  2689         tEntry.SetPriority(EMsvLowPriority);
       
  2690         break;            
       
  2691     }
       
  2692     if (message.status() & QMessage::Read) { 
       
  2693         tEntry.SetUnread(false);
       
  2694         tEntry.SetNew(false);
       
  2695     } else {
       
  2696         tEntry.SetUnread(true);
       
  2697         tEntry.SetNew(true);
       
  2698     }
       
  2699     ipSmsMtm->Entry().ChangeL(tEntry); 
       
  2700     // Save the changes    
       
  2701     ipSmsMtm->SaveMessageL();
       
  2702     
       
  2703     QList<QMessageAddress> list(message.to());
       
  2704     if (!list.empty()){
       
  2705         TPtrC16 receiver(KNullDesC);
       
  2706         QString qreceiver;
       
  2707         for (int i = 0; i < list.size(); ++i) {
       
  2708             qreceiver = list.at(i).addressee();
       
  2709             receiver.Set(reinterpret_cast<const TUint16*>(qreceiver.utf16()));
       
  2710             ipSmsMtm->AddAddresseeL(receiver); 
       
  2711             ipSmsMtm->SaveMessageL();
       
  2712         }
       
  2713     }
       
  2714     
       
  2715     CMsvStore* store = ipSmsMtm->Entry().EditStoreL(); 
       
  2716     CleanupStack::PushL(store);
       
  2717     
       
  2718     QString body = message.textContent();
       
  2719     if (!body.isEmpty()){
       
  2720         TPtrC16 msg(reinterpret_cast<const TUint16*>(body.utf16()));
       
  2721         if (!ipRichText) {
       
  2722             ipCharFormatLayer = CCharFormatLayer::NewL();
       
  2723             ipParaFormatLayer = CParaFormatLayer::NewL();
       
  2724             ipRichText=CRichText::NewL(ipParaFormatLayer,ipCharFormatLayer);
       
  2725         }
       
  2726         ipRichText->Reset();
       
  2727         ipRichText->InsertL(0, msg);
       
  2728         store->StoreBodyTextL(*ipRichText);
       
  2729         store->CommitL();
       
  2730     } 
       
  2731     
       
  2732     CleanupStack::PopAndDestroy(2); // store, entry
       
  2733     
       
  2734     if (!message.receivedDate().isNull() || !message.date().isNull()) {
       
  2735         // Change the date to given date
       
  2736         CMsvEntry* pEntry = ipMsvSession->GetEntryL(messageId);
       
  2737         CleanupStack::PushL(pEntry);
       
  2738         TMsvEntry changedEntry = pEntry->Entry();
       
  2739         if (!message.date().isNull()) {
       
  2740             changedEntry.iDate = qDateTimeToSymbianTTime(message.date());
       
  2741         } else {
       
  2742             changedEntry.iDate = qDateTimeToSymbianTTime(message.receivedDate());
       
  2743         }
       
  2744         pEntry->ChangeL(changedEntry);
       
  2745         CleanupStack::PopAndDestroy(pEntry);
       
  2746     }
       
  2747 }
       
  2748 
       
  2749 void CMTMEngine::updateMMSL(QMessage &message)
       
  2750 {
       
  2751     if (!iSessionReady) {
       
  2752         User::Leave(KErrNotReady);
       
  2753     }
       
  2754     
       
  2755     QMessageId id = message.id();
       
  2756     long int messageId = SymbianHelpers::stripIdPrefix(id.toString()).toLong();
       
  2757     if (messageId == 0)
       
  2758         return;
       
  2759     
       
  2760     ipMmsMtm->SwitchCurrentEntryL(messageId);
       
  2761     ipMmsMtm->LoadMessageL();
       
  2762             
       
  2763     // Add receivers
       
  2764     QList<QMessageAddress> list(message.to());
       
  2765     if (!list.empty()){
       
  2766         TPtrC16 receiver(KNullDesC);
       
  2767         QString qreceiver;
       
  2768         for (int i = 0; i < list.size(); ++i) {
       
  2769             qreceiver = list.at(i).addressee();
       
  2770             receiver.Set(reinterpret_cast<const TUint16*>(qreceiver.utf16()));
       
  2771             ipMmsMtm->AddAddresseeL(receiver); 
       
  2772             }
       
  2773     }
       
  2774     
       
  2775     // Set Subject
       
  2776     QString subject = message.subject();
       
  2777     if (!subject.isEmpty()){
       
  2778         TPtrC16 sbj(reinterpret_cast<const TUint16*>(subject.utf16()));
       
  2779         ipMmsMtm->SetSubjectL(sbj); 
       
  2780     }
       
  2781         
       
  2782     TMsvEntry ent = ipMmsMtm->Entry().Entry();       
       
  2783     ent.SetInPreparation(EFalse); 
       
  2784     ent.SetVisible(ETrue);    
       
  2785     
       
  2786     switch (message.priority()) {
       
  2787     case QMessage::HighPriority:
       
  2788         ent.SetPriority(EMsvHighPriority);
       
  2789         break;
       
  2790     case QMessage::NormalPriority:
       
  2791         ent.SetPriority(EMsvMediumPriority);
       
  2792         break;
       
  2793     case QMessage::LowPriority:
       
  2794         ent.SetPriority(EMsvLowPriority);
       
  2795         break;
       
  2796     }
       
  2797     if (message.status() & QMessage::Read) { 
       
  2798         ent.SetUnread(false);
       
  2799         ent.SetNew(false);
       
  2800     } else {
       
  2801         ent.SetUnread(true);
       
  2802         ent.SetNew(true);
       
  2803     }
       
  2804     ipMmsMtm->Entry().ChangeL(ent); 
       
  2805     // Save the changes    
       
  2806     ipMmsMtm->SaveMessageL();
       
  2807     
       
  2808     CMsvStore* store = ipMmsMtm->Entry().EditStoreL();    
       
  2809     CleanupStack::PushL(store); 
       
  2810     
       
  2811     // attachments.
       
  2812     QByteArray filePath;
       
  2813     QMessageContentContainerIdList contentIds = message.contentIds();
       
  2814     foreach (QMessageContentContainerId id, contentIds){
       
  2815         QMessageContentContainer container = message.find(id);
       
  2816         QMessageContentContainerPrivate* pPrivateContainer = QMessageContentContainerPrivate::implementation(container);
       
  2817         filePath = QMessageContentContainerPrivate::attachmentFilename(container);
       
  2818         if (!filePath.isEmpty()) { // content is attachment
       
  2819             int last = filePath.lastIndexOf("/");
       
  2820             int count = filePath.count();
       
  2821             QByteArray name = filePath.right(count-last-1);
       
  2822             QString fileName = QString(name);
       
  2823             filePath.replace(QByteArray("/"), QByteArray("\\"));
       
  2824             QString temp_path = QString(filePath);
       
  2825             TPtrC16 attachmentPath(KNullDesC);
       
  2826             attachmentPath.Set(reinterpret_cast<const TUint16*>(temp_path.utf16()));
       
  2827             TFileName attachmentFile;
       
  2828             attachmentFile.Append(attachmentPath);    
       
  2829         
       
  2830             RFile attachment;    
       
  2831             User::LeaveIfError(attachment.Open(FsSession(),attachmentFile, EFileShareReadersOnly | EFileRead));    
       
  2832             CleanupClosePushL(attachment);  
       
  2833             
       
  2834             TInt fileSize;
       
  2835             attachment.Size(fileSize);
       
  2836             TInt maxFileSize = 600000;
       
  2837             if (fileSize > maxFileSize){
       
  2838                 return;
       
  2839             }
       
  2840             
       
  2841             HBufC8* pFileContent = HBufC8::NewL(fileSize);
       
  2842             TPtr8 fileContent(pFileContent->Des());
       
  2843             attachment.Read(fileContent);
       
  2844             attachment.Close();
       
  2845             CleanupStack::PushL(pFileContent);
       
  2846             RFile file2;
       
  2847             TFileName tempFileName;
       
  2848             RFs fileServer;
       
  2849             User::LeaveIfError(fileServer.Connect());
       
  2850             CleanupClosePushL(fileServer);
       
  2851             TInt err = file2.Temp(fileServer,iPath,tempFileName,EFileWrite);
       
  2852             if (err != KErrNone){
       
  2853                 return;
       
  2854             }
       
  2855             CleanupClosePushL(file2);
       
  2856             err = file2.Write(*pFileContent);
       
  2857             if (err != KErrNone){
       
  2858                 return;
       
  2859             }
       
  2860             file2.Close();
       
  2861             User::LeaveIfError(file2.Open(FsSession(),tempFileName, EFileShareAny|EFileRead));
       
  2862             // Mime header    
       
  2863             CMsvMimeHeaders* mimeHeaders = CMsvMimeHeaders::NewL();    
       
  2864             CleanupStack::PushL(mimeHeaders); 
       
  2865             TPtrC16 suggestedName(reinterpret_cast<const TUint16*>(fileName.utf16()));
       
  2866             mimeHeaders->SetSuggestedFilenameL(suggestedName);     
       
  2867             // Represents a single attachment and information about the attachment    
       
  2868             CMsvAttachment* attaInfo = CMsvAttachment::NewL(CMsvAttachment::EMsvFile);    
       
  2869             CleanupStack::PushL(attaInfo); 
       
  2870             
       
  2871             // Mime Type    
       
  2872             QByteArray content = container.contentType();
       
  2873             if (content.isEmpty()){
       
  2874                 RApaLsSession session;
       
  2875                 TBuf8<20> fileType;
       
  2876                 if(session.Connect() == KErrNone){                        
       
  2877                     TDataRecognitionResult fileDataType;                     
       
  2878                     session.RecognizeData(tempFileName, *pFileContent, *&fileDataType);                                         
       
  2879                     fileType.Copy(fileDataType.iDataType.Des8());
       
  2880                     content = QByteArray((const char*)fileType.Ptr(), fileType.Length());
       
  2881                     session.Close();                
       
  2882                 }
       
  2883             }
       
  2884             else{
       
  2885                 content.append("/");
       
  2886                 content.append(container.contentSubType());       
       
  2887             }       
       
  2888             QString mime = QString(content);
       
  2889             TPtrC16 mType(reinterpret_cast<const TUint16*>(mime.utf16()));
       
  2890             HBufC8* mimeType = CnvUtfConverter::ConvertFromUnicodeToUtf8L(mType);
       
  2891             
       
  2892             TMsvAttachmentId attachId = KMsvNullIndexEntryId;        
       
  2893             ipMmsMtm->CreateAttachment2L(*store, file2, *mimeType, *mimeHeaders, attaInfo, attachId);
       
  2894             store->CommitL();
       
  2895             file2.Close();
       
  2896             
       
  2897             CleanupStack::Pop(attaInfo);    
       
  2898             CleanupStack::PopAndDestroy(mimeHeaders);  
       
  2899             CleanupStack::Pop(&file2);
       
  2900             CleanupStack::PopAndDestroy(&fileServer);
       
  2901             CleanupStack::PopAndDestroy(pFileContent);
       
  2902             CleanupStack::PopAndDestroy(); //attachment
       
  2903         }
       
  2904         else if (pPrivateContainer->_id == message.bodyId()) { // content is body text
       
  2905             QString body = container.textContent();
       
  2906             TPtrC16 msg(reinterpret_cast<const TUint16*>(body.utf16()));
       
  2907             TMsvAttachmentId attachmentid = KMsvNullIndexEntryId;
       
  2908             TFileName bodyFile( _L("body.txt") );
       
  2909             ipMmsMtm->CreateTextAttachmentL(*store, attachmentid, msg, bodyFile, ETrue); 
       
  2910             store->CommitL();
       
  2911         }
       
  2912     }
       
  2913     
       
  2914     QString messageBody = message.textContent();
       
  2915     if (!messageBody.isEmpty()) { // no contents, only body text
       
  2916         TPtrC16 msg(reinterpret_cast<const TUint16*>(messageBody.utf16()));
       
  2917         TMsvAttachmentId attachmentid = KMsvNullIndexEntryId;
       
  2918         TFileName bodyFile( _L("body.txt") );
       
  2919         ipMmsMtm->CreateTextAttachmentL(*store, attachmentid, msg, bodyFile, ETrue); 
       
  2920         store->CommitL();
       
  2921     }
       
  2922         
       
  2923     CleanupStack::PopAndDestroy(); // store    
       
  2924     // Save the changes
       
  2925     ipMmsMtm->SaveMessageL();
       
  2926     
       
  2927     if (!message.receivedDate().isNull() || !message.date().isNull()) {
       
  2928         // Change the date to given date
       
  2929         CMsvEntry* pEntry = ipMsvSession->GetEntryL(messageId);
       
  2930         CleanupStack::PushL(pEntry);
       
  2931         TMsvEntry changedEntry = pEntry->Entry();
       
  2932         if (!message.date().isNull()) {
       
  2933             changedEntry.iDate = qDateTimeToSymbianTTime(message.date());
       
  2934         } else {
       
  2935             changedEntry.iDate = qDateTimeToSymbianTTime(message.receivedDate());
       
  2936         }
       
  2937         pEntry->ChangeL(changedEntry);
       
  2938         CleanupStack::PopAndDestroy(pEntry);
       
  2939     }
       
  2940 }
       
  2941 
       
  2942 void CMTMEngine::updateEmailL(QMessage &message)
       
  2943 {
       
  2944     if (!iSessionReady) {
       
  2945         User::Leave(KErrNotReady);
       
  2946     }
       
  2947 
       
  2948     QMessageId id = message.id();
       
  2949     long int messageId = SymbianHelpers::stripIdPrefix(id.toString()).toLong();
       
  2950     if (messageId == 0)
       
  2951         return;
       
  2952     
       
  2953     CMsvEntry* pEntry = ipMsvSession->GetEntryL(messageId);
       
  2954     TUid mtmUid = pEntry->Entry().iMtm;
       
  2955     delete pEntry;
       
  2956     
       
  2957     TMsvEntry msvEntry;
       
  2958     if (mtmUid == KUidMsgTypeSMTP) {
       
  2959         ipSmtpMtm->SwitchCurrentEntryL(messageId);
       
  2960         ipSmtpMtm->LoadMessageL();
       
  2961         msvEntry = ipSmtpMtm->Entry().Entry();
       
  2962     } else if (mtmUid == KUidMsgTypePOP3) {
       
  2963         ipPop3Mtm->SwitchCurrentEntryL(messageId);
       
  2964         ipPop3Mtm->LoadMessageL();
       
  2965         msvEntry = ipPop3Mtm->Entry().Entry();
       
  2966     } else if (mtmUid == KUidMsgTypeIMAP4) {
       
  2967         ipImap4Mtm->SwitchCurrentEntryL(messageId);
       
  2968         ipImap4Mtm->LoadMessageL();
       
  2969         msvEntry = ipImap4Mtm->Entry().Entry();
       
  2970     }
       
  2971 
       
  2972     switch (message.priority()) {
       
  2973     case QMessage::HighPriority:
       
  2974         msvEntry.SetPriority(EMsvHighPriority);
       
  2975         break;
       
  2976     case QMessage::NormalPriority:
       
  2977         msvEntry.SetPriority(EMsvMediumPriority);
       
  2978         break;
       
  2979     case QMessage::LowPriority:
       
  2980         msvEntry.SetPriority(EMsvLowPriority);
       
  2981         break;            
       
  2982     }
       
  2983     if (message.status() & QMessage::Read) {
       
  2984         msvEntry.SetUnread(false);
       
  2985         msvEntry.SetNew(false);
       
  2986     } else {
       
  2987         msvEntry.SetUnread(true);
       
  2988         msvEntry.SetNew(true);
       
  2989     }
       
  2990     
       
  2991     msvEntry.iDescription.Set(TPtrC(reinterpret_cast<const TUint16*>(message.subject().utf16())));
       
  2992     msvEntry.iDetails.Set(TPtrC(reinterpret_cast<const TUint16*>(message.from().addressee().utf16())));
       
  2993     
       
  2994     if (mtmUid == KUidMsgTypeSMTP) {
       
  2995         ipSmtpMtm->Entry().ChangeL(msvEntry);
       
  2996     } else {
       
  2997         QMTMWait mtmWait;
       
  2998         CMsvOperation* pMsvOperation = NULL;
       
  2999         if (mtmUid == KUidMsgTypePOP3) {
       
  3000             pMsvOperation = ipPop3Mtm->Entry().ChangeL(msvEntry, mtmWait.iStatus);
       
  3001         } else {
       
  3002             pMsvOperation = ipImap4Mtm->Entry().ChangeL(msvEntry, mtmWait.iStatus);
       
  3003         }
       
  3004         mtmWait.start();
       
  3005         delete pMsvOperation;
       
  3006     }
       
  3007     
       
  3008     // Save the changes    
       
  3009     ipSmtpMtm->SaveMessageL();
       
  3010     
       
  3011     CMsvEntry* entry = ipMsvSession->GetEntryL(messageId);
       
  3012     CleanupStack::PushL(entry);
       
  3013     
       
  3014     CImEmailMessage* mailMsg = CImEmailMessage::NewLC(*entry); 
       
  3015     
       
  3016     CImMimeHeader* mime = CImMimeHeader::NewLC(); 
       
  3017     
       
  3018     QByteArray filePath;
       
  3019     QMessageContentContainerIdList contentIds = message.contentIds();
       
  3020     foreach (QMessageContentContainerId id, contentIds){
       
  3021         QMessageContentContainer container = message.find(id);
       
  3022         QMessageContentContainerPrivate* pPrivateContainer = QMessageContentContainerPrivate::implementation(container);
       
  3023         filePath = QMessageContentContainerPrivate::attachmentFilename(container);
       
  3024         if (!filePath.isEmpty()) { // content is attachment
       
  3025             filePath.replace(QByteArray("/"), QByteArray("\\"));
       
  3026             QString temp_path = QString(filePath);
       
  3027             TPtrC16 attachmentPath(KNullDesC);
       
  3028             attachmentPath.Set(reinterpret_cast<const TUint16*>(temp_path.utf16()));
       
  3029             TFileName attachmentFile;
       
  3030             attachmentFile.Append(attachmentPath);    
       
  3031         
       
  3032             RFile attachment;    
       
  3033             User::LeaveIfError(attachment.Open(FsSession(),attachmentFile, EFileShareReadersOnly | EFileRead));    
       
  3034             CleanupClosePushL(attachment);   
       
  3035             
       
  3036             CMsvAttachment* attachmentInfo = CMsvAttachment::NewL(CMsvAttachment::EMsvFile);
       
  3037             QByteArray filePath = QMessageContentContainerPrivate::attachmentFilename(container);
       
  3038             int last = filePath.lastIndexOf("/");
       
  3039             int count = filePath.count();
       
  3040             QByteArray name = filePath.right(count-last-1);
       
  3041             QString fileName = QString(name);
       
  3042             CleanupStack::PushL(attachmentInfo);  
       
  3043             attachmentInfo->SetAttachmentNameL(TPtrC(reinterpret_cast<const TUint16*>(fileName.utf16())));
       
  3044             QMTMWait mtmWait;
       
  3045             mailMsg->AttachmentManager().AddAttachmentL(attachment, attachmentInfo, mtmWait.iStatus);
       
  3046             mtmWait.start();
       
  3047             CleanupStack::Pop(attachmentInfo);
       
  3048             CleanupStack::Pop(&attachment); // close file
       
  3049         } else if (pPrivateContainer->_id == message.bodyId()) { // content is body text
       
  3050             CParaFormatLayer* paragraphFormatLayer = CParaFormatLayer::NewL();
       
  3051             CleanupStack::PushL(paragraphFormatLayer);
       
  3052         
       
  3053             CCharFormatLayer* characterFormatLayer = CCharFormatLayer::NewL(); 
       
  3054             CleanupStack::PushL(characterFormatLayer);
       
  3055         
       
  3056             CRichText* bodyText = CRichText::NewL(paragraphFormatLayer, characterFormatLayer, CEditableText::EFlatStorage, 256);
       
  3057             CleanupStack::PushL(bodyText);
       
  3058             
       
  3059             //content type
       
  3060             QByteArray contentType = container.contentType();
       
  3061             TPtrC8 content((TUint8 *)(contentType.constData()));
       
  3062             mime->SetContentTypeL(content);
       
  3063             // content subtype
       
  3064             QByteArray subType = container.contentSubType();
       
  3065             TPtrC8 contentSubType((TUint8 *)(subType.constData()));
       
  3066             mime->SetContentSubTypeL(contentSubType);
       
  3067             // content charset
       
  3068             QByteArray charset = container.contentCharset();
       
  3069             if (charset == "UTF-8") {
       
  3070                 mime->SetMimeCharset(KCharacterSetIdentifierUtf8);
       
  3071             }
       
  3072             if (charset == "UTF-16") {
       
  3073                 mime->SetMimeCharset(KCharacterSetIdentifierUcs2);
       
  3074             }
       
  3075             // Insert the contents of a buffer into the document at specified position
       
  3076             bodyText->InsertL(0, TPtrC(reinterpret_cast<const TUint16*>(container.textContent().utf16())));
       
  3077             QMTMWait mtmWait;
       
  3078             mailMsg->StoreBodyTextWithMimeHeaderL(messageId, *bodyText, *mime, mtmWait.iStatus);
       
  3079             mtmWait.start();
       
  3080                     
       
  3081             CleanupStack::PopAndDestroy(3); // bodyText, characterFormatLayer, paragraphFormatLayer
       
  3082         }
       
  3083         
       
  3084     }  
       
  3085     
       
  3086     QString messageBody = message.textContent();
       
  3087     if (!messageBody.isEmpty()) {
       
  3088         CParaFormatLayer* paragraphFormatLayer = CParaFormatLayer::NewL();
       
  3089         CleanupStack::PushL(paragraphFormatLayer);
       
  3090 
       
  3091         CCharFormatLayer* characterFormatLayer = CCharFormatLayer::NewL(); 
       
  3092         CleanupStack::PushL(characterFormatLayer);
       
  3093 
       
  3094         CRichText* bodyText = CRichText::NewL(paragraphFormatLayer, characterFormatLayer, CEditableText::EFlatStorage, 256);
       
  3095         CleanupStack::PushL(bodyText);
       
  3096         
       
  3097         //content type
       
  3098         QByteArray contentType = message.contentType();
       
  3099         TPtrC8 content((TUint8 *)(contentType.constData()));
       
  3100         mime->SetContentTypeL(content);
       
  3101         // content subtype
       
  3102         QByteArray subType = message.contentSubType();
       
  3103         TPtrC8 contentSubType((TUint8 *)(subType.constData()));
       
  3104         mime->SetContentSubTypeL(contentSubType);
       
  3105         // content charset
       
  3106         QByteArray charset = message.contentCharset();
       
  3107         if (charset == "UTF-8") {
       
  3108             mime->SetMimeCharset(KCharacterSetIdentifierUtf8);
       
  3109         }
       
  3110         if (charset == "UTF-16") {
       
  3111             mime->SetMimeCharset(KCharacterSetIdentifierUcs2);
       
  3112         }
       
  3113         
       
  3114         // Insert the contents of a buffer into the document at specified position
       
  3115         bodyText->InsertL(0, TPtrC(reinterpret_cast<const TUint16*>(message.textContent().utf16())));
       
  3116         QMTMWait mtmWait;
       
  3117         mailMsg->StoreBodyTextWithMimeHeaderL(messageId, *bodyText, *mime, mtmWait.iStatus);
       
  3118         mtmWait.start();
       
  3119         CleanupStack::PopAndDestroy(3);
       
  3120         //bodyText, characterFormatLayer, paragraphFormatLayer,
       
  3121     }
       
  3122 
       
  3123     CMsvStore* store = entry->EditStoreL();
       
  3124     CleanupStack::PushL(store);
       
  3125     CImHeader* emailEntry = CImHeader::NewLC();
       
  3126     TRAP_IGNORE(emailEntry->RestoreL(*store));
       
  3127     mime->StoreL(*store);
       
  3128     emailEntry->SetSubjectL(TPtrC(reinterpret_cast<const TUint16*>(message.subject().utf16())));
       
  3129     
       
  3130     QList<QMessageAddress> toList(message.to());
       
  3131     if (toList.count() > 0){
       
  3132         TPtrC16 receiver(KNullDesC);
       
  3133         QString qreceiver;
       
  3134         for (int i = 0; i < toList.size(); ++i) {
       
  3135             qreceiver = toList.at(i).addressee();
       
  3136             receiver.Set(reinterpret_cast<const TUint16*>(qreceiver.utf16()));
       
  3137             emailEntry->ToRecipients().AppendL(receiver); 
       
  3138         }
       
  3139     }
       
  3140     
       
  3141     QList<QMessageAddress> ccList(message.cc());
       
  3142     if (ccList.count() > 0){
       
  3143         TPtrC16 receiver(KNullDesC);
       
  3144         QString qreceiver;
       
  3145         for (int i = 0; i < ccList.size(); ++i) {
       
  3146             qreceiver = ccList.at(i).addressee();
       
  3147             receiver.Set(reinterpret_cast<const TUint16*>(qreceiver.utf16()));
       
  3148             emailEntry->CcRecipients().AppendL(receiver); 
       
  3149         }
       
  3150     }
       
  3151         
       
  3152     QList<QMessageAddress> bccList(message.bcc());
       
  3153     if (bccList.count() > 0){
       
  3154         TPtrC16 receiver(KNullDesC);
       
  3155         QString qreceiver;
       
  3156         for (int i = 0; i < bccList.size(); ++i) {
       
  3157             qreceiver = bccList.at(i).addressee();
       
  3158             receiver.Set(reinterpret_cast<const TUint16*>(qreceiver.utf16()));
       
  3159             emailEntry->BccRecipients().AppendL(receiver); 
       
  3160         }
       
  3161     }
       
  3162      
       
  3163     emailEntry->StoreL(*store);
       
  3164     // Store the changes permanently
       
  3165     store->CommitL();
       
  3166     
       
  3167     CleanupStack::PopAndDestroy(5, entry); 
       
  3168     // mailMsg, emailEntry, store, waiter, entry, mime   
       
  3169 
       
  3170     if (!message.receivedDate().isNull() || !message.date().isNull()) {
       
  3171         // Change the date to given date
       
  3172         CMsvEntry* pEntry = ipMsvSession->GetEntryL(messageId);
       
  3173         CleanupStack::PushL(pEntry);
       
  3174         TMsvEntry changedEntry = pEntry->Entry();
       
  3175         if (!message.date().isNull()) {
       
  3176             changedEntry.iDate = qDateTimeToSymbianTTime(message.date());
       
  3177         } else {
       
  3178             changedEntry.iDate = qDateTimeToSymbianTTime(message.receivedDate());
       
  3179         }
       
  3180         if (mtmUid == KUidMsgTypeSMTP) {
       
  3181             ipSmtpMtm->Entry().ChangeL(changedEntry);
       
  3182         } else {
       
  3183             QMTMWait mtmWait;
       
  3184             CMsvOperation* pMsvOperation = NULL;
       
  3185             if (mtmUid == KUidMsgTypePOP3) {
       
  3186                 pMsvOperation = ipPop3Mtm->Entry().ChangeL(changedEntry, mtmWait.iStatus);
       
  3187             } else {
       
  3188                 pMsvOperation = ipImap4Mtm->Entry().ChangeL(changedEntry, mtmWait.iStatus);
       
  3189             }
       
  3190             mtmWait.start();
       
  3191             delete pMsvOperation;
       
  3192         }
       
  3193         CleanupStack::PopAndDestroy(pEntry);
       
  3194     }
       
  3195 }
       
  3196 
       
  3197 void CMTMEngine::sendMMSL(QMessage &message)
       
  3198 {
       
  3199     if (!iSessionReady) {
       
  3200         User::Leave(KErrNotReady);
       
  3201     }
       
  3202 
       
  3203     bool messageCreated = false;
       
  3204     if (!message.id().isValid()) {
       
  3205         QMessagePrivate::setStandardFolder(message, QMessage::OutboxFolder);
       
  3206         storeMMSL(message);
       
  3207         messageCreated = true;
       
  3208     }
       
  3209     
       
  3210     long int messageId = SymbianHelpers::stripIdPrefix(message.id().toString()).toLong();
       
  3211     if (messageId == 0) {
       
  3212         User::Leave(KErrNotReady);
       
  3213     }
       
  3214 
       
  3215     CMsvEntry* pMsvEntry = retrieveCMsvEntryAndPushToCleanupStack(messageId);
       
  3216 
       
  3217     QMTMWait mtmWait;
       
  3218     
       
  3219     CMsvOperation* pMsvOperation = NULL;
       
  3220     if (!messageCreated) {
       
  3221         ipMmsMtm->SwitchCurrentEntryL(pMsvEntry->Entry().Parent());
       
  3222         pMsvOperation = ipMmsMtm->Entry().CopyL(messageId, KMsvGlobalOutBoxIndexEntryId, mtmWait.iStatus);
       
  3223         mtmWait.start();
       
  3224         delete pMsvOperation;
       
  3225         pMsvOperation = NULL;
       
  3226     }
       
  3227     
       
  3228     // Start sending the message via the Server MTM to the MMS server    
       
  3229     CMsvEntrySelection* pMsvEntrySelection = new(ELeave) CMsvEntrySelection;
       
  3230     pMsvEntrySelection->AppendL(messageId);
       
  3231     ipMmsMtm->SwitchCurrentEntryL(KMsvGlobalOutBoxIndexEntryId);
       
  3232     pMsvOperation = ipMmsMtm->SendL(*pMsvEntrySelection, mtmWait.iStatus);
       
  3233     mtmWait.start();
       
  3234     
       
  3235     delete pMsvOperation;
       
  3236     releaseCMsvEntryAndPopFromCleanupStack(pMsvEntry);    
       
  3237 }
       
  3238 
       
  3239 QString CMTMEngine::privateFolderPath()
       
  3240 {
       
  3241     // Take drive letter from Application full name (Note: TUidName is 10 characters long <=> TBuf<10>)
       
  3242     //TUidName applicationDrive;
       
  3243     //applicationDrive.Copy(CEikonEnv::Static()->EikAppUi()->Application()->AppFullName().Left(2));
       
  3244     
       
  3245     // Get Application private folder path from FileSession
       
  3246     TPath applicationPrivateFolderPathWithoutDriveLetter;
       
  3247     FsSession().PrivatePath(applicationPrivateFolderPathWithoutDriveLetter);
       
  3248 
       
  3249     // Combine drive letter and private folder path to complete path
       
  3250     TPath driveLetterAndPath;
       
  3251     driveLetterAndPath.Copy(_L("C:"));
       
  3252     driveLetterAndPath.Append(applicationPrivateFolderPathWithoutDriveLetter);
       
  3253     
       
  3254     return QString::fromUtf16(driveLetterAndPath.Ptr(), driveLetterAndPath.Length());
       
  3255 }
       
  3256 
       
  3257 void CMTMEngine::storeEmailL(QMessage &message)
       
  3258 {
       
  3259     if (!iSessionReady) {
       
  3260         User::Leave(KErrNotReady);
       
  3261     }
       
  3262 
       
  3263     TMsvId destinationFolderId = 0;
       
  3264     TMsvId imapDestinationFolderId = 0;
       
  3265     if (message.parentFolderId().isValid()) {
       
  3266         destinationFolderId = folderIdFromQMessageFolderId(message.parentFolderId());
       
  3267         CMsvEntry* pMsvEntry = retrieveCMsvEntryAndPushToCleanupStack(destinationFolderId);
       
  3268         if (pMsvEntry->Entry().iMtm == KUidMsgTypeIMAP4 || pMsvEntry->Entry().iMtm == KUidMsgTypePOP3) {
       
  3269             // New IMAP or POP3 message can not be created to IMAP or POP3 service folder.
       
  3270             // => Create IMAP or POP3 message into Drafts folder instead
       
  3271             destinationFolderId = KMsvDraftEntryId; 
       
  3272             if (pMsvEntry->Entry().iMtm == KUidMsgTypeIMAP4) {
       
  3273                 // It's possible to copy newly created IMAP message from Drafts folder
       
  3274                 // to IMAP service folder.
       
  3275                 // Note: IMAP message can not be created directly to IMAP service folder.
       
  3276                 imapDestinationFolderId = destinationFolderId;
       
  3277             }
       
  3278         }
       
  3279         releaseCMsvEntryAndPopFromCleanupStack(pMsvEntry);
       
  3280     } else {
       
  3281         // parentFolderId was not defined for new Message
       
  3282         // => Message will be created into defined standard Folder (Default value is Drafts Folder)
       
  3283         destinationFolderId =  standardFolderId(message.standardFolder());
       
  3284     }
       
  3285     
       
  3286     QMessageAccount messageAccount = this->account(message.parentAccountId());
       
  3287 
       
  3288     QMTMWait mtmWait;
       
  3289     
       
  3290     TMsvEmailTypeList msvEmailTypeList = 0;
       
  3291     TMsvPartList msvPartList = 0;
       
  3292     if (message.status() & QMessage::HasAttachments == QMessage::HasAttachments) {
       
  3293         msvPartList = (KMsvMessagePartBody | KMsvMessagePartAttachments);
       
  3294     } else {
       
  3295         msvPartList = KMsvMessagePartBody;
       
  3296     }
       
  3297     CImEmailOperation* pImEmailOperation = CImEmailOperation::CreateNewL(mtmWait.iStatus, *ipMsvSession, destinationFolderId,
       
  3298                                                                          messageAccount.d_ptr->_service2EntryId, msvPartList,
       
  3299                                                                          msvEmailTypeList, KUidMsgTypeSMTP);
       
  3300     CleanupStack::PushL(pImEmailOperation);
       
  3301     mtmWait.start();
       
  3302     
       
  3303     TMsvId newMessageId;
       
  3304     TPckgC<TMsvId> paramPack(newMessageId);
       
  3305     paramPack.Set(pImEmailOperation->ProgressL());
       
  3306     newMessageId = paramPack();
       
  3307     CleanupStack::PopAndDestroy(pImEmailOperation);
       
  3308     
       
  3309     ipSmtpMtm->SwitchCurrentEntryL(newMessageId);
       
  3310     ipSmtpMtm->LoadMessageL();
       
  3311     
       
  3312     TMsvEntry msvEntry = ipSmtpMtm->Entry().Entry();
       
  3313     switch (message.priority()) {
       
  3314     case QMessage::HighPriority:
       
  3315         msvEntry.SetPriority(EMsvHighPriority);
       
  3316         break;
       
  3317     case QMessage::NormalPriority:
       
  3318         msvEntry.SetPriority(EMsvMediumPriority);
       
  3319         break;
       
  3320     case QMessage::LowPriority:
       
  3321         msvEntry.SetPriority(EMsvLowPriority);
       
  3322         break;            
       
  3323     }
       
  3324     if (message.status() & QMessage::Read) { 
       
  3325         msvEntry.SetUnread(false);
       
  3326         msvEntry.SetNew(false);
       
  3327     } else {
       
  3328         msvEntry.SetUnread(true);
       
  3329         msvEntry.SetNew(true);
       
  3330     }
       
  3331     
       
  3332     ipSmtpMtm->Entry().ChangeL(msvEntry); 
       
  3333     ipSmtpMtm->SaveMessageL();
       
  3334 
       
  3335     CMsvEntry* pMsvEntry = retrieveCMsvEntryAndPushToCleanupStack(newMessageId);
       
  3336 
       
  3337     // Create email message MIME header 
       
  3338     CImMimeHeader* pImMimeHeader = CImMimeHeader::NewLC(); 
       
  3339     QByteArray contentType = message.contentType();
       
  3340     TPtrC8 content((TUint8 *)(contentType.constData()));
       
  3341     pImMimeHeader->SetContentTypeL(content);
       
  3342     QByteArray subType = message.contentSubType();
       
  3343     TPtrC8 contentSubType((TUint8 *)(subType.constData()));
       
  3344     pImMimeHeader->SetContentSubTypeL(contentSubType);
       
  3345     QByteArray charset = message.contentCharset();
       
  3346     if (charset == "UTF-8") {
       
  3347         pImMimeHeader->SetMimeCharset(KCharacterSetIdentifierUtf8);
       
  3348     }
       
  3349     if (charset == "UTF-16") {
       
  3350         pImMimeHeader->SetMimeCharset(KCharacterSetIdentifierUcs2);
       
  3351     }
       
  3352 
       
  3353     CImEmailMessage* pImEmailMessage = CImEmailMessage::NewL(*pMsvEntry);
       
  3354     CleanupStack::PushL(pImEmailMessage);
       
  3355     
       
  3356     if (message.bodyId() == QMessageContentContainerPrivate::bodyContentId()) {
       
  3357         // Message contains only body (not attachments)
       
  3358         QString messageBody = message.textContent();
       
  3359         if (!messageBody.isEmpty()) {
       
  3360             CParaFormatLayer* pParaFormatLayer = CParaFormatLayer::NewL();
       
  3361             CleanupStack::PushL(pParaFormatLayer);
       
  3362             CCharFormatLayer* pCharFormatLayer = CCharFormatLayer::NewL(); 
       
  3363             CleanupStack::PushL(pCharFormatLayer);
       
  3364     
       
  3365             CRichText* pBodyRichText = CRichText::NewL(pParaFormatLayer, pCharFormatLayer, CEditableText::EFlatStorage, 256);
       
  3366             CleanupStack::PushL(pBodyRichText);
       
  3367     
       
  3368             // Insert the contents of a buffer into the document at specified position
       
  3369             pBodyRichText->InsertL(0, TPtrC(reinterpret_cast<const TUint16*>(message.textContent().utf16())));
       
  3370             // Note: Email message MIME header is same as Body MIME header
       
  3371             pImEmailMessage->StoreBodyTextWithMimeHeaderL(newMessageId, *pBodyRichText, *pImMimeHeader,
       
  3372                                                           mtmWait.iStatus);
       
  3373             mtmWait.start();
       
  3374             
       
  3375             CleanupStack::PopAndDestroy(pBodyRichText);
       
  3376             CleanupStack::PopAndDestroy(pCharFormatLayer);
       
  3377             CleanupStack::PopAndDestroy(pParaFormatLayer);
       
  3378         }
       
  3379     } else {
       
  3380         // Message contains body and attachments
       
  3381         QMessageContentContainerIdList contentIds = message.contentIds();
       
  3382         foreach (QMessageContentContainerId id, contentIds){
       
  3383             QMessageContentContainer container = message.find(id);
       
  3384             QMessageContentContainerPrivate* pPrivateContainer = QMessageContentContainerPrivate::implementation(container);
       
  3385             if (pPrivateContainer->_id == message.bodyId()) {
       
  3386                 // ContentContainer is body
       
  3387                 if (!container.textContent().isEmpty()) {
       
  3388                     // Create MIME header for body
       
  3389                     CImMimeHeader* pBodyImMimeHeader = CImMimeHeader::NewLC();
       
  3390                     QByteArray contentType = container.contentType();
       
  3391                     TPtrC8 content((TUint8 *)(contentType.constData()));
       
  3392                     pBodyImMimeHeader->SetContentTypeL(content);
       
  3393                     QByteArray subType = container.contentSubType();
       
  3394                     TPtrC8 contentSubType((TUint8 *)(subType.constData()));
       
  3395                     pBodyImMimeHeader->SetContentSubTypeL(contentSubType);
       
  3396                     QByteArray charset = container.contentCharset();
       
  3397                     if (charset == "UTF-8") {
       
  3398                         pBodyImMimeHeader->SetMimeCharset(KCharacterSetIdentifierUtf8);
       
  3399                     }
       
  3400                     if (charset == "UTF-16") {
       
  3401                         pBodyImMimeHeader->SetMimeCharset(KCharacterSetIdentifierUcs2);
       
  3402                     }
       
  3403     
       
  3404                     // Create CRichText containing body text
       
  3405                     CParaFormatLayer* pParaFormatLayer = CParaFormatLayer::NewL();
       
  3406                     CleanupStack::PushL(pParaFormatLayer);
       
  3407                     CCharFormatLayer* pCharFormatLayer = CCharFormatLayer::NewL(); 
       
  3408                     CleanupStack::PushL(pCharFormatLayer);
       
  3409             
       
  3410                     CRichText* pBodyRichText = CRichText::NewL(pParaFormatLayer, pCharFormatLayer, CEditableText::EFlatStorage);
       
  3411                     CleanupStack::PushL(pBodyRichText);
       
  3412                     // Insert the contents of a buffer into the document at specified position
       
  3413                     pBodyRichText->InsertL(0, TPtrC(reinterpret_cast<const TUint16*>(container.textContent().utf16())));
       
  3414             
       
  3415                     // Store MIME Header and Body text to message
       
  3416                     pImEmailMessage->StoreBodyTextWithMimeHeaderL(newMessageId, *pBodyRichText,
       
  3417                                                                   *pBodyImMimeHeader,
       
  3418                                                                   mtmWait.iStatus);
       
  3419                     mtmWait.start();
       
  3420                     
       
  3421                     CleanupStack::PopAndDestroy(pBodyRichText);
       
  3422                     CleanupStack::PopAndDestroy(pCharFormatLayer);
       
  3423                     CleanupStack::PopAndDestroy(pParaFormatLayer);
       
  3424                     CleanupStack::PopAndDestroy(pBodyImMimeHeader);
       
  3425                 }
       
  3426             } else {
       
  3427                 // ContentContainer is attachment
       
  3428                 QByteArray filePath = QMessageContentContainerPrivate::attachmentFilename(container);
       
  3429                 // Replace Qt style path separator "/" with Symbian path separator "\"
       
  3430                 filePath.replace(QByteArray("/"), QByteArray("\\"));
       
  3431                 // Make sure that "." folder is translated to application private folder
       
  3432                 // For example: "." = "<drive letter>:\private\<application specific private folder>\" 
       
  3433                 if (filePath.startsWith('.')) {
       
  3434                     filePath.remove(0,2); // Remove ".\"
       
  3435                     filePath.insert(0,privateFolderPath().toAscii());
       
  3436                 }
       
  3437                 QString temp_path = QString(filePath);
       
  3438                 TPtrC16 attachmentPath(KNullDesC);
       
  3439                 attachmentPath.Set(reinterpret_cast<const TUint16*>(temp_path.utf16()));
       
  3440                 TFileName attachmentFileName;
       
  3441                 attachmentFileName.Append(attachmentPath);    
       
  3442             
       
  3443                 RFile attachmentFile;    
       
  3444                 User::LeaveIfError(attachmentFile.Open(FsSession(), attachmentFileName,
       
  3445                                                        EFileShareReadersOnly | EFileRead));    
       
  3446                 CleanupClosePushL(attachmentFile);   
       
  3447                 
       
  3448                 CMsvAttachment* pMsvAttachment = CMsvAttachment::NewL(CMsvAttachment::EMsvFile);
       
  3449                 int last = filePath.lastIndexOf("\\");
       
  3450                 int count = filePath.count();
       
  3451                 QByteArray name = filePath.right(count-last-1);
       
  3452                 QString fileName = QString(name);
       
  3453                 CleanupStack::PushL(pMsvAttachment);  
       
  3454                 pMsvAttachment->SetAttachmentNameL(TPtrC(reinterpret_cast<const TUint16*>(fileName.utf16())));
       
  3455                 // Note: Following call transfers ownership of attachmentFile and pMsvAttachment to AttachmentManager
       
  3456                 pImEmailMessage->AttachmentManager().AddAttachmentL(attachmentFile, pMsvAttachment,
       
  3457                                                                     mtmWait.iStatus);
       
  3458                 mtmWait.start();
       
  3459 
       
  3460                 CleanupStack::Pop(pMsvAttachment); // Pop attachment from CleanupStack
       
  3461                 CleanupStack::Pop(&attachmentFile); // Pop file from CleanupStack
       
  3462             }        
       
  3463         }
       
  3464     }
       
  3465     CleanupStack::PopAndDestroy(pImEmailMessage);
       
  3466 
       
  3467     CMsvStore* pMsvStore = pMsvEntry->EditStoreL();
       
  3468     CleanupStack::PushL(pMsvStore);
       
  3469     
       
  3470     pImMimeHeader->StoreL(*pMsvStore);
       
  3471     
       
  3472     CImHeader* pImHeader = CImHeader::NewLC();
       
  3473     pImHeader->RestoreL(*pMsvStore);
       
  3474     pImHeader->SetSubjectL(TPtrC(reinterpret_cast<const TUint16*>(message.subject().utf16())));
       
  3475     pImHeader->SetFromL(TPtrC(reinterpret_cast<const TUint16*>(message.from().addressee().utf16())));
       
  3476     
       
  3477     QList<QMessageAddress> toList(message.to());
       
  3478     if (toList.count() > 0) {
       
  3479         TPtrC16 receiver(KNullDesC);
       
  3480         QString qreceiver;
       
  3481         for (int i = 0; i < toList.size(); ++i) {
       
  3482             qreceiver = toList.at(i).addressee();
       
  3483             receiver.Set(reinterpret_cast<const TUint16*>(qreceiver.utf16()));
       
  3484             pImHeader->ToRecipients().AppendL(receiver); 
       
  3485         }
       
  3486     }
       
  3487     
       
  3488     QList<QMessageAddress> ccList(message.cc());
       
  3489     if (ccList.count() > 0) {
       
  3490         TPtrC16 receiver(KNullDesC);
       
  3491         QString qreceiver;
       
  3492         for (int i = 0; i < ccList.size(); ++i) {
       
  3493             qreceiver = ccList.at(i).addressee();
       
  3494             receiver.Set(reinterpret_cast<const TUint16*>(qreceiver.utf16()));
       
  3495             pImHeader->CcRecipients().AppendL(receiver); 
       
  3496         }
       
  3497     }
       
  3498         
       
  3499     QList<QMessageAddress> bccList(message.bcc());
       
  3500     if (bccList.count() > 0) {
       
  3501         TPtrC16 receiver(KNullDesC);
       
  3502         QString qreceiver;
       
  3503         for (int i = 0; i < bccList.size(); ++i) {
       
  3504             qreceiver = bccList.at(i).addressee();
       
  3505             receiver.Set(reinterpret_cast<const TUint16*>(qreceiver.utf16()));
       
  3506             pImHeader->BccRecipients().AppendL(receiver); 
       
  3507         }
       
  3508     }
       
  3509    
       
  3510     pImHeader->StoreL(*pMsvStore);
       
  3511     CleanupStack::PopAndDestroy(pImHeader);
       
  3512 
       
  3513     // Store the changes permanently
       
  3514     pMsvStore->CommitL();
       
  3515     CleanupStack::PopAndDestroy(pMsvStore);
       
  3516     CleanupStack::PopAndDestroy(pImMimeHeader);
       
  3517 
       
  3518     TMsvEntry changedEntry = pMsvEntry->Entry();
       
  3519     changedEntry.iDescription.Set(TPtrC(reinterpret_cast<const TUint16*>(message.subject().utf16())));
       
  3520     if (toList.count() > 0) {
       
  3521         changedEntry.iDetails.Set(TPtrC(reinterpret_cast<const TUint16*>(toList.at(0).addressee().utf16())));
       
  3522     }
       
  3523     if (!message.receivedDate().isNull() || !message.date().isNull()) {
       
  3524         // Change the date to given date
       
  3525         if (!message.date().isNull()) {
       
  3526             changedEntry.iDate = qDateTimeToSymbianTTime(message.date());
       
  3527         } else {
       
  3528             changedEntry.iDate = qDateTimeToSymbianTTime(message.receivedDate());
       
  3529         }
       
  3530     }
       
  3531     pMsvEntry->ChangeL(changedEntry);
       
  3532     
       
  3533     if (imapDestinationFolderId != 0) {
       
  3534         TMsvId parent = pMsvEntry->Entry().Parent();
       
  3535         ipImap4Mtm->SwitchCurrentEntryL(parent);        
       
  3536         CMsvOperation* pMsvOperation = ipImap4Mtm->Entry().MoveL(newMessageId, imapDestinationFolderId,
       
  3537                                                                  mtmWait.iStatus);
       
  3538         mtmWait.start();
       
  3539         delete pMsvOperation;
       
  3540     }
       
  3541     
       
  3542     releaseCMsvEntryAndPopFromCleanupStack(pMsvEntry);
       
  3543 
       
  3544     QMessagePrivate* privateMessage = QMessagePrivate::implementation(message);
       
  3545     privateMessage->_id = QMessageId(SymbianHelpers::addIdPrefix(QString::number(newMessageId),SymbianHelpers::EngineTypeMTM));
       
  3546 }
       
  3547 
       
  3548 void CMTMEngine::sendEmailL(QMessage &message)
       
  3549 {
       
  3550     if (!iSessionReady) {
       
  3551         User::Leave(KErrNotReady);
       
  3552     }
       
  3553 
       
  3554     QMessageAccountId accountId = message.parentAccountId();
       
  3555     QMessageAccount messageAccount;
       
  3556     if (accountId.isValid()) {
       
  3557         messageAccount = account(accountId);
       
  3558     } else {
       
  3559         accountId = defaultAccount(QMessage::Email);
       
  3560         messageAccount = account(accountId);
       
  3561     }
       
  3562     
       
  3563     bool messageCreated = false;
       
  3564     if (!message.id().isValid()) {
       
  3565         // Message id is not valid
       
  3566         // => Message is not in message store
       
  3567         //    => New message must be created into Outbox folder
       
  3568         QMessagePrivate::setStandardFolder(message, QMessage::OutboxFolder);
       
  3569         message.setParentAccountId(accountId);
       
  3570         storeEmailL(message);
       
  3571         messageCreated = true;
       
  3572     }    
       
  3573     
       
  3574     long int messageId = SymbianHelpers::stripIdPrefix(message.id().toString()).toLong();
       
  3575     if (messageId == 0) {
       
  3576         User::Leave(KErrNotReady);
       
  3577     }    
       
  3578 
       
  3579     CMsvEntry* pMsvEntry = retrieveCMsvEntryAndPushToCleanupStack(messageId);
       
  3580     
       
  3581     QMTMWait mtmWait;
       
  3582     
       
  3583     CMsvOperation* pMsvOperation = NULL;
       
  3584     if (!messageCreated) {
       
  3585         // Sending (old) message that's in message store
       
  3586         // => Copy message from its original location to Outbox folder
       
  3587         ipSmtpMtm->SwitchCurrentEntryL(pMsvEntry->Entry().Parent());
       
  3588         pMsvOperation = ipSmtpMtm->Entry().CopyL(messageId,
       
  3589                                                  KMsvGlobalOutBoxIndexEntryId,
       
  3590                                                  mtmWait.iStatus);
       
  3591         mtmWait.start();
       
  3592         delete pMsvOperation;
       
  3593         pMsvOperation = NULL;
       
  3594     }    
       
  3595     
       
  3596     ipSmtpMtm->SwitchCurrentEntryL(pMsvEntry->Entry().Parent());
       
  3597     // Following sends Email and _moves_ Email from Outbox Folder to Sent Folder
       
  3598     pMsvOperation = ipSmtpMtm->Entry().CopyL(messageId, messageAccount.d_ptr->_service2EntryId, mtmWait.iStatus);
       
  3599     mtmWait.start();
       
  3600     delete pMsvOperation;    
       
  3601     
       
  3602     releaseCMsvEntryAndPopFromCleanupStack(pMsvEntry);   
       
  3603 }
       
  3604 
       
  3605 QDateTime CMTMEngine::symbianTTimetoQDateTime(const TTime& time) const
       
  3606 {
       
  3607     TDateTime dateTime = time.DateTime();
       
  3608     QDate qdate = QDate(dateTime.Year(), static_cast<int>(dateTime.Month())+1, dateTime.Day()+1);
       
  3609     QTime qtime = QTime(dateTime.Hour(), dateTime.Minute(), dateTime.Second(), dateTime.MicroSecond()/1000 );
       
  3610     return QDateTime(qdate, qtime, Qt::UTC);
       
  3611 }
       
  3612 
       
  3613 TTime CMTMEngine::qDateTimeToSymbianTTime(const QDateTime& date) const
       
  3614 {
       
  3615     TDateTime dateTime;
       
  3616     dateTime.SetYear(date.date().year());
       
  3617     dateTime.SetMonth(static_cast<TMonth>(date.date().month()-1));
       
  3618     dateTime.SetDay(date.date().day()-1);
       
  3619     dateTime.SetHour(date.time().hour());
       
  3620     dateTime.SetMinute(date.time().minute());
       
  3621     dateTime.SetSecond(date.time().second());
       
  3622     dateTime.SetMicroSecond(date.time().msec()*1000);
       
  3623     return TTime(dateTime);
       
  3624 }
       
  3625 
       
  3626 QMessage CMTMEngine::smsMessageL(CMsvEntry& receivedEntry, long int messageId) const
       
  3627 {
       
  3628     QMessage message;
       
  3629     int size = 0;
       
  3630     message.setType(QMessage::Sms);
       
  3631 
       
  3632     CMsvStore* pStore = receivedEntry.ReadStoreL();
       
  3633     CleanupStack::PushL(pStore);
       
  3634     
       
  3635     const TMsvEntry& entry = receivedEntry.Entry();
       
  3636     message.setDate(symbianTTimetoQDateTime(entry.iDate));
       
  3637     message.setReceivedDate(symbianTTimetoQDateTime(entry.iDate));
       
  3638 
       
  3639     QMessageAccount account = accountsByType(QMessage::Sms)[0];
       
  3640     QMessagePrivate* privateMessage = QMessagePrivate::implementation(message);
       
  3641     privateMessage->_parentFolderId = createQMessageFolderId(account.d_ptr->_service1EntryId, entry.Parent());
       
  3642     privateMessage->_parentAccountId = account.id();
       
  3643     if (!entry.Unread()) {
       
  3644         privateMessage->_status = privateMessage->_status | QMessage::Read; 
       
  3645     }
       
  3646 
       
  3647     switch (entry.Priority()) {
       
  3648     case EMsvHighPriority: 
       
  3649         message.setPriority(QMessage::HighPriority);
       
  3650         break;
       
  3651     case EMsvMediumPriority:
       
  3652         message.setPriority(QMessage::NormalPriority);
       
  3653         break;
       
  3654     case EMsvLowPriority:
       
  3655         message.setPriority(QMessage::LowPriority);
       
  3656         break;
       
  3657     }
       
  3658     
       
  3659     if (entry.Parent() == KMsvGlobalInBoxIndexEntryId) {
       
  3660         QMessagePrivate::setStandardFolder(message,QMessage::InboxFolder);
       
  3661     } else if (entry.Parent() == KMsvDraftEntryId) {
       
  3662         QMessagePrivate::setStandardFolder(message,QMessage::DraftsFolder);
       
  3663     } else if (entry.Parent() == KMsvSentEntryId) {
       
  3664         QMessagePrivate::setStandardFolder(message,QMessage::SentFolder);
       
  3665     } else if (entry.Parent() == KMsvDeletedEntryFolderEntryId) {
       
  3666         QMessagePrivate::setStandardFolder(message,QMessage::TrashFolder);
       
  3667     }       
       
  3668     
       
  3669     // Read message sender
       
  3670     ipSmsMtm->SwitchCurrentEntryL(messageId);
       
  3671     ipSmsMtm->LoadMessageL();
       
  3672     CSmsHeader& header = ipSmsMtm->SmsHeader();
       
  3673     
       
  3674     message.setFrom(QMessageAddress(QMessageAddress::Phone, QString::fromUtf16(header.FromAddress().Ptr(), header.FromAddress().Length())));
       
  3675     QMessagePrivate::setSenderName(message, QString::fromUtf16(header.FromAddress().Ptr(), header.FromAddress().Length()));
       
  3676     
       
  3677     // Read message recipients
       
  3678     const CArrayPtrFlat<CSmsNumber>&  array = header.Recipients();
       
  3679     QMessageAddressList messageAddresslist;
       
  3680     for (int i=0; i < array.Count(); i++) {
       
  3681         CSmsNumber* smsNumber = array.At(i);
       
  3682         TPtrC recipientNumber = smsNumber->Address();
       
  3683         messageAddresslist.append(QMessageAddress(QMessageAddress::Phone, QString::fromUtf16(recipientNumber.Ptr(), recipientNumber.Length())));
       
  3684     }
       
  3685     message.setTo(messageAddresslist);
       
  3686 
       
  3687     // Read message body
       
  3688     if (pStore->HasBodyTextL()) {
       
  3689         if (!ipRichText) {
       
  3690             ipCharFormatLayer = CCharFormatLayer::NewL();
       
  3691             ipParaFormatLayer = CParaFormatLayer::NewL();
       
  3692             ipRichText=CRichText::NewL(ipParaFormatLayer, ipCharFormatLayer);
       
  3693         }
       
  3694         ipRichText->Reset();
       
  3695         pStore->RestoreBodyTextL(*ipRichText);
       
  3696         HBufC* pMessage = HBufC::NewLC(ipRichText->DocumentLength());
       
  3697         TPtr ptr2(pMessage->Des());
       
  3698         ipRichText->Extract(ptr2);
       
  3699         if (pMessage->Length() > 0) {
       
  3700             size += pMessage->Length();
       
  3701             message.setBody(QString::fromUtf16(pMessage->Ptr(), pMessage->Length()));
       
  3702             if (pMessage->Length() <= 100) {
       
  3703 				message.setSubject(QString::fromUtf16(pMessage->Ptr(), pMessage->Length()));
       
  3704             } else {
       
  3705 				message.setSubject(QString::fromUtf16(pMessage->Ptr(), 100));
       
  3706             }     
       
  3707         }
       
  3708         CleanupStack::PopAndDestroy(pMessage);
       
  3709     }
       
  3710     
       
  3711     CleanupStack::PopAndDestroy(pStore);
       
  3712     
       
  3713     privateMessage->_size = size;
       
  3714     
       
  3715     return message;
       
  3716 }
       
  3717 
       
  3718 QMessage CMTMEngine::mmsMessageL(CMsvEntry& receivedEntry, long int messageId) const
       
  3719 {
       
  3720     QMessage message;
       
  3721     int size = 0;
       
  3722     message.setType(QMessage::Mms);
       
  3723     
       
  3724     CMsvStore* pStore = receivedEntry.ReadStoreL();
       
  3725     CleanupStack::PushL(pStore);
       
  3726 
       
  3727     const TMsvEntry& entry = receivedEntry.Entry();
       
  3728     message.setDate(symbianTTimetoQDateTime(entry.iDate));
       
  3729     message.setReceivedDate(symbianTTimetoQDateTime(entry.iDate));
       
  3730 
       
  3731     QMessageAccount account = accountsByType(QMessage::Mms)[0];
       
  3732     QMessagePrivate* privateMessage = QMessagePrivate::implementation(message);
       
  3733     privateMessage->_parentFolderId = createQMessageFolderId(account.d_ptr->_service1EntryId, entry.Parent());
       
  3734     privateMessage->_parentAccountId = account.id();
       
  3735     if (!entry.Unread()) {
       
  3736         privateMessage->_status = privateMessage->_status | QMessage::Read; 
       
  3737     }
       
  3738 
       
  3739     switch (entry.Priority()) {
       
  3740     case EMsvHighPriority:
       
  3741         message.setPriority(QMessage::HighPriority);
       
  3742         break;
       
  3743     case EMsvMediumPriority:
       
  3744         message.setPriority(QMessage::NormalPriority);
       
  3745         break;
       
  3746     case EMsvLowPriority:
       
  3747         message.setPriority(QMessage::LowPriority);
       
  3748         break;
       
  3749     }
       
  3750 
       
  3751     if (entry.Parent() == KMsvGlobalInBoxIndexEntryId) {
       
  3752         QMessagePrivate::setStandardFolder(message,QMessage::InboxFolder);
       
  3753     } else if (entry.Parent() == KMsvDraftEntryId) {
       
  3754         QMessagePrivate::setStandardFolder(message,QMessage::DraftsFolder);
       
  3755     } else if (entry.Parent() == KMsvSentEntryId) {
       
  3756         QMessagePrivate::setStandardFolder(message,QMessage::SentFolder);
       
  3757     } else if (entry.Parent() == KMsvDeletedEntryFolderEntryId) {
       
  3758         QMessagePrivate::setStandardFolder(message,QMessage::TrashFolder);
       
  3759     }       
       
  3760     
       
  3761     // Read message sender
       
  3762     ipMmsMtm->SwitchCurrentEntryL(messageId);
       
  3763     ipMmsMtm->LoadMessageL();
       
  3764     message.setFrom(QMessageAddress(QMessageAddress::Phone, QString::fromUtf16(ipMmsMtm->Sender().Ptr(), ipMmsMtm->Sender().Length())));
       
  3765     QMessagePrivate::setSenderName(message, QString::fromUtf16(ipMmsMtm->Sender().Ptr(), ipMmsMtm->Sender().Length()));
       
  3766     
       
  3767     // Read message subject
       
  3768     if (receivedEntry.Entry().iDescription.Length() > 0)  {
       
  3769         message.setSubject(QString::fromUtf16(receivedEntry.Entry().iDescription.Ptr(),
       
  3770                                               receivedEntry.Entry().iDescription.Length()));
       
  3771     }
       
  3772     
       
  3773     // Read message body & attachments
       
  3774     TInt count = pStore->AttachmentManagerL().AttachmentCount();
       
  3775     TBool textAdded = EFalse;
       
  3776     if (count > 0) {
       
  3777         privateMessage->_status = privateMessage->_status | QMessage::HasAttachments;
       
  3778     }
       
  3779     for (TInt i = 0; i < count; i++) {
       
  3780         CMsvAttachment* pAttachment = pStore->AttachmentManagerL().GetAttachmentInfoL(i);
       
  3781         CleanupStack::PushL(pAttachment);
       
  3782         if (pAttachment->MimeType() == _L8("text/plain") && !textAdded) {
       
  3783             // Read message body
       
  3784             textAdded = ETrue;
       
  3785             RFile file = pStore->AttachmentManagerL().GetAttachmentFileL(i);
       
  3786             CleanupClosePushL(file);
       
  3787             TInt fileSize;
       
  3788             size += fileSize;
       
  3789             file.Size(fileSize);
       
  3790             HBufC8* pFileContent = HBufC8::NewLC(fileSize);
       
  3791             TPtr8 fileContent(pFileContent->Des());
       
  3792             file.Read(fileContent);
       
  3793             HBufC* pMsg = CnvUtfConverter::ConvertToUnicodeFromUtf8L(*pFileContent);
       
  3794             CleanupStack::PopAndDestroy(pFileContent);
       
  3795             CleanupStack::PopAndDestroy(&file);
       
  3796             if (pMsg->Length() > 0) {
       
  3797                 message.setBody(QString::fromUtf16(pMsg->Ptr(), pMsg->Length()));
       
  3798                 if (receivedEntry.Entry().iDescription.Length() <= 0) { // no subject
       
  3799 					if (pMsg->Length() <= 100) {
       
  3800 						message.setSubject(QString::fromUtf16(pMsg->Ptr(), pMsg->Length()));
       
  3801 					}
       
  3802 					else {
       
  3803 						message.setSubject(QString::fromUtf16(pMsg->Ptr(), 100));
       
  3804 					}
       
  3805                 }
       
  3806             }
       
  3807             delete pMsg;
       
  3808         } else {
       
  3809             QByteArray mimeType;
       
  3810             QByteArray mimeSubType;
       
  3811             QByteArray mimeTypeAndSubType = QByteArray((const char *)pAttachment->MimeType().Ptr(), pAttachment->MimeType().Length());
       
  3812             int index = mimeTypeAndSubType.indexOf("/");
       
  3813             if (index != -1) {
       
  3814                 mimeType = mimeTypeAndSubType.left(index).trimmed();
       
  3815                 mimeSubType = mimeTypeAndSubType.mid(index + 1).trimmed();
       
  3816             }
       
  3817             QByteArray path = QString::fromUtf16(pAttachment->FilePath().Ptr(),pAttachment->FilePath().Length()).toLocal8Bit();
       
  3818             index = path.lastIndexOf('\\');
       
  3819             QByteArray name;
       
  3820             if (index != -1) {
       
  3821                 name = path.right(path.length()-index-1);
       
  3822             } else {
       
  3823                 name = path;
       
  3824             }
       
  3825             int attachmentSize = pAttachment->Size();
       
  3826             size += attachmentSize;
       
  3827             QMessageContentContainer attachment = QMessageContentContainerPrivate::from(messageId, pAttachment->Id(), name, mimeType, mimeSubType, attachmentSize);
       
  3828             appendAttachmentToMessage(message, attachment);
       
  3829         }
       
  3830         CleanupStack::PopAndDestroy(pAttachment);
       
  3831     }
       
  3832 
       
  3833     CleanupStack::PopAndDestroy(pStore);
       
  3834     
       
  3835     privateMessage->_size = size;
       
  3836     
       
  3837     return message;
       
  3838 }
       
  3839 
       
  3840 QMessage CMTMEngine::emailMessageL(CMsvEntry& receivedEntry, long int messageId) const
       
  3841 {
       
  3842     QMessage message;
       
  3843     int size = 0;
       
  3844     message.setType(QMessage::Email);
       
  3845 
       
  3846     const TMsvEntry& entry = receivedEntry.Entry();
       
  3847     message.setDate(symbianTTimetoQDateTime(entry.iDate));
       
  3848     message.setReceivedDate(symbianTTimetoQDateTime(entry.iDate));
       
  3849     
       
  3850     QMessageAccount messageAccount = account(accountIdByServiceId(entry.iServiceId));
       
  3851     message.setParentAccountId(messageAccount.id());
       
  3852 
       
  3853     QMessagePrivate* privateMessage = QMessagePrivate::implementation(message);
       
  3854     privateMessage->_parentFolderId = createQMessageFolderId(messageAccount.d_ptr->_service1EntryId, entry.Parent());
       
  3855     if (!entry.Unread()) {
       
  3856         privateMessage->_status = privateMessage->_status | QMessage::Read; 
       
  3857     }
       
  3858     
       
  3859     switch (entry.Priority()) {
       
  3860     case EMsvHighPriority:
       
  3861         message.setPriority(QMessage::HighPriority);
       
  3862         break;
       
  3863     case EMsvMediumPriority:
       
  3864         message.setPriority(QMessage::NormalPriority);
       
  3865         break;
       
  3866     case EMsvLowPriority:
       
  3867         message.setPriority(QMessage::LowPriority);
       
  3868         break;
       
  3869     }
       
  3870 
       
  3871     if (entry.iMtm == KUidMsgTypePOP3) {
       
  3872         // All incoming POP3 messages are in the root of the POP3 service
       
  3873         QMessageAccount messageAccount = account(message.parentAccountId());
       
  3874         if (entry.Parent() == messageAccount.d_ptr->_service1EntryId) {
       
  3875             QMessagePrivate::setStandardFolder(message,QMessage::InboxFolder);
       
  3876         }
       
  3877     } else if (entry.iMtm == KUidMsgTypeIMAP4) {
       
  3878         // All incoming IMAP4 messages are in the folders which can
       
  3879         // be found from the root of the IMAP4 service
       
  3880         QMessageAccount messageAccount = account(message.parentAccountId());
       
  3881         CMsvEntry* pEntry = retrieveCMsvEntryAndPushToCleanupStack(entry.Parent());
       
  3882         if (pEntry->Entry().Parent() == messageAccount.d_ptr->_service1EntryId) {
       
  3883             QMessagePrivate::setStandardFolder(message,QMessage::InboxFolder);
       
  3884         }
       
  3885         releaseCMsvEntryAndPopFromCleanupStack(pEntry);
       
  3886     }
       
  3887     if (entry.Parent() == KMsvDraftEntryId) {
       
  3888         QMessagePrivate::setStandardFolder(message,QMessage::DraftsFolder);
       
  3889     } else if (entry.Parent() == KMsvSentEntryId) {
       
  3890         QMessagePrivate::setStandardFolder(message,QMessage::SentFolder);
       
  3891     } else if (entry.Parent() == KMsvDeletedEntryFolderEntryId) {
       
  3892         QMessagePrivate::setStandardFolder(message,QMessage::TrashFolder);
       
  3893     }       
       
  3894     
       
  3895     CImHeader* emailEntry = CImHeader::NewLC();
       
  3896     CImEmailMessage* emailMessage = CImEmailMessage::NewLC(receivedEntry);
       
  3897     CImMimeHeader* pImMimeHeader = CImMimeHeader::NewLC();
       
  3898 
       
  3899     TInt mimeHeaderReadError = KErrNotFound;
       
  3900     if (receivedEntry.HasStoreL()) {
       
  3901         CMsvStore* msvStore = receivedEntry.ReadStoreL();
       
  3902         CleanupStack::PushL(msvStore);
       
  3903         TRAP_IGNORE(emailEntry->RestoreL(*msvStore));
       
  3904         size += emailEntry->DataSize();
       
  3905         TRAP(mimeHeaderReadError, pImMimeHeader->RestoreL(*msvStore));
       
  3906         if (mimeHeaderReadError == KErrNone) {
       
  3907             size += pImMimeHeader->Size();
       
  3908         }
       
  3909         CleanupStack::PopAndDestroy(); // store
       
  3910         }
       
  3911     
       
  3912     if (!ipRichText) {
       
  3913         ipCharFormatLayer = CCharFormatLayer::NewL();
       
  3914         ipParaFormatLayer = CParaFormatLayer::NewL();
       
  3915         ipRichText = CRichText::NewL(ipParaFormatLayer, ipCharFormatLayer);
       
  3916     }
       
  3917     ipRichText->Reset();
       
  3918     emailMessage->GetBodyTextL(messageId,
       
  3919                                CImEmailMessage::EThisMessageOnly,
       
  3920                                *ipRichText,
       
  3921                                *ipParaFormatLayer,
       
  3922                                *ipCharFormatLayer);
       
  3923 	
       
  3924     // From GetBodyTextL() documentation:
       
  3925     // A list containing the entry Ids for each body text part within
       
  3926     // the specified message is created during this call. The list can
       
  3927     // be retrieved after this call has completed by calling Selection().
       
  3928     if (emailMessage->Selection().Count() > 0) {
       
  3929         if (pImMimeHeader->ContentType() == KImcvMultipart) {
       
  3930             // Get body content type (CImMimeHeader) from first body part
       
  3931             CMsvEntry* pEntry = retrieveCMsvEntryAndPushToCleanupStack(emailMessage->Selection()[0]);
       
  3932             if (pEntry->HasStoreL()) { 
       
  3933                 CMsvStore* pMsvStore = pEntry->ReadStoreL();
       
  3934                 CleanupStack::PushL(pMsvStore);
       
  3935                 TRAP(mimeHeaderReadError, pImMimeHeader->RestoreL(*pMsvStore));
       
  3936                 if (mimeHeaderReadError == KErrNone) {
       
  3937                     size += pImMimeHeader->Size();
       
  3938                 }
       
  3939                 CleanupStack::PopAndDestroy(pMsvStore);
       
  3940             }
       
  3941             releaseCMsvEntryAndPopFromCleanupStack(pEntry);
       
  3942         }
       
  3943     }
       
  3944     
       
  3945     QByteArray mimeType;
       
  3946     if (mimeHeaderReadError == KErrNone) {
       
  3947         TPtrC8 type = pImMimeHeader->ContentType();
       
  3948         if (type.Length() > 0) {
       
  3949             QByteArray contentType = QByteArray((const char *)type.Ptr(),type.Length());
       
  3950             mimeType.append(contentType);
       
  3951             mimeType.append("/");
       
  3952             
       
  3953             TPtrC8 subType = pImMimeHeader->ContentSubType();
       
  3954             if (subType.Length() > 0) {
       
  3955                 QByteArray contentSubType = QByteArray((const char *)subType.Ptr(),subType.Length());
       
  3956                 mimeType.append(contentSubType);
       
  3957             }    
       
  3958             TUint charset = pImMimeHeader->MimeCharset();
       
  3959             if (charset) {
       
  3960                 mimeType.append(";charset=");
       
  3961                 if (charset == KCharacterSetIdentifierUcs2)
       
  3962                     mimeType.append("UTF-16");
       
  3963                 else if (charset == KCharacterSetIdentifierUtf8)
       
  3964                     mimeType.append("UTF-8");
       
  3965             }
       
  3966         }
       
  3967     }
       
  3968     CleanupStack::PopAndDestroy(pImMimeHeader);
       
  3969     
       
  3970     HBufC* pMessage = HBufC::NewLC(ipRichText->DocumentLength());
       
  3971     TPtr ptr2(pMessage->Des());
       
  3972     ipRichText->Extract(ptr2);
       
  3973     if (pMessage->Length() > 0) {
       
  3974         QString text = QString::fromUtf16(pMessage->Ptr(),pMessage->Length());
       
  3975         message.setBody(text, mimeType);
       
  3976         size += text.size();
       
  3977     }
       
  3978     CleanupStack::PopAndDestroy(pMessage);
       
  3979         
       
  3980     //attachment(s)
       
  3981     emailMessage->GetAttachmentsListL(messageId, CImEmailMessage::EAllAttachments, CImEmailMessage::EThisMessageOnly);
       
  3982     TInt c = emailMessage->AttachmentManager().AttachmentCount();
       
  3983     if (c > 0) {
       
  3984         privateMessage->_status = privateMessage->_status | QMessage::HasAttachments; 
       
  3985     }
       
  3986     for (TInt i = 0; i < c; i++) {
       
  3987        CMsvAttachment* pAttachment = emailMessage->AttachmentManager().GetAttachmentInfoL(i);
       
  3988        CleanupStack::PushL(pAttachment);
       
  3989 
       
  3990        QByteArray mimeType;
       
  3991        QByteArray mimeSubType;
       
  3992        CImMimeHeader* pImMimeHeader = CImMimeHeader::NewLC();
       
  3993        CMsvEntry* pEntry = retrieveCMsvEntryAndPushToCleanupStack(pAttachment->Id());
       
  3994        if (pEntry->HasStoreL()) { 
       
  3995            CMsvStore* pMsvStore = pEntry->ReadStoreL();
       
  3996            CleanupStack::PushL(pMsvStore);
       
  3997            TRAP(mimeHeaderReadError, pImMimeHeader->RestoreL(*pMsvStore));
       
  3998            if (mimeHeaderReadError == KErrNone) {
       
  3999                size += pImMimeHeader->Size();
       
  4000            }
       
  4001            CleanupStack::PopAndDestroy(pMsvStore);
       
  4002        }
       
  4003        releaseCMsvEntryAndPopFromCleanupStack(pEntry);
       
  4004        if (mimeHeaderReadError == KErrNone) {
       
  4005            mimeType = QByteArray((const char *)pImMimeHeader->ContentType().Ptr(), pImMimeHeader->ContentType().Length());
       
  4006            mimeSubType = QByteArray((const char *)pImMimeHeader->ContentSubType().Ptr(), pImMimeHeader->ContentSubType().Length());
       
  4007        }
       
  4008        CleanupStack::PopAndDestroy(pImMimeHeader);
       
  4009        
       
  4010        QByteArray name = QString::fromUtf16(pAttachment->AttachmentName().Ptr(), pAttachment->AttachmentName().Length()).toLocal8Bit();
       
  4011        int attachmentSize = pAttachment->Size();
       
  4012        size += attachmentSize;
       
  4013        QMessageContentContainer attachment = QMessageContentContainerPrivate::from(messageId, pAttachment->Id(), name, mimeType, mimeSubType, attachmentSize);
       
  4014        appendAttachmentToMessage(message, attachment);
       
  4015        CleanupStack::PopAndDestroy(pAttachment);
       
  4016     }
       
  4017      
       
  4018     //from
       
  4019     TPtrC from = emailEntry->From();
       
  4020     if (from.Length() > 0) {
       
  4021         message.setFrom(QMessageAddress(QMessageAddress::Email, QString::fromUtf16(from.Ptr(), from.Length())));
       
  4022         QMessagePrivate::setSenderName(message, QString::fromUtf16(from.Ptr(), from.Length()));
       
  4023     } else {
       
  4024         if (entry.iDetails.Length() > 0)  {
       
  4025             QString fromString = QString::fromUtf16(receivedEntry.Entry().iDetails.Ptr(), receivedEntry.Entry().iDetails.Length());
       
  4026             message.setFrom(QMessageAddress(QMessageAddress::Email, fromString));
       
  4027             QMessagePrivate::setSenderName(message, fromString);
       
  4028         }
       
  4029     }
       
  4030    
       
  4031     //to
       
  4032     CDesCArray& toArray = emailEntry->ToRecipients();
       
  4033     QList<QMessageAddress> toList;
       
  4034     for (TInt i = 0; i < toArray.Count(); i++)
       
  4035     {
       
  4036         TPtrC16 to(toArray.MdcaPoint(i));
       
  4037         toList.append(QMessageAddress(QMessageAddress::Email, QString::fromUtf16(to.Ptr(), to.Length())));            
       
  4038     }
       
  4039     message.setTo(toList);
       
  4040     
       
  4041     //cc
       
  4042     CDesCArray& ccArray = emailEntry->CcRecipients();
       
  4043     QList<QMessageAddress> ccList;
       
  4044     for (TInt i = 0; i < ccArray.Count(); i++)
       
  4045     {
       
  4046         TPtrC16 cc(ccArray.MdcaPoint(i));
       
  4047         ccList.append(QMessageAddress(QMessageAddress::Email, QString::fromUtf16(cc.Ptr(), cc.Length())));            
       
  4048     }
       
  4049     message.setCc(ccList);
       
  4050     
       
  4051     //bcc
       
  4052     CDesCArray& bccArray = emailEntry->BccRecipients();
       
  4053     QList<QMessageAddress> bccList;
       
  4054     for (TInt i = 0; i < bccArray.Count(); i++)
       
  4055     {
       
  4056         TPtrC16 bcc(bccArray.MdcaPoint(i));
       
  4057         bccList.append(QMessageAddress(QMessageAddress::Email, QString::fromUtf16(bcc.Ptr(), bcc.Length())));            
       
  4058     }
       
  4059     message.setBcc(bccList);
       
  4060     
       
  4061     // Read message subject
       
  4062     TPtrC subject = emailEntry->Subject();
       
  4063     if (subject.Length() > 0) {
       
  4064         message.setSubject(QString::fromUtf16(subject.Ptr(), subject.Length()));
       
  4065     } else {
       
  4066         if (entry.iDescription.Length() > 0)  {
       
  4067             message.setSubject(QString::fromUtf16(receivedEntry.Entry().iDescription.Ptr(),
       
  4068                                                   receivedEntry.Entry().iDescription.Length()));
       
  4069         }    
       
  4070     }
       
  4071     
       
  4072     CleanupStack::PopAndDestroy(emailMessage);
       
  4073     CleanupStack::PopAndDestroy(emailEntry);
       
  4074 
       
  4075     privateMessage->_size = size;
       
  4076     
       
  4077     return message;
       
  4078 }
       
  4079 
       
  4080 void CMTMEngine::appendAttachmentToMessage(QMessage& message, QMessageContentContainer& attachment) const
       
  4081 {
       
  4082     QMessagePrivate* privateMessage = QMessagePrivate::implementation(message);
       
  4083     QMessageContentContainerPrivate* container = QMessagePrivate::containerImplementation(message);
       
  4084     
       
  4085     if (container->_attachments.isEmpty()) {
       
  4086         QMessageContentContainerId existingBodyId(message.bodyId());
       
  4087         if (existingBodyId == QMessageContentContainerPrivate::bodyContentId()) {
       
  4088             // The body content is in the message itself - move it to become the first attachment
       
  4089             QMessageContentContainer newBody(message);
       
  4090             QMessageContentContainerPrivate::implementation(newBody)->setDerivedMessage(0);
       
  4091     
       
  4092             container->setContentType("multipart", "mixed", "");
       
  4093             privateMessage->_bodyId = container->prependContent(newBody);
       
  4094         } else {
       
  4095             // This message is now multipart
       
  4096             container->setContentType("multipart", "mixed", "");
       
  4097         }
       
  4098     
       
  4099         container->_available = true;
       
  4100     }
       
  4101     
       
  4102     container->appendContent(attachment);
       
  4103     
       
  4104     bool haveAttachments = !container->_attachments.isEmpty();
       
  4105     message.setStatus(QMessage::HasAttachments,haveAttachments);
       
  4106     
       
  4107     privateMessage->_modified = true;
       
  4108 }
       
  4109 
       
  4110 QByteArray CMTMEngine::attachmentContent(long int messageId, unsigned int attachmentId)
       
  4111 {
       
  4112     QByteArray result;
       
  4113     TRAP_IGNORE(result = attachmentContentL(messageId, attachmentId));
       
  4114     return result;
       
  4115 }
       
  4116 
       
  4117 QByteArray CMTMEngine::attachmentContentL(long int messageId, unsigned int attachmentId)
       
  4118 {
       
  4119     QByteArray result;
       
  4120     
       
  4121     CMsvEntry* pEntry = retrieveCMsvEntryAndPushToCleanupStack(messageId);
       
  4122     if (pEntry->Entry().iMtm == KUidMsgTypeMultimedia) { // MMS
       
  4123         CMsvStore* pStore = pEntry->ReadStoreL();
       
  4124         CleanupStack::PushL(pStore);
       
  4125         RFile file = pStore->AttachmentManagerL().GetAttachmentFileL(attachmentId);
       
  4126         CleanupClosePushL(file);
       
  4127         TInt fileSize;
       
  4128         file.Size(fileSize);
       
  4129         TBuf<KMaxFileName> fileName;
       
  4130         file.Name(fileName);
       
  4131         HBufC8* pFileContent = HBufC8::NewL(fileSize);
       
  4132         TPtr8 fileContent(pFileContent->Des());
       
  4133         file.Read(fileContent);
       
  4134         CleanupStack::PopAndDestroy(&file);
       
  4135         CleanupStack::PushL(pFileContent);
       
  4136         
       
  4137         result = QByteArray((char*)pFileContent->Ptr(),pFileContent->Length());
       
  4138         
       
  4139         CleanupStack::PopAndDestroy(pFileContent);
       
  4140         CleanupStack::PopAndDestroy(pStore);
       
  4141     } else { // Email
       
  4142         CImEmailMessage* pImEmailMessage = CImEmailMessage::NewLC(*pEntry);
       
  4143         RFile file = pImEmailMessage->AttachmentManager().GetAttachmentFileL(attachmentId);
       
  4144         CleanupClosePushL(file);
       
  4145         TInt fileSize;
       
  4146         file.Size(fileSize);
       
  4147         TBuf<KMaxFileName> fileName;
       
  4148         file.Name(fileName);
       
  4149         HBufC8* pFileContent = HBufC8::NewL(fileSize);
       
  4150         TPtr8 fileContent(pFileContent->Des());
       
  4151         file.Read(fileContent);
       
  4152         CleanupStack::PopAndDestroy(&file);
       
  4153         CleanupStack::PushL(pFileContent);
       
  4154         
       
  4155         result = QByteArray((char*)pFileContent->Ptr(),pFileContent->Length());
       
  4156         
       
  4157         CleanupStack::PopAndDestroy(pFileContent);
       
  4158         CleanupStack::PopAndDestroy(pImEmailMessage);
       
  4159     }
       
  4160     releaseCMsvEntryAndPopFromCleanupStack(pEntry);
       
  4161     
       
  4162     return result;
       
  4163 }
       
  4164 
       
  4165 QString CMTMEngine::attachmentTextContent(long int messageId, unsigned int attachmentId, const QByteArray &charset)
       
  4166 {
       
  4167     QString result;
       
  4168     
       
  4169     QByteArray data = attachmentContent(messageId, attachmentId);
       
  4170     if (!data.isEmpty()) {
       
  4171         // Convert attachment data to string form
       
  4172         QTextCodec *codec;
       
  4173         if (!charset.isEmpty()) {
       
  4174             codec = QTextCodec::codecForName(charset);
       
  4175         } else {
       
  4176             codec = QTextCodec::codecForLocale();
       
  4177         }
       
  4178 
       
  4179         if (codec) {
       
  4180             result = codec->toUnicode(data);
       
  4181         }
       
  4182     }
       
  4183     
       
  4184     return result;
       
  4185 }
       
  4186 
       
  4187 QMessage CMTMEngine::pop3MessageL(CMsvEntry& /*receivedEntry*/, long int /*messageId*/) const
       
  4188 {
       
  4189     return QMessage();
       
  4190 }
       
  4191 
       
  4192 QMessage CMTMEngine::imap4MessageL(CMsvEntry& /*receivedEntry*/, long int /*messageId*/) const
       
  4193 {
       
  4194     return QMessage();
       
  4195 }
       
  4196 
       
  4197 CMsvEntry* CMTMEngine::retrieveCMsvEntryAndPushToCleanupStack(TMsvId id) const
       
  4198 {
       
  4199     CMsvEntry* pEntry = NULL;
       
  4200 
       
  4201     if (iCmsvEntryPoolFree.Count() > 0) {
       
  4202         pEntry = iCmsvEntryPoolFree[iCmsvEntryPoolFree.Count()-1];
       
  4203         TInt retVal = iCmsvEntryPoolInUse.Append(pEntry);
       
  4204         if (retVal != KErrNone) {
       
  4205             delete pEntry;
       
  4206             pEntry = NULL;
       
  4207         }
       
  4208     } else {
       
  4209         if (id == 0) {
       
  4210             id = KMsvRootIndexEntryId;
       
  4211         }
       
  4212         TRAPD(err, pEntry = ipMsvSession->GetEntryL(id));
       
  4213         if (err == KErrNone) {
       
  4214             TInt retVal = iCmsvEntryPoolInUse.Append(pEntry);
       
  4215             if (retVal != KErrNone) {
       
  4216                 delete pEntry;
       
  4217                 pEntry = NULL;
       
  4218             }
       
  4219         }
       
  4220     }
       
  4221     
       
  4222     if (id != 0 && pEntry) {
       
  4223         TRAPD(err, pEntry->SetEntryL(id));
       
  4224         if (err != KErrNone) {
       
  4225             TInt pos = iCmsvEntryPoolInUse.Find(pEntry);
       
  4226             if (pos != KErrNotFound) {
       
  4227                 iCmsvEntryPoolInUse.Remove(pos);
       
  4228                 TInt retVal = iCmsvEntryPoolFree.Append(pEntry);
       
  4229                 if (retVal != KErrNone) {
       
  4230                     delete pEntry;
       
  4231                 }
       
  4232             }        
       
  4233             pEntry = NULL;
       
  4234         }
       
  4235     }
       
  4236     
       
  4237     if (pEntry) {
       
  4238         TCleanupItem entryCleanup(cmsvEntryCleanup, pEntry);
       
  4239         CleanupStack::PushL(entryCleanup);
       
  4240     }
       
  4241 
       
  4242     return pEntry;
       
  4243 }
       
  4244 
       
  4245 void CMTMEngine::cmsvEntryCleanup(TAny* aCMsvEntry)
       
  4246 {
       
  4247     CMTMEngine* pMTMEngine = mtmEngine();
       
  4248     CMsvEntry* pEntry = (CMsvEntry*)aCMsvEntry;
       
  4249 
       
  4250     TInt pos = pMTMEngine->iCmsvEntryPoolInUse.Find(pEntry);
       
  4251     if (pos != KErrNotFound) {
       
  4252         pMTMEngine->iCmsvEntryPoolInUse.Remove(pos);
       
  4253         TInt retVal = pMTMEngine->iCmsvEntryPoolFree.Append(pEntry);
       
  4254         if (retVal != KErrNone) {
       
  4255             delete pEntry;
       
  4256         }
       
  4257     }
       
  4258 }
       
  4259 
       
  4260 void CMTMEngine::releaseCMsvEntryAndPopFromCleanupStack(CMsvEntry* pEntry) const
       
  4261 {
       
  4262     if (pEntry) {
       
  4263         CleanupStack::Pop(); // Entry cleanup
       
  4264     }
       
  4265 
       
  4266     TInt pos = iCmsvEntryPoolInUse.Find(pEntry);
       
  4267     if (pos != KErrNotFound) {
       
  4268         iCmsvEntryPoolInUse.Remove(pos);
       
  4269         TInt retVal = iCmsvEntryPoolFree.Append(pEntry);
       
  4270         if (retVal != KErrNone) {
       
  4271             delete pEntry;
       
  4272         }
       
  4273     }
       
  4274 }
       
  4275 
       
  4276 QMessageManager::NotificationFilterId CMTMEngine::registerNotificationFilter(QMessageStorePrivate& aPrivateStore,
       
  4277                                                                            const QMessageFilter &filter)
       
  4278 {
       
  4279     ipMessageStorePrivate = &aPrivateStore;
       
  4280     iListenForNotifications = true;    
       
  4281 
       
  4282     int filterId = ++_filterId;
       
  4283     _filters.insert(filterId, filter);
       
  4284     return filterId;
       
  4285 }
       
  4286 
       
  4287 void CMTMEngine::unregisterNotificationFilter(QMessageManager::NotificationFilterId notificationFilterId)
       
  4288 {
       
  4289     _filters.remove(notificationFilterId);
       
  4290     if (_filters.count() == 0) {
       
  4291         iListenForNotifications = false;
       
  4292     }
       
  4293 }
       
  4294 
       
  4295 bool CMTMEngine::checkIfWaitingDiscardClearMessage(TMsvId aMessageId)
       
  4296 {
       
  4297     TRAPD(err, ipSmsMtm->SwitchCurrentEntryL(aMessageId));
       
  4298     if (err != KErrNone) {
       
  4299         return false;
       
  4300     }
       
  4301     TRAPD(err2, ipSmsMtm->LoadMessageL());
       
  4302     if (err2 != KErrNone) {
       
  4303         return false;
       
  4304     }
       
  4305 
       
  4306     CSmsHeader& header = ipSmsMtm->SmsHeader();       
       
  4307     CSmsPDU& pdu = header.Message().SmsPDU();
       
  4308     
       
  4309     TInt bits7to4 = pdu.Bits7To4();
       
  4310 
       
  4311     TSmsDataCodingScheme::TSmsIndicationState indicationState =
       
  4312         TSmsDataCodingScheme::ESmsIndicationInactive;
       
  4313 
       
  4314     switch (bits7to4) {
       
  4315         case TSmsDataCodingScheme::ESmsDCSMessageWaitingIndication7Bit:
       
  4316         case TSmsDataCodingScheme::ESmsDCSMessageWaitingIndicationUCS2:
       
  4317         case TSmsDataCodingScheme::ESmsDCSMessageWaitingIndicationDiscardMessage:
       
  4318             { 
       
  4319             indicationState = pdu.IndicationState();
       
  4320             
       
  4321             if (indicationState == TSmsDataCodingScheme::ESmsIndicationInactive) {
       
  4322                 return true; // discard clear message
       
  4323             } else if (indicationState == TSmsDataCodingScheme::ESmsIndicationActive) {
       
  4324                 return false; // set message
       
  4325             }
       
  4326             }
       
  4327 
       
  4328         default:
       
  4329             return false; // normal sms message
       
  4330     }
       
  4331 
       
  4332 }
       
  4333 
       
  4334 void CMTMEngine::notification(TMsvSessionEvent aEvent, TUid aMsgType, TMsvId aFolderId, TMsvId aMessageId)
       
  4335 {
       
  4336     if (aFolderId == 0x100001 || aFolderId == 0x100002) { // MMS Notifications Folder
       
  4337         // Ignore MMS Notifications <=> Wait until actual MMS message has been received
       
  4338         return;
       
  4339     }
       
  4340 
       
  4341 #ifdef NCNLISTREMOVED
       
  4342     if (aMsgType == KUidMsgTypeSMS) { // we need to check if sms message is 'indicator clear message' (for voice messages)
       
  4343         if (aEvent == EMsvEntriesCreated) {
       
  4344             iNewMessage = true;
       
  4345             iMessageId = aMessageId;
       
  4346             // cannot be sure if sms is indicator clear message, we have to wait changed event
       
  4347             return;
       
  4348         }
       
  4349         else if (aEvent == EMsvEntriesChanged && iNewMessage && iMessageId == aMessageId) {
       
  4350             iNewMessage = false;
       
  4351             aEvent = EMsvEntriesCreated;
       
  4352             bool clearMessage = checkIfWaitingDiscardClearMessage(aMessageId);
       
  4353             if (clearMessage){
       
  4354                 return;
       
  4355             }
       
  4356         }
       
  4357         else {
       
  4358             iNewMessage = false;
       
  4359             iMessageId = 0;
       
  4360         }
       
  4361     }
       
  4362 #endif // NCNLISTREMOVED
       
  4363     
       
  4364     QMessageManager::NotificationFilterIdSet matchingFilters;
       
  4365 
       
  4366     // Copy the filter map to protect against modification during traversal
       
  4367     QMap<int, QMessageFilter> filters(_filters);
       
  4368     QMap<int, QMessageFilter>::const_iterator it = filters.begin(), end = filters.end();
       
  4369     QMessage message;
       
  4370     bool messageRetrieved = false;
       
  4371     bool unableToReadAndFilterMessage = false;
       
  4372     for ( ; it != end; ++it) {
       
  4373         const QMessageFilter &filter(it.value());
       
  4374 
       
  4375         if (filter.isEmpty()) {
       
  4376             // Empty filter matches to all messages
       
  4377             matchingFilters.insert(it.key());
       
  4378         } else {
       
  4379             QMessageFilterPrivate* privateMessageFilter = QMessageFilterPrivate::implementation(filter);
       
  4380             if (privateMessageFilter->_field == QMessageFilterPrivate::Type && aEvent != EMsvEntriesCreated) {
       
  4381                 if (aMsgType == KUidMsgTypeSMS) {
       
  4382                     message.setType(QMessage::Sms);
       
  4383                 } else if (aMsgType == KUidMsgTypeMultimedia) {
       
  4384                     message.setType(QMessage::Mms);
       
  4385                 } else if (aMsgType == KUidMsgTypeSMTP ||
       
  4386                            aMsgType == KUidMsgTypePOP3 ||
       
  4387                            aMsgType == KUidMsgTypeIMAP4) {
       
  4388                     message.setType(QMessage::Email);
       
  4389                 } else {
       
  4390                     message.setType(QMessage::NoType);
       
  4391                 }
       
  4392             } else if ((privateMessageFilter->_field == QMessageFilterPrivate::StandardFolder && aEvent != EMsvEntriesCreated) &&
       
  4393                        (aMsgType == KUidMsgTypeSMS || aMsgType == KUidMsgTypeMultimedia)) {
       
  4394                 if (aFolderId == KMsvGlobalInBoxIndexEntryId) {
       
  4395                     QMessagePrivate::setStandardFolder(message,QMessage::InboxFolder);
       
  4396                 } else if (aFolderId == KMsvDraftEntryId) {
       
  4397                     QMessagePrivate::setStandardFolder(message,QMessage::DraftsFolder);
       
  4398                 } else if (aFolderId == KMsvSentEntryId) {
       
  4399                     QMessagePrivate::setStandardFolder(message,QMessage::SentFolder);
       
  4400                 } else if (aFolderId == KMsvDeletedEntryFolderEntryId) {
       
  4401                     QMessagePrivate::setStandardFolder(message,QMessage::TrashFolder);
       
  4402                 }
       
  4403             } else if (!messageRetrieved) {           
       
  4404                 message = this->message(QMessageId(SymbianHelpers::addIdPrefix(QString::number(aMessageId),SymbianHelpers::EngineTypeMTM)));
       
  4405                 if (message.type() == QMessage::NoType) {
       
  4406                     unableToReadAndFilterMessage = true;
       
  4407                     matchingFilters.clear();
       
  4408                     break;
       
  4409                 } else {
       
  4410                     messageRetrieved = true;
       
  4411                 }
       
  4412             }
       
  4413             if (privateMessageFilter->filter(message)) {
       
  4414                 matchingFilters.insert(it.key());
       
  4415             }
       
  4416         }
       
  4417     }
       
  4418 
       
  4419     QMessageStorePrivate::NotificationType notificationType = QMessageStorePrivate::Removed;
       
  4420     if (aEvent == EMsvEntriesCreated) {
       
  4421         notificationType = QMessageStorePrivate::Added; 
       
  4422     } else if (aEvent == EMsvEntriesChanged || aEvent == EMsvEntriesMoved) {
       
  4423         notificationType = QMessageStorePrivate::Updated; 
       
  4424     } if (aEvent == EMsvEntriesDeleted) {
       
  4425         notificationType = QMessageStorePrivate::Removed; 
       
  4426     }
       
  4427 
       
  4428     if (matchingFilters.count() > 0) {
       
  4429         // Check if there are already pending events for
       
  4430         // currently handled MessageId
       
  4431         bool pendingEventsForCurrentlyHandledMessageId = false;
       
  4432         for (int i=0; i < iUndeliveredMessageEvents.count(); i++) {
       
  4433             if (iUndeliveredMessageEvents[i].messageId == aMessageId) {
       
  4434                 pendingEventsForCurrentlyHandledMessageId = true;
       
  4435                 break;
       
  4436             }
       
  4437         }
       
  4438         if (pendingEventsForCurrentlyHandledMessageId) {
       
  4439             // There are pending notification events for this messageId.
       
  4440             // => Add new notification event to notification event queue to
       
  4441             //    make sure that all events will be delivered in correct order.
       
  4442             MessageEvent event;
       
  4443             event.messageId = aMessageId;
       
  4444             event.notificationType = notificationType;
       
  4445             event.matchingFilters = matchingFilters;
       
  4446             event.unfiltered = false;
       
  4447             if (iUndeliveredMessageEvents.count() == 0) {
       
  4448                 iDeliveryTriesCounter = 0;
       
  4449             }
       
  4450             iUndeliveredMessageEvents.append(event);
       
  4451             tryToDeliverMessageNotifications();
       
  4452         } else {
       
  4453             // No pending notification events for this messageId.
       
  4454             // => Deliver notification immediately
       
  4455             ipMessageStorePrivate->messageNotification(notificationType,
       
  4456                                                        QMessageId(SymbianHelpers::addIdPrefix(QString::number(aMessageId),SymbianHelpers::EngineTypeMTM)),
       
  4457                                                        matchingFilters);
       
  4458         }
       
  4459     } else if (unableToReadAndFilterMessage) {
       
  4460         if (notificationType != QMessageStorePrivate::Removed) {
       
  4461             MessageEvent event;
       
  4462             event.messageId = aMessageId;
       
  4463             event.notificationType = notificationType;
       
  4464             event.unfiltered = true;
       
  4465             if (iUndeliveredMessageEvents.count() == 0) {
       
  4466                 iDeliveryTriesCounter = 0;
       
  4467             }
       
  4468             iUndeliveredMessageEvents.append(event);
       
  4469             tryToDeliverMessageNotifications();
       
  4470         } else {
       
  4471             // Message was removed before reading was possible
       
  4472             // => All avents related to removed messageId can be ignored
       
  4473             // => Remove all related events from undelivered message events queue
       
  4474             for (int i=iUndeliveredMessageEvents.count()-1; i >= 0; i--) {
       
  4475                 if (iUndeliveredMessageEvents[i].messageId == aMessageId) {
       
  4476                     iUndeliveredMessageEvents.removeAt(i);
       
  4477                 }
       
  4478             }
       
  4479         }
       
  4480     }
       
  4481 }
       
  4482 
       
  4483 void CMTMEngine::tryToDeliverMessageNotifications()
       
  4484 {
       
  4485     if (!IsActive()) {
       
  4486         int count = iUndeliveredMessageEvents.count();
       
  4487         while (count--) {
       
  4488             // Try to deliver the oldest message event notification first
       
  4489             MessageEvent event = iUndeliveredMessageEvents[0];
       
  4490             bool eventHandlingPossible = true;
       
  4491             if (event.notificationType != QMessageStorePrivate::Removed && event.unfiltered) {
       
  4492                 QMessage message = this->message(QMessageId(SymbianHelpers::addIdPrefix(QString::number(event.messageId),SymbianHelpers::EngineTypeMTM)));
       
  4493                 if (message.type() == QMessage::NoType) {
       
  4494                     eventHandlingPossible = false;
       
  4495                 } else {
       
  4496                     event.matchingFilters.clear();
       
  4497                     // Copy the filter map to protect against modification during traversal
       
  4498                     QMap<int, QMessageFilter> filters(_filters);
       
  4499                     QMap<int, QMessageFilter>::const_iterator it = filters.begin(), end = filters.end();
       
  4500                     for ( ; it != end; ++it) {
       
  4501                         const QMessageFilter &filter(it.value());
       
  4502                         if (filter.isEmpty()) {
       
  4503                             // Empty filter matches to all messages
       
  4504                             event.matchingFilters.insert(it.key());
       
  4505                         } else {
       
  4506                             QMessageFilterPrivate* privateMessageFilter = QMessageFilterPrivate::implementation(filter);
       
  4507                             if (privateMessageFilter->filter(message)) {
       
  4508                                 event.matchingFilters.insert(it.key());
       
  4509                             }
       
  4510                         }
       
  4511                     }
       
  4512                 }
       
  4513             }
       
  4514     
       
  4515             if (eventHandlingPossible) {
       
  4516                 // New message entry was ready to be read
       
  4517                 // Remove message event from queue
       
  4518                 iUndeliveredMessageEvents.removeFirst();
       
  4519                 iDeliveryTriesCounter = 0;
       
  4520                 if (event.matchingFilters.count() > 0) { 
       
  4521                     // Deliver message event notification
       
  4522                     ipMessageStorePrivate->messageNotification(event.notificationType,
       
  4523                                                                QMessageId(SymbianHelpers::addIdPrefix(QString::number(event.messageId),SymbianHelpers::EngineTypeMTM)),
       
  4524                                                                event.matchingFilters);
       
  4525                 }
       
  4526             } else {
       
  4527                 // New message entry was NOT ready to be read
       
  4528                 iDeliveryTriesCounter++;
       
  4529                 if (iDeliveryTriesCounter < 50) { 
       
  4530                     // Wait for 0.1 seconds to see if message would
       
  4531                     // be ready to be read & delivered after wait.
       
  4532                     iTimer.After(iStatus, KWaitAfterReceivedMessage);
       
  4533                     SetActive();
       
  4534                     break;
       
  4535                 } else {
       
  4536                     // Remove problematic message event from queue
       
  4537                     iUndeliveredMessageEvents.removeFirst();
       
  4538                     iDeliveryTriesCounter = 0;
       
  4539                 }
       
  4540             }
       
  4541         }
       
  4542     }
       
  4543 }
       
  4544 
       
  4545 void CMTMEngine::RunL()
       
  4546 {
       
  4547     tryToDeliverMessageNotifications();
       
  4548 }
       
  4549 
       
  4550 
       
  4551 void CMTMEngine::DoCancel()
       
  4552 {
       
  4553     iTimer.Cancel();
       
  4554 }
       
  4555 
       
  4556 void CMTMEngine::HandleSessionEventL(TMsvSessionEvent aEvent, TAny* aArg1,
       
  4557                                     TAny* aArg2, TAny* /*aArg3*/)
       
  4558 {
       
  4559     switch (aEvent) {
       
  4560     case EMsvServerReady:
       
  4561         iSessionReady = ETrue;
       
  4562         break;
       
  4563     case EMsvEntriesCreated:
       
  4564     case EMsvEntriesChanged:
       
  4565     case EMsvEntriesDeleted:
       
  4566     case EMsvEntriesMoved:
       
  4567         if (aArg2 && iListenForNotifications) {
       
  4568             CMsvEntrySelection* entries = static_cast<CMsvEntrySelection*>(aArg1);
       
  4569             
       
  4570             if (entries != NULL) {
       
  4571                TInt count = entries->Count();
       
  4572                while (count--) {
       
  4573                    const TMsvId id = (*entries)[count];
       
  4574                    if (aEvent == EMsvEntriesDeleted) {
       
  4575                        notification(aEvent, TUid(), *(static_cast<TMsvId*>(aArg2)), id);
       
  4576                    } else {
       
  4577                        CMsvEntry* pReceivedEntry = NULL;
       
  4578                        TRAPD(err, pReceivedEntry = ipMsvSession->GetEntryL(id));
       
  4579                        if (err == KErrNone) {
       
  4580                            const TMsvEntry& entry = pReceivedEntry->Entry();
       
  4581                            if (entry.iType == KUidMsvMessageEntry) {
       
  4582                                notification(aEvent, entry.iMtm, *(static_cast<TMsvId*>(aArg2)), id);
       
  4583                            }
       
  4584                            delete pReceivedEntry;
       
  4585                        }
       
  4586                    }
       
  4587                }
       
  4588             }
       
  4589         }
       
  4590         break;
       
  4591     
       
  4592     default:
       
  4593         break;
       
  4594     }
       
  4595 }
       
  4596 
       
  4597 CAsynchronousMTMOperation* CMTMEngine::createAsynchronousMTMOperation(QMessageServicePrivate& privateService,
       
  4598                                                                       CBaseMtm* mtm,
       
  4599                                                                       TMsvId serviceId)
       
  4600 {
       
  4601     TInt operationId = ++iOperationIds;
       
  4602     CAsynchronousMTMOperation* op = new CAsynchronousMTMOperation((CMTMEngine&)*this,
       
  4603                                                                    privateService,
       
  4604                                                                    mtm,
       
  4605                                                                    serviceId,
       
  4606                                                                    operationId);
       
  4607     return op;
       
  4608 }
       
  4609 
       
  4610 void CMTMEngine::deleteAsynchronousMTMOperation(CAsynchronousMTMOperation *apOperation)
       
  4611 {
       
  4612     delete apOperation;
       
  4613 }
       
  4614 
       
  4615 CMessagesFindOperation::CMessagesFindOperation(CMTMEngine& aOwner, CMsvSession* apMsvSession, int aOperationId)
       
  4616     : CActive(CActive::EPriorityStandard), iOwner(aOwner), ipMsvSession(apMsvSession), iOperationId(aOperationId),
       
  4617         iResultCorrectlyOrdered(false)
       
  4618 {
       
  4619     CActiveScheduler::Add(this);
       
  4620     iTimer.CreateLocal();
       
  4621 }
       
  4622 
       
  4623 CMessagesFindOperation::~CMessagesFindOperation()
       
  4624 {
       
  4625     Cancel();
       
  4626     iTimer.Close();
       
  4627     delete ipMsvFindOperation;
       
  4628     delete ipEntrySelection;
       
  4629 }
       
  4630 
       
  4631 void CMessagesFindOperation::DoCancel()
       
  4632 {
       
  4633     ipMsvFindOperation->Cancel();
       
  4634 }
       
  4635 
       
  4636 void CMessagesFindOperation::filterAndOrderMessages(const QMessageFilter &filter, const QMessageSortOrder& sortOrder,
       
  4637                                                     QString body, QMessageDataComparator::MatchFlags matchFlags)
       
  4638 {
       
  4639     iFilterList.clear();
       
  4640     iFilterList.append(filter);
       
  4641     filterAndOrderMessages(iFilterList, sortOrder, body, matchFlags);
       
  4642 }
       
  4643 
       
  4644 void CMessagesFindOperation::filterAndOrderMessages(const QMessageFilterPrivate::SortedMessageFilterList& filters,
       
  4645                                                     const QMessageSortOrder& sortOrder,
       
  4646                                                     QString body,
       
  4647                                                     QMessageDataComparator::MatchFlags matchFlags)
       
  4648 {
       
  4649     delete ipMsvFindOperation;
       
  4650     ipMsvFindOperation = NULL;
       
  4651     delete ipEntrySelection;
       
  4652     ipEntrySelection = NULL;
       
  4653     iNumberOfHandledFilters = 0;
       
  4654 
       
  4655     if (filters.count() == 0) {
       
  4656         iIdList = QMessageIdList();
       
  4657         iTimer.After(iStatus, 1);
       
  4658         if (!IsActive()) {
       
  4659             SetActive();
       
  4660         }
       
  4661         return;
       
  4662     }
       
  4663     
       
  4664     QMessageFilterPrivate* pf = QMessageFilterPrivate::implementation(filters[iNumberOfHandledFilters]);
       
  4665     if ((filters.count() == 1) &&
       
  4666         (pf->_field == QMessageFilterPrivate::None) &&
       
  4667         (pf->_filterList.count() == 0)) {
       
  4668         if (pf->_notFilter) {
       
  4669             // There is only one filter: empty ~QMessageFilter()
       
  4670             // => return empty QMessageIdList 
       
  4671             iIdList = QMessageIdList();
       
  4672         } else {
       
  4673             // There is only one filter: empty QMessageFilter()
       
  4674             // => return all messages
       
  4675             ipEntrySelection = new(ELeave)CMsvEntrySelection;
       
  4676             getAllMessagesL(iOrdering);
       
  4677             iIdList = QMessageIdList();
       
  4678             for (int i=0; i < ipEntrySelection->Count(); i++) {
       
  4679                 iIdList.append(QMessageId(SymbianHelpers::addIdPrefix(QString::number((*ipEntrySelection)[i]),SymbianHelpers::EngineTypeMTM)));
       
  4680             }
       
  4681         }
       
  4682         iNumberOfHandledFilters++;
       
  4683         iTimer.After(iStatus, 1);
       
  4684         if (!IsActive()) {
       
  4685             SetActive();
       
  4686         }
       
  4687         return;
       
  4688     }
       
  4689     
       
  4690     // Set sortOrder
       
  4691     if (!sortOrder.isEmpty() ) {
       
  4692         QMessageSortOrderPrivate* privateMessageOrdering = QMessageSortOrderPrivate::implementation(sortOrder);
       
  4693         iOrdering.SetShowInvisibleEntries(EFalse);
       
  4694         QPair<QMessageSortOrderPrivate::Field, Qt::SortOrder> fieldOrder = privateMessageOrdering->_fieldOrderList.at(0);
       
  4695         switch (fieldOrder.first) {
       
  4696         case QMessageSortOrderPrivate::Type:
       
  4697             iOrdering.SetGroupByMtm(true);
       
  4698             break;
       
  4699         case QMessageSortOrderPrivate::Sender:
       
  4700             if (fieldOrder.second == Qt::AscendingOrder) {
       
  4701                 iOrdering.SetSorting(EMsvSortByDetails); // To/From (A-Z folded)
       
  4702             } else {
       
  4703                 iOrdering.SetSorting(EMsvSortByDetailsReverse); // To/From (Z-A folded)
       
  4704             }
       
  4705             break;
       
  4706         case QMessageSortOrderPrivate::Recipients:
       
  4707             if (fieldOrder.second == Qt::AscendingOrder) {
       
  4708                 iOrdering.SetSorting(EMsvSortByDetails); // To/From (A-Z folded)
       
  4709             } else {
       
  4710                 iOrdering.SetSorting(EMsvSortByDetailsReverse); // To/From (Z-A folded)
       
  4711             }
       
  4712             break;
       
  4713         case QMessageSortOrderPrivate::Subject:
       
  4714             if (fieldOrder.second == Qt::AscendingOrder) {
       
  4715                 iOrdering.SetSorting(EMsvSortByDescription); // Description (A-Z folded)
       
  4716             } else {
       
  4717                 iOrdering.SetSorting(EMsvSortByDescriptionReverse); // Description (Z-A folded)
       
  4718             }
       
  4719             break;
       
  4720         case QMessageSortOrderPrivate::TimeStamp:
       
  4721             if (fieldOrder.second == Qt::AscendingOrder) {
       
  4722                 iOrdering.SetSorting(EMsvSortByDate); // Date (earliest-latest) 
       
  4723             } else {
       
  4724                 iOrdering.SetSorting(EMsvSortByDateReverse); // Date (latest-earliest)
       
  4725             }
       
  4726             break;
       
  4727         case QMessageSortOrderPrivate::ReceptionTimeStamp:
       
  4728             if (fieldOrder.second == Qt::AscendingOrder) {
       
  4729                 iOrdering.SetSorting(EMsvSortByDate); // Date (earliest-latest) 
       
  4730             } else {
       
  4731                 iOrdering.SetSorting(EMsvSortByDateReverse); // Date (latest-earliest)
       
  4732             }
       
  4733             break;
       
  4734         case QMessageSortOrderPrivate::Read:
       
  4735             //TODO:
       
  4736             break;
       
  4737         case QMessageSortOrderPrivate::HasAttachments:
       
  4738             //TODO:
       
  4739             break;
       
  4740         case QMessageSortOrderPrivate::Incoming:
       
  4741             //TODO:
       
  4742             break;
       
  4743         case QMessageSortOrderPrivate::Removed:
       
  4744             //TODO:
       
  4745             break;
       
  4746         case QMessageSortOrderPrivate::Priority:
       
  4747             //iOrdering.SetGroupByPriority(true);
       
  4748             break;
       
  4749         case QMessageSortOrderPrivate::Size:
       
  4750             if (fieldOrder.second == Qt::AscendingOrder) {
       
  4751                 iOrdering.SetSorting(EMsvSortBySize); // (smallest-largest) 
       
  4752             } else {
       
  4753                 iOrdering.SetSorting(EMsvSortBySizeReverse); // (largest-smallest)
       
  4754             }
       
  4755             break;
       
  4756         }
       
  4757     }
       
  4758 
       
  4759     switch (pf->_field) {
       
  4760     case QMessageFilterPrivate::Id:
       
  4761         {
       
  4762         iNumberOfHandledFilters++;
       
  4763         if (pf->_comparatorType == QMessageFilterPrivate::Equality) { // QMessageId
       
  4764             QMessageDataComparator::EqualityComparator cmp(static_cast<QMessageDataComparator::EqualityComparator>(pf->_comparatorValue));
       
  4765             if (!pf->_value.isNull() && pf->_value.toString().length() > QString(SymbianHelpers::mtmPrefix).length()) {
       
  4766                 if (cmp == QMessageDataComparator::Equal) {
       
  4767                     long int messageId = SymbianHelpers::stripIdPrefix(pf->_value.toString()).toLong();
       
  4768                     CMsvEntry* pEntry = iOwner.retrieveCMsvEntryAndPushToCleanupStack(messageId);
       
  4769                     if (pEntry) {
       
  4770                         const TMsvEntry& entry = pEntry->Entry();
       
  4771                         if (entry.iType == KUidMsvMessageEntry) {
       
  4772                             ipEntrySelection = new(ELeave)CMsvEntrySelection;
       
  4773                             ipEntrySelection->AppendL(messageId);
       
  4774                         }
       
  4775                         iOwner.releaseCMsvEntryAndPopFromCleanupStack(pEntry);
       
  4776                     }
       
  4777                     iResultCorrectlyOrdered = true;
       
  4778                 } else { // NotEqual
       
  4779                     ipEntrySelection = new(ELeave)CMsvEntrySelection;
       
  4780                     getAllMessagesL(iOrdering);
       
  4781                     long int messageId = SymbianHelpers::stripIdPrefix(pf->_value.toString()).toLong();
       
  4782                     for (int i=0; i < ipEntrySelection->Count(); i++) {
       
  4783                         if (ipEntrySelection->At(i) == messageId) {
       
  4784                             ipEntrySelection->Delete(i);
       
  4785                             break;
       
  4786                         }
       
  4787                     }
       
  4788                 }
       
  4789             } else {
       
  4790                 ipEntrySelection = new(ELeave)CMsvEntrySelection;
       
  4791                 if (cmp == QMessageDataComparator::NotEqual) {
       
  4792                     getAllMessagesL(iOrdering);
       
  4793                 }
       
  4794             }
       
  4795         } else if (pf->_comparatorType == QMessageFilterPrivate::Inclusion) {
       
  4796             QMessageDataComparator::InclusionComparator cmp(static_cast<QMessageDataComparator::InclusionComparator>(pf->_comparatorValue));
       
  4797             if (pf->_ids.count() > 0) { // QMessageIdList
       
  4798                 if (cmp == QMessageDataComparator::Includes) {
       
  4799                     ipEntrySelection = new(ELeave)CMsvEntrySelection;
       
  4800                     for (int i=0; i < pf->_ids.count(); i++) {
       
  4801                         long int messageId = SymbianHelpers::stripIdPrefix(pf->_ids[i].toString()).toLong();
       
  4802                         CMsvEntry* pEntry = iOwner.retrieveCMsvEntryAndPushToCleanupStack(messageId);
       
  4803                         if (pEntry) {
       
  4804                             const TMsvEntry& entry = pEntry->Entry();
       
  4805                             if (entry.iType == KUidMsvMessageEntry) {
       
  4806                                 ipEntrySelection->AppendL(messageId);
       
  4807                             }
       
  4808                             iOwner.releaseCMsvEntryAndPopFromCleanupStack(pEntry);
       
  4809                         }
       
  4810                     }
       
  4811                 } else { // Excludes
       
  4812                     ipEntrySelection = new(ELeave)CMsvEntrySelection;
       
  4813                     getAllMessagesL(iOrdering);
       
  4814                     for (int i=0; i < pf->_ids.count(); i++) {
       
  4815                         long int messageId = SymbianHelpers::stripIdPrefix(pf->_ids[i].toString()).toLong();
       
  4816                         for (int i=0; i < ipEntrySelection->Count(); i++) {
       
  4817                             if (ipEntrySelection->At(i) == messageId) {
       
  4818                                 ipEntrySelection->Delete(i);
       
  4819                                 break;
       
  4820                             }
       
  4821                         }
       
  4822                     }
       
  4823                 }
       
  4824             } else {
       
  4825                 ipEntrySelection = new(ELeave)CMsvEntrySelection;
       
  4826                 if (cmp == QMessageDataComparator::Excludes) {
       
  4827                     getAllMessagesL(iOrdering);
       
  4828                 }
       
  4829                 /*// QMessageFilter
       
  4830                 if (cmp == QMessageDataComparator::Includes) {
       
  4831                     // TODO:
       
  4832                 } else { // Excludes
       
  4833                     // TODO:
       
  4834                 }*/
       
  4835             }
       
  4836         }
       
  4837         break;
       
  4838         }
       
  4839     case QMessageFilterPrivate::ParentAccountId:
       
  4840         {
       
  4841         if (pf->_comparatorType == QMessageFilterPrivate::Equality) { // QMessageAccountId
       
  4842             iNumberOfHandledFilters++;
       
  4843             QMessageDataComparator::EqualityComparator cmp(static_cast<QMessageDataComparator::EqualityComparator>(pf->_comparatorValue));
       
  4844             if (cmp == QMessageDataComparator::Equal) {
       
  4845                 ipEntrySelection = new(ELeave)CMsvEntrySelection;
       
  4846                 
       
  4847                 QMessageAccount messageAccount = iOwner.account(pf->_value.toString());
       
  4848                 QMessageFilterPrivate* privateFilter = NULL;
       
  4849                 if (filters.count() > iNumberOfHandledFilters) {
       
  4850                     privateFilter = QMessageFilterPrivate::implementation(filters[iNumberOfHandledFilters]);
       
  4851                     if (privateFilter->_field != QMessageFilterPrivate::StandardFolder) {
       
  4852                         privateFilter = NULL;
       
  4853                     } else {
       
  4854                         iNumberOfHandledFilters++;
       
  4855                     }
       
  4856                 }
       
  4857                 getAccountSpecificMessagesL(messageAccount, iOrdering, privateFilter);
       
  4858             } else { // NotEqual
       
  4859                 ipEntrySelection = new(ELeave)CMsvEntrySelection;
       
  4860                 
       
  4861                 QStringList exludedAccounts;
       
  4862                 exludedAccounts << pf->_value.toString();
       
  4863                 
       
  4864                 QMessageFilterPrivate* privateFilter = NULL;
       
  4865                 for (int i=iNumberOfHandledFilters; i < filters.count(); i++) {
       
  4866                     privateFilter = QMessageFilterPrivate::implementation(filters[i]);
       
  4867                     if (privateFilter->_field == QMessageFilterPrivate::ParentAccountId &&
       
  4868                         privateFilter->_comparatorType == QMessageFilterPrivate::Equality) {
       
  4869                         cmp = static_cast<QMessageDataComparator::EqualityComparator>(privateFilter->_comparatorValue);
       
  4870                         if (cmp == QMessageDataComparator::NotEqual) {
       
  4871                             exludedAccounts << privateFilter->_value.toString();
       
  4872                             iNumberOfHandledFilters++;
       
  4873                         } else {
       
  4874                             break;
       
  4875                         }
       
  4876                     } else {
       
  4877                         break;
       
  4878                     }
       
  4879                 }
       
  4880 
       
  4881                 privateFilter = NULL;
       
  4882                 if (filters.count() > iNumberOfHandledFilters) {
       
  4883                     privateFilter = QMessageFilterPrivate::implementation(filters[iNumberOfHandledFilters]);
       
  4884                     if (privateFilter->_field == QMessageFilterPrivate::StandardFolder &&
       
  4885                         privateFilter->_comparatorType == QMessageFilterPrivate::Equality) {
       
  4886                         cmp = static_cast<QMessageDataComparator::EqualityComparator>(privateFilter->_comparatorValue);
       
  4887                         if (cmp == QMessageDataComparator::Equal) {
       
  4888                             iNumberOfHandledFilters++;
       
  4889                         }
       
  4890                     } else {
       
  4891                         privateFilter = NULL;
       
  4892                     }
       
  4893                 }
       
  4894                 
       
  4895                 foreach (QMessageAccount value, iOwner.iAccounts) {
       
  4896                     if (!exludedAccounts.contains(value.id().toString())) {
       
  4897                         getAccountSpecificMessagesL(value, iOrdering, privateFilter);
       
  4898                     }
       
  4899                 }
       
  4900             }
       
  4901         } else if (pf->_comparatorType == QMessageFilterPrivate::Inclusion) { // QMessageAccountFilter
       
  4902             QMessageDataComparator::InclusionComparator cmp(static_cast<QMessageDataComparator::InclusionComparator>(pf->_comparatorValue));
       
  4903             if (cmp == QMessageDataComparator::Includes) {
       
  4904                 //TODO:
       
  4905             } else { // Excludes
       
  4906                 //TODO:
       
  4907             }
       
  4908         }
       
  4909         break;
       
  4910         }
       
  4911     case QMessageFilterPrivate::ParentFolderId:
       
  4912         {
       
  4913         if (pf->_comparatorType == QMessageFilterPrivate::Equality) { // QMessageFolderId
       
  4914             QMessageDataComparator::EqualityComparator cmp(static_cast<QMessageDataComparator::EqualityComparator>(pf->_comparatorValue));
       
  4915             if (cmp == QMessageDataComparator::Equal) {
       
  4916                 long int folderId = iOwner.folderIdFromQMessageFolderId(QMessageFolderId(pf->_value.toString()));
       
  4917                 long int serviceEntryId = iOwner.serviceEntryIdFromQMessageFolderId(QMessageFolderId(pf->_value.toString()));
       
  4918                 QMessageAccount messageAccount = iOwner.account(iOwner.accountIdByServiceId(serviceEntryId));
       
  4919                 if (messageAccount.messageTypes() == QMessage::Email) {
       
  4920                     iNumberOfHandledFilters++;
       
  4921                     CMsvEntryFilter* pFilter = CMsvEntryFilter::NewLC();
       
  4922                     pFilter->SetOrder(iOrdering);
       
  4923                     pFilter->SetType(KUidMsvMessageEntry);
       
  4924                     // Get POP3 or IMAP messages from folder 
       
  4925                     CMsvEntrySelection* pEntrySelection1 = new(ELeave)CMsvEntrySelection;
       
  4926                     CleanupStack::PushL(pEntrySelection1);
       
  4927                     pFilter->SetService(messageAccount.d_ptr->_service1EntryId);
       
  4928                     ipMsvSession->GetChildIdsL(folderId, *pFilter, *pEntrySelection1);
       
  4929                     // Get SMTP messages from folder 
       
  4930                     CMsvEntrySelection* pEntrySelection2 = new(ELeave)CMsvEntrySelection;
       
  4931                     CleanupStack::PushL(pEntrySelection2);
       
  4932                     pFilter->SetService(messageAccount.d_ptr->_service2EntryId);
       
  4933                     ipMsvSession->GetChildIdsL(folderId, *pFilter, *pEntrySelection2);
       
  4934                     if (pEntrySelection1->Count() > 0 && pEntrySelection2->Count() > 0) {
       
  4935                         ipEntrySelection = pEntrySelection1;
       
  4936                         for (int i = 0; i < pEntrySelection2->Count(); i++) {
       
  4937                             ipEntrySelection->AppendL(pEntrySelection2->At(i));
       
  4938                         }
       
  4939                         CleanupStack::PopAndDestroy(pEntrySelection2);
       
  4940                         CleanupStack::Pop(pEntrySelection1);
       
  4941                     } else if (pEntrySelection1->Count() > 0) {
       
  4942                         ipEntrySelection = pEntrySelection1;
       
  4943                         CleanupStack::PopAndDestroy(pEntrySelection2);
       
  4944                         CleanupStack::Pop(pEntrySelection1);
       
  4945                         iResultCorrectlyOrdered = true;
       
  4946                     } else {
       
  4947                         // (pEntrySelection2->Count() > 0) or both selections are empty
       
  4948                         ipEntrySelection = pEntrySelection2;
       
  4949                         CleanupStack::Pop(pEntrySelection2);
       
  4950                         CleanupStack::PopAndDestroy(pEntrySelection1);
       
  4951                         iResultCorrectlyOrdered = true;
       
  4952                     }
       
  4953                     CleanupStack::PopAndDestroy(pFilter);
       
  4954                 } else if (messageAccount.messageTypes() == QMessage::Sms || messageAccount.messageTypes() == QMessage::Mms) {
       
  4955                     iNumberOfHandledFilters++;
       
  4956                     CMsvEntry* pEntry = iOwner.retrieveCMsvEntryAndPushToCleanupStack(serviceEntryId);
       
  4957                     if (pEntry) {
       
  4958                         TUid mtm = pEntry->Entry().iMtm;
       
  4959                         iOwner.releaseCMsvEntryAndPopFromCleanupStack(pEntry);
       
  4960                         CMsvEntryFilter* pFilter = CMsvEntryFilter::NewLC();
       
  4961                         pFilter->SetMtm(mtm);
       
  4962                         pFilter->SetOrder(iOrdering);
       
  4963                         pFilter->SetType(KUidMsvMessageEntry);
       
  4964                         ipEntrySelection = new(ELeave)CMsvEntrySelection;
       
  4965                         ipMsvSession->GetChildIdsL(folderId, *pFilter, *ipEntrySelection);
       
  4966                         CleanupStack::PopAndDestroy(pFilter);
       
  4967                     }
       
  4968                     iResultCorrectlyOrdered = true;
       
  4969                 }
       
  4970             } else { // NotEqual
       
  4971                 // TODO:
       
  4972             }
       
  4973         } else if (pf->_comparatorType == QMessageFilterPrivate::Inclusion) { // QMessageFolderFilter
       
  4974             QMessageDataComparator::InclusionComparator cmp(static_cast<QMessageDataComparator::InclusionComparator>(pf->_comparatorValue));
       
  4975             if (cmp == QMessageDataComparator::Includes) {
       
  4976                 // TODO:
       
  4977             } else { // Excludes
       
  4978                 // TODO:
       
  4979             }
       
  4980         }
       
  4981         break;
       
  4982         }
       
  4983     case QMessageFilterPrivate::AncestorFolderIds:
       
  4984         {
       
  4985         iNumberOfHandledFilters++;
       
  4986         if (pf->_comparatorType == QMessageFilterPrivate::Inclusion) {
       
  4987             QMessageDataComparator::InclusionComparator cmp(static_cast<QMessageDataComparator::InclusionComparator>(pf->_comparatorValue));
       
  4988             if (!pf->_value.isNull()) { // QMessageFolderId
       
  4989                 if (cmp == QMessageDataComparator::Includes) {
       
  4990                     // TODO:
       
  4991                 } else { // Excludes
       
  4992                     // TODO:
       
  4993                 }
       
  4994             } else { // QMessageFolderFilter
       
  4995                 if (cmp == QMessageDataComparator::Includes) {
       
  4996                     // TODO:
       
  4997                 } else { // Excludes
       
  4998                     // TODO:
       
  4999                 }
       
  5000             }
       
  5001         }
       
  5002         break;
       
  5003         }
       
  5004     case QMessageFilterPrivate::Type:
       
  5005         {
       
  5006         iNumberOfHandledFilters++;
       
  5007         QMessageFilterPrivate* privateFilter = NULL;
       
  5008         // Check if next filter is StandardFolder filter 
       
  5009         if (filters.count() > iNumberOfHandledFilters) {
       
  5010             privateFilter = QMessageFilterPrivate::implementation(filters[iNumberOfHandledFilters]);
       
  5011             if (privateFilter->_field != QMessageFilterPrivate::StandardFolder) {
       
  5012                 privateFilter = NULL;
       
  5013             } else {
       
  5014                 iNumberOfHandledFilters++;
       
  5015             }
       
  5016         }
       
  5017         if (pf->_comparatorType == QMessageFilterPrivate::Equality) { // QMessage::Type
       
  5018             QMessage::Type type = static_cast<QMessage::Type>(pf->_value.toInt()); 
       
  5019             QMessageDataComparator::EqualityComparator cmp(static_cast<QMessageDataComparator::EqualityComparator>(pf->_comparatorValue));
       
  5020             if (cmp == QMessageDataComparator::Equal) {
       
  5021                 ipEntrySelection = new(ELeave)CMsvEntrySelection;
       
  5022                 QMessageAccountIdList accountIds = iOwner.accountsByType(type);
       
  5023                 for (int i = 0; i < accountIds.count(); i++) {
       
  5024                     QMessageAccount messageAccount = iOwner.account(accountIds[i]);
       
  5025                     getAccountSpecificMessagesL(messageAccount, iOrdering, privateFilter);
       
  5026                 }
       
  5027             } else { // NotEqual
       
  5028                 foreach (QMessageAccount value, iOwner.iAccounts) {
       
  5029                     if (!(value.messageTypes() & type)) {
       
  5030                         getAccountSpecificMessagesL(value, iOrdering, privateFilter);
       
  5031                     }
       
  5032                 }
       
  5033             }
       
  5034         } else if (pf->_comparatorType == QMessageFilterPrivate::Inclusion) { // QMessage::TypeFlags
       
  5035             QMessage::TypeFlags typeFlags = static_cast<QMessage::TypeFlags>(pf->_value.toInt());
       
  5036             QMessageDataComparator::InclusionComparator cmp(static_cast<QMessageDataComparator::InclusionComparator>(pf->_comparatorValue));
       
  5037             if (cmp == QMessageDataComparator::Includes) {
       
  5038                 foreach (QMessageAccount value, iOwner.iAccounts) {
       
  5039                     if (value.messageTypes() | typeFlags) {
       
  5040                         getAccountSpecificMessagesL(value, iOrdering, privateFilter);
       
  5041                     }
       
  5042                 }
       
  5043             } else { // Excludes
       
  5044                 foreach (QMessageAccount value, iOwner.iAccounts) {
       
  5045                     if (!(value.messageTypes() & typeFlags)) {
       
  5046                         getAccountSpecificMessagesL(value, iOrdering, privateFilter);
       
  5047                     }
       
  5048                 }
       
  5049             }
       
  5050         }
       
  5051         break;
       
  5052         }
       
  5053     case QMessageFilterPrivate::StandardFolder:
       
  5054         {
       
  5055         iNumberOfHandledFilters++;
       
  5056         QMessageDataComparator::EqualityComparator cmp(static_cast<QMessageDataComparator::EqualityComparator>(pf->_comparatorValue));
       
  5057         QMessage::StandardFolder standardFolder = static_cast<QMessage::StandardFolder>(pf->_value.toInt());
       
  5058         TMsvId stdFolderId = iOwner.standardFolderId(standardFolder);
       
  5059         if (cmp == QMessageDataComparator::Equal) {
       
  5060             CMsvEntry* pStandardFolderContext = iOwner.retrieveCMsvEntryAndPushToCleanupStack(stdFolderId);
       
  5061             if (pStandardFolderContext) {
       
  5062                 pStandardFolderContext->SetSortTypeL(iOrdering);
       
  5063                 ipEntrySelection = pStandardFolderContext->ChildrenL();
       
  5064                 iOwner.releaseCMsvEntryAndPopFromCleanupStack(pStandardFolderContext);
       
  5065             }
       
  5066             iResultCorrectlyOrdered = true;
       
  5067         } else { // NotEqual
       
  5068             ipEntrySelection = new(ELeave)CMsvEntrySelection;
       
  5069             QMessage::StandardFolder i = QMessage::InboxFolder;
       
  5070             while (i <= QMessage::TrashFolder) {
       
  5071                 if (i != standardFolder) {
       
  5072                     CMsvEntry* pStandardFolderContext = iOwner.retrieveCMsvEntryAndPushToCleanupStack(iOwner.standardFolderId(i));
       
  5073                     if (pStandardFolderContext) {
       
  5074                         pStandardFolderContext->SetSortTypeL(iOrdering);
       
  5075                         CMsvEntrySelection* pEntries = pStandardFolderContext->ChildrenL();
       
  5076                         CleanupStack::PushL(pEntries);
       
  5077                         for (int i = 0; i < pEntries->Count(); i++) {
       
  5078                             ipEntrySelection->AppendL(pEntries->At(i));
       
  5079                         }
       
  5080                         CleanupStack::PopAndDestroy(pEntries);
       
  5081                         iOwner.releaseCMsvEntryAndPopFromCleanupStack(pStandardFolderContext);
       
  5082                     }
       
  5083                 }
       
  5084                 i = static_cast<QMessage::StandardFolder>(static_cast<int>(i) + 1);
       
  5085             }
       
  5086         }
       
  5087         break;
       
  5088         }
       
  5089     case QMessageFilterPrivate::ParentAccountIdFilter:
       
  5090     case QMessageFilterPrivate::ParentFolderIdFilter:
       
  5091     case QMessageFilterPrivate::TimeStamp:
       
  5092     case QMessageFilterPrivate::ReceptionTimeStamp:
       
  5093     case QMessageFilterPrivate::Sender:
       
  5094     case QMessageFilterPrivate::Recipients:
       
  5095     case QMessageFilterPrivate::Subject:
       
  5096     case QMessageFilterPrivate::Status:
       
  5097     case QMessageFilterPrivate::Priority:
       
  5098     case QMessageFilterPrivate::Size:
       
  5099     case QMessageFilterPrivate::None:
       
  5100         break;
       
  5101     }
       
  5102     
       
  5103     TMsvPartList partlist = 0;
       
  5104     TPtrC16 value(KNullDesC);
       
  5105     if (body.isEmpty()) {
       
  5106         if (iNumberOfHandledFilters < filters.count()) {    
       
  5107             pf = QMessageFilterPrivate::implementation(filters[iNumberOfHandledFilters]);
       
  5108             
       
  5109             if (pf->_matchFlags & QMessageDataComparator::MatchCaseSensitive) {
       
  5110                 partlist |= KMsvFindCaseSensitive;
       
  5111             }
       
  5112             if (pf->_matchFlags & QMessageDataComparator::MatchFullWord) {
       
  5113                 partlist |= KMsvFindWholeWord;
       
  5114             }
       
  5115     
       
  5116             switch (pf->_field) {
       
  5117             case QMessageFilterPrivate::Sender:
       
  5118                 {
       
  5119                 if (pf->_comparatorType == QMessageFilterPrivate::Equality) {
       
  5120                     QMessageDataComparator::EqualityComparator cmp(static_cast<QMessageDataComparator::EqualityComparator>(pf->_comparatorValue));
       
  5121                     if (cmp == QMessageDataComparator::Equal) {
       
  5122                         if (pf->_value.toString().length() > 0) {
       
  5123                             value.Set(reinterpret_cast<const TUint16*>(pf->_value.toString().utf16()));
       
  5124                             partlist |= KMsvMessagePartOriginator;
       
  5125                             iNumberOfHandledFilters++;
       
  5126                         }
       
  5127                     } else { // NotEqual
       
  5128                         // TODO:
       
  5129                     }
       
  5130                 } else if (pf->_comparatorType == QMessageFilterPrivate::Inclusion) {
       
  5131                     QMessageDataComparator::InclusionComparator cmp(static_cast<QMessageDataComparator::InclusionComparator>(pf->_comparatorValue));
       
  5132                     if (cmp == QMessageDataComparator::Includes) {
       
  5133                         // TODO:
       
  5134                     } else { // Excludes
       
  5135                         // TODO:
       
  5136                     }
       
  5137                 }
       
  5138                 break;
       
  5139                 }
       
  5140             case QMessageFilterPrivate::Recipients: // to, cc & bcc fields
       
  5141                 {
       
  5142                 if (pf->_comparatorType == QMessageFilterPrivate::Inclusion) {
       
  5143                     QMessageDataComparator::InclusionComparator cmp(static_cast<QMessageDataComparator::InclusionComparator>(pf->_comparatorValue));
       
  5144                     if (cmp == QMessageDataComparator::Includes) {
       
  5145                         if (pf->_value.toString().length() > 0) {
       
  5146                             value.Set(reinterpret_cast<const TUint16*>(pf->_value.toString().utf16()));
       
  5147                             partlist |= KMsvMessagePartRecipient;
       
  5148                             iNumberOfHandledFilters++;
       
  5149                         }
       
  5150                     } else { // Excludes
       
  5151                         //TODO:
       
  5152                     }
       
  5153                 }
       
  5154                 break;
       
  5155                 }
       
  5156             case QMessageFilterPrivate::Subject:
       
  5157                 {
       
  5158                 if (pf->_comparatorType == QMessageFilterPrivate::Equality) {
       
  5159                     QMessageDataComparator::EqualityComparator cmp(static_cast<QMessageDataComparator::EqualityComparator>(pf->_comparatorValue));
       
  5160                     if (cmp == QMessageDataComparator::Equal) {
       
  5161                         if (pf->_value.toString().length() > 0) {
       
  5162                             value.Set(reinterpret_cast<const TUint16*>(pf->_value.toString().utf16()));
       
  5163                             partlist |= KMsvMessagePartDescription;
       
  5164                             iNumberOfHandledFilters++;
       
  5165                         }
       
  5166                     } else { // NotEqual
       
  5167                         // TODO:
       
  5168                     }
       
  5169                 } else if (pf->_comparatorType == QMessageFilterPrivate::Inclusion) {
       
  5170                     QMessageDataComparator::InclusionComparator cmp(static_cast<QMessageDataComparator::InclusionComparator>(pf->_comparatorValue));
       
  5171                     if (cmp == QMessageDataComparator::Includes) {
       
  5172                         // TODO:
       
  5173                     } else { // Excludes
       
  5174                         // TODO:
       
  5175                     }
       
  5176                 }
       
  5177                 break;
       
  5178                 }
       
  5179             case QMessageFilterPrivate::TimeStamp:
       
  5180                 {
       
  5181                 if (pf->_comparatorType == QMessageFilterPrivate::Equality) {
       
  5182                     QMessageDataComparator::EqualityComparator cmp(static_cast<QMessageDataComparator::EqualityComparator>(pf->_comparatorValue));
       
  5183                     if (cmp == QMessageDataComparator::Equal) {
       
  5184                         // TODO:
       
  5185                     } else { // NotEqual
       
  5186                         // TODO:
       
  5187                     }
       
  5188                 } else if (pf->_comparatorType == QMessageFilterPrivate::Relation) {
       
  5189                     QMessageDataComparator::RelationComparator cmp(static_cast<QMessageDataComparator::RelationComparator>(pf->_comparatorValue));
       
  5190                     if (cmp == QMessageDataComparator::LessThan) {
       
  5191                         // TODO:
       
  5192                     } else if (cmp == QMessageDataComparator::LessThanEqual) {
       
  5193                         // TODO:
       
  5194                     } else if (cmp == QMessageDataComparator::GreaterThan) {
       
  5195                         // TODO:
       
  5196                     } else { // GreaterThanEqual
       
  5197                         // TODO:
       
  5198                     }
       
  5199                 }
       
  5200                 break;
       
  5201                 }
       
  5202             case QMessageFilterPrivate::ReceptionTimeStamp:
       
  5203                 {
       
  5204                 if (pf->_comparatorType == QMessageFilterPrivate::Equality) {
       
  5205                     QMessageDataComparator::EqualityComparator cmp(static_cast<QMessageDataComparator::EqualityComparator>(pf->_comparatorValue));
       
  5206                     if (cmp == QMessageDataComparator::Equal) {
       
  5207                         value.Set(reinterpret_cast<const TUint16*>(pf->_value.toString().utf16()));
       
  5208                         partlist |= KMsvMessagePartDate;
       
  5209                         iNumberOfHandledFilters++;
       
  5210                     } else { // NotEqual
       
  5211                         // TODO:
       
  5212                     }
       
  5213                 } else if (pf->_comparatorType == QMessageFilterPrivate::Relation) {
       
  5214                     QMessageDataComparator::RelationComparator cmp(static_cast<QMessageDataComparator::RelationComparator>(pf->_comparatorValue));
       
  5215                     if (cmp == QMessageDataComparator::LessThan) {
       
  5216                         // TODO:
       
  5217                     } else if (cmp == QMessageDataComparator::LessThanEqual) {
       
  5218                         // TODO:
       
  5219                     } else if (cmp == QMessageDataComparator::GreaterThan) {
       
  5220                         // TODO:
       
  5221                     } else { // GreaterThanEqual
       
  5222                         // TODO:
       
  5223                     }
       
  5224                 }
       
  5225                 break;
       
  5226                 }
       
  5227             case QMessageFilterPrivate::Status:
       
  5228                 {
       
  5229                 if (pf->_comparatorType == QMessageFilterPrivate::Equality) {
       
  5230                     QMessageDataComparator::EqualityComparator cmp(static_cast<QMessageDataComparator::EqualityComparator>(pf->_comparatorValue));
       
  5231                     if (cmp == QMessageDataComparator::Equal) {
       
  5232                         // TODO:
       
  5233                     } else { // NotEqual
       
  5234                         // TODO:
       
  5235                     }
       
  5236                 } else if (pf->_comparatorType == QMessageFilterPrivate::Inclusion) {
       
  5237                     QMessageDataComparator::InclusionComparator cmp(static_cast<QMessageDataComparator::InclusionComparator>(pf->_comparatorValue));
       
  5238                     if (cmp == QMessageDataComparator::Includes) {
       
  5239                         // TODO:
       
  5240                     } else { // Excludes
       
  5241                         // TODO:
       
  5242                     }
       
  5243                 }
       
  5244                 break;
       
  5245                 }
       
  5246             case QMessageFilterPrivate::Priority:
       
  5247                 {
       
  5248                 QMessageDataComparator::EqualityComparator cmp(static_cast<QMessageDataComparator::EqualityComparator>(pf->_comparatorValue));
       
  5249                 if (cmp == QMessageDataComparator::Equal) {
       
  5250                     // TODO:
       
  5251                 } else { // NotEqual
       
  5252                     // TODO:
       
  5253                 }
       
  5254                 break;
       
  5255                 }
       
  5256             case QMessageFilterPrivate::Size:
       
  5257                 {
       
  5258                 if (pf->_comparatorType == QMessageFilterPrivate::Equality) {
       
  5259                     QMessageDataComparator::EqualityComparator cmp(static_cast<QMessageDataComparator::EqualityComparator>(pf->_comparatorValue));
       
  5260                     if (cmp == QMessageDataComparator::Equal) {
       
  5261                         // TODO:
       
  5262                     } else { // NotEqual
       
  5263                         // TODO:
       
  5264                     }
       
  5265                 } else if (pf->_comparatorType == QMessageFilterPrivate::Relation) {
       
  5266                     QMessageDataComparator::RelationComparator cmp(static_cast<QMessageDataComparator::RelationComparator>(pf->_comparatorValue));
       
  5267                     if (cmp == QMessageDataComparator::LessThan) {
       
  5268                         // TODO:
       
  5269                     } else if (cmp == QMessageDataComparator::LessThanEqual) {
       
  5270                         // TODO:
       
  5271                     } else if (cmp == QMessageDataComparator::GreaterThan) {
       
  5272                         // TODO:
       
  5273                     } else { // GreaterThanEqual
       
  5274                         // TODO:
       
  5275                     }
       
  5276                 }
       
  5277                 break;
       
  5278                 }
       
  5279             case QMessageFilterPrivate::ParentAccountIdFilter:
       
  5280             case QMessageFilterPrivate::ParentFolderIdFilter:
       
  5281             case QMessageFilterPrivate::Id:
       
  5282             case QMessageFilterPrivate::ParentFolderId:
       
  5283             case QMessageFilterPrivate::AncestorFolderIds:
       
  5284             case QMessageFilterPrivate::ParentAccountId:
       
  5285             case QMessageFilterPrivate::Type:
       
  5286             case QMessageFilterPrivate::StandardFolder:
       
  5287             case QMessageFilterPrivate::None:
       
  5288                 break;
       
  5289             }
       
  5290         }
       
  5291     } else {
       
  5292         // Body 
       
  5293         if (matchFlags & QMessageDataComparator::MatchCaseSensitive) {
       
  5294             partlist |= KMsvFindCaseSensitive;
       
  5295         }
       
  5296         if (matchFlags & QMessageDataComparator::MatchFullWord) {
       
  5297             partlist |= KMsvFindWholeWord;
       
  5298         }
       
  5299         
       
  5300         value.Set(reinterpret_cast<const TUint16*>(body.utf16()));
       
  5301         partlist |= KMsvMessagePartBody;
       
  5302     }
       
  5303     
       
  5304     if (iResultCorrectlyOrdered && iOrdering.Sorting() == EMsvSortByNone && !iOrdering.GroupingOn()) {
       
  5305         iResultCorrectlyOrdered = false;
       
  5306     }
       
  5307 
       
  5308     if (!ipEntrySelection) {
       
  5309         ipEntrySelection = new(ELeave)CMsvEntrySelection;
       
  5310         getAllMessagesL(iOrdering);
       
  5311     }
       
  5312 
       
  5313     if (partlist != 0 && ipEntrySelection->Count() > 0) {
       
  5314         ipMsvFindOperation = CMsvFindOperation::FindInSelectionL(*ipMsvSession, value, *ipEntrySelection, partlist, iStatus);
       
  5315         if (!IsActive()) {
       
  5316             SetActive();
       
  5317         }
       
  5318     } else {
       
  5319         iIdList = QMessageIdList();
       
  5320         for (int i=0; i < ipEntrySelection->Count(); i++) {
       
  5321             iIdList.append(QMessageId(SymbianHelpers::addIdPrefix(QString::number((*ipEntrySelection)[i]),SymbianHelpers::EngineTypeMTM)));
       
  5322         }
       
  5323         iTimer.After(iStatus, 100);
       
  5324         if (!IsActive()) {
       
  5325             SetActive();
       
  5326         }
       
  5327     }
       
  5328 }
       
  5329 
       
  5330 void CMessagesFindOperation::RunL()
       
  5331 {
       
  5332     if (iStatus.Int() != KErrNone) {
       
  5333         iOwner.filterAndOrderMessagesReady(false, iOperationId, QMessageIdList(), 0, false);
       
  5334     } else {
       
  5335         if (ipMsvFindOperation) {
       
  5336             const CMsvFindResultSelection& findResultSelection = ipMsvFindOperation->GetFindResult();
       
  5337             QMessageIdList msgIds;
       
  5338             for (int i=0; i < findResultSelection.Count(); i++) {
       
  5339                 msgIds.append(QMessageId(SymbianHelpers::addIdPrefix(QString::number(findResultSelection[i].iId),SymbianHelpers::EngineTypeMTM)));
       
  5340             }
       
  5341             iOwner.filterAndOrderMessagesReady(true, iOperationId, msgIds, iNumberOfHandledFilters, iResultCorrectlyOrdered);
       
  5342         } else {
       
  5343             iOwner.filterAndOrderMessagesReady(true, iOperationId, iIdList, iNumberOfHandledFilters, iResultCorrectlyOrdered);
       
  5344         }
       
  5345     }
       
  5346     
       
  5347 }
       
  5348 
       
  5349 void CMessagesFindOperation::getAllMessagesL(const TMsvSelectionOrdering sortOrder)
       
  5350 {
       
  5351     // Get all messages from every known account
       
  5352     foreach (QMessageAccount value, iOwner.iAccounts) {
       
  5353         getAccountSpecificMessagesL(value, sortOrder);
       
  5354     }
       
  5355 }
       
  5356 
       
  5357 void CMessagesFindOperation::getAccountSpecificMessagesL(QMessageAccount& messageAccount, const TMsvSelectionOrdering sortOrder, QMessageFilterPrivate* privateFolderFilter)
       
  5358 {
       
  5359     CMsvEntry* pService = iOwner.retrieveCMsvEntryAndPushToCleanupStack(messageAccount.d_ptr->_service1EntryId);
       
  5360     if (pService) {
       
  5361         TUid mtmUid = pService->Entry().iMtm;
       
  5362         iOwner.releaseCMsvEntryAndPopFromCleanupStack(pService);
       
  5363         getServiceSpecificMessagesL(messageAccount.d_ptr->_service1EntryId, sortOrder, privateFolderFilter);
       
  5364     }
       
  5365 
       
  5366     TMsvId serviceId = messageAccount.d_ptr->_service2EntryId;
       
  5367     if (serviceId != 0) {
       
  5368         CMsvEntry* pService = iOwner.retrieveCMsvEntryAndPushToCleanupStack(serviceId);
       
  5369         if (pService) {
       
  5370             TUid mtmUid = pService->Entry().iMtm;
       
  5371             iOwner.releaseCMsvEntryAndPopFromCleanupStack(pService);
       
  5372             int count = ipEntrySelection->Count();
       
  5373             getServiceSpecificMessagesL(messageAccount.d_ptr->_service2EntryId, sortOrder, privateFolderFilter);
       
  5374             if (ipEntrySelection->Count() > count) {
       
  5375                 iResultCorrectlyOrdered = false;
       
  5376             }
       
  5377         }
       
  5378     }
       
  5379 }
       
  5380 
       
  5381 void CMessagesFindOperation::getServiceSpecificMessagesL(TMsvId serviceId, const TMsvSelectionOrdering sortOrder, QMessageFilterPrivate* privateFolderFilter)
       
  5382 {
       
  5383     if (privateFolderFilter) {
       
  5384         QMessageDataComparator::EqualityComparator cmp2(static_cast<QMessageDataComparator::EqualityComparator>(privateFolderFilter->_comparatorValue));
       
  5385         QMessage::StandardFolder standardFolder = static_cast<QMessage::StandardFolder>(privateFolderFilter->_value.toInt()); 
       
  5386         if (cmp2 == QMessageDataComparator::Equal) {
       
  5387             iResultCorrectlyOrdered = true;
       
  5388             getServiceSpecificMessagesFromFolderL(serviceId, sortOrder, iOwner.standardFolderId(standardFolder));
       
  5389         } else { // NotEqual
       
  5390             // Loop through all standard folders
       
  5391             QMessage::StandardFolder i = QMessage::InboxFolder;
       
  5392             while (i <= QMessage::TrashFolder) {
       
  5393                 if (i != standardFolder) {
       
  5394                     getServiceSpecificMessagesFromFolderL(serviceId, sortOrder, iOwner.standardFolderId(i));
       
  5395                 }
       
  5396                 i = static_cast<QMessage::StandardFolder>(static_cast<int>(i) + 1);
       
  5397             }
       
  5398         }
       
  5399     }
       
  5400     else {
       
  5401         // List all service specific messages from Standard Folders
       
  5402         QMessage::StandardFolder i = QMessage::InboxFolder;
       
  5403         while (i <= QMessage::TrashFolder) {
       
  5404             getServiceSpecificMessagesFromFolderL(serviceId, sortOrder, iOwner.standardFolderId(i));
       
  5405             i = static_cast<QMessage::StandardFolder>(static_cast<int>(i) + 1);
       
  5406         }
       
  5407         
       
  5408         // List all service specific messages from user created folders
       
  5409         CMsvEntry* pEntry = iOwner.retrieveCMsvEntryAndPushToCleanupStack(serviceId);
       
  5410         if (pEntry) {
       
  5411             TUid mtmUid = pEntry->Entry().iMtm;
       
  5412             if (mtmUid == KUidMsgTypeSMS || mtmUid == KUidMsgTypeMultimedia || mtmUid == KUidMsgTypeSMTP) {
       
  5413                 pEntry->SetEntryL(KDocumentsEntryIdValue);
       
  5414                 CMsvEntrySelection* pSelection = pEntry->ChildrenWithTypeL(KUidMsvFolderEntry);
       
  5415                 CleanupStack::PushL(pSelection);
       
  5416                 for(TInt i = 0; i < pSelection->Count(); i++) {
       
  5417                     CMsvEntryFilter* pFilter = CMsvEntryFilter::NewLC();
       
  5418                     if (mtmUid == KUidMsgTypeSMS || mtmUid == KUidMsgTypeMultimedia) {
       
  5419                         pFilter->SetMtm(mtmUid);
       
  5420                     } else {
       
  5421                         pFilter->SetService(serviceId);
       
  5422                     }
       
  5423                     pFilter->SetOrder(sortOrder);
       
  5424                     pFilter->SetType(KUidMsvMessageEntry);
       
  5425                     CMsvEntrySelection* pEntries = new(ELeave) CMsvEntrySelection;;
       
  5426                     CleanupStack::PushL(pEntries);
       
  5427                     ipMsvSession->GetChildIdsL(pSelection->At(i), *pFilter, *pEntries);
       
  5428                     for(TInt j = 0; j < pEntries->Count(); j++) {
       
  5429                         ipEntrySelection->AppendL(pEntries->At(j));
       
  5430                     }
       
  5431                     CleanupStack::PopAndDestroy(pEntries);
       
  5432                     CleanupStack::PopAndDestroy(pFilter);
       
  5433                 }
       
  5434                 CleanupStack::PopAndDestroy(pSelection);
       
  5435             }
       
  5436             iOwner.releaseCMsvEntryAndPopFromCleanupStack(pEntry);
       
  5437         }
       
  5438     }
       
  5439 }
       
  5440 
       
  5441 void CMessagesFindOperation::getServiceSpecificMessagesFromFolderL(TMsvId serviceId, const TMsvSelectionOrdering sortOrder, TMsvId standardFolderId)
       
  5442 {
       
  5443     CMsvEntry* pEntry = iOwner.retrieveCMsvEntryAndPushToCleanupStack(serviceId);
       
  5444     if (pEntry) {
       
  5445         pEntry->SetSortTypeL(sortOrder);
       
  5446         TUid mtmUid = pEntry->Entry().iMtm;
       
  5447         if (mtmUid == KUidMsgTypePOP3) {
       
  5448             if (standardFolderId == KMsvGlobalInBoxIndexEntryIdValue) {
       
  5449                 // POP3 service has (Inbox) messages in service root
       
  5450                 CMsvEntrySelection* pMessageEntries = pEntry->ChildrenWithTypeL(KUidMsvMessageEntry);
       
  5451                 CleanupStack::PushL(pMessageEntries);
       
  5452                 for (int i = 0; i < pMessageEntries->Count(); i++) {
       
  5453                     ipEntrySelection->AppendL(pMessageEntries->At(i));
       
  5454                 }
       
  5455                 CleanupStack::PopAndDestroy(pMessageEntries);
       
  5456             }
       
  5457         } else if (mtmUid == KUidMsgTypeIMAP4) {
       
  5458             if (standardFolderId == KMsvGlobalInBoxIndexEntryIdValue) {
       
  5459                 // All IMAP4 folders are treated as Inbox folders
       
  5460                 // IMAP4 service has folders in service root
       
  5461                 CMsvEntrySelection* pFolderEntries = pEntry->ChildrenWithTypeL(KUidMsvFolderEntry);
       
  5462                 CleanupStack::PushL(pFolderEntries);
       
  5463                 for (int i = 0; i < pFolderEntries->Count(); i++) {
       
  5464                     pEntry->SetEntryL(pFolderEntries->At(i));
       
  5465                     CMsvEntrySelection* pMessageEntries = pEntry->ChildrenWithTypeL(KUidMsvMessageEntry);
       
  5466                     CleanupStack::PushL(pMessageEntries);
       
  5467                     for (int j = 0; j < pMessageEntries->Count(); j++) {
       
  5468                         ipEntrySelection->AppendL(pMessageEntries->At(j));
       
  5469                     }
       
  5470                     CleanupStack::PopAndDestroy(pMessageEntries);
       
  5471                 }
       
  5472                 CleanupStack::PopAndDestroy(pFolderEntries);
       
  5473             }
       
  5474         } else {
       
  5475             // Handle SMS, MMS & SMTP Standard Folders
       
  5476             CMsvEntryFilter* pFilter = CMsvEntryFilter::NewLC();
       
  5477             if (mtmUid == KUidMsgTypeSMTP) {
       
  5478                 // There maybe multiple SMTP Services
       
  5479                 // => Messages must be queried using ServiceId
       
  5480                 pFilter->SetService(serviceId);
       
  5481             } else {
       
  5482                 // There is only one service per SMS and per MMS
       
  5483                 // => Messages can be queried using MTM Uid
       
  5484                 pFilter->SetMtm(mtmUid);
       
  5485             }
       
  5486             pFilter->SetOrder(sortOrder);
       
  5487             pFilter->SetType(KUidMsvMessageEntry);
       
  5488             CMsvEntrySelection* pEntries = new(ELeave) CMsvEntrySelection;;
       
  5489             CleanupStack::PushL(pEntries);
       
  5490             ipMsvSession->GetChildIdsL(standardFolderId, *pFilter, *pEntries);
       
  5491             for (int i = 0; i < pEntries->Count(); i++) {
       
  5492                 ipEntrySelection->AppendL(pEntries->At(i));
       
  5493             }
       
  5494             CleanupStack::PopAndDestroy(pEntries);
       
  5495             CleanupStack::PopAndDestroy(pFilter);
       
  5496         }
       
  5497         iOwner.releaseCMsvEntryAndPopFromCleanupStack(pEntry);
       
  5498     }
       
  5499 }
       
  5500 
       
  5501 QMTMWait::QMTMWait(TInt priority)
       
  5502     : CActive(priority)
       
  5503 {
       
  5504     CActiveScheduler::Add(this);
       
  5505 }
       
  5506 
       
  5507 QMTMWait::~QMTMWait()
       
  5508 {
       
  5509     Cancel();
       
  5510 }
       
  5511 
       
  5512 void QMTMWait::start()
       
  5513 {
       
  5514     SetActive();
       
  5515     m_eventLoop.exec();
       
  5516 }
       
  5517 
       
  5518 void QMTMWait::RunL()
       
  5519 {
       
  5520     m_eventLoop.quit();
       
  5521 }
       
  5522 
       
  5523 void QMTMWait::DoCancel()
       
  5524 {
       
  5525     Cancel();
       
  5526 }
       
  5527 
       
  5528 CAsynchronousMTMOperation::CAsynchronousMTMOperation(CMTMEngine& aParent,
       
  5529                                                      QMessageServicePrivate& aPrivateService,
       
  5530                                                      CBaseMtm* apMTM,
       
  5531                                                      TMsvId aServiceId,
       
  5532                                                      TInt aOperationId)
       
  5533     : CActive(EPriorityStandard),
       
  5534       ipParent(&aParent),
       
  5535       iOperationId(aOperationId),
       
  5536       iServiceId(aServiceId),
       
  5537       ipPrivateService(&aPrivateService),
       
  5538       ipMTM(apMTM)
       
  5539 {
       
  5540     CActiveScheduler::Add(this);
       
  5541 }
       
  5542 
       
  5543 CAsynchronousMTMOperation::~CAsynchronousMTMOperation()
       
  5544 {
       
  5545     ipParent = NULL;
       
  5546     Cancel();
       
  5547 }
       
  5548 
       
  5549 bool CAsynchronousMTMOperation::retrieveMessageHeader(TMsvId aMessageId)
       
  5550 {
       
  5551     if (!isActive) {
       
  5552         isActive = true;
       
  5553         iOperation = MTMOperationRetrieveMessageHeader;
       
  5554         iOperationStep = MTMOperationStepConnect;
       
  5555         
       
  5556         iMessageId = aMessageId;
       
  5557         
       
  5558         TRAPD(err, RunL());
       
  5559         if (err == KErrNone) {
       
  5560             return true;
       
  5561         }
       
  5562     }
       
  5563     return false;
       
  5564 }
       
  5565 
       
  5566 bool CAsynchronousMTMOperation::retrieveMessageBody(TMsvId aMessageId)
       
  5567 {
       
  5568     if (!isActive) {
       
  5569         isActive = true;
       
  5570         iOperation = MTMOperationRetrieveMessageBody;
       
  5571         iOperationStep = MTMOperationStepConnect;
       
  5572         
       
  5573         iMessageId = aMessageId;
       
  5574         
       
  5575         TRAPD(err, RunL());
       
  5576         if (err == KErrNone) {
       
  5577             return true;
       
  5578         }
       
  5579     }
       
  5580     return false;
       
  5581 }
       
  5582 
       
  5583 bool CAsynchronousMTMOperation::retrieveMessageAttachments(TMsvId aMessageId)
       
  5584 {
       
  5585     if (!isActive) {
       
  5586         isActive = true;
       
  5587         iOperation = MTMOperationRetrieveMessageAttachments;
       
  5588         iOperationStep = MTMOperationStepConnect;
       
  5589         
       
  5590         iMessageId = aMessageId;
       
  5591         
       
  5592         TRAPD(err, RunL());
       
  5593         if (err == KErrNone) {
       
  5594             return true;
       
  5595         }
       
  5596     }
       
  5597     return false;
       
  5598 }
       
  5599 
       
  5600 bool CAsynchronousMTMOperation::doFullSync()
       
  5601 {
       
  5602     if (!isActive) {
       
  5603         isActive = true;
       
  5604         iOperation = MTMOperationFullSync;
       
  5605         iOperationStep = MTMOperationStepConnect;
       
  5606         TRAPD(err, RunL());
       
  5607         if (err == KErrNone) {
       
  5608             return true;
       
  5609         }
       
  5610     }
       
  5611     return false;
       
  5612 }
       
  5613 
       
  5614 void CAsynchronousMTMOperation::RunL()
       
  5615 {
       
  5616     if (iStatus.Int() != KErrNone && iOperationStep != MTMOperationStepDisconnect) {
       
  5617         delete ipMsvEntrySelection;
       
  5618         ipMsvEntrySelection = NULL;
       
  5619         delete ipMsvOperation;
       
  5620         ipMsvOperation = NULL;
       
  5621     
       
  5622         isActive = false;
       
  5623         ipPrivateService->setFinished(false);
       
  5624 
       
  5625         if (ipParent) {
       
  5626             ipParent->deleteAsynchronousMTMOperation(this);
       
  5627         }
       
  5628         return;
       
  5629     }
       
  5630 
       
  5631     ipMTM->SwitchCurrentEntryL(iServiceId);
       
  5632     
       
  5633     switch(iOperationStep) {
       
  5634     case CAsynchronousMTMOperation::MTMOperationStepConnect:
       
  5635         {
       
  5636         TPckgBuf<TInt> parameter;
       
  5637         ipMsvEntrySelection = new(ELeave) CMsvEntrySelection;
       
  5638         ipMsvEntrySelection->AppendL(iServiceId);
       
  5639         
       
  5640         if (ipMTM->Type() == KUidMsgTypeIMAP4) {
       
  5641             ipMsvOperation = ipMTM->InvokeAsyncFunctionL(KIMAP4MTMConnect,
       
  5642                                                          *ipMsvEntrySelection,
       
  5643                                                          parameter,
       
  5644                                                          iStatus);
       
  5645         } else if (ipMTM->Type() == KUidMsgTypePOP3) {
       
  5646             ipMsvOperation = ipMTM->InvokeAsyncFunctionL(KPOP3MTMConnect,
       
  5647                                                          *ipMsvEntrySelection,
       
  5648                                                          parameter,
       
  5649                                                          iStatus);
       
  5650         }
       
  5651         iOperationStep = MTMOperationStepDoOperation;
       
  5652         SetActive();
       
  5653         }
       
  5654         break;
       
  5655     case CAsynchronousMTMOperation::MTMOperationStepDoOperation:
       
  5656         {
       
  5657         delete ipMsvEntrySelection;
       
  5658         ipMsvEntrySelection = NULL;
       
  5659         delete ipMsvOperation;
       
  5660         ipMsvOperation = NULL;
       
  5661         
       
  5662         if (iOperation == MTMOperationRetrieveMessageHeader) {
       
  5663             // Retrieve header
       
  5664             ipMsvEntrySelection = new(ELeave) CMsvEntrySelection;
       
  5665             
       
  5666             if (ipMTM->Type() == KUidMsgTypeIMAP4) {
       
  5667                 ipMsvEntrySelection->AppendL(iMessageId);
       
  5668                 TImImap4GetMailInfo info;
       
  5669                 info.iMaxEmailSize = KMaxTInt;
       
  5670                 info.iGetMailBodyParts = EGetImap4EmailHeaders;
       
  5671                 TPckg<TImImap4GetMailInfo> bodyInfo(info);
       
  5672                 ipMsvOperation = ipMTM->InvokeAsyncFunctionL(KIMAP4MTMPopulate,
       
  5673                                                              *ipMsvEntrySelection,
       
  5674                                                              bodyInfo,
       
  5675                                                              iStatus);
       
  5676             } else if (ipMTM->Type() == KUidMsgTypePOP3) {
       
  5677                 ipMsvEntrySelection->AppendL(iServiceId);
       
  5678                 ipMsvEntrySelection->AppendL(iMessageId);
       
  5679                 TPckgBuf<TInt> parameter;
       
  5680                 ipMsvOperation = ipMTM->InvokeAsyncFunctionL(KPOP3MTMPopulate,
       
  5681                                                              *ipMsvEntrySelection,
       
  5682                                                              parameter,
       
  5683                                                              iStatus);
       
  5684             }
       
  5685         } else if (iOperation == MTMOperationRetrieveMessageBody) {
       
  5686             // Retrieve message body
       
  5687             ipMsvEntrySelection = new(ELeave) CMsvEntrySelection;
       
  5688             
       
  5689             if (ipMTM->Type() == KUidMsgTypeIMAP4) {
       
  5690                 ipMsvEntrySelection->AppendL(iMessageId);
       
  5691                 TImImap4GetPartialMailInfo info;
       
  5692                 info.iMaxEmailSize = KMaxTInt;
       
  5693                 info.iTotalSizeLimit = KMaxTInt;
       
  5694                 info.iBodyTextSizeLimit = KMaxTInt;
       
  5695                 info.iPartialMailOptions = EBodyTextOnly;
       
  5696                 TPckg<TImImap4GetPartialMailInfo> bodyInfo(info);
       
  5697                 ipMsvOperation = ipMTM->InvokeAsyncFunctionL(KIMAP4MTMPopulate,
       
  5698                                                              *ipMsvEntrySelection,
       
  5699                                                              bodyInfo,
       
  5700                                                              iStatus);
       
  5701             } else if (ipMTM->Type() == KUidMsgTypePOP3) {
       
  5702                 ipMsvEntrySelection->AppendL(iServiceId);
       
  5703                 ipMsvEntrySelection->AppendL(iMessageId);
       
  5704                 TPckgBuf<TInt> parameter;
       
  5705                 ipMsvOperation = ipMTM->InvokeAsyncFunctionL(KPOP3MTMPopulate,
       
  5706                                                              *ipMsvEntrySelection,
       
  5707                                                              parameter,
       
  5708                                                              iStatus);
       
  5709             }
       
  5710         }  else if (iOperation == MTMOperationRetrieveMessageAttachments) {
       
  5711             // Retrieve message attachments
       
  5712             ipMsvEntrySelection = new(ELeave) CMsvEntrySelection;
       
  5713             
       
  5714             if (ipMTM->Type() == KUidMsgTypeIMAP4) {
       
  5715                 ipMsvEntrySelection->AppendL(iMessageId);
       
  5716                 TImImap4GetPartialMailInfo info;
       
  5717                 info.iMaxEmailSize = KMaxTInt;
       
  5718                 info.iTotalSizeLimit = KMaxTInt;
       
  5719                 info.iAttachmentSizeLimit = KMaxTInt;
       
  5720                 info.iPartialMailOptions = EAttachmentsOnly;
       
  5721                 TPckg<TImImap4GetPartialMailInfo> bodyInfo(info);
       
  5722                 ipMsvOperation = ipMTM->InvokeAsyncFunctionL(KIMAP4MTMPopulate,
       
  5723                                                              *ipMsvEntrySelection,
       
  5724                                                              bodyInfo,
       
  5725                                                              iStatus);
       
  5726             } else if (ipMTM->Type() == KUidMsgTypePOP3) {
       
  5727                 ipMsvEntrySelection->AppendL(iServiceId);
       
  5728                 ipMsvEntrySelection->AppendL(iMessageId);
       
  5729                 TPckgBuf<TInt> parameter;
       
  5730                 ipMsvOperation = ipMTM->InvokeAsyncFunctionL(KPOP3MTMPopulate,
       
  5731                                                              *ipMsvEntrySelection,
       
  5732                                                              parameter,
       
  5733                                                              iStatus);
       
  5734             }
       
  5735         } else if (iOperation == MTMOperationFullSync) {
       
  5736             // Do full sync for IMAP Account
       
  5737             // <=> in addition to syncing messages from server to client
       
  5738             //     syncs also changes (like read statuses) from client to server
       
  5739             ipMsvEntrySelection = new(ELeave) CMsvEntrySelection;
       
  5740             ipMsvEntrySelection->AppendL(iServiceId);
       
  5741             
       
  5742             TImImap4GetMailInfo imap4GetMailInfo;
       
  5743             imap4GetMailInfo.iMaxEmailSize = KMaxTInt;
       
  5744             imap4GetMailInfo.iDestinationFolder = iServiceId+1; // remote inbox
       
  5745             imap4GetMailInfo.iGetMailBodyParts = EGetImap4EmailHeaders;
       
  5746             TPckgBuf<TImImap4GetMailInfo> package(imap4GetMailInfo);
       
  5747             
       
  5748             ipMsvOperation = ipMTM->InvokeAsyncFunctionL(KIMAP4MTMFullSync,
       
  5749                                                          *ipMsvEntrySelection,
       
  5750                                                          package,
       
  5751                                                          iStatus);
       
  5752             
       
  5753         
       
  5754         }
       
  5755         iOperationStep = MTMOperationStepDisconnect;
       
  5756         SetActive();
       
  5757         }
       
  5758         break;
       
  5759     case CAsynchronousMTMOperation::MTMOperationStepDisconnect:
       
  5760         {
       
  5761         delete ipMsvEntrySelection;
       
  5762         ipMsvEntrySelection = NULL;
       
  5763         delete ipMsvOperation;
       
  5764         ipMsvOperation = NULL;
       
  5765         
       
  5766         TPckgBuf<TInt> parameter;
       
  5767         ipMsvEntrySelection = new(ELeave) CMsvEntrySelection;
       
  5768         ipMsvEntrySelection->AppendL(iServiceId);
       
  5769         if (ipMTM->Type() == KUidMsgTypeIMAP4) {
       
  5770             ipMsvOperation = ipMTM->InvokeAsyncFunctionL(KIMAP4MTMDisconnect,
       
  5771                                                          *ipMsvEntrySelection,
       
  5772                                                          parameter,
       
  5773                                                          iStatus);
       
  5774         } else if (ipMTM->Type() == KUidMsgTypePOP3) {
       
  5775             ipMsvOperation = ipMTM->InvokeAsyncFunctionL(KPOP3MTMDisconnect,
       
  5776                                                          *ipMsvEntrySelection,
       
  5777                                                          parameter,
       
  5778                                                          iStatus);
       
  5779         }
       
  5780         iOperationStep = MTMOperationStepFinished;
       
  5781         SetActive();
       
  5782         }
       
  5783         break;
       
  5784     case CAsynchronousMTMOperation::MTMOperationStepFinished:
       
  5785         delete ipMsvEntrySelection;
       
  5786         ipMsvEntrySelection = NULL;
       
  5787         delete ipMsvOperation;
       
  5788         ipMsvOperation = NULL;
       
  5789 
       
  5790         isActive = false;
       
  5791         ipPrivateService->setFinished(true);
       
  5792         ipParent->deleteAsynchronousMTMOperation(this);
       
  5793         break;
       
  5794     }
       
  5795 }
       
  5796 
       
  5797 void CAsynchronousMTMOperation::DoCancel()
       
  5798 {
       
  5799     ipMsvOperation->Cancel();
       
  5800 }
       
  5801 
       
  5802 #include "moc_qmtmengine_symbian_p.cpp";
       
  5803 
       
  5804 QTM_END_NAMESPACE