/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Network Auth module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:GPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 or (at your option) any later version
** approved by the KDE Free Qt Foundation. The licenses are as published by
** the Free Software Foundation and appearing in the file LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include <QtNetwork/qtnetwork-config.h>

#ifndef QT_NO_HTTP

#include "qoauth1.h"
#include "qoauth1_p.h"
#include "qoauth1signature.h"
#include "qoauthoobreplyhandler.h"
#include "qoauthhttpserverreplyhandler.h"

#include <QtCore/qmap.h>
#include <QtCore/qlist.h>
#include <QtCore/qvariant.h>
#include <QtCore/qurlquery.h>
#include <QtCore/qdatetime.h>
#include <QtCore/qbytearray.h>
#include <QtCore/qmessageauthenticationcode.h>

#include <QtNetwork/qnetworkreply.h>
#include <QtNetwork/qnetworkrequest.h>
#include <QtNetwork/qnetworkaccessmanager.h>

QT_BEGIN_NAMESPACE

/*!
    \class QOAuth1
    \inmodule QtNetworkAuth
    \ingroup oauth
    \brief The QOAuth1 class provides an implementation of the
    \l {https://tools.ietf.org/html/rfc5849}{OAuth 1 Protocol}.
    \since 5.8

    QOAuth1 provides a method for clients to access server resources
    on behalf of a resource owner (such as a different client or an
    end-user). It also provides a process for end-users to authorize
    third-party access to their server resources without sharing
    their credentials (typically, a username and password pair),
    using user-agent redirections.

    QOAuth1 uses tokens to represent the authorization granted to the
    client by the resource owner.  Typically, token credentials are
    issued by the server at the resource owner's request, after
    authenticating the resource owner's identity (usually using a
    username and password).

    When making the temporary credentials request, the client
    authenticates using only the client credentials. When making the
    token request, the client authenticates using the client
    credentials as well as the temporary credentials. Once the
    client receives and stores the token credentials, it can
    proceed to access protected resources on behalf of the resource
    owner by making authenticated requests using the client
    credentials together with the token credentials received.
*/

/*!
    \enum QOAuth1::SignatureMethod

    Indicates the signature method to be used to sign requests.

    \value Hmac_Sha1
    \l {https://tools.ietf.org/html/rfc5849#section-3.4.2}
    {HMAC-SHA1} signature method.

    \value Rsa_Sha1
    \l {https://tools.ietf.org/html/rfc5849#section-3.4.3}
    {RSA-SHA1} signature method (not supported).

    \value PlainText
    \l {https://tools.ietf.org/html/rfc5849#section-3.4.4}
    {PLAINTEXT} signature method.
*/

using Key = QOAuth1Private::OAuth1KeyString;
const QString Key::oauthCallback =           QStringLiteral("oauth_callback");
const QString Key::oauthCallbackConfirmed =  QStringLiteral("oauth_callback_confirmed");
const QString Key::oauthConsumerKey =        QStringLiteral("oauth_consumer_key");
const QString Key::oauthNonce =              QStringLiteral("oauth_nonce");
const QString Key::oauthSignature =          QStringLiteral("oauth_signature");
const QString Key::oauthSignatureMethod =    QStringLiteral("oauth_signature_method");
const QString Key::oauthTimestamp =          QStringLiteral("oauth_timestamp");
const QString Key::oauthToken =              QStringLiteral("oauth_token");
const QString Key::oauthTokenSecret =        QStringLiteral("oauth_token_secret");
const QString Key::oauthVerifier =           QStringLiteral("oauth_verifier");
const QString Key::oauthVersion =            QStringLiteral("oauth_version");

QOAuth1Private::QOAuth1Private(const QPair<QString, QString> &clientCredentials,
                               QNetworkAccessManager *networkAccessManager) :
    QAbstractOAuthPrivate("qt.networkauth.oauth1",
                          QUrl(),
                          clientCredentials.first,
                          networkAccessManager),
    clientIdentifierSharedKey(clientCredentials.second)
{
    qRegisterMetaType<QNetworkReply::NetworkError>("QNetworkReply::NetworkError");
    qRegisterMetaType<QOAuth1::SignatureMethod>("QOAuth1::SignatureMethod");
}

