transportmanager.cpp 17.9 KB
Newer Older
1
/*
Allen Winter's avatar
Allen Winter committed
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
  Copyright (c) 2006 - 2007 Volker Krause <vkrause@kde.org>

  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.
18 19
*/

20
#include "transportmanager.h"
21
#include "mailtransport_defs.h"
22
#include "smtpjob.h"
23
#include "transport.h"
24
#include "transport_p.h"
25
#include "transportjob.h"
26 27
#include "transporttype.h"
#include "transporttype_p.h"
Laurent Montel's avatar
Laurent Montel committed
28
#include "widgets/addtransportdialog.h"
29 30 31
#include "widgets/transportconfigdialog.h"
#include "widgets/transportconfigwidget.h"
#include "widgets/smtpconfigwidget.h"
Laurent Montel's avatar
Laurent Montel committed
32
#include "helper_p.h"
33 34

#include <QApplication>
35 36
#include <QtDBus/QDBusConnection>
#include <QtDBus/QDBusConnectionInterface>
Tobias Koenig's avatar
Tobias Koenig committed
37
#include <QtDBus/QDBusServiceWatcher>
38
#include <QPointer>
39 40 41
#include <QRegExp>
#include <QStringList>

42 43
#include <KConfig>
#include <KConfigGroup>
Laurent Montel's avatar
Laurent Montel committed
44
#include "mailtransport_debug.h"
45
#include <KEMailSettings>
46
#include <KLocalizedString>
47 48
#include <KMessageBox>
#include <KRandom>
Laurent Montel's avatar
Laurent Montel committed
49
#include <Kdelibs4ConfigMigrator>
50

Laurent Montel's avatar
Laurent Montel committed
51
#include <KWallet/kwallet.h>
52

53
using namespace MailTransport;
54 55
using namespace KWallet;

Laurent Montel's avatar
Laurent Montel committed
56 57
namespace MailTransport
{
Tom Albers's avatar
Tom Albers committed
58 59 60 61
/**
 * Private class that helps to provide binary compatibility between releases.
 * @internal
 */
Volker Krause's avatar
Volker Krause committed
62
class TransportManagerPrivate
Allen Winter's avatar
Allen Winter committed
63
{
Laurent Montel's avatar
Laurent Montel committed
64 65
public:
    TransportManagerPrivate(TransportManager *parent)
66 67 68
        : config(nullptr),
          wallet(nullptr),
          q(parent)
Thomas McGuire's avatar
Thomas McGuire committed
69 70 71
    {
    }

Laurent Montel's avatar
Laurent Montel committed
72 73 74 75
    ~TransportManagerPrivate()
    {
        delete config;
        qDeleteAll(transports);
76
    }
77

Tom Albers's avatar
Tom Albers committed
78
    KConfig *config;
Allen Winter's avatar
Allen Winter committed
79
    QList<Transport *> transports;
80
    TransportType::List types;
Tom Albers's avatar
Tom Albers committed
81
    bool myOwnChange;
82
    bool appliedChange;
Tom Albers's avatar
Tom Albers committed
83 84 85 86 87
    KWallet::Wallet *wallet;
    bool walletOpenFailed;
    bool walletAsyncOpen;
    int defaultTransportId;
    bool isMainInstance;
Allen Winter's avatar
Allen Winter committed
88
    QList<TransportJob *> walletQueue;
Thomas McGuire's avatar
Thomas McGuire committed
89
    TransportManager *q;
90 91 92 93 94 95 96 97 98 99 100

    void readConfig();
    void writeConfig();
    void fillTypes();
    int createId() const;
    void prepareWallet();
    void validateDefault();
    void migrateToWallet();

    // Slots
    void slotTransportsChanged();
Laurent Montel's avatar
Laurent Montel committed
101
    void slotWalletOpened(bool success);
Tobias Koenig's avatar
Tobias Koenig committed
102
    void dbusServiceUnregistered();
Laurent Montel's avatar
Laurent Montel committed
103
    void jobResult(KJob *job);
104
};
105

Volker Krause's avatar
Volker Krause committed
106 107
}

108 109
class StaticTransportManager : public TransportManager
{
Laurent Montel's avatar
Laurent Montel committed
110
public:
111
    StaticTransportManager() : TransportManager() {}
Tom Albers's avatar
Tom Albers committed
112 113
};

