File indexing completed on 2024-05-12 05:25:34

0001 /*
0002    SPDX-FileCopyrightText: 2020-2024 Laurent Montel <montel@kde.org>
0003 
0004    SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "resourceconverterbase.h"
0008 #include "utils.h"
0009 #include <KConfigGroup>
0010 #include <KLocalizedString>
0011 #include <KZip>
0012 #include <PimCommon/PimUtil>
0013 #include <QDir>
0014 #include <QFileInfo>
0015 #include <QTemporaryFile>
0016 
0017 ResourceConverterBase::ResourceConverterBase() = default;
0018 
0019 ResourceConverterBase::~ResourceConverterBase() = default;
0020 
0021 QString ResourceConverterBase::adaptResourcePath(const KSharedConfigPtr &resourceConfig, const QString &storedData)
0022 {
0023     QString newUrl = ResourceConverterBase::resourcePath(resourceConfig);
0024     if (!newUrl.contains(installDefaultDirectory())) {
0025         QFileInfo fileInfo(newUrl);
0026         fileInfo.fileName();
0027         // qCDebug(PIMDATAEXPORTERCORE_LOG)<<" url "<<url.path();
0028         QString currentPath = installDefaultDirectory() + QLatin1Char('/') + storedData;
0029         newUrl = (currentPath + QLatin1Char('/') + fileInfo.fileName());
0030         if (!QDir(currentPath).exists()) {
0031             if (!QDir().mkpath(currentPath)) {
0032                 qCWarning(PIMDATAEXPORTERCORE_LOG) << "Impossible to create subpath " << currentPath;
0033             }
0034         }
0035     }
0036     if (QFileInfo::exists(newUrl)) {
0037         QString newFileName = newUrl;
0038         QFileInfo fileInfo(newFileName);
0039         for (int i = 0;; ++i) {
0040             const QString currentPath = fileInfo.path() + QLatin1Char('/') + QString::number(i) + QLatin1Char('/');
0041             newFileName = currentPath + fileInfo.fileName();
0042             if (!QFileInfo::exists(newFileName)) {
0043                 if (!QDir().mkpath(currentPath)) {
0044                     qCWarning(PIMDATAEXPORTERCORE_LOG) << "Impossible to create subpath " << currentPath;
0045                 }
0046                 break;
0047             }
0048         }
0049         newUrl = newFileName;
0050     }
0051     return newUrl;
0052 }
0053 
0054 QString ResourceConverterBase::resourcePath(const KSharedConfigPtr &resourceConfig, const QString &defaultPath)
0055 {
0056     KConfigGroup group = resourceConfig->group(QStringLiteral("General"));
0057     QString url = group.readEntry(QStringLiteral("Path"), defaultPath);
0058     if (!url.isEmpty()) {
0059         url.replace(QLatin1StringView("$HOME"), QDir::homePath());
0060     }
0061     url = changeResourcePath(url);
0062     return url;
0063 }
0064 
0065 QString ResourceConverterBase::resourcePath(const QString &agentIdentifier, const QString &defaultPath)
0066 {
0067     const QString agentFileName = agentIdentifier + QStringLiteral("rc");
0068     const QString configFileName = QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + QLatin1Char('/') + agentFileName;
0069     // qDebug() << "configFileName " << configFileName;
0070 
0071     KSharedConfigPtr resourceConfig = KSharedConfig::openConfig(configFileName);
0072     const QString url = resourcePath(resourceConfig, defaultPath);
0073     // qDebug() << " resourcePath " << url;
0074     return url;
0075 }
0076 
0077 QString ResourceConverterBase::changeResourcePath(QString url) const
0078 {
0079     return url;
0080 }
0081 
0082 // Merge two methods I think
0083 void ResourceConverterBase::convertCollectionIdsToRealPath(KConfigGroup &group, const QString &currentKey, const QString &prefixCollection)
0084 {
0085     if (group.hasKey(currentKey)) {
0086         const QStringList value = group.readEntry(currentKey, QStringList());
0087         QStringList newValue;
0088         for (QString str : value) {
0089             bool found = false;
0090             if (!prefixCollection.isEmpty() && str.startsWith(prefixCollection)) {
0091                 str.remove(0, prefixCollection.length());
0092             }
0093             const qlonglong collectionId = str.toLongLong(&found);
0094             if (found) {
0095                 const QString realPath = convertToFullCollectionPath(collectionId);
0096                 if (!realPath.isEmpty()) {
0097                     newValue << realPath;
0098                 }
0099             }
0100         }
0101         if (newValue.isEmpty()) {
0102             group.deleteEntry(currentKey);
0103         } else {
0104             group.writeEntry(currentKey, newValue);
0105         }
0106     }
0107 }
0108 
0109 void ResourceConverterBase::convertCollectionListToRealPath(KConfigGroup &group, const QString &currentKey)
0110 {
0111     if (group.hasKey(currentKey)) {
0112         const QStringList listExpension = group.readEntry(currentKey, QStringList());
0113         if (listExpension.isEmpty()) {
0114             group.deleteEntry(currentKey);
0115         } else {
0116             QStringList result;
0117             for (QString collection : listExpension) {
0118                 collection.remove(QLatin1Char('c'));
0119                 bool found = false;
0120                 const qlonglong collectionValue = collection.toLongLong(&found);
0121                 if (found && collectionValue != -1) {
0122                     const QString realPath = convertToFullCollectionPath(collectionValue);
0123                     if (!realPath.isEmpty()) {
0124                         result << realPath;
0125                     }
0126                 }
0127             }
0128             if (result.isEmpty()) {
0129                 group.deleteEntry(currentKey);
0130             } else {
0131                 group.writeEntry(currentKey, result);
0132             }
0133         }
0134     }
0135 }
0136 
0137 void ResourceConverterBase::convertCollectionToRealPath(KConfigGroup &group, const QString &currentKey)
0138 {
0139     if (group.hasKey(currentKey)) {
0140         QString collectionId = group.readEntry(currentKey);
0141         if (collectionId.isEmpty()) {
0142             group.deleteEntry(currentKey);
0143         } else {
0144             collectionId.remove(QLatin1Char('c'));
0145             bool found = false;
0146             const qlonglong collectionValue = collectionId.toLongLong(&found);
0147             if (found && collectionValue != -1) {
0148                 const QString realPath = convertToFullCollectionPath(collectionValue);
0149                 group.writeEntry(currentKey, realPath);
0150             } else {
0151                 group.deleteEntry(currentKey);
0152             }
0153         }
0154     }
0155 }
0156 
0157 QString ResourceConverterBase::agentFileName(const QString &filename)
0158 {
0159     QString agentFileConfigName = filename;
0160     agentFileConfigName.remove(Utils::resourcesPath());
0161     agentFileConfigName.remove(agentFileConfigName.length() - 2, 2); // Remove "rc"
0162     agentFileConfigName = Utils::resourcesPath() + Utils::prefixAkonadiConfigFile() + agentFileConfigName;
0163     return agentFileConfigName;
0164 }
0165 
0166 QString ResourceConverterBase::storeResources(KZip *archive, const QString &identifier, const QString &path)
0167 {
0168     const QString agentFileName = identifier + QStringLiteral("rc");
0169     const QString configFileName = QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + QLatin1Char('/') + agentFileName;
0170     qCWarning(PIMDATAEXPORTERCORE_LOG) << "configFileName " << configFileName << "agentFileName " << configFileName;
0171 
0172     KSharedConfigPtr resourceConfig = KSharedConfig::openConfig(configFileName);
0173     QTemporaryFile tmp;
0174     tmp.open();
0175     KConfig *config = resourceConfig->copyTo(tmp.fileName());
0176 
0177     if (identifier.contains(POP3_RESOURCE_IDENTIFIER)) {
0178         const QString targetCollection = QStringLiteral("targetCollection");
0179         KConfigGroup group = config->group(QStringLiteral("General"));
0180         if (group.hasKey(targetCollection)) {
0181             group.writeEntry(targetCollection, convertToFullCollectionPath(group.readEntry(targetCollection).toLongLong()));
0182         }
0183     } else if (PimCommon::Util::isImapResource(identifier)) {
0184         const QString trash = QStringLiteral("TrashCollection");
0185         KConfigGroup group = config->group(QStringLiteral("cache"));
0186         if (group.hasKey(trash)) {
0187             group.writeEntry(trash, convertToFullCollectionPath(group.readEntry(trash).toLongLong()));
0188         }
0189     }
0190     // Customize resource if necessary here.
0191     config->sync();
0192     bool fileAdded = archive->addLocalFile(tmp.fileName(), path + agentFileName);
0193     delete config;
0194     if (!fileAdded) {
0195         return i18n("Resource file \"%1\" cannot be added to backup file.", agentFileName);
0196     }
0197 
0198     const QString agentConfigFileName = Utils::prefixAkonadiConfigFile() + identifier;
0199     const QString agentConfigFileNamePath =
0200         QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + QLatin1StringView("/akonadi/") + agentConfigFileName;
0201     if (QFileInfo::exists(agentConfigFileNamePath)) {
0202         fileAdded = archive->addLocalFile(agentConfigFileNamePath, path + agentConfigFileName);
0203         if (!fileAdded) {
0204             return i18n("Resource file \"%1\" cannot be added to backup file.", agentConfigFileNamePath);
0205         }
0206     } else {
0207         return i18n("Resource config file \"%1\" doesn't exist.", agentConfigFileNamePath);
0208     }
0209 
0210     return {};
0211 }