void QOAuth1Private::appendCommonHeaders(QVariantMap *headers)
{
    const auto currentDateTime = QDateTime::currentDateTimeUtc();

    headers->insert(Key::oauthNonce, QOAuth1::nonce());
    headers->insert(Key::oauthConsumerKey, clientIdentifier);
    headers->insert(Key::oauthTimestamp, QString::number(currentDateTime.toSecsSinceEpoch()));
    headers->insert(Key::oauthVersion, oauthVersion);
    headers->insert(Key::oauthSignatureMethod, signatureMethodString().toUtf8());
}

void QOAuth1Private::appendSignature(QAbstractOAuth::Stage stage,
                                     QVariantMap *headers,
                                     const QUrl &url,
                                     QNetworkAccessManager::Operation operation,
                                     const QVariantMap parameters)
{
    QByteArray signature;
    {
        QMultiMap<QString, QVariant> headerCopy = *headers;
        QVariantMap allParameters = headerCopy.unite(parameters);
        if (modifyParametersFunction)
            modifyParametersFunction(stage, &allParameters);
        signature = generateSignature(allParameters, url, operation);
    }
    headers->insert(Key::oauthSignature, signature);
}

QNetworkReply *QOAuth1Private::requestToken(QNetworkAccessManager::Operation operation,
                                            const QUrl &url,
                                            const QPair<QString, QString> &token,
                                            const QVariantMap &parameters)
{
    if (Q_UNLIKELY(!networkAccessManager())) {
        qCWarning(loggingCategory, "QNetworkAccessManager not available");
        return nullptr;
    }
    if (Q_UNLIKELY(url.isEmpty())) {
        qCWarning(loggingCategory, "Request Url not set");
        return nullptr;
    }
    if (Q_UNLIKELY(operation != QNetworkAccessManager::GetOperation &&
                   operation != QNetworkAccessManager::PostOperation)) {
        qCWarning(loggingCategory, "Operation not supported");
        return nullptr;
    }

    QNetworkRequest request(url);
    request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);

    QAbstractOAuth::Stage stage = QAbstractOAuth::Stage::RequestingTemporaryCredentials;
    QVariantMap headers;
    QVariantMap remainingParameters;
    appendCommonHeaders(&headers);
    for (auto it = parameters.begin(), end = parameters.end(); it != end; ++it) {
        const auto key = it.key();
        const auto value = it.value();
        if (key.startsWith(QStringLiteral("oauth_")))
            headers.insert(key, value);
        else
            remainingParameters.insert(key, value);
    }
    if (!token.first.isEmpty()) {
        headers.insert(Key::oauthToken, token.first);
        stage = QAbstractOAuth::Stage::RequestingAccessToken;
    }
    appendSignature(stage, &headers, url, operation, remainingParameters);

    request.setRawHeader("Authorization", QOAuth1::generateAuthorizationHeader(headers));

    QNetworkReply *reply = nullptr;
    if (operation == QNetworkAccessManager::GetOperation) {
        if (parameters.size() > 0) {
            QUrl url = request.url();
            url.setQuery(QOAuth1Private::createQuery(remainingParameters));
            request.setUrl(url);
        }
        reply = networkAccessManager()->get(request);
    }
    else if (operation == QNetworkAccessManager::PostOperation) {
        QUrlQuery query = QOAuth1Private::createQuery(remainingParameters);
        const QByteArray data = query.toString(QUrl::FullyEncoded).toUtf8();
        request.setHeader(QNetworkRequest::ContentTypeHeader,
                          QStringLiteral("application/x-www-form-urlencoded"));
        reply = networkAccessManager()->post(request, data);
    }

    connect(reply, &QNetworkReply::errorOccurred,
            this, &QOAuth1Private::_q_onTokenRequestError);

    QAbstractOAuthReplyHandler *handler = replyHandler ? replyHandler.data()
                                                       : defaultReplyHandler.data();
    QObject::connect(reply, &QNetworkReply::finished,
                     [handler, reply]() { handler->networkReplyFinished(reply); });
    connect(handler, &QAbstractOAuthReplyHandler::tokensReceived, this,
            &QOAuth1Private::_q_tokensReceived);

    return reply;
}