Laurent Montel's avatar
Laurent Montel committed
114
StaticTransportManager *sSelf = nullptr;
115

Laurent Montel's avatar
Laurent Montel committed
116 117 118
static void destroyStaticTransportManager()
{
    delete sSelf;
119
}
120 121

TransportManager::TransportManager()
Laurent Montel's avatar
Laurent Montel committed
122
    : QObject(), d(new TransportManagerPrivate(this))
123
{
Laurent Montel's avatar
Laurent Montel committed
124 125
    Kdelibs4ConfigMigrator migrate(QStringLiteral("transportmanager"));
    migrate.setConfigFiles(QStringList() << QStringLiteral("mailtransports"));
Laurent Montel's avatar
Laurent Montel committed
126 127
    migrate.migrate();

Laurent Montel's avatar
Laurent Montel committed
128 129 130
    qAddPostRoutine(destroyStaticTransportManager);
    d->myOwnChange = false;
    d->appliedChange = false;
Laurent Montel's avatar
Laurent Montel committed
131
    d->wallet = nullptr;
Laurent Montel's avatar
Laurent Montel committed
132 133 134
    d->walletOpenFailed = false;
    d->walletAsyncOpen = false;
    d->defaultTransportId = -1;
Laurent Montel's avatar
Laurent Montel committed
135
    d->config = new KConfig(QStringLiteral("mailtransports"));
136

Laurent Montel's avatar
Laurent Montel committed
137 138 139
    QDBusConnection::sessionBus().registerObject(DBUS_OBJECT_PATH, this,
            QDBusConnection::ExportScriptableSlots |
            QDBusConnection::ExportScriptableSignals);
Tobias Koenig's avatar
Tobias Koenig committed
140

Laurent Montel's avatar
Laurent Montel committed
141 142 143 144 145
    QDBusServiceWatcher *watcher =
        new QDBusServiceWatcher(DBUS_SERVICE_NAME, QDBusConnection::sessionBus(),
                                QDBusServiceWatcher::WatchForUnregistration, this);
    connect(watcher, SIGNAL(serviceUnregistered(QString)),
            SLOT(dbusServiceUnregistered()));
146

Laurent Montel's avatar
Laurent Montel committed
147 148 149
    QDBusConnection::sessionBus().connect(QString(), QString(),
                                          DBUS_INTERFACE_NAME, DBUS_CHANGE_SIGNAL,
                                          this, SLOT(slotTransportsChanged()));
150

Laurent Montel's avatar
Laurent Montel committed
151
    d->isMainInstance = QDBusConnection::sessionBus().registerService(DBUS_SERVICE_NAME);
152

Laurent Montel's avatar
Laurent Montel committed
153
    d->fillTypes();
154 155 156 157
}

TransportManager::~TransportManager()
{
Laurent Montel's avatar
Laurent Montel committed
158 159
    qRemovePostRoutine(destroyStaticTransportManager);
    delete d;
160 161
}

Allen Winter's avatar
Allen Winter committed
162
TransportManager *TransportManager::self()
163
{
Laurent Montel's avatar
Laurent Montel committed
164 165 166 167 168
    if (!sSelf) {
        sSelf = new StaticTransportManager;
        sSelf->d->readConfig();
    }
    return sSelf;
169 170
}

Laurent Montel's avatar
Laurent Montel committed
171
Transport *TransportManager::transportById(int id, bool def) const
172
{
Laurent Montel's avatar
Laurent Montel committed
173 174 175 176
    foreach (Transport *t, d->transports) {
        if (t->id() == id) {
            return t;
        }
Allen Winter's avatar
Allen Winter committed
177
    }
178

Laurent Montel's avatar
Laurent Montel committed
179 180 181
    if (def || (id == 0 && d->defaultTransportId != id)) {
        return transportById(d->defaultTransportId, false);
    }
Laurent Montel's avatar
Laurent Montel committed
182
    return nullptr;
183 184
}

Laurent Montel's avatar
Laurent Montel committed
185
Transport *TransportManager::transportByName(const QString &name, bool def) const
186
{
Laurent Montel's avatar
Laurent Montel committed
187 188 189 190
    foreach (Transport *t, d->transports) {
        if (t->name() == name) {
            return t;
        }
Allen Winter's avatar
Allen Winter committed
191
    }
Laurent Montel's avatar
Laurent Montel committed
192 193 194
    if (def) {
        return transportById(0, false);
    }
Laurent Montel's avatar
Laurent Montel committed
195
    return nullptr;
196 197 198 199
}

