ewsconfigdialog.cpp 20.7 KB
Newer Older
1
/*
2
    Copyright (C) 2015-2018 Krzysztof Nowicki <krissn@op.pl>
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

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

20
#include "ewsconfigdialog.h"
21

Laurent Montel's avatar
Laurent Montel committed
22
23
24
25
#include <KConfigDialogManager>
#include <KWindowSystem>
#include <KMessageBox>

26
27
28
29
30
31
#include <QDialogButtonBox>
#include <QVBoxLayout>
#include <QPushButton>

#include "ewsautodiscoveryjob.h"
#include "ewsgetfolderrequest.h"
32
33
#include "ewsresource.h"
#include "ewssettings.h"
34
#include "ewssubscriptionwidget.h"
35
#include "ewsprogressdialog.h"
36
#include "auth/ewspasswordauth.h"
37
#include "auth/ewsoauth.h"
Krzysztof Nowicki's avatar
Krzysztof Nowicki committed
38
#include "ui_ewsconfigdialog.h"
39
40
41
42
43
44
45
46
47
48
49
50
51

typedef QPair<QString, QString> StringPair;

static const QVector<StringPair> userAgents = {
    {QStringLiteral("Microsoft Outlook 2016"), QStringLiteral("Microsoft Office/16.0 (Windows NT 10.0; Microsoft Outlook 16.0.6326; Pro)")},
    {QStringLiteral("Microsoft Outlook 2013"), QStringLiteral("Microsoft Office/15.0 (Windows NT 6.1; Microsoft Outlook 15.0.4420; Pro)")},
    {QStringLiteral("Microsoft Outlook 2010"), QStringLiteral("Microsoft Office/14.0 (Windows NT 6.1; Microsoft Outlook 14.0.5128; Pro)")},
    {QStringLiteral("Microsoft Outlook 2011 for Mac"), QStringLiteral("MacOutlook/14.2.0.101115 (Intel Mac OS X 10.6.7)")},
    {QStringLiteral("Mozilla Thunderbird 38 for Windows (with ExQuilla)"), QStringLiteral("Mozilla/5.0 (Windows NT 6.1; WOW64; rv:38.0) Gecko/20100101 Thunderbird/38.2.0")},
    {QStringLiteral("Mozilla Thunderbird 38 for Linux (with ExQuilla)"), QStringLiteral("Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.2.0")},
    {QStringLiteral("Mozilla Thunderbird 38 for Mac (with ExQuilla)"), QStringLiteral("Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:38.0) Gecko/20100101 Thunderbird/38.2.0")}
};

52
53
static const QString pkeyPasswordMapKey = QStringLiteral("pkey-password");

54
55
56
57
static bool execJob(KJob *job)
{
    QEventLoop loop;
    QObject::connect(job, &KJob::finished, &loop, [&](KJob *j) {
Laurent Montel's avatar
Laurent Montel committed
58
59
        loop.exit(j->error());
    });
60
61
62
63
    job->start();
    return loop.exec() == 0;
}

Laurent Montel's avatar
Laurent Montel committed
64
EwsConfigDialog::EwsConfigDialog(EwsResource *parentResource, EwsClient &client, WId wId, EwsSettings *settings)
Laurent Montel's avatar
Laurent Montel committed
65
66
    : QDialog()
    , mParentResource(parentResource)
67
    , mSettings(settings)
68
69
{
    if (wId) {
70
        setAttribute(Qt::WA_NativeWindow, true);
71
        KWindowSystem::setMainWindow(windowHandle(), wId);
72
73
    }

Laurent Montel's avatar
Laurent Montel committed
74
    QVBoxLayout *mainLayout = new QVBoxLayout(this);
75
76
    QWidget *mainWidget = new QWidget(this);
    mainLayout->addWidget(mainWidget);
Laurent Montel's avatar
Laurent Montel committed
77
78

    mButtonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this);
79
80
81
    QPushButton *okButton = mButtonBox->button(QDialogButtonBox::Ok);
    okButton->setDefault(true);
    okButton->setShortcut(Qt::CTRL | Qt::Key_Return);
82
83
    connect(mButtonBox, &QDialogButtonBox::accepted, this, &EwsConfigDialog::dialogAccepted);
    connect(mButtonBox, &QDialogButtonBox::rejected, this, &EwsConfigDialog::reject);
84
85
    mainLayout->addWidget(mButtonBox);

86
    setWindowTitle(i18nc("@title:window", "Microsoft Exchange Configuration"));
87
88
89
90
91

    mUi = new Ui::SetupServerView;
    mUi->setupUi(mainWidget);
    mUi->accountName->setText(parentResource->name());

92
    mSubWidget = new EwsSubscriptionWidget(client, mSettings.data(), this);
93
94
    mUi->subscriptionTabLayout->addWidget(mSubWidget);

95
    mConfigManager = new KConfigDialogManager(this, mSettings.data());
96
    mConfigManager->updateWidgets();
97
    switch (mSettings->retrievalMethod()) {
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
    case 0:
        mUi->pollRadioButton->setChecked(true);
        break;
    case 1:
        mUi->streamingRadioButton->setChecked(true);
        break;
    default:
        break;
    }

    const EwsServerVersion &serverVer = client.serverVersion();
    if (serverVer.isValid()) {
        mUi->serverStatusText->setText(i18nc("Server status", "OK"));
        mUi->serverVersionText->setText(serverVer.toString());
    }

    bool baseUrlEmpty = mUi->kcfg_BaseUrl->text().isEmpty();
    mButtonBox->button(QDialogButtonBox::Ok)->setEnabled(!baseUrlEmpty);
    mUi->tryConnectButton->setEnabled(!baseUrlEmpty);
    mTryConnectNeeded = baseUrlEmpty;

119
120
    connect(mSettings.data(), &EwsSettings::passwordRequestFinished, mUi->passwordEdit,
            &KPasswordLineEdit::setPassword);
121
    mSettings->requestPassword(false);
122
123
    mUi->authOAuth2RadioButton->setEnabled(true);
    const auto authMode = mSettings->authMode();
124
    if (authMode == QLatin1String("username-password")) {
125
        mUi->authUsernameRadioButton->setChecked(true);
126
    } else if (authMode == QLatin1String("oauth2")) {
127
        mUi->authOAuth2RadioButton->setChecked(true);
128
        mUi->pkeyAuthGroupBox->setEnabled(true);
129
    }
130
131
132
133
#ifdef HAVE_QCA
    mUi->pkeyAuthCert->setText(mSettings->pKeyCert());
    mUi->pkeyAuthKey->setText(mSettings->pKeyKey());
    connect(mSettings.data(), &EwsSettings::mapRequestFinished, this, [&](const QMap<QString, QString> &map) {
Laurent Montel's avatar
Laurent Montel committed
134
135
136
137
        if (map.contains(pkeyPasswordMapKey)) {
            mUi->pkeyAuthPassword->setPassword(map[pkeyPasswordMapKey]);
        }
    });
138
139
    mSettings->requestMap();
#endif
140
141
142

    int selectedIndex = -1;
    int i = 0;
Laurent Montel's avatar
Laurent Montel committed
143
    for (const StringPair &item : qAsConst(userAgents)) {
144
        mUi->userAgentCombo->addItem(item.first, item.second);
145
        if (mSettings->userAgent() == item.second) {
146
147
148
149
150
            selectedIndex = i;
        }
        i++;
    }
    mUi->userAgentCombo->addItem(i18nc("User Agent", "Custom"));
151
    if (!mSettings->userAgent().isEmpty()) {
152
153
        mUi->userAgentGroupBox->setChecked(true);
        mUi->userAgentCombo->setCurrentIndex(selectedIndex >= 0 ? selectedIndex : mUi->userAgentCombo->count() - 1);
154
        mUi->userAgentEdit->setText(mSettings->userAgent());
155
156
157
158
159
160
161
    } else {
        mUi->userAgentCombo->setCurrentIndex(mUi->userAgentCombo->count());
    }

    QIcon ewsIcon = QIcon::fromTheme(QStringLiteral("akonadi-ews"));
    mUi->aboutIconLabel->setPixmap(ewsIcon.pixmap(96, 96, QIcon::Normal, QIcon::On));
    mUi->aboutTextLabel->setText(i18nc("@info", "Akonadi Resource for Microsoft Exchange Web Services (EWS)"));
Laurent Montel's avatar
Laurent Montel committed
162
    mUi->aboutCopyrightLabel->setText(i18nc("@info", "Copyright (c) Krzysztof Nowicki 2015-2017"));
Laurent Montel's avatar
Laurent Montel committed
163
    mUi->aboutVersionLabel->setText(i18nc("@info", "Version %1", QStringLiteral(AKONADI_EWS_VERSION)));
164
165
166
    mUi->aboutLicenseLabel->setText(i18nc("@info", "Distributed under the GNU Library General Public License version 2.0 or later."));
    mUi->aboutUrlLabel->setText(QStringLiteral("<a href=\"https://github.com/KrissN/akonadi-ews\">https://github.com/KrissN/akonadi-ews</a>"));

167
168
169
    mUi->pkeyAuthCert->setMode(KFile::File | KFile::ExistingOnly | KFile::LocalOnly);
    mUi->pkeyAuthKey->setMode(KFile::File | KFile::ExistingOnly | KFile::LocalOnly);

170
171
172
173
174
175
176
    connect(okButton, &QPushButton::clicked, this, &EwsConfigDialog::save);
    connect(mUi->autodiscoverButton, &QPushButton::clicked, this, &EwsConfigDialog::performAutoDiscovery);
    connect(mUi->kcfg_Username, &KLineEdit::textChanged, this, &EwsConfigDialog::setAutoDiscoveryNeeded);
    connect(mUi->passwordEdit, &KPasswordLineEdit::passwordChanged, this, &EwsConfigDialog::setAutoDiscoveryNeeded);
    connect(mUi->kcfg_Domain, &KLineEdit::textChanged, this, &EwsConfigDialog::setAutoDiscoveryNeeded);
    connect(mUi->kcfg_HasDomain, &QCheckBox::toggled, this, &EwsConfigDialog::setAutoDiscoveryNeeded);
    connect(mUi->kcfg_Email, &KLineEdit::textChanged, this, &EwsConfigDialog::setAutoDiscoveryNeeded);
177
178
    connect(mUi->authUsernameRadioButton, &QRadioButton::toggled, this, &EwsConfigDialog::setAutoDiscoveryNeeded);
    connect(mUi->authOAuth2RadioButton, &QRadioButton::toggled, this, &EwsConfigDialog::setAutoDiscoveryNeeded);
179
180
    connect(mUi->kcfg_BaseUrl, &KLineEdit::textChanged, this, &EwsConfigDialog::enableTryConnect);
    connect(mUi->tryConnectButton, &QPushButton::clicked, this, &EwsConfigDialog::tryConnect);
181
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
182
    connect(mUi->userAgentCombo, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &EwsConfigDialog::userAgentChanged);
183
184
185
#else
    connect(mUi->userAgentCombo, QOverload<int, const QString &>::of(&QComboBox::currentIndexChanged), this, &EwsConfigDialog::userAgentChanged);
#endif
186
187
188
    connect(mUi->clearFolderTreeSyncStateButton, &QPushButton::clicked, mParentResource,
            &EwsResource::clearFolderTreeSyncState);
    connect(mUi->clearFolderItemSyncStateButton, &QPushButton::clicked, mParentResource,
Laurent Montel's avatar
Laurent Montel committed
189
            QOverload<>::of(&EwsResource::clearFolderSyncState));
190
191
}

192
EwsConfigDialog::~EwsConfigDialog()
193
194
195
196
{
    delete mUi;
}

197
void EwsConfigDialog::save()
198
199
200
201
{
    mParentResource->setName(mUi->accountName->text());
    mConfigManager->updateSettings();
    if (mUi->pollRadioButton->isChecked()) {
202
        mSettings->setRetrievalMethod(0);
203
    } else {
204
        mSettings->setRetrievalMethod(1);
205
206
207
208
    }

    /* Erase the subscription id in case subscription is disabled or its parameters changed. This
     * fill force creation of a new subscription. */