QString QOAuth1Private::signatureMethodString() const
{
    switch (signatureMethod) { // No default: intended
    case QOAuth1::SignatureMethod::PlainText:
        return QStringLiteral("PLAINTEXT");
    case QOAuth1::SignatureMethod::Hmac_Sha1:
        return QStringLiteral("HMAC-SHA1");
    case QOAuth1::SignatureMethod::Rsa_Sha1:
        qFatal("RSA-SHA1 signature method not supported");
        return QStringLiteral("RSA-SHA1");
    }
    qFatal("Invalid signature method");
    return QString();
}

QByteArray QOAuth1Private::generateSignature(const QVariantMap &parameters,
                                             const QUrl &url,
                                             QNetworkAccessManager::Operation operation) const
{
    QOAuth1Signature signature(url,
                               clientIdentifierSharedKey,
                               tokenSecret,
                               static_cast<QOAuth1Signature::HttpRequestMethod>(operation),
                               parameters);
    return formatSignature(signature);
}

QByteArray QOAuth1Private::generateSignature(const QVariantMap &parameters,
                                             const QUrl &url,
                                             const QByteArray &verb) const
{
    QOAuth1Signature signature(url,
                               clientIdentifierSharedKey,
                               tokenSecret,
                               QOAuth1Signature::HttpRequestMethod::Custom,
                               parameters);
    signature.setCustomMethodString(verb);
    return formatSignature(signature);
}

QByteArray QOAuth1Private::formatSignature(const QOAuth1Signature &signature) const
{
    switch (signatureMethod) {
    case QOAuth1::SignatureMethod::Hmac_Sha1:
        return signature.hmacSha1().toBase64();
    case QOAuth1::SignatureMethod::PlainText:
        return signature.plainText();
    default:
        qFatal("QOAuth1Private::generateSignature: Signature method not supported");
        return QByteArray();
    }
}

QVariantMap QOAuth1Private::createOAuthBaseParams() const
{
    QVariantMap oauthParams;

    const auto currentDateTime = QDateTime::currentDateTimeUtc();

    oauthParams.insert(Key::oauthConsumerKey, clientIdentifier);
    oauthParams.insert(Key::oauthVersion, QStringLiteral("1.0"));
    oauthParams.insert(Key::oauthToken, token);
    oauthParams.insert(Key::oauthSignatureMethod, signatureMethodString());
    oauthParams.insert(Key::oauthNonce, QOAuth1::nonce());
    oauthParams.insert(Key::oauthTimestamp, QString::number(currentDateTime.toSecsSinceEpoch()));

    return oauthParams;
}

void QOAuth1Private::prepareRequestImpl(QNetworkRequest *request,
                                        const QByteArray &verb,
                                        const QByteArray &body)
{
    Q_Q(QOAuth1);
    QVariantMap signingParams;
    if (verb == "POST" &&
        request->header(QNetworkRequest::ContentTypeHeader).toByteArray()
            == "application/x-www-form-urlencoded") {
        QUrlQuery query(QString::fromUtf8(body));
        for (const auto &item : query.queryItems(QUrl::FullyDecoded))
            signingParams.insert(item.first, item.second);
    }
    q->setup(request, signingParams, verb);
}

void QOAuth1Private::_q_onTokenRequestError(QNetworkReply::NetworkError error)
{
    Q_Q(QOAuth1);
    Q_UNUSED(error);
    Q_EMIT q->requestFailed(QAbstractOAuth::Error::NetworkError);
}