QList< Transport * > TransportManager::transports() const
{
Laurent Montel's avatar
Laurent Montel committed
200
    return d->transports;
201 202
}

203
TransportType::List TransportManager::types() const
204
{
Laurent Montel's avatar
Laurent Montel committed
205
    return d->types;
206 207
}

Allen Winter's avatar
Allen Winter committed
208
Transport *TransportManager::createTransport() const
209
{
Laurent Montel's avatar
Laurent Montel committed
210 211 212 213
    int id = d->createId();
    Transport *t = new Transport(QString::number(id));
    t->setId(id);
    return t;
214 215
}

Laurent Montel's avatar
Laurent Montel committed
216
void TransportManager::addTransport(Transport *transport)
217
{
Laurent Montel's avatar
Laurent Montel committed
218
    if (d->transports.contains(transport)) {
Laurent Montel's avatar
Laurent Montel committed
219
        qCDebug(MAILTRANSPORT_LOG) << "Already have this transport.";
Laurent Montel's avatar
Laurent Montel committed
220 221
        return;
    }
Thomas McGuire's avatar
Thomas McGuire committed
222

Laurent Montel's avatar
Laurent Montel committed
223
    qCDebug(MAILTRANSPORT_LOG) << "Added transport" << transport;
Laurent Montel's avatar
Laurent Montel committed
224 225 226
    d->transports.append(transport);
    d->validateDefault();
    emitChangesCommitted();
227 228
}

Laurent Montel's avatar
Laurent Montel committed
229
void TransportManager::schedule(TransportJob *job)
230
{
Laurent Montel's avatar
Laurent Montel committed
231
    connect(job, SIGNAL(result(KJob*)), SLOT(jobResult(KJob*)));
232

Laurent Montel's avatar
Laurent Montel committed
233 234
    // check if the job is waiting for the wallet
    if (!job->transport()->isComplete()) {
Laurent Montel's avatar
Laurent Montel committed
235
        qCDebug(MAILTRANSPORT_LOG) << "job waits for wallet:" << job;
Laurent Montel's avatar
Laurent Montel committed
236 237 238 239
        d->walletQueue << job;
        loadPasswordsAsync();
        return;
    }
240

Laurent Montel's avatar
Laurent Montel committed
241
    job->start();
242 243
}

Volker Krause's avatar
Volker Krause committed
244 245
void TransportManager::createDefaultTransport()
{
Laurent Montel's avatar
Laurent Montel committed
246 247 248 249 250 251 252 253
    KEMailSettings kes;
    Transport *t = createTransport();
    t->setName(i18n("Default Transport"));
    t->setHost(kes.getSetting(KEMailSettings::OutServer));
    if (t->isValid()) {
        t->save();
        addTransport(t);
    } else {
Laurent Montel's avatar
Laurent Montel committed
254
        qCWarning(MAILTRANSPORT_LOG) << "KEMailSettings does not contain a valid transport.";
Laurent Montel's avatar
Laurent Montel committed
255
    }
Volker Krause's avatar
Volker Krause committed
256 257
}

Laurent Montel's avatar
Laurent Montel committed
258 259
bool TransportManager::showTransportCreationDialog(QWidget *parent,
        ShowCondition showCondition)
260
{
Laurent Montel's avatar
Laurent Montel committed
261 262 263 264
    if (showCondition == IfNoTransportExists) {
        if (!isEmpty()) {
            return true;
        }
265

Laurent Montel's avatar
Laurent Montel committed
266 267 268 269 270 271 272 273
        const int response = KMessageBox::messageBox(parent,
                             KMessageBox::WarningContinueCancel,
                             i18n("You must create an outgoing account before sending."),
                             i18n("Create Account Now?"),
                             KGuiItem(i18n("Create Account Now")));
        if (response != KMessageBox::Continue) {
            return false;
        }
274 275
    }

Laurent Montel's avatar
Laurent Montel committed
276 277 278 279
    QPointer<AddTransportDialog> dialog = new AddTransportDialog(parent);
    const bool accepted = (dialog->exec() == QDialog::Accepted);
    delete dialog;
    return accepted;
280 281
}

