2 Situare - A location system for Facebook
3 Copyright (C) 2010 Ixonos Plc. Authors:
5 Ville Tiensuu - ville.tiensuu@ixonos.com
6 Kaj Wallin - kaj.wallin@ixonos.com
7 Henri Lampela - henri.lampela@ixonos.com
9 Situare is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License
11 version 2 as published by the Free Software Foundation.
13 Situare is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with Situare; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
29 #include <QMaemo5InformationBox>
30 #endif // Q_WS_MAEMO_5
32 #include "situarecommon.h"
33 #include "facebookauthentication.h"
34 #include "facebookcommon.h"
37 FacebookAuthentication::FacebookAuthentication(QWidget *parent)
38 : QMainWindow(parent),
45 qDebug() << __PRETTY_FUNCTION__;
47 m_mainlayout = new QHBoxLayout;
49 connect(this, SIGNAL(loginFailure()),
50 this, SLOT(loginFailed()));
52 readCredentials(m_loginCredentials);
55 FacebookAuthentication::~FacebookAuthentication()
57 qDebug() << __PRETTY_FUNCTION__;
65 void FacebookAuthentication::loginDialogDone(const QString &email, const QString &password)
67 qDebug() << __PRETTY_FUNCTION__;
70 m_password = password;
73 void FacebookAuthentication::start()
75 qDebug() << __PRETTY_FUNCTION__;
77 if (!verifyCredentials(m_loginCredentials)) {
79 m_webView = new QWebView;
80 m_loginDialog = new LoginDialog(this);
82 connect(m_webView, SIGNAL(urlChanged(const QUrl &)),
83 this, SLOT(updateCredentials(const QUrl &)));
84 connect(m_webView, SIGNAL(loadFinished(bool)),
85 this, SLOT(loadDone(bool)));
87 connect(m_loginDialog, SIGNAL(loginDialogDone(QString,QString)),
88 this, SLOT(loginDialogDone(QString,QString)));
90 if(m_loginDialog->exec() != QDialog::Accepted) {
91 // if login dialog was canceled we need to stop processing webview
92 // stop and disconnect m_webView;
94 disconnect(m_webView, SIGNAL(loadFinished(bool)),
95 this, SLOT(loadDone(bool)));
96 disconnect(m_webView, SIGNAL(urlChanged(const QUrl &)),
97 this, SLOT(updateCredentials(const QUrl &)));
102 list.append(FACEBOOK_LOGINBASE);
103 list.append(SITUARE_PUBLIC_FACEBOOKAPI_KEY);
104 list.append(INTERVAL1);
105 list.append(SITUARE_LOGIN_SUCCESS);
106 list.append(INTERVAL2);
107 list.append(SITUARE_LOGIN_FAILURE);
108 list.append(FACEBOOK_LOGIN_ENDING);
110 m_webView->load(formLoginPageUrl(list));
111 toggleProgressIndicator(true);
113 setCentralWidget(m_webView);
118 emit credentialsReady(m_loginCredentials);
121 void FacebookAuthentication::loadDone(bool done)
123 qDebug() << __PRETTY_FUNCTION__;
125 // for the first time the login page is opened, we need to refresh it to get cookies working
128 list.append(FACEBOOK_LOGINBASE);
129 list.append(SITUARE_PUBLIC_FACEBOOKAPI_KEY);
130 list.append(INTERVAL1);
131 list.append(SITUARE_LOGIN_SUCCESS);
132 list.append(INTERVAL2);
133 list.append(SITUARE_LOGIN_FAILURE);
134 list.append(FACEBOOK_LOGIN_ENDING);
136 m_webView->load(formLoginPageUrl(list));
142 QWebFrame* frame = m_webView->page()->currentFrame();
146 QWebElementCollection emailCollection = frame->findAllElements("input[name=email]");
148 foreach (QWebElement element, emailCollection) {
149 element.setAttribute("value", m_email.toAscii());
152 QWebElementCollection passwordCollection = frame->findAllElements("input[name=pass]");
153 foreach (QWebElement element, passwordCollection) {
154 element.setAttribute("value", m_password.toAscii());
156 // find connect button
157 QWebElementCollection buttonCollection = frame->findAllElements("input[name=login]");
158 foreach (QWebElement element, buttonCollection)
160 QPoint pos(element.geometry().center());
162 // send a mouse click event to the web page
163 QMouseEvent event0(QEvent::MouseButtonPress, pos, Qt::LeftButton, Qt::LeftButton,
165 QApplication::sendEvent(m_webView->page(), &event0);
166 QMouseEvent event1(QEvent::MouseButtonRelease, pos, Qt::LeftButton, Qt::LeftButton,
168 QApplication::sendEvent(m_webView->page(), &event1);
174 void FacebookAuthentication::loginFailed()
176 qDebug() << __PRETTY_FUNCTION__;
181 toggleProgressIndicator(false);
184 QMaemo5InformationBox::information(this, tr("Invalid E-mail address or password"),
185 QMaemo5InformationBox::NoTimeout);
187 #endif // Q_WS_MAEMO_5
189 if(m_loginDialog->exec() != QDialog::Accepted) {
190 // if login dialog was canceled we need to stop processing webview
191 // stop and disconnect m_webView;
193 disconnect(m_webView, SIGNAL(loadFinished(bool)),
194 this, SLOT(loadDone(bool)));
195 disconnect(m_webView, SIGNAL(urlChanged(const QUrl &)),
196 this, SLOT(updateCredentials(const QUrl &)));
201 // re-load login page for webview
202 toggleProgressIndicator(true);
204 list.append(FACEBOOK_LOGINBASE);
205 list.append(SITUARE_PUBLIC_FACEBOOKAPI_KEY);
206 list.append(INTERVAL1);
207 list.append(SITUARE_LOGIN_SUCCESS);
208 list.append(INTERVAL2);
209 list.append(SITUARE_LOGIN_FAILURE);
210 list.append(FACEBOOK_LOGIN_ENDING);
212 m_webView->load(formLoginPageUrl(list));
216 bool FacebookAuthentication::updateCredentials(const QUrl &url)
218 qDebug() << __PRETTY_FUNCTION__;
223 qDebug() << "url is valid";
225 QString callbackUrl = url.toString();
226 qDebug() << "callbackUrl: " << callbackUrl.toAscii();
228 if (callbackUrl.indexOf(LOGIN_SUCCESS_REPLY) == 0) {
229 qDebug() << "login success";
231 disconnect(m_webView, SIGNAL(loadFinished(bool)),
232 this, SLOT(loadDone(bool)));
233 disconnect(m_webView, SIGNAL(urlChanged(const QUrl &)),
234 this, SLOT(updateCredentials(const QUrl &)));
236 // let's find out session credentials
237 if(callbackUrl.contains(SESSION_KEY)) {
239 QJson::Parser parser;
242 // split string into string part and json part
243 QStringList list = url.toString().split("=");
245 for(int i=0;i<list.count();i++) {
246 // if string starts with json item
247 if(list.at(i).startsWith("{")) {
248 QByteArray jsonString = list.at(i).toAscii();
249 QVariantMap result = parser.parse (jsonString, &ok).toMap();
252 qFatal("An error occurred during parsing");
255 qDebug() << "Session Key" << result[SESSION_KEY].toString();
256 m_loginCredentials.setSessionKey(result[SESSION_KEY].toString());
258 qDebug() << "userID" << result[USER_ID].toString();
259 m_loginCredentials.setUserID(result[USER_ID].toString());
261 qDebug() << "Expires" << result[EXPIRES].toString();
262 m_loginCredentials.setExpires(result[EXPIRES].toString());
264 qDebug() << "Session Secret" << result[SESSION_SECRET].toString();
265 m_loginCredentials.setSessionSecret(result[SESSION_SECRET].toString());
267 qDebug() << "Signature" << result[SIGNATURE].toString();
268 m_loginCredentials.setSig(result[SIGNATURE].toString());
273 writeCredentials(m_loginCredentials);
274 emit credentialsReady(m_loginCredentials);
276 else if ( callbackUrl.indexOf(LOGIN_FAILURE_REPLY) == 0){
277 qWarning() << "login failure" << endl;
278 qDebug() << callbackUrl;
280 /* emit loginFailure for every second login attemps, since webview loads login
281 error page (loadingDone() signal is emitted) and we need to avoid that because
282 at this point we don't have new login parameters */
283 if(m_loginAttempts % 2) {
287 else if(callbackUrl.indexOf(LOGIN_PAGE) == 0) {
288 qDebug() << "correct loginPage";
291 qDebug() << "totally wrong webPage";
292 // we should not get a wrong page at this point
297 qDebug() << " Loading of page failed invalid URL" << endl;
298 // we should not get a wrong page at this point
305 void FacebookAuthentication::writeCredentials(const FacebookCredentials &credentials)
307 qDebug() << __PRETTY_FUNCTION__;
308 QSettings settings(DIRECTORY_NAME, FILE_NAME);
310 settings.setValue(SESSION_KEY, credentials.sessionKey());
311 settings.setValue(USER_ID, credentials.userID());
312 settings.setValue(EXPIRES, credentials.expires());
313 settings.setValue(SESSION_SECRET, credentials.sessionSecret());
314 settings.setValue(SIGNATURE, credentials.sig());
317 void FacebookAuthentication::readCredentials(FacebookCredentials &credentialsFromFile)
319 qDebug() << __PRETTY_FUNCTION__;
321 QSettings settings(DIRECTORY_NAME, FILE_NAME);
323 credentialsFromFile.setSessionKey(settings.value(SESSION_KEY, ERROR).toString());
324 credentialsFromFile.setUserID(settings.value(USER_ID, ERROR).toString());
325 credentialsFromFile.setExpires(settings.value(EXPIRES, ERROR).toString());
326 credentialsFromFile.setSessionSecret(settings.value(SESSION_SECRET, ERROR).toString());
327 credentialsFromFile.setSig(settings.value(SIGNATURE, ERROR).toString());
330 FacebookCredentials FacebookAuthentication::loginCredentials() const
332 qDebug() << __PRETTY_FUNCTION__;
333 return m_loginCredentials;
336 bool FacebookAuthentication::verifyCredentials(const FacebookCredentials &credentials) const
338 qDebug() << __PRETTY_FUNCTION__;
340 // if expires value is 0, then credentials are valid forever
341 if(credentials.expires() == "0") {
345 const QString dateTimeFormat = "dd.MM.yyyy hh:mm:ss";
346 QString expires = credentials.expires();
347 QDateTime expireTime;
348 expireTime.setTime_t(expires.toInt());
349 QString expiresString = expireTime.toString(dateTimeFormat);
350 qDebug() << expiresString.toAscii();
352 QDateTime currentTime;
353 currentTime = QDateTime::currentDateTime();
354 QString currentTimeString = currentTime.toString(dateTimeFormat);
355 qDebug() << currentTimeString.toAscii();
357 return currentTime < expireTime;
361 QUrl FacebookAuthentication::formLoginPageUrl(const QStringList &urlParts) const
363 qDebug() << __PRETTY_FUNCTION__;
365 return QUrl(urlParts.join(EMPTY));
368 void FacebookAuthentication::toggleProgressIndicator(bool value)
370 qDebug() << __PRETTY_FUNCTION__;
372 setAttribute(Qt::WA_Maemo5ShowProgressIndicator, value);
375 #endif // Q_WS_MAEMO_5