void QOAuth1Private::_q_tokensReceived(const QVariantMap &tokens)
{
    Q_Q(QOAuth1);

    if (!tokenRequested && status == QAbstractOAuth::Status::TemporaryCredentialsReceived) {
        // We didn't request a token yet, but in the "TemporaryCredentialsReceived" state _any_
        // new tokens received will count as a successful authentication and we move to the
        // 'Granted' state. To avoid this, 'status' will be temporarily set to 'NotAuthenticated'.
        status = QAbstractOAuth::Status::NotAuthenticated;
    }
    if (tokenRequested) // 'Reset' tokenRequested now that we've gotten new tokens
        tokenRequested = false;

    QPair<QString, QString> credential(tokens.value(Key::oauthToken).toString(),
                                       tokens.value(Key::oauthTokenSecret).toString());
    switch (status) {
    case QAbstractOAuth::Status::NotAuthenticated:
        if (tokens.value(Key::oauthCallbackConfirmed, true).toBool()) {
            q->setTokenCredentials(credential);
            setStatus(QAbstractOAuth::Status::TemporaryCredentialsReceived);
        } else {
            Q_EMIT q->requestFailed(QAbstractOAuth::Error::OAuthCallbackNotVerified);
        }
        break;
    case QAbstractOAuth::Status::TemporaryCredentialsReceived:
        q->setTokenCredentials(credential);
        setStatus(QAbstractOAuth::Status::Granted);
        break;
    case QAbstractOAuth::Status::Granted:
    case QAbstractOAuth::Status::RefreshingToken:
        break;
    }
}

/*!
    Constructs a QOAuth1 object with parent object \a parent.
*/
QOAuth1::QOAuth1(QObject *parent) :
    QOAuth1(nullptr,
            parent)
{}

/*!
    Constructs a QOAuth1 object with parent object \a parent, using
    \a manager to access the network.
*/
QOAuth1::QOAuth1(QNetworkAccessManager *manager, QObject *parent) :
    QOAuth1(QString(),
            QString(),
            manager,
            parent)
{}

/*!
    Constructs a QOAuth1 object with parent object \a parent, using
    \a manager to access the network.
    Also sets \a clientIdentifier and \a clientSharedSecret to sign
    the calls to the web server and identify the application.
*/
QOAuth1::QOAuth1(const QString &clientIdentifier,
                 const QString &clientSharedSecret,
                 QNetworkAccessManager *manager,
                 QObject *parent)
    : QAbstractOAuth(*new QOAuth1Private(qMakePair(clientIdentifier, clientSharedSecret),
                                         manager),
                     parent)
{}

/*!
    Returns the current shared secret used to sign requests to
    the web server.

    \sa setClientSharedSecret(), clientCredentials()
*/
QString QOAuth1::clientSharedSecret() const
{
    Q_D(const QOAuth1);
    return d->clientIdentifierSharedKey;
}

/*!
    Sets \a clientSharedSecret as the string used to sign the
    requests to the web server.

    \sa clientSharedSecret(), setClientCredentials()
*/
void QOAuth1::setClientSharedSecret(const QString &clientSharedSecret)
{
    Q_D(QOAuth1);
    if (d->clientIdentifierSharedKey != clientSharedSecret) {
        d->clientIdentifierSharedKey = clientSharedSecret;
        Q_EMIT clientSharedSecretChanged(clientSharedSecret);
    }
}

/*!
    Returns the pair of QString used to identify the application and
    sign requests to the web server.

    \sa setClientCredentials()
*/
QPair<QString, QString> QOAuth1::clientCredentials() const
{
    Q_D(const QOAuth1);
    return qMakePair(d->clientIdentifier, d->clientIdentifierSharedKey);
}

/*!
    Sets \a clientCredentials as the pair of QString used to identify
    the application and sign requests to the web server.

    \sa clientCredentials()
*/
void QOAuth1::setClientCredentials(const QPair<QString, QString> &clientCredentials)
{
    setClientCredentials(clientCredentials.first, clientCredentials.second);
}

/*!
    Sets \a clientIdentifier and \a clientSharedSecret as the pair of
    QString used to identify the application and sign requests to the
    web server. \a clientIdentifier identifies the application and
    \a clientSharedSecret is used to sign requests.

    \sa clientCredentials()
*/
void QOAuth1::setClientCredentials(const QString &clientIdentifier,
                                   const QString &clientSharedSecret)
{
    setClientIdentifier(clientIdentifier);
    setClientSharedSecret(clientSharedSecret);
}

