mirror of
https://bitbucket.org/smil3y/kde-playground.git
synced 2025-02-24 10:52:52 +00:00
1354 lines
50 KiB
C++
1354 lines
50 KiB
C++
/*
|
|
Copyright (c) 2009 Jonathan Armond <jon.armond@gmail.com>
|
|
Copyright (c) 2010 Volker Krause <vkrause@kde.org>
|
|
Copyright (C) 2010 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.net
|
|
Author: Kevin Krammer, krake@kdab.com
|
|
Copyright (C) 2011 Kevin Krammer, kevin.krammer@gmx.at
|
|
|
|
This library is free software; you can redistribute it and/or modify it
|
|
under the terms of the GNU Library General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or (at your
|
|
option) any later version.
|
|
|
|
This library 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 Library General Public
|
|
License for more details.
|
|
|
|
You should have received a copy of the GNU Library General Public License
|
|
along with this library; see the file COPYING.LIB. If not, write to the
|
|
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
02110-1301, USA.
|
|
*/
|
|
|
|
#include "kmailmigrator.h"
|
|
|
|
|
|
// avoid metatype.h from interfering
|
|
#define POP3_METATYPE_H
|
|
|
|
#include "imapsettings.h"
|
|
#include "pop3settings.h"
|
|
#include "mboxsettings.h"
|
|
#include "maildirsettings.h"
|
|
#include "mixedmaildirsettings.h"
|
|
#include "mixedmaildirstore.h"
|
|
#include "emptyresourcecleaner.h"
|
|
#include "imapcacheadapter.h"
|
|
#include "imapcachecollectionmigrator.h"
|
|
#include "localfolderscollectionmigrator.h"
|
|
|
|
#include "collectionannotationsattribute.h"
|
|
|
|
#include <Mailtransport/Transport>
|
|
|
|
#include <akonadi/agentmanager.h>
|
|
#include <akonadi/agentinstance.h>
|
|
#include <akonadi/agentinstancecreatejob.h>
|
|
#include <akonadi/attributefactory.h>
|
|
#include <akonadi/tag.h>
|
|
#include <akonadi/tagcreatejob.h>
|
|
#include <akonadi/tagattribute.h>
|
|
using Akonadi::AgentManager;
|
|
using Akonadi::AgentInstance;
|
|
using Akonadi::AgentInstanceCreateJob;
|
|
|
|
#include <KIO/CopyJob>
|
|
|
|
#include <KConfig>
|
|
#include <KConfigGroup>
|
|
#include <KDateTime>
|
|
#include <KDebug>
|
|
#include <KStandardDirs>
|
|
#include <KSharedConfig>
|
|
#include <kwallet.h>
|
|
#include <kstringhandler.h>
|
|
#include <KLocalizedString>
|
|
|
|
Q_DECLARE_METATYPE(QList<int>);
|
|
|
|
using KWallet::Wallet;
|
|
|
|
using namespace KMail;
|
|
|
|
/* Enums for use over DBus. Can't include settings.h for each resource because
|
|
all have same class name. If resource interfaces are changed, these will need
|
|
changing too. */
|
|
enum MboxLocking { Procmail, MuttDotLock, MuttDotLockPrivileged, MboxNone };
|
|
|
|
#define SPECIALCOLLECTIONS_LOCK_SERVICE QLatin1String( "org.kde.pim.SpecialCollections" )
|
|
|
|
static MixedMaildirStore *createStoreFromBasePath( const QString &basePath )
|
|
{
|
|
MixedMaildirStore *store = 0;
|
|
const QFileInfo baseDir( basePath );
|
|
if ( baseDir.exists() && baseDir.isDir() ) {
|
|
store = new MixedMaildirStore;
|
|
store->setPath( baseDir.absoluteFilePath() );
|
|
}
|
|
|
|
return store;
|
|
}
|
|
|
|
static void backupConfig( const QString &name, const QDir &backupDir )
|
|
{
|
|
const QString configFile = KStandardDirs::locate( "config", name );
|
|
if ( !configFile.isEmpty() ) {
|
|
QFile::copy( configFile, QFileInfo( backupDir, name ).absoluteFilePath() );
|
|
}
|
|
}
|
|
|
|
KMailMigrator::KMailMigrator() :
|
|
KMigratorBase(),
|
|
mWallet( 0 ),
|
|
mDImapCache( 0 ),
|
|
mImapCache( 0 ),
|
|
mForwardResourceNotifications( false ),
|
|
mImapCacheAdapter( 0 )
|
|
{
|
|
Akonadi::AttributeFactory::registerAttribute<Akonadi::CollectionAnnotationsAttribute>();
|
|
connect( AgentManager::self(), SIGNAL(instanceStatusChanged(Akonadi::AgentInstance)),
|
|
this, SLOT(instanceStatusChanged(Akonadi::AgentInstance)) );
|
|
connect( AgentManager::self(), SIGNAL(instanceProgressChanged(Akonadi::AgentInstance)),
|
|
this, SLOT(instanceProgressChanged(Akonadi::AgentInstance)) );
|
|
}
|
|
|
|
KMailMigrator::~KMailMigrator()
|
|
{
|
|
delete mWallet;
|
|
delete mDImapCache;
|
|
delete mImapCache;
|
|
}
|
|
|
|
void KMailMigrator::migrate()
|
|
{
|
|
emit message( Info, i18n( "Beginning KMail migration..." ) );
|
|
|
|
// copy config files to backup locations
|
|
const KDateTime now = KDateTime::currentLocalDateTime();
|
|
const QDir backupDir( KGlobal::dirs()->saveLocation( "appdata", now.toString() ) );
|
|
|
|
// copy current configs to backup location
|
|
// strickly speaking neither kmailrc not mailtransports are changed by the migrator
|
|
// but copy them anyway as the belong conceptually to the KMail1 -> KMail2 migration
|
|
backupConfig( QLatin1String("kmailrc"), backupDir );
|
|
backupConfig( QLatin1String("mailtransports"), backupDir );
|
|
backupConfig( QLatin1String("emailidentities"), backupDir );
|
|
backupConfig( QLatin1String("kcmkmailsummaryrc"), backupDir );
|
|
backupConfig( QLatin1String("templatesconfigurationrc"), backupDir );
|
|
|
|
KSharedConfigPtr oldConfig = KSharedConfig::openConfig( QLatin1String( "kmailrc" ) );
|
|
mConfig = KSharedConfig::openConfig( QLatin1String( "kmail2rc" ) );
|
|
|
|
const QFileInfo migratorConfigInfo( KStandardDirs::locateLocal( "config", KGlobal::config()->name() ) );
|
|
|
|
const QString &newKMailCfgFile = KStandardDirs::locateLocal( "config", QLatin1String( "kmail2rc" ) );
|
|
|
|
// copy old config into new config, if
|
|
bool copy = false;
|
|
// there is no migrator config (no migration happened yet or full rerun)
|
|
copy = copy || !migratorConfigInfo.exists();
|
|
// new config does not exist yet
|
|
copy = copy || !QFileInfo( newKMailCfgFile ).exists();
|
|
// new config is empty
|
|
copy = copy || mConfig->groupList().isEmpty();
|
|
// new config does not contain any account groups
|
|
copy = copy || mConfig->groupList().filter( QRegExp( QLatin1String("Account \\d+") ) ).isEmpty();
|
|
|
|
if ( copy ) {
|
|
kDebug() << "Copying content from kmailrc";
|
|
oldConfig->copyTo( newKMailCfgFile, mConfig.data() );
|
|
} else {
|
|
kDebug() << "Ignoring kmailrc, just using contents from kmail2rc";
|
|
}
|
|
|
|
mEmailIdentityConfig = KSharedConfig::openConfig( QLatin1String( "emailidentities" ) );
|
|
|
|
mKcmKmailSummaryConfig = KSharedConfig::openConfig( QLatin1String( "kcmkmailsummaryrc" ) );
|
|
|
|
mTemplatesConfig = KSharedConfig::openConfig( QLatin1String( "templatesconfigurationrc" ) );
|
|
|
|
deleteOldGroup();
|
|
migrateTags();
|
|
migrateRCFiles();
|
|
migrateNotifyFile();
|
|
|
|
// copy autosave files if there are any
|
|
const QString autoSaveDir = KGlobal::dirs()->saveLocation( "data", QLatin1String("kmail/autosave"), false );
|
|
if ( !autoSaveDir.isEmpty() ) {
|
|
const QString destDir = KGlobal::dirs()->saveLocation( "data", QLatin1String("kmail2") );
|
|
KIO::CopyJob *job = KIO::copy( KUrl::fromPath( autoSaveDir ),
|
|
KUrl::fromPath( destDir ),
|
|
KIO::HideProgressInfo );
|
|
job->setAutoSkip( true );
|
|
job->setWriteIntoExistingDirectories( true );
|
|
connect( job, SIGNAL(result(KJob*)), this, SLOT(autoSaveCopyResult(KJob*)) );
|
|
}
|
|
|
|
mAccounts = mConfig->groupList().filter( QRegExp( QLatin1String("Account \\d+") ) );
|
|
|
|
mIt = mAccounts.begin();
|
|
migrateNext();
|
|
}
|
|
|
|
void KMailMigrator::autoSaveCopyResult( KJob *job )
|
|
{
|
|
if ( job->error() ) {
|
|
kDebug( KDE_DEFAULT_DEBUG_AREA ) << "error=" << job->error()
|
|
<< "text=" << job->errorString();
|
|
}
|
|
}
|
|
|
|
void KMailMigrator::deleteOldGroup()
|
|
{
|
|
deleteOldGroup( QLatin1String("GroupwareFolderInfo") );
|
|
deleteOldGroup( QLatin1String("Groupware") );
|
|
deleteOldGroup( QLatin1String("IMAP Resource") );
|
|
deleteOldGroup( QLatin1String("Folder_local_root") );
|
|
deleteOldGroup( QLatin1String("Folder_search") );
|
|
}
|
|
|
|
void KMailMigrator::deleteOldGroup( const QString& name ) {
|
|
if ( mConfig->hasGroup( name ) ) {
|
|
KConfigGroup groupName( mConfig, name );
|
|
groupName.deleteGroup();
|
|
}
|
|
}
|
|
|
|
void KMailMigrator::migrateNotifyFile()
|
|
{
|
|
const QString notifyFile = KStandardDirs::locate( "config", QLatin1String("kmail.notifyrc") );
|
|
if ( !notifyFile.isEmpty() ) {
|
|
QFile::copy( notifyFile, KStandardDirs::locateLocal( "config", QLatin1String("kmail2.notifyrc" )) );
|
|
}
|
|
|
|
}
|
|
|
|
void KMailMigrator::migrateTags()
|
|
{
|
|
KConfigGroup tagMigrationConfig( KGlobal::config(), QLatin1String( "MessageTags" ) );
|
|
const QStringList migratedTags = tagMigrationConfig.readEntry( "MigratedTags", QStringList() );
|
|
|
|
const QStringList tagGroups = mConfig->groupList().filter( QRegExp( QLatin1String("MessageTag #\\d+") ) );
|
|
|
|
QSet<QString> groupNames = tagGroups.toSet();
|
|
groupNames.subtract( migratedTags.toSet() );
|
|
|
|
kDebug() << "Tag Groups:" << tagGroups << "MigratedTags:" << migratedTags
|
|
<< "Unmigrated Tags:" << groupNames;
|
|
|
|
QStringList newlyMigratedTags;
|
|
Q_FOREACH ( const QString &groupName, groupNames ) {
|
|
const KConfigGroup group( mConfig, groupName );
|
|
|
|
const QString label = group.readEntry( QLatin1String( "Label" ), QString() );
|
|
if ( label.isEmpty() ) {
|
|
continue;
|
|
}
|
|
const QString name = group.readEntry( QLatin1String( "Name" ), QString() );
|
|
if ( name.isEmpty() ) {
|
|
continue;
|
|
}
|
|
|
|
const QColor textColor = group.readEntry( QLatin1String( "text-color" ), QColor() );
|
|
const QColor backgroundColor = group.readEntry( QLatin1String( "background-color" ), QColor() );
|
|
const bool hasFont = group.hasKey( QLatin1String( "text-font" ) );
|
|
const QFont textFont = group.readEntry( QLatin1String( "text-font" ), QFont() );
|
|
|
|
const bool inToolbar = group.readEntry( QLatin1String( "toolbar" ), false );
|
|
const QString iconName = group.readEntry( QLatin1String( "icon" ), QString::fromLatin1( "mail-tagged" ) );
|
|
|
|
const QString shortcut = group.readEntry( QLatin1String( "shortcut" ), QString() );
|
|
|
|
Akonadi::Tag tag(label);
|
|
Akonadi::TagAttribute *attr = tag.attribute<Akonadi::TagAttribute>(Akonadi::AttributeEntity::AddIfMissing);
|
|
attr->setDisplayName(name);
|
|
attr->setIconName( iconName );
|
|
attr->setInToolbar( inToolbar );
|
|
if (hasFont) {
|
|
attr->setFont( textFont.toString() );
|
|
}
|
|
attr->setBackgroundColor( backgroundColor );
|
|
attr->setTextColor( textColor );
|
|
attr->setShortcut( shortcut );
|
|
|
|
Akonadi::TagCreateJob *createJob = new Akonadi::TagCreateJob(tag);
|
|
createJob->setMergeIfExisting(true);
|
|
|
|
kDebug() << "Tag: label=" << label << "name=" << name
|
|
<< "textColor=" << textColor << "backgroundColor=" << backgroundColor
|
|
<< "hasFont=" << hasFont << "font=" << textFont
|
|
<< "icon=" << iconName << "inToolbar=" << inToolbar
|
|
<< "shortcut=" << shortcut;
|
|
|
|
newlyMigratedTags << groupName;
|
|
}
|
|
|
|
//Cleanup migrated group
|
|
Q_FOREACH ( const QString &groupName, newlyMigratedTags ) {
|
|
deleteOldGroup( groupName );
|
|
}
|
|
|
|
if ( !newlyMigratedTags.isEmpty() ) {
|
|
tagMigrationConfig.writeEntry( "MigratedTags", migratedTags + newlyMigratedTags );
|
|
tagMigrationConfig.sync();
|
|
}
|
|
}
|
|
|
|
void KMailMigrator::migrateRCFiles()
|
|
{
|
|
const QDir sourceDir( KStandardDirs::locateLocal( "data", QLatin1String("kmail") ) );
|
|
const QDir targetDir( KStandardDirs::locateLocal( "data", QLatin1String("kmail2") ) );
|
|
KStandardDirs::makeDir( targetDir.absolutePath() );
|
|
|
|
const QFileInfoList files = sourceDir.entryInfoList( QStringList() << QLatin1String( "*.rc" ),
|
|
QDir::Files | QDir::Readable );
|
|
Q_FOREACH ( const QFileInfo &fileInfo, files ) {
|
|
QFile file( fileInfo.absoluteFilePath() );
|
|
file.copy( QFileInfo( targetDir, fileInfo.fileName() ).absoluteFilePath() );
|
|
}
|
|
}
|
|
|
|
void KMailMigrator::migrateNext()
|
|
{
|
|
while ( mIt != mAccounts.end() ) {
|
|
mCurrentAccount = *mIt;
|
|
const KConfigGroup group( mConfig, mCurrentAccount );
|
|
|
|
const QString name = group.readEntry( "Name" );
|
|
const QString idString = group.readEntry( "Id" );
|
|
if ( migrationState( idString ) == None ) {
|
|
++mIt;
|
|
if ( !migrateCurrentAccount() ) {
|
|
emit message( Error, i18n( "No backend for '%1' available.", name ) );
|
|
migrateNext();
|
|
}
|
|
return;
|
|
}
|
|
|
|
if ( migrationState( idString ) == Complete )
|
|
emit message( Skip, i18n( "'%1' has been already migrated.", name ) );
|
|
|
|
++mIt;
|
|
}
|
|
if ( mIt == mAccounts.end() ) {
|
|
if ( mImapCacheAdapter != 0 ) {
|
|
emit message( Info, i18n( "Enabling access to the disconnected IMAP cache of the previous KMail version" ) );
|
|
emit status( QString() );
|
|
mImapCacheAdapter->start();
|
|
} else {
|
|
migrateLocalFolders();
|
|
}
|
|
}
|
|
}
|
|
|
|
void KMailMigrator::migrateLocalFolders()
|
|
{
|
|
if ( migrationState( QLatin1String("LocalFolders") ) == Complete ) {
|
|
emit message( Skip, i18n( "Local folders have already been migrated." ) );
|
|
emit status( QString() );
|
|
migrationDone();
|
|
return;
|
|
}
|
|
|
|
KConfigGroup cfgGroup( mConfig, "General" );
|
|
cfgGroup.deleteEntry( "QuotaUnit" );
|
|
cfgGroup.deleteEntry( "default-mailbox-format" );
|
|
mConfig->sync();
|
|
const QString localMaildirDefaultPath = KStandardDirs::locateLocal( "data", QLatin1String( "kmail/mail" ) );
|
|
mLocalMaildirPath = cfgGroup.readPathEntry( "folders", localMaildirDefaultPath );
|
|
const QFileInfo fileInfo( mLocalMaildirPath );
|
|
if ( !fileInfo.exists() || !fileInfo.isDir() ) {
|
|
emit status( QString() );
|
|
migrationDone();
|
|
} else {
|
|
kDebug() << mLocalMaildirPath;
|
|
|
|
emit message( Info, i18nc( "@info:status", "Migrating local folders in '%1'...", mLocalMaildirPath ) );
|
|
|
|
// show status/progress info of resources in our dialog
|
|
mForwardResourceNotifications = true;
|
|
|
|
createAgentInstance( QLatin1String("akonadi_mixedmaildir_resource"), this,
|
|
SLOT(localMaildirCreated(KJob*)) );
|
|
}
|
|
}
|
|
|
|
void KMailMigrator::migrationDone()
|
|
{
|
|
emit message( Success, i18n( "Migration successfully completed." ) );
|
|
|
|
migrateInstanceTrashFolder();
|
|
|
|
mConfig->sync();
|
|
kDebug() << "Deleting" << mFailedInstances.count() << "failed resource instances";
|
|
Q_FOREACH ( const AgentInstance &instance, mFailedInstances ) {
|
|
if ( instance.isValid() ) {
|
|
AgentManager::self()->removeInstance( instance );
|
|
}
|
|
}
|
|
cleanupConfigFile();
|
|
migrateConfigurationDialogRestriction();
|
|
deleteLater();
|
|
}
|
|
|
|
OrgKdeAkonadiImapSettingsInterface* KMailMigrator::createImapSettingsInterface( const Akonadi::AgentInstance& instance )
|
|
{
|
|
OrgKdeAkonadiImapSettingsInterface *iface = new OrgKdeAkonadiImapSettingsInterface(
|
|
QLatin1String("org.freedesktop.Akonadi.Resource.") + instance.identifier(),
|
|
QLatin1String("/Settings"), QDBusConnection::sessionBus(), this );
|
|
if ( !iface->isValid() ) {
|
|
migrationFailed( i18n( "Failed to obtain D-Bus interface for remote configuration." ), instance );
|
|
delete iface;
|
|
return 0;
|
|
}
|
|
return iface;
|
|
}
|
|
|
|
OrgKdeAkonadiPOP3SettingsInterface* KMailMigrator::createPop3SettingsInterface( const Akonadi::AgentInstance& instance )
|
|
{
|
|
OrgKdeAkonadiPOP3SettingsInterface *iface = new OrgKdeAkonadiPOP3SettingsInterface(
|
|
QLatin1String("org.freedesktop.Akonadi.Resource.") + instance.identifier(),
|
|
QLatin1String("/Settings"), QDBusConnection::sessionBus(), this );
|
|
if ( !iface->isValid() ) {
|
|
migrationFailed( i18n( "Failed to obtain D-Bus interface for remote configuration." ), instance );
|
|
delete iface;
|
|
return 0;
|
|
}
|
|
return iface;
|
|
}
|
|
|
|
void KMailMigrator::migrateConfigurationDialogRestriction()
|
|
{
|
|
if ( mConfig->hasGroup( "ConfigurationDialogRestrictions" ) ) {
|
|
KSharedConfigPtr resourcebaseconfig = KSharedConfig::openConfig( QLatin1String( "resourcebaserc" ) );
|
|
KConfigGroup oldGroup = mConfig->group( "ConfigurationDialogRestrictions" );
|
|
KConfigGroup newGroup = resourcebaseconfig->group( "ConfigurationDialogRestrictions" );
|
|
oldGroup.copyTo( &newGroup );
|
|
oldGroup.deleteGroup();
|
|
}
|
|
|
|
}
|
|
|
|
void KMailMigrator::cleanupConfigFile()
|
|
{
|
|
mIt = mAccounts.begin();
|
|
AccountIterator end( mAccounts.end() ) ;
|
|
|
|
while ( mIt != end ) {
|
|
const QString accountName = *mIt;
|
|
deleteOldGroup( accountName );
|
|
++mIt;
|
|
}
|
|
|
|
deleteOldGroup( QLatin1String("FavoriteFolderView") );
|
|
|
|
if ( mConfig->hasGroup( "Internal" ) ) {
|
|
KConfigGroup cfgGroup( mConfig, "General" );
|
|
cfgGroup.deleteEntry( "MsgDictSizeHint" );
|
|
}
|
|
}
|
|
|
|
void KMailMigrator::migrateInstanceTrashFolder()
|
|
{
|
|
mIt = mAccounts.begin();
|
|
while ( mIt != mAccounts.end() ) {
|
|
const QString accountName = *mIt;
|
|
const KConfigGroup group( mConfig, accountName );
|
|
if ( mAccountInstance.contains( accountName ) ) {
|
|
AccountConfig accountConf = mAccountInstance.value( accountName );
|
|
Akonadi::AgentInstance instance = accountConf.instance;
|
|
if ( accountConf.imapAccount ) { //Imap
|
|
OrgKdeAkonadiImapSettingsInterface *iface = createImapSettingsInterface( instance );
|
|
if ( iface ) {
|
|
const qint64 value = group.readEntry( "trash", -1 );
|
|
if ( value != -1 ) {
|
|
iface->setTrashCollection( value );
|
|
// make sure the config is saved
|
|
iface->writeConfig();
|
|
instance.reconfigure();
|
|
}
|
|
}
|
|
} else { //Pop3
|
|
OrgKdeAkonadiPOP3SettingsInterface *iface = createPop3SettingsInterface( instance );
|
|
if ( iface ) {
|
|
const qint64 value = group.readEntry( "Folder", -1 );
|
|
if ( value != -1 ) {
|
|
iface->setTargetCollection( value );
|
|
// make sure the config is saved
|
|
iface->writeConfig();
|
|
instance.reconfigure();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
++mIt;
|
|
}
|
|
}
|
|
|
|
void KMailMigrator::migrationFailed( const QString &errorMsg,
|
|
bool doMigrateNext,
|
|
const AgentInstance &instance )
|
|
{
|
|
const KConfigGroup group( mConfig, mCurrentAccount );
|
|
emit message( Error, i18n( "Migration of '%1' to Akonadi resource failed: %2",
|
|
group.readEntry( "Name" ), errorMsg ) );
|
|
|
|
if ( instance.isValid() ) {
|
|
mFailedInstances << instance;
|
|
}
|
|
|
|
mCurrentAccount.clear();
|
|
mCurrentInstance = AgentInstance();
|
|
|
|
if ( doMigrateNext ) {
|
|
migrateNext();
|
|
}
|
|
}
|
|
|
|
void KMailMigrator::migrationCompleted( const AgentInstance &instance, bool doMigrateNext )
|
|
{
|
|
const KConfigGroup group( mConfig, mCurrentAccount );
|
|
const QString accountId = group.readEntry( QLatin1String( "Id" ) );
|
|
|
|
// check if the account is used in filters
|
|
const QStringList filterGroups = mConfig->groupList().filter( QRegExp( QLatin1String("Filter #\\d+") ) );
|
|
//kDebug( KDE_DEFAULT_DEBUG_AREA ) << "filterGroups=" << filterGroups;
|
|
Q_FOREACH ( const QString &groupName, filterGroups ) {
|
|
KConfigGroup filterGroup( mConfig, groupName );
|
|
|
|
QStringList accountsSet = filterGroup.readEntry( QLatin1String( "accounts-set" ), QStringList() );
|
|
//if ( !accountsSet.isEmpty() ) {
|
|
// kDebug( KDE_DEFAULT_DEBUG_AREA ) << "accountsSet=" << accountsSet;
|
|
//}
|
|
const int index = accountsSet.indexOf( accountId );
|
|
if ( index != -1 ) {
|
|
kDebug( KDE_DEFAULT_DEBUG_AREA ) << "replacing account id" << accountId
|
|
<< "in filter" << groupName
|
|
<< "with resource id" << instance.identifier();
|
|
accountsSet.replace( index, instance.identifier() );
|
|
filterGroup.writeEntry( QLatin1String( "accounts-set" ), accountsSet );
|
|
}
|
|
}
|
|
|
|
setMigrationState( group.readEntry( "Id" ), Complete, instance.identifier(),
|
|
group.readEntry( "Type" ).toLower() );
|
|
emit message( Success, i18n( "Migration of '%1' succeeded.", group.readEntry( "Name" ) ) );
|
|
mCurrentAccount.clear();
|
|
mCurrentInstance = AgentInstance();
|
|
|
|
if ( doMigrateNext ) {
|
|
migrateNext();
|
|
}
|
|
}
|
|
|
|
void KMailMigrator::connectCollectionMigrator( AbstractCollectionMigrator *migrator )
|
|
{
|
|
connect( migrator, SIGNAL(message(int,QString)),
|
|
SLOT (collectionMigratorMessage(int,QString)) );
|
|
connect( migrator, SIGNAL(status(QString)), SIGNAL (status(QString)) );
|
|
connect( migrator, SIGNAL(progress(int)), SIGNAL (progress(int)) );
|
|
connect( migrator, SIGNAL(progress(int,int,int)), SIGNAL (progress(int,int,int)) );
|
|
connect( migrator, SIGNAL(migrationFinished(Akonadi::AgentInstance,QString)),
|
|
this, SLOT(collectionMigratorFinished()) );
|
|
connect( migrator, SIGNAL(status(QString)),
|
|
SLOT (collectionMigratorEmittedNotification()) );
|
|
connect( migrator, SIGNAL(progress(int)),
|
|
SLOT (collectionMigratorEmittedNotification()) );
|
|
connect( migrator, SIGNAL(progress(int,int,int)),
|
|
SLOT (collectionMigratorEmittedNotification()) );
|
|
}
|
|
|
|
void KMailMigrator::migratePassword( const QString &idString, const AgentInstance &instance,
|
|
const QString &newFolder, const QString& passwordFromFilePassword )
|
|
{
|
|
QString password;
|
|
if ( mWallet == 0 ) {
|
|
mWallet = Wallet::openWallet( Wallet::NetworkWallet(), 0 );
|
|
}
|
|
if ( mWallet && mWallet->isOpen() ) {
|
|
if ( !passwordFromFilePassword.isEmpty() )
|
|
password = passwordFromFilePassword;
|
|
|
|
if ( password.isEmpty() && mWallet->hasFolder( QLatin1String("kmail") ) ) {
|
|
mWallet->setFolder( QLatin1String("kmail") );
|
|
mWallet->readPassword( QLatin1String("account-") + idString, password );
|
|
}
|
|
|
|
if ( !password.isEmpty() ) {
|
|
if ( !mWallet->hasFolder( newFolder ) )
|
|
mWallet->createFolder( newFolder );
|
|
mWallet->setFolder( newFolder );
|
|
|
|
mWallet->writePassword( instance.identifier() + QLatin1String("rc") , password );
|
|
}
|
|
}
|
|
}
|
|
|
|
bool KMailMigrator::migrateCurrentAccount()
|
|
{
|
|
if ( mCurrentAccount.isEmpty() )
|
|
return false;
|
|
const KConfigGroup group( mConfig, mCurrentAccount );
|
|
|
|
emit message( Info, i18n( "Trying to migrate '%1' to resource...", group.readEntry( "Name" ) ) );
|
|
|
|
// show status/progress info of resources in our dialog
|
|
mForwardResourceNotifications = true;
|
|
|
|
const QString type = group.readEntry( "Type" ).toLower();
|
|
if ( type == QLatin1String( "imap" ) ) {
|
|
createAgentInstance( QLatin1String("akonadi_imap_resource"), this,
|
|
SLOT(imapAccountCreated(KJob*)) );
|
|
} else if ( type == QLatin1String( "dimap" ) ) {
|
|
createAgentInstance( QLatin1String("akonadi_imap_resource"), this,
|
|
SLOT(imapDisconnectedAccountCreated(KJob*)) );
|
|
|
|
} else if ( type == QLatin1String( "pop" ) ) {
|
|
createAgentInstance( QLatin1String("akonadi_pop3_resource"), this,
|
|
SLOT(pop3AccountCreated(KJob*)) );
|
|
} else if ( type == QLatin1String( "maildir" ) ) {
|
|
createAgentInstance( QLatin1String("akonadi_maildir_resource"), this,
|
|
SLOT(maildirAccountCreated(KJob*)) );
|
|
} else if ( type == QLatin1String( "local" ) ) {
|
|
createAgentInstance( QLatin1String("akonadi_mbox_resource"), this,
|
|
SLOT(mboxAccountCreated(KJob*)) );
|
|
} else {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void KMailMigrator::imapDisconnectedAccountCreated( KJob * job )
|
|
{
|
|
if ( job->error() ) {
|
|
migrationFailed( i18n( "Failed to create resource: %1", job->errorText() ) );
|
|
return;
|
|
}
|
|
emit message( Info, i18n( "Created disconnected imap resource" ) );
|
|
migrateImapAccount( job, true );
|
|
}
|
|
|
|
void KMailMigrator::imapAccountCreated( KJob *job )
|
|
{
|
|
if ( job->error() ) {
|
|
migrationFailed( i18n( "Failed to create resource: %1", job->errorText() ) );
|
|
return;
|
|
}
|
|
emit message( Info, i18n( "Created imap resource" ) );
|
|
migrateImapAccount( job, false );
|
|
}
|
|
|
|
|
|
void KMailMigrator::migrateImapAccount( KJob *job, bool disconnected )
|
|
{
|
|
AgentInstance instance = static_cast< AgentInstanceCreateJob* >( job )->instance();
|
|
mCurrentInstance = instance;
|
|
|
|
AccountConfig conf;
|
|
conf.instance = instance;
|
|
conf.imapAccount = true;
|
|
conf.disconnectedImap = disconnected;
|
|
mAccountInstance.insert( mCurrentAccount, conf );
|
|
|
|
KConfigGroup config( mConfig, mCurrentAccount );
|
|
|
|
const QString nameAccount = config.readEntry( "Name" );
|
|
instance.setName( nameAccount );
|
|
emit status( nameAccount );
|
|
|
|
ImapCacheCollectionMigrator::MigrationOptions options = ImapCacheCollectionMigrator::ImportNewMessages;
|
|
if ( disconnected ) {
|
|
const KConfigGroup dimapConfig( KGlobal::config(), QLatin1String( "Disconnected IMAP" ) );
|
|
if ( dimapConfig.isValid() ) {
|
|
options = ImapCacheCollectionMigrator::ConfigOnly;
|
|
|
|
if ( dimapConfig.readEntry( QLatin1String( "ImportNewMessages" ), false ) ) {
|
|
options |= ImapCacheCollectionMigrator::ImportNewMessages;
|
|
}
|
|
|
|
if ( dimapConfig.readEntry( QLatin1String( "ImportCachedMessages" ), false ) ) {
|
|
options |= ImapCacheCollectionMigrator::ImportCachedMessages;
|
|
}
|
|
|
|
if ( dimapConfig.readEntry( QLatin1String( "RemoveDeletedMessages" ), false ) ) {
|
|
options |= ImapCacheCollectionMigrator::RemoveDeletedMessages;
|
|
}
|
|
}
|
|
}
|
|
|
|
MixedMaildirStore *store = 0;
|
|
if ( disconnected ) {
|
|
#if 0
|
|
if ( mDeleteCacheAfterImport ) {
|
|
options |= ImapCacheCollectionMigrator::DeleteImportedMessages;
|
|
}
|
|
#endif
|
|
if ( mDImapCache == 0 ) {
|
|
mDImapCache = createStoreFromBasePath( KStandardDirs::locateLocal( "data", QLatin1String( "kmail/dimap" ) ) );
|
|
}
|
|
store = mDImapCache;
|
|
} else {
|
|
if ( mImapCache == 0 ) {
|
|
mImapCache = createStoreFromBasePath( KStandardDirs::locateLocal( "data", QLatin1String( "kmail/imap" ) ) );
|
|
}
|
|
store = mImapCache;
|
|
}
|
|
|
|
ImapCacheCollectionMigrator *collectionMigrator = new ImapCacheCollectionMigrator( instance, nameAccount, store, this );
|
|
QString topLevelFolder = config.readEntry( "Folder" );
|
|
if ( topLevelFolder.isEmpty() ) {
|
|
topLevelFolder = config.readEntry( "Id" );
|
|
}
|
|
|
|
const QString topLevelRemoteId =
|
|
QLatin1String("imap://") + config.readEntry( "login" ) + QLatin1Char('@') + config.readEntry( "host" ) + QLatin1Char('/');
|
|
|
|
collectionMigrator->setTopLevelFolder( topLevelFolder, nameAccount, topLevelRemoteId );
|
|
collectionMigrator->setMigrationOptions( options );
|
|
|
|
kDebug() << "Starting IMAP collection migration: options="
|
|
<< collectionMigrator->migrationOptions();
|
|
collectionMigrator->setKMailConfig( mConfig );
|
|
collectionMigrator->setEmailIdentityConfig( mEmailIdentityConfig );
|
|
collectionMigrator->setKcmKmailSummaryConfig( mKcmKmailSummaryConfig );
|
|
collectionMigrator->setTemplatesConfig( mTemplatesConfig );
|
|
|
|
if ( config.readEntry( "locally-subscribed-folders", false ) ) {
|
|
collectionMigrator->setUnsubscribedImapFolders( config.readEntry( "locallyUnsubscribedFolders", QStringList() ) );
|
|
}
|
|
|
|
if ( disconnected && store ) {
|
|
if ( mImapCacheAdapter == 0 ) {
|
|
mImapCacheAdapter = new ImapCacheAdapter( store, this );
|
|
connect( mImapCacheAdapter, SIGNAL(finished(int,QString)),
|
|
SLOT(imapCacheAdaptionFinished(int,QString)) );
|
|
}
|
|
mImapCacheAdapter->addAccount( topLevelFolder, nameAccount );
|
|
}
|
|
|
|
connect( collectionMigrator, SIGNAL(migrationFinished(Akonadi::AgentInstance,QString)),
|
|
SLOT(imapFoldersMigrationFinished(Akonadi::AgentInstance,QString)) );
|
|
|
|
connectCollectionMigrator( collectionMigrator );
|
|
|
|
collectionMigrator->startMigration();
|
|
}
|
|
|
|
void KMailMigrator::pop3AccountCreated( KJob *job )
|
|
{
|
|
if ( job->error() ) {
|
|
migrationFailed( i18n( "Failed to create resource: %1", job->errorText() ) );
|
|
return;
|
|
}
|
|
emit message( Info, i18n( "Created pop3 resource" ) );
|
|
|
|
AgentInstance instance = static_cast< AgentInstanceCreateJob* >( job )->instance();
|
|
mCurrentInstance = instance;
|
|
KConfigGroup config( mConfig, mCurrentAccount );
|
|
|
|
OrgKdeAkonadiPOP3SettingsInterface *iface = createPop3SettingsInterface( instance );
|
|
if ( !iface ) {
|
|
return;
|
|
}
|
|
|
|
AccountConfig conf;
|
|
conf.instance = instance;
|
|
conf.imapAccount = false;
|
|
mAccountInstance.insert( mCurrentAccount, conf );
|
|
|
|
iface->setHost( config.readEntry( "host", QString() ) );
|
|
iface->setPort( config.readEntry( "port", 110u ) );
|
|
iface->setLogin( config.readEntry( "login", QString() ) );
|
|
if ( config.readEntry( "use-ssl", true ) )
|
|
iface->setUseSSL( true );
|
|
if ( config.readEntry( "use-tls", true ) )
|
|
iface->setUseTLS( true );
|
|
if ( config.readEntry( "pipelining", false ) )
|
|
iface->setPipelining( true );
|
|
if ( config.readEntry( "leave-on-server", true ) ) {
|
|
iface->setLeaveOnServer( true );
|
|
iface->setLeaveOnServerDays( config.readEntry( "leave-on-server-days", -1 ) );
|
|
iface->setLeaveOnServerCount( config.readEntry( "leave-on-server-count", -1 ) );
|
|
iface->setLeaveOnServerSize( config.readEntry( "leave-on-server-size", -1 ) );
|
|
}
|
|
if ( config.readEntry( "filter-on-server", false ) ) {
|
|
iface->setFilterOnServer( true );
|
|
iface->setFilterCheckSize( config.readEntry( "filter-os-check-size" ).toUInt() );
|
|
}
|
|
const int checkInterval = config.readEntry( "check-interval", 0 );
|
|
if ( checkInterval == 0 )
|
|
iface->setIntervalCheckEnabled( false );
|
|
else {
|
|
iface->setIntervalCheckEnabled( true );
|
|
iface->setIntervalCheckInterval( checkInterval );
|
|
}
|
|
|
|
// check-exclude in Account section means that this account should not be included
|
|
// in manual checks. In KMail UI this is called "Include in manual checks"
|
|
KConfigGroup resourceGroup( mConfig, QString::fromLatin1( "Resource %1" ).arg( instance.identifier() ) );
|
|
resourceGroup.writeEntry( "IncludeInManualChecks", !config.readEntry( "check-exclude", false ) );
|
|
const KConfigGroup generalGroup( mConfig, "General" );
|
|
resourceGroup.writeEntry( "CheckOnStartup", generalGroup.readEntry( "checkmail-startup", false ) );
|
|
resourceGroup.writeEntry( "OfflineOnShutdown", true );
|
|
|
|
// Akonadi kmail uses enums for storing auth options
|
|
// so we have to convert from the old string representations
|
|
typedef MailTransport::Transport::EnumAuthenticationType AuthType;
|
|
QString authOpt = config.readEntry( "auth" );
|
|
if ( authOpt.contains( QLatin1String("PLAIN"), Qt::CaseInsensitive ) )
|
|
iface->setAuthenticationMethod( AuthType::PLAIN );
|
|
else if ( authOpt.contains( QLatin1String("CRAM"), Qt::CaseInsensitive ) )
|
|
iface->setAuthenticationMethod( AuthType::CRAM_MD5 );
|
|
else if ( authOpt.contains( QLatin1String("DIGEST"), Qt::CaseInsensitive ) )
|
|
iface->setAuthenticationMethod( AuthType::DIGEST_MD5);
|
|
else if ( authOpt.contains( QLatin1String("GSSAPI"), Qt::CaseInsensitive ) )
|
|
iface->setAuthenticationMethod( AuthType::GSSAPI );
|
|
else if ( authOpt.contains( QLatin1String("NTLM"), Qt::CaseInsensitive ) )
|
|
iface->setAuthenticationMethod( AuthType::NTLM);
|
|
else if ( authOpt.contains( QLatin1String("APOP"), Qt::CaseInsensitive ) )
|
|
iface->setAuthenticationMethod( AuthType::APOP );
|
|
else
|
|
iface->setAuthenticationMethod( AuthType::CLEAR );
|
|
iface->setPrecommand( config.readPathEntry( "precommand", QString() ) );
|
|
|
|
QString encpasswd;
|
|
|
|
if ( config.readEntry( "store-passwd", false ) ) {
|
|
encpasswd = config.readEntry( "pass" );
|
|
if ( encpasswd.isEmpty() ) {
|
|
encpasswd = config.readEntry( "passwd" );
|
|
if ( !encpasswd.isEmpty() )
|
|
encpasswd = importPassword( encpasswd );
|
|
}
|
|
|
|
if ( !encpasswd.isEmpty() ) {
|
|
encpasswd = KStringHandler::obscure( encpasswd );
|
|
}
|
|
config.deleteEntry( "store-passwd" );
|
|
config.deleteEntry( "passwd" );
|
|
}
|
|
migratePassword( config.readEntry( "Id" ), instance, QLatin1String("pop3"), encpasswd );
|
|
|
|
// POP3 filter from files in kmail appdata
|
|
const QString popFilterFileName = QString::fromLatin1( "kmail/%1:@%2:%3" )
|
|
.arg( config.readEntry( "login", QString() ) )
|
|
.arg( config.readEntry( "host", QString() ) )
|
|
.arg( config.readEntry( "port", 110u ) );
|
|
|
|
const KConfig popFilterConfig( popFilterFileName, KConfig::SimpleConfig, "data" );
|
|
const KConfigGroup popFilterGroup( &popFilterConfig, QString() );
|
|
iface->setDownloadLater( popFilterGroup.readEntry( "downloadLater", QStringList() ) );
|
|
iface->setSeenUidList( popFilterGroup.readEntry( "seenUidList", QStringList() ) );
|
|
iface->setSeenUidTimeList( popFilterGroup.readEntry( "seenUidTimeList", QList<int>() ) );
|
|
|
|
// make sure the config is saved
|
|
iface->writeConfig();
|
|
|
|
//Info: there is trash item in config which is default and we can't configure it => don't look at it in pop account.
|
|
config.deleteEntry( "trash" );
|
|
config.deleteEntry( "use-default-identity" );
|
|
const QString nameAccount = config.readEntry( "Name" );
|
|
instance.setName( nameAccount );
|
|
emit status( nameAccount );
|
|
instance.reconfigure();
|
|
config.sync();
|
|
migrationCompleted( instance );
|
|
}
|
|
|
|
void KMailMigrator::mboxAccountCreated( KJob *job )
|
|
{
|
|
if ( job->error() ) {
|
|
migrationFailed( i18n( "Failed to create resource: %1", job->errorText() ) );
|
|
return;
|
|
}
|
|
emit message( Info, i18n( "Created mbox resource" ) );
|
|
|
|
AgentInstance instance = static_cast< AgentInstanceCreateJob* >( job )->instance();
|
|
mCurrentInstance = instance;
|
|
KConfigGroup config( mConfig, mCurrentAccount );
|
|
|
|
OrgKdeAkonadiMboxSettingsInterface *iface = new OrgKdeAkonadiMboxSettingsInterface(
|
|
QLatin1String("org.freedesktop.Akonadi.Resource.") + instance.identifier(),
|
|
QLatin1String("/Settings"), QDBusConnection::sessionBus(), this );
|
|
|
|
if ( !iface->isValid() ) {
|
|
migrationFailed( i18n( "Failed to obtain D-Bus interface for remote configuration." ), instance );
|
|
delete iface;
|
|
return;
|
|
}
|
|
|
|
iface->setPath( config.readEntry( "Location" ) );
|
|
const QString lockType = config.readEntry( "LockType" ).toLower();
|
|
if ( lockType == QLatin1String( "procmail_locktype" ) ) {
|
|
iface->setLockfileMethod( Procmail );
|
|
iface->setLockfile( config.readEntry( "ProcmailLockFile" ) );
|
|
} else if ( lockType == QLatin1String( "mutt_dotlock" ) )
|
|
iface->setLockfileMethod( MuttDotLock );
|
|
else if ( lockType == QLatin1String( "mutt_dotlock_privileged" ) )
|
|
iface->setLockfileMethod( MuttDotLockPrivileged );
|
|
else if ( lockType == QLatin1String( "none" ) )
|
|
iface->setLockfileMethod( MboxNone );
|
|
|
|
// make sure the config is saved
|
|
iface->writeConfig();
|
|
|
|
// check-exclude in Account section means that this account should not be included
|
|
// in manual checks. In KMail UI this is called "Include in manual checks"
|
|
KConfigGroup resourceGroup( mConfig, QString::fromLatin1( "Resource %1" ).arg( instance.identifier() ) );
|
|
resourceGroup.writeEntry( "IncludeInManualChecks", !config.readEntry( "check-exclude", false ) );
|
|
const KConfigGroup generalGroup( mConfig, "General" );
|
|
resourceGroup.writeEntry( "CheckOnStartup", generalGroup.readEntry( "checkmail-startup", false ) );
|
|
resourceGroup.writeEntry( "OfflineOnShutdown", false );
|
|
|
|
//Info: there is trash item in config which is default and we can't configure it => don't look at it in pop account.
|
|
config.deleteEntry( "trash" );
|
|
config.deleteEntry( "identity-id" );
|
|
config.deleteEntry( "use-default-identity" );
|
|
//We can't specify folder in akonadi
|
|
config.deleteEntry( "Folder" );
|
|
|
|
//TODO check-interval for the moment mbox doesn't support it
|
|
|
|
const QString nameAccount = config.readEntry( "Name" );
|
|
instance.setName( nameAccount );
|
|
emit status( nameAccount );
|
|
instance.reconfigure();
|
|
config.sync();
|
|
migrationCompleted( instance );
|
|
}
|
|
|
|
void KMailMigrator::maildirAccountCreated( KJob *job )
|
|
{
|
|
if ( job->error() ) {
|
|
migrationFailed( i18n( "Failed to create resource: %1", job->errorText() ) );
|
|
return;
|
|
}
|
|
emit message( Info, i18n( "Created maildir resource" ) );
|
|
|
|
AgentInstance instance = static_cast< AgentInstanceCreateJob* >( job )->instance();
|
|
mCurrentInstance = instance;
|
|
KConfigGroup config( mConfig, mCurrentAccount );
|
|
|
|
OrgKdeAkonadiMaildirSettingsInterface *iface = new OrgKdeAkonadiMaildirSettingsInterface(
|
|
QLatin1String("org.freedesktop.Akonadi.Resource.") + instance.identifier(),
|
|
QLatin1String("/Settings"), QDBusConnection::sessionBus(), this );
|
|
|
|
if ( !iface->isValid() ) {
|
|
migrationFailed( i18n( "Failed to obtain D-Bus interface for remote configuration." ), instance );
|
|
delete iface;
|
|
return;
|
|
}
|
|
|
|
iface->setPath( config.readEntry( "Location" ) );
|
|
|
|
// make sure the config is saved
|
|
iface->writeConfig();
|
|
|
|
// check-exclude in Account section means that this account should not be included
|
|
// in manual checks. In KMail UI this is called "Include in manual checks"
|
|
KConfigGroup resourceGroup( mConfig, QString::fromLatin1( "Resource %1" ).arg( instance.identifier() ) );
|
|
resourceGroup.writeEntry( "IncludeInManualChecks", !config.readEntry( "check-exclude", false ) );
|
|
const KConfigGroup generalGroup( mConfig, "General" );
|
|
resourceGroup.writeEntry( "CheckOnStartup", generalGroup.readEntry( "checkmail-startup", false ) );
|
|
resourceGroup.writeEntry( "OfflineOnShutdown", false );
|
|
|
|
//Info: there is trash item in config which is default and we can't configure it => don't look at it in pop account.
|
|
config.deleteEntry( "trash" );
|
|
config.deleteEntry( "identity-id" );
|
|
config.deleteEntry( "use-default-identity" );
|
|
//Now in akonadi we can't specify a folder where we put email, it's a specific top root
|
|
config.deleteEntry( "Folder" );
|
|
|
|
//TODO: check-interval for the moment maildir doesn't support check-interval.
|
|
|
|
const QString nameAccount = config.readEntry( "Name" );
|
|
instance.setName( nameAccount );
|
|
emit status( nameAccount );
|
|
instance.reconfigure();
|
|
config.sync();
|
|
migrationCompleted( instance );
|
|
}
|
|
|
|
void KMailMigrator::localMaildirCreated( KJob *job )
|
|
{
|
|
if ( job->error() ) {
|
|
emit message( Error, i18n( "Failed to create resource for local folders: %1", job->errorText() ) );
|
|
deleteLater();
|
|
return;
|
|
}
|
|
emit message( Info, i18n( "Created local maildir resource." ) );
|
|
|
|
AgentInstance instance = static_cast< AgentInstanceCreateJob* >( job )->instance();
|
|
mCurrentInstance = instance;
|
|
|
|
// do not include KMail folders in manual checks by default
|
|
KConfigGroup resourceGroup( mConfig, QString::fromLatin1( "Resource %1" ).arg( instance.identifier() ) );
|
|
resourceGroup.writeEntry( "IncludeInManualChecks", false );
|
|
// do not synchronize on startup
|
|
resourceGroup.writeEntry( "CheckOnStartup", false );
|
|
resourceGroup.writeEntry( "OfflineOnShutdown", false );
|
|
|
|
const bool specialCollectionsLock =
|
|
QDBusConnection::sessionBus().registerService( SPECIALCOLLECTIONS_LOCK_SERVICE );
|
|
|
|
KConfig specialMailCollectionsConfig( QLatin1String( "specialmailcollectionsrc" ) );
|
|
KConfigGroup specialMailCollectionsGroup = specialMailCollectionsConfig.group( QLatin1String( "SpecialCollections" ) );
|
|
|
|
QString defaultInstanceName;
|
|
QString defaultResourceId = specialMailCollectionsGroup.readEntry( QLatin1String( "DefaultResourceId" ) );
|
|
if ( defaultResourceId.isEmpty() ) {
|
|
kDebug() << "No resource configured for special mail collections, using the migrated"
|
|
<< instance.identifier();
|
|
defaultResourceId = instance.identifier();
|
|
} else {
|
|
const AgentInstance defaultInstance = AgentManager::self()->instance( defaultResourceId );
|
|
if ( !defaultInstance.isValid() ) {
|
|
kDebug() << "Resource" << defaultResourceId
|
|
<< " configured for special mail collections does not exist, using the migrated"
|
|
<< instance.identifier();
|
|
defaultResourceId = instance.identifier();
|
|
} else {
|
|
defaultInstanceName = defaultInstance.name();
|
|
}
|
|
}
|
|
|
|
const QString instanceName = i18n( "KMail Folders" );
|
|
|
|
if ( defaultInstanceName.isEmpty() && specialCollectionsLock ) {
|
|
specialMailCollectionsGroup.writeEntry( QLatin1String( "DefaultResourceId" ), defaultResourceId );
|
|
specialMailCollectionsGroup.sync();
|
|
|
|
emit message( Info,
|
|
i18nc( "@info:status resource that will provide folder such as outbox, sent",
|
|
"Using '%1' for default outbox, sent mail, trash, etc.",
|
|
instanceName ) );
|
|
} else {
|
|
emit message( Info,
|
|
i18nc( "@info:status resource that will provide folder such as outbox, sent",
|
|
"Keeping '%1' for default outbox, sent mail, trash, etc.",
|
|
defaultInstanceName ) );
|
|
}
|
|
|
|
if ( specialCollectionsLock ) {
|
|
QDBusConnection::sessionBus().unregisterService( SPECIALCOLLECTIONS_LOCK_SERVICE );
|
|
}
|
|
|
|
instance.setName( instanceName );
|
|
emit status( instanceName );
|
|
|
|
MixedMaildirStore *store = createStoreFromBasePath( mLocalMaildirPath );
|
|
|
|
LocalFoldersCollectionMigrator *collectionMigrator = new LocalFoldersCollectionMigrator( instance, instanceName, store, this );
|
|
collectionMigrator->setTopLevelFolder( QString(), instanceName );
|
|
collectionMigrator->setKMailConfig( mConfig );
|
|
collectionMigrator->setEmailIdentityConfig( mEmailIdentityConfig );
|
|
collectionMigrator->setKcmKmailSummaryConfig( mKcmKmailSummaryConfig );
|
|
collectionMigrator->setTemplatesConfig( mTemplatesConfig );
|
|
|
|
connect( collectionMigrator, SIGNAL(migrationFinished(Akonadi::AgentInstance,QString)),
|
|
SLOT(localFoldersMigrationFinished(Akonadi::AgentInstance,QString)) );
|
|
connectCollectionMigrator( collectionMigrator );
|
|
|
|
collectionMigrator->startMigration();
|
|
}
|
|
|
|
void KMailMigrator::localFoldersMigrationFinished( const AgentInstance &instance, const QString &error )
|
|
{
|
|
OrgKdeAkonadiMixedMaildirSettingsInterface *iface = new OrgKdeAkonadiMixedMaildirSettingsInterface(
|
|
QLatin1String("org.freedesktop.Akonadi.Resource.") + instance.identifier(),
|
|
QLatin1String("/Settings"), QDBusConnection::sessionBus(), this );
|
|
|
|
if ( !iface->isValid() ) {
|
|
migrationFailed( i18n("Failed to obtain D-Bus interface for remote configuration."), instance );
|
|
delete iface;
|
|
return;
|
|
}
|
|
|
|
iface->setPath( mLocalMaildirPath );
|
|
|
|
// make sure the config is saved
|
|
iface->writeConfig();
|
|
|
|
AgentInstance resource = instance;
|
|
resource.reconfigure();
|
|
|
|
if ( error.isEmpty() ) {
|
|
KConfigGroup config( KGlobal::config(), QLatin1String( "SpecialMailCollections" ) );
|
|
if ( config.readEntry( QLatin1String( "TakeOverIfDefaultIsTotallyEmpty" ), false ) ) {
|
|
KConfig specialMailCollectionsConfig( QLatin1String( "specialmailcollectionsrc" ) );
|
|
KConfigGroup specialMailCollectionsGroup = specialMailCollectionsConfig.group( QLatin1String( "SpecialCollections" ) );
|
|
|
|
QString defaultResourceId = specialMailCollectionsGroup.readEntry( QLatin1String( "DefaultResourceId" ) );
|
|
|
|
AgentInstance defaultResource = AgentManager::self()->instance( defaultResourceId );
|
|
if ( defaultResource.isValid() && defaultResourceId != instance.identifier() ) {
|
|
kDebug() << "Attempting take over of special mail collections role from"
|
|
<< defaultResourceId;
|
|
|
|
EmptyResourceCleaner *cleaner = new EmptyResourceCleaner( defaultResource, this );
|
|
cleaner->setCleaningOptions( EmptyResourceCleaner::CheckOnly );
|
|
connect( cleaner, SIGNAL(cleanupFinished(Akonadi::AgentInstance)),
|
|
SLOT(specialColDefaultResourceCheckFinished(Akonadi::AgentInstance)) );
|
|
return;
|
|
}
|
|
}
|
|
|
|
mCurrentInstance = AgentInstance();
|
|
|
|
setMigrationState( QLatin1String("LocalFolders"), Complete, instance.identifier(), QLatin1String("LocalFolders") );
|
|
emit message( Success, i18n( "Local folders migrated successfully." ) );
|
|
emit status( QString() );
|
|
migrationDone();
|
|
|
|
} else {
|
|
mCurrentInstance = AgentInstance();
|
|
|
|
migrationFailed( error, instance );
|
|
}
|
|
}
|
|
|
|
void KMailMigrator::imapFoldersMigrationFinished( const AgentInstance &instance, const QString &error )
|
|
{
|
|
kDebug() << "imapMigrationFinished: instance=" << instance.identifier()
|
|
<< "error=" << error;
|
|
|
|
OrgKdeAkonadiImapSettingsInterface *iface = createImapSettingsInterface( instance );
|
|
if ( !iface ) {
|
|
return;
|
|
}
|
|
|
|
const bool disconnected = mAccountInstance[ mCurrentAccount ].disconnectedImap;
|
|
|
|
KConfigGroup config( mConfig, mCurrentAccount );
|
|
const QString nameAccount = config.readEntry( "Name" );
|
|
|
|
iface->setImapServer( config.readEntry( "host" ) );
|
|
iface->setImapPort( config.readEntry( "port", 143 ) );
|
|
iface->setUserName( config.readEntry( "login" ) );
|
|
if ( config.readEntry( "use-ssl" ).toLower() == QLatin1String("true") )
|
|
iface->setSafety( QLatin1String("SSL") );
|
|
else if ( config.readEntry( "use-tls" ).toLower() == QLatin1String("true") )
|
|
iface->setSafety( QLatin1String("STARTTLS") );
|
|
else
|
|
iface->setSafety( QLatin1String("NONE") );
|
|
const QString authentication = config.readEntry( "auth" ).toUpper();
|
|
if ( authentication == QLatin1String( "LOGIN" ) )
|
|
iface->setAuthentication( MailTransport::Transport::EnumAuthenticationType::LOGIN );
|
|
else if ( authentication == QLatin1String( "PLAIN" ) )
|
|
iface->setAuthentication( MailTransport::Transport::EnumAuthenticationType::PLAIN );
|
|
else if ( authentication == QLatin1String( "CRAM-MD5" ) )
|
|
iface->setAuthentication( MailTransport::Transport::EnumAuthenticationType::CRAM_MD5 );
|
|
else if ( authentication == QLatin1String( "DIGEST-MD5" ) )
|
|
iface->setAuthentication( MailTransport::Transport::EnumAuthenticationType::DIGEST_MD5 );
|
|
else if ( authentication == QLatin1String( "NTLM" ) )
|
|
iface->setAuthentication( MailTransport::Transport::EnumAuthenticationType::NTLM );
|
|
else if ( authentication == QLatin1String( "GSSAPI" ) )
|
|
iface->setAuthentication( MailTransport::Transport::EnumAuthenticationType::GSSAPI );
|
|
else if ( authentication == QLatin1String( "ANONYMOUS" ) )
|
|
iface->setAuthentication( MailTransport::Transport::EnumAuthenticationType::ANONYMOUS );
|
|
else {
|
|
iface->setAuthentication( MailTransport::Transport::EnumAuthenticationType::CLEAR );
|
|
}
|
|
if ( config.readEntry( "subscribed-folders" ).toLower() == QLatin1String("true") )
|
|
iface->setSubscriptionEnabled( true );
|
|
|
|
// skip interval checking so it doesn't interfere with cache importing
|
|
iface->setIntervalCheckTime( -1 ); //exclude
|
|
|
|
// check-exclude in Account section means that this account should not be included
|
|
// in manual checks. In KMail UI this is called "Include in manual checks"
|
|
KConfigGroup resourceGroup( mConfig, QString::fromLatin1( "Resource %1" ).arg( instance.identifier() ) );
|
|
resourceGroup.writeEntry( "IncludeInManualChecks", !config.readEntry( "check-exclude", false ) );
|
|
const KConfigGroup generalGroup( mConfig, "General" );
|
|
resourceGroup.writeEntry( "CheckOnStartup", generalGroup.readEntry( "checkmail-startup", false ) );
|
|
resourceGroup.writeEntry( "OfflineOnShutdown", true );
|
|
|
|
iface->setSieveSupport( config.readEntry( "sieve-support", false ) );
|
|
iface->setSieveReuseConfig( config.readEntry( "sieve-reuse-config", true ) );
|
|
iface->setSievePort( config.readEntry( "sieve-port", 2000 ) );
|
|
iface->setSieveAlternateUrl( config.readEntry( "sieve-alternate-url" ) );
|
|
iface->setSieveVacationFilename( config.readEntry( "sieve-vacation-filename", "kmail-vacation.siv" ) );
|
|
iface->setDisconnectedModeEnabled( disconnected );
|
|
if ( !disconnected ) {
|
|
iface->setAutomaticExpungeEnabled( config.readEntry( "auto-expunge", true ) );
|
|
}
|
|
const bool useDefaultIdentity = config.readEntry( "use-default-identity", true );
|
|
iface->setUseDefaultIdentity( useDefaultIdentity );
|
|
if ( !useDefaultIdentity )
|
|
iface->setAccountIdentity( config.readEntry( "identity-id" ).toInt() );
|
|
|
|
QString encpasswd ;
|
|
if ( config.readEntry( "store-passwd", false ) ) {
|
|
encpasswd = config.readEntry( "pass" );
|
|
if ( encpasswd.isEmpty() ) {
|
|
encpasswd = config.readEntry( "passwd" );
|
|
if ( !encpasswd.isEmpty() )
|
|
encpasswd = importPassword( encpasswd );
|
|
}
|
|
|
|
if ( !encpasswd.isEmpty() ) {
|
|
encpasswd = KStringHandler::obscure( encpasswd );
|
|
}
|
|
config.deleteEntry( "store-passwd" );
|
|
config.deleteEntry( "passwd" );
|
|
}
|
|
migratePassword( config.readEntry( "Id" ), instance, QLatin1String("imap"), encpasswd );
|
|
|
|
// enable interval checking in case this had been configured
|
|
const int checkInterval = config.readEntry( "check-interval", 0 );
|
|
if ( checkInterval != 0 ) {
|
|
iface->setIntervalCheckEnabled( true );
|
|
iface->setIntervalCheckTime( checkInterval );
|
|
}
|
|
|
|
// make sure the config is saved
|
|
iface->writeConfig();
|
|
|
|
AgentInstance resource = instance;
|
|
resource.reconfigure();
|
|
|
|
config.deleteEntry( "locally-subscribed-folders" );
|
|
config.deleteEntry( "locallyUnsubscribedFolders" );
|
|
|
|
config.deleteEntry( "capabilities" );
|
|
|
|
if ( error.isEmpty() ) {
|
|
migrationCompleted( instance );
|
|
} else {
|
|
migrationFailed( error, true, instance );
|
|
}
|
|
}
|
|
|
|
void KMailMigrator::collectionMigratorMessage( int type, const QString &msg )
|
|
{
|
|
switch ( type ) {
|
|
case Success:
|
|
emit message( Success, msg );
|
|
break;
|
|
|
|
case Skip:
|
|
emit message( Skip, msg );
|
|
break;
|
|
|
|
case Warning:
|
|
emit message( Warning, msg );
|
|
break;
|
|
|
|
case Info:
|
|
emit message( Info, msg );
|
|
break;
|
|
|
|
case Error:
|
|
emit message( Error, msg );
|
|
break;
|
|
|
|
default:
|
|
kError() << "Unknown message type" << type << "msg=" << msg;
|
|
break;
|
|
}
|
|
}
|
|
|
|
void KMailMigrator::collectionMigratorFinished()
|
|
{
|
|
emit status( QString() );
|
|
}
|
|
|
|
void KMailMigrator::collectionMigratorEmittedNotification()
|
|
{
|
|
mForwardResourceNotifications = false;
|
|
}
|
|
|
|
void KMailMigrator::instanceStatusChanged( const AgentInstance &instance )
|
|
{
|
|
if ( !mForwardResourceNotifications ) {
|
|
return;
|
|
}
|
|
|
|
if ( instance.identifier() != mCurrentInstance.identifier() ) {
|
|
return;
|
|
}
|
|
|
|
if ( instance.status() == AgentInstance::Idle ) {
|
|
emit status( QString() );
|
|
} else {
|
|
emit status( instance.statusMessage() );
|
|
}
|
|
}
|
|
|
|
void KMailMigrator::instanceProgressChanged( const AgentInstance &instance )
|
|
{
|
|
if ( !mForwardResourceNotifications ) {
|
|
return;
|
|
}
|
|
|
|
if ( instance.identifier() != mCurrentInstance.identifier() ) {
|
|
return;
|
|
}
|
|
|
|
emit progress( 0, 100, instance.progress() );
|
|
}
|
|
|
|
void KMailMigrator::imapCacheAdaptionFinished( int messageType, const QString &messageText )
|
|
{
|
|
emit message( (KMigratorBase::MessageType)messageType, messageText );
|
|
|
|
mImapCacheAdapter = 0;
|
|
|
|
migrateNext();
|
|
}
|
|
|
|
void KMailMigrator::specialColDefaultResourceCheckFinished( const AgentInstance &instance )
|
|
{
|
|
KConfig specialMailCollectionsConfig( QLatin1String( "specialmailcollectionsrc" ) );
|
|
KConfigGroup specialMailCollectionsGroup = specialMailCollectionsConfig.group( QLatin1String( "SpecialCollections" ) );
|
|
|
|
const EmptyResourceCleaner *cleaner = qobject_cast<const EmptyResourceCleaner*>( QObject::sender() );
|
|
|
|
const bool specialCollectionsLock =
|
|
QDBusConnection::sessionBus().registerService( SPECIALCOLLECTIONS_LOCK_SERVICE );
|
|
|
|
const QString localFoldersIdentifier = mCurrentInstance.identifier();
|
|
if ( cleaner->isResourceDeletable() && specialCollectionsLock ) {
|
|
specialMailCollectionsGroup.writeEntry( QLatin1String( "DefaultResourceId" ), localFoldersIdentifier );
|
|
specialMailCollectionsGroup.sync();
|
|
AgentManager::self()->removeInstance( instance );
|
|
|
|
kDebug() << "Former special mail collection resource" << instance.identifier()
|
|
<< "successfully delete, now using" << specialMailCollectionsGroup.readEntry( QLatin1String( "DefaultResourceId" ) );
|
|
} else {
|
|
kDebug() << "Former special mail collection resource" << instance.identifier()
|
|
<< "still valid";
|
|
}
|
|
|
|
if ( specialCollectionsLock ) {
|
|
QDBusConnection::sessionBus().unregisterService( SPECIALCOLLECTIONS_LOCK_SERVICE );
|
|
}
|
|
|
|
mCurrentInstance = AgentInstance();
|
|
|
|
setMigrationState( QLatin1String("LocalFolders"), Complete, localFoldersIdentifier, QLatin1String("LocalFolders") );
|
|
emit message( Success, i18n( "Local folders migrated successfully." ) );
|
|
emit status( QString() );
|
|
migrationDone();
|
|
}
|
|
|
|
QString KMailMigrator::importPassword(const QString &aStr)
|
|
{
|
|
unsigned int i, val;
|
|
unsigned int len = aStr.length();
|
|
QByteArray result;
|
|
result.resize( len );
|
|
|
|
for ( i = 0; i < len; i++ ) {
|
|
val = aStr[i].toLatin1() - ' ';
|
|
val = ( 255-' ') - val;
|
|
result[i] = (char)( val + ' ');
|
|
}
|
|
result[i] = '\0';
|
|
|
|
return KStringHandler::obscure( QString::fromLatin1(result) );
|
|
}
|
|
|
|
|