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

source code of qtbase/src/network/access/qabstractnetworkcache.cpp