/*!
    Returns the current token secret used to sign authenticated
    requests to the web server.

    \sa setTokenSecret(), tokenCredentials()
*/
QString QOAuth1::tokenSecret() const
{
    Q_D(const QOAuth1);
    return d->tokenSecret;
}
/*!
    Sets \a tokenSecret as the current token secret used to sign
    authenticated calls to the web server.

    \sa tokenSecret(), setTokenCredentials()
*/
void QOAuth1::setTokenSecret(const QString &tokenSecret)
{
    Q_D(QOAuth1);
    if (d->tokenSecret != tokenSecret) {
        d->tokenSecret = tokenSecret;
        Q_EMIT tokenSecretChanged(tokenSecret);
    }
}

/*!
    Returns the pair of QString used to identify and sign
    authenticated requests to the web server.

    \sa setTokenCredentials()
*/
QPair<QString, QString> QOAuth1::tokenCredentials() const
{
    Q_D(const QOAuth1);
    return qMakePair(d->token, d->tokenSecret);
}

/*!
    Sets \a tokenCredentials as the pair of QString used to identify
    and sign authenticated requests to the web server.

    \sa tokenCredentials()
*/
void QOAuth1::setTokenCredentials(const QPair<QString, QString> &tokenCredentials)
{
    setTokenCredentials(tokenCredentials.first, tokenCredentials.second);
}

/*!
    Sets \a token and \a tokenSecret as the pair of QString used to
    identify and sign authenticated requests to the web server.
    Once the client receives and stores the token credentials, it can
    proceed to access protected resources on behalf of the resource
    owner by making authenticated requests using the client
    credentials together with the token credentials received.

    \sa tokenCredentials()
*/
void QOAuth1::setTokenCredentials(const QString &token, const QString &tokenSecret)
{
    setToken(token);
    setTokenSecret(tokenSecret);
}

/*!
    Returns the url used to request temporary credentials to
    start the authentication process.

    \sa setTemporaryCredentialsUrl()
*/
QUrl QOAuth1::temporaryCredentialsUrl() const
{
    Q_D(const QOAuth1);
    return d->temporaryCredentialsUrl;
}

/*!
    Sets \a url as the URL to request temporary credentials to
    start the authentication process.

    \sa temporaryCredentialsUrl()
*/
void QOAuth1::setTemporaryCredentialsUrl(const QUrl &url)
{
    Q_D(QOAuth1);
    if (d->temporaryCredentialsUrl != url) {
        d->temporaryCredentialsUrl = url;
        Q_EMIT temporaryCredentialsUrlChanged(url);
    }
}

/*!
    Returns the url used to request token credentials to continue
    the authentication process.

    \sa setTokenCredentialsUrl()
*/
QUrl QOAuth1::tokenCredentialsUrl() const
{
    Q_D(const QOAuth1);
    return d->tokenCredentialsUrl;
}

/*!
    Sets \a url as the URL to request the token credentials to
    continue the authentication process.

    \sa tokenCredentialsUrl()
*/
void QOAuth1::setTokenCredentialsUrl(const QUrl &url)
{
    Q_D(QOAuth1);
    if (d->tokenCredentialsUrl != url) {
        d->tokenCredentialsUrl = url;
        Q_EMIT tokenCredentialsUrlChanged(url);
    }
}

/*!
    Returns the method used to sign the request to the web server.

    \sa setSignatureMethod()
*/
QOAuth1::SignatureMethod QOAuth1::signatureMethod() const
{
    Q_D(const QOAuth1);
    return d->signatureMethod;
}

/*!
    Sets \a value as the method used to sign requests to the web
    server.

    \sa signatureMethod()
*/
void QOAuth1::setSignatureMethod(QOAuth1::SignatureMethod value)
{
    Q_D(QOAuth1);
    if (d->signatureMethod != value) {
        d->signatureMethod = value;
        Q_EMIT signatureMethodChanged(value);
    }
}

/*!
    Sends an authenticated HEAD request and returns a new
    QNetworkReply. The \a url and \a parameters are used to create
    the request.

    \b {See also}: \l {https://tools.ietf.org/html/rfc2616#section-9.4}
    {Hypertext Transfer Protocol -- HTTP/1.1: HEAD}
*/
QNetworkReply *QOAuth1::head(const QUrl &url, const QVariantMap &parameters)
{
    Q_D(QOAuth1);
    if (!d->networkAccessManager()) {
        qCWarning(d->loggingCategory, "QNetworkAccessManager not available");
        return nullptr;
    }
    QNetworkRequest request(url);
    setup(&request, parameters, QNetworkAccessManager::HeadOperation);
    return d->networkAccessManager()->head(request);
}

