mirror of
https://bitbucket.org/smil3y/kde-extraapps.git
synced 2025-02-25 11:22:55 +00:00
218 lines
7.4 KiB
C++
218 lines
7.4 KiB
C++
/*
|
|
* Copyright 2012 Sebastian Kügler <sebas@kde.org>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU Library General Public License as
|
|
* published by the Free Software Foundation; either version 2 or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program 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 General Public License for more details
|
|
*
|
|
* You should have received a copy of the GNU Library General Public
|
|
* License along with this program; if not, write to the
|
|
* Free Software Foundation, Inc.,
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
/*
|
|
* QOAuth example
|
|
* http://blog.ayoy.net/2009/6/24/oauth
|
|
*
|
|
* Twitter OAuth Docs:
|
|
* https://dev.twitter.com/docs/auth/oauth
|
|
*
|
|
* How does OAuth work diagram:
|
|
* https://dev.twitter.com/sites/default/files/images_documentation/oauth_diagram.png
|
|
*
|
|
*
|
|
*/
|
|
|
|
#include <QUrl>
|
|
#include <KRun>
|
|
#include <KDialog>
|
|
|
|
#include <KWebView>
|
|
#include <KWebPage>
|
|
#include <QWebElement>
|
|
#include <QWebFrame>
|
|
#include <QWebPage>
|
|
#include <QNetworkAccessManager>
|
|
#include <QNetworkCookieJar>
|
|
|
|
#include "koauthwebhelper.h"
|
|
#include <KDebug>
|
|
|
|
namespace KOAuth {
|
|
|
|
class KOAuthWebHelperPrivate {
|
|
|
|
public:
|
|
KOAuthWebHelperPrivate()
|
|
{
|
|
webView = 0;
|
|
dialog = 0;
|
|
busy = false;
|
|
}
|
|
QString user;
|
|
QString password;
|
|
QString serviceBaseUrl;
|
|
QHash<QString, QString> authorizeUrls;
|
|
|
|
QWebView *webView;
|
|
KDialog *dialog;
|
|
bool busy;
|
|
QTimer *timer;
|
|
};
|
|
|
|
|
|
KOAuthWebHelper::KOAuthWebHelper(QObject* parent)
|
|
: QObject(parent),
|
|
d(new KOAuthWebHelperPrivate)
|
|
{
|
|
setObjectName(QLatin1String("QOAuthWebHelper"));
|
|
d->timer = new QTimer();
|
|
d->timer->setInterval(3000);
|
|
d->timer->setSingleShot(true);
|
|
connect(d->timer, SIGNAL(timeout()), SLOT(showDialog()));
|
|
}
|
|
|
|
KOAuthWebHelper::~KOAuthWebHelper()
|
|
{
|
|
kDebug();
|
|
delete d;
|
|
}
|
|
|
|
void KOAuthWebHelper::setUser(const QString& user)
|
|
{
|
|
d->user = user;
|
|
}
|
|
|
|
void KOAuthWebHelper::setPassword(const QString& password)
|
|
{
|
|
d->password = password;
|
|
}
|
|
|
|
void KOAuthWebHelper::setServiceBaseUrl(const QString &url)
|
|
{
|
|
d->serviceBaseUrl = url;
|
|
}
|
|
|
|
void KOAuthWebHelper::showDialog()
|
|
{
|
|
if (d->dialog) {
|
|
kDebug() << "Showing dialog for URL: " << d->webView->page()->mainFrame()->toHtml();
|
|
d->dialog->show();
|
|
}
|
|
}
|
|
|
|
void KOAuthWebHelper::authorizeApp(const QString &serviceBaseUrl, const QString &authorizeUrl, const QString &pageUrl)
|
|
{
|
|
Q_UNUSED(serviceBaseUrl);
|
|
Q_UNUSED(authorizeUrl);
|
|
if (d->serviceBaseUrl == "/" || d->serviceBaseUrl.isEmpty()) return;
|
|
if (!d->webView) {
|
|
d->dialog = new KDialog();
|
|
d->dialog->setCaption( "authorize application" );
|
|
d->dialog->setButtons( KDialog::Ok | KDialog::Cancel);
|
|
|
|
//d->webView = new KWebView(d->dialog, KWebPage::KIOIntegration);
|
|
d->webView = new QWebView(d->dialog);
|
|
d->dialog->setMainWidget(d->webView);
|
|
// d->dialog->show(); // remove
|
|
connect(d->webView->page(), SIGNAL(loadFinished(bool)), SLOT(loadFinished()));
|
|
}
|
|
|
|
// Set an empty cookiejar, we don't want to recycle already logged in users
|
|
QNetworkAccessManager *qnam = d->webView->page()->networkAccessManager();
|
|
QNetworkCookieJar *jar = new QNetworkCookieJar(this);
|
|
qnam->setCookieJar(jar);
|
|
d->authorizeUrls[authorizeUrl] = d->serviceBaseUrl;
|
|
d->webView->page()->mainFrame()->load(pageUrl);
|
|
}
|
|
|
|
bool KOAuthWebHelper::isIdentica()
|
|
{
|
|
return d->serviceBaseUrl.toLower().contains("identi.ca");
|
|
}
|
|
|
|
void KOAuthWebHelper::loadFinished()
|
|
{
|
|
QWebPage *page = dynamic_cast<QWebPage*>(sender());
|
|
if (!page) {
|
|
return;
|
|
}
|
|
|
|
QWebFrame* mf = page->mainFrame();
|
|
QString u = page->mainFrame()->url().toString();
|
|
if (d->authorizeUrls.contains(u)) {
|
|
QString pin;
|
|
foreach (const QWebElement &code, mf->findAllElements("CODE")) {
|
|
pin = code.toPlainText();
|
|
// kDebug() << "tag:" << code.tagName() << "PIN:" << pin;
|
|
};
|
|
|
|
foreach (const QWebElement &code, mf->findAllElements("#oauth_pin")) {
|
|
pin = code.toPlainText();
|
|
// kDebug() << "tag:" << code.tagName() << "PIN:" << pin;
|
|
};
|
|
if (!isIdentica() || !pin.isEmpty()) {
|
|
// kDebug() << "We're done!" << u << pin;
|
|
d->timer->stop(); // No need to show the dialog. :)
|
|
emit statusUpdated(d->user, d->serviceBaseUrl, "Busy", "Application authorized");
|
|
emit appAuthSucceeded(u, pin);
|
|
if (d->dialog) {
|
|
d->dialog->close();
|
|
}
|
|
return;
|
|
}
|
|
} else {
|
|
// The remote service challenges app authorization, this means that the
|
|
// user has to log in to the remote site to retrieve a PIN back, which
|
|
// in turn will produce the accessToken and accessTokenSecret pair in
|
|
// the next, final authorization step.
|
|
emit statusUpdated(d->user, d->serviceBaseUrl, "Waiting", "App Authorization needed");
|
|
|
|
// we have to log in, let's see if we can do that automatically...
|
|
|
|
// For Twitter, there are two cases:
|
|
// - the user is already logged in, we just have to click the accept button
|
|
// - the user is not logged in, in that case the user/password have to be
|
|
// be filled in. We happen to know that, as it's the argument to the "auth"
|
|
// operation in the dataengine.
|
|
// kDebug() << "logging in " << d->user << d->password;
|
|
if (!isIdentica()) {
|
|
// Try to fill in user/pass into the form
|
|
//kDebug() << "twitter.com hacks JavaScript hacks: " << u;
|
|
QString script = "var userName = document.getElementById(\"username_or_email\"); userName.value = \"" + d->user + "\";\n";
|
|
script.append("var passWord = document.getElementById(\"password\"); passWord.value = \"" + d->password + "\";\n");
|
|
mf->evaluateJavaScript(script);
|
|
//kDebug() << "ran script 1: " << script;
|
|
// Evaluate the button click separately, as the above script might abort,
|
|
// and not all lines are actually executed.
|
|
script = QString();
|
|
script.append("var ackButton = document.getElementById(\"allow\"); ackButton.click();");
|
|
mf->evaluateJavaScript(script);
|
|
//kDebug() << "ran script 2: " << script;
|
|
} else if (d->serviceBaseUrl.toLower().contains("identi.ca")) {
|
|
//kDebug() << "Identi.ca hacks JavaScript hacks";
|
|
QVariant r;
|
|
QString script = "var userName = document.getElementById(\"nickname\"); userName.value = \"" + d->user + "\";\n";
|
|
script.append("var passWord = document.getElementById(\"password\"); passWord.value = \"" + d->password + "\";\n");
|
|
r = mf->evaluateJavaScript(script);
|
|
kDebug() << "Ran script 1" << script << r;
|
|
// Evaluate the button click separately, as the above script might abort,
|
|
// and not all lines are actually executed.
|
|
script = "";
|
|
script.append("var ackButton = document.getElementById(\"allow_submit\"); ackButton.click();");
|
|
r = mf->evaluateJavaScript(script);
|
|
kDebug() << "Ran script 2" << script << r;
|
|
}
|
|
d->timer->start();
|
|
}
|
|
}
|
|
|
|
}
|
|
#include "koauthwebhelper.moc"
|