diff --git a/core/abstractimportexportjob.cpp b/core/abstractimportexportjob.cpp index 4bcd5a9..b23c266 100644 --- a/core/abstractimportexportjob.cpp +++ b/core/abstractimportexportjob.cpp @@ -1,620 +1,620 @@ /* Copyright (C) 2012-2017 Montel Laurent This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "abstractimportexportjob.h" #include "archivestorage.h" #include "importexportprogressindicatorbase.h" #include "synchronizeresourcejob.h" #include "MailCommon/MailUtil" #include #include #include #include #include #include #include #include #include #include #include int AbstractImportExportJob::sArchiveVersion = -1; AbstractImportExportJob::AbstractImportExportJob(QObject *parent, ArchiveStorage *archiveStorage, Utils::StoredTypes typeSelected, int numberOfStep) : QObject(parent) , mTypeSelected(typeSelected) , mArchiveStorage(archiveStorage) , mIdentityManager(KIdentityManagement::IdentityManager::self()) , mTempDir(nullptr) , mArchiveDirectory(nullptr) , mNumberOfStep(numberOfStep) , mCreateResource(nullptr) , mIndex(-1) , mImportExportProgressIndicator(new ImportExportProgressIndicatorBase(this)) { mImportExportProgressIndicator->setNumberOfStep(numberOfStep); connect(mImportExportProgressIndicator, &ImportExportProgressIndicatorBase::info, this, &AbstractImportExportJob::info); } AbstractImportExportJob::~AbstractImportExportJob() { delete mCreateResource; delete mTempDir; } void AbstractImportExportJob::createProgressDialog(const QString &title) { mImportExportProgressIndicator->createProgressDialog(title); connect(mImportExportProgressIndicator, &ImportExportProgressIndicatorBase::canceled, this, &AbstractImportExportJob::slotTaskCanceled); } void AbstractImportExportJob::slotTaskCanceled() { Q_EMIT error(i18n("Task Canceled")); Q_EMIT jobFinished(); } bool AbstractImportExportJob::wasCanceled() const { return mImportExportProgressIndicator->wasCanceled(); } void AbstractImportExportJob::increaseProgressDialog() { mImportExportProgressIndicator->increaseProgressDialog(); } void AbstractImportExportJob::setProgressDialogLabel(const QString &text) { mImportExportProgressIndicator->setProgressDialogLabel(text); } ImportExportProgressIndicatorBase *AbstractImportExportJob::importExportProgressIndicator() const { return mImportExportProgressIndicator; } void AbstractImportExportJob::setImportExportProgressIndicator(ImportExportProgressIndicatorBase *importExportProgressIndicator) { delete mImportExportProgressIndicator; mImportExportProgressIndicator = importExportProgressIndicator; mImportExportProgressIndicator->setNumberOfStep(mNumberOfStep); } KZip *AbstractImportExportJob::archive() const { return mArchiveStorage->archive(); } void AbstractImportExportJob::backupUiRcFile(const QString &configFileName, const QString &application) { const QString configrcStr(configFileName); const QString configrc = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1String("/kxmlgui5/") + application + QLatin1Char('/') + configrcStr; if (QFileInfo::exists(configrc)) { backupFile(configrc, Utils::configsPath(), configrcStr); } } void AbstractImportExportJob::backupConfigFile(const QString &configFileName) { const QString configrcStr(configFileName); const QString configrc = QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + QLatin1Char('/') + configrcStr; if (QFileInfo::exists(configrc)) { backupFile(configrc, Utils::configsPath(), configrcStr); } } void AbstractImportExportJob::backupFile(const QString &filename, const QString &path, const QString &storedName) { if (QFileInfo::exists(filename)) { const bool fileAdded = archive()->addLocalFile(filename, path + storedName); if (fileAdded) { Q_EMIT info(i18n("\"%1\" backup done.", path + storedName)); } else { Q_EMIT error(i18n("\"%1\" cannot be exported.", path + storedName)); } } else { Q_EMIT error(i18n("\"%1\" does not exist.", filename)); } } int AbstractImportExportJob::mergeConfigMessageBox(const QString &configName) const { return mImportExportProgressIndicator->mergeConfigMessageBox(configName); } bool AbstractImportExportJob::overwriteConfigMessageBox(const QString &configName) const { return mImportExportProgressIndicator->overwriteConfigMessageBox(configName); } void AbstractImportExportJob::overwriteDirectory(const QString &path, const KArchiveEntry *entry) { if (QDir(path).exists()) { if (overwriteDirectoryMessageBox(path)) { const KArchiveDirectory *dirEntry = static_cast(entry); if (!dirEntry->copyTo(path)) { qCDebug(PIMSETTINGEXPORTERCORE_LOG) << "directory cannot overwrite to " << path; } } } else { const KArchiveDirectory *dirEntry = static_cast(entry); if (dirEntry->copyTo(path)) { qCDebug(PIMSETTINGEXPORTERCORE_LOG) << "directory cannot overwrite to " << path; } } } void AbstractImportExportJob::searchAllFiles(const KArchiveDirectory *dir, const QString &prefix, const QString &searchEntryName) { const QStringList lst = dir->entries(); for (const QString &entryName : lst) { const KArchiveEntry *entry = dir->entry(entryName); if (entry && entry->isDirectory()) { const QString newPrefix = (prefix.isEmpty() ? prefix : prefix + QLatin1Char('/')) + entryName; if (entryName == searchEntryName) { storeArchiveInfoResources(static_cast(entry), entryName); } else { searchAllFiles(static_cast(entry), newPrefix, searchEntryName); } } } } void AbstractImportExportJob::storeArchiveInfoResources(const KArchiveDirectory *dir, const QString &prefix) { const QStringList lst = dir->entries(); for (const QString &entryName : lst) { const KArchiveEntry *entry = dir->entry(entryName); if (entry && entry->isDirectory()) { const KArchiveDirectory *resourceDir = static_cast(entry); const QStringList lst = resourceDir->entries(); if (lst.count() >= 2) { const QString archPath(prefix + QLatin1Char('/') + entryName + QLatin1Char('/')); resourceFiles files; for (const QString &name : lst) { if (isAConfigFile(name)) { files.akonadiConfigFile = archPath + name; } else if (name.startsWith(Utils::prefixAkonadiConfigFile())) { files.akonadiAgentConfigFile = archPath + name; } else { files.akonadiResources = archPath + name; } } files.debug(); mListResourceFile.append(files); } else { qCDebug(PIMSETTINGEXPORTERCORE_LOG) << " Problem in archive. number of file " << lst.count(); } } } } bool AbstractImportExportJob::isAConfigFile(const QString &name) const { Q_UNUSED(name); //Redefine in subclass return true; } bool AbstractImportExportJob::overwriteDirectoryMessageBox(const QString &directory) const { return mImportExportProgressIndicator->overwriteDirectoryMessageBox(directory); } void AbstractImportExportJob::convertRealPathToCollection(KConfigGroup &group, const QString ¤tKey, bool addCollectionPrefix) { if (group.hasKey(currentKey)) { const QString path = group.readEntry(currentKey); if (!path.isEmpty()) { const Akonadi::Collection::Id id = convertPathToId(path); if (id != -1) { if (addCollectionPrefix) { group.writeEntry(currentKey, QStringLiteral("c%1").arg(id)); } else { group.writeEntry(currentKey, id); } } else { group.deleteEntry(currentKey); } } } } void AbstractImportExportJob::convertRealPathToCollectionList(KConfigGroup &group, const QString ¤tKey, bool addCollectionPrefix) { if (group.hasKey(currentKey)) { const QStringList listExpension = group.readEntry(currentKey, QStringList()); QStringList result; if (!listExpension.isEmpty()) { for (const QString &collection : listExpension) { const Akonadi::Collection::Id id = convertPathToId(collection); if (id != -1) { if (addCollectionPrefix) { result << QStringLiteral("c%1").arg(id); } else { result << QStringLiteral("%1").arg(id); } } } if (result.isEmpty()) { group.deleteEntry(currentKey); } else { group.writeEntry(currentKey, result); } } } } Akonadi::Collection::Id AbstractImportExportJob::convertPathToId(const QString &path) { if (mHashConvertPathCollectionId.contains(path)) { return mHashConvertPathCollectionId.value(path); } const Akonadi::Collection::Id id = MailCommon::Util::convertFolderPathToCollectionId(path); if (id != -1) { mHashConvertPathCollectionId.insert(path, id); } return id; } void AbstractImportExportJob::initializeImportJob() { if (mTempDir) { qCDebug(PIMSETTINGEXPORTERCORE_LOG) << " initializeImportJob already called"; } else { mTempDir = new QTemporaryDir(); mTempDirName = mTempDir->path(); mCreateResource = new PimCommon::CreateResource(); connect(mCreateResource, &PimCommon::CreateResource::createResourceInfo, this, &AbstractImportExportJob::info); connect(mCreateResource, &PimCommon::CreateResource::createResourceError, this, &AbstractImportExportJob::error); } } void AbstractImportExportJob::copyToDirectory(const KArchiveEntry *entry, const QString &dest) { const KArchiveDirectory *subfolderDir = static_cast(entry); if (!subfolderDir->copyTo(dest)) { qCDebug(PIMSETTINGEXPORTERCORE_LOG) << "directory cannot copy to " << dest; } Q_EMIT info(i18n("\"%1\" was copied.", dest)); } void AbstractImportExportJob::copyToFile(const KArchiveFile *archivefile, const QString &dest, const QString &filename, const QString &prefix) { QDir dir(mTempDirName); const QString copyToDirName(mTempDirName + QLatin1Char('/') + prefix); const bool created = dir.mkpath(copyToDirName); if (!created) { qCDebug(PIMSETTINGEXPORTERCORE_LOG) << " directory :" << prefix << " not created"; } if (!archivefile->copyTo(copyToDirName)) { qCDebug(PIMSETTINGEXPORTERCORE_LOG) << "file " << filename << " can not copy to " << dest; } QFile file; file.setFileName(copyToDirName + QLatin1Char('/') + filename); //QFile doesn't overwrite => remove old file before //qCDebug(PIMSETTINGEXPORTERCORE_LOG)<<" dest "<showErrorMessage(i18n("File \"%1\" cannot be copied to \"%2\".", filename, dest), i18n("Copy file")); } else { Q_EMIT info(i18n("\"%1\" was restored.", filename)); } } void AbstractImportExportJob::backupResourceFile(const Akonadi::AgentInstance &agent, const QString &defaultPath) { const QString identifier = agent.identifier(); const QString archivePath = defaultPath + identifier + QDir::separator(); QString url = Utils::resourcePath(agent); if (!url.isEmpty()) { QFileInfo fi(url); QString filename = fi.fileName(); const bool fileAdded = archive()->addLocalFile(url, archivePath + filename); if (fileAdded) { const QString errorStr = Utils::storeResources(archive(), identifier, archivePath); if (!errorStr.isEmpty()) { Q_EMIT error(errorStr); } Q_EMIT info(i18n("\"%1\" was backed up.", filename)); url = Akonadi::ServerManager::agentConfigFilePath(identifier); if (!url.isEmpty()) { fi = QFileInfo(url); filename = fi.fileName(); const bool fileAdded = archive()->addLocalFile(url, archivePath + filename); if (fileAdded) { Q_EMIT info(i18n("\"%1\" was backed up.", filename)); } else { Q_EMIT error(i18n("\"%1\" file cannot be added to backup file.", filename)); } } } else { Q_EMIT error(i18n("\"%1\" file cannot be added to backup file.", filename)); } } } QStringList AbstractImportExportJob::restoreResourceFile(const QString &resourceBaseName, const QString &defaultPath, const QString &storePath, bool overwriteResources) { QStringList resourceToSync; //TODO fix sync config after created a resource if (!mListResourceFile.isEmpty()) { QDir dir(mTempDirName); dir.mkdir(defaultPath); const QString copyToDirName(mTempDirName + QLatin1Char('/') + defaultPath); for (int i = 0; i < mListResourceFile.size(); ++i) { resourceFiles value = mListResourceFile.at(i); QMap settings; if (value.akonadiConfigFile.contains(resourceBaseName + QLatin1Char('_'))) { const KArchiveEntry *fileResouceEntry = mArchiveDirectory->entry(value.akonadiConfigFile); if (fileResouceEntry && fileResouceEntry->isFile()) { const KArchiveFile *file = static_cast(fileResouceEntry); file->copyTo(copyToDirName); QString resourceName(file->name()); QString filename(file->name()); //TODO adapt filename otherwise it will use all the time the same filename. qCDebug(PIMSETTINGEXPORTERCORE_LOG) << " filename :" << filename; KSharedConfig::Ptr resourceConfig = KSharedConfig::openConfig(copyToDirName + QLatin1Char('/') + resourceName); QString newUrl; if (overwriteResources) { newUrl = Utils::resourcePath(resourceConfig); } else { newUrl = Utils::adaptResourcePath(resourceConfig, storePath); } const QString dataFile = value.akonadiResources; const KArchiveEntry *dataResouceEntry = mArchiveDirectory->entry(dataFile); if (dataResouceEntry->isFile()) { const KArchiveFile *file = static_cast(dataResouceEntry); file->copyTo(newUrl); } settings.insert(QStringLiteral("Path"), newUrl); const QString agentConfigFile = value.akonadiAgentConfigFile; if (!agentConfigFile.isEmpty()) { const KArchiveEntry *akonadiAgentConfigEntry = mArchiveDirectory->entry(agentConfigFile); if (akonadiAgentConfigEntry->isFile()) { const KArchiveFile *file = static_cast(akonadiAgentConfigEntry); file->copyTo(copyToDirName); resourceName = file->name(); const QString configPath = copyToDirName + QLatin1Char('/') + resourceName; filename = Utils::akonadiAgentName(configPath); } } addSpecificResourceSettings(resourceConfig, resourceBaseName, settings); const QString newResource = mCreateResource->createResource(resourceBaseName, filename, settings); infoAboutNewResource(newResource); resourceToSync << newResource; qCDebug(PIMSETTINGEXPORTERCORE_LOG) << " newResource" << newResource; } } } Q_EMIT info(i18n("Resources restored.")); } else { Q_EMIT error(i18n("No resources files found.")); } return resourceToSync; } void AbstractImportExportJob::addSpecificResourceSettings(KSharedConfig::Ptr /*resourceConfig*/, const QString & /*resourceName*/, QMap & /*settings*/) { //Redefine it in subclass } void AbstractImportExportJob::extractZipFile(const KArchiveFile *file, const QString &source, const QString &destination, bool isStoredAsZippedArchive) { file->copyTo(source); QDir dest(destination); if (!dest.exists()) { dest.mkpath(destination); } if (isStoredAsZippedArchive) { QString errorMsg; KZip *zip = Utils::openZip(source + QLatin1Char('/') + file->name(), errorMsg); if (zip) { const KArchiveDirectory *zipDir = zip->directory(); const QStringList lst = zipDir->entries(); for (const QString &entryName : lst) { const KArchiveEntry *entry = zipDir->entry(entryName); if (entry) { if (entry->isDirectory()) { const KArchiveDirectory *dir = static_cast(entry); dir->copyTo(destination + QDir::separator() + dir->name(), true); } else if (entry->isFile()) { const KArchiveFile *dir = static_cast(entry); dir->copyTo(destination); } } qApp->processEvents(); } delete zip; } else { Q_EMIT error(errorMsg); } } else { QFile archiveFile(source + QLatin1Char('/') + file->name()); if (!archiveFile.copy(destination + QLatin1Char('/') + file->name())) { - Q_EMIT error(i18n("Unable to copy file", file->name())); + Q_EMIT error(i18n("Unable to copy file %1", file->name())); } } } void AbstractImportExportJob::restoreUiRcFile(const QString &configNameStr, const QString &applicationName) { const KArchiveEntry *configNameentry = mArchiveDirectory->entry(Utils::configsPath() + configNameStr); if (configNameentry && configNameentry->isFile()) { const KArchiveFile *configNameconfiguration = static_cast(configNameentry); const QString configNamerc = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1String("/kxmlgui5/") + applicationName + QLatin1Char('/') + configNameStr; if (QFileInfo::exists(configNamerc)) { if (overwriteConfigMessageBox(configNameStr)) { copyToFile(configNameconfiguration, configNamerc, configNameStr, Utils::configsPath()); } } else { copyToFile(configNameconfiguration, configNamerc, configNameStr, Utils::configsPath()); } } } void AbstractImportExportJob::restoreConfigFile(const QString &configNameStr) { const KArchiveEntry *configNameentry = mArchiveDirectory->entry(Utils::configsPath() + configNameStr); if (configNameentry && configNameentry->isFile()) { const KArchiveFile *configNameconfiguration = static_cast(configNameentry); const QString configNamerc = QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + QLatin1Char('/') + configNameStr; if (QFileInfo::exists(configNamerc)) { //TODO 4.12 allow to merge config. if (overwriteConfigMessageBox(configNameStr)) { copyToFile(configNameconfiguration, configNamerc, configNameStr, Utils::configsPath()); } } else { copyToFile(configNameconfiguration, configNamerc, configNameStr, Utils::configsPath()); } } } void AbstractImportExportJob::infoAboutNewResource(const QString &resourceName) { Q_EMIT info(i18n("Resource \'%1\' created.", resourceName)); } int AbstractImportExportJob::archiveVersion() { return sArchiveVersion; } void AbstractImportExportJob::setArchiveVersion(int version) { sArchiveVersion = version; } void AbstractImportExportJob::slotSynchronizeInstanceFailed(const QString &instance) { Q_EMIT error(i18n("Failed to synchronize %1.", instance)); } void AbstractImportExportJob::slotSynchronizeInstanceDone(const QString &name, const QString &identifier) { Q_EMIT info(i18n("Resource %1 synchronized.", name)); Q_EMIT needSynchronizeResource(name, identifier); } void AbstractImportExportJob::slotAllResourceSynchronized() { Q_EMIT info(i18n("All resources synchronized.")); slotNextStep(); } void AbstractImportExportJob::slotNextStep() { //Implement in sub class. } void AbstractImportExportJob::startSynchronizeResources(const QStringList &listResourceToSync) { Q_EMIT info(i18n("Start synchronizing...")); SynchronizeResourceJob *job = new SynchronizeResourceJob(this); job->setListResources(listResourceToSync); connect(job, &SynchronizeResourceJob::synchronizationFinished, this, &AbstractImportExportJob::slotAllResourceSynchronized); connect(job, &SynchronizeResourceJob::synchronizationInstanceDone, this, &AbstractImportExportJob::slotSynchronizeInstanceDone); connect(job, &SynchronizeResourceJob::synchronizationInstanceFailed, this, &AbstractImportExportJob::slotSynchronizeInstanceFailed); job->start(); } void AbstractImportExportJob::initializeListStep() { if (mTypeSelected & Utils::MailTransport) { mListStep << Utils::MailTransport; } if (mTypeSelected & Utils::Mails) { mListStep << Utils::Mails; } if (mTypeSelected & Utils::Resources) { mListStep << Utils::Resources; } if (mTypeSelected & Utils::Identity) { mListStep << Utils::Identity; } if (mTypeSelected & Utils::Config) { mListStep << Utils::Config; } if (mTypeSelected & Utils::Data) { mListStep << Utils::Data; } } void AbstractImportExportJob::storeDirectory(const QString &subDirectory) { const QDir directoryToStore(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + subDirectory); if (directoryToStore.exists()) { const bool templateDirAdded = archive()->addLocalDirectory(directoryToStore.path(), Utils::dataPath() + subDirectory); if (templateDirAdded) { Q_EMIT info(i18n("Directory \"%1\" added to backup file.", directoryToStore.path())); } else { Q_EMIT error(i18n("Directory \"%1\" cannot be added to backup file.", directoryToStore.path())); } } } void AbstractImportExportJob::importDataSubdirectory(const QString &subdirectoryRelativePath) { const KArchiveEntry *themeEntry = mArchiveDirectory->entry(Utils::dataPath() + subdirectoryRelativePath); if (themeEntry && themeEntry->isDirectory()) { const KArchiveDirectory *themeDir = static_cast(themeEntry); const QStringList lst = themeDir->entries(); for (const QString &entryName : lst) { const KArchiveEntry *entry = themeDir->entry(entryName); if (entry && entry->isDirectory()) { QString subFolderName = entryName; const QString topLevelPath = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1Char('/') + subdirectoryRelativePath; QDir themeDirectory(topLevelPath + QStringLiteral("/%1").arg(entryName)); int i = 1; while (themeDirectory.exists()) { subFolderName = entryName + QStringLiteral("_%1").arg(i); themeDirectory = QDir(topLevelPath + QStringLiteral("/%1").arg(subFolderName)); ++i; } copyToDirectory(entry, topLevelPath + QStringLiteral("/%1").arg(subFolderName)); } } } }