/*!
    Sends an authenticated GET request and returns a new
    QNetworkReply. The \a url and \a parameters are used to create
    the request.

    \b {See also}: \l {https://tools.ietf.org/html/rfc2616#section-9.3}
    {Hypertext Transfer Protocol -- HTTP/1.1: GET}
*/
QNetworkReply *QOAuth1::get(const QUrl &url, const QVariantMap &parameters)
{
    Q_D(QOAuth1);
    if (!d->networkAccessManager()) {
        qCWarning(d->loggingCategory, "QNetworkAccessManager not available");
        return nullptr;
    }
    QNetworkRequest request(url);
    setup(&request, parameters, QNetworkAccessManager::GetOperation);
    QNetworkReply *reply = d->networkAccessManager()->get(request);
    connect(reply, &QNetworkReply::finished, [this, reply]() { emit finished(reply); });
    return reply;
}

/*!
    Sends an authenticated POST request and returns a new
    QNetworkReply. The \a url and \a parameters are used to create
    the request.

    \b {See also}: \l {https://tools.ietf.org/html/rfc2616#section-9.5}
    {Hypertext Transfer Protocol -- HTTP/1.1: POST}
*/
QNetworkReply *QOAuth1::post(const QUrl &url, const QVariantMap &parameters)
{
    Q_D(QOAuth1);
    if (!d->networkAccessManager()) {
        qCWarning(d->loggingCategory, "QNetworkAccessManager not available");
        return nullptr;
    }
    QNetworkRequest request(url);
    setup(&request, parameters, QNetworkAccessManager::PostOperation);
    d->addContentTypeHeaders(&request);

    const QByteArray data = d->convertParameters(parameters);
    QNetworkReply *reply = d->networkAccessManager()->post(request, data);
    connect(reply, &QNetworkReply::finished, [this, reply]() { emit finished(reply); });
    return reply;
}

/*!
    Sends an authenticated PUT request and returns a new
    QNetworkReply. The \a url and \a parameters are used to create
    the request.

    \b {See also}: \l {https://tools.ietf.org/html/rfc2616#section-9.6}
    {Hypertext Transfer Protocol -- HTTP/1.1: PUT}
*/
QNetworkReply *QOAuth1::put(const QUrl &url, const QVariantMap &parameters)
{
    Q_D(QOAuth1);
    if (!d->networkAccessManager()) {
        qCWarning(d->loggingCategory, "QNetworkAccessManager not available");
        return nullptr;
    }
    QNetworkRequest request(url);
    setup(&request, parameters, QNetworkAccessManager::PutOperation);
    d->addContentTypeHeaders(&request);

    const QByteArray data = d->convertParameters(parameters);
    QNetworkReply *reply = d->networkAccessManager()->put(request, data);
    connect(reply, &QNetworkReply::finished, std::bind(&QAbstractOAuth::finished, this, reply));
    return reply;
}

/*!
    Sends an authenticated DELETE request and returns a new
    QNetworkReply. The \a url and \a parameters are used to create
    the request.

    \b {See also}: \l {https://tools.ietf.org/html/rfc2616#section-9.7}
    {Hypertext Transfer Protocol -- HTTP/1.1: DELETE}
*/
QNetworkReply *QOAuth1::deleteResource(const QUrl &url, const QVariantMap &parameters)
{
    Q_D(QOAuth1);
    if (!d->networkAccessManager()) {
        qCWarning(d->loggingCategory, "QNetworkAccessManager not available");
        return nullptr;
    }
    QNetworkRequest request(url);
    setup(&request, parameters, QNetworkAccessManager::DeleteOperation);
    QNetworkReply *reply = d->networkAccessManager()->deleteResource(request);
    connect(reply, &QNetworkReply::finished, [this, reply]() { emit finished(reply); });
    return reply;
}