Laurent Montel's avatar
Laurent Montel committed
209
210
    if (!mSubWidget->subscriptionEnabled()
        || (mSubWidget->subscribedList() != mSettings->serverSubscriptionList())) {
211
212
        mSettings->setEventSubscriptionId(QString());
        mSettings->setEventSubscriptionWatermark(QString());
213
214
    }

215
    mSettings->setServerSubscription(mSubWidget->subscriptionEnabled());
216
    if (mSubWidget->subscribedListValid()) {
217
        mSettings->setServerSubscriptionList(mSubWidget->subscribedList());
218
219
220
    }

    if (mUi->userAgentGroupBox->isChecked()) {
221
        mSettings->setUserAgent(mUi->userAgentEdit->text());
222
    } else {
223
        mSettings->setUserAgent(QString());
224
225
    }

226
227
228
229
230
231
    if (mUi->authUsernameRadioButton->isChecked()) {
        mSettings->setAuthMode(QStringLiteral("username-password"));
    }
    if (mUi->authOAuth2RadioButton->isChecked()) {
        mSettings->setAuthMode(QStringLiteral("oauth2"));
    }
232
#ifdef HAVE_QCA
Laurent Montel's avatar
Laurent Montel committed
233
234
    if (mUi->pkeyAuthGroupBox->isEnabled()
        && !mUi->pkeyAuthCert->text().isEmpty() && !mUi->pkeyAuthKey->text().isEmpty()) {
235
236
237
238
239
240
241
        mSettings->setPKeyCert(mUi->pkeyAuthCert->text());
        mSettings->setPKeyKey(mUi->pkeyAuthKey->text());
        const QMap<QString, QString> map = {{pkeyPasswordMapKey, mUi->pkeyAuthPassword->password()}};
        mSettings->setMap(map);
    }
