Changing to new authentication mechanism ongoing
[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     const QString BEGIN("session={");
109     const QString END("}");
110
111     QString urlString = url.toString();
112
113     int begin = urlString.indexOf(BEGIN);
114     int end = urlString.indexOf(END, begin);
115
116     if ((begin > -1) && (end > -1))
117         return urlString.mid(begin, end - begin +1);
118     else
119         return QString();
120 }
121
122 void FacebookAuthentication::saveUsername(const QString &username)
123 {
124     qDebug() << __PRETTY_FUNCTION__;
125
126     QSettings settings(DIRECTORY_NAME, FILE_NAME);
127     settings.setValue(USERNAME, username);
128 }
129
130 void FacebookAuthentication::start()
131 {
132     qDebug() << __PRETTY_FUNCTION__;
133
134     QSettings settings(DIRECTORY_NAME, FILE_NAME);
135
136     QStringList cookies = settings.value(COOKIES).toStringList();
137     if(!cookies.isEmpty()) {
138         emit loginUsingCookies();
139     }
140     else {
141         m_freshLogin = true;
142         emit newLoginRequest();
143     }
144 }
145
146 bool FacebookAuthentication::updateCredentials(const QUrl &url)
147 {
148     qDebug() << __PRETTY_FUNCTION__ << url.toString();
149
150     bool found = false;
151
152     if (url.isValid()) {
153          qDebug() << "url is valid";
154
155         QString callbackUrl = url.toString();
156         qDebug() << "callbackUrl:  " << callbackUrl.toAscii();
157
158         if (callbackUrl.indexOf(LOGIN_SUCCESS_REPLY) == 0) {
159             qDebug() << "login success";
160
161             // let's find out session credentials
162             if(callbackUrl.contains(SESSION_KEY)) {
163
164                 QJson::Parser parser;
165                 bool ok;
166
167                 // split string into string part and json part
168                 QStringList list = url.toString().split("=");
169
170                 for(int i=0;i<list.count();i++) {
171                     // if string starts with json item
172                     if(list.at(i).startsWith("{")) {
173                         QByteArray jsonString = list.at(i).toAscii();
174                         QVariantMap result = parser.parse (jsonString, &ok).toMap();
175
176                         if (!ok) {
177                             emit error(ErrorContext::SITUARE, SituareError::INVALID_JSON);
178                             found = false;
179                         } else {
180                             qDebug() << "Session Key" << result[SESSION_KEY].toString();
181                             m_loginCredentials.setSessionKey(result[SESSION_KEY].toString());
182
183     //                        // commeted out until qjson parser can handle 64-bit integers
184     //                        qDebug() << "userID" << result[USER_ID].toString();
185     //                        m_loginCredentials.setUserID(result[USER_ID].toString().toAscii());
186
187                             // dirty fix, get user id from session_key
188                             QStringList list = result[SESSION_KEY].toString().split("-");
189                             m_loginCredentials.setUserID(list.at(1));
190                             qDebug() << m_loginCredentials.userID();
191
192                             qDebug() << "Expires" << result[EXPIRES].toString();
193                             m_loginCredentials.setExpires(result[EXPIRES].toString());
194
195                             qDebug() << "Session Secret" << result[SESSION_SECRET].toString();
196                             m_loginCredentials.setSessionSecret(result[SESSION_SECRET].toString());
197
198                             qDebug() << "Signature" << result[SIGNATURE].toString();
199                             m_loginCredentials.setSig(result[SIGNATURE].toString());
200
201                             found = true;
202                             m_freshLogin = false;
203                             emit saveCookiesRequest();
204                             emit credentialsReady(m_loginCredentials);
205                         }
206                     }
207                 }
208             }
209         } else if ( callbackUrl.indexOf(LOGIN_FAILURE_REPLY) == 0) {
210             qDebug() << "login failure";
211             qDebug() << callbackUrl;
212             clearAccountInformation(true);
213             if(m_freshLogin) {
214                 emit error(ErrorContext::SITUARE, SituareError::LOGIN_FAILED);
215             } else {
216                 m_freshLogin = true;
217                 emit error(ErrorContext::SITUARE, SituareError::SESSION_EXPIRED);
218             }
219         } else if(callbackUrl.indexOf(LOGIN_PAGE) == 0) {
220             qDebug() << "correct loginPage";
221         } else {
222             qDebug() << "totally wrong webPage";
223             // we should not get a wrong page at this point
224             emit error(ErrorContext::SITUARE, SituareError::LOGIN_FAILED);
225         }
226     } else {
227         qDebug() << " Loading of page failed invalid URL" << endl;
228         // we should not get a wrong page at this point
229         emit error(ErrorContext::SITUARE, SituareError::LOGIN_FAILED);
230     }
231     return found;
232 }
233
234 void FacebookAuthentication::urlChanged(const QUrl &url)
235 {
236     qWarning() << __PRETTY_FUNCTION__ << url.toString();
237
238     // if login succeeded
239     if (url.toString().startsWith(REDIRECT_URI)) {
240         const QString accessToken = parseAccessToken(url);
241         qWarning() << __PRETTY_FUNCTION__ << "parsed access token:" << accessToken;
242         if (!accessToken.isEmpty())
243             emit loggedIn(accessToken);
244     }
245 }