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),
44 qDebug() << __PRETTY_FUNCTION__;
46 m_mainlayout = new QHBoxLayout;
48 connect(this, SIGNAL(loginFailure()),
49 this, SLOT(loginFailed()));
51 readCredentials(m_loginCredentials);
54 FacebookAuthentication::~FacebookAuthentication()
56 qDebug() << __PRETTY_FUNCTION__;
64 void FacebookAuthentication::loginDialogDone(const QString &email, const QString &password)
66 qDebug() << __PRETTY_FUNCTION__;
69 m_password = password;
72 void FacebookAuthentication::start()
74 qDebug() << __PRETTY_FUNCTION__;
76 if (!verifyCredentials(m_loginCredentials)) {
78 m_webView = new QWebView;
79 m_loginDialog = new LoginDialog(this);
81 connect(m_webView, SIGNAL(urlChanged(const QUrl &)),
82 this, SLOT(updateCredentials(const QUrl &)));
83 connect(m_webView, SIGNAL(loadFinished(bool)),
84 this, SLOT(loadDone(bool)));
86 connect(m_loginDialog, SIGNAL(loginDialogDone(QString,QString)),
87 this, SLOT(loginDialogDone(QString,QString)));
89 if(m_loginDialog->exec() != QDialog::Accepted) {
90 // if login dialog was canceled we need to stop processing webview
91 // stop and disconnect m_webView;
93 disconnect(m_webView, SIGNAL(loadFinished(bool)),
94 this, SLOT(loadDone(bool)));
95 disconnect(m_webView, SIGNAL(urlChanged(const QUrl &)),
96 this, SLOT(updateCredentials(const QUrl &)));
101 list.append(FACEBOOK_LOGINBASE);
102 list.append(SITUARE_PUBLIC_FACEBOOKAPI_KEY);
103 list.append(INTERVAL1);
104 list.append(SITUARE_LOGIN_SUCCESS);
105 list.append(INTERVAL2);
106 list.append(SITUARE_LOGIN_FAILURE);
107 list.append(FACEBOOK_LOGIN_ENDING);
109 m_webView->load(formLoginPageUrl(list));
110 toggleProgressIndicator(true);
112 setCentralWidget(m_webView);
117 emit credentialsReady(m_loginCredentials);
120 void FacebookAuthentication::loadDone(bool done)
122 qDebug() << __PRETTY_FUNCTION__;
124 // for the first time the login page is opened, we need to refresh it to get cookies working
127 list.append(FACEBOOK_LOGINBASE);
128 list.append(SITUARE_PUBLIC_FACEBOOKAPI_KEY);
129 list.append(INTERVAL1);
130 list.append(SITUARE_LOGIN_SUCCESS);
131 list.append(INTERVAL2);
132 list.append(SITUARE_LOGIN_FAILURE);
133 list.append(FACEBOOK_LOGIN_ENDING);
135 m_webView->load(formLoginPageUrl(list));
141 QWebFrame* frame = m_webView->page()->currentFrame();
145 QWebElementCollection emailCollection = frame->findAllElements("input[name=email]");
147 foreach (QWebElement element, emailCollection) {
148 element.setAttribute("value", m_email.toAscii());
151 QWebElementCollection passwordCollection = frame->findAllElements("input[name=pass]");
152 foreach (QWebElement element, passwordCollection) {
153 element.setAttribute("value", m_password.toAscii());
155 // find connect button
156 QWebElementCollection buttonCollection = frame->findAllElements("input[name=login]");
157 foreach (QWebElement element, buttonCollection)
159 QPoint pos(element.geometry().center());
161 // send a mouse click event to the web page
162 QMouseEvent event0(QEvent::MouseButtonPress, pos, Qt::LeftButton, Qt::LeftButton,
164 QApplication::sendEvent(m_webView->page(), &event0);
165 QMouseEvent event1(QEvent::MouseButtonRelease, pos, Qt::LeftButton, Qt::LeftButton,
167 QApplication::sendEvent(m_webView->page(), &event1);
173 void FacebookAuthentication::loginFailed()
175 qDebug() << __PRETTY_FUNCTION__;
180 toggleProgressIndicator(false);
183 QMaemo5InformationBox::information(this, tr("Invalid E-mail address or password"),
184 QMaemo5InformationBox::NoTimeout);
186 #endif // Q_WS_MAEMO_5
188 if(m_loginDialog->exec() != QDialog::Accepted) {
189 // if login dialog was canceled we need to stop processing webview
190 // stop and disconnect m_webView;
192 disconnect(m_webView, SIGNAL(loadFinished(bool)),
193 this, SLOT(loadDone(bool)));
194 disconnect(m_webView, SIGNAL(urlChanged(const QUrl &)),
195 this, SLOT(updateCredentials(const QUrl &)));
200 // re-load login page for webview
201 toggleProgressIndicator(true);
203 list.append(FACEBOOK_LOGINBASE);
204 list.append(SITUARE_PUBLIC_FACEBOOKAPI_KEY);
205 list.append(INTERVAL1);
206 list.append(SITUARE_LOGIN_SUCCESS);
207 list.append(INTERVAL2);
208 list.append(SITUARE_LOGIN_FAILURE);
209 list.append(FACEBOOK_LOGIN_ENDING);
211 m_webView->load(formLoginPageUrl(list));
215 bool FacebookAuthentication::updateCredentials(const QUrl &url)
217 qDebug() << __PRETTY_FUNCTION__;
222 qDebug() << "url is valid";
224 QString callbackUrl = url.toString();
225 qDebug() << "callbackUrl: " << callbackUrl.toAscii();
227 if (callbackUrl.indexOf(LOGIN_SUCCESS_REPLY) == 0) {
228 qDebug() << "login success";
230 disconnect(m_webView, SIGNAL(loadFinished(bool)),
231 this, SLOT(loadDone(bool)));
232 disconnect(m_webView, SIGNAL(urlChanged(const QUrl &)),
233 this, SLOT(updateCredentials(const QUrl &)));
235 // let's find out session credentials
236 if(callbackUrl.contains(SESSION_KEY)) {
238 QJson::Parser parser;
241 // split string into string part and json part
242 QStringList list = url.toString().split("=");
244 for(int i=0;i<list.count();i++) {
245 // if string starts with json item
246 if(list.at(i).startsWith("{")) {
247 QByteArray jsonString = list.at(i).toAscii();
248 QVariantMap result = parser.parse (jsonString, &ok).toMap();
251 qFatal("An error occurred during parsing");
254 qDebug() << "Session Key" << result[SESSION_KEY].toString();
255 m_loginCredentials.setSessionKey(result[SESSION_KEY].toString());
257 qDebug() << "userID" << result[USER_ID].toString();
258 m_loginCredentials.setUserID(result[USER_ID].toString());
260 qDebug() << "Expires" << result[EXPIRES].toString();
261 m_loginCredentials.setExpires(result[EXPIRES].toString());
263 qDebug() << "Session Secret" << result[SESSION_SECRET].toString();
264 m_loginCredentials.setSessionSecret(result[SESSION_SECRET].toString());
266 qDebug() << "Signature" << result[SIGNATURE].toString();
267 m_loginCredentials.setSig(result[SIGNATURE].toString());
272 writeCredentials(m_loginCredentials);
273 emit credentialsReady(m_loginCredentials);
275 else if ( callbackUrl.indexOf(LOGIN_FAILURE_REPLY) == 0){
276 qWarning() << "login failure" << endl;
277 qDebug() << callbackUrl;
279 /* emit loginFailure for every second login attemps, since webview loads login
280 error page (loadingDone() signal is emitted) and we need to avoid that because
281 at this point we don't have new login parameters */
282 if(m_loginAttempts % 2) {
286 else if(callbackUrl.indexOf(LOGIN_PAGE) == 0) {
287 qDebug() << "correct loginPage";
290 qDebug() << "totally wrong webPage";
291 // we should not get a wrong page at this point
296 qDebug() << " Loading of page failed invalid URL" << endl;
297 // we should not get a wrong page at this point
304 void FacebookAuthentication::writeCredentials(const FacebookCredentials &credentials)
306 qDebug() << __PRETTY_FUNCTION__;
307 QSettings settings(DIRECTORY_NAME, FILE_NAME);
309 settings.setValue(SESSION_KEY, credentials.sessionKey());
310 settings.setValue(USER_ID, credentials.userID());
311 settings.setValue(EXPIRES, credentials.expires());
312 settings.setValue(SESSION_SECRET, credentials.sessionSecret());
313 settings.setValue(SIGNATURE, credentials.sig());
316 void FacebookAuthentication::readCredentials(FacebookCredentials &credentialsFromFile)
318 qDebug() << __PRETTY_FUNCTION__;
320 QSettings settings(DIRECTORY_NAME, FILE_NAME);
322 credentialsFromFile.setSessionKey(settings.value(SESSION_KEY, ERROR).toString());
323 credentialsFromFile.setUserID(settings.value(USER_ID, ERROR).toString());
324 credentialsFromFile.setExpires(settings.value(EXPIRES, ERROR).toString());
325 credentialsFromFile.setSessionSecret(settings.value(SESSION_SECRET, ERROR).toString());
326 credentialsFromFile.setSig(settings.value(SIGNATURE, ERROR).toString());
329 FacebookCredentials FacebookAuthentication::loginCredentials() const
331 qDebug() << __PRETTY_FUNCTION__;
332 return m_loginCredentials;
335 bool FacebookAuthentication::verifyCredentials(const FacebookCredentials &credentials) const
337 qDebug() << __PRETTY_FUNCTION__;
339 // if expires value is 0, then credentials are valid forever
340 if(credentials.expires() == "0") {
344 const QString dateTimeFormat = "dd.MM.yyyy hh:mm:ss";
345 QString expires = credentials.expires();
346 QDateTime expireTime;
347 expireTime.setTime_t(expires.toInt());
348 QString expiresString = expireTime.toString(dateTimeFormat);
349 qDebug() << expiresString.toAscii();
351 QDateTime currentTime;
352 currentTime = QDateTime::currentDateTime();
353 QString currentTimeString = currentTime.toString(dateTimeFormat);
354 qDebug() << currentTimeString.toAscii();
356 return currentTime < expireTime;
360 QUrl FacebookAuthentication::formLoginPageUrl(const QStringList &urlParts) const
362 qDebug() << __PRETTY_FUNCTION__;
364 return QUrl(urlParts.join(EMPTY));
367 void FacebookAuthentication::toggleProgressIndicator(bool value)
369 qDebug() << __PRETTY_FUNCTION__;
371 setAttribute(Qt::WA_Maemo5ShowProgressIndicator, value);
374 #endif // Q_WS_MAEMO_5