#endif

242
243
244
    if (!mAuthMap.isEmpty()) {
        mSettings->setMap(mAuthMap);
    }
245
    mSettings->save();
246
247
}

248
void EwsConfigDialog::performAutoDiscovery()
249
250
{
    mAutoDiscoveryJob = new EwsAutodiscoveryJob(mUi->kcfg_Email->text(),
Laurent Montel's avatar
Laurent Montel committed
251
252
253
                                                fullUsername(), mUi->passwordEdit->password(),
                                                mUi->userAgentGroupBox->isEnabled() ? mUi->userAgentEdit->text() : QString(),
                                                mUi->kcfg_EnableNTLMv2->isChecked(), this);
254
255
256
    connect(mAutoDiscoveryJob, &EwsAutodiscoveryJob::result, this, &EwsConfigDialog::autoDiscoveryFinished);
    mProgressDialog = new EwsProgressDialog(this, EwsProgressDialog::AutoDiscovery);
    connect(mProgressDialog, &QDialog::rejected, this, &EwsConfigDialog::autoDiscoveryCancelled);
257
258
259
260
    mAutoDiscoveryJob->start();
    mProgressDialog->show();
}

261
void EwsConfigDialog::autoDiscoveryFinished(KJob *job)
262
263
264
265
266
267
268
269
270
271
272
273
274
275
{
    if (job->error() || job != mAutoDiscoveryJob) {
        KMessageBox::error(this, job->errorText(), i18nc("Exchange server autodiscovery", "Autodiscovery failed"));
        mProgressDialog->reject();
    } else {
        mProgressDialog->accept();
        mUi->kcfg_BaseUrl->setText(mAutoDiscoveryJob->ewsUrl());
    }
    mAutoDiscoveryJob->deleteLater();
    mAutoDiscoveryJob = nullptr;
    mProgressDialog->deleteLater();
    mProgressDialog = nullptr;
}