/*!
    Starts the a request for temporary credentials using the request
    method \a operation. The request URL is \a url and the
    \a parameters shall encoded and sent during the request.

    \b {See also}: \l {https://tools.ietf.org/html/rfc5849#section-2.1}
    {The OAuth 1.0 Protocol: Temporary Credentials}
*/
QNetworkReply *QOAuth1::requestTemporaryCredentials(QNetworkAccessManager::Operation operation,
                                                    const QUrl &url,
                                                    const QVariantMap &parameters)
{
    Q_D(QOAuth1);
    d->token.clear();
    d->tokenSecret.clear();
    QVariantMap allParameters(parameters);
    allParameters.insert(Key::oauthCallback, callback());
    return d->requestToken(operation, url, qMakePair(d->token, d->tokenSecret), allParameters);
}

/*!
    Starts a request for token credentials using the request
    method \a operation. The request URL is \a url and the
    \a parameters shall be encoded and sent during the
    request. The \a temporaryToken pair of string is used to identify
    and sign the request.

    \b {See also}: \l {https://tools.ietf.org/html/rfc5849#section-2.3}
    {The OAuth 1.0 Protocol: Token Credentials}
*/
QNetworkReply *QOAuth1::requestTokenCredentials(QNetworkAccessManager::Operation operation,
                                                const QUrl &url,
                                                const QPair<QString, QString> &temporaryToken,
                                                const QVariantMap &parameters)
{
    Q_D(QOAuth1);
    d->tokenRequested = true;
    return d->requestToken(operation, url, temporaryToken, parameters);
}

/*!
    Signs the \a request using \a signingParameters and \a operation.

    \overload
*/
void QOAuth1::setup(QNetworkRequest *request,
                    const QVariantMap &signingParameters,
                    QNetworkAccessManager::Operation operation)
{
    Q_D(const QOAuth1);

    auto oauthParams = d->createOAuthBaseParams();

    // Add signature parameter
    {
        QMultiMap<QString, QVariant> oauthParamsCopy(oauthParams);
        const auto parameters = oauthParamsCopy.unite(signingParameters);
        const auto signature = d->generateSignature(parameters, request->url(), operation);
        oauthParams.insert(Key::oauthSignature, signature);
    }

    if (operation == QNetworkAccessManager::GetOperation) {
        if (signingParameters.size()) {
            QUrl url = request->url();
            QUrlQuery query = QUrlQuery(url.query());
            for (auto it = signingParameters.begin(), end = signingParameters.end(); it != end;
                 ++it)
                query.addQueryItem(it.key(), it.value().toString());
            url.setQuery(query);
            request->setUrl(url);
        }
    }

    request->setRawHeader("Authorization", generateAuthorizationHeader(oauthParams));

    if (operation == QNetworkAccessManager::PostOperation
            || operation == QNetworkAccessManager::PutOperation)
        request->setHeader(QNetworkRequest::ContentTypeHeader,
                           QStringLiteral("application/x-www-form-urlencoded"));
}

/*!
    \since 5.13

    Signs the \a request using \a signingParameters and \a operationVerb.

    \overload
*/
void QOAuth1::setup(QNetworkRequest *request, const QVariantMap &signingParameters, const QByteArray &operationVerb)
{
    Q_D(const QOAuth1);

    auto oauthParams = d->createOAuthBaseParams();

    // Add signature parameter
    {
        QMultiMap<QString, QVariant> oauthParamsCopy(oauthParams);
        const auto parameters = oauthParamsCopy.unite(signingParameters);
        const auto signature = d->generateSignature(parameters, request->url(), operationVerb);
        oauthParams.insert(Key::oauthSignature, signature);
    }

    request->setRawHeader("Authorization", generateAuthorizationHeader(oauthParams));
}

/*!
    Generates a nonce.

    \b {See also}: \l {https://tools.ietf.org/html/rfc5849#section-3.3}
    {The OAuth 1.0 Protocol: Nonce and Timestamp}
*/
QByteArray QOAuth1::nonce()
{
    return QAbstractOAuth::generateRandomString(8);
}

