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 "facebookauthentication.h"
33 #include "facebookcommon.h"
35 FacebookAuthentication::FacebookAuthentication(QWidget *parent)
38 qDebug() << __PRETTY_FUNCTION__;
45 m_loginDialog = new LoginDialog(this);
47 m_webView = new QWebView;
48 m_mainlayout = new QHBoxLayout;
50 m_facebookLoginPage = formLoginPage(FACEBOOK_LOGINBASE, SITUARE_PUBLIC_FACEBOOKAPI_KEY,
51 INTERVAL1, SITUARE_LOGIN_SUCCESS, INTERVAL2,
52 SITUARE_LOGIN_FAILURE, FACEBOOK_LOGIN_ENDING);
54 connect(m_webView, SIGNAL(urlChanged(const QUrl &)),
55 this, SLOT(updateCredentials(const QUrl &)));
56 connect(m_webView, SIGNAL(loadFinished(bool)),
57 this, SLOT(loadDone(bool)));
59 connect(m_loginDialog, SIGNAL(loginDialogDone(QString,QString)),
60 this, SLOT(loginDialogDone(QString,QString)));
62 connect(this, SIGNAL(loginFailure()),
63 this, SLOT(loginFailed()));
65 readCredentials(m_loginCredentials);
68 FacebookAuthentication::~FacebookAuthentication()
70 qDebug() << __PRETTY_FUNCTION__;
86 void FacebookAuthentication::loginDialogDone(const QString &email, const QString &password)
88 qDebug() << __PRETTY_FUNCTION__;
90 m_email.append(email);
91 m_password.append(password);
94 void FacebookAuthentication::start()
96 qDebug() << __PRETTY_FUNCTION__;
97 if (!verifyCredentials(m_loginCredentials)){
98 if(m_loginDialog->exec() != QDialog::Accepted) {
99 // if login dialog was canceled we need to stop processing webview
100 // stop and disconnect m_webView;
102 disconnect(m_webView, SIGNAL(loadFinished(bool)),
103 this, SLOT(loadDone(bool)));
104 disconnect(m_webView, SIGNAL(urlChanged(const QUrl &)),
105 this, SLOT(updateCredentials(const QUrl &)));
109 m_webView->setZoomFactor(FACEBOOK_LOGINPAGE_FONT_SIZE);
110 m_webView->load(m_facebookLoginPage);
111 this->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
127 m_webView->load(m_facebookLoginPage);
133 this->toggleProgressIndicator(false);
134 QWebFrame* frame = m_webView->page()->currentFrame();
138 QWebElementCollection emailCollection = frame->findAllElements("input[name=email]");
140 foreach (QWebElement element, emailCollection) {
141 element.setAttribute("value", m_email.toAscii());
144 QWebElementCollection passwordCollection = frame->findAllElements("input[name=pass]");
145 foreach (QWebElement element, passwordCollection) {
146 element.setAttribute("value", m_password.toAscii());
148 // find connect button
149 QWebElementCollection buttonCollection = frame->findAllElements("input[name=login]");
150 foreach (QWebElement element, buttonCollection)
152 QPoint pos(element.geometry().center());
154 // send a mouse click event to the web page
155 QMouseEvent event0(QEvent::MouseButtonPress, pos, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
156 QApplication::sendEvent(m_webView->page(), &event0);
157 QMouseEvent event1(QEvent::MouseButtonRelease, pos, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
158 QApplication::sendEvent(m_webView->page(), &event1);
164 void FacebookAuthentication::loginFailed()
166 qDebug() << __PRETTY_FUNCTION__;
172 QMaemo5InformationBox::information(this, tr("Invalid E-mail address or password"),
173 QMaemo5InformationBox::NoTimeout);
175 #endif // Q_WS_MAEMO_5
177 if(m_loginDialog->exec() != QDialog::Accepted) {
178 // if login dialog was canceled we need to stop processing webview
179 // stop and disconnect m_webView;
181 disconnect(m_webView, SIGNAL(loadFinished(bool)),
182 this, SLOT(loadDone(bool)));
183 disconnect(m_webView, SIGNAL(urlChanged(const QUrl &)),
184 this, SLOT(updateCredentials(const QUrl &)));
189 // re-load login page for webview
190 this->toggleProgressIndicator(true);
191 m_webView->setZoomFactor(FACEBOOK_LOGINPAGE_FONT_SIZE);
192 m_webView->load(m_facebookLoginPage);
196 bool FacebookAuthentication::updateCredentials(const QUrl &url)
198 qDebug() << __PRETTY_FUNCTION__;
200 bool foundSessionKey = FALSE;
201 bool foundUserID = FALSE;
202 bool foundExpires = FALSE;
203 bool foundSessionSecret = FALSE;
204 bool foundSig = FALSE;
207 qDebug() << "url is valid" << endl;
209 QString callbackUrl = url.toString();
210 QString urlEdit(callbackUrl);
211 qDebug() << "callbackUrl: " << endl << callbackUrl.toAscii() << endl;
213 if ( callbackUrl.indexOf(LOGIN_SUCCESS_REPLY) == 0 ){
214 qDebug() << "login success" << endl;
216 disconnect(m_webView, SIGNAL(loadFinished(bool)),
217 this, SLOT(loadDone(bool)));
218 disconnect(m_webView, SIGNAL(urlChanged(const QUrl &)),
219 this, SLOT(updateCredentials(const QUrl &)));
221 // let's find out session key
222 int indexOfCredential = callbackUrl.indexOf(SESSION_KEY);
224 if (indexOfCredential != -1){
225 foundSessionKey = TRUE;
227 indexOfCredential += 14; //lenght of SESSION_KEY
228 urlEdit.remove(0,indexOfCredential);
229 indexOfCredential = urlEdit.indexOf(USER_ID);
230 urlEdit.remove(indexOfCredential, urlEdit.length());
231 urlEdit.remove("\",\"");
233 qDebug() << "Session Key" << endl << urlEdit.toAscii() << endl;
234 m_loginCredentials.setSessionKey(urlEdit);
237 // let's find out uid
238 urlEdit = callbackUrl;
239 indexOfCredential = callbackUrl.indexOf(USER_ID);
241 if (indexOfCredential != -1){
244 indexOfCredential += 5; //length of USER_ID:
245 urlEdit.remove(0,indexOfCredential);
246 indexOfCredential = urlEdit.indexOf(EXPIRES);
247 urlEdit.remove(indexOfCredential, urlEdit.length());
248 urlEdit.remove(",\"");
250 qDebug() << "userID" << endl << urlEdit.toAscii() << endl;
251 m_loginCredentials.setUserID(urlEdit);
254 // let's find out expires
255 urlEdit = callbackUrl;
256 indexOfCredential = callbackUrl.indexOf(EXPIRES);
258 if (indexOfCredential != -1){
261 indexOfCredential += 9; //length of EXPIRES
262 urlEdit.remove(0,indexOfCredential);
263 indexOfCredential = urlEdit.indexOf(SESSION_SECRET);
264 urlEdit.remove(indexOfCredential, urlEdit.length());
265 urlEdit.remove(",\"");
267 qDebug() << "Expires" << endl << urlEdit.toAscii() << endl;
268 m_loginCredentials.setExpires(urlEdit);
271 // let's find out sessionsecret
272 urlEdit = callbackUrl;
273 indexOfCredential = callbackUrl.indexOf(SESSION_SECRET);
275 if (indexOfCredential != -1){
276 foundSessionSecret = TRUE;
278 indexOfCredential += 9; //" length of SESSION_SECRET
279 urlEdit.remove(0,indexOfCredential);
280 indexOfCredential = urlEdit.indexOf(SIGNATURE);
281 urlEdit.remove(indexOfCredential, urlEdit.length());
282 urlEdit.remove("\",\"");
284 qDebug() << "Session Secret" << endl << urlEdit.toAscii() << endl;
285 m_loginCredentials.setSessionSecret(urlEdit);
288 // let's find out sig
289 urlEdit = callbackUrl;
290 indexOfCredential = callbackUrl.indexOf(SIGNATURE);
292 if (indexOfCredential != -1){
295 indexOfCredential += 6; //" length of SIGNATURE
296 urlEdit.remove(0,indexOfCredential);
297 urlEdit.remove("\"}");
299 qDebug() << "Signature" << endl << urlEdit.toAscii() << endl;
300 m_loginCredentials.setSig(urlEdit);
304 writeCredentials(m_loginCredentials);
305 emit credentialsReady(m_loginCredentials);
308 else if ( callbackUrl.indexOf(LOGIN_FAILURE_REPLY) == 0){
309 qWarning() << "login failure" << endl;
310 qDebug() << callbackUrl;
312 /* emit loginFailure for every second login attemps, since webview loads login
313 error page (loadingDone() signal is emitted) and we need to avoid that because
314 at this point we don't have new login parameters */
315 if(m_loginAttempts % 2) {
320 else if ( callbackUrl.indexOf(LOGIN_PAGE) == 0){
321 qDebug() << "correct loginPage";
325 qDebug() << "totally wrong webPage";
326 // we should not get a wrong page at this point
332 qDebug() << " Loading of page failed invalid URL" << endl;
333 // we should not get a wrong page at this point
338 return (foundSessionKey && foundUserID && foundExpires && foundSessionSecret && foundSig);
341 void FacebookAuthentication::writeCredentials(const FacebookCredentials &credentials)
343 qDebug() << __PRETTY_FUNCTION__;
344 QSettings settings(DIRECTORY_NAME, FILE_NAME);
346 settings.setValue("Session Key", credentials.sessionKey());
347 settings.setValue("User ID", credentials.userID());
348 settings.setValue("Expires", credentials.expires());
349 settings.setValue("Session Secret", credentials.sessionSecret());
350 settings.setValue("Sig", credentials.sig());
353 void FacebookAuthentication::readCredentials(FacebookCredentials &credentialsFromFile)
355 qDebug() << __PRETTY_FUNCTION__;
357 QSettings settings(DIRECTORY_NAME, FILE_NAME);
359 credentialsFromFile.setSessionKey(settings.value("Session Key", "Error").toString());
360 credentialsFromFile.setUserID(settings.value("User ID", "Error").toString());
361 credentialsFromFile.setExpires(settings.value("Expires", "Error").toString());
362 credentialsFromFile.setSessionSecret(settings.value("Session Secret", "Error").toString());
363 credentialsFromFile.setSig(settings.value("Sig", "Error").toString());
366 FacebookCredentials FacebookAuthentication::loginCredentials() const
368 qDebug() << __PRETTY_FUNCTION__;
369 return m_loginCredentials;
372 bool FacebookAuthentication::verifyCredentials(const FacebookCredentials &credentials) const
374 qDebug() << __PRETTY_FUNCTION__;
376 // if expires value is 0, then credentials are valid forever
377 if(credentials.expires() == "0") {
381 QString expires = credentials.expires();
382 QDateTime expireTime;
383 expireTime.setTime_t(expires.toInt());
384 QString expiresString = expireTime.toString("dd.MM.yyyy hh:mm:ss");
385 qDebug() << expiresString.toAscii();
387 QDateTime currentTime;
388 currentTime = QDateTime::currentDateTime();
389 QString currentTimeString = currentTime.toString("dd.MM.yyyy hh:mm:ss");
390 qDebug() << currentTimeString.toAscii();
392 return currentTime < expireTime;
396 QString FacebookAuthentication::formLoginPage(const QString & part1, const QString & part2,
397 const QString & part3, const QString & part4,
398 const QString & part5, const QString & part6,
399 const QString & part7) const
402 loginPage.append(part1);
403 loginPage.append(part2);
404 loginPage.append(part3);
405 loginPage.append(part4);
406 loginPage.append(part5);
407 loginPage.append(part5);
408 loginPage.append(part6);
409 loginPage.append(part7);
414 void FacebookAuthentication::toggleProgressIndicator(bool value)
416 qDebug() << __PRETTY_FUNCTION__;
418 setAttribute(Qt::WA_Maemo5ShowProgressIndicator, value);
421 #endif // Q_WS_MAEMO_5