276
void EwsConfigDialog::tryConnectFinished(KJob *job)
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
{
    if (job->error() || job != mTryConnectJob) {
        KMessageBox::error(this, job->errorText(), i18nc("Exchange server connection", "Connection failed"));
        mUi->serverStatusText->setText(i18nc("Exchange server status", "Failed"));
        mUi->serverVersionText->setText(i18nc("Exchange server version", "Unknown"));
        mProgressDialog->reject();
    } else {
        mUi->serverStatusText->setText(i18nc("Exchange server status", "OK"));
        mUi->serverVersionText->setText(mTryConnectJob->serverVersion().toString());
        mProgressDialog->accept();
    }
    //mTryConnectJob->deleteLater();
    mTryConnectJob = nullptr;
    //mProgressDialog->deleteLater();
    mProgressDialog = nullptr;
}

294
void EwsConfigDialog::autoDiscoveryCancelled()
295
296
297
298
299
300
301
302
{
    if (mAutoDiscoveryJob) {
        mAutoDiscoveryJob->kill();
    }
    mProgressDialog->deleteLater();
    mProgressDialog = nullptr;
}

303
void EwsConfigDialog::tryConnectCancelled()
304
305
306
307
{
    if (mTryConnectJob) {
        mTryConnectJob->kill();
    }
308
309

    mTryConnectJobCancelled = true;
310
311
}

