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"
36 FacebookAuthentication::FacebookAuthentication(QWidget *parent)
37 : QMainWindow(parent),
43 qDebug() << __PRETTY_FUNCTION__;
45 m_mainlayout = new QHBoxLayout;
47 connect(this, SIGNAL(loginFailure()),
48 this, SLOT(loginFailed()));
50 readCredentials(m_loginCredentials);
53 FacebookAuthentication::~FacebookAuthentication()
55 qDebug() << __PRETTY_FUNCTION__;
60 void FacebookAuthentication::loginDialogDone(const QString &email, const QString &password)
62 qDebug() << __PRETTY_FUNCTION__;
65 m_password = password;
68 void FacebookAuthentication::start()
70 qDebug() << __PRETTY_FUNCTION__;
71 if (!verifyCredentials(m_loginCredentials)){
73 m_webView = new QWebView(this);
74 m_loginDialog = new LoginDialog(this);
76 connect(m_webView, SIGNAL(urlChanged(const QUrl &)),
77 this, SLOT(updateCredentials(const QUrl &)));
78 connect(m_webView, SIGNAL(loadFinished(bool)),
79 this, SLOT(loadDone(bool)));
81 connect(m_loginDialog, SIGNAL(loginDialogDone(QString,QString)),
82 this, SLOT(loginDialogDone(QString,QString)));
84 if(m_loginDialog->exec() != QDialog::Accepted) {
85 // if login dialog was canceled we need to stop processing webview
86 // stop and disconnect m_webView;
88 disconnect(m_webView, SIGNAL(loadFinished(bool)),
89 this, SLOT(loadDone(bool)));
90 disconnect(m_webView, SIGNAL(urlChanged(const QUrl &)),
91 this, SLOT(updateCredentials(const QUrl &)));
96 list.append(FACEBOOK_LOGINBASE);
97 list.append(SITUARE_PUBLIC_FACEBOOKAPI_KEY);
98 list.append(INTERVAL1);
99 list.append(SITUARE_LOGIN_SUCCESS);
100 list.append(INTERVAL2);
101 list.append(SITUARE_LOGIN_FAILURE);
102 list.append(FACEBOOK_LOGIN_ENDING);
104 m_webView->load(formLoginPageUrl(list));
105 toggleProgressIndicator(true);
107 setCentralWidget(m_webView);
112 emit credentialsReady(m_loginCredentials);
115 void FacebookAuthentication::loadDone(bool done)
117 qDebug() << __PRETTY_FUNCTION__;
119 // for the first time the login page is opened, we need to refresh it to get cookies working
122 list.append(FACEBOOK_LOGINBASE);
123 list.append(SITUARE_PUBLIC_FACEBOOKAPI_KEY);
124 list.append(INTERVAL1);
125 list.append(SITUARE_LOGIN_SUCCESS);
126 list.append(INTERVAL2);
127 list.append(SITUARE_LOGIN_FAILURE);
128 list.append(FACEBOOK_LOGIN_ENDING);
130 m_webView->load(formLoginPageUrl(list));
136 QWebFrame* frame = m_webView->page()->currentFrame();
140 QWebElementCollection emailCollection = frame->findAllElements("input[name=email]");
142 foreach (QWebElement element, emailCollection) {
143 element.setAttribute("value", m_email.toAscii());
146 QWebElementCollection passwordCollection = frame->findAllElements("input[name=pass]");
147 foreach (QWebElement element, passwordCollection) {
148 element.setAttribute("value", m_password.toAscii());
150 // find connect button
151 QWebElementCollection buttonCollection = frame->findAllElements("input[name=login]");
152 foreach (QWebElement element, buttonCollection)
154 QPoint pos(element.geometry().center());
156 // send a mouse click event to the web page
157 QMouseEvent event0(QEvent::MouseButtonPress, pos, Qt::LeftButton, Qt::LeftButton,
159 QApplication::sendEvent(m_webView->page(), &event0);
160 QMouseEvent event1(QEvent::MouseButtonRelease, pos, Qt::LeftButton, Qt::LeftButton,
162 QApplication::sendEvent(m_webView->page(), &event1);
168 void FacebookAuthentication::loginFailed()
170 qDebug() << __PRETTY_FUNCTION__;
175 toggleProgressIndicator(false);
178 QMaemo5InformationBox::information(this, tr("Invalid E-mail address or password"),
179 QMaemo5InformationBox::NoTimeout);
181 #endif // Q_WS_MAEMO_5
183 if(m_loginDialog->exec() != QDialog::Accepted) {
184 // if login dialog was canceled we need to stop processing webview
185 // stop and disconnect m_webView;
187 disconnect(m_webView, SIGNAL(loadFinished(bool)),
188 this, SLOT(loadDone(bool)));
189 disconnect(m_webView, SIGNAL(urlChanged(const QUrl &)),
190 this, SLOT(updateCredentials(const QUrl &)));
195 // re-load login page for webview
196 toggleProgressIndicator(true);
198 list.append(FACEBOOK_LOGINBASE);
199 list.append(SITUARE_PUBLIC_FACEBOOKAPI_KEY);
200 list.append(INTERVAL1);
201 list.append(SITUARE_LOGIN_SUCCESS);
202 list.append(INTERVAL2);
203 list.append(SITUARE_LOGIN_FAILURE);
204 list.append(FACEBOOK_LOGIN_ENDING);
206 m_webView->load(formLoginPageUrl(list));
210 bool FacebookAuthentication::updateCredentials(const QUrl &url)
212 qDebug() << __PRETTY_FUNCTION__;
217 qDebug() << "url is valid";
219 QString callbackUrl = url.toString();
220 qDebug() << "callbackUrl: " << callbackUrl.toAscii();
222 if (callbackUrl.indexOf(LOGIN_SUCCESS_REPLY) == 0) {
223 qDebug() << "login success";
225 disconnect(m_webView, SIGNAL(loadFinished(bool)),
226 this, SLOT(loadDone(bool)));
227 disconnect(m_webView, SIGNAL(urlChanged(const QUrl &)),
228 this, SLOT(updateCredentials(const QUrl &)));
230 // let's find out session credentials
231 if(callbackUrl.contains(SESSION_KEY)) {
233 QJson::Parser parser;
236 // split string into string part and json part
237 QStringList list = url.toString().split("=");
239 for(int i=0;i<list.count();i++) {
240 // if string starts with json item
241 if(list.at(i).startsWith("{")) {
242 QByteArray jsonString = list.at(i).toAscii();
243 QVariantMap result = parser.parse (jsonString, &ok).toMap();
246 qFatal("An error occurred during parsing");
249 qDebug() << "Session Key" << result[SESSION_KEY].toString();
250 m_loginCredentials.setSessionKey(result[SESSION_KEY].toString());
252 qDebug() << "userID" << result[USER_ID].toString();
253 m_loginCredentials.setUserID(result[USER_ID].toString());
255 qDebug() << "Expires" << result[EXPIRES].toString();
256 m_loginCredentials.setExpires(result[EXPIRES].toString());
258 qDebug() << "Session Secret" << result[SESSION_SECRET].toString();
259 m_loginCredentials.setSessionSecret(result[SESSION_SECRET].toString());
261 qDebug() << "Signature" << result[SIGNATURE].toString();
262 m_loginCredentials.setSig(result[SIGNATURE].toString());
267 writeCredentials(m_loginCredentials);
268 emit credentialsReady(m_loginCredentials);
270 else if ( callbackUrl.indexOf(LOGIN_FAILURE_REPLY) == 0){
271 qWarning() << "login failure" << endl;
272 qDebug() << callbackUrl;
274 /* emit loginFailure for every second login attemps, since webview loads login
275 error page (loadingDone() signal is emitted) and we need to avoid that because
276 at this point we don't have new login parameters */
277 if(m_loginAttempts % 2) {
281 else if(callbackUrl.indexOf(LOGIN_PAGE) == 0) {
282 qDebug() << "correct loginPage";
285 qDebug() << "totally wrong webPage";
286 // we should not get a wrong page at this point
291 qDebug() << " Loading of page failed invalid URL" << endl;
292 // we should not get a wrong page at this point
299 void FacebookAuthentication::writeCredentials(const FacebookCredentials &credentials)
301 qDebug() << __PRETTY_FUNCTION__;
302 QSettings settings(DIRECTORY_NAME, FILE_NAME);
304 settings.setValue(SESSION_KEY, credentials.sessionKey());
305 settings.setValue(USER_ID, credentials.userID());
306 settings.setValue(EXPIRES, credentials.expires());
307 settings.setValue(SESSION_SECRET, credentials.sessionSecret());
308 settings.setValue(SIGNATURE, credentials.sig());
311 void FacebookAuthentication::readCredentials(FacebookCredentials &credentialsFromFile)
313 qDebug() << __PRETTY_FUNCTION__;
315 QSettings settings(DIRECTORY_NAME, FILE_NAME);
317 credentialsFromFile.setSessionKey(settings.value(SESSION_KEY, ERROR).toString());
318 credentialsFromFile.setUserID(settings.value(USER_ID, ERROR).toString());
319 credentialsFromFile.setExpires(settings.value(EXPIRES, ERROR).toString());
320 credentialsFromFile.setSessionSecret(settings.value(SESSION_SECRET, ERROR).toString());
321 credentialsFromFile.setSig(settings.value(SIGNATURE, ERROR).toString());
324 FacebookCredentials FacebookAuthentication::loginCredentials() const
326 qDebug() << __PRETTY_FUNCTION__;
327 return m_loginCredentials;
330 bool FacebookAuthentication::verifyCredentials(const FacebookCredentials &credentials) const
332 qDebug() << __PRETTY_FUNCTION__;
334 // if expires value is 0, then credentials are valid forever
335 if(credentials.expires() == "0") {
339 const QString dateTimeFormat = "dd.MM.yyyy hh:mm:ss";
340 QString expires = credentials.expires();
341 QDateTime expireTime;
342 expireTime.setTime_t(expires.toInt());
343 QString expiresString = expireTime.toString(dateTimeFormat);
344 qDebug() << expiresString.toAscii();
346 QDateTime currentTime;
347 currentTime = QDateTime::currentDateTime();
348 QString currentTimeString = currentTime.toString(dateTimeFormat);
349 qDebug() << currentTimeString.toAscii();
351 return currentTime < expireTime;
355 QUrl FacebookAuthentication::formLoginPageUrl(const QStringList &urlParts) const
357 qDebug() << __PRETTY_FUNCTION__;
359 return QUrl(urlParts.join(EMPTY));
362 void FacebookAuthentication::toggleProgressIndicator(bool value)
364 qDebug() << __PRETTY_FUNCTION__;
366 setAttribute(Qt::WA_Maemo5ShowProgressIndicator, value);
369 #endif // Q_WS_MAEMO_5