Final implementation of logout
[situare] / src / facebookservice / facebookauthentication.cpp
1 /*
2    Situare - A location system for Facebook
3    Copyright (C) 2010  Ixonos Plc. Authors:
4
5        Ville Tiensuu - ville.tiensuu@ixonos.com
6        Kaj Wallin - kaj.wallin@ixonos.com
7        Henri Lampela - henri.lampela@ixonos.com
8
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.
12
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.
17
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,
21    USA.
22 */
23
24 #include <QtDebug>
25 #include <QDateTime>
26 #include <QSettings>
27 #include <QStringList>
28 #include <QVariantMap>
29
30 #ifdef Q_WS_MAEMO_5
31 #include <QMaemo5InformationBox>
32 #endif // Q_WS_MAEMO_5
33
34 #include "facebookauthentication.h"
35 #include "facebookcommon.h"
36 #include "../common.h"
37 #include "parser.h"
38
39 FacebookAuthentication::FacebookAuthentication(QObject *parent)
40     : QObject(parent),
41     m_loginAttempts(0)
42
43 {
44     qDebug() << __PRETTY_FUNCTION__;
45
46     readCredentials(m_loginCredentials);
47 }
48
49 void FacebookAuthentication::start()
50 {
51     qDebug() << __PRETTY_FUNCTION__;
52
53     if (!verifyCredentials(m_loginCredentials)) {
54         QStringList list;
55         list.append(FACEBOOK_LOGINBASE);
56         list.append(SITUARE_PUBLIC_FACEBOOKAPI_KEY);
57         list.append(INTERVAL1);
58         list.append(SITUARE_LOGIN_SUCCESS);
59         list.append(INTERVAL2);
60         list.append(SITUARE_LOGIN_FAILURE);
61         list.append(FACEBOOK_LOGIN_ENDING);
62
63         emit newLoginRequest(formLoginPageUrl(list));
64     }
65     else {
66         emit credentialsReady(false, m_loginCredentials);
67     }
68
69 }
70
71 bool FacebookAuthentication::updateCredentials(const QUrl &url)
72 {
73     qDebug() << __PRETTY_FUNCTION__;
74
75     bool found = false;
76
77     if (url.isValid()){
78          qDebug() << "url is valid";
79
80         QString callbackUrl = url.toString();
81         qDebug() << "callbackUrl:  " << callbackUrl.toAscii();
82
83         if (callbackUrl.indexOf(LOGIN_SUCCESS_REPLY) == 0) {
84             qDebug() << "login success";
85
86             // let's find out session credentials
87             if(callbackUrl.contains(SESSION_KEY)) {
88
89                 QJson::Parser parser;
90                 bool ok;
91
92                 // split string into string part and json part
93                 QStringList list = url.toString().split("=");
94
95                 for(int i=0;i<list.count();i++) {
96                     // if string starts with json item
97                     if(list.at(i).startsWith("{")) {
98                         QByteArray jsonString = list.at(i).toAscii();
99                         QVariantMap result = parser.parse (jsonString, &ok).toMap();
100                         if (!ok) {
101
102                             qFatal("An error occurred during parsing");
103                             exit (1);
104                         }
105                         qDebug() << "Session Key" << result[SESSION_KEY].toString();
106                         m_loginCredentials.setSessionKey(result[SESSION_KEY].toString());
107
108 //                        // commeted out until qjson parser can handle 64-bit integers
109 //                        qDebug() << "userID" << result[USER_ID].toString();
110 //                        m_loginCredentials.setUserID(result[USER_ID].toString().toAscii());
111
112                         // dirty fix, get user id from session_key
113                         QStringList list = result[SESSION_KEY].toString().split("-");
114                         m_loginCredentials.setUserID(list.at(1));
115                         qDebug() << m_loginCredentials.userID();
116
117                         qDebug() << "Expires" << result[EXPIRES].toString();
118                         m_loginCredentials.setExpires(result[EXPIRES].toString());
119
120                         qDebug() << "Session Secret" << result[SESSION_SECRET].toString();
121                         m_loginCredentials.setSessionSecret(result[SESSION_SECRET].toString());
122
123                         qDebug() << "Signature" << result[SIGNATURE].toString();
124                         m_loginCredentials.setSig(result[SIGNATURE].toString());
125                     }
126                 }
127                 found = true;
128             }
129             writeCredentials(m_loginCredentials);
130             emit credentialsReady(true, m_loginCredentials);
131         }
132         else if ( callbackUrl.indexOf(LOGIN_FAILURE_REPLY) == 0){
133             qWarning() << "login failure" << endl;
134             qDebug() << callbackUrl;
135             ++m_loginAttempts;
136             /* emit loginFailure for every second login attemps, since webview loads login
137                error page (loadingDone() signal is emitted) and we need to avoid that because
138                at this point we don't have new login parameters */
139             if(m_loginAttempts % 2) {
140                 emit loginFailure();
141             }
142         }
143         else if(callbackUrl.indexOf(LOGIN_PAGE) == 0) {
144             qDebug() << "correct loginPage";
145         }
146         else {
147             qDebug() << "totally wrong webPage";
148             // we should not get a wrong page at this point
149             emit loginFailure();
150         }
151     }
152     else {
153         qDebug() << " Loading of page failed invalid URL" << endl;
154         // we should not get a wrong page at this point
155         emit loginFailure();
156         return false;
157     }
158     return found;
159 }
160
161 void FacebookAuthentication::writeCredentials(const FacebookCredentials &credentials)
162 {
163     qDebug() << __PRETTY_FUNCTION__;
164     QSettings settings(DIRECTORY_NAME, FILE_NAME);
165
166     settings.setValue(SESSION_KEY, credentials.sessionKey());
167     settings.setValue(USER_ID, credentials.userID());
168     settings.setValue(EXPIRES, credentials.expires());
169     settings.setValue(SESSION_SECRET, credentials.sessionSecret());
170     settings.setValue(SIGNATURE, credentials.sig());
171 }
172
173 void FacebookAuthentication::readCredentials(FacebookCredentials &credentialsFromFile)
174 {
175     qDebug() << __PRETTY_FUNCTION__;
176
177     QSettings settings(DIRECTORY_NAME, FILE_NAME);
178
179     credentialsFromFile.setSessionKey(settings.value(SESSION_KEY, ERROR).toString());
180     credentialsFromFile.setUserID(settings.value(USER_ID, ERROR).toString());
181     credentialsFromFile.setExpires(settings.value(EXPIRES, ERROR).toString());
182     credentialsFromFile.setSessionSecret(settings.value(SESSION_SECRET, ERROR).toString());
183     credentialsFromFile.setSig(settings.value(SIGNATURE, ERROR).toString());
184 }
185
186  FacebookCredentials FacebookAuthentication::loginCredentials() const
187  {
188      qDebug() << __PRETTY_FUNCTION__;
189      return m_loginCredentials;
190  }
191
192  bool FacebookAuthentication::verifyCredentials(const FacebookCredentials &credentials) const
193  {
194      qDebug() << __PRETTY_FUNCTION__;
195
196      // if expires value is 0, then credentials are valid forever
197      if(credentials.expires() == "0") {
198          return true;
199      }
200      else {
201          const QString dateTimeFormat = "dd.MM.yyyy  hh:mm:ss";
202          QString expires = credentials.expires();
203          QDateTime expireTime;
204          expireTime.setTime_t(expires.toInt());
205          QString expiresString = expireTime.toString(dateTimeFormat);
206          qDebug() << expiresString.toAscii();
207
208          QDateTime currentTime;
209          currentTime = QDateTime::currentDateTime();
210          QString currentTimeString = currentTime.toString(dateTimeFormat);
211          qDebug() << currentTimeString.toAscii();
212
213          return currentTime < expireTime;
214      }
215  }
216
217  QUrl FacebookAuthentication::formLoginPageUrl(const QStringList &urlParts) const
218  {
219     qDebug() << __PRETTY_FUNCTION__;
220
221     return QUrl(urlParts.join(EMPTY));
222  }
223
224  void FacebookAuthentication::saveUsername(const QString &username)
225  {
226      qDebug() << __PRETTY_FUNCTION__;
227
228      QSettings settings(DIRECTORY_NAME, FILE_NAME);
229      settings.setValue(USERNAME, username);
230  }
231
232  const QString FacebookAuthentication::loadUsername()
233  {
234      qDebug() << __PRETTY_FUNCTION__;
235
236      QSettings settings(DIRECTORY_NAME, FILE_NAME);
237      return settings.value(USERNAME, EMPTY).toString();
238  }
239
240  void FacebookAuthentication::clearAccountInformation(bool keepUsername)
241  {
242      qDebug() << __PRETTY_FUNCTION__;
243
244      m_loginCredentials.clearCredentials();
245      QSettings settings(DIRECTORY_NAME, FILE_NAME);
246      if(!keepUsername) {
247         settings.remove(USERNAME);
248      }
249      settings.remove(USER_ID);
250      settings.remove(SESSION_KEY);
251      settings.remove(SESSION_SECRET);
252      settings.remove(EXPIRES);
253      settings.remove(SIGNATURE);
254
255      emit credentialsChanged(m_loginCredentials);
256  }