312
void EwsConfigDialog::setAutoDiscoveryNeeded()
313
314
315
{
    mAutoDiscoveryNeeded = true;
    mTryConnectNeeded = true;
316
    mAuthMap.clear();
317
318
319
320
321
322
323
324

    /* Enable the OK button when at least the e-mail and username fields are set. Additionally if
     * autodiscovery is disabled, enable the OK button only if the base URL is set. */
    bool okEnabled = !mUi->kcfg_Username->text().isEmpty() && !mUi->kcfg_Email->text().isEmpty();
    if (!mUi->kcfg_AutoDiscovery->isChecked() && mUi->kcfg_BaseUrl->text().isEmpty()) {
        okEnabled = false;
    }
    mButtonBox->button(QDialogButtonBox::Ok)->setEnabled(okEnabled);
325
326

    mUi->pkeyAuthGroupBox->setEnabled(mUi->authOAuth2RadioButton->isChecked());
327
328
}

329
QString EwsConfigDialog::fullUsername() const
330
331
332
333
334
335
336
337
{
    QString username = mUi->kcfg_Username->text();
    if (mUi->kcfg_HasDomain->isChecked()) {
        username.prepend(mUi->kcfg_Domain->text() + QStringLiteral("\\"));
    }
    return username;
}

338
void EwsConfigDialog::dialogAccepted()
339
340
341
{
    if (mUi->kcfg_AutoDiscovery->isChecked() && mAutoDiscoveryNeeded) {
        mAutoDiscoveryJob = new EwsAutodiscoveryJob(mUi->kcfg_Email->text(),
Laurent Montel's avatar
Laurent Montel committed
342
343
344
                                                    fullUsername(), mUi->passwordEdit->password(),
                                                    mUi->userAgentGroupBox->isEnabled() ? mUi->userAgentEdit->text() : QString(),
                                                    mUi->kcfg_EnableNTLMv2->isChecked(), this);
345
346
347
        connect(mAutoDiscoveryJob, &EwsAutodiscoveryJob::result, this, &EwsConfigDialog::autoDiscoveryFinished);
        mProgressDialog = new EwsProgressDialog(this, EwsProgressDialog::AutoDiscovery);
        connect(mProgressDialog, &QDialog::rejected, this, &EwsConfigDialog::autoDiscoveryCancelled);
348
349
350
351
352
353
354
        mAutoDiscoveryJob->start();
        if (!mProgressDialog->exec()) {
            if (KMessageBox::questionYesNo(this,
                                           i18n("Autodiscovery failed. This can be caused by incorrect parameters. Do you still want to save your settings?"),
                                           i18n("Exchange server autodiscovery")) == KMessageBox::Yes) {
                accept();
            }
Laurent Montel's avatar
Laurent Montel committed
355
            return;
356
357
358
359
360
361
        }
    }

    if (mTryConnectNeeded) {
        EwsClient cli;
        cli.setUrl(mUi->kcfg_BaseUrl->text());
362
363
        const auto auth = prepareAuth();
        cli.setAuth(auth);
364
365
366
367
368
369
370
        if (mUi->userAgentGroupBox->isChecked()) {
            cli.setUserAgent(mUi->userAgentEdit->text());
        }
        cli.setEnableNTLMv2(mUi->kcfg_EnableNTLMv2->isChecked());
        mTryConnectJob = new EwsGetFolderRequest(cli, this);
        mTryConnectJob->setFolderShape(EwsFolderShape(EwsShapeIdOnly));
        mTryConnectJob->setFolderIds(EwsId::List() << EwsId(EwsDIdInbox));
371
372
373
        connect(mTryConnectJob, &EwsGetFolderRequest::result, this, &EwsConfigDialog::tryConnectFinished);
        mProgressDialog = new EwsProgressDialog(this, EwsProgressDialog::TryConnect);
        connect(mProgressDialog, &QDialog::rejected, this, &EwsConfigDialog::tryConnectCancelled);
374
        mTryConnectJob->start();
375
376
377
378
379
380
381
        if (!execJob(mTryConnectJob)) {
            if (!mTryConnectJobCancelled) {
                if (KMessageBox::questionYesNo(this,
                                               i18n("Connecting to Exchange failed. This can be caused by incorrect parameters. Do you still want to save your settings?"),
                                               i18n("Exchange server connection")) == KMessageBox::Yes) {
                    accept();
                }
382
            }
Laurent Montel's avatar
Laurent Montel committed
383
            return;
384
385
386
387
388
389
390
391
392
393
        } else {
            accept();
        }
    }

    if (!mTryConnectNeeded && !mAutoDiscoveryNeeded) {
        accept();
    }
}