Laurent Montel's avatar
Laurent Montel committed
282
bool TransportManager::configureTransport(Transport *transport, QWidget *parent)
283
{
Laurent Montel's avatar
Laurent Montel committed
284 285 286 287 288 289
    QPointer<TransportConfigDialog> transportConfigDialog =
        new TransportConfigDialog(transport, parent);
    transportConfigDialog->setWindowTitle(i18n("Configure account"));
    bool okClicked = (transportConfigDialog->exec() == QDialog::Accepted);
    delete transportConfigDialog;
    return okClicked;
290 291
}

Laurent Montel's avatar
Laurent Montel committed
292
TransportJob *TransportManager::createTransportJob(int transportId)
293
{
Laurent Montel's avatar
Laurent Montel committed
294 295
    Transport *t = transportById(transportId, false);
    if (!t) {
Laurent Montel's avatar
Laurent Montel committed
296
        return nullptr;
Laurent Montel's avatar
Laurent Montel committed
297 298 299 300 301 302 303 304
    }
    t = t->clone(); // Jobs delete their transports.
    t->updatePasswordState();
    switch (t->type()) {
    case Transport::EnumType::SMTP:
        return new SmtpJob(t, this);
    }
    Q_ASSERT(false);
Laurent Montel's avatar
Laurent Montel committed
305
    return nullptr;
306 307
}

Laurent Montel's avatar
Laurent Montel committed
308
TransportJob *TransportManager::createTransportJob(const QString &transport)
309
{
Laurent Montel's avatar
Laurent Montel committed
310
    bool ok = false;
Laurent Montel's avatar
Laurent Montel committed
311
    Transport *t = nullptr;
312

Laurent Montel's avatar
Laurent Montel committed
313 314 315 316
    int transportId = transport.toInt(&ok);
    if (ok) {
        t = transportById(transportId);
    }
317

Laurent Montel's avatar
Laurent Montel committed
318 319 320
    if (!t) {
        t = transportByName(transport, false);
    }
321

Laurent Montel's avatar
Laurent Montel committed
322 323 324
    if (t) {
        return createTransportJob(t->id());
    }
325

Laurent Montel's avatar
Laurent Montel committed
326
    return nullptr;
327 328 329
}

bool TransportManager::isEmpty() const
330
{
Laurent Montel's avatar
Laurent Montel committed
331
    return d->transports.isEmpty();
332 333 334 335
}

QList<int> TransportManager::transportIds() const
{
Laurent Montel's avatar
Laurent Montel committed
336
    QList<int> rv;
337
    rv.reserve(d->transports.count());
Laurent Montel's avatar
Laurent Montel committed
338 339 340 341
    foreach (Transport *t, d->transports) {
        rv << t->id();
    }
    return rv;
342 343 344 345
}

QStringList TransportManager::transportNames() const
{
Laurent Montel's avatar
Laurent Montel committed
346
    QStringList rv;
347
    rv.reserve(d->transports.count());
Laurent Montel's avatar
Laurent Montel committed
348 349 350 351
    foreach (Transport *t, d->transports) {
        rv << t->name();
    }
    return rv;
352 353 354 355
}

QString TransportManager::defaultTransportName() const
{
Laurent Montel's avatar
Laurent Montel committed
356 357 358 359 360
    Transport *t = transportById(d->defaultTransportId, false);
    if (t) {
        return t->name();
    }
    return QString();
361 362 363 364
}

int TransportManager::defaultTransportId() const
{
Laurent Montel's avatar
Laurent Montel committed
365
    return d->defaultTransportId;
366 367
}

Laurent Montel's avatar
Laurent Montel committed
368
void TransportManager::setDefaultTransport(int id)
369
{
Laurent Montel's avatar
Laurent Montel committed
370 371 372 373 374
    if (id == d->defaultTransportId || !transportById(id, false)) {
        return;
    }
    d->defaultTransportId = id;
    d->writeConfig();
375 376
}

Laurent Montel's avatar
Laurent Montel committed
377
void TransportManager::removeTransport(int id)
378
{
Laurent Montel's avatar
Laurent Montel committed
379 380 381 382 383 384 385 386 387
    Transport *t = transportById(id, false);
    if (!t) {
        return;
    }
    emit transportRemoved(t->id(), t->name());

    d->transports.removeAll(t);
    d->validateDefault();
    QString group = t->currentGroup();
388 389
    if (t->storePassword()) {
        Wallet *currentWallet = wallet();
Laurent Montel's avatar
Laurent Montel committed
390 391
        if (currentWallet) {
            currentWallet->removeEntry(QString::number(t->id()));
392 393
        }
    }
Laurent Montel's avatar
Laurent Montel committed
394 395 396
    delete t;
    d->config->deleteGroup(group);
    d->writeConfig();
397

398 399
}

