Destroy login browser after successfully logged in
[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 "parser.h"
25
26 #include <QtDebug>
27 #include <QDateTime>
28 #include <QSettings>
29 #include <QStringList>
30 #include <QVariantMap>
31
32 #ifdef Q_WS_MAEMO_5
33 #include <QMaemo5InformationBox>
34 #endif // Q_WS_MAEMO_5
35
36 #include "common.h"
37 #include "error.h"
38 #include "facebookcommon.h"
39
40 #include "facebookauthentication.h"
41
42 const QString REDIRECT_URI = "http://www.facebook.com/connect/login_success.html";
43
44 FacebookAuthentication::FacebookAuthentication(QObject *parent)
45     : QObject(parent),
46     m_freshLogin(false)
47 {
48     qDebug() << __PRETTY_FUNCTION__;
49
50 }
51
52 void FacebookAuthentication::clearAccountInformation(bool keepUsername)
53 {
54     qDebug() << __PRETTY_FUNCTION__;
55
56     m_loginCredentials.clearCredentials();
57     QSettings settings(DIRECTORY_NAME, FILE_NAME);
58
59     if(!keepUsername) {
60         settings.remove(USERNAME);
61         settings.remove(SETTINGS_AUTOMATIC_UPDATE_ENABLED);
62         settings.remove(SETTINGS_AUTOMATIC_UPDATE_INTERVAL);
63     }
64
65     settings.remove(COOKIES);
66     settings.remove(USER_UNSEND_MESSAGE);
67     settings.remove(USER_UNSEND_MESSAGE_PUBLISH);
68 }
69
70 void FacebookAuthentication::loadFinished(bool ok)
71 {
72     qWarning() << __PRETTY_FUNCTION__ << ok;
73
74     ///< @todo show browsed window if url != redirect url
75 }
76
77 const QString FacebookAuthentication::loadUsername()
78 {
79     qDebug() << __PRETTY_FUNCTION__;
80
81     QSettings settings(DIRECTORY_NAME, FILE_NAME);
82     return settings.value(USERNAME, EMPTY).toString();
83 }
84
85 FacebookCredentials FacebookAuthentication::loginCredentials() const
86 {
87     qDebug() << __PRETTY_FUNCTION__;
88     return m_loginCredentials;
89 }
90
91 QString FacebookAuthentication::parseAccessToken(const QUrl &url)
92 {
93     qWarning() << __PRETTY_FUNCTION__;
94
95     const QString ACCESS_TOKEN_PARAMETER("#access_token=");
96     const QString EXPIRATION_PARAMETER("&expires_in=");
97
98     QString urlString = url.toString();
99
100     int begin = urlString.indexOf(ACCESS_TOKEN_PARAMETER) + ACCESS_TOKEN_PARAMETER.length();
101     int end = urlString.indexOf(EXPIRATION_PARAMETER);
102
103     if ((begin > -1) && (end > begin))
104         return urlString.mid(begin, end - begin);
105     else
106         return QString();
107 }
108
109 void FacebookAuthentication::saveUsername(const QString &username)
110 {
111     qDebug() << __PRETTY_FUNCTION__;
112
113     QSettings settings(DIRECTORY_NAME, FILE_NAME);
114     settings.setValue(USERNAME, username);
115 }
116
117 void FacebookAuthentication::start()
118 {
119     qDebug() << __PRETTY_FUNCTION__;
120
121     QSettings settings(DIRECTORY_NAME, FILE_NAME);
122
123     QStringList cookies = settings.value(COOKIES).toStringList();
124     if(!cookies.isEmpty()) {
125         emit loginUsingCookies();
126     }
127     else {
128         m_freshLogin = true;
129         emit newLoginRequest();
130     }
131 }
132
133 bool FacebookAuthentication::updateCredentials(const QUrl &url)
134 {
135     qDebug() << __PRETTY_FUNCTION__ << url.toString();
136
137     bool found = false;
138
139     if (url.isValid()) {
140          qDebug() << "url is valid";
141
142         QString callbackUrl = url.toString();
143         qDebug() << "callbackUrl:  " << callbackUrl.toAscii();
144
145         if (callbackUrl.indexOf(LOGIN_SUCCESS_REPLY) == 0) {
146             qDebug() << "login success";
147
148             // let's find out session credentials
149             if(callbackUrl.contains(SESSION_KEY)) {
150
151                 QJson::Parser parser;
152                 bool ok;
153
154                 // split string into string part and json part
155                 QStringList list = url.toString().split("=");
156
157                 for(int i=0;i<list.count();i++) {
158                     // if string starts with json item
159                     if(list.at(i).startsWith("{")) {
160                         QByteArray jsonString = list.at(i).toAscii();
161                         QVariantMap result = parser.parse (jsonString, &ok).toMap();
162
163                         if (!ok) {
164                             emit error(ErrorContext::SITUARE, SituareError::INVALID_JSON);
165                             found = false;
166                         } else {
167                             qDebug() << "Session Key" << result[SESSION_KEY].toString();
168                             m_loginCredentials.setSessionKey(result[SESSION_KEY].toString());
169
170     //                        // commeted out until qjson parser can handle 64-bit integers
171     //                        qDebug() << "userID" << result[USER_ID].toString();
172     //                        m_loginCredentials.setUserID(result[USER_ID].toString().toAscii());
173
174                             // dirty fix, get user id from session_key
175                             QStringList list = result[SESSION_KEY].toString().split("-");
176                             m_loginCredentials.setUserID(list.at(1));
177                             qDebug() << m_loginCredentials.userID();
178
179                             qDebug() << "Expires" << result[EXPIRES].toString();
180                             m_loginCredentials.setExpires(result[EXPIRES].toString());
181
182                             qDebug() << "Session Secret" << result[SESSION_SECRET].toString();
183                             m_loginCredentials.setSessionSecret(result[SESSION_SECRET].toString());
184
185                             qDebug() << "Signature" << result[SIGNATURE].toString();
186                             m_loginCredentials.setSig(result[SIGNATURE].toString());
187
188                             found = true;
189                             m_freshLogin = false;
190                             emit saveCookiesRequest();
191                             emit credentialsReady(m_loginCredentials);
192                         }
193                     }
194                 }
195             }
196         } else if ( callbackUrl.indexOf(LOGIN_FAILURE_REPLY) == 0) {
197             qDebug() << "login failure";
198             qDebug() << callbackUrl;
199             clearAccountInformation(true);
200             if(m_freshLogin) {
201                 emit error(ErrorContext::SITUARE, SituareError::LOGIN_FAILED);
202             } else {
203                 m_freshLogin = true;
204                 emit error(ErrorContext::SITUARE, SituareError::SESSION_EXPIRED);
205             }
206         } else if(callbackUrl.indexOf(LOGIN_PAGE) == 0) {
207             qDebug() << "correct loginPage";
208         } else {
209             qDebug() << "totally wrong webPage";
210             // we should not get a wrong page at this point
211             emit error(ErrorContext::SITUARE, SituareError::LOGIN_FAILED);
212         }
213     } else {
214         qDebug() << " Loading of page failed invalid URL" << endl;
215         // we should not get a wrong page at this point
216         emit error(ErrorContext::SITUARE, SituareError::LOGIN_FAILED);
217     }
218     return found;
219 }
220
221 void FacebookAuthentication::urlChanged(const QUrl &url)
222 {
223     qWarning() << __PRETTY_FUNCTION__ << url.toString();
224
225     // if login succeeded
226     if (url.toString().startsWith(REDIRECT_URI)) {
227         const QString accessToken = parseAccessToken(url);
228         qWarning() << __PRETTY_FUNCTION__ << "parsed access token:" << accessToken;
229         if (!accessToken.isEmpty())
230             emit loggedIn(accessToken);
231     }
232 }