394
void EwsConfigDialog::enableTryConnect()
395
396
397
398
399
400
401
402
403
404
405
406
407
408
{
    mTryConnectNeeded = true;
    bool baseUrlEmpty = mUi->kcfg_BaseUrl->text().isEmpty();

    /* Enable the OK button when at least the e-mail and username fields are set. Additionally if
     * autodiscovery is disabled, enable the OK button only if the base URL is set. */
    bool okEnabled = !mUi->kcfg_Username->text().isEmpty() && !mUi->kcfg_Email->text().isEmpty();
    if (!mUi->kcfg_AutoDiscovery->isChecked() && baseUrlEmpty) {
        okEnabled = false;
    }
    mButtonBox->button(QDialogButtonBox::Ok)->setEnabled(okEnabled);
    mUi->tryConnectButton->setEnabled(!baseUrlEmpty);
}

409
void EwsConfigDialog::tryConnect()
410
411
412
{
    EwsClient cli;
    cli.setUrl(mUi->kcfg_BaseUrl->text());
413
414
    const auto auth = prepareAuth();
    cli.setAuth(auth);
415
416
417
418
419
420
421
    if (mUi->userAgentGroupBox->isChecked()) {
        cli.setUserAgent(mUi->userAgentEdit->text());
    }
    cli.setEnableNTLMv2(mUi->kcfg_EnableNTLMv2->isChecked());
    mTryConnectJob = new EwsGetFolderRequest(cli, this);
    mTryConnectJob->setFolderShape(EwsFolderShape(EwsShapeIdOnly));
    mTryConnectJob->setFolderIds(EwsId::List() << EwsId(EwsDIdInbox));
422
    mTryConnectJobCancelled = false;
423
424
    mProgressDialog = new EwsProgressDialog(this, EwsProgressDialog::TryConnect);
    connect(mProgressDialog, &QDialog::rejected, this, &EwsConfigDialog::tryConnectCancelled);
425
    mProgressDialog->show();
426
427
428
429
430
431
    if (!execJob(mTryConnectJob)) {
        if (!mTryConnectJobCancelled) {
            mUi->serverStatusText->setText(i18nc("Exchange server status", "Failed"));
            mUi->serverVersionText->setText(i18nc("Exchange server version", "Unknown"));
            KMessageBox::error(this, mTryConnectJob->errorText(), i18n("Connection failed"));
        }
432
433
434
435
436
    } else {
        mUi->serverStatusText->setText(i18nc("Exchange server status", "OK"));
        mUi->serverVersionText->setText(mTryConnectJob->serverVersion().toString());
    }
    mProgressDialog->hide();
437
    mTryConnectJob = nullptr;
438
439
}

