2012-11-29 17:03:52 +01:00
|
|
|
#include "dropboxauthenticator.h"
|
|
|
|
|
|
|
|
#include <time.h>
|
|
|
|
|
2012-11-29 17:53:37 +01:00
|
|
|
#include <qjson/parser.h>
|
|
|
|
|
2012-11-29 17:28:47 +01:00
|
|
|
#include <QDesktopServices>
|
2012-11-29 17:03:52 +01:00
|
|
|
#include <QStringList>
|
2012-11-29 17:28:47 +01:00
|
|
|
#include <QTcpSocket>
|
2012-11-29 17:03:52 +01:00
|
|
|
|
|
|
|
#include "core/closure.h"
|
|
|
|
#include "core/logging.h"
|
|
|
|
#include "core/network.h"
|
2012-11-30 14:40:54 +01:00
|
|
|
#include "internet/localredirectserver.h"
|
2012-11-29 17:03:52 +01:00
|
|
|
|
|
|
|
namespace {
|
|
|
|
static const char* kAppKey = "qh6ca27eclt9p2k";
|
|
|
|
static const char* kAppSecret = "pg7y68h5efap8r6";
|
|
|
|
|
2012-11-29 17:46:37 +01:00
|
|
|
// OAuth 1.0 endpoints
|
2012-11-29 17:03:52 +01:00
|
|
|
static const char* kRequestTokenEndpoint =
|
|
|
|
"https://api.dropbox.com/1/oauth/request_token";
|
2012-11-29 17:28:47 +01:00
|
|
|
static const char* kAuthoriseEndpoint =
|
|
|
|
"https://www.dropbox.com/1/oauth/authorize";
|
|
|
|
static const char* kAccessTokenEndpoint =
|
|
|
|
"https://api.dropbox.com/1/oauth/access_token";
|
|
|
|
|
2012-11-29 17:46:37 +01:00
|
|
|
// Dropbox API endpoints
|
|
|
|
static const char* kAccountInfoEndpoint =
|
|
|
|
"https://api.dropbox.com/1/account/info";
|
|
|
|
|
2012-11-29 17:03:52 +01:00
|
|
|
} // namespace
|
|
|
|
|
|
|
|
DropboxAuthenticator::DropboxAuthenticator(QObject* parent)
|
|
|
|
: QObject(parent),
|
|
|
|
network_(new NetworkAccessManager(this)) {
|
|
|
|
}
|
|
|
|
|
2012-11-29 18:19:41 +01:00
|
|
|
void DropboxAuthenticator::StartAuthorisation() {
|
2012-11-29 17:03:52 +01:00
|
|
|
QUrl url(kRequestTokenEndpoint);
|
2012-11-29 18:43:56 +01:00
|
|
|
QByteArray authorisation_header = GenerateAuthorisationHeader(
|
|
|
|
QString::null, QString::null);
|
2012-11-29 17:03:52 +01:00
|
|
|
QNetworkRequest request(url);
|
2012-11-29 18:43:56 +01:00
|
|
|
request.setRawHeader("Authorization", authorisation_header);
|
2012-11-29 17:03:52 +01:00
|
|
|
|
|
|
|
QNetworkReply* reply = network_->post(request, QByteArray());
|
|
|
|
NewClosure(reply, SIGNAL(finished()),
|
|
|
|
this, SLOT(RequestTokenFinished(QNetworkReply*)), reply);
|
|
|
|
}
|
|
|
|
|
2012-11-29 17:46:37 +01:00
|
|
|
namespace {
|
|
|
|
|
|
|
|
// Parse a string like a=b&c=d into a map.
|
|
|
|
QMap<QString, QString> ParseParamList(const QString& params) {
|
|
|
|
QMap<QString, QString> ret;
|
|
|
|
QStringList components = params.split("&");
|
2012-11-29 17:28:47 +01:00
|
|
|
foreach (const QString& component, components) {
|
|
|
|
QStringList pairs = component.split("=");
|
|
|
|
if (pairs.size() != 2) {
|
|
|
|
continue;
|
|
|
|
}
|
2012-11-29 17:46:37 +01:00
|
|
|
ret[pairs[0]] = pairs[1];
|
2012-11-29 17:28:47 +01:00
|
|
|
}
|
2012-11-29 17:46:37 +01:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void DropboxAuthenticator::RequestTokenFinished(QNetworkReply* reply) {
|
|
|
|
reply->deleteLater();
|
|
|
|
QString result = reply->readAll();
|
|
|
|
QMap<QString, QString> params = ParseParamList(result);
|
2012-11-29 17:28:47 +01:00
|
|
|
token_ = params["oauth_token"];
|
|
|
|
secret_ = params["oauth_token_secret"];
|
|
|
|
Authorise();
|
|
|
|
}
|
|
|
|
|
|
|
|
void DropboxAuthenticator::Authorise() {
|
2012-11-30 14:40:54 +01:00
|
|
|
LocalRedirectServer* server = new LocalRedirectServer(this);
|
|
|
|
server->Listen();
|
2012-11-29 17:28:47 +01:00
|
|
|
|
2012-11-30 14:40:54 +01:00
|
|
|
NewClosure(server, SIGNAL(Finished()),
|
|
|
|
this, SLOT(RedirectArrived(LocalRedirectServer*)), server);
|
2012-11-29 17:28:47 +01:00
|
|
|
|
|
|
|
QUrl url(kAuthoriseEndpoint);
|
|
|
|
url.addQueryItem("oauth_token", token_);
|
2012-11-30 14:40:54 +01:00
|
|
|
url.addQueryItem("oauth_callback", server->url().toString());
|
2012-11-29 17:28:47 +01:00
|
|
|
|
|
|
|
QDesktopServices::openUrl(url);
|
|
|
|
}
|
|
|
|
|
2012-11-30 14:40:54 +01:00
|
|
|
void DropboxAuthenticator::RedirectArrived(LocalRedirectServer* server) {
|
|
|
|
server->deleteLater();
|
|
|
|
QUrl request_url = server->request_url();
|
|
|
|
qLog(Debug) << Q_FUNC_INFO << request_url;
|
|
|
|
uid_ = request_url.queryItemValue("uid");
|
|
|
|
RequestAccessToken();
|
2012-11-29 17:28:47 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void DropboxAuthenticator::RequestAccessToken() {
|
|
|
|
QUrl url(kAccessTokenEndpoint);
|
|
|
|
QNetworkRequest request(url);
|
2012-11-29 18:43:56 +01:00
|
|
|
QByteArray authorisation_header = GenerateAuthorisationHeader(
|
|
|
|
token_, secret_);
|
|
|
|
request.setRawHeader("Authorization", authorisation_header);
|
2012-11-29 17:28:47 +01:00
|
|
|
|
|
|
|
QNetworkReply* reply = network_->post(request, QByteArray());
|
|
|
|
NewClosure(reply, SIGNAL(finished()),
|
|
|
|
this, SLOT(RequestAccessTokenFinished(QNetworkReply*)), reply);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DropboxAuthenticator::RequestAccessTokenFinished(QNetworkReply* reply) {
|
2012-11-29 17:46:37 +01:00
|
|
|
reply->deleteLater();
|
|
|
|
QString result = QString::fromAscii(reply->readAll());
|
|
|
|
qLog(Debug) << result;
|
|
|
|
QMap<QString, QString> params = ParseParamList(result);
|
|
|
|
access_token_ = params["oauth_token"];
|
|
|
|
access_token_secret_ = params["oauth_token_secret"];
|
|
|
|
qLog(Debug) << Q_FUNC_INFO << access_token_ << access_token_secret_;
|
|
|
|
RequestAccountInformation();
|
|
|
|
}
|
|
|
|
|
|
|
|
QByteArray DropboxAuthenticator::GenerateAuthorisationHeader() {
|
2012-11-29 18:43:56 +01:00
|
|
|
return GenerateAuthorisationHeader(access_token_, access_token_secret_);
|
|
|
|
}
|
|
|
|
|
|
|
|
QByteArray DropboxAuthenticator::GenerateAuthorisationHeader(
|
|
|
|
const QString& token,
|
|
|
|
const QString& token_secret) {
|
2012-11-29 17:46:37 +01:00
|
|
|
typedef QPair<QString, QString> Param;
|
|
|
|
QByteArray signature = QUrl::toPercentEncoding(
|
2012-11-29 18:43:56 +01:00
|
|
|
QString("%1&%2").arg(kAppSecret, token_secret));
|
2012-11-29 17:46:37 +01:00
|
|
|
QList<Param> params;
|
|
|
|
params << Param("oauth_consumer_key", kAppKey)
|
|
|
|
<< Param("oauth_signature_method", "PLAINTEXT")
|
|
|
|
<< Param("oauth_timestamp", QString::number(time(NULL)))
|
|
|
|
<< Param("oauth_nonce", QString::number(qrand()))
|
2012-11-29 18:43:56 +01:00
|
|
|
<< Param("oauth_signature", signature);
|
|
|
|
if (!token.isNull()) {
|
|
|
|
params << Param("oauth_token", token);
|
|
|
|
}
|
2012-11-29 17:46:37 +01:00
|
|
|
QStringList encoded_params;
|
|
|
|
foreach (const Param& p, params) {
|
|
|
|
encoded_params << QString("%1=\"%2\"").arg(p.first, p.second);
|
|
|
|
}
|
|
|
|
QString authorisation_header = QString("OAuth ") + encoded_params.join(", ");
|
|
|
|
return authorisation_header.toUtf8();
|
|
|
|
}
|
|
|
|
|
|
|
|
void DropboxAuthenticator::RequestAccountInformation() {
|
|
|
|
QUrl url(kAccountInfoEndpoint);
|
|
|
|
QNetworkRequest request(url);
|
|
|
|
request.setRawHeader("Authorization", GenerateAuthorisationHeader());
|
|
|
|
qLog(Debug) << Q_FUNC_INFO << url << request.rawHeader("Authorization");
|
|
|
|
QNetworkReply* reply = network_->get(request);
|
|
|
|
NewClosure(reply, SIGNAL(finished()),
|
|
|
|
this, SLOT(RequestAccountInformationFinished(QNetworkReply*)), reply);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DropboxAuthenticator::RequestAccountInformationFinished(QNetworkReply* reply) {
|
|
|
|
reply->deleteLater();
|
2012-11-29 17:53:37 +01:00
|
|
|
QJson::Parser parser;
|
|
|
|
QVariantMap response = parser.parse(reply).toMap();
|
|
|
|
name_ = response["display_name"].toString();
|
2012-11-29 18:19:41 +01:00
|
|
|
emit Finished();
|
2012-11-29 17:03:52 +01:00
|
|
|
}
|