|
1 /** |
|
2 This file is part of CWRT package ** |
|
3 |
|
4 Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** |
|
5 |
|
6 This program is free software: you can redistribute it and/or modify |
|
7 it under the terms of the GNU (Lesser) General Public License as |
|
8 published by the Free Software Foundation, version 2.1 of the License. |
|
9 This program is distributed in the hope that it will be useful, but |
|
10 WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
12 (Lesser) General Public License for more details. You should have |
|
13 received a copy of the GNU (Lesser) General Public License along |
|
14 with this program. If not, see <http://www.gnu.org/licenses/>. |
|
15 */ |
|
16 |
|
17 #include <qnetworkaccessmanager.h> |
|
18 #include <QNetworkReply> |
|
19 #include <QNetworkProxy> |
|
20 #include "downloadcore.h" |
|
21 |
|
22 // Http Headers |
|
23 #define RANGE_HEADER "Range" |
|
24 #define ETAG_HEADER "ETag" |
|
25 #define ECONTENT_DISPOSITION_HEADER "Content-Disposition" |
|
26 #define IF_MATCH_HEADER "If-Match" |
|
27 |
|
28 enum DownloadMethod |
|
29 { |
|
30 Invalid, |
|
31 FromURL, |
|
32 FromReply |
|
33 }; |
|
34 |
|
35 // private implementation class |
|
36 class DownloadCorePrivate |
|
37 { |
|
38 DM_DECLARE_PUBLIC(DownloadCore); |
|
39 public: |
|
40 DownloadCorePrivate(); |
|
41 ~DownloadCorePrivate(); |
|
42 |
|
43 // member variables |
|
44 QString m_url; // url |
|
45 QNetworkReply *m_reply; |
|
46 QNetworkAccessManager *m_networkAccessManager; |
|
47 // content type |
|
48 QString m_contentType; |
|
49 // ETag header value |
|
50 QString m_entityTag; |
|
51 // total size |
|
52 qint64 m_sizeInHeader; |
|
53 // Last error code |
|
54 QNetworkReply::NetworkError m_lastError; |
|
55 QString m_lastErrorString; |
|
56 QNetworkProxy *m_proxy; //not owned |
|
57 DownloadMethod m_dlMethod; |
|
58 bool networkAccessManagerOwned; |
|
59 QString m_fileNameFromContentDisposition; |
|
60 }; |
|
61 |
|
62 DownloadCorePrivate::DownloadCorePrivate() |
|
63 { |
|
64 m_url = ""; |
|
65 m_reply = 0; |
|
66 m_networkAccessManager = 0; |
|
67 m_contentType = ""; |
|
68 m_entityTag = ""; |
|
69 m_sizeInHeader = 0; |
|
70 m_lastError = QNetworkReply::NoError; |
|
71 m_lastErrorString = ""; |
|
72 m_proxy = 0; |
|
73 m_dlMethod = Invalid; |
|
74 networkAccessManagerOwned = false; |
|
75 m_fileNameFromContentDisposition =""; |
|
76 } |
|
77 |
|
78 DownloadCorePrivate::~DownloadCorePrivate() |
|
79 { |
|
80 if(m_reply) |
|
81 { |
|
82 m_reply->deleteLater(); |
|
83 m_reply = 0; |
|
84 } |
|
85 if(networkAccessManagerOwned && m_networkAccessManager) |
|
86 { |
|
87 m_networkAccessManager->disconnect(); |
|
88 delete m_networkAccessManager; |
|
89 m_networkAccessManager = 0; |
|
90 } |
|
91 } |
|
92 |
|
93 DownloadCore::DownloadCore(const QString& url) |
|
94 { |
|
95 DM_INITIALIZE(DownloadCore); |
|
96 priv->m_url = url; |
|
97 priv->m_dlMethod = FromURL; |
|
98 |
|
99 if(!priv->m_networkAccessManager) |
|
100 { |
|
101 priv->m_networkAccessManager = new QNetworkAccessManager(this); |
|
102 priv->networkAccessManagerOwned = true; |
|
103 } |
|
104 } |
|
105 |
|
106 DownloadCore::DownloadCore(QNetworkReply *reply) |
|
107 { |
|
108 DM_INITIALIZE(DownloadCore); |
|
109 priv->m_reply = reply; |
|
110 priv->m_dlMethod = FromReply; |
|
111 |
|
112 priv->m_networkAccessManager = (priv->m_reply)->manager(); |
|
113 priv->m_url = (priv->m_reply)->url().toString(QUrl::None); |
|
114 |
|
115 QVariant header = (priv->m_reply)->header(QNetworkRequest::ContentLengthHeader); |
|
116 if(header.isValid()) |
|
117 { |
|
118 priv->m_sizeInHeader = header.toInt(); |
|
119 } |
|
120 |
|
121 header = (priv->m_reply)->header(QNetworkRequest::ContentTypeHeader); |
|
122 if(header.isValid()) |
|
123 { |
|
124 priv->m_contentType = header.toString(); |
|
125 } |
|
126 } |
|
127 |
|
128 DownloadCore::~DownloadCore() |
|
129 { |
|
130 DM_UNINITIALIZE(DownloadCore); |
|
131 } |
|
132 |
|
133 int DownloadCore::doDownload(void) |
|
134 { |
|
135 DM_PRIVATE(DownloadCore); |
|
136 switch(priv->m_dlMethod) |
|
137 { |
|
138 case FromURL: |
|
139 { |
|
140 if((priv->m_url).length() <= 0 ) |
|
141 { |
|
142 return -1; |
|
143 } |
|
144 if(priv->m_proxy) |
|
145 { |
|
146 priv->m_networkAccessManager->setProxy(*(priv->m_proxy)); |
|
147 } |
|
148 |
|
149 /* submit the HTTP request */ |
|
150 QNetworkRequest req(priv->m_url); |
|
151 priv->m_reply = (priv->m_networkAccessManager)->get(req); |
|
152 |
|
153 /* establish all HTTP listeners */ |
|
154 connect(priv->m_reply, SIGNAL(metaDataChanged()), this, SLOT(parseHeaders())); |
|
155 connect(priv->m_reply, SIGNAL(downloadProgress(qint64 , qint64 )), this, SIGNAL(downloadProgress(qint64 , qint64 ))); |
|
156 connect(priv->m_reply, SIGNAL(finished()), this, SIGNAL(finished())); |
|
157 connect(priv->m_reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SIGNAL(error(QNetworkReply::NetworkError))); |
|
158 break; |
|
159 } |
|
160 case FromReply: |
|
161 { |
|
162 if(!priv->m_reply) |
|
163 { |
|
164 return -1; |
|
165 } |
|
166 /* establish all HTTP listeners */ |
|
167 connect(priv->m_reply, SIGNAL(downloadProgress(qint64 , qint64 )),this, SIGNAL(downloadProgress(qint64 , qint64 ))); |
|
168 connect(priv->m_reply, SIGNAL(finished()), this, SIGNAL(finished())); |
|
169 connect(priv->m_reply, SIGNAL(error(QNetworkReply::NetworkError)),this, SIGNAL(error(QNetworkReply::NetworkError))); |
|
170 break; |
|
171 } |
|
172 default: |
|
173 { |
|
174 return -1;// error |
|
175 } |
|
176 } |
|
177 return 0; // successful |
|
178 } |
|
179 |
|
180 int DownloadCore::post(const QString& url, const QByteArray& data) |
|
181 { |
|
182 DM_PRIVATE(DownloadCore); |
|
183 QNetworkRequest req(url); |
|
184 // cancel the ongoing transaction if any |
|
185 abort(); |
|
186 // post the data |
|
187 priv->m_reply = priv->m_networkAccessManager->post(req, data); |
|
188 if(priv->m_reply) |
|
189 { |
|
190 connect(priv->m_reply, SIGNAL(uploadProgress(qint64, qint64)), this, SIGNAL(uploadProgress(qint64, qint64))); |
|
191 return 0; // successful |
|
192 } |
|
193 else |
|
194 { |
|
195 return -1; // error |
|
196 } |
|
197 } |
|
198 |
|
199 int DownloadCore::resumeDownload(qint64 startOffeset) |
|
200 { |
|
201 DM_PRIVATE(DownloadCore); |
|
202 |
|
203 QNetworkRequest req(priv->m_url); |
|
204 // set the RANGE header |
|
205 QString buf; |
|
206 buf.sprintf("bytes=%ld-", (long int)startOffeset); |
|
207 req.setRawHeader(RANGE_HEADER, buf.toAscii()); |
|
208 // set ETag header |
|
209 if (!priv->m_entityTag.isEmpty()) |
|
210 req.setRawHeader(IF_MATCH_HEADER, (priv->m_entityTag).toAscii()); |
|
211 |
|
212 if(!priv->m_networkAccessManager) |
|
213 { |
|
214 priv->m_networkAccessManager = new QNetworkAccessManager(this); |
|
215 priv->networkAccessManagerOwned = true; |
|
216 } |
|
217 if(priv->m_proxy) |
|
218 { |
|
219 priv->m_networkAccessManager->setProxy(*(priv->m_proxy)); |
|
220 } |
|
221 |
|
222 /* submit the HTTP request */ |
|
223 priv->m_reply = (priv->m_networkAccessManager)->get(req); |
|
224 |
|
225 /* establish all HTTP listeners */ |
|
226 connect(priv->m_reply, SIGNAL(metaDataChanged()), this, SLOT(parseHeaders())); |
|
227 connect(priv->m_reply, SIGNAL(downloadProgress(qint64 , qint64 )), this, SIGNAL(downloadProgress(qint64 , qint64 ))); |
|
228 connect(priv->m_reply, SIGNAL(finished()), this, SIGNAL(finished())); |
|
229 connect(priv->m_reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SIGNAL(error(QNetworkReply::NetworkError))); |
|
230 return 0; // successful |
|
231 } |
|
232 |
|
233 int DownloadCore::abort(void) |
|
234 { |
|
235 DM_PRIVATE(DownloadCore); |
|
236 if(priv->m_reply) |
|
237 { |
|
238 (priv->m_reply)->abort(); |
|
239 priv->m_reply->deleteLater(); |
|
240 priv->m_reply = 0; |
|
241 } |
|
242 return 0; // successful |
|
243 } |
|
244 |
|
245 QString& DownloadCore::url(void) |
|
246 { |
|
247 DM_PRIVATE(DownloadCore); |
|
248 return priv->m_url; |
|
249 } |
|
250 |
|
251 void DownloadCore::changeUrl(QString& url) |
|
252 { |
|
253 DM_PRIVATE(DownloadCore); |
|
254 priv->m_url = url; |
|
255 priv->m_dlMethod = FromURL; |
|
256 } |
|
257 |
|
258 QNetworkReply* DownloadCore::reply(void) |
|
259 { |
|
260 DM_PRIVATE(DownloadCore); |
|
261 return priv->m_reply; |
|
262 } |
|
263 |
|
264 QNetworkAccessManager* DownloadCore::networkAccessManager(void) |
|
265 { |
|
266 DM_PRIVATE(DownloadCore); |
|
267 return priv->m_networkAccessManager; |
|
268 } |
|
269 |
|
270 QString& DownloadCore::contentType(void) |
|
271 { |
|
272 DM_PRIVATE(DownloadCore); |
|
273 return priv->m_contentType; |
|
274 } |
|
275 |
|
276 QString& DownloadCore::entityTag(void) |
|
277 { |
|
278 DM_PRIVATE(DownloadCore); |
|
279 return priv->m_entityTag; |
|
280 } |
|
281 |
|
282 void DownloadCore::setContentType(const QString& contentType) |
|
283 { |
|
284 DM_PRIVATE(DownloadCore); |
|
285 priv->m_contentType = contentType; |
|
286 return; |
|
287 } |
|
288 |
|
289 void DownloadCore::setEntityTag(const QString& entityTag) |
|
290 { |
|
291 DM_PRIVATE(DownloadCore); |
|
292 priv->m_entityTag = entityTag; |
|
293 } |
|
294 |
|
295 qint64 DownloadCore::sizeInHeader(void) |
|
296 { |
|
297 DM_PRIVATE(DownloadCore); |
|
298 return priv->m_sizeInHeader; |
|
299 } |
|
300 |
|
301 QNetworkReply::NetworkError DownloadCore::lastError(void) |
|
302 { |
|
303 DM_PRIVATE(DownloadCore); |
|
304 return priv->m_lastError; |
|
305 } |
|
306 |
|
307 void DownloadCore::setLastError(QNetworkReply::NetworkError code) |
|
308 { |
|
309 DM_PRIVATE(DownloadCore); |
|
310 priv->m_lastError = code; |
|
311 } |
|
312 |
|
313 QString DownloadCore::lastErrorString(void) |
|
314 { |
|
315 DM_PRIVATE(DownloadCore); |
|
316 return priv->m_lastErrorString; |
|
317 } |
|
318 |
|
319 void DownloadCore::setLastErrorString(const QString& errStr) |
|
320 { |
|
321 DM_PRIVATE(DownloadCore); |
|
322 priv->m_lastErrorString = errStr; |
|
323 } |
|
324 |
|
325 void DownloadCore::setProxy(QNetworkProxy *proxy) |
|
326 { |
|
327 DM_PRIVATE(DownloadCore); |
|
328 priv->m_proxy = proxy; |
|
329 } |
|
330 |
|
331 QNetworkProxy* DownloadCore::proxy() |
|
332 { |
|
333 DM_PRIVATE(DownloadCore); |
|
334 return priv->m_proxy; |
|
335 } |
|
336 |
|
337 QString DownloadCore::fileNameFromContentDispositionHeader() |
|
338 { |
|
339 DM_PRIVATE(DownloadCore); |
|
340 return priv->m_fileNameFromContentDisposition; |
|
341 } |
|
342 |
|
343 void DownloadCore::parseHeaders(void) |
|
344 { |
|
345 DM_PRIVATE(DownloadCore); |
|
346 QVariant lenHeader = (priv->m_reply)->header(QNetworkRequest::ContentLengthHeader); |
|
347 if(lenHeader.isValid()) |
|
348 { |
|
349 priv->m_sizeInHeader = lenHeader.toInt(); |
|
350 } |
|
351 priv->m_contentType = (priv->m_reply)->header(QNetworkRequest::ContentTypeHeader).toString(); |
|
352 |
|
353 // ETag |
|
354 priv->m_entityTag = (priv->m_reply)->rawHeader(ETAG_HEADER); |
|
355 |
|
356 if (priv->m_reply->hasRawHeader(ECONTENT_DISPOSITION_HEADER)) { |
|
357 const QString value = priv->m_reply->rawHeader(ECONTENT_DISPOSITION_HEADER); |
|
358 const int pos = value.indexOf("filename="); |
|
359 if (pos != -1) { |
|
360 QString name = value.mid(pos + 9); |
|
361 if (name.startsWith('"') && name.endsWith('"')) |
|
362 name = name.mid(1, name.size() - 2); |
|
363 priv->m_fileNameFromContentDisposition = name; |
|
364 } |
|
365 } |
|
366 // emit the signal |
|
367 emit metaDataChanged(); |
|
368 return; |
|
369 } |
|
370 |