Update
This commit is contained in:
parent
21ce26a3d8
commit
98426ae24a
21 changed files with 2471 additions and 1 deletions
|
@ -1,4 +1,5 @@
|
||||||
#About the oauth library for BlackBerry 10
|
About the oauth library for BlackBerry 10
|
||||||
|
==========================================
|
||||||
This is a OAuth library built for the Cascades development framework for BlackBerry 10. It is a fork and BlackBerry specific implementation of the KQOauth library that can be found here http://www.gitorious.org/kqoauth under the LGPL license.
|
This is a OAuth library built for the Cascades development framework for BlackBerry 10. It is a fork and BlackBerry specific implementation of the KQOauth library that can be found here http://www.gitorious.org/kqoauth under the LGPL license.
|
||||||
|
|
||||||
This library supports both OAuth1 and OAuth2 authorization flow and authorized requests.
|
This library supports both OAuth1 and OAuth2 authorization flow and authorized requests.
|
56
oauth/kqoauth2request.cpp
Normal file
56
oauth/kqoauth2request.cpp
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
/**
|
||||||
|
* KQOAuth - An OAuth authentication library for Qt.
|
||||||
|
*
|
||||||
|
* Author: Johan Paul (johan.paul@d-pointer.com)
|
||||||
|
* http://www.d-pointer.com
|
||||||
|
*
|
||||||
|
* KQOAuth is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* KQOAuth 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 Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with KQOAuth. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#include <QtDebug>
|
||||||
|
|
||||||
|
#include "kqoauth2request_p.h"
|
||||||
|
#include "kqoauth2request.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Private d_ptr implementations.
|
||||||
|
*/
|
||||||
|
KQOAuth2Request_Private::KQOAuth2Request_Private()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
KQOAuth2Request_Private::~KQOAuth2Request_Private()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Public implementations.
|
||||||
|
*/
|
||||||
|
KQOAuth2Request::KQOAuth2Request(QObject *parent) :
|
||||||
|
KQOAuthRequest(parent),
|
||||||
|
d_ptr(new KQOAuth2Request_Private)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KQOAuth2Request::isValid() const {
|
||||||
|
// Access token must always be retrieved using the POST HTTP method.
|
||||||
|
// And then check the validity of the XAuth request.
|
||||||
|
// Provided by the base class as a protected method for us.
|
||||||
|
return validateOauth2Request();
|
||||||
|
}
|
||||||
|
|
||||||
|
void KQOAuth2Request::initRequest(KQOAuthRequest::RequestType type, const QUrl &requestEndpoint) {
|
||||||
|
KQOAuthRequest::initRequest(type,requestEndpoint);
|
||||||
|
setRequestOAuthMethod(KQOAuthRequest::OAUTH2);
|
||||||
|
}
|
45
oauth/kqoauth2request.h
Normal file
45
oauth/kqoauth2request.h
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
/**
|
||||||
|
* KQOAuth - An OAuth authentication library for Qt.
|
||||||
|
*
|
||||||
|
* Author: Johan Paul (johan.paul@d-pointer.com)
|
||||||
|
* http://www.d-pointer.com
|
||||||
|
*
|
||||||
|
* KQOAuth is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* KQOAuth 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 Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with KQOAuth. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#ifndef KQOAUTH2REQUEST_H
|
||||||
|
#define KQOAUTH2REQUEST_H
|
||||||
|
|
||||||
|
#include "kqoauthrequest.h"
|
||||||
|
#include "kqoauthrequest_1.h"
|
||||||
|
|
||||||
|
class KQOAuth2Request_Private;
|
||||||
|
class KQOAUTH_EXPORT KQOAuth2Request : public KQOAuthRequest
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
KQOAuth2Request(QObject *parent = 0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* These methods can be overridden in child classes which are different types of
|
||||||
|
* OAuth requests.
|
||||||
|
*/
|
||||||
|
// Validate the request of this type.
|
||||||
|
bool isValid() const;
|
||||||
|
void initRequest(KQOAuthRequest::RequestType type, const QUrl &requestEndpoint);
|
||||||
|
|
||||||
|
private:
|
||||||
|
KQOAuth2Request_Private * const d_ptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // KQOAUTHREQUEST_XAUTH_H
|
14
oauth/kqoauth2request_p.h
Normal file
14
oauth/kqoauth2request_p.h
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
#ifndef KQOAUTH2REQUEST_P_H
|
||||||
|
#define KQOAUTH2REQUEST_P_H
|
||||||
|
|
||||||
|
#include "kqoauthglobals.h"
|
||||||
|
|
||||||
|
class KQOAuthRequest;
|
||||||
|
class KQOAUTH_EXPORT KQOAuth2Request_Private
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
KQOAuth2Request_Private();
|
||||||
|
~KQOAuth2Request_Private();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // KQOAUTHREQUEST_XAUTH_P_H
|
110
oauth/kqoauthauthreplyserver.cpp
Normal file
110
oauth/kqoauthauthreplyserver.cpp
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
/**
|
||||||
|
* KQOAuth - An OAuth authentication library for Qt.
|
||||||
|
*
|
||||||
|
* Author: Johan Paul (johan.paul@d-pointer.com)
|
||||||
|
* http://www.d-pointer.com
|
||||||
|
*
|
||||||
|
* KQOAuth is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* KQOAuth 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 Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with KQOAuth. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#include <QTcpSocket>
|
||||||
|
#include <QStringList>
|
||||||
|
#include <QUrl>
|
||||||
|
|
||||||
|
#include "kqoauthauthreplyserver.h"
|
||||||
|
#include "kqoauthauthreplyserver_p.h"
|
||||||
|
|
||||||
|
KQOAuthAuthReplyServerPrivate::KQOAuthAuthReplyServerPrivate(KQOAuthAuthReplyServer *parent):
|
||||||
|
q_ptr(parent)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
KQOAuthAuthReplyServerPrivate::~KQOAuthAuthReplyServerPrivate()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void KQOAuthAuthReplyServerPrivate::onIncomingConnection() {
|
||||||
|
Q_Q(KQOAuthAuthReplyServer);
|
||||||
|
|
||||||
|
socket = q->nextPendingConnection();
|
||||||
|
connect(socket, SIGNAL(readyRead()),
|
||||||
|
this, SLOT(onBytesReady()), Qt::UniqueConnection);
|
||||||
|
}
|
||||||
|
|
||||||
|
void KQOAuthAuthReplyServerPrivate::onBytesReady() {
|
||||||
|
Q_Q(KQOAuthAuthReplyServer);
|
||||||
|
|
||||||
|
QByteArray reply;
|
||||||
|
QByteArray content;
|
||||||
|
content.append("<HTML><h1>Account authorized, go ahead back to the tumblr app and start your experience!</h1></HTML>");
|
||||||
|
|
||||||
|
reply.append("HTTP/1.0 200 OK \r\n");
|
||||||
|
reply.append("Content-Type: text/html; charset=\"utf-8\"\r\n");
|
||||||
|
reply.append(QString("Content-Length: %1\r\n").arg(content.size()));
|
||||||
|
reply.append("\r\n");
|
||||||
|
reply.append(content);
|
||||||
|
socket->write(reply);
|
||||||
|
|
||||||
|
QByteArray data = socket->readAll();
|
||||||
|
QMultiMap<QString, QString> queryParams = parseQueryParams(&data);
|
||||||
|
|
||||||
|
socket->disconnectFromHost();
|
||||||
|
q->close();
|
||||||
|
emit q->verificationReceived(queryParams);
|
||||||
|
}
|
||||||
|
|
||||||
|
QMultiMap<QString, QString> KQOAuthAuthReplyServerPrivate::parseQueryParams(QByteArray *data) {
|
||||||
|
QString splitGetLine = QString(*data).split("\r\n").first(); // Retrieve the first line with query params.
|
||||||
|
splitGetLine.remove("GET "); // Clean the line from GET
|
||||||
|
splitGetLine.remove("HTTP/1.1"); // From HTTP
|
||||||
|
splitGetLine.remove("\r\n"); // And from rest.
|
||||||
|
splitGetLine.prepend("http://localhost"); // Now, make it a URL
|
||||||
|
|
||||||
|
QUrl getTokenUrl(splitGetLine);
|
||||||
|
QList< QPair<QString, QString> > tokens = getTokenUrl.queryItems(); // Ask QUrl to do our work.
|
||||||
|
|
||||||
|
QMultiMap<QString, QString> queryParams;
|
||||||
|
QPair<QString, QString> tokenPair;
|
||||||
|
foreach (tokenPair, tokens) {
|
||||||
|
queryParams.insert(tokenPair.first.trimmed(), tokenPair.second.trimmed());
|
||||||
|
}
|
||||||
|
|
||||||
|
return queryParams;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
KQOAuthAuthReplyServer::KQOAuthAuthReplyServer(QObject *parent) :
|
||||||
|
QTcpServer(parent),
|
||||||
|
d_ptr( new KQOAuthAuthReplyServerPrivate(this) )
|
||||||
|
{
|
||||||
|
Q_D(KQOAuthAuthReplyServer);
|
||||||
|
|
||||||
|
connect(this, SIGNAL(newConnection()),
|
||||||
|
d, SLOT(onIncomingConnection()));
|
||||||
|
}
|
||||||
|
|
||||||
|
KQOAuthAuthReplyServer::~KQOAuthAuthReplyServer()
|
||||||
|
{
|
||||||
|
delete d_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void KQOAuthAuthReplyServer::setSuccessHtmlFile(QString filePath) {
|
||||||
|
Q_D(KQOAuthAuthReplyServer);
|
||||||
|
d->localFile = filePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
48
oauth/kqoauthauthreplyserver.h
Normal file
48
oauth/kqoauthauthreplyserver.h
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
/**
|
||||||
|
* KQOAuth - An OAuth authentication library for Qt.
|
||||||
|
*
|
||||||
|
* Author: Johan Paul (johan.paul@d-pointer.com)
|
||||||
|
* http://www.d-pointer.com
|
||||||
|
*
|
||||||
|
* KQOAuth is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* KQOAuth 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 Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with KQOAuth. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#ifndef KQOAUTHAUTHREPLYSERVER_H
|
||||||
|
#define KQOAUTHAUTHREPLYSERVER_H
|
||||||
|
|
||||||
|
#include <QTcpServer>
|
||||||
|
|
||||||
|
#include "kqoauthglobals.h"
|
||||||
|
|
||||||
|
class KQOAuthAuthReplyServerPrivate;
|
||||||
|
class KQOAUTH_EXPORT KQOAuthAuthReplyServer : public QTcpServer
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit KQOAuthAuthReplyServer(QObject *parent);
|
||||||
|
~KQOAuthAuthReplyServer();
|
||||||
|
void setSuccessHtmlFile(QString filePath);
|
||||||
|
|
||||||
|
Q_SIGNALS:
|
||||||
|
void verificationReceived(QMultiMap<QString, QString>);
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
KQOAuthAuthReplyServerPrivate * const d_ptr;
|
||||||
|
Q_DECLARE_PRIVATE(KQOAuthAuthReplyServer);
|
||||||
|
Q_DISABLE_COPY(KQOAuthAuthReplyServer);
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // KQOAUTHAUTHREPLYSERVER_H
|
47
oauth/kqoauthauthreplyserver_p.h
Normal file
47
oauth/kqoauthauthreplyserver_p.h
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
/**
|
||||||
|
* KQOAuth - An OAuth authentication library for Qt.
|
||||||
|
*
|
||||||
|
* Author: Johan Paul (johan.paul@d-pointer.com)
|
||||||
|
* http://www.d-pointer.com
|
||||||
|
*
|
||||||
|
* KQOAuth is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* KQOAuth 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 Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with KQOAuth. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
// Note this class shouldn't be copied or used and the implementation might change later.
|
||||||
|
#ifndef KQOAUTHAUTHREPLYSERVER_P_H
|
||||||
|
#define KQOAUTHAUTHREPLYSERVER_P_H
|
||||||
|
|
||||||
|
#include "kqoauthauthreplyserver.h"
|
||||||
|
#include <QMultiMap>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
class KQOAUTH_EXPORT KQOAuthAuthReplyServerPrivate: public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
KQOAuthAuthReplyServerPrivate( KQOAuthAuthReplyServer * parent );
|
||||||
|
~KQOAuthAuthReplyServerPrivate();
|
||||||
|
QMultiMap<QString, QString> parseQueryParams(QByteArray *sdata);
|
||||||
|
|
||||||
|
public Q_SLOTS:
|
||||||
|
void onIncomingConnection();
|
||||||
|
void onBytesReady();
|
||||||
|
|
||||||
|
public:
|
||||||
|
KQOAuthAuthReplyServer * q_ptr;
|
||||||
|
Q_DECLARE_PUBLIC(KQOAuthAuthReplyServer);
|
||||||
|
QTcpSocket *socket;
|
||||||
|
QString localFile;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // KQOAUTHAUTHREPLYSERVER_P_H
|
48
oauth/kqoauthglobals.h
Normal file
48
oauth/kqoauthglobals.h
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
/**
|
||||||
|
* KQOAuth - An OAuth authentication library for Qt.
|
||||||
|
*
|
||||||
|
* Author: Johan Paul (johan.paul@d-pointer.com)
|
||||||
|
* http://www.d-pointer.com
|
||||||
|
*
|
||||||
|
* KQOAuth is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* KQOAuth 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 Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with KQOAuth. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#ifndef KQOAUTHGLOBALS_H
|
||||||
|
#define KQOAUTHGLOBALS_H
|
||||||
|
|
||||||
|
#include <QtCore/qglobal.h>
|
||||||
|
|
||||||
|
#if defined(KQOAUTH)
|
||||||
|
# define KQOAUTH_EXPORT Q_DECL_EXPORT
|
||||||
|
#else
|
||||||
|
# define KQOAUTH_EXPORT Q_DECL_IMPORT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//////////// Static constant definitions ///////////
|
||||||
|
const QString OAUTH_KEY_CONSUMER("oauth_consumer");
|
||||||
|
const QString OAUTH_KEY_CONSUMER_KEY("oauth_consumer_key");
|
||||||
|
const QString OAUTH_KEY_TOKEN("oauth_token");
|
||||||
|
const QString OAUTH_KEY_TOKEN_SECRET("oauth_token_secret");
|
||||||
|
const QString OAUTH_KEY_SIGNATURE_METHOD("oauth_signature_method");
|
||||||
|
const QString OAUTH_KEY_TIMESTAMP("oauth_timestamp");
|
||||||
|
const QString OAUTH_KEY_NONCE("oauth_nonce");
|
||||||
|
const QString OAUTH_KEY_SIGNATURE("oauth_signature");
|
||||||
|
const QString OAUTH_KEY_CALLBACK("oauth_callback");
|
||||||
|
const QString OAUTH_KEY_VERIFIER("oauth_verifier");
|
||||||
|
const QString OAUTH_KEY_VERSION("oauth_version");
|
||||||
|
const QString OAUTH2_KEY_CLIENT_ID("client_id");
|
||||||
|
const QString OAUTH2_KEY_CLIENT_SECRET("client_secret");
|
||||||
|
const QString OAUTH2_KEY_REDIRECT_URI("redirect_uri");
|
||||||
|
const QString OAUTH2_KEY_RESPONSE_TYPE("response_type");
|
||||||
|
|
||||||
|
#endif // KQOAUTHGLOBALS_H
|
677
oauth/kqoauthmanager.cpp
Normal file
677
oauth/kqoauthmanager.cpp
Normal file
|
@ -0,0 +1,677 @@
|
||||||
|
/**
|
||||||
|
* KQOAuth - An OAuth authentication library for Qt.
|
||||||
|
*
|
||||||
|
* Author: Johan Paul (johan.paul@d-pointer.com)
|
||||||
|
* http://www.d-pointer.com
|
||||||
|
*
|
||||||
|
* KQOAuth is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* KQOAuth 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 Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with KQOAuth. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#include <QtCore>
|
||||||
|
|
||||||
|
#include "kqoauthmanager.h"
|
||||||
|
#include "kqoauthmanager_p.h"
|
||||||
|
#include "bps/navigator.h"
|
||||||
|
|
||||||
|
|
||||||
|
////////////// Private d_ptr implementation ////////////////
|
||||||
|
|
||||||
|
KQOAuthManagerPrivate::KQOAuthManagerPrivate(KQOAuthManager *parent) :
|
||||||
|
error(KQOAuthManager::NoError) ,
|
||||||
|
r(0) ,
|
||||||
|
opaqueRequest(new KQOAuthRequest) ,
|
||||||
|
q_ptr(parent) ,
|
||||||
|
callbackServer(new KQOAuthAuthReplyServer(parent)) ,
|
||||||
|
isVerified(false) ,
|
||||||
|
isAuthorized(false) ,
|
||||||
|
autoAuth(false),
|
||||||
|
networkManager(new QNetworkAccessManager),
|
||||||
|
managerUserSet(false)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
KQOAuthManagerPrivate::~KQOAuthManagerPrivate() {
|
||||||
|
delete opaqueRequest;
|
||||||
|
opaqueRequest = 0;
|
||||||
|
|
||||||
|
if (!managerUserSet) {
|
||||||
|
delete networkManager;
|
||||||
|
networkManager = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QList< QPair<QString, QString> > KQOAuthManagerPrivate::createQueryParams(const KQOAuthParameters &requestParams) {
|
||||||
|
QList<QString> requestKeys = requestParams.keys();
|
||||||
|
QList<QString> requestValues = requestParams.values();
|
||||||
|
|
||||||
|
QList< QPair<QString, QString> > result;
|
||||||
|
for(int i=0; i<requestKeys.size(); i++) {
|
||||||
|
result.append( qMakePair(requestKeys.at(i),
|
||||||
|
requestValues.at(i))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
QMultiMap<QString, QString> KQOAuthManagerPrivate::createTokensFromResponse(QByteArray reply) {
|
||||||
|
QMultiMap<QString, QString> result;
|
||||||
|
QString replyString(reply);
|
||||||
|
|
||||||
|
QStringList parameterPairs = replyString.split('&', QString::SkipEmptyParts);
|
||||||
|
foreach (const QString ¶meterPair, parameterPairs) {
|
||||||
|
QStringList parameter = parameterPair.split('=');
|
||||||
|
result.insert(parameter.value(0), parameter.value(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KQOAuthManagerPrivate::setSuccessfulRequestToken(const QMultiMap<QString, QString> &request) {
|
||||||
|
if (currentRequestType == KQOAuthRequest::TemporaryCredentials) {
|
||||||
|
hasTemporaryToken = (!QString(request.value("oauth_token")).isEmpty() && !QString(request.value("oauth_token_secret")).isEmpty());
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasTemporaryToken) {
|
||||||
|
requestToken = QUrl::fromPercentEncoding( QString(request.value("oauth_token")).toLocal8Bit() );
|
||||||
|
requestTokenSecret = QUrl::fromPercentEncoding( QString(request.value("oauth_token_secret")).toLocal8Bit() );
|
||||||
|
}
|
||||||
|
|
||||||
|
return hasTemporaryToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KQOAuthManagerPrivate::setSuccessfulAuthorized(const QMultiMap<QString, QString> &request ) {
|
||||||
|
if (currentRequestType == KQOAuthRequest::AccessToken) {
|
||||||
|
isAuthorized = (!QString(request.value("oauth_token")).isEmpty() && !QString(request.value("oauth_token_secret")).isEmpty());
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isAuthorized) {
|
||||||
|
requestToken = QUrl::fromPercentEncoding( QString(request.value("oauth_token")).toLocal8Bit() );
|
||||||
|
requestTokenSecret = QUrl::fromPercentEncoding( QString(request.value("oauth_token_secret")).toLocal8Bit() );
|
||||||
|
}
|
||||||
|
|
||||||
|
return isAuthorized;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KQOAuthManagerPrivate::emitTokens() {
|
||||||
|
Q_Q(KQOAuthManager);
|
||||||
|
|
||||||
|
if (this->requestToken.isEmpty() || this->requestTokenSecret.isEmpty()) {
|
||||||
|
error = KQOAuthManager::RequestUnauthorized;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentRequestType == KQOAuthRequest::TemporaryCredentials) {
|
||||||
|
// Signal that we are ready to use the protected resources.
|
||||||
|
emit q->temporaryTokenReceived(this->requestToken, this->requestTokenSecret);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentRequestType == KQOAuthRequest::AccessToken) {
|
||||||
|
// Signal that we are ready to use the protected resources.
|
||||||
|
emit q->accessTokenReceived(this->requestToken, this->requestTokenSecret);
|
||||||
|
}
|
||||||
|
|
||||||
|
emit q->receivedToken(this->requestToken, this->requestTokenSecret);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KQOAuthManagerPrivate::setupCallbackServer() {
|
||||||
|
return callbackServer->listen();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/////////////// Public implementation ////////////////
|
||||||
|
|
||||||
|
KQOAuthManager::KQOAuthManager(QObject *parent) :
|
||||||
|
QObject(parent) ,
|
||||||
|
d_ptr(new KQOAuthManagerPrivate(this))
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
KQOAuthManager::~KQOAuthManager()
|
||||||
|
{
|
||||||
|
delete d_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KQOAuthManager::executeRequest(KQOAuthRequest *request) {
|
||||||
|
Q_D(KQOAuthManager);
|
||||||
|
|
||||||
|
d->r = request;
|
||||||
|
|
||||||
|
if (request == 0) {
|
||||||
|
qWarning() << "Request is NULL. Cannot proceed.";
|
||||||
|
d->error = KQOAuthManager::RequestError;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!request->requestEndpoint().isValid()) {
|
||||||
|
qWarning() << "Request endpoint URL is not valid. Cannot proceed.";
|
||||||
|
d->error = KQOAuthManager::RequestEndpointError;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!request->isValid()) {
|
||||||
|
qWarning() << "Request is not valid. Cannot proceed.";
|
||||||
|
d->error = KQOAuthManager::RequestValidationError;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
d->currentRequestType = request->requestType();
|
||||||
|
|
||||||
|
QNetworkRequest networkRequest;
|
||||||
|
networkRequest.setUrl( request->requestEndpoint() );
|
||||||
|
|
||||||
|
if (d->autoAuth && d->currentRequestType == KQOAuthRequest::TemporaryCredentials) {
|
||||||
|
d->setupCallbackServer();
|
||||||
|
connect(d->callbackServer, SIGNAL(verificationReceived(QMultiMap<QString, QString>)),
|
||||||
|
this, SLOT( onVerificationReceived(QMultiMap<QString, QString>)));
|
||||||
|
|
||||||
|
QString serverString = "http://localhost:";
|
||||||
|
serverString.append(QString::number(d->callbackServer->serverPort()));
|
||||||
|
request->setCallbackUrl(QUrl(serverString));
|
||||||
|
qDebug() << serverString;
|
||||||
|
}
|
||||||
|
|
||||||
|
// And now fill the request with "Authorization" header data.
|
||||||
|
QList<QByteArray> requestHeaders = request->requestParameters();
|
||||||
|
QByteArray authHeader;
|
||||||
|
|
||||||
|
bool first = true;
|
||||||
|
foreach (const QByteArray header, requestHeaders) {
|
||||||
|
if (!first) {
|
||||||
|
authHeader.append(", ");
|
||||||
|
} else {
|
||||||
|
authHeader.append("OAuth ");
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
authHeader.append(header);
|
||||||
|
}
|
||||||
|
networkRequest.setRawHeader("Authorization", authHeader);
|
||||||
|
|
||||||
|
connect(d->networkManager, SIGNAL(finished(QNetworkReply *)),
|
||||||
|
this, SLOT(onRequestReplyReceived(QNetworkReply *)), Qt::UniqueConnection);
|
||||||
|
disconnect(d->networkManager, SIGNAL(finished(QNetworkReply *)),
|
||||||
|
this, SLOT(onAuthorizedRequestReplyReceived(QNetworkReply *)));
|
||||||
|
|
||||||
|
if (request->httpMethod() == KQOAuthRequest::GET) {
|
||||||
|
// Get the requested additional params as a list of pairs we can give QUrl
|
||||||
|
QList< QPair<QString, QString> > urlParams = d->createQueryParams(request->additionalParameters());
|
||||||
|
|
||||||
|
// Take the original URL and append the query params to it.
|
||||||
|
QUrl urlWithParams = networkRequest.url();
|
||||||
|
urlWithParams.setQueryItems(urlParams);
|
||||||
|
networkRequest.setUrl(urlWithParams);
|
||||||
|
|
||||||
|
// Submit the request including the params.
|
||||||
|
QNetworkReply *reply = d->networkManager->get(networkRequest);
|
||||||
|
connect(reply, SIGNAL(error(QNetworkReply::NetworkError)),
|
||||||
|
this, SLOT(slotError(QNetworkReply::NetworkError)));
|
||||||
|
|
||||||
|
} else if (request->httpMethod() == KQOAuthRequest::POST) {
|
||||||
|
|
||||||
|
networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, request->contentType());
|
||||||
|
|
||||||
|
qDebug() << networkRequest.rawHeaderList();
|
||||||
|
qDebug() << networkRequest.rawHeader("Authorization");
|
||||||
|
qDebug() << networkRequest.rawHeader("Content-Type");
|
||||||
|
|
||||||
|
QNetworkReply *reply;
|
||||||
|
if (request->contentType() == "application/x-www-form-urlencoded") {
|
||||||
|
reply = d->networkManager->post(networkRequest, request->requestBody());
|
||||||
|
} else {
|
||||||
|
reply = d->networkManager->post(networkRequest, request->rawData());
|
||||||
|
}
|
||||||
|
|
||||||
|
connect(reply, SIGNAL(error(QNetworkReply::NetworkError)),
|
||||||
|
this, SLOT(slotError(QNetworkReply::NetworkError)));
|
||||||
|
}
|
||||||
|
|
||||||
|
d->r->requestTimerStart();
|
||||||
|
}
|
||||||
|
|
||||||
|
void KQOAuthManager::executeAuthorizedRequest(KQOAuthRequest *request, int id) {
|
||||||
|
Q_D(KQOAuthManager);
|
||||||
|
|
||||||
|
d->r = request;
|
||||||
|
|
||||||
|
if (request == 0) {
|
||||||
|
qWarning() << "Request is NULL. Cannot proceed.";
|
||||||
|
d->error = KQOAuthManager::RequestError;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!request->requestEndpoint().isValid()) {
|
||||||
|
qWarning() << "Request endpoint URL is not valid. Cannot proceed.";
|
||||||
|
d->error = KQOAuthManager::RequestEndpointError;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!request->isValid()) {
|
||||||
|
qWarning() << "Request is not valid. Cannot proceed.";
|
||||||
|
d->error = KQOAuthManager::RequestValidationError;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
d->currentRequestType = request->requestType();
|
||||||
|
|
||||||
|
QNetworkRequest networkRequest;
|
||||||
|
networkRequest.setUrl( request->requestEndpoint() );
|
||||||
|
|
||||||
|
if ( d->currentRequestType != KQOAuthRequest::AuthorizedRequest){
|
||||||
|
qWarning() << "Not Authorized Request. Cannot proceed";
|
||||||
|
d->error = KQOAuthManager::RequestError;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(request->oauthMethod() != KQOAuthRequest::OAUTH2) {
|
||||||
|
// And now fill the request with "Authorization" header data.
|
||||||
|
QList<QByteArray> requestHeaders = request->requestParameters();
|
||||||
|
QByteArray authHeader;
|
||||||
|
|
||||||
|
bool first = true;
|
||||||
|
foreach (const QByteArray header, requestHeaders) {
|
||||||
|
if (!first) {
|
||||||
|
authHeader.append(", ");
|
||||||
|
} else {
|
||||||
|
authHeader.append("OAuth ");
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
authHeader.append(header);
|
||||||
|
}
|
||||||
|
networkRequest.setRawHeader("Authorization", authHeader);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
disconnect(d->networkManager, SIGNAL(finished(QNetworkReply *)),
|
||||||
|
this, SLOT(onRequestReplyReceived(QNetworkReply *)));
|
||||||
|
connect(d->networkManager, SIGNAL(finished(QNetworkReply *)),
|
||||||
|
this, SLOT(onAuthorizedRequestReplyReceived(QNetworkReply*)), Qt::UniqueConnection);
|
||||||
|
|
||||||
|
if (request->httpMethod() == KQOAuthRequest::GET) {
|
||||||
|
// Get the requested additional params as a list of pairs we can give QUrl
|
||||||
|
QList< QPair<QString, QString> > urlParams = d->createQueryParams(request->additionalParameters());
|
||||||
|
|
||||||
|
// Take the original URL and append the query params to it.
|
||||||
|
QUrl urlWithParams = networkRequest.url();
|
||||||
|
urlWithParams.setQueryItems(urlParams);
|
||||||
|
networkRequest.setUrl(urlWithParams);
|
||||||
|
|
||||||
|
// Submit the request including the params.
|
||||||
|
QNetworkReply *reply = d->networkManager->get(networkRequest);
|
||||||
|
connect(reply, SIGNAL(error(QNetworkReply::NetworkError)),
|
||||||
|
this, SLOT(slotError(QNetworkReply::NetworkError)));
|
||||||
|
|
||||||
|
} else if (request->httpMethod() == KQOAuthRequest::POST) {
|
||||||
|
|
||||||
|
networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, request->contentType());
|
||||||
|
|
||||||
|
/*
|
||||||
|
qDebug() << networkRequest.rawHeaderList();
|
||||||
|
qDebug() << networkRequest.rawHeader("Authorization");
|
||||||
|
qDebug() << networkRequest.rawHeader("Content-Type");
|
||||||
|
*/
|
||||||
|
QNetworkReply *reply;
|
||||||
|
if (request->contentType() == "application/x-www-form-urlencoded") {
|
||||||
|
reply = d->networkManager->post(networkRequest, request->requestBody());
|
||||||
|
} else {
|
||||||
|
reply = d->networkManager->post(networkRequest, request->rawData());
|
||||||
|
}
|
||||||
|
|
||||||
|
d->requestIds.insert(reply, id);
|
||||||
|
|
||||||
|
connect(reply, SIGNAL(error(QNetworkReply::NetworkError)),
|
||||||
|
this, SLOT(slotError(QNetworkReply::NetworkError)));
|
||||||
|
}
|
||||||
|
|
||||||
|
d->r->requestTimerStart();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void KQOAuthManager::setHandleUserAuthorization(bool set) {
|
||||||
|
Q_D(KQOAuthManager);
|
||||||
|
|
||||||
|
d->autoAuth = set;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KQOAuthManager::hasTemporaryToken() {
|
||||||
|
Q_D(KQOAuthManager);
|
||||||
|
|
||||||
|
return d->hasTemporaryToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KQOAuthManager::isVerified() {
|
||||||
|
Q_D(KQOAuthManager);
|
||||||
|
|
||||||
|
return d->isVerified;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KQOAuthManager::isAuthorized() {
|
||||||
|
Q_D(KQOAuthManager);
|
||||||
|
|
||||||
|
return d->isAuthorized;
|
||||||
|
}
|
||||||
|
|
||||||
|
KQOAuthManager::KQOAuthError KQOAuthManager::lastError() {
|
||||||
|
Q_D(KQOAuthManager);
|
||||||
|
|
||||||
|
return d->error;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KQOAuthManager::setNetworkManager(QNetworkAccessManager *manager) {
|
||||||
|
Q_D(KQOAuthManager);
|
||||||
|
|
||||||
|
if (manager == 0) {
|
||||||
|
d->error = KQOAuthManager::ManagerError;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!d->managerUserSet) {
|
||||||
|
delete d->networkManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
d->managerUserSet = true;
|
||||||
|
d->networkManager = manager;
|
||||||
|
}
|
||||||
|
|
||||||
|
QNetworkAccessManager * KQOAuthManager::networkManager() const {
|
||||||
|
Q_D(const KQOAuthManager);
|
||||||
|
|
||||||
|
if (d->managerUserSet) {
|
||||||
|
return d->networkManager;
|
||||||
|
} else {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void KQOAuthManager::setSuccessHtmlFile(QString file) {
|
||||||
|
Q_D(KQOAuthManager);
|
||||||
|
d->successHtmlFile = file;
|
||||||
|
d->callbackServer->setSuccessHtmlFile(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////// Public convenience API /////////////
|
||||||
|
void KQOAuthManager::getOauth2UserAuthorization(QUrl authorizationEndpoint, QString consumerKey) {
|
||||||
|
Q_D(KQOAuthManager);
|
||||||
|
|
||||||
|
d->setupCallbackServer();
|
||||||
|
connect(d->callbackServer, SIGNAL(verificationReceived(QMultiMap<QString, QString>)),
|
||||||
|
this, SLOT( onVerificationReceived(QMultiMap<QString, QString>)));
|
||||||
|
|
||||||
|
QString serverString = "http://localhost:";
|
||||||
|
serverString.append(QString::number(d->callbackServer->serverPort()));
|
||||||
|
QUrl openWebPageUrl(authorizationEndpoint.toString(), QUrl::StrictMode);
|
||||||
|
openWebPageUrl.addQueryItem(OAUTH2_KEY_CLIENT_ID, consumerKey);
|
||||||
|
openWebPageUrl.addQueryItem(OAUTH2_KEY_RESPONSE_TYPE, "token");
|
||||||
|
openWebPageUrl.addQueryItem(OAUTH2_KEY_REDIRECT_URI, serverString);
|
||||||
|
qDebug() << openWebPageUrl.toString();
|
||||||
|
navigator_invoke(openWebPageUrl.toString().toStdString().c_str(),0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void KQOAuthManager::getUserAuthorization(QUrl authorizationEndpoint) {
|
||||||
|
Q_D(KQOAuthManager);
|
||||||
|
|
||||||
|
if (!d->hasTemporaryToken) {
|
||||||
|
qWarning() << "No temporary tokens retreieved. Cannot get user authorization.";
|
||||||
|
d->error = KQOAuthManager::RequestUnauthorized;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!authorizationEndpoint.isValid()) {
|
||||||
|
qWarning() << "Authorization endpoint not valid. Cannot proceed.";
|
||||||
|
d->error = KQOAuthManager::RequestEndpointError;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
d->error = KQOAuthManager::NoError;
|
||||||
|
|
||||||
|
QPair<QString, QString> tokenParam = qMakePair(QString("oauth_token"), QString(d->requestToken));
|
||||||
|
QUrl openWebPageUrl(authorizationEndpoint.toString(), QUrl::StrictMode);
|
||||||
|
openWebPageUrl.addQueryItem(tokenParam.first, tokenParam.second);
|
||||||
|
|
||||||
|
// Open the user's default browser to the resource authorization page provided
|
||||||
|
// by the service.
|
||||||
|
|
||||||
|
qDebug() << openWebPageUrl.toString();
|
||||||
|
navigator_invoke(openWebPageUrl.toString().toStdString().c_str(),0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void KQOAuthManager::getUserAccessTokens(QUrl accessTokenEndpoint) {
|
||||||
|
Q_D(KQOAuthManager);
|
||||||
|
|
||||||
|
if (!d->isVerified) {
|
||||||
|
qWarning() << "Not verified. Cannot get access tokens.";
|
||||||
|
d->error = KQOAuthManager::RequestUnauthorized;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!accessTokenEndpoint.isValid()) {
|
||||||
|
qWarning() << "Endpoint for access token exchange is not valid. Cannot proceed.";
|
||||||
|
d->error = KQOAuthManager::RequestEndpointError;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
d->error = KQOAuthManager::NoError;
|
||||||
|
|
||||||
|
d->opaqueRequest->clearRequest();
|
||||||
|
d->opaqueRequest->initRequest(KQOAuthRequest::AccessToken, accessTokenEndpoint);
|
||||||
|
d->opaqueRequest->setToken(d->requestToken);
|
||||||
|
d->opaqueRequest->setTokenSecret(d->requestTokenSecret);
|
||||||
|
d->opaqueRequest->setVerifier(d->requestVerifier);
|
||||||
|
d->opaqueRequest->setConsumerKey(d->consumerKey);
|
||||||
|
d->opaqueRequest->setConsumerSecretKey(d->consumerKeySecret);
|
||||||
|
|
||||||
|
executeRequest(d->opaqueRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
void KQOAuthManager::sendAuthorizedRequest(QUrl requestEndpoint, const KQOAuthParameters &requestParameters) {
|
||||||
|
Q_D(KQOAuthManager);
|
||||||
|
|
||||||
|
if (!d->isAuthorized) {
|
||||||
|
qWarning() << "No access tokens retrieved. Cannot send authorized requests.";
|
||||||
|
d->error = KQOAuthManager::RequestUnauthorized;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!requestEndpoint.isValid()) {
|
||||||
|
qWarning() << "Endpoint for authorized request is not valid. Cannot proceed.";
|
||||||
|
d->error = KQOAuthManager::RequestEndpointError;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
d->error = KQOAuthManager::NoError;
|
||||||
|
|
||||||
|
d->opaqueRequest->clearRequest();
|
||||||
|
d->opaqueRequest->initRequest(KQOAuthRequest::AuthorizedRequest, requestEndpoint);
|
||||||
|
d->opaqueRequest->setAdditionalParameters(requestParameters);
|
||||||
|
d->opaqueRequest->setToken(d->requestToken);
|
||||||
|
d->opaqueRequest->setTokenSecret(d->requestTokenSecret);
|
||||||
|
d->opaqueRequest->setConsumerKey(d->consumerKey);
|
||||||
|
d->opaqueRequest->setConsumerSecretKey(d->consumerKeySecret);
|
||||||
|
|
||||||
|
executeRequest(d->opaqueRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/////////////// Private slots //////////////////
|
||||||
|
|
||||||
|
void KQOAuthManager::onRequestReplyReceived( QNetworkReply *reply ) {
|
||||||
|
Q_D(KQOAuthManager);
|
||||||
|
|
||||||
|
QNetworkReply::NetworkError networkError = reply->error();
|
||||||
|
switch (networkError) {
|
||||||
|
case QNetworkReply::NoError:
|
||||||
|
d->error = KQOAuthManager::NoError;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case QNetworkReply::ContentAccessDenied:
|
||||||
|
case QNetworkReply::AuthenticationRequiredError:
|
||||||
|
d->error = KQOAuthManager::RequestUnauthorized;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
d->error = KQOAuthManager::NetworkError;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Let's disconnect this slot first
|
||||||
|
/*
|
||||||
|
disconnect(d->networkManager, SIGNAL(finished(QNetworkReply *)),
|
||||||
|
this, SLOT(onRequestReplyReceived(QNetworkReply *)));
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Read the content of the reply from the network.
|
||||||
|
QByteArray networkReply = reply->readAll();
|
||||||
|
|
||||||
|
// Stop any timer we have set on the request.
|
||||||
|
d->r->requestTimerStop();
|
||||||
|
|
||||||
|
// Just don't do anything if we didn't get anything useful.
|
||||||
|
if(networkReply.isEmpty()) {
|
||||||
|
reply->deleteLater();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QMultiMap<QString, QString> responseTokens;
|
||||||
|
|
||||||
|
// We need to emit the signal even if we got an error.
|
||||||
|
if (d->error != KQOAuthManager::NoError) {
|
||||||
|
reply->deleteLater();
|
||||||
|
emit requestReady(networkReply);
|
||||||
|
d->emitTokens();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
responseTokens = d->createTokensFromResponse(networkReply);
|
||||||
|
d->opaqueRequest->clearRequest();
|
||||||
|
d->opaqueRequest->setHttpMethod(KQOAuthRequest::POST); // XXX FIXME: Convenient API does not support GET
|
||||||
|
if (!d->isAuthorized || !d->isVerified) {
|
||||||
|
if (d->setSuccessfulRequestToken(responseTokens)) {
|
||||||
|
qDebug() << "Successfully got request tokens.";
|
||||||
|
d->consumerKey = d->r->consumerKeyForManager();
|
||||||
|
d->consumerKeySecret = d->r->consumerKeySecretForManager();
|
||||||
|
d->opaqueRequest->setSignatureMethod(KQOAuthRequest::HMAC_SHA1);
|
||||||
|
d->opaqueRequest->setCallbackUrl(d->r->callbackUrlForManager());
|
||||||
|
|
||||||
|
d->emitTokens();
|
||||||
|
|
||||||
|
} else if (d->setSuccessfulAuthorized(responseTokens)) {
|
||||||
|
qDebug() << "Successfully got access tokens.";
|
||||||
|
d->opaqueRequest->setSignatureMethod(KQOAuthRequest::HMAC_SHA1);
|
||||||
|
|
||||||
|
d->emitTokens();
|
||||||
|
} else if (d->currentRequestType == KQOAuthRequest::AuthorizedRequest) {
|
||||||
|
emit authorizedRequestDone();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
emit requestReady(networkReply);
|
||||||
|
|
||||||
|
reply->deleteLater(); // We need to clean this up, after the event processing is done.
|
||||||
|
}
|
||||||
|
|
||||||
|
void KQOAuthManager::onAuthorizedRequestReplyReceived( QNetworkReply *reply ) {
|
||||||
|
Q_D(KQOAuthManager);
|
||||||
|
|
||||||
|
QNetworkReply::NetworkError networkError = reply->error();
|
||||||
|
switch (networkError) {
|
||||||
|
case QNetworkReply::NoError:
|
||||||
|
d->error = KQOAuthManager::NoError;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case QNetworkReply::ContentAccessDenied:
|
||||||
|
case QNetworkReply::AuthenticationRequiredError:
|
||||||
|
d->error = KQOAuthManager::RequestUnauthorized;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
d->error = KQOAuthManager::NetworkError;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
disconnect(d->networkManager, SIGNAL(finished(QNetworkReply *)),
|
||||||
|
this, SLOT(onAuthorizedRequestReplyReceived(QNetworkReply *)));
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Read the content of the reply from the network.
|
||||||
|
QByteArray networkReply = reply->readAll();
|
||||||
|
|
||||||
|
// Stop any timer we have set on the request.
|
||||||
|
d->r->requestTimerStop();
|
||||||
|
|
||||||
|
// Just don't do anything if we didn't get anything useful.
|
||||||
|
if(networkReply.isEmpty()) {
|
||||||
|
reply->deleteLater();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We need to emit the signal even if we got an error.
|
||||||
|
if (d->error != KQOAuthManager::NoError) {
|
||||||
|
qWarning() << "Network reply error";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
d->opaqueRequest->clearRequest();
|
||||||
|
d->opaqueRequest->setHttpMethod(KQOAuthRequest::POST); // XXX FIXME: Convenient API does not support GET
|
||||||
|
if (d->currentRequestType == KQOAuthRequest::AuthorizedRequest) {
|
||||||
|
emit authorizedRequestDone();
|
||||||
|
}
|
||||||
|
|
||||||
|
int id = d->requestIds.take(reply);
|
||||||
|
emit authorizedRequestReady(networkReply, id);
|
||||||
|
reply->deleteLater();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void KQOAuthManager::onVerificationReceived(QMultiMap<QString, QString> response) {
|
||||||
|
Q_D(KQOAuthManager);
|
||||||
|
|
||||||
|
QString token = response.value("oauth_token");
|
||||||
|
QString verifier = response.value("oauth_verifier");
|
||||||
|
if (verifier.isEmpty()) {
|
||||||
|
d->error = KQOAuthManager::RequestUnauthorized;
|
||||||
|
}
|
||||||
|
|
||||||
|
verifier = QUrl::fromPercentEncoding(verifier.toUtf8()); // We get the raw URL response here so we need to convert it back
|
||||||
|
// to plain string so we can percent encode it again later in requests.
|
||||||
|
|
||||||
|
if (d->error == KQOAuthManager::NoError) {
|
||||||
|
d->requestVerifier = verifier;
|
||||||
|
d->isVerified = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
emit authorizationReceived(token, verifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
void KQOAuthManager::slotError(QNetworkReply::NetworkError error) {
|
||||||
|
Q_UNUSED(error)
|
||||||
|
Q_D(KQOAuthManager);
|
||||||
|
|
||||||
|
d->error = KQOAuthManager::NetworkError;
|
||||||
|
QByteArray emptyResponse;
|
||||||
|
emit requestReady(emptyResponse);
|
||||||
|
emit authorizedRequestDone();
|
||||||
|
|
||||||
|
QNetworkReply *reply = qobject_cast<QNetworkReply *>(sender());
|
||||||
|
d->requestIds.remove(reply);
|
||||||
|
reply->deleteLater();
|
||||||
|
}
|
||||||
|
|
192
oauth/kqoauthmanager.h
Normal file
192
oauth/kqoauthmanager.h
Normal file
|
@ -0,0 +1,192 @@
|
||||||
|
/**
|
||||||
|
* KQOAuth - An OAuth authentication library for Qt.
|
||||||
|
*
|
||||||
|
* Author: Johan Paul (johan.paul@d-pointer.com)
|
||||||
|
* http://www.d-pointer.com
|
||||||
|
*
|
||||||
|
* KQOAuth is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* KQOAuth 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 Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with KQOAuth. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#ifndef KQOAUTHMANAGER_H
|
||||||
|
#define KQOAUTHMANAGER_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QMultiMap>
|
||||||
|
#include <QNetworkReply>
|
||||||
|
|
||||||
|
#include "kqoauthrequest.h"
|
||||||
|
|
||||||
|
class KQOAuthRequest;
|
||||||
|
class KQOAuthManagerThread;
|
||||||
|
class KQOAuthManagerPrivate;
|
||||||
|
class QNetworkAccessManager;
|
||||||
|
class QUrl;
|
||||||
|
class QByteArray;
|
||||||
|
class KQOAUTH_EXPORT KQOAuthManager : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
|
||||||
|
enum KQOAuthError {
|
||||||
|
NoError, // No error
|
||||||
|
NetworkError, // Network error: timeout, cannot connect.
|
||||||
|
RequestEndpointError, // Request endpoint is not valid.
|
||||||
|
RequestValidationError, // Request is not valid: some parameter missing?
|
||||||
|
RequestUnauthorized, // Authorization error: trying to access a resource without tokens.
|
||||||
|
RequestError, // The given request to KQOAuthManager is invalid: NULL?,
|
||||||
|
ManagerError // Manager error, cannot use for sending requests.
|
||||||
|
};
|
||||||
|
|
||||||
|
explicit KQOAuthManager(QObject *parent = 0);
|
||||||
|
~KQOAuthManager();
|
||||||
|
|
||||||
|
KQOAuthError lastError();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The manager executes the given request. It takes the HTTP parameters from the
|
||||||
|
* request and uses QNetworkAccessManager to submit the HTTP request to the net.
|
||||||
|
* When the request is done it will emit signal requestReady(QByteArray networkReply).
|
||||||
|
* NOTE: At the moment there is no timeout for the request.
|
||||||
|
*/
|
||||||
|
void executeRequest(KQOAuthRequest *request);
|
||||||
|
void executeAuthorizedRequest(KQOAuthRequest *request, int id);
|
||||||
|
/**
|
||||||
|
* Indicates to the user that KQOAuthManager should handle user authorization by
|
||||||
|
* opening the user's default browser and parsing the reply from the service.
|
||||||
|
* By setting the parameter to true, KQOAuthManager will store intermediate results
|
||||||
|
* of the OAuth 1.0 process in its own opaque request. This information is used in
|
||||||
|
* the user authorization process and also when calling sendAuthorizedRequest().
|
||||||
|
* NOTE: You need to set this to true if you want to use getUserAccessTokens() or
|
||||||
|
* sendAuthorizedRequest().
|
||||||
|
*/
|
||||||
|
void setHandleUserAuthorization(bool set);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the KQOAuthManager has retrieved the oauth_token value. Otherwise
|
||||||
|
* return false.
|
||||||
|
*/
|
||||||
|
bool hasTemporaryToken();
|
||||||
|
/**
|
||||||
|
* Returns true if the user has authorized us to use the protected resources. Otherwise
|
||||||
|
* returns false.
|
||||||
|
* NOTE: In order for KQOAuthManager to know if the user has authorized us to use the
|
||||||
|
* protected resources, KQOAuthManager must be in control of the user authorization
|
||||||
|
* process. Hence, this returns true if setHandleUserAuthorization() is set to true
|
||||||
|
* and the user is authorized with getUserAuthorization().
|
||||||
|
*/
|
||||||
|
bool isVerified();
|
||||||
|
/**
|
||||||
|
* Returns true if KQOAuthManager has the access token and hence can access the protected
|
||||||
|
* resources. Otherwise returns false.
|
||||||
|
* NOTE: In order for KQOAuthManager to know if we have access to protected resource
|
||||||
|
* KQOAuthManager must be in control of the user authorization process and requesting
|
||||||
|
* the acess token. Hence, this returns true if setHandleUserAuthorization() is set to true
|
||||||
|
* and the user is authorized with getUserAuthorization() and the access token must be retrieved
|
||||||
|
* with getUserAccessTokens.
|
||||||
|
*/
|
||||||
|
bool isAuthorized();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the file path string that the local server will serve on a successful authentication. This will generally direct
|
||||||
|
* your user to go back to your application and continue using the app.
|
||||||
|
*/
|
||||||
|
void setSuccessHtmlFile(QString filePath);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a convenience API for authorizing the user.
|
||||||
|
* The call will open the user's default browser, setup a local HTTP server and parse the reply from the
|
||||||
|
* service after the user has authorized us to access protected resources. If the user authorizes
|
||||||
|
* us to access protected resources, the verifier token is stored in KQOAuthManager for further use.
|
||||||
|
* In order to use this method, you must set setHandleUserAuthorization() to true.
|
||||||
|
*/
|
||||||
|
void getUserAuthorization(QUrl authorizationEndpoint);
|
||||||
|
/**
|
||||||
|
* This is a convenience API for retrieving the access token in exchange for the temporary token and the
|
||||||
|
* verifier.
|
||||||
|
* This call will create a KQOAuthRequest and use the previously stored temporary token and verifier to
|
||||||
|
* exchange for the access token, which will be used to access the protected resources.
|
||||||
|
* Note that in order to use this method, KQOAuthManager must be in control of the user authorization process.
|
||||||
|
* Set setHandleUserAuthorization() to true and retrieve user authorization with void getUserAuthorization.
|
||||||
|
*/
|
||||||
|
void getUserAccessTokens(QUrl accessTokenEndpoint);
|
||||||
|
/**
|
||||||
|
* This is a method for bypassing all the oauth1 auth process and using the browser based oauth2 flow. This will
|
||||||
|
* launch the browser and set the callback url pointed to a localhost url. Make sure your oauth2 service supports redirect_uri param.
|
||||||
|
*/
|
||||||
|
void getOauth2UserAuthorization(QUrl authorizationEndpoint, QString consumerKey);
|
||||||
|
/**
|
||||||
|
* Sends a request to the protected resources. Parameters for the request are service specific and
|
||||||
|
* are given to the 'requestParameters' as parameters.
|
||||||
|
* Note that in order to use this method, KQOAuthManager must be in control of the user authorization process.
|
||||||
|
* Set setHandleUserAuthorization() to true and retrieve user authorization with void getUserAuthorization.
|
||||||
|
*/
|
||||||
|
void sendAuthorizedRequest(QUrl requestEndpoint, const KQOAuthParameters &requestParameters);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a custom QNetworkAccessManager to handle network requests. This method can be useful if the
|
||||||
|
* application is using some proxy settings for example.
|
||||||
|
* The application is responsible for deleting this manager. KQOAuthManager will not delete any
|
||||||
|
* previously given manager.
|
||||||
|
* If the manager is NULL, the manager will not be set and the KQOAuthManager::Error.
|
||||||
|
* If no manager is given, KQOAuthManager will use the default one it will create by itself.
|
||||||
|
*/
|
||||||
|
void setNetworkManager(QNetworkAccessManager *manager);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the given QNetworkAccessManager. Returns NULL if none is given.
|
||||||
|
*/
|
||||||
|
QNetworkAccessManager* networkManager() const;
|
||||||
|
|
||||||
|
Q_SIGNALS:
|
||||||
|
// This signal will be emitted after each request has got a reply.
|
||||||
|
// Parameter is the raw response from the service.
|
||||||
|
void requestReady(QByteArray networkReply);
|
||||||
|
|
||||||
|
void authorizedRequestReady(QByteArray networkReply, int id);
|
||||||
|
|
||||||
|
// This signal will be emited when we have an request tokens available
|
||||||
|
// (either temporary resource tokens, or authorization tokens).
|
||||||
|
void receivedToken(QString oauth_token, QString oauth_token_secret); // oauth_token, oauth_token_secret
|
||||||
|
|
||||||
|
// This signal is emited when temporary tokens are returned from the service.
|
||||||
|
// Note that this signal is also emited in case temporary tokens are not available.
|
||||||
|
void temporaryTokenReceived(QString oauth_token, QString oauth_token_secret); // oauth_token, oauth_token_secret
|
||||||
|
|
||||||
|
// This signal is emited when the user has authenticated the application to
|
||||||
|
// communicate with the protected resources. Next we need to exchange the
|
||||||
|
// temporary tokens for access tokens.
|
||||||
|
// Note that this signal is also emited if user denies access.
|
||||||
|
void authorizationReceived(QString oauth_token, QString oauth_verifier); // oauth_token, oauth_verifier
|
||||||
|
|
||||||
|
// This signal is emited when access tokens are received from the service. We are
|
||||||
|
// ready to start communicating with the protected resources.
|
||||||
|
void accessTokenReceived(QString oauth_token, QString oauth_token_secret); // oauth_token, oauth_token_secret
|
||||||
|
|
||||||
|
// This signal is emited when the authorized request is done.
|
||||||
|
// This ends the kQOAuth interactions.
|
||||||
|
void authorizedRequestDone();
|
||||||
|
|
||||||
|
private Q_SLOTS:
|
||||||
|
void onRequestReplyReceived( QNetworkReply *reply );
|
||||||
|
void onAuthorizedRequestReplyReceived( QNetworkReply *reply );
|
||||||
|
void onVerificationReceived(QMultiMap<QString, QString> response);
|
||||||
|
void slotError(QNetworkReply::NetworkError error);
|
||||||
|
|
||||||
|
private:
|
||||||
|
KQOAuthManagerPrivate *d_ptr;
|
||||||
|
Q_DECLARE_PRIVATE(KQOAuthManager);
|
||||||
|
Q_DISABLE_COPY(KQOAuthManager);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // KQOAUTHMANAGER_H
|
74
oauth/kqoauthmanager_p.h
Normal file
74
oauth/kqoauthmanager_p.h
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
/**
|
||||||
|
* KQOAuth - An OAuth authentication library for Qt.
|
||||||
|
*
|
||||||
|
* Author: Johan Paul (johan.paul@d-pointer.com)
|
||||||
|
* http://www.d-pointer.com
|
||||||
|
*
|
||||||
|
* KQOAuth is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* KQOAuth 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 Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with KQOAuth. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#ifndef KQOAUTHMANAGER_P_H
|
||||||
|
#define KQOAUTHMANAGER_P_H
|
||||||
|
|
||||||
|
#include "kqoauthauthreplyserver.h"
|
||||||
|
#include "kqoauthrequest.h"
|
||||||
|
|
||||||
|
class KQOAUTH_EXPORT KQOAuthManagerPrivate {
|
||||||
|
|
||||||
|
public:
|
||||||
|
KQOAuthManagerPrivate(KQOAuthManager *parent);
|
||||||
|
~KQOAuthManagerPrivate();
|
||||||
|
|
||||||
|
QList< QPair<QString, QString> > createQueryParams(const KQOAuthParameters &requestParams);
|
||||||
|
QMultiMap<QString, QString> createTokensFromResponse(QByteArray reply);
|
||||||
|
bool setSuccessfulRequestToken(const QMultiMap<QString, QString> &request);
|
||||||
|
bool setSuccessfulAuthorized(const QMultiMap<QString, QString> &request);
|
||||||
|
void emitTokens();
|
||||||
|
bool setupCallbackServer();
|
||||||
|
|
||||||
|
KQOAuthManager::KQOAuthError error;
|
||||||
|
KQOAuthRequest *r; // This request is used to cache the user sent request.
|
||||||
|
KQOAuthRequest *opaqueRequest; // This request is used to creating opaque convenience requests for the user.
|
||||||
|
KQOAuthManager * const q_ptr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The items below are needed in order to store the state of the manager and
|
||||||
|
* by that be able to do convenience operations for the user.
|
||||||
|
*/
|
||||||
|
KQOAuthRequest::RequestType currentRequestType;
|
||||||
|
|
||||||
|
// Variables we store here for opaque request handling.
|
||||||
|
// NOTE: The variables are labeled the same for both access token request
|
||||||
|
// and protected resource access.
|
||||||
|
QString requestToken;
|
||||||
|
QString requestTokenSecret;
|
||||||
|
QString consumerKey;
|
||||||
|
QString consumerKeySecret;
|
||||||
|
QString requestVerifier;
|
||||||
|
|
||||||
|
QString successHtmlFile;
|
||||||
|
|
||||||
|
KQOAuthAuthReplyServer *callbackServer;
|
||||||
|
|
||||||
|
bool hasTemporaryToken;
|
||||||
|
bool isVerified;
|
||||||
|
bool isAuthorized;
|
||||||
|
bool autoAuth;
|
||||||
|
QNetworkAccessManager *networkManager;
|
||||||
|
bool managerUserSet;
|
||||||
|
QMap<QNetworkReply*, int> requestIds;
|
||||||
|
|
||||||
|
Q_DECLARE_PUBLIC(KQOAuthManager);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // KQOAUTHMANAGER_P_H
|
628
oauth/kqoauthrequest.cpp
Normal file
628
oauth/kqoauthrequest.cpp
Normal file
|
@ -0,0 +1,628 @@
|
||||||
|
/**
|
||||||
|
* KQOAuth - An OAuth authentication library for Qt.
|
||||||
|
*
|
||||||
|
* Author: Johan Paul (johan.paul@d-pointer.com)
|
||||||
|
* http://www.d-pointer.com
|
||||||
|
*
|
||||||
|
* KQOAuth is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* KQOAuth 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 Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with KQOAuth. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#include <QByteArray>
|
||||||
|
#include <QDateTime>
|
||||||
|
#include <QCryptographicHash>
|
||||||
|
#include <QPair>
|
||||||
|
#include <QStringList>
|
||||||
|
|
||||||
|
#include <QtDebug>
|
||||||
|
#include <QtAlgorithms>
|
||||||
|
|
||||||
|
#include "kqoauthrequest.h"
|
||||||
|
#include "kqoauthrequest_p.h"
|
||||||
|
#include "kqoauthutils.h"
|
||||||
|
#include "kqoauthglobals.h"
|
||||||
|
|
||||||
|
|
||||||
|
//////////// Private d_ptr implementation /////////
|
||||||
|
|
||||||
|
KQOAuthRequestPrivate::KQOAuthRequestPrivate() :
|
||||||
|
timeout(0)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
KQOAuthRequestPrivate::~KQOAuthRequestPrivate()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// This method will not include the "oauthSignature" paramater, since it is calculated from these parameters.
|
||||||
|
void KQOAuthRequestPrivate::prepareRequest() {
|
||||||
|
|
||||||
|
// If parameter list is not empty, we don't want to insert these values by
|
||||||
|
// accident a second time. So giving up.
|
||||||
|
if( !requestParameters.isEmpty() ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ( requestType ) {
|
||||||
|
case KQOAuthRequest::TemporaryCredentials:
|
||||||
|
requestParameters.append( qMakePair( OAUTH_KEY_CALLBACK, oauthCallbackUrl.toString()) ); // This is so ugly that it is almost beautiful.
|
||||||
|
requestParameters.append( qMakePair( OAUTH_KEY_SIGNATURE_METHOD, oauthSignatureMethod) );
|
||||||
|
requestParameters.append( qMakePair( OAUTH_KEY_CONSUMER_KEY, oauthConsumerKey ));
|
||||||
|
requestParameters.append( qMakePair( OAUTH_KEY_VERSION, oauthVersion ));
|
||||||
|
requestParameters.append( qMakePair( OAUTH_KEY_TIMESTAMP, this->oauthTimestamp() ));
|
||||||
|
requestParameters.append( qMakePair( OAUTH_KEY_NONCE, this->oauthNonce() ));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case KQOAuthRequest::AccessToken:
|
||||||
|
requestParameters.append( qMakePair( OAUTH_KEY_SIGNATURE_METHOD, oauthSignatureMethod ));
|
||||||
|
requestParameters.append( qMakePair( OAUTH_KEY_CONSUMER_KEY, oauthConsumerKey ));
|
||||||
|
requestParameters.append( qMakePair( OAUTH_KEY_VERSION, oauthVersion ));
|
||||||
|
requestParameters.append( qMakePair( OAUTH_KEY_TIMESTAMP, this->oauthTimestamp() ));
|
||||||
|
requestParameters.append( qMakePair( OAUTH_KEY_NONCE, this->oauthNonce() ));
|
||||||
|
requestParameters.append( qMakePair( OAUTH_KEY_VERIFIER, oauthVerifier ));
|
||||||
|
requestParameters.append( qMakePair( OAUTH_KEY_TOKEN, oauthToken ));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case KQOAuthRequest::AuthorizedRequest:
|
||||||
|
if(requestOAuthMethod == KQOAuthRequest::OAUTH1) {
|
||||||
|
requestParameters.append( qMakePair( OAUTH_KEY_SIGNATURE_METHOD, oauthSignatureMethod ));
|
||||||
|
requestParameters.append( qMakePair( OAUTH_KEY_CONSUMER_KEY, oauthConsumerKey ));
|
||||||
|
requestParameters.append( qMakePair( OAUTH_KEY_VERSION, oauthVersion ));
|
||||||
|
requestParameters.append( qMakePair( OAUTH_KEY_TIMESTAMP, this->oauthTimestamp() ));
|
||||||
|
requestParameters.append( qMakePair( OAUTH_KEY_NONCE, this->oauthNonce() ));
|
||||||
|
requestParameters.append( qMakePair( OAUTH_KEY_TOKEN, oauthToken ));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void KQOAuthRequestPrivate::signRequest() {
|
||||||
|
QString signature = this->oauthSignature();
|
||||||
|
requestParameters.append( qMakePair( OAUTH_KEY_SIGNATURE, signature) );
|
||||||
|
}
|
||||||
|
|
||||||
|
QString KQOAuthRequestPrivate::oauthSignature() {
|
||||||
|
/**
|
||||||
|
* http://oauth.net/core/1.0/#anchor16
|
||||||
|
* The HMAC-SHA1 signature method uses the HMAC-SHA1 signature algorithm as defined in [RFC2104] where the
|
||||||
|
* Signature Base String is the text and the key is the concatenated values (each first encoded per Parameter
|
||||||
|
* Encoding) of the Consumer Secret and Token Secret, separated by an ‘&’ character (ASCII code 38) even if empty.
|
||||||
|
**/
|
||||||
|
QByteArray baseString = this->requestBaseString();
|
||||||
|
|
||||||
|
QString secret = QString(QUrl::toPercentEncoding(oauthConsumerSecretKey)) + "&" + QString(QUrl::toPercentEncoding(oauthTokenSecret));
|
||||||
|
QString signature = KQOAuthUtils::hmac_sha1(baseString, secret);
|
||||||
|
|
||||||
|
if (debugOutput) {
|
||||||
|
qDebug() << "========== KQOAuthRequest has the following signature:";
|
||||||
|
qDebug() << " * Signature : " << QUrl::toPercentEncoding(signature) << "\n";
|
||||||
|
}
|
||||||
|
return QString( QUrl::toPercentEncoding(signature) );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool normalizedParameterSort(const QPair<QString, QString> &left, const QPair<QString, QString> &right) {
|
||||||
|
QString keyLeft = left.first;
|
||||||
|
QString valueLeft = left.second;
|
||||||
|
QString keyRight = right.first;
|
||||||
|
QString valueRight = right.second;
|
||||||
|
|
||||||
|
if(keyLeft == keyRight) {
|
||||||
|
return (valueLeft < valueRight);
|
||||||
|
} else {
|
||||||
|
return (keyLeft < keyRight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
QByteArray KQOAuthRequestPrivate::requestBaseString() {
|
||||||
|
QByteArray baseString;
|
||||||
|
|
||||||
|
// Every request has these as the commont parameters.
|
||||||
|
baseString.append( oauthHttpMethodString.toUtf8() + "&"); // HTTP method
|
||||||
|
baseString.append( QUrl::toPercentEncoding( oauthRequestEndpoint.toString(QUrl::RemoveQuery) ) + "&" ); // The path and query components
|
||||||
|
|
||||||
|
QList< QPair<QString, QString> > baseStringParameters;
|
||||||
|
baseStringParameters.append(requestParameters);
|
||||||
|
baseStringParameters.append(additionalParameters);
|
||||||
|
|
||||||
|
// Sort the request parameters. These parameters have been
|
||||||
|
// initialized earlier.
|
||||||
|
qSort(baseStringParameters.begin(),
|
||||||
|
baseStringParameters.end(),
|
||||||
|
normalizedParameterSort
|
||||||
|
);
|
||||||
|
|
||||||
|
// Last append the request parameters correctly encoded.
|
||||||
|
baseString.append( encodedParamaterList(baseStringParameters) );
|
||||||
|
|
||||||
|
if (debugOutput) {
|
||||||
|
qDebug() << "========== KQOAuthRequest has the following base string:";
|
||||||
|
qDebug() << baseString << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
return baseString;
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray KQOAuthRequestPrivate::encodedParamaterList(const QList< QPair<QString, QString> > ¶meters) {
|
||||||
|
QByteArray resultList;
|
||||||
|
|
||||||
|
bool first = true;
|
||||||
|
QPair<QString, QString> parameter;
|
||||||
|
|
||||||
|
// Do the debug output.
|
||||||
|
if (debugOutput) {
|
||||||
|
qDebug() << "========== KQOAuthRequest has the following parameters:";
|
||||||
|
}
|
||||||
|
foreach (parameter, parameters) {
|
||||||
|
if(!first) {
|
||||||
|
resultList.append( "&" );
|
||||||
|
} else {
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Here we don't need to explicitely encode the strings to UTF-8 since
|
||||||
|
// QUrl::toPercentEncoding() takes care of that for us.
|
||||||
|
resultList.append( QUrl::toPercentEncoding(parameter.first) // Parameter key
|
||||||
|
+ "="
|
||||||
|
+ QUrl::toPercentEncoding(parameter.second) // Parameter value
|
||||||
|
);
|
||||||
|
if (debugOutput) {
|
||||||
|
qDebug() << " * "
|
||||||
|
<< parameter.first
|
||||||
|
<< " : "
|
||||||
|
<< parameter.second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (debugOutput) {
|
||||||
|
qDebug() << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
return QUrl::toPercentEncoding(resultList);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString KQOAuthRequestPrivate::oauthTimestamp() const {
|
||||||
|
// This is basically for unit tests only. In most cases we don't set the nonce beforehand.
|
||||||
|
if (!oauthTimestamp_.isEmpty()) {
|
||||||
|
return oauthTimestamp_;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if QT_VERSION >= 0x040700
|
||||||
|
return QString::number(QDateTime::currentDateTimeUtc().toTime_t());
|
||||||
|
#else
|
||||||
|
return QString::number(QDateTime::currentDateTime().toUTC().toTime_t());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
QString KQOAuthRequestPrivate::oauthNonce() const {
|
||||||
|
// This is basically for unit tests only. In most cases we don't set the nonce beforehand.
|
||||||
|
if (!oauthNonce_.isEmpty()) {
|
||||||
|
return oauthNonce_;
|
||||||
|
}
|
||||||
|
|
||||||
|
return QString::number(qrand());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KQOAuthRequestPrivate::validateRequest() const {
|
||||||
|
switch ( requestType ) {
|
||||||
|
case KQOAuthRequest::TemporaryCredentials:
|
||||||
|
if (oauthRequestEndpoint.isEmpty()
|
||||||
|
|| oauthConsumerKey.isEmpty()
|
||||||
|
|| oauthNonce_.isEmpty()
|
||||||
|
|| oauthSignatureMethod.isEmpty()
|
||||||
|
|| oauthTimestamp_.isEmpty()
|
||||||
|
|| oauthVersion.isEmpty())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case KQOAuthRequest::AccessToken:
|
||||||
|
if (oauthRequestEndpoint.isEmpty()
|
||||||
|
|| oauthVerifier.isEmpty()
|
||||||
|
|| oauthConsumerKey.isEmpty()
|
||||||
|
|| oauthNonce_.isEmpty()
|
||||||
|
|| oauthSignatureMethod.isEmpty()
|
||||||
|
|| oauthTimestamp_.isEmpty()
|
||||||
|
|| oauthToken.isEmpty()
|
||||||
|
|| oauthTokenSecret.isEmpty()
|
||||||
|
|| oauthVersion.isEmpty())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case KQOAuthRequest::AuthorizedRequest:
|
||||||
|
if(requestOAuthMethod == KQOAuthRequest::OAUTH1) {
|
||||||
|
if (oauthRequestEndpoint.isEmpty()
|
||||||
|
|| oauthConsumerKey.isEmpty()
|
||||||
|
|| oauthNonce_.isEmpty()
|
||||||
|
|| oauthSignatureMethod.isEmpty()
|
||||||
|
|| oauthTimestamp_.isEmpty()
|
||||||
|
|| oauthToken.isEmpty()
|
||||||
|
|| oauthTokenSecret.isEmpty()
|
||||||
|
|| oauthVersion.isEmpty())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
if(oauthToken.isEmpty()){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We should not come here.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////// Public implementation ////////////////
|
||||||
|
|
||||||
|
KQOAuthRequest::KQOAuthRequest(QObject *parent) :
|
||||||
|
QObject(parent),
|
||||||
|
d_ptr(new KQOAuthRequestPrivate)
|
||||||
|
{
|
||||||
|
d_ptr->debugOutput = false; // No debug output by default.
|
||||||
|
qsrand(QTime::currentTime().msec()); // We need to seed the nonce random number with something.
|
||||||
|
// However, we cannot do this while generating the nonce since
|
||||||
|
// we might get the same seed. So initializing here should be fine.
|
||||||
|
}
|
||||||
|
|
||||||
|
KQOAuthRequest::~KQOAuthRequest()
|
||||||
|
{
|
||||||
|
delete d_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KQOAuthRequest::initRequest(KQOAuthRequest::RequestType type, const QUrl &requestEndpoint) {
|
||||||
|
Q_D(KQOAuthRequest);
|
||||||
|
|
||||||
|
if (!requestEndpoint.isValid()) {
|
||||||
|
qWarning() << "Endpoint URL is not valid. Ignoring. This request might not work.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type < 0 || type > KQOAuthRequest::AuthorizedRequest) {
|
||||||
|
qWarning() << "Invalid request type. Ignoring. This request might not work.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear the request
|
||||||
|
clearRequest();
|
||||||
|
|
||||||
|
// Set smart defaults.
|
||||||
|
d->requestType = type;
|
||||||
|
d->oauthRequestEndpoint = requestEndpoint;
|
||||||
|
d->oauthTimestamp_ = d->oauthTimestamp();
|
||||||
|
d->oauthNonce_ = d->oauthNonce();
|
||||||
|
this->setSignatureMethod(KQOAuthRequest::HMAC_SHA1);
|
||||||
|
this->setHttpMethod(KQOAuthRequest::POST);
|
||||||
|
d->oauthVersion = "1.0"; // Currently supports only version 1.0
|
||||||
|
|
||||||
|
d->contentType = "application/x-www-form-urlencoded";
|
||||||
|
}
|
||||||
|
|
||||||
|
void KQOAuthRequest::setConsumerKey(const QString &consumerKey) {
|
||||||
|
Q_D(KQOAuthRequest);
|
||||||
|
d->oauthConsumerKey = consumerKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KQOAuthRequest::setConsumerSecretKey(const QString &consumerSecretKey) {
|
||||||
|
Q_D(KQOAuthRequest);
|
||||||
|
d->oauthConsumerSecretKey = consumerSecretKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KQOAuthRequest::setCallbackUrl(const QUrl &callbackUrl) {
|
||||||
|
Q_D(KQOAuthRequest);
|
||||||
|
|
||||||
|
d->oauthCallbackUrl = callbackUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KQOAuthRequest::setSignatureMethod(KQOAuthRequest::RequestSignatureMethod requestMethod) {
|
||||||
|
Q_D(KQOAuthRequest);
|
||||||
|
QString requestMethodString;
|
||||||
|
|
||||||
|
switch (requestMethod) {
|
||||||
|
case KQOAuthRequest::PLAINTEXT:
|
||||||
|
requestMethodString = "PLAINTEXT";
|
||||||
|
break;
|
||||||
|
case KQOAuthRequest::HMAC_SHA1:
|
||||||
|
requestMethodString = "HMAC-SHA1";
|
||||||
|
break;
|
||||||
|
case KQOAuthRequest::RSA_SHA1:
|
||||||
|
requestMethodString = "RSA-SHA1";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// We should not come here
|
||||||
|
qWarning() << "Invalid signature method set.";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
d->oauthSignatureMethod = requestMethodString;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KQOAuthRequest::setTokenSecret(const QString &tokenSecret) {
|
||||||
|
Q_D(KQOAuthRequest);
|
||||||
|
|
||||||
|
d->oauthTokenSecret = tokenSecret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KQOAuthRequest::setToken(const QString &token) {
|
||||||
|
Q_D(KQOAuthRequest);
|
||||||
|
|
||||||
|
d->oauthToken = token;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KQOAuthRequest::setVerifier(const QString &verifier) {
|
||||||
|
Q_D(KQOAuthRequest);
|
||||||
|
|
||||||
|
d->oauthVerifier = verifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void KQOAuthRequest::setHttpMethod(KQOAuthRequest::RequestHttpMethod httpMethod) {
|
||||||
|
Q_D(KQOAuthRequest);
|
||||||
|
|
||||||
|
QString requestHttpMethodString;
|
||||||
|
|
||||||
|
switch (httpMethod) {
|
||||||
|
case KQOAuthRequest::GET:
|
||||||
|
requestHttpMethodString = "GET";
|
||||||
|
break;
|
||||||
|
case KQOAuthRequest::POST:
|
||||||
|
requestHttpMethodString = "POST";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
qWarning() << "Invalid HTTP method set.";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
d->oauthHttpMethod = httpMethod;
|
||||||
|
d->oauthHttpMethodString = requestHttpMethodString;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KQOAuthRequest::setRequestOAuthMethod(KQOAuthRequest::RequestOAuthMethod oauthMethod) {
|
||||||
|
Q_D(KQOAuthRequest);
|
||||||
|
|
||||||
|
d->requestOAuthMethod = oauthMethod;
|
||||||
|
}
|
||||||
|
|
||||||
|
KQOAuthRequest::RequestHttpMethod KQOAuthRequest::httpMethod() const {
|
||||||
|
Q_D(const KQOAuthRequest);
|
||||||
|
|
||||||
|
return d->oauthHttpMethod;
|
||||||
|
}
|
||||||
|
|
||||||
|
KQOAuthRequest::RequestOAuthMethod KQOAuthRequest::oauthMethod() const {
|
||||||
|
Q_D(const KQOAuthRequest);
|
||||||
|
|
||||||
|
return d->requestOAuthMethod;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KQOAuthRequest::setAdditionalParameters(const KQOAuthParameters &additionalParams) {
|
||||||
|
Q_D(KQOAuthRequest);
|
||||||
|
|
||||||
|
QList<QString> additionalKeys = additionalParams.keys();
|
||||||
|
QList<QString> additionalValues = additionalParams.values();
|
||||||
|
|
||||||
|
int i=0;
|
||||||
|
foreach(QString key, additionalKeys) {
|
||||||
|
QString value = additionalValues.at(i);
|
||||||
|
d->additionalParameters.append( qMakePair(key, value) );
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
KQOAuthParameters KQOAuthRequest::additionalParameters() const {
|
||||||
|
Q_D(const KQOAuthRequest);
|
||||||
|
|
||||||
|
QMultiMap<QString, QString> additionalParams;
|
||||||
|
for(int i=0; i<d->additionalParameters.size(); i++) {
|
||||||
|
additionalParams.insert(d->additionalParameters.at(i).first,
|
||||||
|
d->additionalParameters.at(i).second);
|
||||||
|
}
|
||||||
|
if(d->requestOAuthMethod == KQOAuthRequest::OAUTH2) {
|
||||||
|
additionalParams.insert(OAUTH_KEY_TOKEN, d->oauthToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
return additionalParams;
|
||||||
|
}
|
||||||
|
|
||||||
|
KQOAuthRequest::RequestType KQOAuthRequest::requestType() const {
|
||||||
|
Q_D(const KQOAuthRequest);
|
||||||
|
return d->requestType;
|
||||||
|
}
|
||||||
|
|
||||||
|
QUrl KQOAuthRequest::requestEndpoint() const {
|
||||||
|
Q_D(const KQOAuthRequest);
|
||||||
|
return d->oauthRequestEndpoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<QByteArray> KQOAuthRequest::requestParameters() {
|
||||||
|
Q_D(KQOAuthRequest);
|
||||||
|
|
||||||
|
QList<QByteArray> requestParamList;
|
||||||
|
|
||||||
|
d->prepareRequest();
|
||||||
|
if (!isValid() ) {
|
||||||
|
qWarning() << "Request is not valid! I will still sign it, but it will probably not work.";
|
||||||
|
}
|
||||||
|
if(d->requestOAuthMethod != KQOAuthRequest::OAUTH2) {
|
||||||
|
d->signRequest();
|
||||||
|
}
|
||||||
|
|
||||||
|
QPair<QString, QString> requestParam;
|
||||||
|
QString param;
|
||||||
|
QString value;
|
||||||
|
foreach (requestParam, d->requestParameters) {
|
||||||
|
param = requestParam.first;
|
||||||
|
value = requestParam.second;
|
||||||
|
requestParamList.append(QString(param + "=\"" + value +"\"").toUtf8());
|
||||||
|
}
|
||||||
|
|
||||||
|
return requestParamList;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString KQOAuthRequest::contentType()
|
||||||
|
{
|
||||||
|
Q_D(const KQOAuthRequest);
|
||||||
|
return d->contentType;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KQOAuthRequest::setContentType(const QString &contentType)
|
||||||
|
{
|
||||||
|
Q_D(KQOAuthRequest);
|
||||||
|
d->contentType = contentType;
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray KQOAuthRequest::rawData()
|
||||||
|
{
|
||||||
|
Q_D(const KQOAuthRequest);
|
||||||
|
return d->postRawData;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KQOAuthRequest::setRawData(const QByteArray &rawData)
|
||||||
|
{
|
||||||
|
Q_D(KQOAuthRequest);
|
||||||
|
d->postRawData = rawData;
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray KQOAuthRequest::requestBody() const {
|
||||||
|
Q_D(const KQOAuthRequest);
|
||||||
|
|
||||||
|
QByteArray postBodyContent;
|
||||||
|
bool first = true;
|
||||||
|
for(int i=0; i < d->additionalParameters.size(); i++) {
|
||||||
|
if(!first) {
|
||||||
|
postBodyContent.append("&");
|
||||||
|
} else {
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString key = d->additionalParameters.at(i).first;
|
||||||
|
QString value = d->additionalParameters.at(i).second;
|
||||||
|
|
||||||
|
postBodyContent.append(QUrl::toPercentEncoding(key) + QString("=").toUtf8() +
|
||||||
|
QUrl::toPercentEncoding(value));
|
||||||
|
}
|
||||||
|
qDebug() << postBodyContent;
|
||||||
|
return postBodyContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KQOAuthRequest::isValid() const {
|
||||||
|
Q_D(const KQOAuthRequest);
|
||||||
|
|
||||||
|
return d->validateRequest();
|
||||||
|
}
|
||||||
|
|
||||||
|
void KQOAuthRequest::setTimeout(int timeoutMilliseconds) {
|
||||||
|
Q_D(KQOAuthRequest);
|
||||||
|
d->timeout = timeoutMilliseconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KQOAuthRequest::clearRequest() {
|
||||||
|
Q_D(KQOAuthRequest);
|
||||||
|
|
||||||
|
d->oauthRequestEndpoint = "";
|
||||||
|
d->oauthHttpMethodString = "";
|
||||||
|
d->oauthConsumerKey = "";
|
||||||
|
d->oauthConsumerSecretKey = "";
|
||||||
|
d->oauthToken = "";
|
||||||
|
d->oauthTokenSecret = "";
|
||||||
|
d->oauthSignatureMethod = "";
|
||||||
|
d->oauthCallbackUrl = "";
|
||||||
|
d->oauthVerifier = "";
|
||||||
|
d->oauthTimestamp_ = "";
|
||||||
|
d->oauthNonce_ = "";
|
||||||
|
d->requestParameters.clear();
|
||||||
|
d->additionalParameters.clear();
|
||||||
|
d->timeout = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KQOAuthRequest::setEnableDebugOutput(bool enabled) {
|
||||||
|
Q_D(KQOAuthRequest);
|
||||||
|
d->debugOutput = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Protected implementations for inherited classes
|
||||||
|
*/
|
||||||
|
bool KQOAuthRequest::validateXAuthRequest() const {
|
||||||
|
Q_D(const KQOAuthRequest);
|
||||||
|
|
||||||
|
if (d->oauthRequestEndpoint.isEmpty()
|
||||||
|
|| d->oauthConsumerKey.isEmpty()
|
||||||
|
|| d->oauthNonce_.isEmpty()
|
||||||
|
|| d->oauthSignatureMethod.isEmpty()
|
||||||
|
|| d->oauthTimestamp_.isEmpty()
|
||||||
|
|| d->oauthVersion.isEmpty())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KQOAuthRequest::validateOauth2Request() const {
|
||||||
|
Q_D(const KQOAuthRequest);
|
||||||
|
|
||||||
|
if (d->oauthRequestEndpoint.isEmpty()
|
||||||
|
|| d->oauthConsumerKey.isEmpty()
|
||||||
|
|| d->oauthConsumerSecretKey.isEmpty())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Private implementations for friend classes
|
||||||
|
*/
|
||||||
|
QString KQOAuthRequest::consumerKeyForManager() const {
|
||||||
|
Q_D(const KQOAuthRequest);
|
||||||
|
return d->oauthConsumerKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString KQOAuthRequest::consumerKeySecretForManager() const {
|
||||||
|
Q_D(const KQOAuthRequest);
|
||||||
|
return d->oauthConsumerSecretKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
QUrl KQOAuthRequest::callbackUrlForManager() const {
|
||||||
|
Q_D(const KQOAuthRequest);
|
||||||
|
return d->oauthCallbackUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KQOAuthRequest::requestTimerStart()
|
||||||
|
{
|
||||||
|
Q_D(KQOAuthRequest);
|
||||||
|
if (d->timeout > 0) {
|
||||||
|
connect(&(d->timer), SIGNAL(timeout()), this, SIGNAL(requestTimedout()));
|
||||||
|
d->timer.start(d->timeout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void KQOAuthRequest::requestTimerStop()
|
||||||
|
{
|
||||||
|
Q_D(KQOAuthRequest);
|
||||||
|
if (d->timeout > 0) {
|
||||||
|
disconnect(&(d->timer), SIGNAL(timeout()), this, SIGNAL(requestTimedout()));
|
||||||
|
d->timer.stop();
|
||||||
|
}
|
||||||
|
}
|
153
oauth/kqoauthrequest.h
Normal file
153
oauth/kqoauthrequest.h
Normal file
|
@ -0,0 +1,153 @@
|
||||||
|
/**
|
||||||
|
* KQOAuth - An OAuth authentication library for Qt.
|
||||||
|
*
|
||||||
|
* Author: Johan Paul (johan.paul@d-pointer.com)
|
||||||
|
* http://www.d-pointer.com
|
||||||
|
*
|
||||||
|
* KQOAuth is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* KQOAuth 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 Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with KQOAuth. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#ifndef KQOAUTHREQUEST_H
|
||||||
|
#define KQOAUTHREQUEST_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QUrl>
|
||||||
|
#include <QMultiMap>
|
||||||
|
|
||||||
|
#include "kqoauthglobals.h"
|
||||||
|
|
||||||
|
typedef QMultiMap<QString, QString> KQOAuthParameters;
|
||||||
|
|
||||||
|
class KQOAuthRequestPrivate;
|
||||||
|
class KQOAUTH_EXPORT KQOAuthRequest : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit KQOAuthRequest(QObject *parent = 0);
|
||||||
|
~KQOAuthRequest();
|
||||||
|
|
||||||
|
enum RequestType {
|
||||||
|
TemporaryCredentials = 0,
|
||||||
|
AccessToken,
|
||||||
|
AuthorizedRequest
|
||||||
|
};
|
||||||
|
|
||||||
|
enum RequestSignatureMethod {
|
||||||
|
PLAINTEXT = 0,
|
||||||
|
HMAC_SHA1,
|
||||||
|
RSA_SHA1
|
||||||
|
};
|
||||||
|
|
||||||
|
enum RequestHttpMethod {
|
||||||
|
GET = 0,
|
||||||
|
POST
|
||||||
|
};
|
||||||
|
|
||||||
|
enum RequestOAuthMethod {
|
||||||
|
OAUTH1 = 0,
|
||||||
|
OAUTH2
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* These methods can be overridden in child classes which are different types of
|
||||||
|
* OAuth requests.
|
||||||
|
*/
|
||||||
|
// Validate the request of this type.
|
||||||
|
virtual bool isValid() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* These methods are OAuth request type specific and not overridden in child
|
||||||
|
* classes.
|
||||||
|
* NOTE: Refactorting still a TODO
|
||||||
|
*/
|
||||||
|
// Initialize the request of this type.
|
||||||
|
virtual void initRequest(KQOAuthRequest::RequestType type, const QUrl &requestEndpoint);
|
||||||
|
|
||||||
|
void setConsumerKey(const QString &consumerKey);
|
||||||
|
void setConsumerSecretKey(const QString &consumerSecretKey);
|
||||||
|
|
||||||
|
// Mandatory methods for acquiring a request token
|
||||||
|
void setCallbackUrl(const QUrl &callbackUrl);
|
||||||
|
|
||||||
|
// Mandator methods for acquiring a access token
|
||||||
|
void setTokenSecret(const QString &tokenSecret);
|
||||||
|
void setToken(const QString &token);
|
||||||
|
void setVerifier(const QString &verifier);
|
||||||
|
|
||||||
|
// Request signature method to use - HMAC_SHA1 currently only supported
|
||||||
|
void setSignatureMethod(KQOAuthRequest::RequestSignatureMethod = KQOAuthRequest::HMAC_SHA1);
|
||||||
|
|
||||||
|
// Request's HTTP method.
|
||||||
|
void setHttpMethod(KQOAuthRequest::RequestHttpMethod = KQOAuthRequest::POST);
|
||||||
|
KQOAuthRequest::RequestHttpMethod httpMethod() const;
|
||||||
|
KQOAuthRequest::RequestOAuthMethod oauthMethod() const;
|
||||||
|
void setRequestOAuthMethod(KQOAuthRequest::RequestOAuthMethod = KQOAuthRequest::OAUTH1);
|
||||||
|
|
||||||
|
// Sets the timeout for this request. If the timeout expires, signal "requestTimedout" will be
|
||||||
|
// emitted from the manager.
|
||||||
|
// 0 = If set to zero, timeout is disabled.
|
||||||
|
// TODO: Do we need some request ID now?
|
||||||
|
void setTimeout(int timeoutMilliseconds);
|
||||||
|
|
||||||
|
// Additional optional parameters to the request.
|
||||||
|
void setAdditionalParameters(const KQOAuthParameters &additionalParams);
|
||||||
|
KQOAuthParameters additionalParameters() const;
|
||||||
|
QList<QByteArray> requestParameters(); // This will return all request's parameters in the raw format given
|
||||||
|
// to the QNetworkRequest.
|
||||||
|
QByteArray requestBody() const; // This will return the POST body as given to the QNetworkRequest.
|
||||||
|
|
||||||
|
KQOAuthRequest::RequestType requestType() const;
|
||||||
|
QUrl requestEndpoint() const;
|
||||||
|
|
||||||
|
void setContentType(const QString &contentType);
|
||||||
|
QString contentType();
|
||||||
|
|
||||||
|
void setRawData(const QByteArray &rawData);
|
||||||
|
QByteArray rawData();
|
||||||
|
|
||||||
|
void clearRequest();
|
||||||
|
|
||||||
|
// Enable verbose debug output for request content.
|
||||||
|
void setEnableDebugOutput(bool enabled);
|
||||||
|
|
||||||
|
Q_SIGNALS:
|
||||||
|
// This signal is emited if the request is not completed before the request's timeout
|
||||||
|
// value has expired.
|
||||||
|
void requestTimedout();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool validateXAuthRequest() const;
|
||||||
|
bool validateOauth2Request() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
KQOAuthRequestPrivate * const d_ptr;
|
||||||
|
Q_DECLARE_PRIVATE(KQOAuthRequest);
|
||||||
|
Q_DISABLE_COPY(KQOAuthRequest);
|
||||||
|
|
||||||
|
// These classes are only for the internal use of KQOAuthManager so it can
|
||||||
|
// work with the opaque request.
|
||||||
|
QString consumerKeyForManager() const;
|
||||||
|
QString consumerKeySecretForManager() const;
|
||||||
|
QUrl callbackUrlForManager() const;
|
||||||
|
|
||||||
|
// This method is for timeout handling by the KQOAuthManager.
|
||||||
|
void requestTimerStart();
|
||||||
|
void requestTimerStop();
|
||||||
|
|
||||||
|
friend class KQOAuthManager;
|
||||||
|
#ifdef UNIT_TEST
|
||||||
|
friend class Ut_KQOAuth;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // KQOAUTHREQUEST_H
|
5
oauth/kqoauthrequest_1.cpp
Normal file
5
oauth/kqoauthrequest_1.cpp
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
#include "kqoauthrequest_1.h"
|
||||||
|
|
||||||
|
KQOAuthRequest_1::KQOAuthRequest_1()
|
||||||
|
{
|
||||||
|
}
|
12
oauth/kqoauthrequest_1.h
Normal file
12
oauth/kqoauthrequest_1.h
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#ifndef KQOAUTHREQUEST_1_H
|
||||||
|
#define KQOAUTHREQUEST_1_H
|
||||||
|
|
||||||
|
#include "kqoauthrequest.h"
|
||||||
|
|
||||||
|
class KQOAUTH_EXPORT KQOAuthRequest_1 : public KQOAuthRequest
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
KQOAuthRequest_1();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // KQOAUTHREQUEST_1_H
|
94
oauth/kqoauthrequest_p.h
Normal file
94
oauth/kqoauthrequest_p.h
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
/**
|
||||||
|
* KQOAuth - An OAuth authentication library for Qt.
|
||||||
|
*
|
||||||
|
* Author: Johan Paul (johan.paul@d-pointer.com)
|
||||||
|
* http://www.d-pointer.com
|
||||||
|
*
|
||||||
|
* KQOAuth is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* KQOAuth 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 Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with KQOAuth. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#ifndef KQOAUTHREQUEST_P_H
|
||||||
|
#define KQOAUTHREQUEST_P_H
|
||||||
|
#include "kqoauthglobals.h"
|
||||||
|
#include "kqoauthrequest.h"
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
#include <QUrl>
|
||||||
|
#include <QMap>
|
||||||
|
#include <QPair>
|
||||||
|
#include <QMultiMap>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
|
class KQOAUTH_EXPORT KQOAuthRequestPrivate {
|
||||||
|
|
||||||
|
public:
|
||||||
|
KQOAuthRequestPrivate();
|
||||||
|
~KQOAuthRequestPrivate();
|
||||||
|
|
||||||
|
// Helper methods to get the values for the OAuth request parameters.
|
||||||
|
QString oauthTimestamp() const;
|
||||||
|
QString oauthNonce() const;
|
||||||
|
QString oauthSignature();
|
||||||
|
|
||||||
|
// Utility methods for making the request happen.
|
||||||
|
void prepareRequest();
|
||||||
|
void signRequest();
|
||||||
|
bool validateRequest() const;
|
||||||
|
QByteArray requestBaseString();
|
||||||
|
QByteArray encodedParamaterList(const QList< QPair<QString, QString> > &requestParameters);
|
||||||
|
void insertAdditionalParams();
|
||||||
|
void insertPostBody();
|
||||||
|
|
||||||
|
QUrl oauthRequestEndpoint;
|
||||||
|
KQOAuthRequest::RequestHttpMethod oauthHttpMethod;
|
||||||
|
QString oauthHttpMethodString;
|
||||||
|
QString oauthConsumerKey;
|
||||||
|
QString oauthConsumerSecretKey;
|
||||||
|
QString oauthToken;
|
||||||
|
QString oauthTokenSecret;
|
||||||
|
QString oauthSignatureMethod;
|
||||||
|
QUrl oauthCallbackUrl;
|
||||||
|
QString oauthVersion;
|
||||||
|
QString oauthVerifier;
|
||||||
|
|
||||||
|
// These will be generated by the helper methods
|
||||||
|
QString oauthTimestamp_;
|
||||||
|
QString oauthNonce_;
|
||||||
|
|
||||||
|
// User specified additional parameters needed for the request.
|
||||||
|
QList< QPair<QString, QString> > additionalParameters;
|
||||||
|
|
||||||
|
// The raw POST body content as given to the HTTP request.
|
||||||
|
QByteArray postBodyContent;
|
||||||
|
|
||||||
|
// Protocol parameters.
|
||||||
|
// These parameters are used in the "Authorized" header of the HTTP request.
|
||||||
|
QList< QPair<QString, QString> > requestParameters;
|
||||||
|
|
||||||
|
KQOAuthRequest::RequestType requestType;
|
||||||
|
KQOAuthRequest::RequestOAuthMethod requestOAuthMethod;
|
||||||
|
|
||||||
|
//The Content-Type HTTP header
|
||||||
|
QString contentType;
|
||||||
|
|
||||||
|
//Raw data to post if type is not url-encoded
|
||||||
|
QByteArray postRawData;
|
||||||
|
|
||||||
|
// Timeout for this request in milliseconds.
|
||||||
|
int timeout;
|
||||||
|
QTimer timer;
|
||||||
|
|
||||||
|
bool debugOutput;
|
||||||
|
|
||||||
|
};
|
||||||
|
#endif // KQOAUTHREQUEST_P_H
|
91
oauth/kqoauthrequest_xauth.cpp
Normal file
91
oauth/kqoauthrequest_xauth.cpp
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
/**
|
||||||
|
* KQOAuth - An OAuth authentication library for Qt.
|
||||||
|
*
|
||||||
|
* Author: Johan Paul (johan.paul@d-pointer.com)
|
||||||
|
* http://www.d-pointer.com
|
||||||
|
*
|
||||||
|
* KQOAuth is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* KQOAuth 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 Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with KQOAuth. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#include <QtDebug>
|
||||||
|
|
||||||
|
#include "kqoauthrequest_xauth_p.h"
|
||||||
|
#include "kqoauthrequest_xauth.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Private d_ptr implementations.
|
||||||
|
*/
|
||||||
|
KQOAuthRequest_XAuthPrivate::KQOAuthRequest_XAuthPrivate()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
KQOAuthRequest_XAuthPrivate::~KQOAuthRequest_XAuthPrivate()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Public implementations.
|
||||||
|
*/
|
||||||
|
KQOAuthRequest_XAuth::KQOAuthRequest_XAuth(QObject *parent) :
|
||||||
|
KQOAuthRequest(parent),
|
||||||
|
d_ptr(new KQOAuthRequest_XAuthPrivate)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KQOAuthRequest_XAuth::isValid() const {
|
||||||
|
// An xAuth can never request temporary credentials.
|
||||||
|
if (requestType() == KQOAuthRequest::TemporaryCredentials) {
|
||||||
|
qWarning() << "XAuth request cannot be of type KQOAuthRequest::TemporaryCredentials. Aborting.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Access token must always be retrieved using the POST HTTP method.
|
||||||
|
if (requestType() == KQOAuthRequest::AccessToken
|
||||||
|
&& httpMethod() != KQOAuthRequest::POST) {
|
||||||
|
|
||||||
|
qWarning() << "Access tokens must be fetched using the POST HTTP method. Aborting.";
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!xauth_parameters_set) {
|
||||||
|
qWarning() << "No XAuth parameters set. Aborting.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// And then check the validity of the XAuth request.
|
||||||
|
// Provided by the base class as a protected method for us.
|
||||||
|
return validateXAuthRequest();
|
||||||
|
}
|
||||||
|
|
||||||
|
void KQOAuthRequest_XAuth::setXAuthLogin(const QString &username,
|
||||||
|
const QString &password) {
|
||||||
|
|
||||||
|
if (username.isEmpty() || password.isEmpty()) {
|
||||||
|
qWarning() << "Username or password cannot be empty. Aborting.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
xauth_parameters_set = true;
|
||||||
|
|
||||||
|
qDebug() << username << password;
|
||||||
|
|
||||||
|
KQOAuthParameters xauthParams;
|
||||||
|
xauthParams.insert("x_auth_username", username);
|
||||||
|
xauthParams.insert("x_auth_password", password);
|
||||||
|
xauthParams.insert("x_auth_mode", "client_auth");
|
||||||
|
|
||||||
|
setAdditionalParameters(xauthParams);
|
||||||
|
}
|
||||||
|
|
49
oauth/kqoauthrequest_xauth.h
Normal file
49
oauth/kqoauthrequest_xauth.h
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
/**
|
||||||
|
* KQOAuth - An OAuth authentication library for Qt.
|
||||||
|
*
|
||||||
|
* Author: Johan Paul (johan.paul@d-pointer.com)
|
||||||
|
* http://www.d-pointer.com
|
||||||
|
*
|
||||||
|
* KQOAuth is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* KQOAuth 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 Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with KQOAuth. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#ifndef KQOAUTHREQUEST_XAUTH_H
|
||||||
|
#define KQOAUTHREQUEST_XAUTH_H
|
||||||
|
|
||||||
|
#include "kqoauthrequest.h"
|
||||||
|
#include "kqoauthrequest_1.h"
|
||||||
|
|
||||||
|
class KQOAuthRequest_XAuthPrivate;
|
||||||
|
class KQOAUTH_EXPORT KQOAuthRequest_XAuth : public KQOAuthRequest
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
KQOAuthRequest_XAuth(QObject *parent = 0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* These methods can be overridden in child classes which are different types of
|
||||||
|
* OAuth requests.
|
||||||
|
*/
|
||||||
|
// Validate the request of this type.
|
||||||
|
bool isValid() const;
|
||||||
|
|
||||||
|
// Give the xAuth specific parameters.
|
||||||
|
void setXAuthLogin(const QString &username = "",
|
||||||
|
const QString &password = "");
|
||||||
|
|
||||||
|
private:
|
||||||
|
KQOAuthRequest_XAuthPrivate * const d_ptr;
|
||||||
|
bool xauth_parameters_set;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // KQOAUTHREQUEST_XAUTH_H
|
14
oauth/kqoauthrequest_xauth_p.h
Normal file
14
oauth/kqoauthrequest_xauth_p.h
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
#ifndef KQOAUTHREQUEST_XAUTH_P_H
|
||||||
|
#define KQOAUTHREQUEST_XAUTH_P_H
|
||||||
|
|
||||||
|
#include "kqoauthglobals.h"
|
||||||
|
|
||||||
|
class KQOAuthRequest;
|
||||||
|
class KQOAUTH_EXPORT KQOAuthRequest_XAuthPrivate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
KQOAuthRequest_XAuthPrivate();
|
||||||
|
~KQOAuthRequest_XAuthPrivate();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // KQOAUTHREQUEST_XAUTH_P_H
|
79
oauth/kqoauthutils.cpp
Normal file
79
oauth/kqoauthutils.cpp
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
/**
|
||||||
|
* KQOAuth - An OAuth authentication library for Qt.
|
||||||
|
*
|
||||||
|
* Author: Johan Paul (johan.paul@d-pointer.com)
|
||||||
|
* http://www.d-pointer.com
|
||||||
|
*
|
||||||
|
* KQOAuth is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* KQOAuth 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 Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with KQOAuth. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#include <QString>
|
||||||
|
#include <QCryptographicHash>
|
||||||
|
#include <QByteArray>
|
||||||
|
|
||||||
|
#include <QtDebug>
|
||||||
|
#include "kqoauthutils.h"
|
||||||
|
|
||||||
|
QString KQOAuthUtils::hmac_sha1(const QString &message, const QString &key)
|
||||||
|
{
|
||||||
|
QByteArray keyBytes = key.toAscii();
|
||||||
|
int keyLength; // Lenght of key word
|
||||||
|
const int blockSize = 64; // Both MD5 and SHA-1 have a block size of 64.
|
||||||
|
|
||||||
|
keyLength = keyBytes.size();
|
||||||
|
// If key is longer than block size, we need to hash the key
|
||||||
|
if (keyLength > blockSize) {
|
||||||
|
QCryptographicHash hash(QCryptographicHash::Sha1);
|
||||||
|
hash.addData(keyBytes);
|
||||||
|
keyBytes = hash.result();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* http://tools.ietf.org/html/rfc2104 - (1) */
|
||||||
|
// Create the opad and ipad for the hash function.
|
||||||
|
QByteArray ipad;
|
||||||
|
QByteArray opad;
|
||||||
|
|
||||||
|
ipad.fill( 0, blockSize);
|
||||||
|
opad.fill( 0, blockSize);
|
||||||
|
|
||||||
|
ipad.replace(0, keyBytes.length(), keyBytes);
|
||||||
|
opad.replace(0, keyBytes.length(), keyBytes);
|
||||||
|
|
||||||
|
/* http://tools.ietf.org/html/rfc2104 - (2) & (5) */
|
||||||
|
for (int i=0; i<64; i++) {
|
||||||
|
ipad[i] = ipad[i] ^ 0x36;
|
||||||
|
opad[i] = opad[i] ^ 0x5c;
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray workArray;
|
||||||
|
workArray.clear();
|
||||||
|
|
||||||
|
workArray.append(ipad, 64);
|
||||||
|
/* http://tools.ietf.org/html/rfc2104 - (3) */
|
||||||
|
workArray.append(message.toAscii());
|
||||||
|
|
||||||
|
|
||||||
|
/* http://tools.ietf.org/html/rfc2104 - (4) */
|
||||||
|
QByteArray sha1 = QCryptographicHash::hash(workArray, QCryptographicHash::Sha1);
|
||||||
|
|
||||||
|
/* http://tools.ietf.org/html/rfc2104 - (6) */
|
||||||
|
workArray.clear();
|
||||||
|
workArray.append(opad, 64);
|
||||||
|
workArray.append(sha1);
|
||||||
|
|
||||||
|
sha1.clear();
|
||||||
|
|
||||||
|
/* http://tools.ietf.org/html/rfc2104 - (7) */
|
||||||
|
sha1 = QCryptographicHash::hash(workArray, QCryptographicHash::Sha1);
|
||||||
|
return QString(sha1.toBase64());
|
||||||
|
}
|
33
oauth/kqoauthutils.h
Normal file
33
oauth/kqoauthutils.h
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
/**
|
||||||
|
* KQOAuth - An OAuth authentication library for Qt.
|
||||||
|
*
|
||||||
|
* Author: Johan Paul (johan.paul@d-pointer.com)
|
||||||
|
* http://www.d-pointer.com
|
||||||
|
*
|
||||||
|
* KQOAuth is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* KQOAuth 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 Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with KQOAuth. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#ifndef KQOAUTHUTILS_H
|
||||||
|
#define KQOAUTHUTILS_H
|
||||||
|
|
||||||
|
#include "kqoauthglobals.h"
|
||||||
|
|
||||||
|
class QString;
|
||||||
|
class KQOAUTH_EXPORT KQOAuthUtils
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
static QString hmac_sha1(const QString &message, const QString &key);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // KQOAUTHUTILS_H
|
Loading…
Reference in a new issue