1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2016 The Qt Company Ltd. |
4 | ** Contact: https://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the QtNetwork module of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:LGPL$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and The Qt Company. For licensing terms |
14 | ** and conditions see https://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at https://www.qt.io/contact-us. |
16 | ** |
17 | ** GNU Lesser General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser |
19 | ** General Public License version 3 as published by the Free Software |
20 | ** Foundation and appearing in the file LICENSE.LGPL3 included in the |
21 | ** packaging of this file. Please review the following information to |
22 | ** ensure the GNU Lesser General Public License version 3 requirements |
23 | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. |
24 | ** |
25 | ** GNU General Public License Usage |
26 | ** Alternatively, this file may be used under the terms of the GNU |
27 | ** General Public License version 2.0 or (at your option) the GNU General |
28 | ** Public license version 3 or any later version approved by the KDE Free |
29 | ** Qt Foundation. The licenses are as published by the Free Software |
30 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 |
31 | ** included in the packaging of this file. Please review the following |
32 | ** information to ensure the GNU General Public License requirements will |
33 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and |
34 | ** https://www.gnu.org/licenses/gpl-3.0.html. |
35 | ** |
36 | ** $QT_END_LICENSE$ |
37 | ** |
38 | ****************************************************************************/ |
39 | |
40 | #include "qabstractnetworkcache.h" |
41 | #include "qabstractnetworkcache_p.h" |
42 | |
43 | #include <qdatastream.h> |
44 | #include <qdatetime.h> |
45 | #include <qurl.h> |
46 | |
47 | #include <qdebug.h> |
48 | |
49 | QT_BEGIN_NAMESPACE |
50 | |
51 | class QNetworkCacheMetaDataPrivate : public QSharedData |
52 | { |
53 | |
54 | public: |
55 | QNetworkCacheMetaDataPrivate() |
56 | : QSharedData() |
57 | , saveToDisk(true) |
58 | {} |
59 | |
60 | bool operator==(const QNetworkCacheMetaDataPrivate &other) const |
61 | { |
62 | return |
63 | url == other.url |
64 | && lastModified == other.lastModified |
65 | && expirationDate == other.expirationDate |
66 | && headers == other.headers |
67 | && saveToDisk == other.saveToDisk; |
68 | } |
69 | |
70 | QUrl url; |
71 | QDateTime lastModified; |
72 | QDateTime expirationDate; |
73 | QNetworkCacheMetaData::RawHeaderList ; |
74 | QNetworkCacheMetaData::AttributesMap attributes; |
75 | bool saveToDisk; |
76 | |
77 | static void save(QDataStream &out, const QNetworkCacheMetaData &metaData); |
78 | static void load(QDataStream &in, QNetworkCacheMetaData &metaData); |
79 | }; |
80 | Q_GLOBAL_STATIC(QNetworkCacheMetaDataPrivate, metadata_shared_invalid) |
81 | |
82 | /*! |
83 | \class QNetworkCacheMetaData |
84 | \since 4.5 |
85 | \ingroup shared |
86 | \inmodule QtNetwork |
87 | |
88 | \brief The QNetworkCacheMetaData class provides cache information. |
89 | |
90 | QNetworkCacheMetaData provides information about a cache file including |
91 | the url, when it was last modified, when the cache file was created, headers |
92 | for file and if the file should be saved onto a disk. |
93 | |
94 | \sa QAbstractNetworkCache |
95 | */ |
96 | |
97 | /*! |
98 | \typedef QNetworkCacheMetaData::RawHeader |
99 | |
100 | Synonym for QPair<QByteArray, QByteArray> |
101 | */ |
102 | |
103 | /*! |
104 | \typedef QNetworkCacheMetaData::RawHeaderList |
105 | |
106 | Synonym for QList<RawHeader> |
107 | */ |
108 | |
109 | /*! |
110 | \typedef QNetworkCacheMetaData::AttributesMap |
111 | |
112 | Synonym for QHash<QNetworkRequest::Attribute, QVariant> |
113 | */ |
114 | |
115 | /*! |
116 | Constructs an invalid network cache meta data. |
117 | |
118 | \sa isValid() |
119 | */ |
120 | QNetworkCacheMetaData::QNetworkCacheMetaData() |
121 | : d(new QNetworkCacheMetaDataPrivate) |
122 | { |
123 | } |
124 | |
125 | /*! |
126 | Destroys the network cache meta data. |
127 | */ |
128 | QNetworkCacheMetaData::~QNetworkCacheMetaData() |
129 | { |
130 | // QSharedDataPointer takes care of freeing d |
131 | } |
132 | |
133 | /*! |
134 | Constructs a copy of the \a other QNetworkCacheMetaData. |
135 | */ |
136 | QNetworkCacheMetaData::QNetworkCacheMetaData(const QNetworkCacheMetaData &other) |
137 | : d(other.d) |
138 | { |
139 | } |
140 | |
141 | /*! |
142 | Makes a copy of the \a other QNetworkCacheMetaData and returns a reference to the copy. |
143 | */ |
144 | QNetworkCacheMetaData &QNetworkCacheMetaData::operator=(const QNetworkCacheMetaData &other) |
145 | { |
146 | d = other.d; |
147 | return *this; |
148 | } |
149 | |
150 | /*! |
151 | \fn void QNetworkCacheMetaData::swap(QNetworkCacheMetaData &other) |
152 | \since 5.0 |
153 | |
154 | Swaps this metadata instance with \a other. This function is very |
155 | fast and never fails. |
156 | */ |
157 | |
158 | /*! |
159 | Returns \c true if this meta data is equal to the \a other meta data; otherwise returns \c false. |
160 | |
161 | \sa operator!=() |
162 | */ |
163 | bool QNetworkCacheMetaData::operator==(const QNetworkCacheMetaData &other) const |
164 | { |
165 | if (d == other.d) |
166 | return true; |
167 | if (d && other.d) |
168 | return *d == *other.d; |
169 | return false; |
170 | } |
171 | |
172 | /*! |
173 | \fn bool QNetworkCacheMetaData::operator!=(const QNetworkCacheMetaData &other) const |
174 | |
175 | Returns \c true if this meta data is not equal to the \a other meta data; otherwise returns \c false. |
176 | |
177 | \sa operator==() |
178 | */ |
179 | |
180 | /*! |
181 | Returns \c true if this network cache meta data has attributes that have been set otherwise false. |
182 | */ |
183 | bool QNetworkCacheMetaData::isValid() const |
184 | { |
185 | return !(*d == *metadata_shared_invalid()); |
186 | } |
187 | |
188 | /*! |
189 | Returns is this cache should be allowed to be stored on disk. |
190 | |
191 | Some cache implementations can keep these cache items in memory for performance reasons, |
192 | but for security reasons they should not be written to disk. |
193 | |
194 | Specifically with http, documents with Cache-control set to no-store or any |
195 | https document that doesn't have "Cache-control: public" set will |
196 | set the saveToDisk to false. |
197 | |
198 | \sa setSaveToDisk() |
199 | */ |
200 | bool QNetworkCacheMetaData::saveToDisk() const |
201 | { |
202 | return d->saveToDisk; |
203 | } |
204 | |
205 | /*! |
206 | Sets whether this network cache meta data and associated content should be |
207 | allowed to be stored on disk to \a allow. |
208 | |
209 | \sa saveToDisk() |
210 | */ |
211 | void QNetworkCacheMetaData::setSaveToDisk(bool allow) |
212 | { |
213 | d->saveToDisk = allow; |
214 | } |
215 | |
216 | /*! |
217 | Returns the URL this network cache meta data is referring to. |
218 | |
219 | \sa setUrl() |
220 | */ |
221 | QUrl QNetworkCacheMetaData::url() const |
222 | { |
223 | return d->url; |
224 | } |
225 | |
226 | /*! |
227 | Sets the URL this network cache meta data to be \a url. |
228 | |
229 | The password and fragment are removed from the url. |
230 | |
231 | \sa url() |
232 | */ |
233 | void QNetworkCacheMetaData::setUrl(const QUrl &url) |
234 | { |
235 | d->url = url; |
236 | d->url.setPassword(password: QString()); |
237 | d->url.setFragment(fragment: QString()); |
238 | } |
239 | |
240 | /*! |
241 | Returns a list of all raw headers that are set in this meta data. |
242 | The list is in the same order that the headers were set. |
243 | |
244 | \sa setRawHeaders() |
245 | */ |
246 | QNetworkCacheMetaData::RawHeaderList QNetworkCacheMetaData::() const |
247 | { |
248 | return d->headers; |
249 | } |
250 | |
251 | /*! |
252 | Sets the raw headers to \a list. |
253 | |
254 | \sa rawHeaders() |
255 | */ |
256 | void QNetworkCacheMetaData::(const RawHeaderList &list) |
257 | { |
258 | d->headers = list; |
259 | } |
260 | |
261 | /*! |
262 | Returns the date and time when the meta data was last modified. |
263 | */ |
264 | QDateTime QNetworkCacheMetaData::lastModified() const |
265 | { |
266 | return d->lastModified; |
267 | } |
268 | |
269 | /*! |
270 | Sets the date and time when the meta data was last modified to \a dateTime. |
271 | */ |
272 | void QNetworkCacheMetaData::setLastModified(const QDateTime &dateTime) |
273 | { |
274 | d->lastModified = dateTime; |
275 | } |
276 | |
277 | /*! |
278 | Returns the date and time when the meta data expires. |
279 | */ |
280 | QDateTime QNetworkCacheMetaData::expirationDate() const |
281 | { |
282 | return d->expirationDate; |
283 | } |
284 | |
285 | /*! |
286 | Sets the date and time when the meta data expires to \a dateTime. |
287 | */ |
288 | void QNetworkCacheMetaData::setExpirationDate(const QDateTime &dateTime) |
289 | { |
290 | d->expirationDate = dateTime; |
291 | } |
292 | |
293 | /*! |
294 | \since 4.6 |
295 | |
296 | Returns all the attributes stored with this cache item. |
297 | |
298 | \sa setAttributes(), QNetworkRequest::Attribute |
299 | */ |
300 | QNetworkCacheMetaData::AttributesMap QNetworkCacheMetaData::attributes() const |
301 | { |
302 | return d->attributes; |
303 | } |
304 | |
305 | /*! |
306 | \since 4.6 |
307 | |
308 | Sets all attributes of this cache item to be the map \a attributes. |
309 | |
310 | \sa attributes(), QNetworkRequest::setAttribute() |
311 | */ |
312 | void QNetworkCacheMetaData::setAttributes(const AttributesMap &attributes) |
313 | { |
314 | d->attributes = attributes; |
315 | } |
316 | |
317 | /*! |
318 | \relates QNetworkCacheMetaData |
319 | \since 4.5 |
320 | |
321 | Writes \a metaData to the \a out stream. |
322 | |
323 | \sa {Serializing Qt Data Types} |
324 | */ |
325 | QDataStream &operator<<(QDataStream &out, const QNetworkCacheMetaData &metaData) |
326 | { |
327 | QNetworkCacheMetaDataPrivate::save(out, metaData); |
328 | return out; |
329 | } |
330 | |
331 | static inline QDataStream &operator<<(QDataStream &out, const QNetworkCacheMetaData::AttributesMap &hash) |
332 | { |
333 | out << quint32(hash.size()); |
334 | QNetworkCacheMetaData::AttributesMap::ConstIterator it = hash.begin(); |
335 | QNetworkCacheMetaData::AttributesMap::ConstIterator end = hash.end(); |
336 | while (it != end) { |
337 | out << int(it.key()) << it.value(); |
338 | ++it; |
339 | } |
340 | return out; |
341 | } |
342 | |
343 | void QNetworkCacheMetaDataPrivate::save(QDataStream &out, const QNetworkCacheMetaData &metaData) |
344 | { |
345 | // note: if you change the contents of the meta data here |
346 | // remember to bump the cache version in qnetworkdiskcache.cpp CurrentCacheVersion |
347 | out << metaData.url(); |
348 | out << metaData.expirationDate(); |
349 | out << metaData.lastModified(); |
350 | out << metaData.saveToDisk(); |
351 | out << metaData.attributes(); |
352 | out << metaData.rawHeaders(); |
353 | } |
354 | |
355 | /*! |
356 | \relates QNetworkCacheMetaData |
357 | \since 4.5 |
358 | |
359 | Reads a QNetworkCacheMetaData from the stream \a in into \a metaData. |
360 | |
361 | \sa {Serializing Qt Data Types} |
362 | */ |
363 | QDataStream &operator>>(QDataStream &in, QNetworkCacheMetaData &metaData) |
364 | { |
365 | QNetworkCacheMetaDataPrivate::load(in, metaData); |
366 | return in; |
367 | } |
368 | |
369 | static inline QDataStream &operator>>(QDataStream &in, QNetworkCacheMetaData::AttributesMap &hash) |
370 | { |
371 | hash.clear(); |
372 | QDataStream::Status oldStatus = in.status(); |
373 | in.resetStatus(); |
374 | hash.clear(); |
375 | |
376 | quint32 n; |
377 | in >> n; |
378 | |
379 | for (quint32 i = 0; i < n; ++i) { |
380 | if (in.status() != QDataStream::Ok) |
381 | break; |
382 | |
383 | int k; |
384 | QVariant t; |
385 | in >> k >> t; |
386 | hash.insert(akey: QNetworkRequest::Attribute(k), avalue: t); |
387 | } |
388 | |
389 | if (in.status() != QDataStream::Ok) |
390 | hash.clear(); |
391 | if (oldStatus != QDataStream::Ok) |
392 | in.setStatus(oldStatus); |
393 | return in; |
394 | } |
395 | |
396 | void QNetworkCacheMetaDataPrivate::load(QDataStream &in, QNetworkCacheMetaData &metaData) |
397 | { |
398 | in >> metaData.d->url; |
399 | in >> metaData.d->expirationDate; |
400 | in >> metaData.d->lastModified; |
401 | in >> metaData.d->saveToDisk; |
402 | in >> metaData.d->attributes; |
403 | in >> metaData.d->headers; |
404 | } |
405 | |
406 | /*! |
407 | \class QAbstractNetworkCache |
408 | \since 4.5 |
409 | \inmodule QtNetwork |
410 | |
411 | \brief The QAbstractNetworkCache class provides the interface for cache implementations. |
412 | |
413 | QAbstractNetworkCache is the base class for every standard cache that is used by |
414 | QNetworkAccessManager. QAbstractNetworkCache is an abstract class and cannot be |
415 | instantiated. |
416 | |
417 | \sa QNetworkDiskCache |
418 | */ |
419 | |
420 | /*! |
421 | Constructs an abstract network cache with the given \a parent. |
422 | */ |
423 | QAbstractNetworkCache::QAbstractNetworkCache(QObject *parent) |
424 | : QObject(*new QAbstractNetworkCachePrivate, parent) |
425 | { |
426 | } |
427 | |
428 | /*! |
429 | \internal |
430 | */ |
431 | QAbstractNetworkCache::QAbstractNetworkCache(QAbstractNetworkCachePrivate &dd, QObject *parent) |
432 | : QObject(dd, parent) |
433 | { |
434 | } |
435 | |
436 | /*! |
437 | Destroys the cache. |
438 | |
439 | Any operations that have not been inserted are discarded. |
440 | |
441 | \sa insert() |
442 | */ |
443 | QAbstractNetworkCache::~QAbstractNetworkCache() |
444 | { |
445 | } |
446 | |
447 | /*! |
448 | \fn QNetworkCacheMetaData QAbstractNetworkCache::metaData(const QUrl &url) = 0 |
449 | Returns the meta data for the url \a url. |
450 | |
451 | If the url is valid and the cache contains the data for url, |
452 | a valid QNetworkCacheMetaData is returned. |
453 | |
454 | In the base class this is a pure virtual function. |
455 | |
456 | \sa updateMetaData(), data() |
457 | */ |
458 | |
459 | /*! |
460 | \fn void QAbstractNetworkCache::updateMetaData(const QNetworkCacheMetaData &metaData) = 0 |
461 | Updates the cache meta date for the metaData's url to \a metaData |
462 | |
463 | If the cache does not contains a cache item for the url then no action is taken. |
464 | |
465 | In the base class this is a pure virtual function. |
466 | |
467 | \sa metaData(), prepare() |
468 | */ |
469 | |
470 | /*! |
471 | \fn QIODevice *QAbstractNetworkCache::data(const QUrl &url) = 0 |
472 | Returns the data associated with \a url. |
473 | |
474 | It is up to the application that requests the data to delete |
475 | the QIODevice when done with it. |
476 | |
477 | If there is no cache for \a url, the url is invalid, or if there |
478 | is an internal cache error \nullptr is returned. |
479 | |
480 | In the base class this is a pure virtual function. |
481 | |
482 | \sa metaData(), prepare() |
483 | */ |
484 | |
485 | /*! |
486 | \fn bool QAbstractNetworkCache::remove(const QUrl &url) = 0 |
487 | Removes the cache entry for \a url, returning true if success otherwise false. |
488 | |
489 | In the base class this is a pure virtual function. |
490 | |
491 | \sa clear(), prepare() |
492 | */ |
493 | |
494 | /*! |
495 | \fn QIODevice *QAbstractNetworkCache::prepare(const QNetworkCacheMetaData &metaData) = 0 |
496 | Returns the device that should be populated with the data for |
497 | the cache item \a metaData. When all of the data has been written |
498 | insert() should be called. If metaData is invalid or the url in |
499 | the metadata is invalid \nullptr is returned. |
500 | |
501 | The cache owns the device and will take care of deleting it when |
502 | it is inserted or removed. |
503 | |
504 | To cancel a prepared inserted call remove() on the metadata's url. |
505 | |
506 | In the base class this is a pure virtual function. |
507 | |
508 | \sa remove(), updateMetaData(), insert() |
509 | */ |
510 | |
511 | /*! |
512 | \fn void QAbstractNetworkCache::insert(QIODevice *device) = 0 |
513 | Inserts the data in \a device and the prepared meta data into the cache. |
514 | After this function is called the data and meta data should be retrievable |
515 | using data() and metaData(). |
516 | |
517 | To cancel a prepared inserted call remove() on the metadata's url. |
518 | |
519 | In the base class this is a pure virtual function. |
520 | |
521 | \sa prepare(), remove() |
522 | */ |
523 | |
524 | /*! |
525 | \fn qint64 QAbstractNetworkCache::cacheSize() const = 0 |
526 | Returns the current size taken up by the cache. Depending upon |
527 | the cache implementation this might be disk or memory size. |
528 | |
529 | In the base class this is a pure virtual function. |
530 | |
531 | \sa clear() |
532 | */ |
533 | |
534 | /*! |
535 | \fn void QAbstractNetworkCache::clear() = 0 |
536 | Removes all items from the cache. Unless there was failures |
537 | clearing the cache cacheSize() should return 0 after a call to clear. |
538 | |
539 | In the base class this is a pure virtual function. |
540 | |
541 | \sa cacheSize(), remove() |
542 | */ |
543 | |
544 | QT_END_NAMESPACE |
545 | |