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 "importcalendarjobinterface.h"
0008 #include "archivestorage.h"
0009 
0010 #include <KArchive>
0011 #include <KArchiveDirectory>
0012 #include <KArchiveEntry>
0013 #include <KConfigGroup>
0014 #include <KLocalizedString>
0015 #include <KZip>
0016 
0017 #include "pimdataexportcore_debug.h"
0018 
0019 #include <QColor>
0020 #include <QDir>
0021 #include <QFile>
0022 #include <QStandardPaths>
0023 #include <QTimer>
0024 
0025 ImportCalendarJobInterface::ImportCalendarJobInterface(QObject *parent, Utils::StoredTypes typeSelected, ArchiveStorage *archiveStorage, int numberOfStep)
0026     : AbstractImportExportJob(parent, archiveStorage, typeSelected, numberOfStep)
0027 {
0028     initializeImportJob();
0029 }
0030 
0031 ImportCalendarJobInterface::~ImportCalendarJobInterface() = default;
0032 
0033 void ImportCalendarJobInterface::start()
0034 {
0035     Q_EMIT title(i18n("Starting to import KOrganizer settings..."));
0036     mArchiveDirectory = archive()->directory();
0037     createProgressDialog(i18n("Import KOrganizer settings"));
0038     searchAllFiles(mArchiveDirectory, QString(), QStringLiteral("calendar"));
0039     initializeListStep();
0040     QTimer::singleShot(0, this, &ImportCalendarJobInterface::slotNextStep);
0041 }
0042 
0043 void ImportCalendarJobInterface::slotNextStep()
0044 {
0045     ++mIndex;
0046     if (mIndex < mListStep.count()) {
0047         Utils::StoredType type = mListStep.at(mIndex);
0048         if (type == Utils::Resources) {
0049             restoreResources();
0050         } else if (type == Utils::Config) {
0051             restoreConfig();
0052         } else {
0053             qCDebug(PIMDATAEXPORTERCORE_LOG) << Q_FUNC_INFO << " not supported type " << type;
0054             slotNextStep();
0055         }
0056     } else {
0057         Q_EMIT jobFinished();
0058     }
0059 }
0060 
0061 void ImportCalendarJobInterface::addSpecificResourceSettings(const KSharedConfig::Ptr &resourceConfig,
0062                                                              const QString &resourceName,
0063                                                              QMap<QString, QVariant> &settings)
0064 {
0065     if (resourceName == QLatin1StringView("akonadi_ical_resource")) {
0066         KConfigGroup general = resourceConfig->group(QStringLiteral("General"));
0067         if (general.hasKey(QStringLiteral("DisplayName"))) {
0068             settings.insert(QStringLiteral("DisplayName"), general.readEntry(QStringLiteral("DisplayName")));
0069         }
0070         if (general.hasKey(QStringLiteral("ReadOnly"))) {
0071             settings.insert(QStringLiteral("ReadOnly"), general.readEntry(QStringLiteral("ReadOnly"), false));
0072         }
0073         if (general.hasKey(QStringLiteral("MonitorFile"))) {
0074             settings.insert(QStringLiteral("MonitorFile"), general.readEntry(QStringLiteral("MonitorFile"), true));
0075         }
0076     }
0077 }
0078 
0079 bool ImportCalendarJobInterface::isAConfigFile(const QString &name) const
0080 {
0081     return name.endsWith(QLatin1StringView("rc"))
0082         && (name.contains(QLatin1StringView("akonadi_ical_resource_")) || name.contains(QLatin1StringView("akonadi_davgroupware_resource_"))
0083             || name.contains(QLatin1StringView("akonadi_icaldir_resource_")) || name.contains(QLatin1StringView("akonadi_openxchange_resource_"))
0084             || name.contains(QLatin1StringView("akonadi_google_resource_")));
0085 }
0086 
0087 void ImportCalendarJobInterface::restoreConfig()
0088 {
0089     increaseProgressDialog();
0090     setProgressDialogLabel(i18n("Restore configs..."));
0091     const QString korganizerPrinterrcStr(QStringLiteral("calendar_printing.rc"));
0092     const QString oldKorganizerPrintrrcStr(QStringLiteral("korganizer_printing.rc"));
0093     const KArchiveEntry *oldKorganizerPrinterEntry = mArchiveDirectory->entry(Utils::configsPath() + oldKorganizerPrintrrcStr);
0094     if (oldKorganizerPrinterEntry && oldKorganizerPrinterEntry->isFile()) {
0095         const auto korganizerFile = static_cast<const KArchiveFile *>(oldKorganizerPrinterEntry);
0096         const QString oldKorganizerPrintrrc = QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + QLatin1Char('/') + korganizerPrinterrcStr;
0097         if (QFileInfo::exists(oldKorganizerPrintrrc)) {
0098             if (overwriteConfigMessageBox(oldKorganizerPrintrrc)) {
0099                 copyToFile(korganizerFile, oldKorganizerPrintrrc, oldKorganizerPrintrrcStr, Utils::configsPath());
0100             }
0101         } else {
0102             copyToFile(korganizerFile, oldKorganizerPrintrrc, oldKorganizerPrintrrcStr, Utils::configsPath());
0103         }
0104     } else {
0105         const KArchiveEntry *korganizerPrinterEntry = mArchiveDirectory->entry(Utils::configsPath() + korganizerPrinterrcStr);
0106         if (korganizerPrinterEntry && korganizerPrinterEntry->isFile()) {
0107             const auto korganizerFile = static_cast<const KArchiveFile *>(korganizerPrinterEntry);
0108             const QString korganizerPrinterrc = QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + QLatin1Char('/') + korganizerPrinterrcStr;
0109             if (QFileInfo::exists(korganizerPrinterrc)) {
0110                 if (overwriteConfigMessageBox(korganizerPrinterrcStr)) {
0111                     copyToFile(korganizerFile, korganizerPrinterrc, korganizerPrinterrcStr, Utils::configsPath());
0112                 }
0113             } else {
0114                 copyToFile(korganizerFile, korganizerPrinterrc, korganizerPrinterrcStr, Utils::configsPath());
0115             }
0116         }
0117     }
0118 
0119     {
0120         const QString korganizerStr(QStringLiteral("korganizerrc"));
0121         const KArchiveEntry *korganizerrcentry = mArchiveDirectory->entry(Utils::configsPath() + korganizerStr);
0122         if (korganizerrcentry && korganizerrcentry->isFile()) {
0123             const auto korganizerrcFile = static_cast<const KArchiveFile *>(korganizerrcentry);
0124             const QString korganizerrc = QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + QLatin1Char('/') + korganizerStr;
0125             if (QFileInfo::exists(korganizerrc)) {
0126                 if (overwriteConfigMessageBox(korganizerStr)) {
0127                     importkorganizerConfig(korganizerrcFile, korganizerrc, korganizerStr, Utils::configsPath());
0128                 }
0129             } else {
0130                 importkorganizerConfig(korganizerrcFile, korganizerrc, korganizerStr, Utils::configsPath());
0131             }
0132         }
0133     }
0134 
0135     {
0136         const QString eventviewStr(QStringLiteral("eventviewsrc"));
0137         const KArchiveEntry *eventviewentry = mArchiveDirectory->entry(Utils::configsPath() + eventviewStr);
0138         if (eventviewentry && eventviewentry->isFile()) {
0139             const auto eventviewrcFile = static_cast<const KArchiveFile *>(eventviewentry);
0140             const QString eventviewrc = QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + QLatin1Char('/') + eventviewStr;
0141             if (QFileInfo::exists(eventviewrc)) {
0142                 if (overwriteConfigMessageBox(eventviewStr)) {
0143                     importeventViewConfig(eventviewrcFile, eventviewrc, eventviewStr, Utils::configsPath());
0144                 }
0145             } else {
0146                 importeventViewConfig(eventviewrcFile, eventviewrc, eventviewStr, Utils::configsPath());
0147             }
0148         }
0149     }
0150     {
0151         const QString kalendaracStr(QStringLiteral("kalendaracrc"));
0152         const KArchiveEntry *kalendaracentry = mArchiveDirectory->entry(Utils::configsPath() + kalendaracStr);
0153         if (kalendaracentry && kalendaracentry->isFile()) {
0154             const auto kalendaracFile = static_cast<const KArchiveFile *>(kalendaracentry);
0155             const QString kalendaracrc = QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + QLatin1Char('/') + kalendaracStr;
0156             if (QFileInfo::exists(kalendaracrc)) {
0157                 if (overwriteConfigMessageBox(kalendaracStr)) {
0158                     copyToFile(kalendaracFile, kalendaracrc, kalendaracStr, Utils::configsPath());
0159                 }
0160             } else {
0161                 copyToFile(kalendaracFile, kalendaracrc, kalendaracStr, Utils::configsPath());
0162             }
0163         }
0164     }
0165     {
0166         const QString kalendarStr(QStringLiteral("kalendarrc"));
0167         const KArchiveEntry *kalendarentry = mArchiveDirectory->entry(Utils::configsPath() + kalendarStr);
0168         if (kalendarentry && kalendarentry->isFile()) {
0169             const auto kalendarentryFile = static_cast<const KArchiveFile *>(kalendarentry);
0170             const QString kalendarentrycrc = QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + QLatin1Char('/') + kalendarStr;
0171             if (QFileInfo::exists(kalendarentrycrc)) {
0172                 if (overwriteConfigMessageBox(kalendarStr)) {
0173                     importKalendarConfig(kalendarentryFile, kalendarentrycrc, kalendarStr, Utils::configsPath());
0174                 }
0175             } else {
0176                 importKalendarConfig(kalendarentryFile, kalendarentrycrc, kalendarStr, Utils::configsPath());
0177             }
0178         }
0179     }
0180 
0181     {
0182         const QString freebusyStr(QStringLiteral("freebusyurls"));
0183         const KArchiveEntry *freebusyentry = mArchiveDirectory->entry(Utils::dataPath() + QLatin1StringView("korganizer/") + freebusyStr);
0184         if (freebusyentry && freebusyentry->isFile()) {
0185             const auto freebusyrcFile = static_cast<const KArchiveFile *>(freebusyentry);
0186 
0187             const QString freebusypath =
0188                 QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1StringView("/korganizer/") + freebusyStr;
0189             if (QFileInfo::exists(freebusypath)) {
0190                 // TODO 4.12 merge it.
0191                 if (overwriteConfigMessageBox(freebusyStr)) {
0192                     copyToFile(freebusyrcFile, freebusypath, freebusyStr, Utils::dataPath());
0193                 }
0194             } else {
0195                 copyToFile(freebusyrcFile, freebusypath, freebusyStr, Utils::dataPath());
0196             }
0197         }
0198     }
0199 
0200     {
0201         const KArchiveEntry *templateEntry = mArchiveDirectory->entry(Utils::dataPath() + QStringLiteral("korganizer/templates/"));
0202         if (templateEntry && templateEntry->isDirectory()) {
0203             // TODO 4.12 verify if template already exists.
0204             const QString templatePath =
0205                 QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1Char('/') + QStringLiteral("korganizer/templates/");
0206             const auto templateDir = static_cast<const KArchiveDirectory *>(templateEntry);
0207             if (!templateDir->copyTo(templatePath)) {
0208                 qCDebug(PIMDATAEXPORTERCORE_LOG) << "template cannot copy to " << templatePath;
0209             }
0210         }
0211     }
0212 
0213     {
0214         const KArchiveEntry *designerEntry = mArchiveDirectory->entry(Utils::dataPath() + QStringLiteral("korganizer/designer/"));
0215         if (designerEntry && designerEntry->isDirectory()) {
0216             const QString templatePath =
0217                 QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1Char('/') + QStringLiteral("korganizer/designer/");
0218             const auto templateDir = static_cast<const KArchiveDirectory *>(designerEntry);
0219             if (!templateDir->copyTo(templatePath)) {
0220                 qCDebug(PIMDATAEXPORTERCORE_LOG) << "template cannot copy to " << templatePath;
0221             }
0222         }
0223     }
0224 
0225     restoreUiRcFile(QStringLiteral("korganizerui.rc"), QStringLiteral("korganizer"));
0226     restoreUiRcFile(QStringLiteral("korganizer_part.rc"), QStringLiteral("korganizer"));
0227 
0228     restoreConfigFile(QStringLiteral("eventviewsrc"));
0229     emitInfo(i18n("Config restored."));
0230     QTimer::singleShot(0, this, &ImportCalendarJobInterface::slotNextStep);
0231 }
0232 
0233 void ImportCalendarJobInterface::importkorganizerConfig(const KArchiveFile *file, const QString &config, const QString &filename, const QString &prefix)
0234 {
0235     copyToFile(file, config, filename, prefix);
0236     KSharedConfig::Ptr korganizerConfig = KSharedConfig::openConfig(config);
0237 
0238     convertCollectionListStrToAkonadiId(korganizerConfig, QStringLiteral("GlobalCollectionSelection"), QStringLiteral("Selection"), true);
0239     convertCollectionListStrToAkonadiId(korganizerConfig, QStringLiteral("CollectionTreeView"), QStringLiteral("Expansion"), true);
0240     convertCollectionListStrToAkonadiId(korganizerConfig, QStringLiteral("GlobalCollectionView"), QStringLiteral("Expansion"), true);
0241 
0242     korganizerConfig->sync();
0243 }
0244 
0245 void ImportCalendarJobInterface::importKalendarConfig(const KArchiveFile *file, const QString &config, const QString &filename, const QString &prefix)
0246 {
0247     copyToFile(file, config, filename, prefix);
0248     KSharedConfig::Ptr kalendarConfig = KSharedConfig::openConfig(config);
0249 
0250     convertCollectionListStrToAkonadiId(kalendarConfig, QStringLiteral("GlobalCollectionSelection"), QStringLiteral("Selection"), true);
0251     convertResourceColors(kalendarConfig);
0252     kalendarConfig->sync();
0253 }
0254 
0255 void ImportCalendarJobInterface::importeventViewConfig(const KArchiveFile *file, const QString &config, const QString &filename, const QString &prefix)
0256 {
0257     copyToFile(file, config, filename, prefix);
0258     KSharedConfig::Ptr eventviewConfig = KSharedConfig::openConfig(config);
0259     convertResourceColors(eventviewConfig);
0260     eventviewConfig->sync();
0261 }
0262 
0263 void ImportCalendarJobInterface::convertResourceColors(const KSharedConfig::Ptr &config)
0264 {
0265     const QString resourceColorStr(QStringLiteral("Resources Colors"));
0266     if (config->hasGroup(resourceColorStr)) {
0267         KConfigGroup group = config->group(resourceColorStr);
0268         const QStringList keyList = group.keyList();
0269         for (const QString &key : keyList) {
0270             const Akonadi::Collection::Id id = convertPathToId(key);
0271             if (id != -1) {
0272                 const QColor color = group.readEntry(key, QColor());
0273                 group.writeEntry(QString::number(id), color);
0274             }
0275             group.deleteEntry(key);
0276         }
0277     }
0278 }
0279 
0280 void ImportCalendarJobInterface::restoreResources()
0281 {
0282     emitInfo(i18n("Restore resources..."));
0283     setProgressDialogLabel(i18n("Restore resources..."));
0284     increaseProgressDialog();
0285     QStringList listResource;
0286     listResource << restoreResourceFile(QStringLiteral("akonadi_ical_resource"), Utils::calendarPath(), Utils::storeCalendar());
0287     listResource << restoreResourceFile(QStringLiteral("akonadi_davgroupware_resource"), Utils::calendarPath(), Utils::storeCalendar());
0288     listResource << restoreResourceFile(QStringLiteral("akonadi_openxchange_resource"), Utils::calendarPath(), Utils::storeCalendar());
0289     listResource << restoreResourceFile(QStringLiteral("akonadi_google_resource"), Utils::calendarPath(), Utils::storeCalendar());
0290 
0291     if (!mListResourceFile.isEmpty()) {
0292         QDir dir(mTempDirName);
0293         dir.mkdir(Utils::addressbookPath());
0294         const QString copyToDirName(mTempDirName + QLatin1Char('/') + Utils::calendarPath());
0295         QDir().mkpath(copyToDirName);
0296         const int numberOfResourceFile = mListResourceFile.size();
0297         for (int i = 0; i < numberOfResourceFile; ++i) {
0298             ResourceFiles value = mListResourceFile.at(i);
0299             QMap<QString, QVariant> settings;
0300             if (value.akonadiConfigFile.contains(QLatin1StringView("akonadi_icaldir_resource_"))) {
0301                 const KArchiveEntry *fileResouceEntry = mArchiveDirectory->entry(value.akonadiConfigFile);
0302                 if (fileResouceEntry && fileResouceEntry->isFile()) {
0303                     const auto file = static_cast<const KArchiveFile *>(fileResouceEntry);
0304                     copyArchiveFileTo(file, copyToDirName);
0305                     QString resourceName(file->name());
0306 
0307                     QString filename(resourceName);
0308                     // TODO adapt filename otherwise it will use all the time the
0309                     // same filename.
0310                     qCDebug(PIMDATAEXPORTERCORE_LOG) << " filename :" << filename;
0311 
0312                     KSharedConfig::Ptr resourceConfig = KSharedConfig::openConfig(copyToDirName + QLatin1Char('/') + resourceName);
0313 
0314                     const QString newUrl = adaptResourcePath(resourceConfig, Utils::storeCalendar());
0315                     QFileInfo newUrlInfo(newUrl);
0316 
0317                     const QString dataFile = value.akonadiResources;
0318                     const KArchiveEntry *dataResouceEntry = mArchiveDirectory->entry(dataFile);
0319                     bool isDirResource = value.akonadiConfigFile.contains(QLatin1StringView("akonadi_icaldir_resource_"));
0320                     if (dataResouceEntry->isFile()) {
0321                         const auto fileEntry = static_cast<const KArchiveFile *>(dataResouceEntry);
0322                         // TODO  adapt directory name too
0323                         extractZipFile(fileEntry,
0324                                        copyToDirName,
0325                                        newUrlInfo.path(),
0326                                        value.akonadiConfigFile.contains(QLatin1StringView("akonadi_icaldir_resource_")));
0327                     }
0328                     settings.insert(QStringLiteral("Path"), newUrl);
0329 
0330                     const QString agentConfigFile = value.akonadiAgentConfigFile;
0331                     if (!agentConfigFile.isEmpty()) {
0332                         const KArchiveEntry *akonadiAgentConfigEntry = mArchiveDirectory->entry(agentConfigFile);
0333                         if (akonadiAgentConfigEntry->isFile()) {
0334                             const auto fileEntry = static_cast<const KArchiveFile *>(akonadiAgentConfigEntry);
0335                             copyArchiveFileTo(fileEntry, copyToDirName);
0336                             resourceName = fileEntry->name();
0337                             filename = Utils::akonadiAgentName(copyToDirName + QLatin1Char('/') + resourceName);
0338                         }
0339                     }
0340                     const QString resourceTypeName = isDirResource ? QStringLiteral("akonadi_icaldir_resource") : QStringLiteral("akonadi_ical_resource");
0341                     const QString newResource = createResource(resourceTypeName, filename, settings, true);
0342                     infoAboutNewResource(newResource);
0343                     listResource << newResource;
0344                     qCDebug(PIMDATAEXPORTERCORE_LOG) << " newResource" << newResource;
0345                 }
0346             }
0347         }
0348     }
0349     // It's maildir support. Need to add support
0350     synchronizeResource(listResource);
0351 }
0352 
0353 QString ImportCalendarJobInterface::configLocation() const
0354 {
0355     return installConfigLocation();
0356 }
0357 
0358 QString ImportCalendarJobInterface::applicationName() const
0359 {
0360     return QStringLiteral("[Korganizer]");
0361 }
0362 
0363 QString ImportCalendarJobInterface::installConfigLocation() const
0364 {
0365     return QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + QLatin1Char('/');
0366 }
0367 
0368 #include "moc_importcalendarjobinterface.cpp"