440
void EwsConfigDialog::userAgentChanged(int)
441
442
443
444
445
446
447
{
    QString data = mUi->userAgentCombo->currentData().toString();
    mUi->userAgentEdit->setEnabled(data.isEmpty());
    if (!data.isEmpty()) {
        mUi->userAgentEdit->setText(data);
    }
}
448

449
EwsAbstractAuth *EwsConfigDialog::prepareAuth()
450
{
451
452
    EwsAbstractAuth *auth = nullptr;

453
    if (mUi->authOAuth2RadioButton->isChecked()) {
454
        auth = new EwsOAuth(this, mUi->kcfg_Email->text(), mSettings->oAuth2AppId(), mSettings->oAuth2ReturnUri());
Laurent Montel's avatar
Laurent Montel committed
455
    } else if (mUi->authUsernameRadioButton->isChecked()) {
456
        auth = new EwsPasswordAuth(fullUsername(), this);
Laurent Montel's avatar
Laurent Montel committed
457
458
459
    } else {
        //Be sure that it will not crash.
        return auth;
460
    }
461
    auth->setAuthParentWidget(this);
462

463
#ifdef HAVE_QCA
Laurent Montel's avatar
Laurent Montel committed
464
465
    if (mUi->pkeyAuthGroupBox->isEnabled()
        && !mUi->pkeyAuthCert->text().isEmpty() && !mUi->pkeyAuthKey->text().isEmpty()) {
466
467
468
469
470
        auth->setPKeyAuthCertificateFiles(mUi->pkeyAuthCert->text(), mUi->pkeyAuthKey->text());
        mAuthMap[pkeyPasswordMapKey] = mUi->pkeyAuthPassword->password();
    }
#endif

471
    connect(auth, &EwsAbstractAuth::requestWalletPassword, this, [&](bool) {
Laurent Montel's avatar
Laurent Montel committed
472
473
        auth->walletPasswordRequestFinished(mUi->passwordEdit->password());
    });
474
    connect(auth, &EwsAbstractAuth::requestWalletMap, this, [&]() {
Laurent Montel's avatar
Laurent Montel committed
475
476
        auth->walletMapRequestFinished(mAuthMap);
    });
477
    connect(auth, &EwsAbstractAuth::setWalletMap, this, [&](const QMap<QString, QString> &map) {
Laurent Montel's avatar
Laurent Montel committed
478
479
        mAuthMap = map;
    });
480
481
482
483
484
485
486

    auth->init();

    QEventLoop loop;
    bool authFinished = false;

    connect(auth, &EwsAbstractAuth::authSucceeded, this, [&]() {
Laurent Montel's avatar
Laurent Montel committed
487
488
489
490
491
492
493
        authFinished = true;
        loop.exit(0);
    });
    connect(auth, &EwsAbstractAuth::authFailed, this, [&](const QString &) {
        authFinished = true;
        loop.exit(0);
    });
494
495
496
497
498
499
500
501

    if (auth->authenticate(true)) {
        if (!authFinished) {
            loop.exec();
        }
    }

    return auth;
502
}