File indexing completed on 2024-12-22 05:05:26

0001 /*
0002    SPDX-FileCopyrightText: 2012-2024 Laurent Montel <montel@kde.org>
0003 
0004    SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "exportmailjobinterface.h"
0008 #include "importexportmailutil.h"
0009 
0010 #include <MailCommon/FilterImporterExporter>
0011 
0012 #include <MailTransport/TransportManager>
0013 
0014 #include <KLocalizedString>
0015 #include <KZip>
0016 #include <QTemporaryFile>
0017 
0018 #include "pimdataexportcore_debug.h"
0019 #include "resourceconverterimpl.h"
0020 #include <KMime/Message>
0021 #include <QDir>
0022 #include <QFile>
0023 #include <QRegularExpression>
0024 #include <QStandardPaths>
0025 #include <QTimer>
0026 
0027 #include <KIdentityManagementCore/Identity>
0028 
0029 ExportMailJobInterface::ExportMailJobInterface(QObject *parent, Utils::StoredTypes typeSelected, ArchiveStorage *archiveStorage, int numberOfStep)
0030     : AbstractImportExportJob(parent, archiveStorage, typeSelected, numberOfStep)
0031 {
0032 }
0033 
0034 ExportMailJobInterface::~ExportMailJobInterface() = default;
0035 
0036 bool ExportMailJobInterface::checkBackupType(Utils::StoredType type) const
0037 {
0038     return mTypeSelected & type;
0039 }
0040 
0041 void ExportMailJobInterface::start()
0042 {
0043     Q_EMIT title(i18n("Start export KMail settings..."));
0044     createProgressDialog(i18n("Export KMail settings"));
0045     if (checkBackupType(Utils::Identity)) {
0046         QTimer::singleShot(0, this, &ExportMailJobInterface::slotCheckBackupIdentity);
0047     } else if (checkBackupType(Utils::MailTransport)) {
0048         QTimer::singleShot(0, this, &ExportMailJobInterface::slotCheckBackupMailTransport);
0049     } else if (checkBackupType(Utils::Config)) {
0050         QTimer::singleShot(0, this, &ExportMailJobInterface::slotCheckBackupConfig);
0051     } else if (checkBackupType(Utils::Mails)) {
0052         QTimer::singleShot(0, this, &ExportMailJobInterface::slotCheckBackupMails);
0053     } else if (checkBackupType(Utils::Resources)) {
0054         QTimer::singleShot(0, this, &ExportMailJobInterface::slotCheckBackupResources);
0055     } else {
0056         Q_EMIT jobFinished();
0057     }
0058 }
0059 
0060 void ExportMailJobInterface::slotCheckBackupIdentity()
0061 {
0062     if (checkBackupType(Utils::Identity)) {
0063         backupIdentity();
0064         increaseProgressDialog();
0065         if (wasCanceled()) {
0066             Q_EMIT jobFinished();
0067             return;
0068         }
0069     }
0070     QTimer::singleShot(0, this, &ExportMailJobInterface::slotCheckBackupMailTransport);
0071 }
0072 
0073 void ExportMailJobInterface::slotCheckBackupMailTransport()
0074 {
0075     if (checkBackupType(Utils::MailTransport)) {
0076         backupTransports();
0077         increaseProgressDialog();
0078         if (wasCanceled()) {
0079             Q_EMIT jobFinished();
0080             return;
0081         }
0082     }
0083     QTimer::singleShot(0, this, &ExportMailJobInterface::slotCheckBackupConfig);
0084 }
0085 
0086 void ExportMailJobInterface::slotCheckBackupConfig()
0087 {
0088     if (checkBackupType(Utils::Config)) {
0089         backupConfig();
0090         increaseProgressDialog();
0091         if (wasCanceled()) {
0092             Q_EMIT jobFinished();
0093             return;
0094         }
0095     }
0096     QTimer::singleShot(0, this, &ExportMailJobInterface::slotCheckBackupMails);
0097 }
0098 
0099 void ExportMailJobInterface::slotCheckBackupMails()
0100 {
0101     mAkonadiInstanceInfo = listOfResource();
0102     if (checkBackupType(Utils::Mails)) {
0103         increaseProgressDialog();
0104         backupFolderAttributes();
0105         return;
0106     }
0107     QTimer::singleShot(0, this, &ExportMailJobInterface::slotCheckBackupResources);
0108 }
0109 
0110 void ExportMailJobInterface::backupFolderAttributes()
0111 {
0112     setProgressDialogLabel(i18n("Backing up Folder Attributes..."));
0113     connect(this, &ExportMailJobInterface::exportAttributeDone, this, [this]() {
0114         setProgressDialogLabel(i18n("Backing up Mails..."));
0115         emitInfo(i18n("Start export resource..."));
0116         QTimer::singleShot(0, this, &ExportMailJobInterface::slotWriteNextArchiveResource);
0117     });
0118     exportFolderAttributes();
0119 }
0120 
0121 void ExportMailJobInterface::backupTransports()
0122 {
0123     setProgressDialogLabel(i18n("Backing up transports..."));
0124 
0125     const QString mailtransportsStr(QStringLiteral("mailtransports"));
0126     const QString maitransportsrc = QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + QLatin1Char('/') + mailtransportsStr;
0127     if (!QFileInfo::exists(maitransportsrc)) {
0128         emitInfo(i18n("Transports backup done."));
0129     } else {
0130         KSharedConfigPtr mailtransportsConfig = KSharedConfig::openConfig(mailtransportsStr);
0131 
0132         QTemporaryFile tmp;
0133         tmp.open();
0134         KConfig *config = mailtransportsConfig->copyTo(tmp.fileName());
0135 
0136         config->sync();
0137         const bool fileAdded = archive()->addLocalFile(tmp.fileName(), Utils::transportsPath() + QStringLiteral("mailtransports"));
0138         delete config;
0139         if (fileAdded) {
0140             emitInfo(i18n("Transports backup done."));
0141         } else {
0142             emitError(i18n("Transport file cannot be added to backup file."));
0143         }
0144     }
0145 }
0146 
0147 void ExportMailJobInterface::slotCheckBackupResources()
0148 {
0149     if (checkBackupType(Utils::Resources)) {
0150         backupResources();
0151         increaseProgressDialog();
0152         if (wasCanceled()) {
0153             Q_EMIT jobFinished();
0154             return;
0155         }
0156     }
0157     Q_EMIT jobFinished();
0158 }
0159 
0160 QString ExportMailJobInterface::applicationName() const
0161 {
0162     return QStringLiteral("[KMail]");
0163 }
0164 
0165 void ExportMailJobInterface::backupConfig()
0166 {
0167     setProgressDialogLabel(i18n("Backing up config..."));
0168 
0169     exportFilters();
0170 
0171     backupUiRcFile(QStringLiteral("sieveeditorui.rc"), QStringLiteral("sieveeditor"));
0172     backupUiRcFile(QStringLiteral("kmreadermainwin.rc"), QStringLiteral("kmail2"));
0173     backupUiRcFile(QStringLiteral("kmcomposerui.rc"), QStringLiteral("kmail2"));
0174     backupUiRcFile(QStringLiteral("kmmainwin.rc"), QStringLiteral("kmail2"));
0175     backupUiRcFile(QStringLiteral("kmail_part.rc"), QStringLiteral("kmail2"));
0176     backupUiRcFile(QStringLiteral("kontactsummary_part.rc"), QStringLiteral("kontactsummary"));
0177     backupUiRcFile(QStringLiteral("kontactui.rc"), QStringLiteral("kontact"));
0178     backupUiRcFile(QStringLiteral("kleopatra.rc"), QStringLiteral("kleopatra"));
0179     backupUiRcFile(QStringLiteral("headerthemeeditorui.rc"), QStringLiteral("headerthemeeditor"));
0180     backupUiRcFile(QStringLiteral("contactthemeeditorui.rc"), QStringLiteral("contactthemeeditor"));
0181     backupUiRcFile(QStringLiteral("contactprintthemeeditorui.rc"), QStringLiteral("contactprintthemeeditor"));
0182     backupUiRcFile(QStringLiteral("kwatchgnupgui.rc"), QStringLiteral("kwatchgnupg"));
0183     backupUiRcFile(QStringLiteral("akonadiconsoleui.rc"), QStringLiteral("akonadiconsole"));
0184 
0185     backupConfigFile(QStringLiteral("kabldaprc"));
0186     backupConfigFile(QStringLiteral("kmailsnippetrc"));
0187     backupConfigFile(QStringLiteral("sievetemplaterc"));
0188     backupConfigFile(QStringLiteral("customtemplatesrc"));
0189     backupConfigFile(QStringLiteral("kontactrc"));
0190     backupConfigFile(QStringLiteral("kontact_summaryrc"));
0191     backupConfigFile(QStringLiteral("storageservicerc"));
0192     backupConfigFile(QStringLiteral("kpimbalooblacklist"));
0193     backupConfigFile(QStringLiteral("kleopatrarc"));
0194     backupConfigFile(QStringLiteral("sieveeditorrc"));
0195     backupConfigFile(QStringLiteral("kwatchgnupgrc"));
0196     backupConfigFile(QStringLiteral("pimpluginsrc"));
0197     backupConfigFile(QStringLiteral("texttospeechrc"));
0198     backupConfigFile(QStringLiteral("kleopatracertificateselectiondialogrc"));
0199     backupConfigFile(QStringLiteral("dkimsettingsrc"));
0200     backupConfigFile(QStringLiteral("confirmbeforedeletingrc"));
0201 
0202     // Notify file config
0203     backupConfigFile(QStringLiteral("akonadi_mailfilter_agent.notifyrc"));
0204     backupConfigFile(QStringLiteral("akonadi_sendlater_agent.notifyrc"));
0205     backupConfigFile(QStringLiteral("akonadi_archivemail_agent.notifyrc"));
0206     backupConfigFile(QStringLiteral("kmail2.notifyrc"));
0207     backupConfigFile(QStringLiteral("akonadi_newmailnotifier_agent.notifyrc"));
0208     backupConfigFile(QStringLiteral("akonadi_maildispatcher_agent.notifyrc"));
0209     backupConfigFile(QStringLiteral("akonadi_followupreminder_agent.notifyrc"));
0210     backupConfigFile(QStringLiteral("messagevieweradblockrc"));
0211     backupConfigFile(QStringLiteral("messageviewer.notifyrc"));
0212     backupConfigFile(QStringLiteral("akonadi_newmailnotifier_agentrc"));
0213 
0214     const QString folderMailArchiveStr(QStringLiteral("foldermailarchiverc"));
0215     const QString folderMailArchiverc = QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + QLatin1Char('/') + folderMailArchiveStr;
0216     if (QFileInfo::exists(folderMailArchiverc)) {
0217         KSharedConfigPtr archivemailrc = KSharedConfig::openConfig(folderMailArchiveStr);
0218 
0219         QTemporaryFile tmp;
0220         tmp.open();
0221 
0222         KConfig *archiveConfig = archivemailrc->copyTo(tmp.fileName());
0223         const QStringList archiveList = archiveConfig->groupList().filter(QRegularExpression(QStringLiteral("FolderArchiveAccount")));
0224 
0225         for (const QString &str : archiveList) {
0226             KConfigGroup oldGroup = archiveConfig->group(str);
0227             const qint64 id = oldGroup.readEntry("topLevelCollectionId", -1);
0228             if (id != -1) {
0229                 const QString realPath = convertToFullCollectionPath(id);
0230                 if (!realPath.isEmpty()) {
0231                     oldGroup.writeEntry(QStringLiteral("topLevelCollectionId"), realPath);
0232                 }
0233             }
0234         }
0235         archiveConfig->sync();
0236 
0237         backupFile(tmp.fileName(), Utils::configsPath(), folderMailArchiveStr);
0238         delete archiveConfig;
0239     }
0240     const QString unifiedMailBoxStr(QStringLiteral("akonadi_unifiedmailbox_agentrc"));
0241     const QString unifiedMailBoxrc = QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + QLatin1Char('/') + unifiedMailBoxStr;
0242     if (QFileInfo::exists(unifiedMailBoxrc)) {
0243         KSharedConfigPtr mboxrc = KSharedConfig::openConfig(unifiedMailBoxrc);
0244 
0245         QTemporaryFile tmp;
0246         tmp.open();
0247 
0248         KConfig *archiveConfig = mboxrc->copyTo(tmp.fileName());
0249         auto group = archiveConfig->group(QStringLiteral("UnifiedMailboxes"));
0250         const auto boxGroups = group.groupList();
0251         for (const auto &str : boxGroups) {
0252             KConfigGroup oldGroup = group.group(str);
0253 
0254             const qint64 id = oldGroup.readEntry("collectionId", -1);
0255             if (id != -1) {
0256                 const QString realPath = convertToFullCollectionPath(id);
0257                 if (!realPath.isEmpty()) {
0258                     oldGroup.writeEntry(QStringLiteral("collectionId"), realPath);
0259                 }
0260             }
0261             const QString sourceKey(QStringLiteral("sources"));
0262             convertCollectionListToRealPath(oldGroup, sourceKey);
0263         }
0264         archiveConfig->sync();
0265 
0266         backupFile(tmp.fileName(), Utils::configsPath(), unifiedMailBoxStr);
0267         delete archiveConfig;
0268     }
0269 
0270     const QString archiveMailAgentConfigurationStr(QStringLiteral("akonadi_archivemail_agentrc"));
0271     const QString archiveMailAgentconfigurationrc =
0272         QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + QLatin1Char('/') + archiveMailAgentConfigurationStr;
0273     if (QFileInfo::exists(archiveMailAgentconfigurationrc)) {
0274         KSharedConfigPtr archivemailrc = KSharedConfig::openConfig(archiveMailAgentConfigurationStr);
0275 
0276         QTemporaryFile tmp;
0277         tmp.open();
0278 
0279         KConfig *archiveConfig = archivemailrc->copyTo(tmp.fileName());
0280         const QStringList archiveList = archiveConfig->groupList().filter(QRegularExpression(QStringLiteral("ArchiveMailCollection \\d+")));
0281         const QString archiveGroupPattern = QStringLiteral("ArchiveMailCollection ");
0282 
0283         for (const QString &str : archiveList) {
0284             bool found = false;
0285             const int collectionId = QStringView(str).right(str.length() - archiveGroupPattern.length()).toInt(&found);
0286             if (found) {
0287                 KConfigGroup oldGroup = archiveConfig->group(str);
0288                 const QString realPath = convertToFullCollectionPath(collectionId);
0289                 if (!realPath.isEmpty()) {
0290                     const QString collectionPath(archiveGroupPattern + realPath);
0291                     KConfigGroup newGroup(archiveConfig, collectionPath);
0292                     oldGroup.copyTo(&newGroup);
0293                     newGroup.writeEntry(QStringLiteral("saveCollectionId"), realPath);
0294                 }
0295                 oldGroup.deleteGroup();
0296             }
0297         }
0298         archiveConfig->sync();
0299 
0300         backupFile(tmp.fileName(), Utils::configsPath(), archiveMailAgentConfigurationStr);
0301         delete archiveConfig;
0302     }
0303 
0304     const QString templatesconfigurationrcStr(QStringLiteral("templatesconfigurationrc"));
0305     const QString templatesconfigurationrc = QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + QLatin1Char('/') + templatesconfigurationrcStr;
0306     if (QFileInfo::exists(templatesconfigurationrc)) {
0307         KSharedConfigPtr templaterc = KSharedConfig::openConfig(templatesconfigurationrcStr);
0308 
0309         QTemporaryFile tmp;
0310         tmp.open();
0311 
0312         KConfig *templateConfig = templaterc->copyTo(tmp.fileName());
0313         const QString templateGroupPattern = QStringLiteral("Templates #");
0314         const QStringList templateList = templateConfig->groupList().filter(QRegularExpression(QStringLiteral("Templates #\\d+")));
0315         for (const QString &str : templateList) {
0316             bool found = false;
0317             const int collectionId = QStringView(str).right(str.length() - templateGroupPattern.length()).toInt(&found);
0318             if (found) {
0319                 KConfigGroup oldGroup = templateConfig->group(str);
0320                 const QString realPath = convertToFullCollectionPath(collectionId);
0321                 if (!realPath.isEmpty()) {
0322                     KConfigGroup newGroup(templateConfig, templateGroupPattern + realPath);
0323                     oldGroup.copyTo(&newGroup);
0324                 }
0325                 oldGroup.deleteGroup();
0326             }
0327         }
0328         templateConfig->sync();
0329 
0330         backupFile(tmp.fileName(), Utils::configsPath(), templatesconfigurationrcStr);
0331         delete templateConfig;
0332     }
0333 
0334     storeDirectory(QStringLiteral("/messageviewerplugins/"));
0335     storeDirectory(QStringLiteral("/messageviewer/themes/"));
0336 
0337     const QDir gravatarDirectory(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QStringLiteral("/gravatar/"));
0338     if (gravatarDirectory.exists()) {
0339         const QFileInfoList listFileInfo = gravatarDirectory.entryInfoList(QStringList() << QStringLiteral("*.png"), QDir::Files);
0340         const int listSize(listFileInfo.size());
0341         for (int i = 0; i < listSize; ++i) {
0342             backupFile(listFileInfo.at(i).absoluteFilePath(), Utils::dataPath() + QStringLiteral("gravatar/"), listFileInfo.at(i).fileName());
0343         }
0344     }
0345 
0346     const QDir autocorrectDirectory(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QStringLiteral("/autocorrect/"));
0347     if (autocorrectDirectory.exists()) {
0348         const QFileInfoList listFileInfo = autocorrectDirectory.entryInfoList(QStringList() << QStringLiteral("*.xml"), QDir::Files);
0349         const int listSize(listFileInfo.size());
0350         for (int i = 0; i < listSize; ++i) {
0351             backupFile(listFileInfo.at(i).absoluteFilePath(), Utils::dataPath() + QStringLiteral("autocorrect/"), listFileInfo.at(i).fileName());
0352         }
0353     }
0354     const QString adblockFilePath = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QStringLiteral("/kmail2/adblockrules_local");
0355     if (QFileInfo::exists(adblockFilePath)) {
0356         backupFile(adblockFilePath, Utils::dataPath() + QStringLiteral("kmail2/"), QStringLiteral("adblockrules_local"));
0357     }
0358 
0359     const QString kmailStr(QStringLiteral("kmail2rc"));
0360     const QString kmail2rc = QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + QLatin1Char('/') + kmailStr;
0361     if (QFileInfo::exists(kmail2rc)) {
0362         KSharedConfigPtr kmailrc = KSharedConfig::openConfig(kmail2rc);
0363 
0364         QTemporaryFile tmp;
0365         tmp.open();
0366 
0367         KConfig *kmailConfig = kmailrc->copyTo(tmp.fileName());
0368         const QString folderGroupPattern = QStringLiteral("Folder-");
0369         const QStringList folderList = kmailConfig->groupList().filter(QRegularExpression(QStringLiteral("Folder-\\d+")));
0370         for (const QString &str : folderList) {
0371             bool found = false;
0372             const int collectionId = QStringView(str).right(str.length() - folderGroupPattern.length()).toInt(&found);
0373             if (found) {
0374                 KConfigGroup oldGroup = kmailConfig->group(str);
0375                 ImportExportMailUtil::cleanupFolderSettings(oldGroup);
0376                 const QString realPath = convertToFullCollectionPath(collectionId);
0377                 if (!realPath.isEmpty()) {
0378                     KConfigGroup newGroup(kmailConfig, folderGroupPattern + realPath);
0379                     oldGroup.copyTo(&newGroup);
0380                 }
0381                 oldGroup.deleteGroup();
0382             }
0383         }
0384         const QString composerStr(QStringLiteral("Composer"));
0385         if (kmailConfig->hasGroup(composerStr)) {
0386             KConfigGroup composerGroup = kmailConfig->group(composerStr);
0387             const QString previousStr(QStringLiteral("previous-fcc"));
0388             if (composerGroup.hasKey(previousStr)) {
0389                 const int collectionId = composerGroup.readEntry(previousStr, -1);
0390                 if (collectionId != -1) {
0391                     const QString realPath = convertToFullCollectionPath(collectionId);
0392                     composerGroup.writeEntry(previousStr, realPath);
0393                 }
0394             }
0395         }
0396 
0397         const QString generalStr(QStringLiteral("General"));
0398         if (kmailConfig->hasGroup(generalStr)) {
0399             KConfigGroup generalGroup = kmailConfig->group(generalStr);
0400             const QString startupFolderStr(QStringLiteral("startupFolder"));
0401             if (generalGroup.hasKey(startupFolderStr)) {
0402                 const int collectionId = generalGroup.readEntry(startupFolderStr, -1);
0403                 if (collectionId != -1) {
0404                     const QString realPath = convertToFullCollectionPath(collectionId);
0405                     generalGroup.writeEntry(startupFolderStr, realPath);
0406                 }
0407             }
0408         }
0409 
0410         const QString storageModelSelectedMessageStr(QStringLiteral("MessageListView::StorageModelSelectedMessages"));
0411         if (kmailConfig->hasGroup(storageModelSelectedMessageStr)) {
0412             KConfigGroup storageGroup = kmailConfig->group(storageModelSelectedMessageStr);
0413             const QString storageModelSelectedPattern(QStringLiteral("MessageUniqueIdForStorageModel"));
0414             const QStringList storageList = storageGroup.keyList().filter(QRegularExpression(QStringLiteral("MessageUniqueIdForStorageModel\\d+")));
0415             for (const QString &str : storageList) {
0416                 bool found = false;
0417                 const int collectionId = QStringView(str).right(str.length() - storageModelSelectedPattern.length()).toInt(&found);
0418                 const QString oldValue = storageGroup.readEntry(str);
0419                 if (found) {
0420                     const QString realPath = convertToFullCollectionPath(collectionId);
0421                     if (!realPath.isEmpty()) {
0422                         storageGroup.writeEntry(QStringLiteral("%1%2").arg(storageModelSelectedPattern, realPath), oldValue);
0423                         storageGroup.deleteEntry(str);
0424                     } else {
0425                         storageGroup.deleteEntry(str);
0426                     }
0427                 }
0428             }
0429         }
0430 
0431         const QString collectionFolderViewStr(QStringLiteral("CollectionFolderView"));
0432         if (kmailConfig->hasGroup(collectionFolderViewStr)) {
0433             KConfigGroup favoriteGroup = kmailConfig->group(collectionFolderViewStr);
0434 
0435             const QString currentKey(QStringLiteral("Current"));
0436             convertCollectionToRealPath(favoriteGroup, currentKey);
0437 
0438             const QString expensionKey(QStringLiteral("Expansion"));
0439             convertCollectionListToRealPath(favoriteGroup, expensionKey);
0440         }
0441 
0442         const QString favoriteCollectionStr(QStringLiteral("FavoriteCollections"));
0443         if (kmailConfig->hasGroup(favoriteCollectionStr)) {
0444             KConfigGroup favoriteGroup = kmailConfig->group(favoriteCollectionStr);
0445 
0446             const QString favoriteCollectionIdsStr(QStringLiteral("FavoriteCollectionIds"));
0447             convertCollectionIdsToRealPath(favoriteGroup, favoriteCollectionIdsStr);
0448         }
0449 
0450         const QString favoriteCollectionOrderStr(QStringLiteral("FavoriteCollectionsOrder"));
0451         if (kmailConfig->hasGroup(favoriteCollectionOrderStr)) {
0452             KConfigGroup favoriteGroup = kmailConfig->group(favoriteCollectionOrderStr);
0453             // For favorite id for root collection == 0 and we store only folder => c
0454             const QString favoriteCollectionIdsStr(QStringLiteral("0"));
0455             const QString prefixCollection(QStringLiteral("c"));
0456             convertCollectionIdsToRealPath(favoriteGroup, favoriteCollectionIdsStr, prefixCollection);
0457         }
0458 
0459         // Event collection
0460         const QString eventCollectionStr(QStringLiteral("Event"));
0461         if (kmailConfig->hasGroup(eventCollectionStr)) {
0462             KConfigGroup eventGroup = kmailConfig->group(eventCollectionStr);
0463             const QString eventLastEventSelectedFolder(QStringLiteral("LastEventSelectedFolder"));
0464             convertCollectionIdsToRealPath(eventGroup, eventLastEventSelectedFolder);
0465         }
0466 
0467         // Todo collection
0468         const QString todoCollectionStr(QStringLiteral("Todo"));
0469         if (kmailConfig->hasGroup(todoCollectionStr)) {
0470             KConfigGroup todoGroup = kmailConfig->group(todoCollectionStr);
0471             const QString todoLastEventSelectedFolder(QStringLiteral("LastSelectedFolder"));
0472             convertCollectionIdsToRealPath(todoGroup, todoLastEventSelectedFolder);
0473         }
0474         // FolderSelectionDialog collection
0475         const QString folderSelectionCollectionStr(QStringLiteral("FolderSelectionDialog"));
0476         if (kmailConfig->hasGroup(folderSelectionCollectionStr)) {
0477             KConfigGroup folderSelectionGroup = kmailConfig->group(folderSelectionCollectionStr);
0478             const QString folderSelectionSelectedFolder(QStringLiteral("LastSelectedFolder"));
0479             convertCollectionIdsToRealPath(folderSelectionGroup, folderSelectionSelectedFolder);
0480         }
0481 
0482         // Note collection
0483         const QString noteCollectionStr(QStringLiteral("Note"));
0484         if (kmailConfig->hasGroup(noteCollectionStr)) {
0485             KConfigGroup noteGroup = kmailConfig->group(noteCollectionStr);
0486             const QString noteLastEventSelectedFolder(QStringLiteral("LastNoteSelectedFolder"));
0487             convertCollectionIdsToRealPath(noteGroup, noteLastEventSelectedFolder);
0488         }
0489 
0490         // Convert MessageListTab collection id
0491         const QString messageListPaneStr(QStringLiteral("MessageListPane"));
0492         if (kmailConfig->hasGroup(messageListPaneStr)) {
0493             KConfigGroup messageListPaneGroup = kmailConfig->group(messageListPaneStr);
0494             const int numberOfTab = messageListPaneGroup.readEntry(QStringLiteral("tabNumber"), 0);
0495             for (int i = 0; i < numberOfTab; ++i) {
0496                 KConfigGroup messageListPaneTabGroup = kmailConfig->group(QStringLiteral("MessageListTab%1").arg(i));
0497                 const QString messageListPaneTabFolderStr(QStringLiteral("collectionId"));
0498                 convertCollectionIdsToRealPath(messageListPaneTabGroup, messageListPaneTabFolderStr);
0499             }
0500         }
0501 
0502         // Automatic Add Contacts
0503         const QList<uint> listIdentities = listIdentityUoid();
0504         for (uint identity : listIdentities) {
0505             const QString groupId = QStringLiteral("Automatic Add Contacts %1").arg(identity);
0506             if (kmailConfig->hasGroup(groupId)) {
0507                 KConfigGroup identityGroup = kmailConfig->group(groupId);
0508                 const QString automaticAddContactStr(QStringLiteral("Collection"));
0509                 convertCollectionIdsToRealPath(identityGroup, automaticAddContactStr);
0510             }
0511         }
0512 
0513         // TODO add confirm address too
0514 
0515         // Clean up kmail2rc
0516         const QString tipOfDaysStr(QStringLiteral("TipOfDay"));
0517         if (kmailConfig->hasGroup(tipOfDaysStr)) {
0518             kmailConfig->deleteGroup(tipOfDaysStr);
0519         }
0520         const QString startupStr(QStringLiteral("Startup"));
0521         if (kmailConfig->hasGroup(startupStr)) {
0522             kmailConfig->deleteGroup(startupStr);
0523         }
0524 
0525         const QString search(QStringLiteral("Search"));
0526         if (kmailConfig->hasGroup(search)) {
0527             KConfigGroup searchGroup = kmailConfig->group(search);
0528             searchGroup.deleteGroup();
0529         }
0530 
0531         kmailConfig->sync();
0532         backupFile(tmp.fileName(), Utils::configsPath(), kmailStr);
0533         delete kmailConfig;
0534     }
0535 
0536     emitInfo(i18n("Config backup done."));
0537 }
0538 
0539 void ExportMailJobInterface::backupIdentity()
0540 {
0541     setProgressDialogLabel(i18n("Backing up identity..."));
0542 
0543     const QString emailidentitiesStr(QStringLiteral("emailidentities"));
0544     const QString emailidentitiesrc = QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + QLatin1Char('/') + emailidentitiesStr;
0545     if (QFileInfo::exists(emailidentitiesrc)) {
0546         KSharedConfigPtr identity = KSharedConfig::openConfig(emailidentitiesrc);
0547 
0548         QTemporaryFile tmp;
0549         tmp.open();
0550 
0551         KConfig *identityConfig = identity->copyTo(tmp.fileName());
0552         const QStringList accountList = identityConfig->groupList().filter(QRegularExpression(QStringLiteral("Identity #\\d+")));
0553         for (const QString &account : accountList) {
0554             KConfigGroup group = identityConfig->group(account);
0555             const QString fcc = QStringLiteral("Fcc");
0556             if (group.hasKey(fcc)) {
0557                 const QString realPath = convertToFullCollectionPath(group.readEntry(fcc).toLongLong());
0558                 group.writeEntry(fcc, realPath);
0559             }
0560             const QString draft = QStringLiteral("Drafts");
0561             if (group.hasKey(draft)) {
0562                 const QString realPath = convertToFullCollectionPath(group.readEntry(draft).toLongLong());
0563                 group.writeEntry(draft, realPath);
0564             }
0565             const QString templates = QStringLiteral("Templates");
0566             if (group.hasKey(templates)) {
0567                 const QString realPath = convertToFullCollectionPath(group.readEntry(templates).toLongLong());
0568                 group.writeEntry(templates, realPath);
0569             }
0570             const QString vcard = QStringLiteral("VCardFile");
0571             if (group.hasKey(vcard)) {
0572                 const QString vcardFileName = group.readEntry(vcard);
0573                 if (!vcardFileName.isEmpty()) {
0574                     const int uoid = group.readEntry(QStringLiteral("uoid"), -1);
0575                     QFile file(vcardFileName);
0576                     if (file.exists()) {
0577                         const bool fileAdded =
0578                             archive()->addLocalFile(vcardFileName, Utils::identitiesPath() + QString::number(uoid) + QLatin1Char('/') + file.fileName());
0579                         if (!fileAdded) {
0580                             emitError(i18n("vCard file \"%1\" cannot be saved.", file.fileName()));
0581                         }
0582                     } else {
0583                         group.deleteEntry(vcard);
0584                     }
0585                 }
0586             }
0587         }
0588 
0589         identityConfig->sync();
0590         const bool fileAdded = archive()->addLocalFile(tmp.fileName(), Utils::identitiesPath() + QStringLiteral("emailidentities"));
0591         delete identityConfig;
0592         if (fileAdded) {
0593             emitInfo(i18n("Identity backup done."));
0594         } else {
0595             emitError(i18n("Identity file cannot be added to backup file."));
0596         }
0597     }
0598 }
0599 
0600 void ExportMailJobInterface::slotMailsJobTerminated()
0601 {
0602     if (wasCanceled()) {
0603         Q_EMIT jobFinished();
0604         return;
0605     }
0606     mIndexIdentifier++;
0607     QTimer::singleShot(0, this, &ExportMailJobInterface::slotWriteNextArchiveResource);
0608 }
0609 
0610 void ExportMailJobInterface::slotWriteNextArchiveResource()
0611 {
0612     if (mIndexIdentifier < mAkonadiInstanceInfo.count()) {
0613         const Utils::AkonadiInstanceInfo agent = mAkonadiInstanceInfo.at(mIndexIdentifier);
0614         const QStringList capabilities(agent.capabilities);
0615         if (agent.mimeTypes.contains(KMime::Message::mimeType())) {
0616             if (capabilities.contains(QLatin1StringView("Resource")) && !capabilities.contains(QLatin1StringView("Virtual"))
0617                 && !capabilities.contains(QLatin1StringView("MailTransport"))) {
0618                 const QString identifier = agent.identifier;
0619                 if (identifier.contains(QLatin1StringView("akonadi_maildir_resource_"))
0620                     || identifier.contains(QLatin1StringView("akonadi_mixedmaildir_resource_"))) {
0621                     const QString archivePath = Utils::mailsPath() + identifier + QLatin1Char('/');
0622                     const QString url = resourcePath(identifier);
0623                     if (!mAgentPaths.contains(url)) {
0624                         if (!url.isEmpty()) {
0625                             mAgentPaths << url;
0626                             exportResourceToArchive(archivePath, url, identifier);
0627                         } else {
0628                             qCDebug(PIMDATAEXPORTERCORE_LOG) << "Url is empty for " << identifier;
0629                             QTimer::singleShot(0, this, &ExportMailJobInterface::slotMailsJobTerminated);
0630                         }
0631                     } else {
0632                         QTimer::singleShot(0, this, &ExportMailJobInterface::slotMailsJobTerminated);
0633                     }
0634                 } else if (identifier.contains(QLatin1StringView("akonadi_mbox_resource_"))) {
0635                     backupMailResourceFile(identifier, Utils::mailsPath()); // FIXME addressbookPath or MailPAth ???
0636                     QTimer::singleShot(0, this, &ExportMailJobInterface::slotMailsJobTerminated);
0637                 } else {
0638                     QTimer::singleShot(0, this, &ExportMailJobInterface::slotMailsJobTerminated);
0639                 }
0640             } else {
0641                 QTimer::singleShot(0, this, &ExportMailJobInterface::slotMailsJobTerminated);
0642             }
0643         } else {
0644             QTimer::singleShot(0, this, &ExportMailJobInterface::slotMailsJobTerminated);
0645         }
0646     } else {
0647         QTimer::singleShot(0, this, &ExportMailJobInterface::slotCheckBackupResources);
0648     }
0649 }
0650 
0651 void ExportMailJobInterface::backupResources()
0652 {
0653     setProgressDialogLabel(i18n("Backing up resources..."));
0654 
0655     for (const Utils::AkonadiInstanceInfo &agent : std::as_const(mAkonadiInstanceInfo)) {
0656         const QStringList capabilities = agent.capabilities;
0657         if (agent.mimeTypes.contains(KMime::Message::mimeType())) {
0658             if (capabilities.contains(QLatin1StringView("Resource")) && !capabilities.contains(QLatin1StringView("Virtual"))
0659                 && !capabilities.contains(QLatin1StringView("MailTransport"))) {
0660                 const QString identifier = agent.identifier;
0661                 // Store just pop3/imap/kolab/gmail account. Store other config when we copy data.
0662                 if (identifier.contains(QLatin1StringView("pop3")) || identifier.contains(QLatin1StringView("imap"))
0663                     || identifier.contains(QLatin1StringView("_kolab_")) || identifier.contains(QLatin1StringView("_gmail_"))) {
0664                     const QString errorStr = storeResources(archive(), identifier, Utils::resourcesPath());
0665                     if (!errorStr.isEmpty()) {
0666                         emitError(errorStr);
0667                     }
0668                 } else {
0669                     qCDebug(PIMDATAEXPORTERCORE_LOG) << " resource \"" << identifier << "\" will not store";
0670                 }
0671             }
0672         }
0673     }
0674 
0675     emitInfo(i18n("Resources backup done."));
0676 }
0677 
0678 #include "moc_exportmailjobinterface.cpp"