Volker Krause's avatar
Volker Krause committed
400
void TransportManagerPrivate::readConfig()
401
{
Laurent Montel's avatar
Laurent Montel committed
402 403 404
    QList<Transport *> oldTransports = transports;
    transports.clear();

405
    QRegExp re(QStringLiteral("^Transport (.+)$"));
Laurent Montel's avatar
Laurent Montel committed
406 407
    const QStringList groups = config->groupList().filter(re);
    for (const QString &s : groups) {
Laurent Montel's avatar
Laurent Montel committed
408 409 410
        if (re.indexIn(s) == -1) {
            continue;
        }
Laurent Montel's avatar
Laurent Montel committed
411
        Transport *t = nullptr;
Laurent Montel's avatar
Laurent Montel committed
412 413 414 415

        // see if we happen to have that one already
        foreach (Transport *old, oldTransports) {
            if (old->currentGroup() == QLatin1String("Transport ") + re.cap(1)) {
Laurent Montel's avatar
Laurent Montel committed
416
                qCDebug(MAILTRANSPORT_LOG) << "reloading existing transport:" << s;
Laurent Montel's avatar
Laurent Montel committed
417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433
                t = old;
                t->d->passwordNeedsUpdateFromWallet = true;
                t->load();
                oldTransports.removeAll(old);
                break;
            }
        }

        if (!t) {
            t = new Transport(re.cap(1));
        }
        if (t->id() <= 0) {
            t->setId(createId());
            t->save();
        }
        transports.append(t);
    }
434

Laurent Montel's avatar
Laurent Montel committed
435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454
    qDeleteAll(oldTransports);
    oldTransports.clear();

    // read default transport
    KConfigGroup group(config, "General");
    defaultTransportId = group.readEntry("default-transport", 0);
    if (defaultTransportId == 0) {
        // migrated default transport contains the name instead
        QString name = group.readEntry("default-transport", QString());
        if (!name.isEmpty()) {
            Transport *t = q->transportByName(name, false);
            if (t) {
                defaultTransportId = t->id();
                writeConfig();
            }
        }
    }
    validateDefault();
    migrateToWallet();
    q->loadPasswordsAsync();
455 456
}

Volker Krause's avatar
Volker Krause committed
457
void TransportManagerPrivate::writeConfig()
458
{
Laurent Montel's avatar
Laurent Montel committed
459 460 461 462
    KConfigGroup group(config, "General");
    group.writeEntry("default-transport", defaultTransportId);
    config->sync();
    q->emitChangesCommitted();
463 464
}

Volker Krause's avatar
Volker Krause committed
465
void TransportManagerPrivate::fillTypes()
466
{
Laurent Montel's avatar
Laurent Montel committed
467 468 469 470
    Q_ASSERT(types.isEmpty());

    // SMTP.
    {
471
        TransportType type;
Laurent Montel's avatar
Laurent Montel committed
472 473 474
        type.d->mType = Transport::EnumType::SMTP;
        type.d->mName = i18nc("@option SMTP transport", "SMTP");
        type.d->mDescription = i18n("An SMTP server on the Internet");
475
        types << type;
476 477 478
    }
}

479 480
void TransportManager::emitChangesCommitted()
{
Laurent Montel's avatar
Laurent Montel committed
481 482 483 484
    d->myOwnChange = true; // prevent us from reading our changes again
    d->appliedChange = false; // but we have to read them at least once
    emit transportsChanged();
    emit changesCommitted();
485 486
}

Volker Krause's avatar
Volker Krause committed
487
void TransportManagerPrivate::slotTransportsChanged()
488
{
Laurent Montel's avatar
Laurent Montel committed
489 490 491 492 493
    if (myOwnChange && appliedChange) {
        myOwnChange = false;
        appliedChange = false;
        return;
    }
494

Laurent Montel's avatar
Laurent Montel committed
495
    qCDebug(MAILTRANSPORT_LOG);
Laurent Montel's avatar
Laurent Montel committed
496 497 498 499 500
    config->reparseConfiguration();
    // FIXME: this deletes existing transport objects!
    readConfig();
    appliedChange = true; // to prevent recursion
    emit q->transportsChanged();
501 502
}