/*!
    Generates an authorization header using \a oauthParams.

    \b {See also}: \l {https://tools.ietf.org/html/rfc5849#section-3.5.1}
    {The OAuth 1.0 Protocol: Authorization Header}
*/
QByteArray QOAuth1::generateAuthorizationHeader(const QVariantMap &oauthParams)
{
    // TODO Add realm parameter support
    bool first = true;
    QString ret(QStringLiteral("OAuth "));
    QVariantMap headers(oauthParams);
    for (auto it = headers.begin(), end = headers.end(); it != end; ++it) {
        if (first)
            first = false;
        else
            ret += QLatin1String(",");
        ret += it.key() +
               QLatin1String("=\"") +
               QString::fromUtf8(QUrl::toPercentEncoding(it.value().toString())) +
               QLatin1Char('\"');
    }
    return ret.toUtf8();
}

/*!
    Starts the Redirection-Based Authorization flow.

    \note For an out-of-band reply handler, a verifier string is
    received after the call to this function; pass that to
    continueGrantWithVerifier() to continue the grant process.

    \sa continueGrantWithVerifier()

    \b {See also}: \l {https://tools.ietf.org/html/rfc5849#section-2}
    {The OAuth 1.0 Protocol: Redirection-Based Authorization}
*/
void QOAuth1::grant()
{
    Q_D(QOAuth1);
    using Key = QOAuth1Private::OAuth1KeyString;

    if (d->temporaryCredentialsUrl.isEmpty()) {
        qCWarning(d->loggingCategory, "requestTokenUrl is empty");
        return;
    }
    if (d->tokenCredentialsUrl.isEmpty()) {
        qCWarning(d->loggingCategory, "authorizationGrantUrl is empty");
        return;
    }
    if (!d->token.isEmpty() && status() == Status::Granted) {
        qCWarning(d->loggingCategory, "Already authenticated");
        return;
    }

    QMetaObject::Connection connection;
    connection = connect(this, &QAbstractOAuth::statusChanged, [&](Status status) {
        Q_D(QOAuth1);

        if (status == Status::TemporaryCredentialsReceived) {
            if (d->authorizationUrl.isEmpty()) {
                // try upgrading token without verifier
                auto reply = requestTokenCredentials(QNetworkAccessManager::PostOperation,
                                                     d->tokenCredentialsUrl,
                                                     qMakePair(d->token, d->tokenSecret));
                connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
            } else {
                QVariantMap parameters;
                parameters.insert(Key::oauthToken, d->token);
                if (d->modifyParametersFunction)
                    d->modifyParametersFunction(Stage::RequestingAuthorization, &parameters);

                // https://tools.ietf.org/html/rfc5849#section-2.2
                resourceOwnerAuthorization(d->authorizationUrl, parameters);
            }
        } else if (status == Status::NotAuthenticated) {
            // Inherit class called QAbstractOAuth::setStatus(Status::NotAuthenticated);
            setTokenCredentials(QString(), QString());
            disconnect(connection);
        }
    });

    auto httpReplyHandler = qobject_cast<QOAuthHttpServerReplyHandler*>(replyHandler());
    if (httpReplyHandler) {
        connect(httpReplyHandler, &QOAuthHttpServerReplyHandler::callbackReceived, [&](
                const QVariantMap &values) {
            QString verifier = values.value(Key::oauthVerifier).toString();
            if (verifier.isEmpty()) {
                qCWarning(d->loggingCategory, "%s not found in the callback",
                          qPrintable(Key::oauthVerifier));
                return;
            }
            continueGrantWithVerifier(verifier);
        });
    }

    // requesting temporary credentials
    auto reply = requestTemporaryCredentials(QNetworkAccessManager::PostOperation,
                                             d->temporaryCredentialsUrl);
    connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
}

/*!
    Continues the Redirection-Based Authorization flow using
    \a verifier. Call this function when using an Out-of-band reply
    handler to supply the verifier provided by the web server.
*/
void QOAuth1::continueGrantWithVerifier(const QString &verifier)
{
    // https://tools.ietf.org/html/rfc5849#section-2.3
    Q_D(QOAuth1);

    QVariantMap parameters;
    parameters.insert(Key::oauthVerifier, verifier);
    auto reply = requestTokenCredentials(QNetworkAccessManager::PostOperation,
                                         d->tokenCredentialsUrl,
                                         qMakePair(d->token, d->tokenSecret),
                                         parameters);
    connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
}

QT_END_NAMESPACE

#endif // QT_NO_HTTP
