File indexing completed on 2024-06-02 05:20:57

0001 /*
0002     SPDX-FileCopyrightText: 2015-2016 Krzysztof Nowicki <krissn@op.pl>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "ewsautodiscoveryjob.h"
0008 
0009 #include "ewspoxautodiscoverrequest.h"
0010 #include "ewsresource_debug.h"
0011 
0012 #include <KLocalizedString>
0013 
0014 EwsAutodiscoveryJob::EwsAutodiscoveryJob(const QString &email,
0015                                          const QString &username,
0016                                          const QString &password,
0017                                          const QString &userAgent,
0018                                          bool enableNTLMv2,
0019                                          QObject *parent)
0020     : EwsJob(parent)
0021     , mEmail(email)
0022     , mUsername(username)
0023     , mPassword(password)
0024     , mUserAgent(userAgent)
0025     , mEnableNTLMv2(enableNTLMv2)
0026 {
0027 }
0028 
0029 EwsAutodiscoveryJob::~EwsAutodiscoveryJob() = default;
0030 
0031 void EwsAutodiscoveryJob::start()
0032 {
0033     parseEmail();
0034 
0035     if (!mUrlQueue.isEmpty()) {
0036         sendNextRequest(false);
0037     }
0038 }
0039 
0040 void EwsAutodiscoveryJob::parseEmail()
0041 {
0042     const int atIndex = mEmail.indexOf(QLatin1Char('@'));
0043     if (atIndex < 0) {
0044         setErrorMsg(i18n("Incorrect email address"));
0045         emitResult();
0046         return;
0047     }
0048 
0049     const QString domain = mEmail.mid(atIndex + 1);
0050     if (domain.isEmpty()) {
0051         setErrorMsg(i18n("Incorrect email address"));
0052         emitResult();
0053         return;
0054     }
0055 
0056     addUrls(domain);
0057 }
0058 
0059 void EwsAutodiscoveryJob::addUrls(const QString &domain)
0060 {
0061     mUrlQueue.enqueue(QStringLiteral("https://") + domain + QStringLiteral("/autodiscover/autodiscover.xml"));
0062     mUrlQueue.enqueue(QStringLiteral("https://autodiscover.") + domain + QStringLiteral("/autodiscover/autodiscover.xml"));
0063     mUrlQueue.enqueue(QStringLiteral("http://") + domain + QStringLiteral("/autodiscover/autodiscover.xml"));
0064     mUrlQueue.enqueue(QStringLiteral("http://autodiscover.") + domain + QStringLiteral("/autodiscover/autodiscover.xml"));
0065 }
0066 
0067 void EwsAutodiscoveryJob::sendNextRequest(bool useCreds)
0068 {
0069     QUrl url(mUrlQueue.head());
0070     if (useCreds) {
0071         url.setUserName(mUsername);
0072         url.setPassword(mPassword);
0073     }
0074     mUsedCreds = useCreds;
0075     auto req = new EwsPoxAutodiscoverRequest(url, mEmail, mUserAgent, mEnableNTLMv2, this);
0076     connect(req, &EwsPoxAutodiscoverRequest::result, this, &EwsAutodiscoveryJob::autodiscoveryRequestFinished);
0077     req->start();
0078 }
0079 
0080 void EwsAutodiscoveryJob::autodiscoveryRequestFinished(KJob *job)
0081 {
0082     auto req = qobject_cast<EwsPoxAutodiscoverRequest *>(job);
0083     if (!req) {
0084         setErrorMsg(QStringLiteral("Invalid EwsPoxAutodiscoverRequest job object"));
0085         emitResult();
0086         return;
0087     }
0088 
0089     if (req->error()) {
0090         if (req->error() == 401 && !mUsedCreds && req->lastHttpUrl().scheme() != QLatin1StringView("http")) { // Don't try authentication over HTTP
0091             /* The 401 error may have come from an URL different to the original one (due to
0092              * redirections). When the original URL is retried with credentials KIO HTTP will issue
0093              * a warning that an authenticated request is made to a host that never asked for it.
0094              * To fix this restart the request using the last URL that resulted in the 401 code. */
0095             mUrlQueue.head() = req->lastHttpUrl().toString();
0096             sendNextRequest(true);
0097             return;
0098         } else {
0099             mUrlQueue.removeFirst();
0100         }
0101 
0102         if (mUrlQueue.isEmpty()) {
0103             setErrorText(job->errorText());
0104             setError(job->error());
0105             emitResult();
0106         } else {
0107             sendNextRequest(false);
0108         }
0109     } else {
0110         switch (req->action()) {
0111         case EwsPoxAutodiscoverRequest::Settings: {
0112             EwsPoxAutodiscoverRequest::Protocol proto = req->protocol(EwsPoxAutodiscoverRequest::ExchangeProto);
0113             if (!proto.isValid()) {
0114                 setErrorMsg(i18n("Exchange protocol information not found"));
0115             } else {
0116                 mEwsUrl = proto.ewsUrl();
0117                 mOabUrl = proto.oabUrl();
0118             }
0119             emitResult();
0120             break;
0121         }
0122         case EwsPoxAutodiscoverRequest::RedirectAddr:
0123             qCDebug(EWSRES_LOG) << "Redirected to e-mail addr" << req->redirectAddr();
0124             mEmail = req->redirectAddr();
0125             mUrlQueue.clear();
0126             parseEmail();
0127             if (!mUrlQueue.isEmpty()) {
0128                 sendNextRequest(false);
0129             }
0130             break;
0131         case EwsPoxAutodiscoverRequest::RedirectUrl:
0132             qCDebug(EWSRES_LOG) << "Redirected to URL" << req->redirectUrl();
0133             mUrlQueue.clear();
0134             mUrlQueue.enqueue(req->redirectUrl());
0135             sendNextRequest(false);
0136             break;
0137         }
0138     }
0139 }
0140 
0141 #include "moc_ewsautodiscoveryjob.cpp"