Volker Krause's avatar
Volker Krause committed
503
int TransportManagerPrivate::createId() const
504
{
Laurent Montel's avatar
Laurent Montel committed
505
    QList<int> usedIds;
506
    usedIds.reserve(1 + transports.count());
Laurent Montel's avatar
Laurent Montel committed
507
    for (Transport *t : qAsConst(transports)) {
Laurent Montel's avatar
Laurent Montel committed
508 509 510 511 512 513 514 515
        usedIds << t->id();
    }
    usedIds << 0; // 0 is default for unknown
    int newId;
    do {
        newId = KRandom::random();
    } while (usedIds.contains(newId));
    return newId;
516 517
}

Laurent Montel's avatar
Laurent Montel committed
518
KWallet::Wallet *TransportManager::wallet()
519
{
Laurent Montel's avatar
Laurent Montel committed
520 521 522
    if (d->wallet && d->wallet->isOpen()) {
        return d->wallet;
    }
523

Laurent Montel's avatar
Laurent Montel committed
524
    if (!Wallet::isEnabled() || d->walletOpenFailed) {
Laurent Montel's avatar
Laurent Montel committed
525
        return nullptr;
Laurent Montel's avatar
Laurent Montel committed
526
    }
527

Laurent Montel's avatar
Laurent Montel committed
528 529 530 531 532 533
    WId window = 0;
    if (qApp->activeWindow()) {
        window = qApp->activeWindow()->winId();
    } else if (!QApplication::topLevelWidgets().isEmpty()) {
        window = qApp->topLevelWidgets().first()->winId();
    }
534

Laurent Montel's avatar
Laurent Montel committed
535 536
    delete d->wallet;
    d->wallet = Wallet::openWallet(Wallet::NetworkWallet(), window);
537

Laurent Montel's avatar
Laurent Montel committed
538 539
    if (!d->wallet) {
        d->walletOpenFailed = true;
Laurent Montel's avatar
Laurent Montel committed
540
        return nullptr;
Laurent Montel's avatar
Laurent Montel committed
541
    }
542

Laurent Montel's avatar
Laurent Montel committed
543 544
    d->prepareWallet();
    return d->wallet;
545 546
}

Volker Krause's avatar
Volker Krause committed
547
void TransportManagerPrivate::prepareWallet()
548
{
Laurent Montel's avatar
Laurent Montel committed
549 550 551 552 553 554 555
    if (!wallet) {
        return;
    }
    if (!wallet->hasFolder(WALLET_FOLDER)) {
        wallet->createFolder(WALLET_FOLDER);
    }
    wallet->setFolder(WALLET_FOLDER);
556 557 558 559
}

void TransportManager::loadPasswords()
{
Laurent Montel's avatar
Laurent Montel committed
560 561 562
    foreach (Transport *t, d->transports) {
        t->readPassword();
    }
563

Laurent Montel's avatar
Laurent Montel committed
564 565 566
    // flush the wallet queue
    const QList<TransportJob *> copy = d->walletQueue;
    d->walletQueue.clear();
Laurent Montel's avatar
Laurent Montel committed
567
    for (TransportJob *job : copy) {
Laurent Montel's avatar
Laurent Montel committed
568 569
        job->start();
    }
570

Laurent Montel's avatar
Laurent Montel committed
571
    emit passwordsChanged();
572 573 574 575
}

void TransportManager::loadPasswordsAsync()
{
Laurent Montel's avatar
Laurent Montel committed
576
    qCDebug(MAILTRANSPORT_LOG);
577

Laurent Montel's avatar
Laurent Montel committed
578 579 580 581 582 583 584
    // check if there is anything to do at all
    bool found = false;
    foreach (Transport *t, d->transports) {
        if (!t->isComplete()) {
            found = true;
            break;
        }
585
    }
Laurent Montel's avatar
Laurent Montel committed
586 587
    if (!found) {
        return;
Allen Winter's avatar
Allen Winter committed
588 589
    }

Laurent Montel's avatar
Laurent Montel committed
590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611
    // async wallet opening
    if (!d->wallet && !d->walletOpenFailed) {
        WId window = 0;
        if (qApp->activeWindow()) {
            window = qApp->activeWindow()->winId();
        } else if (!QApplication::topLevelWidgets().isEmpty()) {
            window = qApp->topLevelWidgets().first()->winId();
        }

        d->wallet = Wallet::openWallet(Wallet::NetworkWallet(), window,
                                       Wallet::Asynchronous);
        if (d->wallet) {
            connect(d->wallet, SIGNAL(walletOpened(bool)), SLOT(slotWalletOpened(bool)));
            d->walletAsyncOpen = true;
        } else {
            d->walletOpenFailed = true;
            loadPasswords();
        }
        return;
    }
    if (d->wallet && !d->walletAsyncOpen) {
        loadPasswords();
612 613 614
    }
}

