diff -r cfcbf08528c4 -r 2b40d63a9c3d qtmobility/src/messaging/qmtmengine_symbian.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/qtmobility/src/messaging/qmtmengine_symbian.cpp Fri Apr 16 15:51:22 2010 +0300 @@ -0,0 +1,5533 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qmessagestore_symbian_p.h" +#include "qmtmengine_symbian_p.h" +#include "qmessage_symbian_p.h" +#include "qmessagesortorder_p.h" +#include "qmessageaccount.h" +#include "qmessageaccount_p.h" +#include "qmessageaccountfilter.h" +#include "qmessageaccountfilter_p.h" +#include "qmessageaccountsortorder_p.h" +#include "qmessagefoldersortorder_p.h" +#include "qmessagesortorder_p.h" +#include "qmessagefolder.h" +#include "qmessagefolder_p.h" +#include "qmessagefolderfilter.h" +#include "qmessagefolderfilter_p.h" +#include "qmessageservice_symbian_p.h" +#include "qmessagecontentcontainer_symbian_p.h" +#include "qmessagecontentcontainer_p.h" + +#include +#include // TMsvId's +#include // CClientMtmRegistry +#include // CSmsClientMtm +#include // CMmsClientMtm +#include // CSmtpClientMtm +#include // CImap4ClientMtm +#include // CPop3ClientMtm +#include //CEmailAccounts +#include // CMsvFindOperation +#include // TMsvPartList +#include // CnvUtfConverter +#include +#include // Attachemt mimeheader +#include +#include +#include +#include // CMtmUiRegistry +#include // CBaseMtmUi +#include +#include // SendUi API +#include //CMessageData +#include +#include +#include +#include +#include +#include +#include +#include // KImcvMultipart declaration + +#include + +QTM_BEGIN_NAMESPACE + +const TInt KWaitAfterReceivedMessage = 100000; // = 0.1 seconds +#define KDocumentsEntryIdValue 0x1008 + +Q_GLOBAL_STATIC(CMTMEngine,mtmEngine); + +CMTMEngine::CMTMEngine() + : CActive(EPriorityStandard) +{ + iFsSession.Connect(); + CActiveScheduler::Add(this); + iTimer.CreateLocal(); + + TRAPD(err, + ipMsvSession = CMsvSession::OpenSyncL(*this); + iSessionReady = ETrue; + ipClientMtmReg = CClientMtmRegistry::NewL(*ipMsvSession); + ipSmsMtm = static_cast(ipClientMtmReg->NewMtmL(KUidMsgTypeSMS)); + ipMmsMtm = static_cast(ipClientMtmReg->NewMtmL(KUidMsgTypeMultimedia)); + ipSmtpMtm = static_cast(ipClientMtmReg->NewMtmL(KUidMsgTypeSMTP)); + ipImap4Mtm = static_cast(ipClientMtmReg->NewMtmL(KUidMsgTypeIMAP4)); + ipPop3Mtm = static_cast(ipClientMtmReg->NewMtmL(KUidMsgTypePOP3)); + ); + Q_UNUSED(err) + + // Create & Add SMS Account + TRAPD(accountError, + iSMSAccountidAsString = QString::number(mtmServiceEntryIdL(CMTMEngine::MTMTypeSMS)); + QMessageAccount smsAcc = QMessageAccountPrivate::from(QMessageAccountId(iSMSAccountidAsString), + QString("SMS"), + mtmServiceEntryIdL(CMTMEngine::MTMTypeSMS), + 0, + QMessage::Sms); + iAccounts.insert(iSMSAccountidAsString, smsAcc); + + + // Create & Add MMS Account + iMMSAccountidAsString = QString::number(mtmServiceEntryIdL(CMTMEngine::MTMTypeMMS)); + QMessageAccount mmsAcc = QMessageAccountPrivate::from(QMessageAccountId(iMMSAccountidAsString), + QString("MMS"), + mtmServiceEntryIdL(CMTMEngine::MTMTypeMMS), + 0, + QMessage::Mms | QMessage::Email); + iAccounts.insert(iMMSAccountidAsString, mmsAcc); + updateEmailAccountsL(); + ); + Q_UNUSED(accountError) + + TRAPD(err2, + TBuf privatePath; + FsSession().CreatePrivatePath(EDriveC); + FsSession().PrivatePath(privatePath); + iPath.Append(_L("c:")); + iPath.Append(privatePath); + iPath.Append(_L("tempattachments\\")); + CFileMan* pFileMan = CFileMan::NewL(FsSession()); + CleanupStack::PushL(pFileMan); + pFileMan->RmDir(iPath); + FsSession().MkDirAll(iPath); + CleanupStack::PopAndDestroy(pFileMan); + ); + Q_UNUSED(err2) +} + +CMTMEngine::~CMTMEngine() +{ + iCmsvEntryPoolFree.ResetAndDestroy(); + iCmsvEntryPoolInUse.ResetAndDestroy(); + + delete ipPop3Mtm; + delete ipImap4Mtm; + delete ipSmtpMtm; + delete ipMmsMtm; + delete ipSmsMtm; + + delete ipClientMtmReg; + delete ipMsvSession; + + TRAPD(error, + TBuf privatePath; + FsSession().CreatePrivatePath(EDriveC); + FsSession().PrivatePath(privatePath); + TBuf path; + path.Append(_L("c:")); + path.Append(privatePath); + path.Append(_L("tempattachments\\")); + CFileMan* pFileMan=CFileMan::NewL(FsSession()); + CleanupStack::PushL(pFileMan); + pFileMan->RmDir(path); + CleanupStack::PopAndDestroy(pFileMan); + ); + Q_UNUSED(error) + + Cancel(); + iTimer.Close(); + iFsSession.Close(); +} + +CMTMEngine* CMTMEngine::instance() +{ + return mtmEngine(); +} + +bool CMTMEngine::accountLessThan(const QMessageAccountId accountId1, const QMessageAccountId accountId2) +{ + CMTMEngine* pMTMEngine = mtmEngine(); + return QMessageAccountSortOrderPrivate::lessThan(pMTMEngine->iCurrentAccountOrdering, + pMTMEngine->account(accountId1), + pMTMEngine->account(accountId2)); +} + +void CMTMEngine::orderAccounts(QMessageAccountIdList& accountIds, const QMessageAccountSortOrder &sortOrder) const +{ + iCurrentAccountOrdering = sortOrder; + qSort(accountIds.begin(), accountIds.end(), CMTMEngine::accountLessThan); +} + +bool CMTMEngine::folderLessThan(const QMessageFolderId folderId1, const QMessageFolderId folderId2) +{ + CMTMEngine* pMTMEngine = mtmEngine(); + return QMessageFolderSortOrderPrivate::lessThan(pMTMEngine->iCurrentFolderOrdering, + pMTMEngine->folder(folderId1), + pMTMEngine->folder(folderId2)); +} + +void CMTMEngine::orderFolders(QMessageFolderIdList& folderIds, const QMessageFolderSortOrder &sortOrder) const +{ + iCurrentFolderOrdering = sortOrder; + qSort(folderIds.begin(), folderIds.end(), CMTMEngine::folderLessThan); +} + +bool CMTMEngine::messageLessThan(const QMessage& message1, const QMessage& message2) +{ + CMTMEngine* pMTMEngine = mtmEngine(); + return QMessageSortOrderPrivate::lessThan(pMTMEngine->iCurrentMessageOrdering, message1, message2); +} + +void CMTMEngine::orderMessages(QMessageIdList& messageIds, const QMessageSortOrder &sortOrder) const +{ + iCurrentMessageOrdering = sortOrder; + QList messages; + for (int i=0; i < messageIds.count(); i++) { + messages.append(message(messageIds[i])); + } + qSort(messages.begin(), messages.end(), CMTMEngine::messageLessThan); + messageIds.clear(); + for (int i=0; i < messages.count(); i++) { + messageIds.append(messages[i].id()); + } +} + +QMessageAccountIdList CMTMEngine::queryAccounts(const QMessageAccountFilter &filter, const QMessageAccountSortOrder &sortOrder, uint limit, uint offset) const +{ + QMessageAccountIdList accountIds; + + TRAPD(err, updateEmailAccountsL()); + Q_UNUSED(err) + + QMessageAccountFilterPrivate* privateMessageAccountFilter = QMessageAccountFilterPrivate::implementation(filter); + if (filter.isEmpty()) { + if (!privateMessageAccountFilter->_notFilter) { + // All accounts are returned for empty filter + foreach (QMessageAccount value, iAccounts) { + accountIds.append(value.id()); + } + } + } else { + if (privateMessageAccountFilter->_valid) { + foreach (QMessageAccount value, iAccounts) { + if (privateMessageAccountFilter->filter(value)) { + accountIds.append(value.id()); + } + } + } else { + foreach (QMessageAccount value, iAccounts) { + if (privateMessageAccountFilter->filter(value)) { + accountIds.append(value.id()); + } + } + } + } + + if (!sortOrder.isEmpty()) { + orderAccounts(accountIds, sortOrder); + } + + applyOffsetAndLimitToAccountIds(accountIds, offset, limit); + + return accountIds; +} + +void CMTMEngine::applyOffsetAndLimitToAccountIds(QMessageAccountIdList& idList, int offset, int limit) const +{ + if (offset > 0) { + if (offset > idList.count()) { + idList.clear(); + } else { + for (int i = 0; i < offset; i++) { + idList.removeFirst(); + } + } + } + if (limit > 0) { + for (int i = idList.count()-1; i >= limit; i--) { + idList.removeAt(i); + } + } +} + +int CMTMEngine::countAccounts(const QMessageAccountFilter &filter) const +{ + return queryAccounts(filter, QMessageAccountSortOrder(), 0, 0).count(); +} + +QMessageAccount CMTMEngine::account(const QMessageAccountId &id) const +{ + TRAPD(err, updateEmailAccountsL()); + Q_UNUSED(err) + return iAccounts[id.toString()]; +} + +QMessageAccountId CMTMEngine::accountIdByServiceId(TMsvId serviceId) const +{ + TRAPD(err, updateEmailAccountsL()); + Q_UNUSED(err) + + foreach (QMessageAccount value, iAccounts) { + if (value.d_ptr->_service1EntryId == serviceId || + value.d_ptr->_service2EntryId == serviceId) { + return value.id(); + } + } + + return QMessageAccountId(); +} + +QMessageAccountId CMTMEngine::defaultAccount(QMessage::Type type) const +{ + TRAPD(err, updateEmailAccountsL()); + Q_UNUSED(err) + + if (type == QMessage::Email) { + // Email + return idefaultEmailAccountId; + } else { + // Sms & Mms + foreach (QMessageAccount value, iAccounts) { + if ((value.messageTypes() & type) == (int)type) { + return value.id(); + } + } + } + + return QMessageAccountId(); +} + +QMessageAccountIdList CMTMEngine::accountsByType(QMessage::Type type) const +{ + QMessageAccountIdList accountIds; + + foreach (QMessageAccount value, iAccounts) { + if ((value.messageTypes() & type) == (int)type) { + accountIds.append(value.id()); + } + } + + return accountIds; +} + +void CMTMEngine::updateEmailAccountsL() const +{ + QStringList keys = iAccounts.keys(); + keys.removeOne(iSMSAccountidAsString); + keys.removeOne(iMMSAccountidAsString); + + CEmailAccounts* pEmailAccounts = CEmailAccounts::NewLC(); + + // Default Email account will be the first Email account in the iAccounts list + TSmtpAccount defaultAccount; + TInt err = pEmailAccounts->DefaultSmtpAccountL(defaultAccount); + if (err == KErrNone) { + QString idAsString; + if (defaultAccount.iRelatedService != 0) { + idAsString = QString::number(defaultAccount.iRelatedService); + } else { + idAsString = QString::number(defaultAccount.iSmtpService); + } + if (!iAccounts.contains(idAsString)) { + QMessageAccount account = QMessageAccountPrivate::from(QMessageAccountId(idAsString), + QString::fromUtf16(defaultAccount.iSmtpAccountName.Ptr(), defaultAccount.iSmtpAccountName.Length()), + defaultAccount.iRelatedService, + defaultAccount.iSmtpService, + QMessage::Email); + iAccounts.insert(idAsString, account); + idefaultEmailAccountId = account.id(); + } else { + keys.removeOne(idAsString); + } + } else { + idefaultEmailAccountId = QMessageAccountId(); + } + + RArray imapAccounts(10); + pEmailAccounts->GetImapAccountsL(imapAccounts); + CleanupClosePushL(imapAccounts); + for (int i=0; i < imapAccounts.Count(); i++) { + QString idAsString = QString::number(imapAccounts[i].iImapService); + if (!iAccounts.contains(idAsString)) { + QMessageAccount account = QMessageAccountPrivate::from(QMessageAccountId(idAsString), + QString::fromUtf16(imapAccounts[i].iImapAccountName.Ptr(), imapAccounts[i].iImapAccountName.Length()), + imapAccounts[i].iImapService, + imapAccounts[i].iSmtpService, + QMessage::Email); + iAccounts.insert(idAsString, account); + } else { + keys.removeOne(idAsString); + } + } + CleanupStack::PopAndDestroy(&imapAccounts); + + RArray popAccounts(10); + pEmailAccounts->GetPopAccountsL(popAccounts); + CleanupClosePushL(popAccounts); + for (int i=0; i < popAccounts.Count(); i++) { + QString idAsString = QString::number(popAccounts[i].iPopService); + if (!iAccounts.contains(idAsString)) { + QMessageAccount account = QMessageAccountPrivate::from(QMessageAccountId(QString::number(popAccounts[i].iPopService)), + QString::fromUtf16(popAccounts[i].iPopAccountName.Ptr(), popAccounts[i].iPopAccountName.Length()), + popAccounts[i].iPopService, + popAccounts[i].iSmtpService, + QMessage::Email); + iAccounts.insert(idAsString, account); + } else { + keys.removeOne(idAsString); + } + } + CleanupStack::PopAndDestroy(&popAccounts); + + RArray smtpAccounts(10); + pEmailAccounts->GetSmtpAccountsL(smtpAccounts); + CleanupClosePushL(smtpAccounts); + for (int i=0; i < smtpAccounts.Count(); i++) { + if (smtpAccounts[i].iRelatedService == 0) { + QString idAsString = QString::number(smtpAccounts[i].iSmtpService); + if (!iAccounts.contains(idAsString)) { + QMessageAccount account = QMessageAccountPrivate::from(QMessageAccountId(QString::number(smtpAccounts[i].iSmtpService)), + QString::fromUtf16(smtpAccounts[i].iSmtpAccountName.Ptr(), smtpAccounts[i].iSmtpAccountName.Length()), + smtpAccounts[i].iRelatedService, + smtpAccounts[i].iSmtpService, + QMessage::Email); + iAccounts.insert(idAsString, account); + } else { + keys.removeOne(idAsString); + } + } + } + CleanupStack::PopAndDestroy(&smtpAccounts); + + for (int i=0; i < keys.count(); i++) { + iAccounts.remove(keys[i]); + } + + CleanupStack::PopAndDestroy(pEmailAccounts); +} + +TUid CMTMEngine::mtmUidByType(MTMType aMTMType) +{ + switch(aMTMType) { + case CMTMEngine::MTMTypeSMS: return KUidMsgTypeSMS; + case CMTMEngine::MTMTypeMMS: return KUidMsgTypeMultimedia; + case CMTMEngine::MTMTypeSMTP: return KUidMsgTypeSMTP; + case CMTMEngine::MTMTypeIMAP: return KUidMsgTypeIMAP4; + case CMTMEngine::MTMTypePOP3: return KUidMsgTypePOP3; + } + + return TUid(); +} + +CBaseMtm* CMTMEngine::mtmByUid(TUid aMTMUid) +{ + if (aMTMUid == KUidMsgTypeSMS) { + return ipSmsMtm; + } else if (aMTMUid == KUidMsgTypeMultimedia) { + return ipMmsMtm; + } else if (aMTMUid == KUidMsgTypeSMTP) { + return ipSmtpMtm; + } else if (aMTMUid == KUidMsgTypeIMAP4) { + return ipImap4Mtm; + } else if (aMTMUid == KUidMsgTypePOP3) { + return ipPop3Mtm; + } + + return 0; +} + +TMsvId CMTMEngine::mtmServiceEntryIdL(MTMType aMTMType) const +{ + TUid mtmUID; + switch(aMTMType) { + case CMTMEngine::MTMTypeSMS: + mtmUID = KUidMsgTypeSMS; + break; + case CMTMEngine::MTMTypeMMS: + mtmUID = KUidMsgTypeMultimedia; + break; + case CMTMEngine::MTMTypeSMTP: + mtmUID = KUidMsgTypeSMTP; + break; + case CMTMEngine::MTMTypeIMAP: + mtmUID = KUidMsgTypeIMAP4; + break; + case CMTMEngine::MTMTypePOP3: + mtmUID = KUidMsgTypePOP3; + break; + } + + CMsvEntry* pCurrentEntry = ipMsvSession->GetEntryL(KMsvRootIndexEntryId); + CleanupStack::PushL(pCurrentEntry); + + // Sorting or grouping is not needed + pCurrentEntry->SetSortTypeL(TMsvSelectionOrdering(KMsvNoGrouping,EMsvSortByNone, ETrue)); + + // Loop through child entries until MTM specific + // root entry has been found + TMsvId mtmRootEntryId = KMsvRootIndexEntryId; + TInt count = pCurrentEntry->Count(); + for(TInt i = 0; iGetEntry(mtmRootEntryId, mtmServiceEntryId, indexEntry); + if (error != KErrNone) { + // MTM specific service entry Id was not found + return 0; + } + + return mtmServiceEntryId; +} + +bool CMTMEngine::switchToMTMRootEntry(MTMType aMTMType) +{ + TRAPD(err, + CBaseMtm* pMTM = mtmByType(aMTMType); + TMsvId mtmEntryId = mtmServiceEntryIdL(aMTMType); + + CMsvEntry* pMTMServiceEntry = ipMsvSession->GetEntryL(mtmEntryId); + CleanupStack::PushL(pMTMServiceEntry); + // Set service entry as current entry of ClientMTM class + pMTM->SetCurrentEntryL(pMTMServiceEntry); // Takes ownership of pMTMServiceEntry + CleanupStack::Pop(pMTMServiceEntry); + ); + if (err != KErrNone) + return false; + else + return true; +} + +CBaseMtm* CMTMEngine::mtmByType(MTMType aMTMType) +{ + switch(aMTMType) { + case CMTMEngine::MTMTypeSMS: return ipSmsMtm; + case CMTMEngine::MTMTypeMMS: return ipMmsMtm; + case CMTMEngine::MTMTypeSMTP: return ipSmtpMtm; + case CMTMEngine::MTMTypeIMAP: return ipImap4Mtm; + case CMTMEngine::MTMTypePOP3: return ipPop3Mtm; + } + + return 0; +} + +TMsvId CMTMEngine::standardFolderId(QMessage::StandardFolder standardFolder) +{ + switch(standardFolder) { + case QMessage::InboxFolder: return KMsvGlobalInBoxIndexEntryIdValue; + case QMessage::OutboxFolder: return KMsvGlobalOutBoxIndexEntryIdValue; + case QMessage::DraftsFolder: return KMsvDraftEntryIdValue; + case QMessage::SentFolder: return KMsvSentEntryIdValue; + case QMessage::TrashFolder: return KMsvDeletedEntryFolderEntryIdValue; + } + + return TMsvId(); +} + +bool CMTMEngine::addMessage(QMessage* message) +{ + bool retVal = false; + + if (message->type() == QMessage::NoType) { + if (message->parentAccountId().isValid()){ + QMessageAccount account = QMessageAccount(message->parentAccountId()); + QMessage::TypeFlags types = account.messageTypes(); + if (types & QMessage::Sms) { + message->setType(QMessage::Sms); + } else if (types & QMessage::Mms) { + message->setType(QMessage::Mms); + } else if (types & QMessage::Email) { + message->setType(QMessage::Email); + } + } else { + return false; + } + } + + if (!message->parentAccountId().isValid() && message->type() != QMessage::NoType) { + message->setParentAccountId(QMessageAccount::defaultAccount(message->type())); + } + + if (message->type() == QMessage::Sms){ + retVal = storeSMS(*message); + } + else if (message->type() == QMessage::Mms){ + retVal = storeMMS(*message); + } + else if (message->type() == QMessage::Email){ + retVal = storeEmail(*message); + } + + return retVal; +} + +bool CMTMEngine::updateMessage(QMessage* m) +{ + bool retVal = true; + + if (m->parentAccountId().isValid()){ + QMessageAccount account = QMessageAccount(m->parentAccountId()); + QMessage::TypeFlags types = account.messageTypes(); + if (types & QMessage::Sms){ + m->setType(QMessage::Sms); + } else if (types & QMessage::Mms){ + m->setType(QMessage::Mms); + } else if (types & QMessage::Email){ + m->setType(QMessage::Email); + } + } + + if (m->type() == QMessage::Sms){ + TRAPD(err, updateSMSL(*m)); + if (err != KErrNone) + retVal = false; + } else if (m->type() == QMessage::Mms){ + TRAPD(err, updateMMSL(*m)); + if (err != KErrNone) + retVal = false; + } else if (m->type() == QMessage::Email){ + TRAPD(err, updateEmailL(*m)); + if (err != KErrNone) + retVal = false; + } + + return retVal; +} + +// Copy message to another folder. +void CMTMEngine::copyMessageL(TMsvId aMessageId, TMsvId aFolder) +{ + ipSmsMtm->SwitchCurrentEntryL(aMessageId); + TMsvSelectionOrdering selection; + selection.SetShowInvisibleEntries(ETrue); + CMsvEntry* pParentEntry = CMsvEntry::NewL(ipSmsMtm->Session(), + ipSmsMtm->Entry().Entry().Parent(), + selection); + CleanupStack::PushL(pParentEntry); + // iSmsMtm points to the parent + pParentEntry->CopyL(aMessageId, aFolder); + CleanupStack::PopAndDestroy(); // parentEntry +} + +bool CMTMEngine::removeMessage(const QMessageId &id, QMessageManager::RemovalOption option) +{ + if (!iSessionReady) + return false; + + bool retVal = false; + TRAPD(err, retVal = removeMessageL(id, option)); + if (err != KErrNone) + retVal = false; + + return retVal; +} + +bool CMTMEngine::showMessage(const QMessageId &id) +{ + if (!iSessionReady) + return false; + + TRAPD(err, showMessageL(id)); + if (err != KErrNone) + return false; + else + return true; +} + +void CMTMEngine::showMessageL(const QMessageId &id) +{ + long int messageId = id.toString().toLong(); + + CMsvEntry* pEntry = ipMsvSession->GetEntryL(messageId); + CleanupStack::PushL(pEntry); + CBaseMtm* mtm = ipClientMtmReg->NewMtmL(pEntry->Entry().iMtm); + CleanupStack::PushL(mtm); + + CMtmUiRegistry* mtmUiRegistry = CMtmUiRegistry::NewL(*ipMsvSession); + CleanupStack::PushL(mtmUiRegistry); + + CBaseMtmUi* ui = mtmUiRegistry->NewMtmUiL(*mtm); + CleanupStack::PushL(ui); + + ui->BaseMtm().SwitchCurrentEntryL(messageId); + CMsvOperationWait* waiter = CMsvOperationWait::NewLC(); + waiter->Start(); + CMsvOperation* op = ui->OpenL(waiter->iStatus); + CleanupStack::PushL(op); + + CActiveScheduler::Start(); + + CleanupStack::PopAndDestroy(6); // op,waiter,ui,mtmuiregistry,mtm,pEntry +} + +bool CMTMEngine::composeMessage(const QMessage &message) +{ + bool retVal = true; + + if (message.parentAccountId().isValid()){ + QMessageAccount account = QMessageAccount(message.parentAccountId()); + QMessage::TypeFlags types = account.messageTypes(); + if (types & QMessage::Sms){ + TRAPD(err, retVal = composeSMSL(message)); + if (err != KErrNone) + retVal = false; + } else if (types & QMessage::Mms){ + TRAPD(err, retVal = composeMMSL(message)); + if (err != KErrNone) + retVal = false; + } else if (types & QMessage::Email){ + TRAPD(err, retVal = composeEmailL(message)); + if (err != KErrNone) + retVal = false; + } + } else { + if (message.type() == QMessage::Sms){ + TRAPD(err, retVal = composeSMSL(message)); + if (err != KErrNone) + retVal = false; + } + else if (message.type() == QMessage::Mms){ + TRAPD(err, retVal = composeMMSL(message)); + if (err != KErrNone) + retVal = false; + } + else if (message.type() == QMessage::Email){ + TRAPD(err, retVal = composeEmailL(message)); + if (err != KErrNone) + retVal = false; + } + } + + return retVal; +} + +bool CMTMEngine::composeSMSL(const QMessage &message) +{ + CSendUi *sendUi = CSendUi::NewL(); + CleanupStack::PushL(sendUi); + CMessageData* messageData = CMessageData::NewLC(); + // Add receivers + QList list(message.to()); + TPtrC16 receiver(KNullDesC); + QString qreceiver; + for (int i = 0; i < list.size(); ++i) { + qreceiver = list.at(i).recipient(); + receiver.Set(reinterpret_cast(qreceiver.utf16())); + messageData->AppendToAddressL(receiver, KNullDesC); + } + // Set Body text + QString body = message.textContent(); + TPtrC16 msg(reinterpret_cast(body.utf16())); + HBufC* bd = msg.AllocLC(); + TPtr ptr(bd->Des()); + + ipParaFormatLayer = CParaFormatLayer::NewL(); + ipCharFormatLayer = CCharFormatLayer::NewL(); + ipRichText = CRichText::NewL(ipParaFormatLayer,ipCharFormatLayer); + TInt pos = 0; // Insertion position of text will be zero + ipRichText->Reset(); + ipRichText->InsertL(pos, ptr); + messageData->SetBodyTextL(ipRichText); + + sendUi->CreateAndSendMessageL(KSenduiMtmSmsUid, messageData, KNullUid, ETrue); + CleanupStack::PopAndDestroy(3); //bd, messageData and sendUi + return true; +} + +bool CMTMEngine::composeMMSL(const QMessage &message) +{ + CSendUi *sendUi = CSendUi::NewL(); + CleanupStack::PushL(sendUi); + TUid bioTypeUid = KNullUid; + CMessageData* messageData = CMessageData::NewLC(); + + // Add receivers + QList list(message.to()); + TPtrC16 receiver(KNullDesC); + QString qreceiver; + for (int i = 0; i < list.size(); ++i) { + qreceiver = list.at(i).recipient(); + receiver.Set(reinterpret_cast(qreceiver.utf16())); + messageData->AppendToAddressL(receiver, KNullDesC); + } + + // Set Subject + QString subject = message.subject(); + TPtrC16 sbj(reinterpret_cast(subject.utf16())); + messageData->SetSubjectL(&sbj); + + QByteArray filePath; + QMessageContentContainerIdList contentIds = message.contentIds(); + foreach (QMessageContentContainerId id, contentIds){ + QMessageContentContainer container = message.find(id); + QByteArray filePath = QMessageContentContainerPrivate::attachmentFilename(container); + QString fileName = QString(filePath); + QString body = container.textContent(); + if (!fileName.isEmpty()){ // content is attachment + filePath.replace(QByteArray("/"), QByteArray("\\")); + QString temp_path = QString(filePath); + TPtrC16 attachmentPath(KNullDesC); + attachmentPath.Set(reinterpret_cast(temp_path.utf16())); + messageData->AppendAttachmentL(attachmentPath); + } + else if (!body.isEmpty()) { // content is Body text + TPtrC16 msg(reinterpret_cast(body.utf16())); + HBufC* bd = msg.AllocLC(); + TPtr ptr(bd->Des()); + ipParaFormatLayer = CParaFormatLayer::NewL(); + ipCharFormatLayer = CCharFormatLayer::NewL(); + ipRichText = CRichText::NewL(ipParaFormatLayer, ipCharFormatLayer); + TInt pos = 0; // Insertion position of text will be zero + ipRichText->Reset(); + ipRichText->InsertL(pos, ptr); + messageData->SetBodyTextL(ipRichText); + CleanupStack::PopAndDestroy(bd); + } + } + QString messageBody = message.textContent(); + if (!messageBody.isEmpty()) { // no contents, only body text + TPtrC16 msg(reinterpret_cast(messageBody.utf16())); + HBufC* bd = msg.AllocLC(); + TPtr ptr(bd->Des()); + ipParaFormatLayer = CParaFormatLayer::NewL(); + ipCharFormatLayer = CCharFormatLayer::NewL(); + ipRichText = CRichText::NewL(ipParaFormatLayer, ipCharFormatLayer); + TInt pos = 0; // Insertion position of text will be zero + ipRichText->Reset(); + ipRichText->InsertL(pos, ptr); + messageData->SetBodyTextL(ipRichText); + CleanupStack::PopAndDestroy(bd); + } + + sendUi->CreateAndSendMessageL(KSenduiMtmMmsUid, messageData, KNullUid, ETrue); + CleanupStack::PopAndDestroy(2); //messageData and sendUi + return true; +} + +bool CMTMEngine::composeEmailL(const QMessage &message) +{ + CSendUi *sendUi = CSendUi::NewL(); + CleanupStack::PushL(sendUi); + CMessageData* messageData = CMessageData::NewLC(); + + // Add receivers + QList list(message.to()); + TPtrC16 receiver(KNullDesC); + QString qreceiver; + for (int i = 0; i < list.size(); ++i) { + qreceiver = list.at(i).recipient(); + receiver.Set(reinterpret_cast(qreceiver.utf16())); + messageData->AppendToAddressL(receiver, KNullDesC); + } + //cc + QList ccList(message.cc()); + TPtrC16 ccReceiver(KNullDesC); + QString ccQreceiver; + for (int i = 0; i < ccList.size(); ++i) { + ccQreceiver = ccList.at(i).recipient(); + ccReceiver.Set(reinterpret_cast(ccQreceiver.utf16())); + messageData->AppendCcAddressL(ccReceiver, KNullDesC); + } + //bcc + QList bccList(message.bcc()); + TPtrC16 bccReceiver(KNullDesC); + QString bccQreceiver; + for (int i = 0; i < bccList.size(); ++i) { + bccQreceiver = bccList.at(i).recipient(); + bccReceiver.Set(reinterpret_cast(bccQreceiver.utf16())); + messageData->AppendBccAddressL(bccReceiver, KNullDesC); + } + + // Set Subject + QString subject = message.subject(); + TPtrC16 sbj(reinterpret_cast(subject.utf16())); + messageData->SetSubjectL(&sbj); + + QByteArray filePath; + QMessageContentContainerIdList contentIds = message.contentIds(); + foreach (QMessageContentContainerId id, contentIds){ + QMessageContentContainer container = message.find(id); + QByteArray filePath = QMessageContentContainerPrivate::attachmentFilename(container); + QString body = container.textContent(); + QString fileName = QString(filePath); + if (!fileName.isEmpty()){ // content is attachment + filePath.replace(QByteArray("/"), QByteArray("\\")); + QString temp_path = QString(filePath); + TPtrC16 attachmentPath(KNullDesC); + attachmentPath.Set(reinterpret_cast(temp_path.utf16())); + messageData->AppendAttachmentL(attachmentPath); + } + else if (!body.isEmpty()) { // content is Body text + TPtrC16 msg(reinterpret_cast(body.utf16())); + HBufC* bd = msg.AllocLC(); + TPtr ptr(bd->Des()); + ipParaFormatLayer = CParaFormatLayer::NewL(); + ipCharFormatLayer = CCharFormatLayer::NewL(); + ipRichText = CRichText::NewL(ipParaFormatLayer, ipCharFormatLayer); + TInt pos = 0; // Insertion position of text will be zero + ipRichText->Reset(); + ipRichText->InsertL(pos, ptr); + messageData->SetBodyTextL(ipRichText); + CleanupStack::PopAndDestroy(bd); + } + } + QString messageBody = message.textContent(); + if (!messageBody.isEmpty()) { // no contents, only body text + TPtrC16 msg(reinterpret_cast(messageBody.utf16())); + HBufC* bd = msg.AllocLC(); + TPtr ptr(bd->Des()); + ipParaFormatLayer = CParaFormatLayer::NewL(); + ipCharFormatLayer = CCharFormatLayer::NewL(); + ipRichText = CRichText::NewL(ipParaFormatLayer, ipCharFormatLayer); + TInt pos = 0; // Insertion position of text will be zero + ipRichText->Reset(); + ipRichText->InsertL(pos, ptr); + messageData->SetBodyTextL(ipRichText); + CleanupStack::PopAndDestroy(bd); + } + + sendUi->CreateAndSendMessageL(KSenduiMtmSmtpUid, messageData, KNullUid, ETrue); + CleanupStack::PopAndDestroy(2); //messageData and sendUi + return true; +} + +bool CMTMEngine::retrieve(const QMessageId &messageId, const QMessageContentContainerId& id) +{ + TRAPD(err, retrieveL(messageId, id)); + if (err != KErrNone) + return false; + else + return true; +} + +void CMTMEngine::retrieveL(const QMessageId &messageId, const QMessageContentContainerId& id) +{ + Q_UNUSED(id); // all attachments are retrieved (cannot retrieve only one) + + long int messId = messageId.toString().toLong(); + + CMsvEntry* pEntry = ipMsvSession->GetEntryL(messId); + CleanupStack::PushL(pEntry); + + CMsvEntrySelection* sel = new(ELeave) CMsvEntrySelection; + CleanupStack::PushL(sel); + + CMsvOperationWait* wait = CMsvOperationWait::NewLC(); + + if (pEntry->Entry().iMtm == KUidMsgTypeIMAP4){ + TPckgBuf parameter; + + ipImap4Mtm->SwitchCurrentEntryL(pEntry->OwningService()); + + sel->AppendL(messId); + + CMsvOperation* opConnect = ipImap4Mtm->InvokeAsyncFunctionL(KIMAP4MTMConnect, + *sel, parameter, wait->iStatus); + CleanupStack::PushL(opConnect); + wait->Start(); + CActiveScheduler::Start(); + + TImImap4GetPartialMailInfo info; + info.iPartialMailOptions = EAttachmentsOnly; + TPckg bodyInfo(info); + + CMsvOperation* opPopulate = ipImap4Mtm->InvokeAsyncFunctionL(KIMAP4MTMPopulate, + *sel, bodyInfo, wait->iStatus); + CleanupStack::PushL(opPopulate); + wait->Start(); + CActiveScheduler::Start(); + + if (wait->iStatus.Int() != KErrNone) { + if (wait->iStatus.Int() == KErrNotFound){ + // TODO: set messagestatus removed + } + } + + CMsvOperation* opDisconnect = ipImap4Mtm->InvokeAsyncFunctionL(KIMAP4MTMDisconnect, + *sel, parameter, wait->iStatus); + CleanupStack::PushL(opDisconnect); + + wait->Start(); + CActiveScheduler::Start(); + + CleanupStack::PopAndDestroy(3); + } + + if (pEntry->Entry().iMtm == KUidMsgTypePOP3){ + TPckgBuf parameter; + + ipPop3Mtm->SwitchCurrentEntryL(pEntry->OwningService()); + + sel->AppendL(pEntry->EntryId()); + + CMsvOperation* opConnect = ipPop3Mtm->InvokeAsyncFunctionL(KPOP3MTMConnect, + *sel, parameter, wait->iStatus); + + CleanupStack::PushL(opConnect); + wait->Start(); + CActiveScheduler::Start(); + + CImPop3Settings *popSettings = new (ELeave) CImPop3Settings; + CleanupStack::PushL(popSettings); + CEmailAccounts *emailAccounts = CEmailAccounts::NewLC(); + TPopAccount account; + emailAccounts->GetPopAccountL(pEntry->OwningService(), account); + emailAccounts->LoadPopSettingsL(account, *popSettings); + // cannot retrieve only attachment, have to retrieve entire message + popSettings->SetGetMailOptions(EGetPop3EmailMessages); + emailAccounts->SavePopSettingsL(account,*popSettings); + CleanupStack::PopAndDestroy(emailAccounts); + CleanupStack::PopAndDestroy(popSettings); + + CMsvOperation* opPopulate = ipPop3Mtm->InvokeAsyncFunctionL(KPOP3MTMPopulate, + *sel, parameter, wait->iStatus); + CleanupStack::PushL(opPopulate); + wait->Start(); + CActiveScheduler::Start(); + + CMsvOperation* opDisconnect = ipPop3Mtm->InvokeAsyncFunctionL(KPOP3MTMDisconnect, + *sel, parameter, wait->iStatus); + CleanupStack::PushL(opDisconnect); + + wait->Start(); + CActiveScheduler::Start(); + CleanupStack::PopAndDestroy(3); + + } + + CleanupStack::PopAndDestroy(wait); + CleanupStack::PopAndDestroy(sel); + CleanupStack::PopAndDestroy(pEntry); +} + +bool CMTMEngine::retrieveBody(const QMessageId& id) +{ + TRAPD(err, retrieveBodyL(id)); + if (err != KErrNone) + return false; + else + return true; +} + +void CMTMEngine::retrieveBodyL(const QMessageId& id) const +{ + long int messageId = id.toString().toLong(); + + CMsvEntry* pEntry = ipMsvSession->GetEntryL(messageId); + CleanupStack::PushL(pEntry); + + CMsvEntrySelection* sel = new(ELeave) CMsvEntrySelection; + CleanupStack::PushL(sel); + + CMsvOperationWait* wait = CMsvOperationWait::NewLC(); + + if (pEntry->Entry().iMtm == KUidMsgTypeIMAP4){ + TPckgBuf parameter; + + ipImap4Mtm->SwitchCurrentEntryL(pEntry->OwningService()); + + sel->AppendL(messageId); + + CMsvOperation* opConnect = ipImap4Mtm->InvokeAsyncFunctionL(KIMAP4MTMConnect, + *sel, parameter, wait->iStatus); + CleanupStack::PushL(opConnect); + wait->Start(); + CActiveScheduler::Start(); + + TImImap4GetPartialMailInfo info; + info.iPartialMailOptions = EBodyTextOnly; + TPckg bodyInfo(info); + + CMsvOperation* opPopulate = ipImap4Mtm->InvokeAsyncFunctionL(KIMAP4MTMPopulate, + *sel, bodyInfo, wait->iStatus); + CleanupStack::PushL(opPopulate); + wait->Start(); + CActiveScheduler::Start(); + + if (wait->iStatus.Int() != KErrNone) { + if (wait->iStatus.Int() == KErrNotFound){ + // TODO: set messagestatus removed + } + } + + CMsvOperation* opDisconnect = ipImap4Mtm->InvokeAsyncFunctionL(KIMAP4MTMDisconnect, + *sel, parameter, wait->iStatus); + CleanupStack::PushL(opDisconnect); + + wait->Start(); + CActiveScheduler::Start(); + + CleanupStack::PopAndDestroy(3); + } + + if (pEntry->Entry().iMtm == KUidMsgTypePOP3){ + TPckgBuf parameter; + + ipPop3Mtm->SwitchCurrentEntryL(pEntry->OwningService()); + + sel->AppendL(pEntry->EntryId()); + + CMsvOperation* opConnect = ipPop3Mtm->InvokeAsyncFunctionL(KPOP3MTMConnect, + *sel, parameter, wait->iStatus); + + CleanupStack::PushL(opConnect); + wait->Start(); + CActiveScheduler::Start(); + + CImPop3Settings *popSettings = new (ELeave) CImPop3Settings; + CleanupStack::PushL(popSettings); + CEmailAccounts *emailAccounts = CEmailAccounts::NewLC(); + TPopAccount account; + emailAccounts->GetPopAccountL(pEntry->OwningService(), account); + emailAccounts->LoadPopSettingsL(account, *popSettings); + // cannot retrieve only body, have to retrieve entire message + popSettings->SetGetMailOptions(EGetPop3EmailMessages); + emailAccounts->SavePopSettingsL(account,*popSettings); + CleanupStack::PopAndDestroy(emailAccounts); + CleanupStack::PopAndDestroy(popSettings); + + CMsvOperation* opPopulate = ipPop3Mtm->InvokeAsyncFunctionL(KPOP3MTMPopulate, + *sel, parameter, wait->iStatus); + CleanupStack::PushL(opPopulate); + wait->Start(); + CActiveScheduler::Start(); + + CMsvOperation* opDisconnect = ipPop3Mtm->InvokeAsyncFunctionL(KPOP3MTMDisconnect, + *sel, parameter, wait->iStatus); + CleanupStack::PushL(opDisconnect); + + wait->Start(); + CActiveScheduler::Start(); + CleanupStack::PopAndDestroy(3); + + } + + CleanupStack::PopAndDestroy(wait); + CleanupStack::PopAndDestroy(sel); + CleanupStack::PopAndDestroy(pEntry); +} + +bool CMTMEngine::retrieveHeader(const QMessageId& id) +{ + TRAPD(err, retrieveHeaderL(id)); + if (err != KErrNone) + return false; + else + return true; +} + +void CMTMEngine::retrieveHeaderL(const QMessageId& id) const +{ + long int messageId = id.toString().toLong(); + + CMsvEntry* pEntry = ipMsvSession->GetEntryL(messageId); + CleanupStack::PushL(pEntry); + + CMsvEntrySelection* sel = new(ELeave) CMsvEntrySelection; + CleanupStack::PushL(sel); + + CMsvOperationWait* wait = CMsvOperationWait::NewLC(); + + if (pEntry->Entry().iMtm == KUidMsgTypeIMAP4){ + TPckgBuf parameter; + + ipImap4Mtm->SwitchCurrentEntryL(pEntry->OwningService()); + + sel->AppendL(messageId); + + CMsvOperation* opConnect = ipImap4Mtm->InvokeAsyncFunctionL(KIMAP4MTMConnect, + *sel, parameter, wait->iStatus); + CleanupStack::PushL(opConnect); + wait->Start(); + CActiveScheduler::Start(); + + TImImap4GetMailInfo info; + info.iGetMailBodyParts = EGetImap4EmailHeaders; + TPckg bodyInfo(info); + + CMsvOperation* opPopulate = ipImap4Mtm->InvokeAsyncFunctionL(KIMAP4MTMPopulate, + *sel, bodyInfo, wait->iStatus); + CleanupStack::PushL(opPopulate); + wait->Start(); + CActiveScheduler::Start(); + + CMsvOperation* opDisconnect = ipImap4Mtm->InvokeAsyncFunctionL(KIMAP4MTMDisconnect, + *sel, parameter, wait->iStatus); + CleanupStack::PushL(opDisconnect); + + wait->Start(); + CActiveScheduler::Start(); + + CleanupStack::PopAndDestroy(3); + } + + if (pEntry->Entry().iMtm == KUidMsgTypePOP3){ + TPckgBuf parameter; + + ipPop3Mtm->SwitchCurrentEntryL(pEntry->OwningService()); + + sel->AppendL(pEntry->EntryId()); + + CMsvOperation* opConnect = ipPop3Mtm->InvokeAsyncFunctionL(KPOP3MTMConnect, + *sel, parameter, wait->iStatus); + CleanupStack::PushL(opConnect); + wait->Start(); + CActiveScheduler::Start(); + + CImPop3Settings *popSettings = new (ELeave) CImPop3Settings; + CleanupStack::PushL(popSettings); + CEmailAccounts *emailAccounts = CEmailAccounts::NewLC(); + TPopAccount account; + emailAccounts->GetPopAccountL(pEntry->OwningService(), account); + emailAccounts->LoadPopSettingsL(account, *popSettings); + popSettings->SetGetMailOptions(EGetPop3EmailHeaders); + emailAccounts->SavePopSettingsL(account,*popSettings); + CleanupStack::PopAndDestroy(emailAccounts); + CleanupStack::PopAndDestroy(popSettings); + + CMsvOperation* opPopulate = ipPop3Mtm->InvokeAsyncFunctionL(KPOP3MTMPopulate, + *sel, parameter, wait->iStatus); + CleanupStack::PushL(opPopulate); + wait->Start(); + CActiveScheduler::Start(); + + CMsvOperation* opDisconnect = ipPop3Mtm->InvokeAsyncFunctionL(KPOP3MTMDisconnect, + *sel, parameter, wait->iStatus); + CleanupStack::PushL(opDisconnect); + + wait->Start(); + CActiveScheduler::Start(); + + CleanupStack::PopAndDestroy(3); + + } + + CleanupStack::PopAndDestroy(wait); + CleanupStack::PopAndDestroy(sel); + CleanupStack::PopAndDestroy(pEntry); +} + +bool CMTMEngine::exportUpdates(const QMessageAccountId &id) +{ + TRAPD(err, exportUpdatesL(id)); + if (err != KErrNone) { + return false; + } else { + return true; + } +} + +void CMTMEngine::exportUpdatesL(const QMessageAccountId &id) const +{ + QMessageAccount account = this->account(id); + CMsvEntry* pEntry = retrieveCMsvEntryAndPushToCleanupStack(account.d_ptr->_service1EntryId); + if (!pEntry) { + User::Leave(KErrNotFound); + } + if (pEntry->Entry().iMtm == KUidMsgTypeIMAP4) { + TPckgBuf parameter; + CMsvEntrySelection* pMsvEntrySelection = new(ELeave) CMsvEntrySelection; + CleanupStack::PushL(pMsvEntrySelection); + CMsvOperationWait* pMsvOperationWait = CMsvOperationWait::NewLC(); + + ipImap4Mtm->SwitchCurrentEntryL(account.d_ptr->_service1EntryId); + pMsvEntrySelection->AppendL(account.d_ptr->_service1EntryId); + + CMsvOperation* pMsvOperation = ipImap4Mtm->InvokeAsyncFunctionL(KIMAP4MTMConnect, *pMsvEntrySelection, + parameter, pMsvOperationWait->iStatus); + CleanupStack::PushL(pMsvOperation); + pMsvOperationWait->Start(); + CActiveScheduler::Start(); + CleanupStack::PopAndDestroy(pMsvOperation); + + pMsvOperation = ipImap4Mtm->InvokeAsyncFunctionL(KIMAP4MTMFullSync, *pMsvEntrySelection, + parameter, pMsvOperationWait->iStatus); + CleanupStack::PushL(pMsvOperation); + pMsvOperationWait->Start(); + CActiveScheduler::Start(); + CleanupStack::PopAndDestroy(pMsvOperation); + + pMsvOperation = ipImap4Mtm->InvokeAsyncFunctionL(KIMAP4MTMDisconnect, *pMsvEntrySelection, + parameter, pMsvOperationWait->iStatus); + CleanupStack::PushL(pMsvOperation); + pMsvOperationWait->Start(); + CActiveScheduler::Start(); + CleanupStack::PopAndDestroy(pMsvOperation); + + CleanupStack::PopAndDestroy(pMsvOperationWait); + CleanupStack::PopAndDestroy(pMsvEntrySelection); + } + releaseCMsvEntryAndPopFromCleanupStack(pEntry); +} + +bool CMTMEngine::removeMessageL(const QMessageId &id, QMessageManager::RemovalOption /*option*/) +{ + long int messageId = id.toString().toLong(); + CMsvEntry* pEntry = ipMsvSession->GetEntryL(messageId); + CleanupStack::PushL(pEntry); + + if (pEntry->Entry().iMtm == KUidMsgTypeSMS) { + if (!ipSmsMtm) + return false; + ipSmsMtm->SwitchCurrentEntryL(messageId); + TMsvId parent = ipSmsMtm->Entry().Entry().Parent(); + ipSmsMtm->SwitchCurrentEntryL(parent); + ipSmsMtm->Entry().DeleteL(messageId); + } else if (pEntry->Entry().iMtm == KUidMsgTypeMultimedia) { + if (!ipMmsMtm) + return false; + ipMmsMtm->SwitchCurrentEntryL(messageId); + TMsvId parent = ipMmsMtm->Entry().Entry().Parent(); + ipMmsMtm->SwitchCurrentEntryL(parent); + ipMmsMtm->Entry().DeleteL(messageId); + } else if (pEntry->Entry().iMtm == KUidMsgTypeSMTP) { + if (!ipSmtpMtm) + return false; + ipSmtpMtm->SwitchCurrentEntryL(messageId); + TMsvId parent = ipSmtpMtm->Entry().Entry().Parent(); + ipSmtpMtm->SwitchCurrentEntryL(parent); + ipSmtpMtm->Entry().DeleteL(messageId); + } else if (pEntry->Entry().iMtm == KUidMsgTypeIMAP4) { + if (!ipImap4Mtm) + return false; + ipImap4Mtm->SwitchCurrentEntryL(messageId); + TMsvId parent = ipImap4Mtm->Entry().Entry().Parent(); + ipImap4Mtm->SwitchCurrentEntryL(parent); + CMsvOperationWait* pMsvOperationWait = CMsvOperationWait::NewLC(); + CMsvOperation* pMsvOperation = ipImap4Mtm->Entry().DeleteL(messageId, pMsvOperationWait->iStatus); + CleanupStack::PushL(pMsvOperation); + pMsvOperationWait->Start(); + CActiveScheduler::Start(); + CleanupStack::PopAndDestroy(pMsvOperation); + CleanupStack::PopAndDestroy(pMsvOperationWait); + } else if (pEntry->Entry().iMtm == KUidMsgTypePOP3) { + if (!ipPop3Mtm) + return false; + ipPop3Mtm->SwitchCurrentEntryL(messageId); + TMsvId parent = ipPop3Mtm->Entry().Entry().Parent(); + ipPop3Mtm->SwitchCurrentEntryL(parent); + CMsvOperationWait* pMsvOperationWait = CMsvOperationWait::NewLC(); + CMsvOperation* pMsvOperation = ipPop3Mtm->Entry().DeleteL(messageId, pMsvOperationWait->iStatus); + CleanupStack::PushL(pMsvOperation); + pMsvOperationWait->Start(); + CActiveScheduler::Start(); + CleanupStack::PopAndDestroy(pMsvOperation); + CleanupStack::PopAndDestroy(pMsvOperationWait); + } + + CleanupStack::PopAndDestroy(pEntry); + + return true; +} + +bool CMTMEngine::removeMessages(const QMessageFilter& /*filter*/, QMessageManager::RemovalOption /*option*/) +{ + return false; +} + +void CMTMEngine::handleNestedFiltersFromMessageFilter(QMessageFilter &filter) const +{ + QMessageFilterPrivate* pMFFilter = QMessageFilterPrivate::implementation(filter); + if (pMFFilter->_filterList.count() > 0) { + int filterListCount = pMFFilter->_filterList.count(); + for (int i=0; i < filterListCount; i++) { + for (int j=0; j < pMFFilter->_filterList[i].count(); j++) { + QMessageFilterPrivate* pMFFilter2 = QMessageFilterPrivate::implementation(pMFFilter->_filterList[i][j]); + if (pMFFilter2->_field == QMessageFilterPrivate::ParentAccountIdFilter) { + QMessageAccountIdList accountIds = queryAccounts(*pMFFilter2->_accountFilter, QMessageAccountSortOrder(), 0, 0); + QMessageDataComparator::InclusionComparator cmp(static_cast(pMFFilter2->_comparatorValue)); + if (accountIds.count() > 0) { + pMFFilter->_filterList[i].removeAt(j); + if (cmp == QMessageDataComparator::Includes) { + for (int x = 0; x < accountIds.count(); x++) { + if (x == 0) { + if (x+1 < accountIds.count()) { + pMFFilter->_filterList.append(pMFFilter->_filterList[i]); + } + pMFFilter->_filterList[i].append(QMessageFilter::byParentAccountId(accountIds[x],QMessageDataComparator::Equal)); + qSort(pMFFilter->_filterList[i].begin(), pMFFilter->_filterList[i].end(), QMessageFilterPrivate::lessThan); + } else { + if (x+1 < accountIds.count()) { + pMFFilter->_filterList.append(pMFFilter->_filterList[pMFFilter->_filterList.count()-1]); + pMFFilter->_filterList[pMFFilter->_filterList.count()-2].append(QMessageFilter::byParentAccountId(accountIds[x],QMessageDataComparator::Equal)); + qSort(pMFFilter->_filterList[pMFFilter->_filterList.count()-2].begin(), pMFFilter->_filterList[pMFFilter->_filterList.count()-2].end(), QMessageFilterPrivate::lessThan); + } else { + pMFFilter->_filterList[pMFFilter->_filterList.count()-1].append(QMessageFilter::byParentAccountId(accountIds[x],QMessageDataComparator::Equal)); + qSort(pMFFilter->_filterList[pMFFilter->_filterList.count()-1].begin(), pMFFilter->_filterList[pMFFilter->_filterList.count()-1].end(), QMessageFilterPrivate::lessThan); + } + } + } + } else { // Excludes + for (int x = 0; x < accountIds.count(); x++) { + pMFFilter->_filterList[i].append(QMessageFilter::byParentAccountId(accountIds[x],QMessageDataComparator::NotEqual)); + } + qSort(pMFFilter->_filterList[i].begin(), pMFFilter->_filterList[i].end(), QMessageFilterPrivate::lessThan); + } + } else { + delete pMFFilter2->_accountFilter; + pMFFilter2->_accountFilter = 0; + pMFFilter2->_field = QMessageFilterPrivate::Id; + qSort(pMFFilter->_filterList[i].begin(), pMFFilter->_filterList[i].end(), QMessageFilterPrivate::lessThan); + } + } else if (pMFFilter2->_field == QMessageFilterPrivate::ParentFolderIdFilter) { + QMessageFolderIdList folderIds = queryFolders(*pMFFilter2->_folderFilter, QMessageFolderSortOrder(), 0, 0); + QMessageDataComparator::InclusionComparator cmp(static_cast(pMFFilter2->_comparatorValue)); + if (folderIds.count() > 0) { + pMFFilter->_filterList[i].removeAt(j); + if (cmp == QMessageDataComparator::Includes) { + for (int x = 0; x < folderIds.count(); x++) { + if (x == 0) { + if (x+1 < folderIds.count()) { + pMFFilter->_filterList.append(pMFFilter->_filterList[i]); + } + pMFFilter->_filterList[i].append(QMessageFilter::byParentFolderId(folderIds[x],QMessageDataComparator::Equal)); + qSort(pMFFilter->_filterList[i].begin(), pMFFilter->_filterList[i].end(), QMessageFilterPrivate::lessThan); + } else { + if (x+1 < folderIds.count()) { + pMFFilter->_filterList.append(pMFFilter->_filterList[pMFFilter->_filterList.count()-1]); + pMFFilter->_filterList[pMFFilter->_filterList.count()-2].append(QMessageFilter::byParentFolderId(folderIds[x],QMessageDataComparator::Equal)); + qSort(pMFFilter->_filterList[pMFFilter->_filterList.count()-2].begin(), pMFFilter->_filterList[pMFFilter->_filterList.count()-2].end(), QMessageFilterPrivate::lessThan); + } else { + pMFFilter->_filterList[pMFFilter->_filterList.count()-1].append(QMessageFilter::byParentFolderId(folderIds[x],QMessageDataComparator::Equal)); + qSort(pMFFilter->_filterList[pMFFilter->_filterList.count()-1].begin(), pMFFilter->_filterList[pMFFilter->_filterList.count()-1].end(), QMessageFilterPrivate::lessThan); + } + } + } + } else { // Excludes + for (int x = 0; x < folderIds.count(); x++) { + pMFFilter->_filterList[i].append(QMessageFilter::byParentFolderId(folderIds[x],QMessageDataComparator::NotEqual)); + } + qSort(pMFFilter->_filterList[i].begin(), pMFFilter->_filterList[i].end(), QMessageFilterPrivate::lessThan); + } + } else { + delete pMFFilter2->_folderFilter; + pMFFilter2->_folderFilter = 0; + pMFFilter2->_field = QMessageFilterPrivate::Id; + qSort(pMFFilter->_filterList[i].begin(), pMFFilter->_filterList[i].end(), QMessageFilterPrivate::lessThan); + } + } else { + break; + } + } + } + } else { + if (pMFFilter->_field == QMessageFilterPrivate::ParentAccountIdFilter) { + QMessageAccountIdList accountIds = queryAccounts(*pMFFilter->_accountFilter, QMessageAccountSortOrder(), 0, 0); + QMessageDataComparator::InclusionComparator cmp(static_cast(pMFFilter->_comparatorValue)); + if (accountIds.count() > 0) { + for (int i=0; i < accountIds.count(); i++) { + if (i == 0) { + delete pMFFilter->_accountFilter; + pMFFilter->_accountFilter = 0; + pMFFilter->_field = QMessageFilterPrivate::ParentAccountId; + pMFFilter->_value = accountIds[0].toString(); + pMFFilter->_comparatorType = QMessageFilterPrivate::Equality; + if (cmp == QMessageDataComparator::Includes) { + pMFFilter->_comparatorValue = static_cast(QMessageDataComparator::Equal); + } else { // Excludes + pMFFilter->_comparatorValue = static_cast(QMessageDataComparator::NotEqual); + } + } else { + if (cmp == QMessageDataComparator::Includes) { + filter |= QMessageFilter::byParentAccountId(accountIds[i],QMessageDataComparator::Equal); + } else { // Excludes + filter &= QMessageFilter::byParentAccountId(accountIds[i],QMessageDataComparator::NotEqual); + } + } + } + } else { + delete pMFFilter->_accountFilter; + pMFFilter->_accountFilter = 0; + pMFFilter->_field = QMessageFilterPrivate::Id; + } + } else if (pMFFilter->_field == QMessageFilterPrivate::ParentFolderIdFilter) { + QMessageFolderIdList folderIds = queryFolders(*pMFFilter->_folderFilter, QMessageFolderSortOrder(), 0, 0); + QMessageDataComparator::InclusionComparator cmp(static_cast(pMFFilter->_comparatorValue)); + if (folderIds.count() > 0) { + for (int i=0; i < folderIds.count(); i++) { + if (i == 0) { + delete pMFFilter->_folderFilter; + pMFFilter->_folderFilter = 0; + pMFFilter->_field = QMessageFilterPrivate::ParentFolderId; + pMFFilter->_value = folderIds[0].toString(); + pMFFilter->_comparatorType = QMessageFilterPrivate::Equality; + if (cmp == QMessageDataComparator::Includes) { + pMFFilter->_comparatorValue = static_cast(QMessageDataComparator::Equal); + } else { // Excludes + pMFFilter->_comparatorValue = static_cast(QMessageDataComparator::NotEqual); + } + } else { + if (cmp == QMessageDataComparator::Includes) { + filter |= QMessageFilter::byParentFolderId(folderIds[i],QMessageDataComparator::Equal); + } else { // Excludes + filter &= QMessageFilter::byParentFolderId(folderIds[i],QMessageDataComparator::NotEqual); + } + } + } + } else { + delete pMFFilter->_folderFilter; + pMFFilter->_folderFilter = 0; + pMFFilter->_field = QMessageFilterPrivate::Id; + } + } + } +} + +bool CMTMEngine::queryMessages(QMessageServicePrivate& privateService, const QMessageFilter &filter, const QMessageSortOrder &sortOrder, uint limit, uint offset) const +{ + TRAPD(err, queryMessagesL(privateService, filter, sortOrder, limit, offset)); + if (err != KErrNone) { + return false; + } + return true; +} + +void CMTMEngine::queryMessagesL(QMessageServicePrivate& privateService, const QMessageFilter &filter, const QMessageSortOrder &sortOrder, uint limit, uint offset) const +{ + MessageQueryInfo queryInfo; + queryInfo.operationId = ++iOperationIds; + if (queryInfo.operationId == 100000) { + queryInfo.operationId = 1; + } + queryInfo.isQuery = true; + queryInfo.filter = filter; + queryInfo.sortOrder = sortOrder; + queryInfo.offset = offset; + queryInfo.limit = limit; + queryInfo.findOperation = new CMessagesFindOperation((CMTMEngine&)*this, ipMsvSession, queryInfo.operationId); + queryInfo.privateService = &privateService; + queryInfo.currentFilterListIndex = 0; + iMessageQueries.append(queryInfo); + + handleNestedFiltersFromMessageFilter(iMessageQueries[iMessageQueries.count()-1].filter); + + QMessageFilterPrivate* pf = QMessageFilterPrivate::implementation(iMessageQueries[iMessageQueries.count()-1].filter); + if (pf->_filterList.count() == 0) { + queryInfo.findOperation->filterAndOrderMessages(iMessageQueries[iMessageQueries.count()-1].filter, + iMessageQueries[iMessageQueries.count()-1].sortOrder); + } else { + queryInfo.findOperation->filterAndOrderMessages(pf->_filterList[0], iMessageQueries[iMessageQueries.count()-1].sortOrder); + } +} + +bool CMTMEngine::queryMessages(QMessageServicePrivate& privateService, const QMessageFilter &filter, const QString &body, QMessageDataComparator::MatchFlags matchFlags, const QMessageSortOrder &sortOrder, uint limit, uint offset) const +{ + TRAPD(err, queryMessagesL(privateService, filter, body, matchFlags, sortOrder, limit, offset)); + if (err != KErrNone) { + return false; + } + return true; +} + +void CMTMEngine::queryMessagesL(QMessageServicePrivate& privateService, const QMessageFilter &filter, const QString &body, QMessageDataComparator::MatchFlags matchFlags, const QMessageSortOrder &sortOrder, uint limit, uint offset) const +{ + MessageQueryInfo queryInfo; + queryInfo.operationId = ++iOperationIds; + if (queryInfo.operationId == 100000) { + queryInfo.operationId = 1; + } + queryInfo.isQuery = true; + queryInfo.body = body; + queryInfo.matchFlags = matchFlags; + queryInfo.filter = filter; + queryInfo.sortOrder = sortOrder; + queryInfo.offset = offset; + queryInfo.limit = limit; + queryInfo.findOperation = new CMessagesFindOperation((CMTMEngine&)*this, ipMsvSession, queryInfo.operationId); + queryInfo.privateService = &privateService; + queryInfo.currentFilterListIndex = 0; + iMessageQueries.append(queryInfo); + + handleNestedFiltersFromMessageFilter(iMessageQueries[iMessageQueries.count()-1].filter); + + QMessageFilterPrivate* pf = QMessageFilterPrivate::implementation(iMessageQueries[iMessageQueries.count()-1].filter); + if (pf->_filterList.count() == 0) { + queryInfo.findOperation->filterAndOrderMessages(iMessageQueries[iMessageQueries.count()-1].filter, + iMessageQueries[iMessageQueries.count()-1].sortOrder, + body, + matchFlags); + } else { + queryInfo.findOperation->filterAndOrderMessages(pf->_filterList[0], + iMessageQueries[iMessageQueries.count()-1].sortOrder, + body, + matchFlags); + } +} + +bool CMTMEngine::countMessages(QMessageServicePrivate& privateService, const QMessageFilter &filter) +{ + TRAPD(err, countMessagesL(privateService, filter)); + if (err != KErrNone) { + return false; + } + return true; +} + +void CMTMEngine::countMessagesL(QMessageServicePrivate& privateService, const QMessageFilter &filter) +{ + MessageQueryInfo queryInfo; + queryInfo.operationId = ++iOperationIds; + if (queryInfo.operationId == 100000) { + queryInfo.operationId = 1; + } + queryInfo.isQuery = false; + queryInfo.matchFlags = 0; + queryInfo.filter = filter; + queryInfo.sortOrder = QMessageSortOrder(); + queryInfo.offset = 0; + queryInfo.limit = 0; + queryInfo.findOperation = new CMessagesFindOperation((CMTMEngine&)*this, ipMsvSession, queryInfo.operationId); + queryInfo.privateService = &privateService; + queryInfo.currentFilterListIndex = 0; + queryInfo.count = 0; + iMessageQueries.append(queryInfo); + + handleNestedFiltersFromMessageFilter(iMessageQueries[iMessageQueries.count()-1].filter); + + QMessageFilterPrivate* pf = QMessageFilterPrivate::implementation(iMessageQueries[iMessageQueries.count()-1].filter); + if (pf->_filterList.count() == 0) { + queryInfo.findOperation->filterAndOrderMessages(iMessageQueries[iMessageQueries.count()-1].filter, + iMessageQueries[iMessageQueries.count()-1].sortOrder); + } else { + queryInfo.findOperation->filterAndOrderMessages(pf->_filterList[0], iMessageQueries[iMessageQueries.count()-1].sortOrder); + } +} + +void CMTMEngine::filterAndOrderMessagesReady(bool success, int operationId, QMessageIdList ids, int numberOfHandledFilters, + bool resultSetOrdered) +{ + int index=0; + for (; index < iMessageQueries.count(); index++) { + if (iMessageQueries[index].operationId == operationId) { + break; + } + } + + if (success) { + // If there are unhandled filters, loop through all filters and do filtering for ids using unhandled filters. + QMessageFilterPrivate* pf = QMessageFilterPrivate::implementation(iMessageQueries[index].filter); + if (pf->_filterList.count() > 0) { + if (pf->_filterList[iMessageQueries[index].currentFilterListIndex].count() > numberOfHandledFilters) { + for (int i=0; i < ids.count(); i++) { + QMessage msg = message(ids[i]); + for (int j=numberOfHandledFilters; j < pf->_filterList[iMessageQueries[index].currentFilterListIndex].count(); j++) { + QMessageFilterPrivate* pf2 = QMessageFilterPrivate::implementation(pf->_filterList[iMessageQueries[index].currentFilterListIndex][j]); + if (!pf2->filter(msg)) { + ids.removeAt(i); + i--; + break; + } + } + } + } + } + + if (pf->_filterList.count() > 0) { + // Filter contains filterlist (or filterlists), not just one single filter + if (iMessageQueries[index].currentFilterListIndex == 0) { + iMessageQueries[index].ids << ids; + iMessageQueries[index].count = ids.count(); + } else { + // Append new ids to resultset + for (int i=0; i < ids.count(); i++) { + if (!iMessageQueries[index].ids.contains(ids[i])) { + iMessageQueries[index].ids.append(ids[i]); + iMessageQueries[index].count++;; + } + } + } + + iMessageQueries[index].currentFilterListIndex++; + if (iMessageQueries[index].currentFilterListIndex < pf->_filterList.count()) { + // There are still unhandled filter lists left + iMessageQueries[index].findOperation->filterAndOrderMessages(pf->_filterList[iMessageQueries[index].currentFilterListIndex], + iMessageQueries[index].sortOrder, + iMessageQueries[index].body, + iMessageQueries[index].matchFlags); + return; + } else { + // All filters successfully handled + if (iMessageQueries[index].isQuery) { + if (!iMessageQueries[index].sortOrder.isEmpty()) { + // Make sure that messages are correctly ordered + orderMessages(iMessageQueries[index].ids, iMessageQueries[index].sortOrder); + } + applyOffsetAndLimitToMsgIds(iMessageQueries[index].ids, + iMessageQueries[index].offset, + iMessageQueries[index].limit); + emit iMessageQueries[index].privateService->messagesFound(iMessageQueries[index].ids); + } else { + emit iMessageQueries[index].privateService->messagesCounted(iMessageQueries[index].count); + } + iMessageQueries[index].privateService->_active = false; + emit iMessageQueries[index].privateService->stateChanged(QMessageService::FinishedState); + } + } else { + // There was only one single filter to handle + if (numberOfHandledFilters == 0) { + // The one and only filter was not handled + // => Do filtering for all returned messages + for (int i=ids.count()-1; i >= 0; i--) { + QMessage msg = message(ids[i]); + if (!pf->filter(msg)) { + ids.removeAt(i); + } + } + } + // => All filters successfully handled + if (iMessageQueries[index].isQuery) { + // Make sure that messages are correctly ordered + if (!iMessageQueries[index].sortOrder.isEmpty() && !resultSetOrdered) { + orderMessages(ids, iMessageQueries[index].sortOrder); + } + // Handle offest & limit + applyOffsetAndLimitToMsgIds(ids, iMessageQueries[index].offset, iMessageQueries[index].limit); + emit iMessageQueries[index].privateService->messagesFound(ids); + } else { + emit iMessageQueries[index].privateService->messagesCounted(ids.count()); + } + iMessageQueries[index].privateService->_active = false; + emit iMessageQueries[index].privateService->stateChanged(QMessageService::FinishedState); + } + } else { + iMessageQueries[index].privateService->_active = false; + if (iMessageQueries[index].privateService->_error == QMessageManager::NoError) { + iMessageQueries[index].privateService->_error = QMessageManager::RequestIncomplete; + } + emit iMessageQueries[index].privateService->stateChanged(QMessageService::FinishedState); + } + + delete iMessageQueries[index].findOperation; + iMessageQueries.removeAt(index); +} + +void CMTMEngine::applyOffsetAndLimitToMsgIds(QMessageIdList& idList, int offset, int limit) const +{ + if (offset > 0) { + if (offset > idList.count()) { + idList.clear(); + } else { + for (int i = 0; i < offset; i++) { + idList.removeFirst(); + } + } + } + if (limit > 0) { + for (int i = idList.count()-1; i >= limit; i--) { + idList.removeAt(i); + } + } +} + +QMessageFolderIdList CMTMEngine::filterMessageFolders(const QMessageFolderFilter& filter, bool& filterHandled) const +{ + QMessageFolderIdList ids; + TRAPD(err, ids = filterMessageFoldersL(filter, filterHandled)); + Q_UNUSED(err) + return ids; +} + +QMessageFolderIdList CMTMEngine::filterMessageFoldersL(const QMessageFolderFilter& filter, bool& filterHandled) const +{ + filterHandled = false; + QMessageFolderIdList ids; + + if (filter.isEmpty()) { + QMessageFolderFilterPrivate* pf = QMessageFolderFilterPrivate::implementation(filter); + if (!pf->_notFilter) { + ids = allFolders(); + } + filterHandled = true; + } else { + QMessageFolderFilterPrivate* pf = QMessageFolderFilterPrivate::implementation(filter); + if (!pf->_valid) { + return QMessageFolderIdList(); + } + + switch (pf->_field) { + case QMessageFolderFilterPrivate::Id: + { + if (pf->_comparatorType == QMessageFolderFilterPrivate::Equality) { + QMessageDataComparator::EqualityComparator cmp(static_cast(pf->_comparatorValue)); + if (pf->_value.toString().length() > 0) { + bool folderOk = false; + long int folderId = folderIdFromQMessageFolderId(QMessageFolderId(pf->_value.toString())); + CMsvEntry* pEntry = retrieveCMsvEntryAndPushToCleanupStack(folderId); + if (pEntry) { + if (pEntry->Entry().iType == KUidMsvFolderEntry) { + folderOk = true; + } + releaseCMsvEntryAndPopFromCleanupStack(pEntry); + } + if (cmp == QMessageDataComparator::Equal) { + if (folderOk) { + ids.append(QMessageFolderId(pf->_value.toString())); + } + } else { // NotEqual + ids = allFolders(); + if (folderOk) { + ids.removeOne(QMessageFolderId(pf->_value.toString())); + } + } + } else { + if (cmp == QMessageDataComparator::NotEqual) { + ids = allFolders(); + } + } + filterHandled = true; + } else if (pf->_comparatorType == QMessageFolderFilterPrivate::Inclusion) { + QMessageDataComparator::InclusionComparator cmp(static_cast(pf->_comparatorValue)); + if (pf->_ids.count() > 0) { // QMessageIdList + QMessageFolderIdList ids2; + for (int i=0; i < pf->_ids.count(); i++) { + long int folderId = folderIdFromQMessageFolderId(QMessageFolderId(pf->_ids[i].toString())); + CMsvEntry* pEntry = retrieveCMsvEntryAndPushToCleanupStack(folderId); + if (pEntry) { + const TMsvEntry& entry = pEntry->Entry(); + if (entry.iType == KUidMsvFolderEntry) { + ids2.append(pf->_ids[i]); + } + releaseCMsvEntryAndPopFromCleanupStack(pEntry); + } + } + if (cmp == QMessageDataComparator::Includes) { + ids << ids2; + } else { // Excludes + ids = allFolders(); + for (int i=0; i < ids2.count(); i++) { + ids.removeOne(ids2[i]); + } + } + filterHandled = true; + } else { + // Empty QMessageIdList as a list + if (cmp == QMessageDataComparator::Excludes) { + ids = allFolders(); + } + filterHandled = true; + + // QMessageFilter + /*if (cmp == QMessageDataComparator::Includes) { + // TODO: + } else { // Excludes + // TODO: + }*/ + } + } + break; + } + case QMessageFolderFilterPrivate::Name: + { + if (pf->_comparatorType == QMessageFolderFilterPrivate::Equality) { + QMessageDataComparator::EqualityComparator cmp(static_cast(pf->_comparatorValue)); + if (cmp == QMessageDataComparator::Equal) { + // TODO: + } else { // NotEqual + // TODO: + } + } else if (pf->_comparatorType == QMessageFolderFilterPrivate::Inclusion) { + QMessageDataComparator::InclusionComparator cmp(static_cast(pf->_comparatorValue)); + if (cmp == QMessageDataComparator::Includes) { + // TODO: + } else { // Excludes + if (pf->_value.toString().isEmpty() || pf->_value.toString().length() == 0) { + filterHandled = true; + } + } + } + break; + } + case QMessageFolderFilterPrivate::Path: + { + if (pf->_comparatorType == QMessageFolderFilterPrivate::Equality) { + QMessageDataComparator::EqualityComparator cmp(static_cast(pf->_comparatorValue)); + if (cmp == QMessageDataComparator::Equal) { + // TODO: + } else { // NotEqual + // TODO: + } + } else if (pf->_comparatorType == QMessageFolderFilterPrivate::Inclusion) { + QMessageDataComparator::InclusionComparator cmp(static_cast(pf->_comparatorValue)); + if (cmp == QMessageDataComparator::Includes) { + // TODO: + } else { // Excludes + if (pf->_value.toString().isEmpty() || pf->_value.toString().length() == 0) { + filterHandled = true; + } + } + } + break; + } + case QMessageFolderFilterPrivate::ParentAccountId: + { + if (pf->_comparatorType == QMessageFolderFilterPrivate::Equality) { + QMessageDataComparator::EqualityComparator cmp(static_cast(pf->_comparatorValue)); + if (cmp == QMessageDataComparator::Equal) { + if (pf->_value.toString().length() > 0) { + ids = folderIdsByAccountId(QMessageAccountId(pf->_value.toString())); + } + } else { // NotEqual + ids = allFolders(); + if (pf->_value.toString().length() > 0) { + QMessageFolderIdList ids2 = folderIdsByAccountId(QMessageAccountId(pf->_value.toString())); + for (int i = 0; i < ids2.count(); i++) { + ids.removeOne(ids2[i]); + } + } + } + filterHandled = true; + } else if (pf->_comparatorType == QMessageFolderFilterPrivate::Inclusion) { + QMessageDataComparator::InclusionComparator cmp(static_cast(pf->_comparatorValue)); + if (cmp == QMessageDataComparator::Includes) { + // TODO: + } else { // Excludes + // TODO: + } + } + break; + } + case QMessageFolderFilterPrivate::ParentFolderId: + { + if (pf->_comparatorType == QMessageFolderFilterPrivate::Equality) { + QMessageDataComparator::EqualityComparator cmp(static_cast(pf->_comparatorValue)); + if (cmp == QMessageDataComparator::Equal) { + long int folderId = pf->_value.toString().toLong(); + CMsvEntry* pEntry = retrieveCMsvEntryAndPushToCleanupStack(folderId); + if (pEntry) { + const TMsvEntry& entry = pEntry->Entry(); + if (entry.iType == KUidMsvFolderEntry) { + CMsvEntrySelection* pSelection = pEntry->ChildrenWithTypeL(KUidMsvFolderEntry); + CleanupStack::PushL(pSelection); + if (pSelection->Count() > 0) { + for(TInt i = 0; i < pSelection->Count(); i++) { + ids.append(QMessageFolderId(QString::number(pSelection->At(i)))); + } + } + CleanupStack::PopAndDestroy(pSelection); + } + releaseCMsvEntryAndPopFromCleanupStack(pEntry); + } + } else { // NotEqual + // TODO: + } + } else if (pf->_comparatorType == QMessageFolderFilterPrivate::Inclusion) { + QMessageDataComparator::InclusionComparator cmp(static_cast(pf->_comparatorValue)); + if (cmp == QMessageDataComparator::Includes) { + // TODO: + } else { // Excludes + // TODO: + } + } + break; + } + case QMessageFolderFilterPrivate::AncestorFolderIds: + { + if (pf->_comparatorType == QMessageFolderFilterPrivate::Inclusion) { + QMessageDataComparator::InclusionComparator cmp(static_cast(pf->_comparatorValue)); + if (!pf->_value.isNull()) { // QMessageFolderId + if (cmp == QMessageDataComparator::Includes) { + // TODO: + } else { // Excludes + // TODO: + } + } else { // QMessageFolderFilter + if (cmp == QMessageDataComparator::Includes) { + // TODO: + } else { // Excludes + // TODO: + } + } + } + break; + } + case QMessageFolderFilterPrivate::ParentAccountIdFilter: + case QMessageFolderFilterPrivate::None: + break; + } + } + + if (!filterHandled) { + ids = allFolders(); + } + + return ids; +} + +QMessageFolderIdList CMTMEngine::allFolders() const +{ + QMessageFolderIdList ids; + TRAPD(err, updateEmailAccountsL()); + Q_UNUSED(err) + foreach (QMessageAccount value, iAccounts) { + QMessageFolderIdList ids2 = folderIdsByAccountId(value.id()); + ids << ids2; + } + return ids; +} + +QMessageFolderIdList CMTMEngine::folderIdsByAccountId(const QMessageAccountId& accountId) const +{ + QMessageAccount messageAccount = account(accountId); + QMessageFolderIdList ids = folderIdsByServiceEntryId(messageAccount.d_ptr->_service1EntryId, + messageAccount.d_ptr->_service1EntryId); + if (messageAccount.d_ptr->_service2EntryId) { + QMessageFolderIdList ids2 = folderIdsByServiceEntryId(messageAccount.d_ptr->_service2EntryId, + messageAccount.d_ptr->_service1EntryId); + ids << ids2; + } + return ids; +} + +QMessageFolderIdList CMTMEngine::folderIdsByServiceEntryId(const TMsvId& serviceEntryId, + const TMsvId& folderServiceEntryId) const +{ + QMessageFolderIdList ids; + + CMsvEntry* pEntry = retrieveCMsvEntryAndPushToCleanupStack(serviceEntryId); + if (pEntry) { + const TMsvEntry& entry = pEntry->Entry(); + if (entry.iMtm == KUidMsgTypeSMS || entry.iMtm == KUidMsgTypeMultimedia || entry.iMtm == KUidMsgTypeSMTP) { + // Add all Standard Folders to FolderIdList + if (entry.iMtm != KUidMsgTypeSMTP) { + // SMTP is for sending only => Don't add Inbox for SMTP + ids.append(createQMessageFolderId(folderServiceEntryId, KMsvGlobalInBoxIndexEntryId)); + } + ids.append(createQMessageFolderId(folderServiceEntryId, KMsvGlobalOutBoxIndexEntryId)); + ids.append(createQMessageFolderId(folderServiceEntryId, KMsvDraftEntryId)); + ids.append(createQMessageFolderId(folderServiceEntryId, KMsvSentEntryId)); + ids.append(createQMessageFolderId(folderServiceEntryId, KMsvDeletedEntryFolderEntryId)); + pEntry->SetEntryL(KDocumentsEntryIdValue); + } + + if (entry.iMtm == KUidMsgTypePOP3) { + ids.append(createQMessageFolderId(folderServiceEntryId, serviceEntryId)); + } else { + CMsvEntryFilter* pFilter = CMsvEntryFilter::NewLC(); + pFilter->SetService(serviceEntryId); + pFilter->SetType(KUidMsvFolderEntry); + CMsvEntrySelection* pSelection = new(ELeave) CMsvEntrySelection; + CleanupStack::PushL(pSelection); + ipMsvSession->GetChildIdsL(pEntry->Entry().Id(), *pFilter, *pSelection); + if (pSelection->Count() > 0) { + for(TInt i = 0; i < pSelection->Count(); i++) { + ids.append(createQMessageFolderId(folderServiceEntryId, pSelection->At(i))); + } + } + CleanupStack::PopAndDestroy(pSelection); + CleanupStack::PopAndDestroy(pFilter); + } + releaseCMsvEntryAndPopFromCleanupStack(pEntry); + } + + return ids; +} + +QMessageFolderId CMTMEngine::createQMessageFolderId(const TMsvId& serviceEntryId, const TMsvId& folderId) const +{ + QString nullString = "00000000"; + QString serviceEntryIdString = QString::number(serviceEntryId); + serviceEntryIdString = nullString.left(8-serviceEntryIdString.length()) + serviceEntryIdString; + QString folderIdString = QString::number(folderId); + folderIdString = nullString.left(8-folderIdString.length()) + folderIdString; + return serviceEntryIdString+folderIdString; +} + +TMsvId CMTMEngine::serviceEntryIdFromQMessageFolderId(const QMessageFolderId& folderId) const +{ + return folderId.toString().left(8).toLong(); +} + +TMsvId CMTMEngine::folderIdFromQMessageFolderId(const QMessageFolderId& folderId) const +{ + return folderId.toString().right(8).toLong(); +} + +void CMTMEngine::handleNestedFiltersFromFolderFilter(QMessageFolderFilter &filter) const +{ + QMessageFolderFilterPrivate* pMFFilter = QMessageFolderFilterPrivate::implementation(filter); + if (pMFFilter->_filterList.count() > 0) { + int filterListCount = pMFFilter->_filterList.count(); + for (int i=0; i < filterListCount; i++) { + for (int j=0; j < pMFFilter->_filterList[i].count(); j++) { + QMessageFolderFilterPrivate* pMFFilter2 = QMessageFolderFilterPrivate::implementation(pMFFilter->_filterList[i][j]); + if (pMFFilter2->_field == QMessageFolderFilterPrivate::ParentAccountIdFilter) { + QMessageAccountIdList accountIds = queryAccounts(*pMFFilter2->_accountFilter, QMessageAccountSortOrder(), 0, 0); + QMessageDataComparator::InclusionComparator cmp(static_cast(pMFFilter2->_comparatorValue)); + if (accountIds.count() > 0) { + pMFFilter->_filterList[i].removeAt(j); + if (cmp == QMessageDataComparator::Includes) { + for (int x = 0; x < accountIds.count(); x++) { + if (x == 0) { + if (x+1 < accountIds.count()) { + pMFFilter->_filterList.append(pMFFilter->_filterList[i]); + } + pMFFilter->_filterList[i].append(QMessageFolderFilter::byParentAccountId(accountIds[x],QMessageDataComparator::Equal)); + qSort(pMFFilter->_filterList[i].begin(), pMFFilter->_filterList[i].end(), QMessageFolderFilterPrivate::lessThan); + } else { + if (x+1 < accountIds.count()) { + pMFFilter->_filterList.append(pMFFilter->_filterList[pMFFilter->_filterList.count()-1]); + pMFFilter->_filterList[pMFFilter->_filterList.count()-2].append(QMessageFolderFilter::byParentAccountId(accountIds[x],QMessageDataComparator::Equal)); + qSort(pMFFilter->_filterList[pMFFilter->_filterList.count()-2].begin(), pMFFilter->_filterList[pMFFilter->_filterList.count()-2].end(), QMessageFolderFilterPrivate::lessThan); + } else { + pMFFilter->_filterList[pMFFilter->_filterList.count()-1].append(QMessageFolderFilter::byParentAccountId(accountIds[x],QMessageDataComparator::Equal)); + qSort(pMFFilter->_filterList[pMFFilter->_filterList.count()-1].begin(), pMFFilter->_filterList[pMFFilter->_filterList.count()-1].end(), QMessageFolderFilterPrivate::lessThan); + } + } + } + } else { // Excludes + for (int x = 0; x < accountIds.count(); x++) { + pMFFilter->_filterList[i].append(QMessageFolderFilter::byParentAccountId(accountIds[x],QMessageDataComparator::NotEqual)); + } + qSort(pMFFilter->_filterList[i].begin(), pMFFilter->_filterList[i].end(), QMessageFolderFilterPrivate::lessThan); + } + } else { + delete pMFFilter2->_accountFilter; + pMFFilter2->_accountFilter = 0; + pMFFilter2->_field = QMessageFolderFilterPrivate::Id; + qSort(pMFFilter->_filterList[i].begin(), pMFFilter->_filterList[i].end(), QMessageFolderFilterPrivate::lessThan); + } + } else { + break; + } + } + } + } else { + if (pMFFilter->_field == QMessageFolderFilterPrivate::ParentAccountIdFilter) { + QMessageAccountIdList accountIds = queryAccounts(*pMFFilter->_accountFilter, QMessageAccountSortOrder(), 0, 0); + QMessageDataComparator::InclusionComparator cmp(static_cast(pMFFilter->_comparatorValue)); + if (accountIds.count() > 0) { + for (int i=0; i < accountIds.count(); i++) { + if (i == 0) { + delete pMFFilter->_accountFilter; + pMFFilter->_accountFilter = 0; + pMFFilter->_field = QMessageFolderFilterPrivate::ParentAccountId; + pMFFilter->_value = accountIds[0].toString(); + pMFFilter->_comparatorType = QMessageFolderFilterPrivate::Equality; + if (cmp == QMessageDataComparator::Includes) { + pMFFilter->_comparatorValue = static_cast(QMessageDataComparator::Equal); + } else { // Excludes + pMFFilter->_comparatorValue = static_cast(QMessageDataComparator::NotEqual); + } + } else { + if (cmp == QMessageDataComparator::Includes) { + filter |= QMessageFolderFilter::byParentAccountId(accountIds[i],QMessageDataComparator::Equal); + } else { // Excludes + filter &= QMessageFolderFilter::byParentAccountId(accountIds[i],QMessageDataComparator::NotEqual); + } + } + } + } else { + delete pMFFilter->_accountFilter; + pMFFilter->_accountFilter = 0; + pMFFilter->_field = QMessageFolderFilterPrivate::Id; + } + } + } +} + +QMessageFolderIdList CMTMEngine::queryFolders(const QMessageFolderFilter &filter, const QMessageFolderSortOrder &sortOrder, uint limit, uint offset) const +{ + QMessageFolderIdList ids; + + QMessageFolderFilter copyOfFilter = filter; + handleNestedFiltersFromFolderFilter(copyOfFilter); + + QMessageFolderFilterPrivate* pMFFilter = QMessageFolderFilterPrivate::implementation(copyOfFilter); + + if (pMFFilter->_filterList.count() > 0) { + for (int i=0; i < pMFFilter->_filterList.count(); i++) { + bool filterHandled; + QMessageFolderIdList ids2 = filterMessageFolders(pMFFilter->_filterList[i][0], filterHandled); + for (int x=ids2.count()-1; x >= 0; x--) { + QMessageFolder mf = folder(ids2[x]); + int j = filterHandled ? 1 : 0; + for (; j < pMFFilter->_filterList[i].count(); j++) { + if (!QMessageFolderFilterPrivate::implementation(pMFFilter->_filterList[i][j])->filter(mf)) { + ids2.removeAt(x); + break; + } + } + } + for (int j=0; j < ids2.count(); j++) { + if (!ids.contains(ids2[j])) { + ids.append(ids2[j]); + } + } + } + } else { + bool filterHandled; + ids = filterMessageFolders(copyOfFilter, filterHandled); + if (!filterHandled) { + for (int i=ids.count()-1; i >= 0; i--) { + if (!QMessageFolderFilterPrivate::implementation(copyOfFilter)->filter(ids[i])) { + ids.removeAt(i); + } + } + } + } + + if (!sortOrder.isEmpty()) { + orderFolders(ids, sortOrder); + } + + applyOffsetAndLimitToMsgFolderIds(ids, offset, limit); + + return ids; +} + +void CMTMEngine::applyOffsetAndLimitToMsgFolderIds(QMessageFolderIdList& idList, int offset, int limit) const +{ + if (offset > 0) { + if (offset > idList.count()) { + idList.clear(); + } else { + for (int i = 0; i < offset; i++) { + idList.removeFirst(); + } + } + } + if (limit > 0) { + for (int i = idList.count()-1; i >= limit; i--) { + idList.removeAt(i); + } + } +} + +int CMTMEngine::countFolders(const QMessageFolderFilter &filter) const +{ + return queryFolders(filter, QMessageFolderSortOrder(), 0, 0).count(); +} + +QMessageFolder CMTMEngine::folder(const QMessageFolderId &id) const +{ + if (!iSessionReady) + return QMessageFolder(); + + QMessageFolder folder; + TRAPD(err, folder = folderL(id)); + Q_UNUSED(err) + + return folder; +} + +QMessageFolder CMTMEngine::folderL(const QMessageFolderId &id) const +{ + QMessageFolder folder; + + TMsvId folderId = folderIdFromQMessageFolderId(id); + TMsvId serviceId = serviceEntryIdFromQMessageFolderId(id); + CMsvEntry* pEntry = retrieveCMsvEntryAndPushToCleanupStack(folderId); + if (pEntry) { + if (pEntry->Entry().iMtm == KUidMsgTypePOP3) { + pEntry->SetEntryL(KMsvGlobalInBoxIndexEntryId); + } + QMessageAccountId accountId(accountIdByServiceId(serviceId)); + QMessageFolderId parentId; + QString name = QString::fromUtf16(pEntry->Entry().iDetails.Ptr(), pEntry->Entry().iDetails.Length()); + folder = QMessageFolderPrivate::from(id, accountId, parentId, name, name); + releaseCMsvEntryAndPopFromCleanupStack(pEntry); + } + + return folder; +} + +QMessage CMTMEngine::message(const QMessageId& id) const +{ + if (!iSessionReady) + return QMessage(); + + QMessage message; + TRAPD(err, message = messageL(id)); + Q_UNUSED(err) + + return message; +} + +QMessage CMTMEngine::messageL(const QMessageId& id) const +{ + QMessage message; + + long int messageId = id.toString().toLong(); + CMsvEntry* pEntry = ipMsvSession->GetEntryL(messageId); + CleanupStack::PushL(pEntry); + + if (pEntry->Entry().iMtm == KUidMsgTypeSMS) { + if (!ipSmsMtm) + return message; + message = smsMessageL(*pEntry, messageId); + } else if (pEntry->Entry().iMtm == KUidMsgTypeMultimedia) { + if (!ipMmsMtm) + return message; + message = mmsMessageL(*pEntry, messageId); + } else if (pEntry->Entry().iMtm == KUidMsgTypeSMTP) { + if (!ipSmtpMtm) + return message; + message = emailMessageL(*pEntry, messageId); + } else if (pEntry->Entry().iMtm == KUidMsgTypeIMAP4) { + if (!ipImap4Mtm) + return message; + message = emailMessageL(*pEntry, messageId); + } else if (pEntry->Entry().iMtm == KUidMsgTypePOP3) { + if (!ipPop3Mtm) + return message; + message = emailMessageL(*pEntry, messageId); + } + + CleanupStack::PopAndDestroy(pEntry); + + QMessagePrivate* privateMessage = QMessagePrivate::implementation(message); + privateMessage->_id = id; + privateMessage->_modified = false; + + return message; +} + +bool CMTMEngine::storeMMS(QMessage &message) +{ + if (!iSessionReady) { + return false; + } + + TRAPD(err, storeMMSL(message)); + if (err != KErrNone) { + return false; + } + + return true; +} + +bool CMTMEngine::sendMMS(QMessage &message) +{ + if (!iSessionReady) { + return false; + } + + TRAPD(err, sendMMSL(message)); + if (err != KErrNone) { + return false; + } + + return true; +} + +bool CMTMEngine::storeEmail(QMessage &message) +{ + if (!iSessionReady) { + return false; + } + + TRAPD(err, storeEmailL(message)); + if (err != KErrNone) { + return false; + } + + return true; +} + +bool CMTMEngine::sendEmail(QMessage &message) +{ + if (!iSessionReady) { + return false; + } + + TRAPD(err, sendEmailL(message)); + if (err != KErrNone) { + return false; + } + + return true; +} + +bool CMTMEngine::storeSMS(QMessage &message) +{ + if (!iSessionReady) + return false; + + TRAPD(err, storeSMSL(message)); + if (err != KErrNone) { + return false; + } + + return true; +} + +void CMTMEngine::storeSMSL(QMessage &message) +{ + if (!iSessionReady) { + User::Leave(KErrNotReady); + } + + TMsvId destinationFolderId; + if (message.parentFolderId().isValid()) { + destinationFolderId = folderIdFromQMessageFolderId(message.parentFolderId()); + } else { + // parentFolderId was not defined for new Message + // => Message will be created into defined standard Folder (Default value is Drafts Folder) + destinationFolderId = standardFolderId(message.standardFolder()); + } + + // Current entry is the Draft folder. + ipSmsMtm->SwitchCurrentEntryL(destinationFolderId); + // Create a new SMS message entry as a child of the current context. + ipSmsMtm->CreateMessageL(KUidMsgTypeSMS.iUid); + TMsvEntry entry = ipSmsMtm->Entry().Entry(); + + switch (message.priority()) { + case QMessage::HighPriority: + entry.SetPriority(EMsvHighPriority); + break; + case QMessage::NormalPriority: + entry.SetPriority(EMsvMediumPriority); + break; + case QMessage::LowPriority: + entry.SetPriority(EMsvLowPriority); + break; + } + if (message.status() & QMessage::Read) { + entry.SetUnread(false); + entry.SetNew(false); + } else { + entry.SetUnread(true); + entry.SetNew(true); + } + ipSmsMtm->Entry().ChangeL(entry); + + QList list(message.to()); + if (!list.empty()){ + TPtrC16 receiver(KNullDesC); + QString qreceiver; + for (int i = 0; i < list.size(); ++i) { + qreceiver = list.at(i).recipient(); + receiver.Set(reinterpret_cast(qreceiver.utf16())); + ipSmsMtm->AddAddresseeL(receiver); + ipSmsMtm->SaveMessageL(); + } + } + + CMsvStore* store = ipSmsMtm->Entry().EditStoreL(); + CleanupStack::PushL(store); + + QString body = message.textContent(); + if (!body.isEmpty()){ + TPtrC16 msg(reinterpret_cast(body.utf16())); + if (!ipRichText) { + ipCharFormatLayer = CCharFormatLayer::NewL(); + ipParaFormatLayer = CParaFormatLayer::NewL(); + ipRichText=CRichText::NewL(ipParaFormatLayer,ipCharFormatLayer); + } + ipRichText->Reset(); + ipRichText->InsertL(0, msg); + store->StoreBodyTextL(*ipRichText); + store->CommitL(); + } + CleanupStack::PopAndDestroy(store); + + QMessagePrivate* privateMessage = QMessagePrivate::implementation(message); + privateMessage->_id = QMessageId(QString::number(entry.Id())); + + if (!message.receivedDate().isNull() || !message.date().isNull()) { + // Change the date to given date + CMsvEntry* pEntry = ipMsvSession->GetEntryL(entry.Id()); + CleanupStack::PushL(pEntry); + TMsvEntry changedEntry = pEntry->Entry(); + if (!message.date().isNull()) { + changedEntry.iDate = qDateTimeToSymbianTTime(message.date()); + } else { + changedEntry.iDate = qDateTimeToSymbianTTime(message.receivedDate()); + } + pEntry->ChangeL(changedEntry); + CleanupStack::PopAndDestroy(pEntry); + } +} + +bool CMTMEngine::sendSMS(QMessage &message) +{ + if (!iSessionReady) { + return false; + } + + TRAPD(err, sendSMSL(message)); + if (err != KErrNone) { + return false; + } + + return true; +} + +void CMTMEngine::sendSMSL(QMessage &message) +{ + if (!iSessionReady) { + User::Leave(KErrNotReady); + } + + if (!message.id().isValid()) { + QMessagePrivate::setStandardFolder(message, QMessage::DraftsFolder); + storeSMSL(message); + } + + long int messageId = message.id().toString().toLong(); + if (messageId == 0) { + User::Leave(KErrNotReady); + } + + CMsvEntry* pMsvEntry = retrieveCMsvEntryAndPushToCleanupStack(messageId); + CMsvOperationWait* pMsvOperationWait = CMsvOperationWait::NewLC(); + + ipSmsMtm->SwitchCurrentEntryL(pMsvEntry->Entry().Parent()); + // Following sends SMS and _moves_ SMS from Drafts Folder to Sent Folder + CMsvOperation* pMsvOperation = ipSmsMtm->Entry().CopyL(messageId, ipSmsMtm->ServiceId(), pMsvOperationWait->iStatus); + pMsvOperationWait->Start(); + CActiveScheduler::Start(); + delete pMsvOperation; + + CleanupStack::PopAndDestroy(pMsvOperationWait); + releaseCMsvEntryAndPopFromCleanupStack(pMsvEntry); +} + +void CMTMEngine::storeMMSL(QMessage &message) +{ + if (!iSessionReady) { + User::Leave(KErrNotReady); + } + + TMsvId destinationFolderId; + if (message.parentFolderId().isValid()) { + destinationFolderId = folderIdFromQMessageFolderId(message.parentFolderId()); + } else { + // parentFolderId was not defined for new Message + // => Message will be created into defined standard Folder (Default value is Drafts Folder) + destinationFolderId = standardFolderId(message.standardFolder()); + } + + CMsvOperationWait* wait = CMsvOperationWait::NewLC(); + wait->Start(); + CMsvOperation* operation = ipMmsMtm->CreateNewEntryL(destinationFolderId, wait->iStatus); + CleanupStack::PushL(operation); + CActiveScheduler::Start(); + if (wait->iStatus.Int() != KErrNone){ + //TODO: handle error + } + TPckgBuf pkg; + pkg.Copy( operation->ProgressL()); + TMsvId indexEntry= pkg(); + CleanupStack::PopAndDestroy(2); // operation and wait + ipMmsMtm->SwitchCurrentEntryL(indexEntry); + ipMmsMtm->LoadMessageL(); + + // Add receivers + QList list(message.to()); + TPtrC16 receiver(KNullDesC); + QString qreceiver; + for (int i = 0; i < list.size(); ++i) { + qreceiver = list.at(i).recipient(); + receiver.Set(reinterpret_cast(qreceiver.utf16())); + ipMmsMtm->AddAddresseeL(receiver); + } + + // Set Subject + QString subject = message.subject(); + TPtrC16 sbj(reinterpret_cast(subject.utf16())); + ipMmsMtm->SetSubjectL(sbj); + + TMsvEntry ent = ipMmsMtm->Entry().Entry(); + ent.SetInPreparation(EFalse); + ent.SetVisible(ETrue); + + switch (message.priority()) { + case QMessage::HighPriority: + ent.SetPriority(EMsvHighPriority); + break; + case QMessage::NormalPriority: + ent.SetPriority(EMsvMediumPriority); + break; + case QMessage::LowPriority: + ent.SetPriority(EMsvLowPriority); + break; + } + if (message.status() & QMessage::Read) { + ent.SetUnread(false); + ent.SetNew(false); + } else { + ent.SetUnread(true); + ent.SetNew(true); + } + ipMmsMtm->Entry().ChangeL(ent); + // Save the changes + ipMmsMtm->SaveMessageL(); + + CMsvStore* store = ipMmsMtm->Entry().EditStoreL(); + CleanupStack::PushL(store); + + // attachments. + QByteArray filePath; + QMessageContentContainerIdList contentIds = message.contentIds(); + foreach (QMessageContentContainerId id, contentIds){ + QMessageContentContainer container = message.find(id); + filePath = QMessageContentContainerPrivate::attachmentFilename(container); + QString body = container.textContent(); + if (!filePath.isEmpty()) { // content is attachment + int last = filePath.lastIndexOf("/"); + int count = filePath.count(); + QByteArray name = filePath.right(count-last-1); + QString fileName = QString(name); + filePath.replace(QByteArray("/"), QByteArray("\\")); + QString temp_path = QString(filePath); + TPtrC16 attachmentPath(KNullDesC); + attachmentPath.Set(reinterpret_cast(temp_path.utf16())); + TFileName attachmentFile; + attachmentFile.Append(attachmentPath); + + RFile attachment; + User::LeaveIfError(attachment.Open(FsSession(),attachmentFile, EFileShareReadersOnly | EFileRead)); + CleanupClosePushL(attachment); + + TInt fileSize; + attachment.Size(fileSize); + TInt maxFileSize = 600000; + if (fileSize > maxFileSize){ + return; + } + + HBufC8* pFileContent = HBufC8::NewL(fileSize); + TPtr8 fileContent(pFileContent->Des()); + attachment.Read(fileContent); + attachment.Close(); + CleanupStack::PushL(pFileContent); + RFile file2; + TFileName tempFileName; + RFs fileServer; + User::LeaveIfError(fileServer.Connect()); + CleanupClosePushL(fileServer); + TInt err = file2.Temp(fileServer,iPath,tempFileName,EFileWrite); + if (err != KErrNone){ + return; + } + CleanupClosePushL(file2); + err = file2.Write(*pFileContent); + if (err != KErrNone){ + return; + } + file2.Close(); + User::LeaveIfError(file2.Open(FsSession(),tempFileName, EFileShareAny|EFileRead)); + // Mime header + CMsvMimeHeaders* mimeHeaders = CMsvMimeHeaders::NewL(); + CleanupStack::PushL(mimeHeaders); + TPtrC16 suggestedName(reinterpret_cast(fileName.utf16())); + mimeHeaders->SetSuggestedFilenameL(suggestedName); + // Represents a single attachment and information about the attachment + CMsvAttachment* attaInfo = CMsvAttachment::NewL(CMsvAttachment::EMsvFile); + CleanupStack::PushL(attaInfo); + + // Mime Type + QByteArray content = container.contentType(); + if (content.isEmpty()){ + RApaLsSession session; + //TPtrC16 filePtr(reinterpret_cast(fileString.utf16())); + TBuf8<20> fileType; + if(session.Connect() == KErrNone){ + TDataRecognitionResult fileDataType; + session.RecognizeData(tempFileName, *pFileContent, *&fileDataType); + fileType.Copy(fileDataType.iDataType.Des8()); + content = QByteArray((const char*)fileType.Ptr(), fileType.Length()); + session.Close(); + } + } + else{ + content.append("/"); + content.append(container.contentSubType()); + } + + QString mime = QString(content); + TPtrC16 mType(reinterpret_cast(mime.utf16())); + HBufC8* mimeType = CnvUtfConverter::ConvertFromUnicodeToUtf8L(mType); + + TMsvAttachmentId attachId = KMsvNullIndexEntryId; + ipMmsMtm->CreateAttachment2L(*store, file2, *mimeType, *mimeHeaders, attaInfo, attachId); + store->CommitL(); + file2.Close(); + + CleanupStack::Pop(attaInfo); + CleanupStack::PopAndDestroy(mimeHeaders); + CleanupStack::Pop(&file2); + CleanupStack::PopAndDestroy(&fileServer); + CleanupStack::PopAndDestroy(pFileContent); + CleanupStack::PopAndDestroy(); //attachment + } + else if (!body.isEmpty()) { // Add body + TPtrC16 msg(reinterpret_cast(body.utf16())); + TMsvAttachmentId attachmentid = KMsvNullIndexEntryId; + TFileName bodyFile( _L("body.txt") ); + ipMmsMtm->CreateTextAttachmentL(*store, attachmentid, msg, bodyFile, ETrue); + store->CommitL(); + } + + } + QString messageBody = message.textContent(); + if (!messageBody.isEmpty()) { // no contents, only body text + TPtrC16 msg(reinterpret_cast(messageBody.utf16())); + TMsvAttachmentId attachmentid = KMsvNullIndexEntryId; + TFileName bodyFile( _L("body.txt") ); + ipMmsMtm->CreateTextAttachmentL(*store, attachmentid, msg, bodyFile, ETrue); + store->CommitL(); + } + + CleanupStack::PopAndDestroy(); // store + + QMessagePrivate* privateMessage = QMessagePrivate::implementation(message); + privateMessage->_id = QMessageId(QString::number(indexEntry)); + // Save the changes + ipMmsMtm->SaveMessageL(); + + if (!message.receivedDate().isNull() || !message.date().isNull()) { + // Change the date to given date + CMsvEntry* pEntry = ipMsvSession->GetEntryL(indexEntry); + CleanupStack::PushL(pEntry); + TMsvEntry changedEntry = pEntry->Entry(); + if (!message.date().isNull()) { + changedEntry.iDate = qDateTimeToSymbianTTime(message.date()); + } else { + changedEntry.iDate = qDateTimeToSymbianTTime(message.receivedDate()); + } + pEntry->ChangeL(changedEntry); + CleanupStack::PopAndDestroy(pEntry); + } +} + +void CMTMEngine::updateSMSL(QMessage &message) +{ + if (!iSessionReady) { + User::Leave(KErrNotReady); + } + + QMessageId id = message.id(); + long int messageId = id.toString().toLong(); + if (messageId == 0) + return; + + CMsvEntry* entry = ipMsvSession->GetEntryL(messageId); + CleanupStack::PushL(entry); + + ipSmsMtm->SwitchCurrentEntryL(messageId); + ipSmsMtm->LoadMessageL(); + + TMsvEntry tEntry = ipSmsMtm->Entry().Entry(); + switch (message.priority()) { + case QMessage::HighPriority: + tEntry.SetPriority(EMsvHighPriority); + break; + case QMessage::NormalPriority: + tEntry.SetPriority(EMsvMediumPriority); + break; + case QMessage::LowPriority: + tEntry.SetPriority(EMsvLowPriority); + break; + } + if (message.status() & QMessage::Read) { + tEntry.SetUnread(false); + tEntry.SetNew(false); + } else { + tEntry.SetUnread(true); + tEntry.SetNew(true); + } + ipSmsMtm->Entry().ChangeL(tEntry); + // Save the changes + ipSmsMtm->SaveMessageL(); + + QList list(message.to()); + if (!list.empty()){ + TPtrC16 receiver(KNullDesC); + QString qreceiver; + for (int i = 0; i < list.size(); ++i) { + qreceiver = list.at(i).recipient(); + receiver.Set(reinterpret_cast(qreceiver.utf16())); + ipSmsMtm->AddAddresseeL(receiver); + ipSmsMtm->SaveMessageL(); + } + } + + CMsvStore* store = ipSmsMtm->Entry().EditStoreL(); + CleanupStack::PushL(store); + + QString body = message.textContent(); + if (!body.isEmpty()){ + TPtrC16 msg(reinterpret_cast(body.utf16())); + if (!ipRichText) { + ipCharFormatLayer = CCharFormatLayer::NewL(); + ipParaFormatLayer = CParaFormatLayer::NewL(); + ipRichText=CRichText::NewL(ipParaFormatLayer,ipCharFormatLayer); + } + ipRichText->Reset(); + ipRichText->InsertL(0, msg); + store->StoreBodyTextL(*ipRichText); + store->CommitL(); + } + + CleanupStack::PopAndDestroy(2); // store, entry + + if (!message.receivedDate().isNull() || !message.date().isNull()) { + // Change the date to given date + CMsvEntry* pEntry = ipMsvSession->GetEntryL(messageId); + CleanupStack::PushL(pEntry); + TMsvEntry changedEntry = pEntry->Entry(); + if (!message.date().isNull()) { + changedEntry.iDate = qDateTimeToSymbianTTime(message.date()); + } else { + changedEntry.iDate = qDateTimeToSymbianTTime(message.receivedDate()); + } + pEntry->ChangeL(changedEntry); + CleanupStack::PopAndDestroy(pEntry); + } +} + +void CMTMEngine::updateMMSL(QMessage &message) +{ + if (!iSessionReady) { + User::Leave(KErrNotReady); + } + + QMessageId id = message.id(); + long int messageId = id.toString().toLong(); + if (messageId == 0) + return; + + ipMmsMtm->SwitchCurrentEntryL(messageId); + ipMmsMtm->LoadMessageL(); + + // Add receivers + QList list(message.to()); + if (!list.empty()){ + TPtrC16 receiver(KNullDesC); + QString qreceiver; + for (int i = 0; i < list.size(); ++i) { + qreceiver = list.at(i).recipient(); + receiver.Set(reinterpret_cast(qreceiver.utf16())); + ipMmsMtm->AddAddresseeL(receiver); + } + } + + // Set Subject + QString subject = message.subject(); + if (!subject.isEmpty()){ + TPtrC16 sbj(reinterpret_cast(subject.utf16())); + ipMmsMtm->SetSubjectL(sbj); + } + + TMsvEntry ent = ipMmsMtm->Entry().Entry(); + ent.SetInPreparation(EFalse); + ent.SetVisible(ETrue); + + switch (message.priority()) { + case QMessage::HighPriority: + ent.SetPriority(EMsvHighPriority); + break; + case QMessage::NormalPriority: + ent.SetPriority(EMsvMediumPriority); + break; + case QMessage::LowPriority: + ent.SetPriority(EMsvLowPriority); + break; + } + if (message.status() & QMessage::Read) { + ent.SetUnread(false); + ent.SetNew(false); + } else { + ent.SetUnread(true); + ent.SetNew(true); + } + ipMmsMtm->Entry().ChangeL(ent); + // Save the changes + ipMmsMtm->SaveMessageL(); + + CMsvStore* store = ipMmsMtm->Entry().EditStoreL(); + CleanupStack::PushL(store); + + // attachments. + QByteArray filePath; + QMessageContentContainerIdList contentIds = message.contentIds(); + foreach (QMessageContentContainerId id, contentIds){ + QMessageContentContainer container = message.find(id); + QMessageContentContainerPrivate* pPrivateContainer = QMessageContentContainerPrivate::implementation(container); + filePath = QMessageContentContainerPrivate::attachmentFilename(container); + if (!filePath.isEmpty()) { // content is attachment + int last = filePath.lastIndexOf("/"); + int count = filePath.count(); + QByteArray name = filePath.right(count-last-1); + QString fileName = QString(name); + filePath.replace(QByteArray("/"), QByteArray("\\")); + QString temp_path = QString(filePath); + TPtrC16 attachmentPath(KNullDesC); + attachmentPath.Set(reinterpret_cast(temp_path.utf16())); + TFileName attachmentFile; + attachmentFile.Append(attachmentPath); + + RFile attachment; + User::LeaveIfError(attachment.Open(FsSession(),attachmentFile, EFileShareReadersOnly | EFileRead)); + CleanupClosePushL(attachment); + + TInt fileSize; + attachment.Size(fileSize); + TInt maxFileSize = 600000; + if (fileSize > maxFileSize){ + return; + } + + HBufC8* pFileContent = HBufC8::NewL(fileSize); + TPtr8 fileContent(pFileContent->Des()); + attachment.Read(fileContent); + attachment.Close(); + CleanupStack::PushL(pFileContent); + RFile file2; + TFileName tempFileName; + RFs fileServer; + User::LeaveIfError(fileServer.Connect()); + CleanupClosePushL(fileServer); + TInt err = file2.Temp(fileServer,iPath,tempFileName,EFileWrite); + if (err != KErrNone){ + return; + } + CleanupClosePushL(file2); + err = file2.Write(*pFileContent); + if (err != KErrNone){ + return; + } + file2.Close(); + User::LeaveIfError(file2.Open(FsSession(),tempFileName, EFileShareAny|EFileRead)); + // Mime header + CMsvMimeHeaders* mimeHeaders = CMsvMimeHeaders::NewL(); + CleanupStack::PushL(mimeHeaders); + TPtrC16 suggestedName(reinterpret_cast(fileName.utf16())); + mimeHeaders->SetSuggestedFilenameL(suggestedName); + // Represents a single attachment and information about the attachment + CMsvAttachment* attaInfo = CMsvAttachment::NewL(CMsvAttachment::EMsvFile); + CleanupStack::PushL(attaInfo); + + // Mime Type + QByteArray content = container.contentType(); + if (content.isEmpty()){ + RApaLsSession session; + TBuf8<20> fileType; + if(session.Connect() == KErrNone){ + TDataRecognitionResult fileDataType; + session.RecognizeData(tempFileName, *pFileContent, *&fileDataType); + fileType.Copy(fileDataType.iDataType.Des8()); + content = QByteArray((const char*)fileType.Ptr(), fileType.Length()); + session.Close(); + } + } + else{ + content.append("/"); + content.append(container.contentSubType()); + } + QString mime = QString(content); + TPtrC16 mType(reinterpret_cast(mime.utf16())); + HBufC8* mimeType = CnvUtfConverter::ConvertFromUnicodeToUtf8L(mType); + + TMsvAttachmentId attachId = KMsvNullIndexEntryId; + ipMmsMtm->CreateAttachment2L(*store, file2, *mimeType, *mimeHeaders, attaInfo, attachId); + store->CommitL(); + file2.Close(); + + CleanupStack::Pop(attaInfo); + CleanupStack::PopAndDestroy(mimeHeaders); + CleanupStack::Pop(&file2); + CleanupStack::PopAndDestroy(&fileServer); + CleanupStack::PopAndDestroy(pFileContent); + CleanupStack::PopAndDestroy(); //attachment + } + else if (pPrivateContainer->_id == message.bodyId()) { // content is body text + QString body = container.textContent(); + TPtrC16 msg(reinterpret_cast(body.utf16())); + TMsvAttachmentId attachmentid = KMsvNullIndexEntryId; + TFileName bodyFile( _L("body.txt") ); + ipMmsMtm->CreateTextAttachmentL(*store, attachmentid, msg, bodyFile, ETrue); + store->CommitL(); + } + } + + QString messageBody = message.textContent(); + if (!messageBody.isEmpty()) { // no contents, only body text + TPtrC16 msg(reinterpret_cast(messageBody.utf16())); + TMsvAttachmentId attachmentid = KMsvNullIndexEntryId; + TFileName bodyFile( _L("body.txt") ); + ipMmsMtm->CreateTextAttachmentL(*store, attachmentid, msg, bodyFile, ETrue); + store->CommitL(); + } + + CleanupStack::PopAndDestroy(); // store + // Save the changes + ipMmsMtm->SaveMessageL(); + + if (!message.receivedDate().isNull() || !message.date().isNull()) { + // Change the date to given date + CMsvEntry* pEntry = ipMsvSession->GetEntryL(messageId); + CleanupStack::PushL(pEntry); + TMsvEntry changedEntry = pEntry->Entry(); + if (!message.date().isNull()) { + changedEntry.iDate = qDateTimeToSymbianTTime(message.date()); + } else { + changedEntry.iDate = qDateTimeToSymbianTTime(message.receivedDate()); + } + pEntry->ChangeL(changedEntry); + CleanupStack::PopAndDestroy(pEntry); + } +} + +void CMTMEngine::updateEmailL(QMessage &message) +{ + if (!iSessionReady) { + User::Leave(KErrNotReady); + } + + QMessageId id = message.id(); + long int messageId = id.toString().toLong(); + if (messageId == 0) + return; + + CMsvEntry* pEntry = ipMsvSession->GetEntryL(messageId); + TUid mtmUid = pEntry->Entry().iMtm; + delete pEntry; + + TMsvEntry msvEntry; + if (mtmUid == KUidMsgTypeSMTP) { + ipSmtpMtm->SwitchCurrentEntryL(messageId); + ipSmtpMtm->LoadMessageL(); + msvEntry = ipSmtpMtm->Entry().Entry(); + } else if (mtmUid == KUidMsgTypePOP3) { + ipPop3Mtm->SwitchCurrentEntryL(messageId); + ipPop3Mtm->LoadMessageL(); + msvEntry = ipPop3Mtm->Entry().Entry(); + } else if (mtmUid == KUidMsgTypeIMAP4) { + ipImap4Mtm->SwitchCurrentEntryL(messageId); + ipImap4Mtm->LoadMessageL(); + msvEntry = ipImap4Mtm->Entry().Entry(); + } + + switch (message.priority()) { + case QMessage::HighPriority: + msvEntry.SetPriority(EMsvHighPriority); + break; + case QMessage::NormalPriority: + msvEntry.SetPriority(EMsvMediumPriority); + break; + case QMessage::LowPriority: + msvEntry.SetPriority(EMsvLowPriority); + break; + } + if (message.status() & QMessage::Read) { + msvEntry.SetUnread(false); + msvEntry.SetNew(false); + } else { + msvEntry.SetUnread(true); + msvEntry.SetNew(true); + } + + msvEntry.iDescription.Set(TPtrC(reinterpret_cast(message.subject().utf16()))); + msvEntry.iDetails.Set(TPtrC(reinterpret_cast(message.from().recipient().utf16()))); + + if (mtmUid == KUidMsgTypeSMTP) { + ipSmtpMtm->Entry().ChangeL(msvEntry); + } else { + CMsvOperationWait* pMsvOperationWait = CMsvOperationWait::NewLC(); + CMsvOperation* pMsvOperation = NULL; + if (mtmUid == KUidMsgTypePOP3) { + pMsvOperation = ipPop3Mtm->Entry().ChangeL(msvEntry, pMsvOperationWait->iStatus); + } else { + pMsvOperation = ipImap4Mtm->Entry().ChangeL(msvEntry, pMsvOperationWait->iStatus); + } + pMsvOperationWait->Start(); + CActiveScheduler::Start(); + delete pMsvOperation; + CleanupStack::PopAndDestroy(pMsvOperationWait); + } + + // Save the changes + ipSmtpMtm->SaveMessageL(); + + CMsvEntry* entry = ipMsvSession->GetEntryL(messageId); + CleanupStack::PushL(entry); + + CImEmailMessage* mailMsg = CImEmailMessage::NewLC(*entry); + + CMsvOperationWait* waiter = CMsvOperationWait::NewLC(); + + CImMimeHeader* mime = CImMimeHeader::NewLC(); + + QByteArray filePath; + QMessageContentContainerIdList contentIds = message.contentIds(); + foreach (QMessageContentContainerId id, contentIds){ + QMessageContentContainer container = message.find(id); + QMessageContentContainerPrivate* pPrivateContainer = QMessageContentContainerPrivate::implementation(container); + filePath = QMessageContentContainerPrivate::attachmentFilename(container); + if (!filePath.isEmpty()) { // content is attachment + filePath.replace(QByteArray("/"), QByteArray("\\")); + QString temp_path = QString(filePath); + TPtrC16 attachmentPath(KNullDesC); + attachmentPath.Set(reinterpret_cast(temp_path.utf16())); + TFileName attachmentFile; + attachmentFile.Append(attachmentPath); + + RFile attachment; + User::LeaveIfError(attachment.Open(FsSession(),attachmentFile, EFileShareReadersOnly | EFileRead)); + CleanupClosePushL(attachment); + + CMsvAttachment* attachmentInfo = CMsvAttachment::NewL(CMsvAttachment::EMsvFile); + QByteArray filePath = QMessageContentContainerPrivate::attachmentFilename(container); + int last = filePath.lastIndexOf("/"); + int count = filePath.count(); + QByteArray name = filePath.right(count-last-1); + QString fileName = QString(name); + CleanupStack::PushL(attachmentInfo); + attachmentInfo->SetAttachmentNameL(TPtrC(reinterpret_cast(fileName.utf16()))); + mailMsg->AttachmentManager().AddAttachmentL(attachment, attachmentInfo, waiter->iStatus); + waiter->Start(); + CActiveScheduler::Start(); + CleanupStack::Pop(attachmentInfo); + CleanupStack::Pop(&attachment); // close file + } else if (pPrivateContainer->_id == message.bodyId()) { // content is body text + CParaFormatLayer* paragraphFormatLayer = CParaFormatLayer::NewL(); + CleanupStack::PushL(paragraphFormatLayer); + + CCharFormatLayer* characterFormatLayer = CCharFormatLayer::NewL(); + CleanupStack::PushL(characterFormatLayer); + + CRichText* bodyText = CRichText::NewL(paragraphFormatLayer, characterFormatLayer, CEditableText::EFlatStorage, 256); + CleanupStack::PushL(bodyText); + + //content type + QByteArray contentType = container.contentType(); + TPtrC8 content((TUint8 *)(contentType.constData())); + mime->SetContentTypeL(content); + // content subtype + QByteArray subType = container.contentSubType(); + TPtrC8 contentSubType((TUint8 *)(subType.constData())); + mime->SetContentSubTypeL(contentSubType); + // content charset + QByteArray charset = container.contentCharset(); + if (charset == "UTF-8") { + mime->SetMimeCharset(KCharacterSetIdentifierUtf8); + } + if (charset == "UTF-16") { + mime->SetMimeCharset(KCharacterSetIdentifierUcs2); + } + // Insert the contents of a buffer into the document at specified position + bodyText->InsertL(0, TPtrC(reinterpret_cast(container.textContent().utf16()))); + mailMsg->StoreBodyTextWithMimeHeaderL(messageId, *bodyText, *mime, waiter->iStatus); + + waiter->Start(); + CActiveScheduler::Start(); + + CleanupStack::PopAndDestroy(3); // bodyText, characterFormatLayer, paragraphFormatLayer + } + + } + + QString messageBody = message.textContent(); + if (!messageBody.isEmpty()) { + CParaFormatLayer* paragraphFormatLayer = CParaFormatLayer::NewL(); + CleanupStack::PushL(paragraphFormatLayer); + + CCharFormatLayer* characterFormatLayer = CCharFormatLayer::NewL(); + CleanupStack::PushL(characterFormatLayer); + + CRichText* bodyText = CRichText::NewL(paragraphFormatLayer, characterFormatLayer, CEditableText::EFlatStorage, 256); + CleanupStack::PushL(bodyText); + + //content type + QByteArray contentType = message.contentType(); + TPtrC8 content((TUint8 *)(contentType.constData())); + mime->SetContentTypeL(content); + // content subtype + QByteArray subType = message.contentSubType(); + TPtrC8 contentSubType((TUint8 *)(subType.constData())); + mime->SetContentSubTypeL(contentSubType); + // content charset + QByteArray charset = message.contentCharset(); + if (charset == "UTF-8") { + mime->SetMimeCharset(KCharacterSetIdentifierUtf8); + } + if (charset == "UTF-16") { + mime->SetMimeCharset(KCharacterSetIdentifierUcs2); + } + + // Insert the contents of a buffer into the document at specified position + bodyText->InsertL(0, TPtrC(reinterpret_cast(message.textContent().utf16()))); + mailMsg->StoreBodyTextWithMimeHeaderL(messageId, *bodyText, *mime, waiter->iStatus); + waiter->Start(); + CActiveScheduler::Start(); + CleanupStack::PopAndDestroy(3); + //bodyText, characterFormatLayer, paragraphFormatLayer, + } + + CMsvStore* store = entry->EditStoreL(); + CleanupStack::PushL(store); + CImHeader* emailEntry = CImHeader::NewLC(); + TRAP_IGNORE(emailEntry->RestoreL(*store)); + mime->StoreL(*store); + emailEntry->SetSubjectL(TPtrC(reinterpret_cast(message.subject().utf16()))); + + QList toList(message.to()); + if (toList.count() > 0){ + TPtrC16 receiver(KNullDesC); + QString qreceiver; + for (int i = 0; i < toList.size(); ++i) { + qreceiver = toList.at(i).recipient(); + receiver.Set(reinterpret_cast(qreceiver.utf16())); + emailEntry->ToRecipients().AppendL(receiver); + } + } + + QList ccList(message.cc()); + if (ccList.count() > 0){ + TPtrC16 receiver(KNullDesC); + QString qreceiver; + for (int i = 0; i < ccList.size(); ++i) { + qreceiver = ccList.at(i).recipient(); + receiver.Set(reinterpret_cast(qreceiver.utf16())); + emailEntry->CcRecipients().AppendL(receiver); + } + } + + QList bccList(message.bcc()); + if (bccList.count() > 0){ + TPtrC16 receiver(KNullDesC); + QString qreceiver; + for (int i = 0; i < bccList.size(); ++i) { + qreceiver = bccList.at(i).recipient(); + receiver.Set(reinterpret_cast(qreceiver.utf16())); + emailEntry->BccRecipients().AppendL(receiver); + } + } + + emailEntry->StoreL(*store); + // Store the changes permanently + store->CommitL(); + + CleanupStack::PopAndDestroy(6, entry); + // mailMsg, emailEntry, store, waiter, entry, mime + + if (!message.receivedDate().isNull() || !message.date().isNull()) { + // Change the date to given date + CMsvEntry* pEntry = ipMsvSession->GetEntryL(messageId); + CleanupStack::PushL(pEntry); + TMsvEntry changedEntry = pEntry->Entry(); + if (!message.date().isNull()) { + changedEntry.iDate = qDateTimeToSymbianTTime(message.date()); + } else { + changedEntry.iDate = qDateTimeToSymbianTTime(message.receivedDate()); + } + if (mtmUid == KUidMsgTypeSMTP) { + ipSmtpMtm->Entry().ChangeL(changedEntry); + } else { + CMsvOperationWait* pMsvOperationWait = CMsvOperationWait::NewLC(); + CMsvOperation* pMsvOperation = NULL; + if (mtmUid == KUidMsgTypePOP3) { + pMsvOperation = ipPop3Mtm->Entry().ChangeL(changedEntry, pMsvOperationWait->iStatus); + } else { + pMsvOperation = ipImap4Mtm->Entry().ChangeL(changedEntry, pMsvOperationWait->iStatus); + } + pMsvOperationWait->Start(); + CActiveScheduler::Start(); + delete pMsvOperation; + CleanupStack::PopAndDestroy(pMsvOperationWait); + } + CleanupStack::PopAndDestroy(pEntry); + } +} + +void CMTMEngine::sendMMSL(QMessage &message) +{ + if (!iSessionReady) { + User::Leave(KErrNotReady); + } + + bool messageCreated = false; + if (!message.id().isValid()) { + QMessagePrivate::setStandardFolder(message, QMessage::OutboxFolder); + storeMMSL(message); + messageCreated = true; + } + + long int messageId = message.id().toString().toLong(); + if (messageId == 0) { + User::Leave(KErrNotReady); + } + + CMsvEntry* pMsvEntry = retrieveCMsvEntryAndPushToCleanupStack(messageId); + CMsvOperationWait* pMsvOperationWait = CMsvOperationWait::NewLC(); + + CMsvOperation* pMsvOperation = NULL; + if (!messageCreated) { + ipMmsMtm->SwitchCurrentEntryL(pMsvEntry->Entry().Parent()); + pMsvOperation = ipMmsMtm->Entry().CopyL(messageId, KMsvGlobalOutBoxIndexEntryId, pMsvOperationWait->iStatus); + pMsvOperationWait->Start(); + CActiveScheduler::Start(); + delete pMsvOperation; + pMsvOperation = NULL; + } + + // Start sending the message via the Server MTM to the MMS server + CMsvEntrySelection* pMsvEntrySelection = new(ELeave) CMsvEntrySelection; + pMsvEntrySelection->AppendL(messageId); + ipMmsMtm->SwitchCurrentEntryL(KMsvGlobalOutBoxIndexEntryId); + pMsvOperation = ipMmsMtm->SendL(*pMsvEntrySelection, pMsvOperationWait->iStatus); + pMsvOperationWait->Start(); + CActiveScheduler::Start(); + delete pMsvOperation; + + while (pMsvOperationWait->iStatus == KRequestPending) { + CActiveScheduler::Start(); + } + + CleanupStack::PopAndDestroy(pMsvOperationWait); + releaseCMsvEntryAndPopFromCleanupStack(pMsvEntry); +} + +QString CMTMEngine::privateFolderPath() +{ + // Take drive letter from Application full name (Note: TUidName is 10 characters long <=> TBuf<10>) + //TUidName applicationDrive; + //applicationDrive.Copy(CEikonEnv::Static()->EikAppUi()->Application()->AppFullName().Left(2)); + + // Get Application private folder path from FileSession + TPath applicationPrivateFolderPathWithoutDriveLetter; + FsSession().PrivatePath(applicationPrivateFolderPathWithoutDriveLetter); + + // Combine drive letter and private folder path to complete path + TPath driveLetterAndPath; + driveLetterAndPath.Copy(_L("C:")); + driveLetterAndPath.Append(applicationPrivateFolderPathWithoutDriveLetter); + + return QString::fromUtf16(driveLetterAndPath.Ptr(), driveLetterAndPath.Length()); +} + +void CMTMEngine::storeEmailL(QMessage &message) +{ + if (!iSessionReady) { + User::Leave(KErrNotReady); + } + + TMsvId destinationFolderId = 0; + TMsvId imapDestinationFolderId = 0; + if (message.parentFolderId().isValid()) { + destinationFolderId = folderIdFromQMessageFolderId(message.parentFolderId()); + CMsvEntry* pMsvEntry = retrieveCMsvEntryAndPushToCleanupStack(destinationFolderId); + if (pMsvEntry->Entry().iMtm == KUidMsgTypeIMAP4 || pMsvEntry->Entry().iMtm == KUidMsgTypePOP3) { + // New IMAP or POP3 message can not be created to IMAP or POP3 service folder. + // => Create IMAP or POP3 message into Drafts folder instead + destinationFolderId = KMsvDraftEntryId; + if (pMsvEntry->Entry().iMtm == KUidMsgTypeIMAP4) { + // It's possible to copy newly created IMAP message from Drafts folder + // to IMAP service folder. + // Note: IMAP message can not be created directly to IMAP service folder. + imapDestinationFolderId = destinationFolderId; + } + } + releaseCMsvEntryAndPopFromCleanupStack(pMsvEntry); + } else { + // parentFolderId was not defined for new Message + // => Message will be created into defined standard Folder (Default value is Drafts Folder) + destinationFolderId = standardFolderId(message.standardFolder()); + } + + QMessageAccount messageAccount = this->account(message.parentAccountId()); + + CMsvOperationWait* pMsvOperationWait = CMsvOperationWait::NewLC(); + TMsvEmailTypeList msvEmailTypeList = 0; + TMsvPartList msvPartList = 0; + if (message.status() & QMessage::HasAttachments == QMessage::HasAttachments) { + msvPartList = (KMsvMessagePartBody | KMsvMessagePartAttachments); + } else { + msvPartList = KMsvMessagePartBody; + } + CImEmailOperation* pImEmailOperation = CImEmailOperation::CreateNewL(pMsvOperationWait->iStatus, *ipMsvSession, destinationFolderId, + messageAccount.d_ptr->_service2EntryId, msvPartList, + msvEmailTypeList, KUidMsgTypeSMTP); + CleanupStack::PushL(pImEmailOperation); + pMsvOperationWait->Start(); + CActiveScheduler::Start(); + + TMsvId newMessageId; + TPckgC paramPack(newMessageId); + paramPack.Set(pImEmailOperation->ProgressL()); + newMessageId = paramPack(); + CleanupStack::PopAndDestroy(pImEmailOperation); + + ipSmtpMtm->SwitchCurrentEntryL(newMessageId); + ipSmtpMtm->LoadMessageL(); + + TMsvEntry msvEntry = ipSmtpMtm->Entry().Entry(); + switch (message.priority()) { + case QMessage::HighPriority: + msvEntry.SetPriority(EMsvHighPriority); + break; + case QMessage::NormalPriority: + msvEntry.SetPriority(EMsvMediumPriority); + break; + case QMessage::LowPriority: + msvEntry.SetPriority(EMsvLowPriority); + break; + } + if (message.status() & QMessage::Read) { + msvEntry.SetUnread(false); + msvEntry.SetNew(false); + } else { + msvEntry.SetUnread(true); + msvEntry.SetNew(true); + } + + ipSmtpMtm->Entry().ChangeL(msvEntry); + ipSmtpMtm->SaveMessageL(); + + CMsvEntry* pMsvEntry = retrieveCMsvEntryAndPushToCleanupStack(newMessageId); + + // Create email message MIME header + CImMimeHeader* pImMimeHeader = CImMimeHeader::NewLC(); + QByteArray contentType = message.contentType(); + TPtrC8 content((TUint8 *)(contentType.constData())); + pImMimeHeader->SetContentTypeL(content); + QByteArray subType = message.contentSubType(); + TPtrC8 contentSubType((TUint8 *)(subType.constData())); + pImMimeHeader->SetContentSubTypeL(contentSubType); + QByteArray charset = message.contentCharset(); + if (charset == "UTF-8") { + pImMimeHeader->SetMimeCharset(KCharacterSetIdentifierUtf8); + } + if (charset == "UTF-16") { + pImMimeHeader->SetMimeCharset(KCharacterSetIdentifierUcs2); + } + + CImEmailMessage* pImEmailMessage = CImEmailMessage::NewL(*pMsvEntry); + CleanupStack::PushL(pImEmailMessage); + + if (message.bodyId() == QMessageContentContainerPrivate::bodyContentId()) { + // Message contains only body (not attachments) + QString messageBody = message.textContent(); + if (!messageBody.isEmpty()) { + CParaFormatLayer* pParaFormatLayer = CParaFormatLayer::NewL(); + CleanupStack::PushL(pParaFormatLayer); + CCharFormatLayer* pCharFormatLayer = CCharFormatLayer::NewL(); + CleanupStack::PushL(pCharFormatLayer); + + CRichText* pBodyRichText = CRichText::NewL(pParaFormatLayer, pCharFormatLayer, CEditableText::EFlatStorage, 256); + CleanupStack::PushL(pBodyRichText); + + // Insert the contents of a buffer into the document at specified position + pBodyRichText->InsertL(0, TPtrC(reinterpret_cast(message.textContent().utf16()))); + // Note: Email message MIME header is same as Body MIME header + pImEmailMessage->StoreBodyTextWithMimeHeaderL(newMessageId, *pBodyRichText, *pImMimeHeader, + pMsvOperationWait->iStatus); + pMsvOperationWait->Start(); + CActiveScheduler::Start(); + + CleanupStack::PopAndDestroy(pBodyRichText); + CleanupStack::PopAndDestroy(pCharFormatLayer); + CleanupStack::PopAndDestroy(pParaFormatLayer); + } + } else { + // Message contains body and attachments + QMessageContentContainerIdList contentIds = message.contentIds(); + foreach (QMessageContentContainerId id, contentIds){ + QMessageContentContainer container = message.find(id); + QMessageContentContainerPrivate* pPrivateContainer = QMessageContentContainerPrivate::implementation(container); + if (pPrivateContainer->_id == message.bodyId()) { + // ContentContainer is body + if (!container.textContent().isEmpty()) { + // Create MIME header for body + CImMimeHeader* pBodyImMimeHeader = CImMimeHeader::NewLC(); + QByteArray contentType = container.contentType(); + TPtrC8 content((TUint8 *)(contentType.constData())); + pBodyImMimeHeader->SetContentTypeL(content); + QByteArray subType = container.contentSubType(); + TPtrC8 contentSubType((TUint8 *)(subType.constData())); + pBodyImMimeHeader->SetContentSubTypeL(contentSubType); + QByteArray charset = container.contentCharset(); + if (charset == "UTF-8") { + pBodyImMimeHeader->SetMimeCharset(KCharacterSetIdentifierUtf8); + } + if (charset == "UTF-16") { + pBodyImMimeHeader->SetMimeCharset(KCharacterSetIdentifierUcs2); + } + + // Create CRichText containing body text + CParaFormatLayer* pParaFormatLayer = CParaFormatLayer::NewL(); + CleanupStack::PushL(pParaFormatLayer); + CCharFormatLayer* pCharFormatLayer = CCharFormatLayer::NewL(); + CleanupStack::PushL(pCharFormatLayer); + + CRichText* pBodyRichText = CRichText::NewL(pParaFormatLayer, pCharFormatLayer, CEditableText::EFlatStorage); + CleanupStack::PushL(pBodyRichText); + // Insert the contents of a buffer into the document at specified position + pBodyRichText->InsertL(0, TPtrC(reinterpret_cast(container.textContent().utf16()))); + + // Store MIME Header and Body text to message + pImEmailMessage->StoreBodyTextWithMimeHeaderL(newMessageId, *pBodyRichText, *pBodyImMimeHeader, pMsvOperationWait->iStatus); + pMsvOperationWait->Start(); + CActiveScheduler::Start(); + + CleanupStack::PopAndDestroy(pBodyRichText); + CleanupStack::PopAndDestroy(pCharFormatLayer); + CleanupStack::PopAndDestroy(pParaFormatLayer); + CleanupStack::PopAndDestroy(pBodyImMimeHeader); + } + } else { + // ContentContainer is attachment + QByteArray filePath = QMessageContentContainerPrivate::attachmentFilename(container); + // Replace Qt style path separator "/" with Symbian path separator "\" + filePath.replace(QByteArray("/"), QByteArray("\\")); + // Make sure that "." folder is translated to application private folder + // For example: "." = ":\private\\" + if (filePath.startsWith('.')) { + filePath.remove(0,2); // Remove ".\" + filePath.insert(0,privateFolderPath().toAscii()); + } + QString temp_path = QString(filePath); + TPtrC16 attachmentPath(KNullDesC); + attachmentPath.Set(reinterpret_cast(temp_path.utf16())); + TFileName attachmentFileName; + attachmentFileName.Append(attachmentPath); + + RFile attachmentFile; + User::LeaveIfError(attachmentFile.Open(FsSession(), attachmentFileName, + EFileShareReadersOnly | EFileRead)); + CleanupClosePushL(attachmentFile); + + CMsvAttachment* pMsvAttachment = CMsvAttachment::NewL(CMsvAttachment::EMsvFile); + int last = filePath.lastIndexOf("\\"); + int count = filePath.count(); + QByteArray name = filePath.right(count-last-1); + QString fileName = QString(name); + CleanupStack::PushL(pMsvAttachment); + pMsvAttachment->SetAttachmentNameL(TPtrC(reinterpret_cast(fileName.utf16()))); + // Note: Following call transfers ownership of attachmentFile and pMsvAttachment to AttachmentManager + pImEmailMessage->AttachmentManager().AddAttachmentL(attachmentFile, pMsvAttachment, pMsvOperationWait->iStatus); + pMsvOperationWait->Start(); + CActiveScheduler::Start(); + CleanupStack::Pop(pMsvAttachment); // Pop attachment from CleanupStack + CleanupStack::Pop(&attachmentFile); // Pop file from CleanupStack + } + } + } + CleanupStack::PopAndDestroy(pImEmailMessage); + + CMsvStore* pMsvStore = pMsvEntry->EditStoreL(); + CleanupStack::PushL(pMsvStore); + + pImMimeHeader->StoreL(*pMsvStore); + + CImHeader* pImHeader = CImHeader::NewLC(); + pImHeader->RestoreL(*pMsvStore); + pImHeader->SetSubjectL(TPtrC(reinterpret_cast(message.subject().utf16()))); + pImHeader->SetFromL(TPtrC(reinterpret_cast(message.from().recipient().utf16()))); + + QList toList(message.to()); + if (toList.count() > 0) { + TPtrC16 receiver(KNullDesC); + QString qreceiver; + for (int i = 0; i < toList.size(); ++i) { + qreceiver = toList.at(i).recipient(); + receiver.Set(reinterpret_cast(qreceiver.utf16())); + pImHeader->ToRecipients().AppendL(receiver); + } + } + + QList ccList(message.cc()); + if (ccList.count() > 0) { + TPtrC16 receiver(KNullDesC); + QString qreceiver; + for (int i = 0; i < ccList.size(); ++i) { + qreceiver = ccList.at(i).recipient(); + receiver.Set(reinterpret_cast(qreceiver.utf16())); + pImHeader->CcRecipients().AppendL(receiver); + } + } + + QList bccList(message.bcc()); + if (bccList.count() > 0) { + TPtrC16 receiver(KNullDesC); + QString qreceiver; + for (int i = 0; i < bccList.size(); ++i) { + qreceiver = bccList.at(i).recipient(); + receiver.Set(reinterpret_cast(qreceiver.utf16())); + pImHeader->BccRecipients().AppendL(receiver); + } + } + + pImHeader->StoreL(*pMsvStore); + CleanupStack::PopAndDestroy(pImHeader); + + // Store the changes permanently + pMsvStore->CommitL(); + CleanupStack::PopAndDestroy(pMsvStore); + CleanupStack::PopAndDestroy(pImMimeHeader); + + TMsvEntry changedEntry = pMsvEntry->Entry(); + changedEntry.iDescription.Set(TPtrC(reinterpret_cast(message.subject().utf16()))); + if (toList.count() > 0) { + changedEntry.iDetails.Set(TPtrC(reinterpret_cast(toList.at(0).recipient().utf16()))); + } + if (!message.receivedDate().isNull() || !message.date().isNull()) { + // Change the date to given date + if (!message.date().isNull()) { + changedEntry.iDate = qDateTimeToSymbianTTime(message.date()); + } else { + changedEntry.iDate = qDateTimeToSymbianTTime(message.receivedDate()); + } + } + pMsvEntry->ChangeL(changedEntry); + + if (imapDestinationFolderId != 0) { + TMsvId parent = pMsvEntry->Entry().Parent(); + ipImap4Mtm->SwitchCurrentEntryL(parent); + CMsvOperation* pMsvOperation = ipImap4Mtm->Entry().MoveL(newMessageId, imapDestinationFolderId, + pMsvOperationWait->iStatus); + CleanupStack::PushL(pMsvOperation); + pMsvOperationWait->Start(); + CActiveScheduler::Start(); + CleanupStack::PopAndDestroy(pMsvOperation); + } + + releaseCMsvEntryAndPopFromCleanupStack(pMsvEntry); + + CleanupStack::PopAndDestroy(pMsvOperationWait); + + QMessagePrivate* privateMessage = QMessagePrivate::implementation(message); + privateMessage->_id = QMessageId(QString::number(newMessageId)); +} + +void CMTMEngine::sendEmailL(QMessage &message) +{ + if (!iSessionReady) { + User::Leave(KErrNotReady); + } + + QMessageAccountId accountId = message.parentAccountId(); + QMessageAccount messageAccount; + if (accountId.isValid()) { + messageAccount = account(accountId); + } else { + accountId = defaultAccount(QMessage::Email); + messageAccount = account(accountId); + } + + bool messageCreated = false; + if (!message.id().isValid()) { + // Message id is not valid + // => Message is not in message store + // => New message must be created into Outbox folder + QMessagePrivate::setStandardFolder(message, QMessage::OutboxFolder); + message.setParentAccountId(accountId); + storeEmailL(message); + messageCreated = true; + } + + long int messageId = message.id().toString().toLong(); + if (messageId == 0) { + User::Leave(KErrNotReady); + } + + CMsvEntry* pMsvEntry = retrieveCMsvEntryAndPushToCleanupStack(messageId); + CMsvOperationWait* pMsvOperationWait = CMsvOperationWait::NewLC(); + + CMsvOperation* pMsvOperation = NULL; + if (!messageCreated) { + // Sending (old) message that's in message store + // => Copy message from its original location to Outbox folder + ipSmtpMtm->SwitchCurrentEntryL(pMsvEntry->Entry().Parent()); + pMsvOperation = ipSmtpMtm->Entry().CopyL(messageId, KMsvGlobalOutBoxIndexEntryId, pMsvOperationWait->iStatus); + pMsvOperationWait->Start(); + CActiveScheduler::Start(); + delete pMsvOperation; + pMsvOperation = NULL; + } + + ipSmtpMtm->SwitchCurrentEntryL(pMsvEntry->Entry().Parent()); + // Following sends Email and _moves_ Email from Outbox Folder to Sent Folder + pMsvOperation = ipSmtpMtm->Entry().CopyL(messageId, messageAccount.d_ptr->_service2EntryId, pMsvOperationWait->iStatus); + pMsvOperationWait->Start(); + CActiveScheduler::Start(); + delete pMsvOperation; + + CleanupStack::PopAndDestroy(pMsvOperationWait); + releaseCMsvEntryAndPopFromCleanupStack(pMsvEntry); +} + +QDateTime CMTMEngine::symbianTTimetoQDateTime(const TTime& time) const +{ + TDateTime dateTime = time.DateTime(); + QDate qdate = QDate(dateTime.Year(), static_cast(dateTime.Month())+1, dateTime.Day()+1); + QTime qtime = QTime(dateTime.Hour(), dateTime.Minute(), dateTime.Second(), dateTime.MicroSecond()/1000 ); + return QDateTime(qdate, qtime, Qt::UTC); +} + +TTime CMTMEngine::qDateTimeToSymbianTTime(const QDateTime& date) const +{ + TDateTime dateTime; + dateTime.SetYear(date.date().year()); + dateTime.SetMonth(static_cast(date.date().month()-1)); + dateTime.SetDay(date.date().day()-1); + dateTime.SetHour(date.time().hour()); + dateTime.SetMinute(date.time().minute()); + dateTime.SetSecond(date.time().second()); + dateTime.SetMicroSecond(date.time().msec()*1000); + return TTime(dateTime); +} + +QMessage CMTMEngine::smsMessageL(CMsvEntry& receivedEntry, long int messageId) const +{ + QMessage message; + int size = 0; + message.setType(QMessage::Sms); + + CMsvStore* pStore = receivedEntry.ReadStoreL(); + CleanupStack::PushL(pStore); + + const TMsvEntry& entry = receivedEntry.Entry(); + message.setDate(symbianTTimetoQDateTime(entry.iDate)); + message.setReceivedDate(symbianTTimetoQDateTime(entry.iDate)); + + QMessageAccount account = accountsByType(QMessage::Sms)[0]; + QMessagePrivate* privateMessage = QMessagePrivate::implementation(message); + privateMessage->_parentFolderId = createQMessageFolderId(account.d_ptr->_service1EntryId, entry.Parent()); + privateMessage->_parentAccountId = account.id(); + if (!entry.Unread()) { + privateMessage->_status = privateMessage->_status | QMessage::Read; + } + + switch (entry.Priority()) { + case EMsvHighPriority: + message.setPriority(QMessage::HighPriority); + break; + case EMsvMediumPriority: + message.setPriority(QMessage::NormalPriority); + break; + case EMsvLowPriority: + message.setPriority(QMessage::LowPriority); + break; + } + + if (entry.Parent() == KMsvGlobalInBoxIndexEntryId) { + QMessagePrivate::setStandardFolder(message,QMessage::InboxFolder); + } else if (entry.Parent() == KMsvDraftEntryId) { + QMessagePrivate::setStandardFolder(message,QMessage::DraftsFolder); + } else if (entry.Parent() == KMsvSentEntryId) { + QMessagePrivate::setStandardFolder(message,QMessage::SentFolder); + } else if (entry.Parent() == KMsvDeletedEntryFolderEntryId) { + QMessagePrivate::setStandardFolder(message,QMessage::TrashFolder); + } + + // Read message sender + ipSmsMtm->SwitchCurrentEntryL(messageId); + ipSmsMtm->LoadMessageL(); + CSmsHeader& header = ipSmsMtm->SmsHeader(); + message.setFrom(QMessageAddress(QMessageAddress::Phone, QString::fromUtf16(header.FromAddress().Ptr(), header.FromAddress().Length()))); + QMessagePrivate::setSenderName(message, QString::fromUtf16(header.FromAddress().Ptr(), header.FromAddress().Length())); + + // Read message recipients + const CArrayPtrFlat& array = header.Recipients(); + QMessageAddressList messageAddresslist; + for (int i=0; i < array.Count(); i++) { + CSmsNumber* smsNumber = array.At(i); + TPtrC recipientNumber = smsNumber->Address(); + messageAddresslist.append(QMessageAddress(QMessageAddress::Phone, QString::fromUtf16(recipientNumber.Ptr(), recipientNumber.Length()))); + } + message.setTo(messageAddresslist); + + // Read message body + if (pStore->HasBodyTextL()) { + if (!ipRichText) { + ipCharFormatLayer = CCharFormatLayer::NewL(); + ipParaFormatLayer = CParaFormatLayer::NewL(); + ipRichText=CRichText::NewL(ipParaFormatLayer, ipCharFormatLayer); + } + ipRichText->Reset(); + pStore->RestoreBodyTextL(*ipRichText); + HBufC* pMessage = HBufC::NewLC(ipRichText->DocumentLength()); + TPtr ptr2(pMessage->Des()); + ipRichText->Extract(ptr2); + if (pMessage->Length() > 0) { + size += pMessage->Length(); + message.setBody(QString::fromUtf16(pMessage->Ptr(), pMessage->Length())); + if (pMessage->Length() <= 100) { + message.setSubject(QString::fromUtf16(pMessage->Ptr(), pMessage->Length())); + } else { + message.setSubject(QString::fromUtf16(pMessage->Ptr(), 100)); + } + } + CleanupStack::PopAndDestroy(pMessage); + } + + CleanupStack::PopAndDestroy(pStore); + + privateMessage->_size = size; + + return message; +} + +QMessage CMTMEngine::mmsMessageL(CMsvEntry& receivedEntry, long int messageId) const +{ + QMessage message; + int size = 0; + message.setType(QMessage::Mms); + + CMsvStore* pStore = receivedEntry.ReadStoreL(); + CleanupStack::PushL(pStore); + + const TMsvEntry& entry = receivedEntry.Entry(); + message.setDate(symbianTTimetoQDateTime(entry.iDate)); + message.setReceivedDate(symbianTTimetoQDateTime(entry.iDate)); + + QMessageAccount account = accountsByType(QMessage::Mms)[0]; + QMessagePrivate* privateMessage = QMessagePrivate::implementation(message); + privateMessage->_parentFolderId = createQMessageFolderId(account.d_ptr->_service1EntryId, entry.Parent()); + privateMessage->_parentAccountId = account.id(); + if (!entry.Unread()) { + privateMessage->_status = privateMessage->_status | QMessage::Read; + } + + switch (entry.Priority()) { + case EMsvHighPriority: + message.setPriority(QMessage::HighPriority); + break; + case EMsvMediumPriority: + message.setPriority(QMessage::NormalPriority); + break; + case EMsvLowPriority: + message.setPriority(QMessage::LowPriority); + break; + } + + if (entry.Parent() == KMsvGlobalInBoxIndexEntryId) { + QMessagePrivate::setStandardFolder(message,QMessage::InboxFolder); + } else if (entry.Parent() == KMsvDraftEntryId) { + QMessagePrivate::setStandardFolder(message,QMessage::DraftsFolder); + } else if (entry.Parent() == KMsvSentEntryId) { + QMessagePrivate::setStandardFolder(message,QMessage::SentFolder); + } else if (entry.Parent() == KMsvDeletedEntryFolderEntryId) { + QMessagePrivate::setStandardFolder(message,QMessage::TrashFolder); + } + + // Read message sender + ipMmsMtm->SwitchCurrentEntryL(messageId); + ipMmsMtm->LoadMessageL(); + message.setFrom(QMessageAddress(QMessageAddress::Phone, QString::fromUtf16(ipMmsMtm->Sender().Ptr(), ipMmsMtm->Sender().Length()))); + QMessagePrivate::setSenderName(message, QString::fromUtf16(ipMmsMtm->Sender().Ptr(), ipMmsMtm->Sender().Length())); + + // Read message subject + if (receivedEntry.Entry().iDescription.Length() > 0) { + message.setSubject(QString::fromUtf16(receivedEntry.Entry().iDescription.Ptr(), + receivedEntry.Entry().iDescription.Length())); + } + + // Read message body & attachments + TInt count = pStore->AttachmentManagerL().AttachmentCount(); + TBool textAdded = EFalse; + if (count > 0) { + privateMessage->_status = privateMessage->_status | QMessage::HasAttachments; + } + for (TInt i = 0; i < count; i++) { + CMsvAttachment* pAttachment = pStore->AttachmentManagerL().GetAttachmentInfoL(i); + CleanupStack::PushL(pAttachment); + if (pAttachment->MimeType() == _L8("text/plain") && !textAdded) { + // Read message body + textAdded = ETrue; + RFile file = pStore->AttachmentManagerL().GetAttachmentFileL(i); + CleanupClosePushL(file); + TInt fileSize; + size += fileSize; + file.Size(fileSize); + HBufC8* pFileContent = HBufC8::NewLC(fileSize); + TPtr8 fileContent(pFileContent->Des()); + file.Read(fileContent); + HBufC* pMsg = CnvUtfConverter::ConvertToUnicodeFromUtf8L(*pFileContent); + CleanupStack::PopAndDestroy(pFileContent); + CleanupStack::PopAndDestroy(&file); + if (pMsg->Length() > 0) { + message.setBody(QString::fromUtf16(pMsg->Ptr(), pMsg->Length())); + if (receivedEntry.Entry().iDescription.Length() <= 0) { // no subject + if (pMsg->Length() <= 100) { + message.setSubject(QString::fromUtf16(pMsg->Ptr(), pMsg->Length())); + } + else { + message.setSubject(QString::fromUtf16(pMsg->Ptr(), 100)); + } + } + } + delete pMsg; + } else { + QByteArray mimeType; + QByteArray mimeSubType; + QByteArray mimeTypeAndSubType = QByteArray((const char *)pAttachment->MimeType().Ptr(), pAttachment->MimeType().Length()); + int index = mimeTypeAndSubType.indexOf("/"); + if (index != -1) { + mimeType = mimeTypeAndSubType.left(index).trimmed(); + mimeSubType = mimeTypeAndSubType.mid(index + 1).trimmed(); + } + QByteArray path = QString::fromUtf16(pAttachment->FilePath().Ptr(),pAttachment->FilePath().Length()).toLocal8Bit(); + index = path.lastIndexOf('\\'); + QByteArray name; + if (index != -1) { + name = path.right(path.length()-index-1); + } else { + name = path; + } + int attachmentSize = pAttachment->Size(); + size += attachmentSize; + QMessageContentContainer attachment = QMessageContentContainerPrivate::from(messageId, pAttachment->Id(), name, mimeType, mimeSubType, attachmentSize); + appendAttachmentToMessage(message, attachment); + } + CleanupStack::PopAndDestroy(pAttachment); + } + + CleanupStack::PopAndDestroy(pStore); + + privateMessage->_size = size; + + return message; +} + +QMessage CMTMEngine::emailMessageL(CMsvEntry& receivedEntry, long int messageId) const +{ + QMessage message; + int size = 0; + message.setType(QMessage::Email); + + const TMsvEntry& entry = receivedEntry.Entry(); + message.setDate(symbianTTimetoQDateTime(entry.iDate)); + message.setReceivedDate(symbianTTimetoQDateTime(entry.iDate)); + + QMessageAccount messageAccount = account(accountIdByServiceId(entry.iServiceId)); + message.setParentAccountId(messageAccount.id()); + + QMessagePrivate* privateMessage = QMessagePrivate::implementation(message); + privateMessage->_parentFolderId = createQMessageFolderId(messageAccount.d_ptr->_service1EntryId, entry.Parent()); + if (!entry.Unread()) { + privateMessage->_status = privateMessage->_status | QMessage::Read; + } + + switch (entry.Priority()) { + case EMsvHighPriority: + message.setPriority(QMessage::HighPriority); + break; + case EMsvMediumPriority: + message.setPriority(QMessage::NormalPriority); + break; + case EMsvLowPriority: + message.setPriority(QMessage::LowPriority); + break; + } + + if (entry.iMtm == KUidMsgTypePOP3) { + // All incoming POP3 messages are in the root of the POP3 service + QMessageAccount messageAccount = account(message.parentAccountId()); + if (entry.Parent() == messageAccount.d_ptr->_service1EntryId) { + QMessagePrivate::setStandardFolder(message,QMessage::InboxFolder); + } + } else if (entry.iMtm == KUidMsgTypeIMAP4) { + // All incoming IMAP4 messages are in the folders which can + // be found from the root of the IMAP4 service + QMessageAccount messageAccount = account(message.parentAccountId()); + CMsvEntry* pEntry = retrieveCMsvEntryAndPushToCleanupStack(entry.Parent()); + if (pEntry->Entry().Parent() == messageAccount.d_ptr->_service1EntryId) { + QMessagePrivate::setStandardFolder(message,QMessage::InboxFolder); + } + releaseCMsvEntryAndPopFromCleanupStack(pEntry); + } + if (entry.Parent() == KMsvDraftEntryId) { + QMessagePrivate::setStandardFolder(message,QMessage::DraftsFolder); + } else if (entry.Parent() == KMsvSentEntryId) { + QMessagePrivate::setStandardFolder(message,QMessage::SentFolder); + } else if (entry.Parent() == KMsvDeletedEntryFolderEntryId) { + QMessagePrivate::setStandardFolder(message,QMessage::TrashFolder); + } + + CImHeader* emailEntry = CImHeader::NewLC(); + CImEmailMessage* emailMessage = CImEmailMessage::NewLC(receivedEntry); + CImMimeHeader* pImMimeHeader = CImMimeHeader::NewLC(); + + TInt mimeHeaderReadError = KErrNotFound; + if (receivedEntry.HasStoreL()) { + CMsvStore* msvStore = receivedEntry.ReadStoreL(); + CleanupStack::PushL(msvStore); + TRAP_IGNORE(emailEntry->RestoreL(*msvStore)); + size += emailEntry->DataSize(); + TRAP(mimeHeaderReadError, pImMimeHeader->RestoreL(*msvStore)); + if (mimeHeaderReadError == KErrNone) { + size += pImMimeHeader->Size(); + } + CleanupStack::PopAndDestroy(); // store + } + + if (!ipRichText) { + ipCharFormatLayer = CCharFormatLayer::NewL(); + ipParaFormatLayer = CParaFormatLayer::NewL(); + ipRichText = CRichText::NewL(ipParaFormatLayer, ipCharFormatLayer); + } + ipRichText->Reset(); + emailMessage->GetBodyTextL(messageId, + CImEmailMessage::EThisMessageOnly, + *ipRichText, + *ipParaFormatLayer, + *ipCharFormatLayer); + + // From GetBodyTextL() documentation: + // A list containing the entry Ids for each body text part within + // the specified message is created during this call. The list can + // be retrieved after this call has completed by calling Selection(). + if (emailMessage->Selection().Count() > 0) { + if (pImMimeHeader->ContentType() == KImcvMultipart) { + // Get body content type (CImMimeHeader) from first body part + CMsvEntry* pEntry = retrieveCMsvEntryAndPushToCleanupStack(emailMessage->Selection()[0]); + if (pEntry->HasStoreL()) { + CMsvStore* pMsvStore = pEntry->ReadStoreL(); + CleanupStack::PushL(pMsvStore); + TRAP(mimeHeaderReadError, pImMimeHeader->RestoreL(*pMsvStore)); + if (mimeHeaderReadError == KErrNone) { + size += pImMimeHeader->Size(); + } + CleanupStack::PopAndDestroy(pMsvStore); + } + releaseCMsvEntryAndPopFromCleanupStack(pEntry); + } + } + + QByteArray mimeType; + if (mimeHeaderReadError == KErrNone) { + TPtrC8 type = pImMimeHeader->ContentType(); + if (type.Length() > 0) { + QByteArray contentType = QByteArray((const char *)type.Ptr(),type.Length()); + mimeType.append(contentType); + mimeType.append("/"); + + TPtrC8 subType = pImMimeHeader->ContentSubType(); + if (subType.Length() > 0) { + QByteArray contentSubType = QByteArray((const char *)subType.Ptr(),subType.Length()); + mimeType.append(contentSubType); + } + TUint charset = pImMimeHeader->MimeCharset(); + if (charset) { + mimeType.append(";charset="); + if (charset == KCharacterSetIdentifierUcs2) + mimeType.append("UTF-16"); + else if (charset == KCharacterSetIdentifierUtf8) + mimeType.append("UTF-8"); + } + } + } + CleanupStack::PopAndDestroy(pImMimeHeader); + + HBufC* pMessage = HBufC::NewLC(ipRichText->DocumentLength()); + TPtr ptr2(pMessage->Des()); + ipRichText->Extract(ptr2); + if (pMessage->Length() > 0) { + QString text = QString::fromUtf16(pMessage->Ptr(),pMessage->Length()); + message.setBody(text, mimeType); + size += text.size(); + } + CleanupStack::PopAndDestroy(pMessage); + + //attachment(s) + emailMessage->GetAttachmentsListL(messageId, CImEmailMessage::EAllAttachments, CImEmailMessage::EThisMessageOnly); + TInt c = emailMessage->AttachmentManager().AttachmentCount(); + if (c > 0) { + privateMessage->_status = privateMessage->_status | QMessage::HasAttachments; + } + for (TInt i = 0; i < c; i++) { + CMsvAttachment* pAttachment = emailMessage->AttachmentManager().GetAttachmentInfoL(i); + CleanupStack::PushL(pAttachment); + + QByteArray mimeType; + QByteArray mimeSubType; + CImMimeHeader* pImMimeHeader = CImMimeHeader::NewLC(); + CMsvEntry* pEntry = retrieveCMsvEntryAndPushToCleanupStack(pAttachment->Id()); + if (pEntry->HasStoreL()) { + CMsvStore* pMsvStore = pEntry->ReadStoreL(); + CleanupStack::PushL(pMsvStore); + TRAP(mimeHeaderReadError, pImMimeHeader->RestoreL(*pMsvStore)); + if (mimeHeaderReadError == KErrNone) { + size += pImMimeHeader->Size(); + } + CleanupStack::PopAndDestroy(pMsvStore); + } + releaseCMsvEntryAndPopFromCleanupStack(pEntry); + if (mimeHeaderReadError == KErrNone) { + mimeType = QByteArray((const char *)pImMimeHeader->ContentType().Ptr(), pImMimeHeader->ContentType().Length()); + mimeSubType = QByteArray((const char *)pImMimeHeader->ContentSubType().Ptr(), pImMimeHeader->ContentSubType().Length()); + } + CleanupStack::PopAndDestroy(pImMimeHeader); + + QByteArray name = QString::fromUtf16(pAttachment->AttachmentName().Ptr(), pAttachment->AttachmentName().Length()).toLocal8Bit(); + int attachmentSize = pAttachment->Size(); + size += attachmentSize; + QMessageContentContainer attachment = QMessageContentContainerPrivate::from(messageId, pAttachment->Id(), name, mimeType, mimeSubType, attachmentSize); + appendAttachmentToMessage(message, attachment); + CleanupStack::PopAndDestroy(pAttachment); + } + + //from + TPtrC from = emailEntry->From(); + if (from.Length() > 0) { + message.setFrom(QMessageAddress(QMessageAddress::Email, QString::fromUtf16(from.Ptr(), from.Length()))); + QMessagePrivate::setSenderName(message, QString::fromUtf16(from.Ptr(), from.Length())); + } else { + if (entry.iDetails.Length() > 0) { + QString fromString = QString::fromUtf16(receivedEntry.Entry().iDetails.Ptr(), receivedEntry.Entry().iDetails.Length()); + message.setFrom(QMessageAddress(QMessageAddress::Email, fromString)); + QMessagePrivate::setSenderName(message, fromString); + } + } + + //to + CDesCArray& toArray = emailEntry->ToRecipients(); + QList toList; + for (TInt i = 0; i < toArray.Count(); i++) + { + TPtrC16 to(toArray.MdcaPoint(i)); + toList.append(QMessageAddress(QMessageAddress::Email, QString::fromUtf16(to.Ptr(), to.Length()))); + } + message.setTo(toList); + + //cc + CDesCArray& ccArray = emailEntry->CcRecipients(); + QList ccList; + for (TInt i = 0; i < ccArray.Count(); i++) + { + TPtrC16 cc(ccArray.MdcaPoint(i)); + ccList.append(QMessageAddress(QMessageAddress::Email, QString::fromUtf16(cc.Ptr(), cc.Length()))); + } + message.setCc(ccList); + + //bcc + CDesCArray& bccArray = emailEntry->BccRecipients(); + QList bccList; + for (TInt i = 0; i < bccArray.Count(); i++) + { + TPtrC16 bcc(bccArray.MdcaPoint(i)); + bccList.append(QMessageAddress(QMessageAddress::Email, QString::fromUtf16(bcc.Ptr(), bcc.Length()))); + } + message.setBcc(bccList); + + // Read message subject + TPtrC subject = emailEntry->Subject(); + if (subject.Length() > 0) { + message.setSubject(QString::fromUtf16(subject.Ptr(), subject.Length())); + } else { + if (entry.iDescription.Length() > 0) { + message.setSubject(QString::fromUtf16(receivedEntry.Entry().iDescription.Ptr(), + receivedEntry.Entry().iDescription.Length())); + } + } + + CleanupStack::PopAndDestroy(emailMessage); + CleanupStack::PopAndDestroy(emailEntry); + + privateMessage->_size = size; + + return message; +} + +void CMTMEngine::appendAttachmentToMessage(QMessage& message, QMessageContentContainer& attachment) const +{ + QMessagePrivate* privateMessage = QMessagePrivate::implementation(message); + QMessageContentContainerPrivate* container = QMessagePrivate::containerImplementation(message); + + if (container->_attachments.isEmpty()) { + QMessageContentContainerId existingBodyId(message.bodyId()); + if (existingBodyId == QMessageContentContainerPrivate::bodyContentId()) { + // The body content is in the message itself - move it to become the first attachment + QMessageContentContainer newBody(message); + QMessageContentContainerPrivate::implementation(newBody)->setDerivedMessage(0); + + container->setContentType("multipart", "mixed", ""); + privateMessage->_bodyId = container->prependContent(newBody); + } else { + // This message is now multipart + container->setContentType("multipart", "mixed", ""); + } + + container->_available = true; + } + + container->appendContent(attachment); + + bool haveAttachments = !container->_attachments.isEmpty(); + message.setStatus(QMessage::HasAttachments,haveAttachments); + + privateMessage->_modified = true; +} + +QByteArray CMTMEngine::attachmentContent(long int messageId, unsigned int attachmentId) +{ + QByteArray result; + TRAP_IGNORE(result = attachmentContentL(messageId, attachmentId)); + return result; +} + +QByteArray CMTMEngine::attachmentContentL(long int messageId, unsigned int attachmentId) +{ + QByteArray result; + + CMsvEntry* pEntry = retrieveCMsvEntryAndPushToCleanupStack(messageId); + if (pEntry->Entry().iMtm == KUidMsgTypeMultimedia) { // MMS + CMsvStore* pStore = pEntry->ReadStoreL(); + CleanupStack::PushL(pStore); + RFile file = pStore->AttachmentManagerL().GetAttachmentFileL(attachmentId); + CleanupClosePushL(file); + TInt fileSize; + file.Size(fileSize); + TBuf fileName; + file.Name(fileName); + HBufC8* pFileContent = HBufC8::NewL(fileSize); + TPtr8 fileContent(pFileContent->Des()); + file.Read(fileContent); + CleanupStack::PopAndDestroy(&file); + CleanupStack::PushL(pFileContent); + + result = QByteArray((char*)pFileContent->Ptr(),pFileContent->Length()); + + CleanupStack::PopAndDestroy(pFileContent); + CleanupStack::PopAndDestroy(pStore); + } else { // Email + CImEmailMessage* pImEmailMessage = CImEmailMessage::NewLC(*pEntry); + RFile file = pImEmailMessage->AttachmentManager().GetAttachmentFileL(attachmentId); + CleanupClosePushL(file); + TInt fileSize; + file.Size(fileSize); + TBuf fileName; + file.Name(fileName); + HBufC8* pFileContent = HBufC8::NewL(fileSize); + TPtr8 fileContent(pFileContent->Des()); + file.Read(fileContent); + CleanupStack::PopAndDestroy(&file); + CleanupStack::PushL(pFileContent); + + result = QByteArray((char*)pFileContent->Ptr(),pFileContent->Length()); + + CleanupStack::PopAndDestroy(pFileContent); + CleanupStack::PopAndDestroy(pImEmailMessage); + } + releaseCMsvEntryAndPopFromCleanupStack(pEntry); + + return result; +} + +QString CMTMEngine::attachmentTextContent(long int messageId, unsigned int attachmentId, const QByteArray &charset) +{ + QString result; + + QByteArray data = attachmentContent(messageId, attachmentId); + if (!data.isEmpty()) { + // Convert attachment data to string form + QTextCodec *codec; + if (!charset.isEmpty()) { + codec = QTextCodec::codecForName(charset); + } else { + codec = QTextCodec::codecForLocale(); + } + + if (codec) { + result = codec->toUnicode(data); + } + } + + return result; +} + +QMessage CMTMEngine::pop3MessageL(CMsvEntry& /*receivedEntry*/, long int /*messageId*/) const +{ + return QMessage(); +} + +QMessage CMTMEngine::imap4MessageL(CMsvEntry& /*receivedEntry*/, long int /*messageId*/) const +{ + return QMessage(); +} + +CMsvEntry* CMTMEngine::retrieveCMsvEntryAndPushToCleanupStack(TMsvId id) const +{ + CMsvEntry* pEntry = NULL; + + if (iCmsvEntryPoolFree.Count() > 0) { + pEntry = iCmsvEntryPoolFree[iCmsvEntryPoolFree.Count()-1]; + TInt retVal = iCmsvEntryPoolInUse.Append(pEntry); + if (retVal != KErrNone) { + delete pEntry; + pEntry = NULL; + } + } else { + if (id == 0) { + id = KMsvRootIndexEntryId; + } + TRAPD(err, pEntry = ipMsvSession->GetEntryL(id)); + if (err == KErrNone) { + TInt retVal = iCmsvEntryPoolInUse.Append(pEntry); + if (retVal != KErrNone) { + delete pEntry; + pEntry = NULL; + } + } + } + + if (id != 0 && pEntry) { + TRAPD(err, pEntry->SetEntryL(id)); + if (err != KErrNone) { + TInt pos = iCmsvEntryPoolInUse.Find(pEntry); + if (pos != KErrNotFound) { + iCmsvEntryPoolInUse.Remove(pos); + TInt retVal = iCmsvEntryPoolFree.Append(pEntry); + if (retVal != KErrNone) { + delete pEntry; + } + } + pEntry = NULL; + } + } + + if (pEntry) { + TCleanupItem entryCleanup(cmsvEntryCleanup, pEntry); + CleanupStack::PushL(entryCleanup); + } + + return pEntry; +} + +void CMTMEngine::cmsvEntryCleanup(TAny* aCMsvEntry) +{ + CMTMEngine* pMTMEngine = mtmEngine(); + CMsvEntry* pEntry = (CMsvEntry*)aCMsvEntry; + + TInt pos = pMTMEngine->iCmsvEntryPoolInUse.Find(pEntry); + if (pos != KErrNotFound) { + pMTMEngine->iCmsvEntryPoolInUse.Remove(pos); + TInt retVal = pMTMEngine->iCmsvEntryPoolFree.Append(pEntry); + if (retVal != KErrNone) { + delete pEntry; + } + } +} + +void CMTMEngine::releaseCMsvEntryAndPopFromCleanupStack(CMsvEntry* pEntry) const +{ + if (pEntry) { + CleanupStack::Pop(); // Entry cleanup + } + + TInt pos = iCmsvEntryPoolInUse.Find(pEntry); + if (pos != KErrNotFound) { + iCmsvEntryPoolInUse.Remove(pos); + TInt retVal = iCmsvEntryPoolFree.Append(pEntry); + if (retVal != KErrNone) { + delete pEntry; + } + } +} + +QMessageManager::NotificationFilterId CMTMEngine::registerNotificationFilter(QMessageStorePrivate& aPrivateStore, + const QMessageFilter &filter) +{ + ipMessageStorePrivate = &aPrivateStore; + iListenForNotifications = true; + + int filterId = ++_filterId; + _filters.insert(filterId, filter); + return filterId; +} + +void CMTMEngine::unregisterNotificationFilter(QMessageManager::NotificationFilterId notificationFilterId) +{ + _filters.remove(notificationFilterId); + if (_filters.count() == 0) { + iListenForNotifications = false; + } +} + +void CMTMEngine::notification(TMsvSessionEvent aEvent, TUid aMsgType, TMsvId aFolderId, TMsvId aMessageId) +{ + if (aFolderId == 0x100001 || aFolderId == 0x100002) { // MMS Notifications Folder + // Ignore MMS Notifications <=> Wait until actual MMS message has been received + return; + } + + QMessageManager::NotificationFilterIdSet matchingFilters; + + // Copy the filter map to protect against modification during traversal + QMap filters(_filters); + QMap::const_iterator it = filters.begin(), end = filters.end(); + QMessage message; + bool messageRetrieved = false; + bool unableToReadAndFilterMessage = false; + for ( ; it != end; ++it) { + const QMessageFilter &filter(it.value()); + + if (filter.isEmpty()) { + // Empty filter matches to all messages + matchingFilters.insert(it.key()); + } else { + QMessageFilterPrivate* privateMessageFilter = QMessageFilterPrivate::implementation(filter); + if (privateMessageFilter->_field == QMessageFilterPrivate::Type) { + if (aMsgType == KUidMsgTypeSMS) { + message.setType(QMessage::Sms); + } else if (aMsgType == KUidMsgTypeMultimedia) { + message.setType(QMessage::Mms); + } else if (aMsgType == KUidMsgTypeSMTP || + aMsgType == KUidMsgTypePOP3 || + aMsgType == KUidMsgTypeIMAP4) { + message.setType(QMessage::Email); + } else { + message.setType(QMessage::NoType); + } + } else if ((privateMessageFilter->_field == QMessageFilterPrivate::StandardFolder) && + (aMsgType == KUidMsgTypeSMS || aMsgType == KUidMsgTypeMultimedia)) { + if (aFolderId == KMsvGlobalInBoxIndexEntryId) { + QMessagePrivate::setStandardFolder(message,QMessage::InboxFolder); + } else if (aFolderId == KMsvDraftEntryId) { + QMessagePrivate::setStandardFolder(message,QMessage::DraftsFolder); + } else if (aFolderId == KMsvSentEntryId) { + QMessagePrivate::setStandardFolder(message,QMessage::SentFolder); + } else if (aFolderId == KMsvDeletedEntryFolderEntryId) { + QMessagePrivate::setStandardFolder(message,QMessage::TrashFolder); + } + } else if (!messageRetrieved) { + message = this->message(QMessageId(QString::number(aMessageId))); + if (message.type() == QMessage::NoType) { + unableToReadAndFilterMessage = true; + matchingFilters.clear(); + break; + } else { + messageRetrieved = true; + } + } + if (privateMessageFilter->filter(message)) { + matchingFilters.insert(it.key()); + } + } + } + + QMessageStorePrivate::NotificationType notificationType = QMessageStorePrivate::Removed; + if (aEvent == EMsvEntriesCreated) { + notificationType = QMessageStorePrivate::Added; + } else if (aEvent == EMsvEntriesChanged || aEvent == EMsvEntriesMoved) { + notificationType = QMessageStorePrivate::Updated; + } if (aEvent == EMsvEntriesDeleted) { + notificationType = QMessageStorePrivate::Removed; + } + + if (matchingFilters.count() > 0) { + // Check if there are already pending events for + // currently handled MessageId + bool pendingEventsForCurrentlyHandledMessageId = false; + for (int i=0; i < iUndeliveredMessageEvents.count(); i++) { + if (iUndeliveredMessageEvents[i].messageId == aMessageId) { + pendingEventsForCurrentlyHandledMessageId = true; + break; + } + } + if (pendingEventsForCurrentlyHandledMessageId) { + // There are pending notification events for this messageId. + // => Add new notification event to notification event queue to + // make sure that all events will be delivered in correct order. + MessageEvent event; + event.messageId = aMessageId; + event.notificationType = notificationType; + event.matchingFilters = matchingFilters; + event.unfiltered = false; + if (iUndeliveredMessageEvents.count() == 0) { + iDeliveryTriesCounter = 0; + } + iUndeliveredMessageEvents.append(event); + tryToDeliverMessageNotifications(); + } else { + // No pending notification events for this messageId. + // => Deliver notification immediately + ipMessageStorePrivate->messageNotification(notificationType, + QMessageId(QString::number(aMessageId)), + matchingFilters); + } + } else if (unableToReadAndFilterMessage) { + if (notificationType != QMessageStorePrivate::Removed) { + MessageEvent event; + event.messageId = aMessageId; + event.notificationType = notificationType; + event.unfiltered = true; + if (iUndeliveredMessageEvents.count() == 0) { + iDeliveryTriesCounter = 0; + } + iUndeliveredMessageEvents.append(event); + tryToDeliverMessageNotifications(); + } else { + // Message was removed before reading was possible + // => All avents related to removed messageId can be ignored + // => Remove all related events from undelivered message events queue + for (int i=iUndeliveredMessageEvents.count()-1; i >= 0; i--) { + if (iUndeliveredMessageEvents[i].messageId == aMessageId) { + iUndeliveredMessageEvents.removeAt(i); + } + } + } + } +} + +void CMTMEngine::tryToDeliverMessageNotifications() +{ + if (!IsActive()) { + int count = iUndeliveredMessageEvents.count(); + while (count--) { + // Try to deliver the oldest message event notification first + MessageEvent event = iUndeliveredMessageEvents[0]; + bool eventHandlingPossible = true; + if (event.notificationType != QMessageStorePrivate::Removed && event.unfiltered) { + QMessage message = this->message(QMessageId(QString::number(event.messageId))); + if (message.type() == QMessage::NoType) { + eventHandlingPossible = false; + } else { + event.matchingFilters.clear(); + // Copy the filter map to protect against modification during traversal + QMap filters(_filters); + QMap::const_iterator it = filters.begin(), end = filters.end(); + for ( ; it != end; ++it) { + const QMessageFilter &filter(it.value()); + if (filter.isEmpty()) { + // Empty filter matches to all messages + event.matchingFilters.insert(it.key()); + } else { + QMessageFilterPrivate* privateMessageFilter = QMessageFilterPrivate::implementation(filter); + if (privateMessageFilter->filter(message)) { + event.matchingFilters.insert(it.key()); + } + } + } + } + } + + if (eventHandlingPossible) { + // New message entry was ready to be read + // Remove message event from queue + iUndeliveredMessageEvents.removeFirst(); + iDeliveryTriesCounter = 0; + if (event.matchingFilters.count() > 0) { + // Deliver message event notification + ipMessageStorePrivate->messageNotification(event.notificationType, + QMessageId(QString::number(event.messageId)), + event.matchingFilters); + } + } else { + // New message entry was NOT ready to be read + iDeliveryTriesCounter++; + if (iDeliveryTriesCounter < 50) { + // Wait for 0.1 seconds to see if message would + // be ready to be read & delivered after wait. + iTimer.After(iStatus, KWaitAfterReceivedMessage); + SetActive(); + break; + } else { + // Remove problematic message event from queue + iUndeliveredMessageEvents.removeFirst(); + iDeliveryTriesCounter = 0; + } + } + } + } +} + +void CMTMEngine::RunL() +{ + tryToDeliverMessageNotifications(); +} + + +void CMTMEngine::DoCancel() +{ + iTimer.Cancel(); +} + +void CMTMEngine::HandleSessionEventL(TMsvSessionEvent aEvent, TAny* aArg1, + TAny* aArg2, TAny* /*aArg3*/) +{ + switch (aEvent) { + case EMsvServerReady: + iSessionReady = ETrue; + break; + case EMsvEntriesCreated: + case EMsvEntriesChanged: + case EMsvEntriesDeleted: + case EMsvEntriesMoved: + if (aArg2 && iListenForNotifications) { + CMsvEntrySelection* entries = static_cast(aArg1); + + if (entries != NULL) { + TInt count = entries->Count(); + while (count--) { + const TMsvId id = (*entries)[count]; + if (aEvent == EMsvEntriesDeleted) { + notification(aEvent, TUid(), *(static_cast(aArg2)), id); + } else { + CMsvEntry* pReceivedEntry = NULL; + TRAPD(err, pReceivedEntry = ipMsvSession->GetEntryL(id)); + if (err == KErrNone) { + const TMsvEntry& entry = pReceivedEntry->Entry(); + if (entry.iType == KUidMsvMessageEntry) { + notification(aEvent, entry.iMtm, *(static_cast(aArg2)), id); + } + delete pReceivedEntry; + } + } + } + } + } + break; + + default: + break; + } +} + +CMessagesFindOperation::CMessagesFindOperation(CMTMEngine& aOwner, CMsvSession* apMsvSession, int aOperationId) + : CActive(CActive::EPriorityStandard), iOwner(aOwner), ipMsvSession(apMsvSession), iOperationId(aOperationId), + iResultCorrectlyOrdered(false) +{ + CActiveScheduler::Add(this); + iTimer.CreateLocal(); +} + +CMessagesFindOperation::~CMessagesFindOperation() +{ + Cancel(); + iTimer.Close(); + delete ipMsvFindOperation; + delete ipEntrySelection; +} + +void CMessagesFindOperation::DoCancel() +{ + ipMsvFindOperation->Cancel(); +} + +void CMessagesFindOperation::filterAndOrderMessages(const QMessageFilter &filter, const QMessageSortOrder& sortOrder, + QString body, QMessageDataComparator::MatchFlags matchFlags) +{ + iFilterList.clear(); + iFilterList.append(filter); + filterAndOrderMessages(iFilterList, sortOrder, body, matchFlags); +} + +void CMessagesFindOperation::filterAndOrderMessages(const QMessageFilterPrivate::SortedMessageFilterList& filters, + const QMessageSortOrder& sortOrder, + QString body, + QMessageDataComparator::MatchFlags matchFlags) +{ + delete ipMsvFindOperation; + ipMsvFindOperation = NULL; + delete ipEntrySelection; + ipEntrySelection = NULL; + iNumberOfHandledFilters = 0; + + if (filters.count() == 0) { + iIdList = QMessageIdList(); + iTimer.After(iStatus, 1); + if (!IsActive()) { + SetActive(); + } + return; + } + + QMessageFilterPrivate* pf = QMessageFilterPrivate::implementation(filters[iNumberOfHandledFilters]); + if ((filters.count() == 1) && + (pf->_field == QMessageFilterPrivate::None) && + (pf->_filterList.count() == 0)) { + if (pf->_notFilter) { + // There is only one filter: empty ~QMessageFilter() + // => return empty QMessageIdList + iIdList = QMessageIdList(); + } else { + // There is only one filter: empty QMessageFilter() + // => return all messages + ipEntrySelection = new(ELeave)CMsvEntrySelection; + getAllMessagesL(iOrdering); + iIdList = QMessageIdList(); + for (int i=0; i < ipEntrySelection->Count(); i++) { + iIdList.append(QMessageId(QString::number((*ipEntrySelection)[i]))); + } + } + iNumberOfHandledFilters++; + iTimer.After(iStatus, 1); + if (!IsActive()) { + SetActive(); + } + return; + } + + // Set sortOrder + if (!sortOrder.isEmpty() ) { + QMessageSortOrderPrivate* privateMessageOrdering = QMessageSortOrderPrivate::implementation(sortOrder); + iOrdering.SetShowInvisibleEntries(EFalse); + QPair fieldOrder = privateMessageOrdering->_fieldOrderList.at(0); + switch (fieldOrder.first) { + case QMessageSortOrderPrivate::Type: + iOrdering.SetGroupByMtm(true); + break; + case QMessageSortOrderPrivate::Sender: + if (fieldOrder.second == Qt::AscendingOrder) { + iOrdering.SetSorting(EMsvSortByDetails); // To/From (A-Z folded) + } else { + iOrdering.SetSorting(EMsvSortByDetailsReverse); // To/From (Z-A folded) + } + break; + case QMessageSortOrderPrivate::Recipients: + if (fieldOrder.second == Qt::AscendingOrder) { + iOrdering.SetSorting(EMsvSortByDetails); // To/From (A-Z folded) + } else { + iOrdering.SetSorting(EMsvSortByDetailsReverse); // To/From (Z-A folded) + } + break; + case QMessageSortOrderPrivate::Subject: + if (fieldOrder.second == Qt::AscendingOrder) { + iOrdering.SetSorting(EMsvSortByDescription); // Description (A-Z folded) + } else { + iOrdering.SetSorting(EMsvSortByDescriptionReverse); // Description (Z-A folded) + } + break; + case QMessageSortOrderPrivate::TimeStamp: + if (fieldOrder.second == Qt::AscendingOrder) { + iOrdering.SetSorting(EMsvSortByDate); // Date (earliest-latest) + } else { + iOrdering.SetSorting(EMsvSortByDateReverse); // Date (latest-earliest) + } + break; + case QMessageSortOrderPrivate::ReceptionTimeStamp: + if (fieldOrder.second == Qt::AscendingOrder) { + iOrdering.SetSorting(EMsvSortByDate); // Date (earliest-latest) + } else { + iOrdering.SetSorting(EMsvSortByDateReverse); // Date (latest-earliest) + } + break; + case QMessageSortOrderPrivate::Read: + //TODO: + break; + case QMessageSortOrderPrivate::HasAttachments: + //TODO: + break; + case QMessageSortOrderPrivate::Incoming: + //TODO: + break; + case QMessageSortOrderPrivate::Removed: + //TODO: + break; + case QMessageSortOrderPrivate::Priority: + //iOrdering.SetGroupByPriority(true); + break; + case QMessageSortOrderPrivate::Size: + if (fieldOrder.second == Qt::AscendingOrder) { + iOrdering.SetSorting(EMsvSortBySize); // (smallest-largest) + } else { + iOrdering.SetSorting(EMsvSortBySizeReverse); // (largest-smallest) + } + break; + } + } + + switch (pf->_field) { + case QMessageFilterPrivate::Id: + { + iNumberOfHandledFilters++; + if (pf->_comparatorType == QMessageFilterPrivate::Equality) { // QMessageId + QMessageDataComparator::EqualityComparator cmp(static_cast(pf->_comparatorValue)); + if (!pf->_value.isNull() && pf->_value.toString().length() > 0) { + if (cmp == QMessageDataComparator::Equal) { + long int messageId = pf->_value.toString().toLong(); + CMsvEntry* pEntry = iOwner.retrieveCMsvEntryAndPushToCleanupStack(messageId); + if (pEntry) { + const TMsvEntry& entry = pEntry->Entry(); + if (entry.iType == KUidMsvMessageEntry) { + ipEntrySelection = new(ELeave)CMsvEntrySelection; + ipEntrySelection->AppendL(messageId); + } + iOwner.releaseCMsvEntryAndPopFromCleanupStack(pEntry); + } + iResultCorrectlyOrdered = true; + } else { // NotEqual + ipEntrySelection = new(ELeave)CMsvEntrySelection; + getAllMessagesL(iOrdering); + long int messageId = pf->_value.toString().toLong(); + for (int i=0; i < ipEntrySelection->Count(); i++) { + if (ipEntrySelection->At(i) == messageId) { + ipEntrySelection->Delete(i); + break; + } + } + } + } else { + ipEntrySelection = new(ELeave)CMsvEntrySelection; + if (cmp == QMessageDataComparator::NotEqual) { + getAllMessagesL(iOrdering); + } + } + } else if (pf->_comparatorType == QMessageFilterPrivate::Inclusion) { + QMessageDataComparator::InclusionComparator cmp(static_cast(pf->_comparatorValue)); + if (pf->_ids.count() > 0) { // QMessageIdList + if (cmp == QMessageDataComparator::Includes) { + ipEntrySelection = new(ELeave)CMsvEntrySelection; + for (int i=0; i < pf->_ids.count(); i++) { + long int messageId = pf->_ids[i].toString().toLong(); + CMsvEntry* pEntry = iOwner.retrieveCMsvEntryAndPushToCleanupStack(messageId); + if (pEntry) { + const TMsvEntry& entry = pEntry->Entry(); + if (entry.iType == KUidMsvMessageEntry) { + ipEntrySelection->AppendL(messageId); + } + iOwner.releaseCMsvEntryAndPopFromCleanupStack(pEntry); + } + } + } else { // Excludes + ipEntrySelection = new(ELeave)CMsvEntrySelection; + getAllMessagesL(iOrdering); + for (int i=0; i < pf->_ids.count(); i++) { + long int messageId = pf->_ids[i].toString().toLong(); + for (int i=0; i < ipEntrySelection->Count(); i++) { + if (ipEntrySelection->At(i) == messageId) { + ipEntrySelection->Delete(i); + break; + } + } + } + } + } else { + ipEntrySelection = new(ELeave)CMsvEntrySelection; + if (cmp == QMessageDataComparator::Excludes) { + getAllMessagesL(iOrdering); + } + /*// QMessageFilter + if (cmp == QMessageDataComparator::Includes) { + // TODO: + } else { // Excludes + // TODO: + }*/ + } + } + break; + } + case QMessageFilterPrivate::ParentAccountId: + { + if (pf->_comparatorType == QMessageFilterPrivate::Equality) { // QMessageAccountId + iNumberOfHandledFilters++; + QMessageDataComparator::EqualityComparator cmp(static_cast(pf->_comparatorValue)); + if (cmp == QMessageDataComparator::Equal) { + ipEntrySelection = new(ELeave)CMsvEntrySelection; + + QMessageAccount messageAccount = iOwner.account(pf->_value.toString()); + QMessageFilterPrivate* privateFilter = NULL; + if (filters.count() > iNumberOfHandledFilters) { + privateFilter = QMessageFilterPrivate::implementation(filters[iNumberOfHandledFilters]); + if (privateFilter->_field != QMessageFilterPrivate::StandardFolder) { + privateFilter = NULL; + } else { + iNumberOfHandledFilters++; + } + } + getAccountSpecificMessagesL(messageAccount, iOrdering, privateFilter); + } else { // NotEqual + ipEntrySelection = new(ELeave)CMsvEntrySelection; + + QStringList exludedAccounts; + exludedAccounts << pf->_value.toString(); + + QMessageFilterPrivate* privateFilter = NULL; + for (int i=iNumberOfHandledFilters; i < filters.count(); i++) { + privateFilter = QMessageFilterPrivate::implementation(filters[i]); + if (privateFilter->_field == QMessageFilterPrivate::ParentAccountId && + privateFilter->_comparatorType == QMessageFilterPrivate::Equality) { + cmp = static_cast(privateFilter->_comparatorValue); + if (cmp == QMessageDataComparator::NotEqual) { + exludedAccounts << privateFilter->_value.toString(); + iNumberOfHandledFilters++; + } else { + break; + } + } else { + break; + } + } + + privateFilter = NULL; + if (filters.count() > iNumberOfHandledFilters) { + privateFilter = QMessageFilterPrivate::implementation(filters[iNumberOfHandledFilters]); + if (privateFilter->_field == QMessageFilterPrivate::StandardFolder && + privateFilter->_comparatorType == QMessageFilterPrivate::Equality) { + cmp = static_cast(privateFilter->_comparatorValue); + if (cmp == QMessageDataComparator::Equal) { + iNumberOfHandledFilters++; + } + } else { + privateFilter = NULL; + } + } + + foreach (QMessageAccount value, iOwner.iAccounts) { + if (!exludedAccounts.contains(value.id().toString())) { + getAccountSpecificMessagesL(value, iOrdering, privateFilter); + } + } + } + } else if (pf->_comparatorType == QMessageFilterPrivate::Inclusion) { // QMessageAccountFilter + QMessageDataComparator::InclusionComparator cmp(static_cast(pf->_comparatorValue)); + if (cmp == QMessageDataComparator::Includes) { + //TODO: + } else { // Excludes + //TODO: + } + } + break; + } + case QMessageFilterPrivate::ParentFolderId: + { + if (pf->_comparatorType == QMessageFilterPrivate::Equality) { // QMessageFolderId + QMessageDataComparator::EqualityComparator cmp(static_cast(pf->_comparatorValue)); + if (cmp == QMessageDataComparator::Equal) { + long int folderId = iOwner.folderIdFromQMessageFolderId(QMessageFolderId(pf->_value.toString())); + long int serviceEntryId = iOwner.serviceEntryIdFromQMessageFolderId(QMessageFolderId(pf->_value.toString())); + QMessageAccount messageAccount = iOwner.account(iOwner.accountIdByServiceId(serviceEntryId)); + if (messageAccount.messageTypes() == QMessage::Email) { + iNumberOfHandledFilters++; + CMsvEntryFilter* pFilter = CMsvEntryFilter::NewLC(); + pFilter->SetOrder(iOrdering); + pFilter->SetType(KUidMsvMessageEntry); + // Get POP3 or IMAP messages from folder + CMsvEntrySelection* pEntrySelection1 = new(ELeave)CMsvEntrySelection; + CleanupStack::PushL(pEntrySelection1); + pFilter->SetService(messageAccount.d_ptr->_service1EntryId); + ipMsvSession->GetChildIdsL(folderId, *pFilter, *pEntrySelection1); + // Get SMTP messages from folder + CMsvEntrySelection* pEntrySelection2 = new(ELeave)CMsvEntrySelection; + CleanupStack::PushL(pEntrySelection2); + pFilter->SetService(messageAccount.d_ptr->_service2EntryId); + ipMsvSession->GetChildIdsL(folderId, *pFilter, *pEntrySelection2); + if (pEntrySelection1->Count() > 0 && pEntrySelection2->Count() > 0) { + ipEntrySelection = pEntrySelection1; + for (int i = 0; i < pEntrySelection2->Count(); i++) { + ipEntrySelection->AppendL(pEntrySelection2->At(i)); + } + CleanupStack::PopAndDestroy(pEntrySelection2); + CleanupStack::Pop(pEntrySelection1); + } else if (pEntrySelection1->Count() > 0) { + ipEntrySelection = pEntrySelection1; + CleanupStack::PopAndDestroy(pEntrySelection2); + CleanupStack::Pop(pEntrySelection1); + iResultCorrectlyOrdered = true; + } else { + // (pEntrySelection2->Count() > 0) or both selections are empty + ipEntrySelection = pEntrySelection2; + CleanupStack::Pop(pEntrySelection2); + CleanupStack::PopAndDestroy(pEntrySelection1); + iResultCorrectlyOrdered = true; + } + CleanupStack::PopAndDestroy(pFilter); + } else if (messageAccount.messageTypes() == QMessage::Sms || messageAccount.messageTypes() == QMessage::Mms) { + iNumberOfHandledFilters++; + CMsvEntry* pEntry = iOwner.retrieveCMsvEntryAndPushToCleanupStack(serviceEntryId); + if (pEntry) { + TUid mtm = pEntry->Entry().iMtm; + iOwner.releaseCMsvEntryAndPopFromCleanupStack(pEntry); + CMsvEntryFilter* pFilter = CMsvEntryFilter::NewLC(); + pFilter->SetMtm(mtm); + pFilter->SetOrder(iOrdering); + pFilter->SetType(KUidMsvMessageEntry); + ipEntrySelection = new(ELeave)CMsvEntrySelection; + ipMsvSession->GetChildIdsL(folderId, *pFilter, *ipEntrySelection); + CleanupStack::PopAndDestroy(pFilter); + } + iResultCorrectlyOrdered = true; + } + } else { // NotEqual + // TODO: + } + } else if (pf->_comparatorType == QMessageFilterPrivate::Inclusion) { // QMessageFolderFilter + QMessageDataComparator::InclusionComparator cmp(static_cast(pf->_comparatorValue)); + if (cmp == QMessageDataComparator::Includes) { + // TODO: + } else { // Excludes + // TODO: + } + } + break; + } + case QMessageFilterPrivate::AncestorFolderIds: + { + iNumberOfHandledFilters++; + if (pf->_comparatorType == QMessageFilterPrivate::Inclusion) { + QMessageDataComparator::InclusionComparator cmp(static_cast(pf->_comparatorValue)); + if (!pf->_value.isNull()) { // QMessageFolderId + if (cmp == QMessageDataComparator::Includes) { + // TODO: + } else { // Excludes + // TODO: + } + } else { // QMessageFolderFilter + if (cmp == QMessageDataComparator::Includes) { + // TODO: + } else { // Excludes + // TODO: + } + } + } + break; + } + case QMessageFilterPrivate::Type: + { + iNumberOfHandledFilters++; + QMessageFilterPrivate* privateFilter = NULL; + // Check if next filter is StandardFolder filter + if (filters.count() > iNumberOfHandledFilters) { + privateFilter = QMessageFilterPrivate::implementation(filters[iNumberOfHandledFilters]); + if (privateFilter->_field != QMessageFilterPrivate::StandardFolder) { + privateFilter = NULL; + } else { + iNumberOfHandledFilters++; + } + } + if (pf->_comparatorType == QMessageFilterPrivate::Equality) { // QMessage::Type + QMessage::Type type = static_cast(pf->_value.toInt()); + QMessageDataComparator::EqualityComparator cmp(static_cast(pf->_comparatorValue)); + if (cmp == QMessageDataComparator::Equal) { + ipEntrySelection = new(ELeave)CMsvEntrySelection; + QMessageAccountIdList accountIds = iOwner.accountsByType(type); + for (int i = 0; i < accountIds.count(); i++) { + QMessageAccount messageAccount = iOwner.account(accountIds[i]); + getAccountSpecificMessagesL(messageAccount, iOrdering, privateFilter); + } + } else { // NotEqual + foreach (QMessageAccount value, iOwner.iAccounts) { + if (!(value.messageTypes() & type)) { + getAccountSpecificMessagesL(value, iOrdering, privateFilter); + } + } + } + } else if (pf->_comparatorType == QMessageFilterPrivate::Inclusion) { // QMessage::TypeFlags + QMessage::TypeFlags typeFlags = static_cast(pf->_value.toInt()); + QMessageDataComparator::InclusionComparator cmp(static_cast(pf->_comparatorValue)); + if (cmp == QMessageDataComparator::Includes) { + foreach (QMessageAccount value, iOwner.iAccounts) { + if (value.messageTypes() | typeFlags) { + getAccountSpecificMessagesL(value, iOrdering, privateFilter); + } + } + } else { // Excludes + foreach (QMessageAccount value, iOwner.iAccounts) { + if (!(value.messageTypes() & typeFlags)) { + getAccountSpecificMessagesL(value, iOrdering, privateFilter); + } + } + } + } + break; + } + case QMessageFilterPrivate::StandardFolder: + { + iNumberOfHandledFilters++; + QMessageDataComparator::EqualityComparator cmp(static_cast(pf->_comparatorValue)); + QMessage::StandardFolder standardFolder = static_cast(pf->_value.toInt()); + TMsvId stdFolderId = iOwner.standardFolderId(standardFolder); + if (cmp == QMessageDataComparator::Equal) { + CMsvEntry* pStandardFolderContext = iOwner.retrieveCMsvEntryAndPushToCleanupStack(stdFolderId); + if (pStandardFolderContext) { + pStandardFolderContext->SetSortTypeL(iOrdering); + ipEntrySelection = pStandardFolderContext->ChildrenL(); + iOwner.releaseCMsvEntryAndPopFromCleanupStack(pStandardFolderContext); + } + iResultCorrectlyOrdered = true; + } else { // NotEqual + ipEntrySelection = new(ELeave)CMsvEntrySelection; + QMessage::StandardFolder i = QMessage::InboxFolder; + while (i <= QMessage::TrashFolder) { + if (i != standardFolder) { + CMsvEntry* pStandardFolderContext = iOwner.retrieveCMsvEntryAndPushToCleanupStack(iOwner.standardFolderId(i)); + if (pStandardFolderContext) { + pStandardFolderContext->SetSortTypeL(iOrdering); + CMsvEntrySelection* pEntries = pStandardFolderContext->ChildrenL(); + CleanupStack::PushL(pEntries); + for (int i = 0; i < pEntries->Count(); i++) { + ipEntrySelection->AppendL(pEntries->At(i)); + } + CleanupStack::PopAndDestroy(pEntries); + iOwner.releaseCMsvEntryAndPopFromCleanupStack(pStandardFolderContext); + } + } + i = static_cast(static_cast(i) + 1); + } + } + break; + } + case QMessageFilterPrivate::ParentAccountIdFilter: + case QMessageFilterPrivate::ParentFolderIdFilter: + case QMessageFilterPrivate::TimeStamp: + case QMessageFilterPrivate::ReceptionTimeStamp: + case QMessageFilterPrivate::Sender: + case QMessageFilterPrivate::Recipients: + case QMessageFilterPrivate::Subject: + case QMessageFilterPrivate::Status: + case QMessageFilterPrivate::Priority: + case QMessageFilterPrivate::Size: + case QMessageFilterPrivate::None: + break; + } + + TMsvPartList partlist = 0; + TPtrC16 value(KNullDesC); + if (body.isEmpty()) { + if (iNumberOfHandledFilters < filters.count()) { + pf = QMessageFilterPrivate::implementation(filters[iNumberOfHandledFilters]); + + if (pf->_matchFlags & QMessageDataComparator::MatchCaseSensitive) { + partlist |= KMsvFindCaseSensitive; + } + if (pf->_matchFlags & QMessageDataComparator::MatchFullWord) { + partlist |= KMsvFindWholeWord; + } + + switch (pf->_field) { + case QMessageFilterPrivate::Sender: + { + if (pf->_comparatorType == QMessageFilterPrivate::Equality) { + QMessageDataComparator::EqualityComparator cmp(static_cast(pf->_comparatorValue)); + if (cmp == QMessageDataComparator::Equal) { + if (pf->_value.toString().length() > 0) { + value.Set(reinterpret_cast(pf->_value.toString().utf16())); + partlist |= KMsvMessagePartOriginator; + iNumberOfHandledFilters++; + } + } else { // NotEqual + // TODO: + } + } else if (pf->_comparatorType == QMessageFilterPrivate::Inclusion) { + QMessageDataComparator::InclusionComparator cmp(static_cast(pf->_comparatorValue)); + if (cmp == QMessageDataComparator::Includes) { + // TODO: + } else { // Excludes + // TODO: + } + } + break; + } + case QMessageFilterPrivate::Recipients: // to, cc & bcc fields + { + if (pf->_comparatorType == QMessageFilterPrivate::Inclusion) { + QMessageDataComparator::InclusionComparator cmp(static_cast(pf->_comparatorValue)); + if (cmp == QMessageDataComparator::Includes) { + if (pf->_value.toString().length() > 0) { + value.Set(reinterpret_cast(pf->_value.toString().utf16())); + partlist |= KMsvMessagePartRecipient; + iNumberOfHandledFilters++; + } + } else { // Excludes + //TODO: + } + } + break; + } + case QMessageFilterPrivate::Subject: + { + if (pf->_comparatorType == QMessageFilterPrivate::Equality) { + QMessageDataComparator::EqualityComparator cmp(static_cast(pf->_comparatorValue)); + if (cmp == QMessageDataComparator::Equal) { + if (pf->_value.toString().length() > 0) { + value.Set(reinterpret_cast(pf->_value.toString().utf16())); + partlist |= KMsvMessagePartDescription; + iNumberOfHandledFilters++; + } + } else { // NotEqual + // TODO: + } + } else if (pf->_comparatorType == QMessageFilterPrivate::Inclusion) { + QMessageDataComparator::InclusionComparator cmp(static_cast(pf->_comparatorValue)); + if (cmp == QMessageDataComparator::Includes) { + // TODO: + } else { // Excludes + // TODO: + } + } + break; + } + case QMessageFilterPrivate::TimeStamp: + { + if (pf->_comparatorType == QMessageFilterPrivate::Equality) { + QMessageDataComparator::EqualityComparator cmp(static_cast(pf->_comparatorValue)); + if (cmp == QMessageDataComparator::Equal) { + // TODO: + } else { // NotEqual + // TODO: + } + } else if (pf->_comparatorType == QMessageFilterPrivate::Relation) { + QMessageDataComparator::RelationComparator cmp(static_cast(pf->_comparatorValue)); + if (cmp == QMessageDataComparator::LessThan) { + // TODO: + } else if (cmp == QMessageDataComparator::LessThanEqual) { + // TODO: + } else if (cmp == QMessageDataComparator::GreaterThan) { + // TODO: + } else { // GreaterThanEqual + // TODO: + } + } + break; + } + case QMessageFilterPrivate::ReceptionTimeStamp: + { + if (pf->_comparatorType == QMessageFilterPrivate::Equality) { + QMessageDataComparator::EqualityComparator cmp(static_cast(pf->_comparatorValue)); + if (cmp == QMessageDataComparator::Equal) { + value.Set(reinterpret_cast(pf->_value.toString().utf16())); + partlist |= KMsvMessagePartDate; + iNumberOfHandledFilters++; + } else { // NotEqual + // TODO: + } + } else if (pf->_comparatorType == QMessageFilterPrivate::Relation) { + QMessageDataComparator::RelationComparator cmp(static_cast(pf->_comparatorValue)); + if (cmp == QMessageDataComparator::LessThan) { + // TODO: + } else if (cmp == QMessageDataComparator::LessThanEqual) { + // TODO: + } else if (cmp == QMessageDataComparator::GreaterThan) { + // TODO: + } else { // GreaterThanEqual + // TODO: + } + } + break; + } + case QMessageFilterPrivate::Status: + { + if (pf->_comparatorType == QMessageFilterPrivate::Equality) { + QMessageDataComparator::EqualityComparator cmp(static_cast(pf->_comparatorValue)); + if (cmp == QMessageDataComparator::Equal) { + // TODO: + } else { // NotEqual + // TODO: + } + } else if (pf->_comparatorType == QMessageFilterPrivate::Inclusion) { + QMessageDataComparator::InclusionComparator cmp(static_cast(pf->_comparatorValue)); + if (cmp == QMessageDataComparator::Includes) { + // TODO: + } else { // Excludes + // TODO: + } + } + break; + } + case QMessageFilterPrivate::Priority: + { + QMessageDataComparator::EqualityComparator cmp(static_cast(pf->_comparatorValue)); + if (cmp == QMessageDataComparator::Equal) { + // TODO: + } else { // NotEqual + // TODO: + } + break; + } + case QMessageFilterPrivate::Size: + { + if (pf->_comparatorType == QMessageFilterPrivate::Equality) { + QMessageDataComparator::EqualityComparator cmp(static_cast(pf->_comparatorValue)); + if (cmp == QMessageDataComparator::Equal) { + // TODO: + } else { // NotEqual + // TODO: + } + } else if (pf->_comparatorType == QMessageFilterPrivate::Relation) { + QMessageDataComparator::RelationComparator cmp(static_cast(pf->_comparatorValue)); + if (cmp == QMessageDataComparator::LessThan) { + // TODO: + } else if (cmp == QMessageDataComparator::LessThanEqual) { + // TODO: + } else if (cmp == QMessageDataComparator::GreaterThan) { + // TODO: + } else { // GreaterThanEqual + // TODO: + } + } + break; + } + case QMessageFilterPrivate::ParentAccountIdFilter: + case QMessageFilterPrivate::ParentFolderIdFilter: + case QMessageFilterPrivate::Id: + case QMessageFilterPrivate::ParentFolderId: + case QMessageFilterPrivate::AncestorFolderIds: + case QMessageFilterPrivate::ParentAccountId: + case QMessageFilterPrivate::Type: + case QMessageFilterPrivate::StandardFolder: + case QMessageFilterPrivate::None: + break; + } + } + } else { + // Body + if (matchFlags & QMessageDataComparator::MatchCaseSensitive) { + partlist |= KMsvFindCaseSensitive; + } + if (matchFlags & QMessageDataComparator::MatchFullWord) { + partlist |= KMsvFindWholeWord; + } + + value.Set(reinterpret_cast(body.utf16())); + partlist |= KMsvMessagePartBody; + } + + if (iResultCorrectlyOrdered && iOrdering.Sorting() == EMsvSortByNone && !iOrdering.GroupingOn()) { + iResultCorrectlyOrdered = false; + } + + if (!ipEntrySelection) { + ipEntrySelection = new(ELeave)CMsvEntrySelection; + getAllMessagesL(iOrdering); + } + + if (partlist != 0 && ipEntrySelection->Count() > 0) { + ipMsvFindOperation = CMsvFindOperation::FindInSelectionL(*ipMsvSession, value, *ipEntrySelection, partlist, iStatus); + if (!IsActive()) { + SetActive(); + } + } else { + iIdList = QMessageIdList(); + for (int i=0; i < ipEntrySelection->Count(); i++) { + iIdList.append(QMessageId(QString::number((*ipEntrySelection)[i]))); + } + iTimer.After(iStatus, 100); + if (!IsActive()) { + SetActive(); + } + } +} + +void CMessagesFindOperation::RunL() +{ + if (iStatus.Int() != KErrNone) { + iOwner.filterAndOrderMessagesReady(false, iOperationId, QMessageIdList(), 0, false); + } else { + if (ipMsvFindOperation) { + const CMsvFindResultSelection& findResultSelection = ipMsvFindOperation->GetFindResult(); + QMessageIdList msgIds; + for (int i=0; i < findResultSelection.Count(); i++) { + msgIds.append(QMessageId(QString::number(findResultSelection[i].iId))); + } + iOwner.filterAndOrderMessagesReady(true, iOperationId, msgIds, iNumberOfHandledFilters, iResultCorrectlyOrdered); + } else { + iOwner.filterAndOrderMessagesReady(true, iOperationId, iIdList, iNumberOfHandledFilters, iResultCorrectlyOrdered); + } + } + +} + +void CMessagesFindOperation::getAllMessagesL(const TMsvSelectionOrdering sortOrder) +{ + // Get all messages from every known account + foreach (QMessageAccount value, iOwner.iAccounts) { + getAccountSpecificMessagesL(value, sortOrder); + } +} + +void CMessagesFindOperation::getAccountSpecificMessagesL(QMessageAccount& messageAccount, const TMsvSelectionOrdering sortOrder, QMessageFilterPrivate* privateFolderFilter) +{ + CMsvEntry* pService = iOwner.retrieveCMsvEntryAndPushToCleanupStack(messageAccount.d_ptr->_service1EntryId); + if (pService) { + TUid mtmUid = pService->Entry().iMtm; + iOwner.releaseCMsvEntryAndPopFromCleanupStack(pService); + getServiceSpecificMessagesL(messageAccount.d_ptr->_service1EntryId, sortOrder, privateFolderFilter); + } + + TMsvId serviceId = messageAccount.d_ptr->_service2EntryId; + if (serviceId != 0) { + CMsvEntry* pService = iOwner.retrieveCMsvEntryAndPushToCleanupStack(serviceId); + if (pService) { + TUid mtmUid = pService->Entry().iMtm; + iOwner.releaseCMsvEntryAndPopFromCleanupStack(pService); + int count = ipEntrySelection->Count(); + getServiceSpecificMessagesL(messageAccount.d_ptr->_service2EntryId, sortOrder, privateFolderFilter); + if (ipEntrySelection->Count() > count) { + iResultCorrectlyOrdered = false; + } + } + } +} + +void CMessagesFindOperation::getServiceSpecificMessagesL(TMsvId serviceId, const TMsvSelectionOrdering sortOrder, QMessageFilterPrivate* privateFolderFilter) +{ + if (privateFolderFilter) { + QMessageDataComparator::EqualityComparator cmp2(static_cast(privateFolderFilter->_comparatorValue)); + QMessage::StandardFolder standardFolder = static_cast(privateFolderFilter->_value.toInt()); + if (cmp2 == QMessageDataComparator::Equal) { + iResultCorrectlyOrdered = true; + getServiceSpecificMessagesFromFolderL(serviceId, sortOrder, iOwner.standardFolderId(standardFolder)); + } else { // NotEqual + // Loop through all standard folders + QMessage::StandardFolder i = QMessage::InboxFolder; + while (i <= QMessage::TrashFolder) { + if (i != standardFolder) { + getServiceSpecificMessagesFromFolderL(serviceId, sortOrder, iOwner.standardFolderId(i)); + } + i = static_cast(static_cast(i) + 1); + } + } + } + else { + // List all service specific messages from Standard Folders + QMessage::StandardFolder i = QMessage::InboxFolder; + while (i <= QMessage::TrashFolder) { + getServiceSpecificMessagesFromFolderL(serviceId, sortOrder, iOwner.standardFolderId(i)); + i = static_cast(static_cast(i) + 1); + } + + // List all service specific messages from user created folders + CMsvEntry* pEntry = iOwner.retrieveCMsvEntryAndPushToCleanupStack(serviceId); + if (pEntry) { + TUid mtmUid = pEntry->Entry().iMtm; + if (mtmUid == KUidMsgTypeSMS || mtmUid == KUidMsgTypeMultimedia || mtmUid == KUidMsgTypeSMTP) { + pEntry->SetEntryL(KDocumentsEntryIdValue); + CMsvEntrySelection* pSelection = pEntry->ChildrenWithTypeL(KUidMsvFolderEntry); + CleanupStack::PushL(pSelection); + for(TInt i = 0; i < pSelection->Count(); i++) { + CMsvEntryFilter* pFilter = CMsvEntryFilter::NewLC(); + if (mtmUid == KUidMsgTypeSMS || mtmUid == KUidMsgTypeMultimedia) { + pFilter->SetMtm(mtmUid); + } else { + pFilter->SetService(serviceId); + } + pFilter->SetOrder(sortOrder); + pFilter->SetType(KUidMsvMessageEntry); + CMsvEntrySelection* pEntries = new(ELeave) CMsvEntrySelection;; + CleanupStack::PushL(pEntries); + ipMsvSession->GetChildIdsL(pSelection->At(i), *pFilter, *pEntries); + for(TInt j = 0; j < pEntries->Count(); j++) { + ipEntrySelection->AppendL(pEntries->At(j)); + } + CleanupStack::PopAndDestroy(pEntries); + CleanupStack::PopAndDestroy(pFilter); + } + CleanupStack::PopAndDestroy(pSelection); + } + iOwner.releaseCMsvEntryAndPopFromCleanupStack(pEntry); + } + } +} + +void CMessagesFindOperation::getServiceSpecificMessagesFromFolderL(TMsvId serviceId, const TMsvSelectionOrdering sortOrder, TMsvId standardFolderId) +{ + CMsvEntry* pEntry = iOwner.retrieveCMsvEntryAndPushToCleanupStack(serviceId); + if (pEntry) { + pEntry->SetSortTypeL(sortOrder); + TUid mtmUid = pEntry->Entry().iMtm; + if (mtmUid == KUidMsgTypePOP3) { + if (standardFolderId == KMsvGlobalInBoxIndexEntryIdValue) { + // POP3 service has (Inbox) messages in service root + CMsvEntrySelection* pMessageEntries = pEntry->ChildrenWithTypeL(KUidMsvMessageEntry); + CleanupStack::PushL(pMessageEntries); + for (int i = 0; i < pMessageEntries->Count(); i++) { + ipEntrySelection->AppendL(pMessageEntries->At(i)); + } + CleanupStack::PopAndDestroy(pMessageEntries); + } + } else if (mtmUid == KUidMsgTypeIMAP4) { + if (standardFolderId == KMsvGlobalInBoxIndexEntryIdValue) { + // All IMAP4 folders are treated as Inbox folders + // IMAP4 service has folders in service root + CMsvEntrySelection* pFolderEntries = pEntry->ChildrenWithTypeL(KUidMsvFolderEntry); + CleanupStack::PushL(pFolderEntries); + for (int i = 0; i < pFolderEntries->Count(); i++) { + pEntry->SetEntryL(pFolderEntries->At(i)); + CMsvEntrySelection* pMessageEntries = pEntry->ChildrenWithTypeL(KUidMsvMessageEntry); + CleanupStack::PushL(pMessageEntries); + for (int j = 0; j < pMessageEntries->Count(); j++) { + ipEntrySelection->AppendL(pMessageEntries->At(j)); + } + CleanupStack::PopAndDestroy(pMessageEntries); + } + CleanupStack::PopAndDestroy(pFolderEntries); + } + } else { + // Handle SMS, MMS & SMTP Standard Folders + CMsvEntryFilter* pFilter = CMsvEntryFilter::NewLC(); + if (mtmUid == KUidMsgTypeSMTP) { + // There maybe multiple SMTP Services + // => Messages must be queried using ServiceId + pFilter->SetService(serviceId); + } else { + // There is only one service per SMS and per MMS + // => Messages can be queried using MTM Uid + pFilter->SetMtm(mtmUid); + } + pFilter->SetOrder(sortOrder); + pFilter->SetType(KUidMsvMessageEntry); + CMsvEntrySelection* pEntries = new(ELeave) CMsvEntrySelection;; + CleanupStack::PushL(pEntries); + ipMsvSession->GetChildIdsL(standardFolderId, *pFilter, *pEntries); + for (int i = 0; i < pEntries->Count(); i++) { + ipEntrySelection->AppendL(pEntries->At(i)); + } + CleanupStack::PopAndDestroy(pEntries); + CleanupStack::PopAndDestroy(pFilter); + } + iOwner.releaseCMsvEntryAndPopFromCleanupStack(pEntry); + } +} + + +QTM_END_NAMESPACE