|
1 /** |
|
2 * Copyright (c) 2010 Sasken Communication Technologies Ltd. |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of the "{License}" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "{LicenseUrl}". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Narasimhulu Kavadapu, Sasken Communication Technologies Ltd - Initial contribution |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * class to handle calls to rest Server API's |
|
16 */ |
|
17 |
|
18 #define EMULATORTESTING |
|
19 |
|
20 #include "requestSP.h" |
|
21 #include "sessionSP.h" |
|
22 #include "xmlParser.h" |
|
23 #include "errorCodes.h" |
|
24 |
|
25 #include <QNetworkRequest> |
|
26 #include <QXmlSimpleReader> |
|
27 #include <QXmlInputSource> |
|
28 #include <QCryptographicHash> |
|
29 #include <QtAlgorithms> |
|
30 #include <QDebug> |
|
31 #include <qnetworkproxy.h> |
|
32 |
|
33 /////////////////////////////////////////////////////////////////////////////////////////////////// |
|
34 // global |
|
35 |
|
36 static const QString kAPIVersion = "1.0"; |
|
37 static const QString kAPIFormat = "XML"; |
|
38 static const QString kStringBoundary = "3i2ndDfv2rTHiSisAbouNdArYfORhtTPEefj3q2f"; |
|
39 |
|
40 static const double kTimeoutInterval = 180.0; |
|
41 |
|
42 |
|
43 /////////////////////////////////////////////////////////////////////////////////////////////////// |
|
44 |
|
45 static bool caseInsensitiveLessThan(const QString &s1, const QString &s2) |
|
46 { |
|
47 return s1.toLower() < s2.toLower(); |
|
48 } |
|
49 |
|
50 /////////////////////////////////////////////////////////////////////////////////////////////////// |
|
51 // Static class functions |
|
52 |
|
53 FBRequest* FBRequest::request() |
|
54 { |
|
55 return FBRequest::requestWithSession(FBSession::session()); |
|
56 } |
|
57 |
|
58 FBRequest* FBRequest::requestWithSession (FBSession* aSession) |
|
59 { |
|
60 FBRequest* request = new FBRequest(aSession); |
|
61 return request; |
|
62 } |
|
63 |
|
64 /////////////////////////////////////////////////////////////////////////////////////////////////// |
|
65 // instance public functions |
|
66 FBRequest::FBRequest(FBSession* aSession) : iSession ( aSession ), iNetworkAccessManager ( this ) |
|
67 {} |
|
68 |
|
69 const QDateTime& FBRequest::timeStamp() const |
|
70 { |
|
71 return iTimestamp; |
|
72 } |
|
73 |
|
74 void FBRequest::connect() |
|
75 { |
|
76 qDebug()<<"Inside FBRequest::connect"; |
|
77 emit requestLoading(); |
|
78 |
|
79 |
|
80 |
|
81 QString url ; |
|
82 /*if (iMethod.length()) |
|
83 url = iUrl; |
|
84 else*/ |
|
85 url = generateGetURL(); |
|
86 |
|
87 qDebug() << "Complete URL : " << url; |
|
88 |
|
89 QNetworkRequest request; |
|
90 request.setUrl(QUrl(url)); |
|
91 |
|
92 /* from the Qt docs on QNetworkAccessManager: |
|
93 QNetworkAccessManager by default does not have a set cache. |
|
94 Qt provides a simple disk cache, QNetworkDiskCache, which can be used. |
|
95 |
|
96 However we will not use it.*/ |
|
97 |
|
98 request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::AlwaysNetwork); |
|
99 request.setAttribute(QNetworkRequest::CacheSaveControlAttribute, false); |
|
100 |
|
101 iTimestamp = QDateTime::currentDateTime(); |
|
102 |
|
103 if (iMethod.length()) |
|
104 { |
|
105 const QString contentType = "multipart/form-data; boundary=" + kStringBoundary; |
|
106 request.setRawHeader("Content-Type", contentType.toUtf8()); |
|
107 |
|
108 /* connect all signals from iNetWorkAccessManager to this */ |
|
109 QByteArray postBody ; |
|
110 generatePostBody (postBody); |
|
111 |
|
112 pbar = new progressbar; |
|
113 pbar->show(); |
|
114 |
|
115 #ifdef __WINSCW__ |
|
116 proxysettings(); |
|
117 #endif |
|
118 QNetworkReply* reply = iNetworkAccessManager.get(request); |
|
119 |
|
120 QObject::connect(reply, SIGNAL(finished()), this, SLOT(networkReplyFinished())); |
|
121 QObject::connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), |
|
122 this, SLOT(networkReplyError(QNetworkReply::NetworkError))); |
|
123 |
|
124 } |
|
125 } |
|
126 void FBRequest::proxysettings() |
|
127 { |
|
128 #ifdef EMULATORTESTING |
|
129 qDebug()<<"proxysettings"; |
|
130 |
|
131 // Reading the keys, CSM Stubbed - START |
|
132 QFile file("c://data//DoNotShare.txt"); |
|
133 if (!file.open(QIODevice::ReadOnly)) |
|
134 { |
|
135 qDebug()<<"File to read the windows username and password could not be opened, returning!!!"; |
|
136 return; |
|
137 } |
|
138 |
|
139 QByteArray arr = file.readAll(); |
|
140 QList<QByteArray> list = arr.split(' '); |
|
141 file.close(); |
|
142 |
|
143 QString username(list[0]); |
|
144 QString password(list[1]); |
|
145 |
|
146 QString httpProxy = "10.1.0.214";//ipwproxy.sasken.com |
|
147 QString httpPort = "3128"; |
|
148 |
|
149 QString httpUser =username;/* This could be taken thru an QDialog implmentation to remove the Hard coding */ |
|
150 QString httpPass =password;/* This could be taken thru an QDialog implmentation to remove the Hard coding */ |
|
151 |
|
152 /*==Classes used from Network Module==*/ |
|
153 QNetworkProxy proxy; |
|
154 |
|
155 proxy.setType(QNetworkProxy::HttpProxy); |
|
156 proxy.setHostName(httpProxy); |
|
157 proxy.setPort(httpPort.toInt()); |
|
158 proxy.setUser(httpUser); |
|
159 proxy.setPassword(httpPass); |
|
160 |
|
161 QNetworkProxy::setApplicationProxy(proxy); |
|
162 #endif |
|
163 } |
|
164 /////////////////////////////////////////////////////////////////////////////////////////////////// |
|
165 // instance private functions |
|
166 QString FBRequest::md5(const QString& aData) |
|
167 { |
|
168 QByteArray byteArray; |
|
169 byteArray.insert(0, aData.toUtf8()); |
|
170 |
|
171 QByteArray md5Hash = QCryptographicHash::hash(byteArray,QCryptographicHash::Md5 ).toHex(); |
|
172 QString returnString ( md5Hash ); |
|
173 |
|
174 return returnString; |
|
175 } |
|
176 |
|
177 bool FBRequest::isSpecialMethod() const { |
|
178 return ( iMethod.compare("facebook.auth.getSession", Qt::CaseInsensitive) == 0 |
|
179 || iMethod.compare("facebook.auth.createToken", Qt::CaseInsensitive) == 0 ); |
|
180 } |
|
181 |
|
182 QString FBRequest::urlForMethod (const QString& aMethod) const { |
|
183 |
|
184 return iSession->apiURL(); |
|
185 } |
|
186 |
|
187 QString FBRequest::generateGetURL() const |
|
188 { |
|
189 const QUrl url(iUrl); |
|
190 const QString queryPrefix = url.hasQuery() ? "&" : "?"; |
|
191 |
|
192 QStringList pairs; |
|
193 DictionaryIterator i(iParams); |
|
194 |
|
195 while (i.hasNext()) { |
|
196 i.next(); |
|
197 pairs << i.key().toUtf8() + "=" + i.value().toUtf8(); |
|
198 } |
|
199 |
|
200 return iUrl + queryPrefix + pairs.join("&"); |
|
201 } |
|
202 |
|
203 QString FBRequest::generateCallId() const { |
|
204 QDateTime dateTime = QDateTime::currentDateTime(); |
|
205 uint secs = dateTime.toTime_t(); |
|
206 QString result = QString::number(secs, 10); |
|
207 return result; |
|
208 } |
|
209 |
|
210 QString FBRequest::generateSig(Dictionary Params) |
|
211 { |
|
212 QString joined; |
|
213 QStringList keys = Params.keys(); |
|
214 |
|
215 qSort(keys.begin(), keys.end(), caseInsensitiveLessThan); |
|
216 |
|
217 QListIterator<QString> i(keys); |
|
218 |
|
219 joined.append(iSession->apiSecret().toUtf8()); |
|
220 |
|
221 while (i.hasNext()) |
|
222 { |
|
223 const QString key = i.next(); |
|
224 joined.append(key.toUtf8()); |
|
225 //joined.append("="); |
|
226 joined.append(Params.value(key).toUtf8()); |
|
227 } |
|
228 |
|
229 return md5(joined); |
|
230 } |
|
231 |
|
232 void FBRequest::generatePostBody( QByteArray& body ) |
|
233 { |
|
234 QString endLine = "\r\n--" + kStringBoundary + "\r\n"; |
|
235 body.append( "--" + kStringBoundary.toUtf8() + "\r\n" ) ; |
|
236 |
|
237 |
|
238 DictionaryIterator i (iParams); |
|
239 |
|
240 while (i.hasNext()) |
|
241 { |
|
242 i.next(); |
|
243 |
|
244 body.append("Content-Disposition: form-data; name=\"" + i.key().toUtf8() + "\"\r\n\r\n" ); |
|
245 body.append(i.value().toUtf8()); |
|
246 body.append(endLine.toUtf8()); |
|
247 } |
|
248 |
|
249 |
|
250 if (iDataParam.size()) |
|
251 { |
|
252 if (iDataParamPicture) |
|
253 { |
|
254 body.append("Content-Disposition: form-data; filename=\"photo\"\r\n" ); |
|
255 body.append("Content-Type: image/png\r\n\r\n" ); |
|
256 } |
|
257 else |
|
258 { |
|
259 body.append("Content-Disposition: form-data; filename=\"data\"\r\n"); |
|
260 body.append("Content-Type: content/unknown\r\n\r\n"); |
|
261 } |
|
262 |
|
263 body.append(iDataParam); |
|
264 body.append(endLine.toUtf8()); |
|
265 |
|
266 } |
|
267 } |
|
268 |
|
269 void FBRequest::handleResponseData( const QByteArray& aResponseData ) |
|
270 { |
|
271 qDebug()<<"Inside FBRequest::handleResponseData"; |
|
272 FBError error; |
|
273 QVariant result = parseXMLResponse( aResponseData, error); |
|
274 |
|
275 qDebug() << "parsed result : " << result; |
|
276 |
|
277 if (error.code() != 0) |
|
278 { |
|
279 emit requestFailedWithFlickrError(error); |
|
280 } |
|
281 else |
|
282 { |
|
283 emit requestDidLoad(result); |
|
284 } |
|
285 |
|
286 delete pbar; |
|
287 } |
|
288 |
|
289 void FBRequest::post( const QString& aUrl, const Dictionary& aParams) |
|
290 { |
|
291 iUrl = aUrl; |
|
292 iParams = aParams; |
|
293 |
|
294 iSession->send(this); |
|
295 } |
|
296 |
|
297 void FBRequest::cancel() |
|
298 { |
|
299 |
|
300 } |
|
301 |
|
302 |
|
303 void FBRequest::call (const QString& aMethod, const Dictionary& aParams) |
|
304 { |
|
305 qDebug()<<"Inside FBRequest::call"; |
|
306 QByteArray dataParams; |
|
307 callWithDataParams(aMethod, aParams, dataParams, false); |
|
308 |
|
309 } |
|
310 void FBRequest::callforToken () |
|
311 { |
|
312 |
|
313 iUrl = iSession->apiURL(); |
|
314 iMethod = "flickr.auth.getToken"; |
|
315 |
|
316 Dictionary params; |
|
317 params["method"] = iMethod; |
|
318 params["api_key"] = iSession->apiKey(); |
|
319 params["frob"] = iSession->frobKey(); |
|
320 |
|
321 // XXX: workaround what seems to be a Qt bug with the extras-devel libraries. |
|
322 QString signature = generateSig(params); |
|
323 |
|
324 params["api_sig"] = signature; |
|
325 |
|
326 iParams = params; |
|
327 // XXX: end workaround. |
|
328 |
|
329 iSession->send(this); |
|
330 } |
|
331 |
|
332 void FBRequest::callWithDataParams (const QString& aMethod, const Dictionary& aParams, const QByteArray& aDataParam, bool aDataParamPicture) |
|
333 { |
|
334 qDebug()<<"Inside FBRequest::callWithDataParams"; |
|
335 iUrl = urlForMethod(aMethod); |
|
336 iMethod = aMethod; |
|
337 iParams = aParams; |
|
338 iDataParam = aDataParam; |
|
339 iDataParamPicture = aDataParamPicture; |
|
340 |
|
341 |
|
342 iParams["method"] = iMethod; |
|
343 iParams["api_key"] = iSession->apiKey(); |
|
344 |
|
345 // XXX: workaround what seems to be a Qt bug with the extras-devel libraries. |
|
346 QString signature = generateSig(iParams); |
|
347 iParams["api_sig"] = signature; |
|
348 // XXX: end workaround. |
|
349 |
|
350 iSession->send(this); |
|
351 } |
|
352 |
|
353 |
|
354 QVariant FBRequest::parseXMLResponse ( const QByteArray& aResponseData, FBError& aError) |
|
355 { |
|
356 qDebug()<<"Inside FBRequest::parseXMLResponse"; |
|
357 QXmlInputSource input; |
|
358 input.setData(aResponseData); |
|
359 |
|
360 FBXMLHandler handler; |
|
361 QXmlSimpleReader parser; |
|
362 parser.setContentHandler(&handler); |
|
363 bool result = parser.parse(&input); |
|
364 |
|
365 QVariant rootObject = handler.rootObject(); |
|
366 |
|
367 |
|
368 if (handler.parseError() || !result) |
|
369 { |
|
370 aError.setCode( FBRESPONSE_PARSE_ERROR ); |
|
371 aError.setDescription("parser was unable to parse the xml response from facebook server."); |
|
372 |
|
373 return QVariant(); |
|
374 } |
|
375 else if (handler.rootName().compare("error_response")==0) |
|
376 { |
|
377 QVariantHash errorDict = rootObject.toHash(); |
|
378 |
|
379 bool result; |
|
380 int errorCode = errorDict.value("error_code").toInt(&result); |
|
381 |
|
382 aError.setCode( errorCode ); |
|
383 aError.setDescription( errorDict.value("error_msg").toString() ); |
|
384 |
|
385 return rootObject; |
|
386 } |
|
387 else |
|
388 { |
|
389 return rootObject; |
|
390 } |
|
391 |
|
392 } |
|
393 |
|
394 /////////////////////////////////////////////////////////////////////////////////////////////////// |
|
395 // instance provate slots |
|
396 void FBRequest::networkReplyError ( QNetworkReply::NetworkError aCode ) |
|
397 { |
|
398 emit requestFailedWithNetworkError(aCode ); |
|
399 } |
|
400 |
|
401 void FBRequest::networkReplyFinished () |
|
402 { |
|
403 qDebug()<<"Inside FBRequest::networkReplyFinished"; |
|
404 QNetworkReply* reply = static_cast<QNetworkReply*> ( sender() ); |
|
405 QByteArray responseData = reply->readAll(); |
|
406 |
|
407 qDebug() << "Response Data(QByteArray) : " << responseData; |
|
408 QString str(responseData); |
|
409 qDebug() << "Response Data(QString) : " << str; |
|
410 handleResponseData ( responseData ); |
|
411 |
|
412 } |