Laurent Montel's avatar
Laurent Montel committed
615
void TransportManagerPrivate::slotWalletOpened(bool success)
616
{
Laurent Montel's avatar
Laurent Montel committed
617
    qCDebug(MAILTRANSPORT_LOG);
Laurent Montel's avatar
Laurent Montel committed
618 619 620 621
    walletAsyncOpen = false;
    if (!success) {
        walletOpenFailed = true;
        delete wallet;
Laurent Montel's avatar
Laurent Montel committed
622
        wallet = nullptr;
Laurent Montel's avatar
Laurent Montel committed
623 624 625 626
    } else {
        prepareWallet();
    }
    q->loadPasswords();
627 628
}

Volker Krause's avatar
Volker Krause committed
629
void TransportManagerPrivate::validateDefault()
630
{
Laurent Montel's avatar
Laurent Montel committed
631 632 633 634 635 636 637
    if (!q->transportById(defaultTransportId, false)) {
        if (q->isEmpty()) {
            defaultTransportId = -1;
        } else {
            defaultTransportId = transports.first()->id();
            writeConfig();
        }
638 639 640
    }
}

Volker Krause's avatar
Volker Krause committed
641
void TransportManagerPrivate::migrateToWallet()
642
{
Laurent Montel's avatar
Laurent Montel committed
643 644 645 646 647 648 649 650 651 652 653 654 655 656
    // check if we tried this already
    static bool firstRun = true;
    if (!firstRun) {
        return;
    }
    firstRun = false;

    // check if we are the main instance
    if (!isMainInstance) {
        return;
    }

    // check if migration is needed
    QStringList names;
Laurent Montel's avatar
Laurent Montel committed
657
    for (Transport *t : qAsConst(transports)) {
Laurent Montel's avatar
Laurent Montel committed
658 659 660 661 662 663 664 665 666 667
        if (t->needsWalletMigration()) {
            names << t->name();
        }
    }
    if (names.isEmpty()) {
        return;
    }

    // ask user if he wants to migrate
    int result = KMessageBox::questionYesNoList(
Laurent Montel's avatar
Laurent Montel committed
668
                     nullptr,
Laurent Montel's avatar
Laurent Montel committed
669 670 671 672 673 674 675 676
                     i18n("The following mail transports store their passwords in an "
                          "unencrypted configuration file.\nFor security reasons, "
                          "please consider migrating these passwords to KWallet, the "
                          "KDE Wallet management tool,\nwhich stores sensitive data "
                          "for you in a strongly encrypted file.\n"
                          "Do you want to migrate your passwords to KWallet?"),
                     names, i18n("Question"),
                     KGuiItem(i18n("Migrate")), KGuiItem(i18n("Keep")),
Laurent Montel's avatar
Laurent Montel committed
677
                     QStringLiteral("WalletMigrate"));
Laurent Montel's avatar
Laurent Montel committed
678 679 680 681 682 683 684 685 686 687
    if (result != KMessageBox::Yes) {
        return;
    }

    // perform migration
    foreach (Transport *t, transports) {
        if (t->needsWalletMigration()) {
            t->migrateToWallet();
        }
    }
688 689
}

Tobias Koenig's avatar
Tobias Koenig committed
690
void TransportManagerPrivate::dbusServiceUnregistered()
691
{
Laurent Montel's avatar
Laurent Montel committed
692
    QDBusConnection::sessionBus().registerService(DBUS_SERVICE_NAME);
693 694
}

695

Laurent Montel's avatar
Laurent Montel committed
696
void TransportManagerPrivate::jobResult(KJob *job)
697
{
Laurent Montel's avatar
Laurent Montel committed
698
    walletQueue.removeAll(static_cast<TransportJob *>(job));
699 700
}

701
#include "moc_transportmanager.cpp"