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
49QT_BEGIN_NAMESPACE
50
51class QNetworkCacheMetaDataPrivate : public QSharedData
52{
53
54public:
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 headers;
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};
80Q_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 */
120QNetworkCacheMetaData::QNetworkCacheMetaData()
121 : d(new QNetworkCacheMetaDataPrivate)
122{
123}
124
125/*!
126 Destroys the network cache meta data.
127 */
128QNetworkCacheMetaData::~QNetworkCacheMetaData()
129{
130 // QSharedDataPointer takes care of freeing d
131}
132
133/*!
134 Constructs a copy of the \a other QNetworkCacheMetaData.
135 */
136QNetworkCacheMetaData::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 */
144QNetworkCacheMetaData &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 */
163bool 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 */
183bool 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 */
200bool 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 */
211void 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 */
221QUrl 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 */
233void QNetworkCacheMetaData::setUrl(const QUrl &url)
234{
235 auto *p = d.data();
236 p->url = url;
237 p->url.setPassword(QString());
238 p->url.setFragment(QString());
239}
240
241/*!
242 Returns a list of all raw headers that are set in this meta data.
243 The list is in the same order that the headers were set.
244
245 \sa setRawHeaders()
246 */
247QNetworkCacheMetaData::RawHeaderList QNetworkCacheMetaData::rawHeaders() const
248{
249 return d->headers;
250}
251
252/*!
253 Sets the raw headers to \a list.
254
255 \sa rawHeaders()
256 */
257void QNetworkCacheMetaData::setRawHeaders(const RawHeaderList &list)
258{
259 d->headers = list;
260}
261
262/*!
263 Returns the date and time when the meta data was last modified.
264 */
265QDateTime QNetworkCacheMetaData::lastModified() const
266{
267 return d->lastModified;
268}
269
270/*!
271 Sets the date and time when the meta data was last modified to \a dateTime.
272 */
273void QNetworkCacheMetaData::setLastModified(const QDateTime &dateTime)
274{
275 d->lastModified = dateTime;
276}
277
278/*!
279 Returns the date and time when the meta data expires.
280 */
281QDateTime QNetworkCacheMetaData::expirationDate() const
282{
283 return d->expirationDate;
284}
285
286/*!
287 Sets the date and time when the meta data expires to \a dateTime.
288 */
289void QNetworkCacheMetaData::setExpirationDate(const QDateTime &dateTime)
290{
291 d->expirationDate = dateTime;
292}
293
294/*!
295 \since 4.6
296
297 Returns all the attributes stored with this cache item.
298
299 \sa setAttributes(), QNetworkRequest::Attribute
300*/
301QNetworkCacheMetaData::AttributesMap QNetworkCacheMetaData::attributes() const
302{
303 return d->attributes;
304}
305
306/*!
307 \since 4.6
308
309 Sets all attributes of this cache item to be the map \a attributes.
310
311 \sa attributes(), QNetworkRequest::setAttribute()
312*/
313void QNetworkCacheMetaData::setAttributes(const AttributesMap &attributes)
314{
315 d->attributes = attributes;
316}
317
318/*!
319 \relates QNetworkCacheMetaData
320 \since 4.5
321
322 Writes \a metaData to the \a out stream.
323
324 \sa {Serializing Qt Data Types}
325*/
326QDataStream &operator<<(QDataStream &out, const QNetworkCacheMetaData &metaData)
327{
328 QNetworkCacheMetaDataPrivate::save(out, metaData);
329 return out;
330}
331
332static inline QDataStream &operator<<(QDataStream &out, const QNetworkCacheMetaData::AttributesMap &hash)
333{
334 out << quint32(hash.size());
335 QNetworkCacheMetaData::AttributesMap::ConstIterator it = hash.begin();
336 QNetworkCacheMetaData::AttributesMap::ConstIterator end = hash.end();
337 while (it != end) {
338 out << int(it.key()) << it.value();
339 ++it;
340 }
341 return out;
342}
343
344void QNetworkCacheMetaDataPrivate::save(QDataStream &out, const QNetworkCacheMetaData &metaData)
345{
346 // note: if you change the contents of the meta data here
347 // remember to bump the cache version in qnetworkdiskcache.cpp CurrentCacheVersion
348 out << metaData.url();
349 out << metaData.expirationDate();
350 out << metaData.lastModified();
351 out << metaData.saveToDisk();
352 out << metaData.attributes();
353 out << metaData.rawHeaders();
354}
355
356/*!
357 \relates QNetworkCacheMetaData
358 \since 4.5
359
360 Reads a QNetworkCacheMetaData from the stream \a in into \a metaData.
361
362 \sa {Serializing Qt Data Types}
363*/
364QDataStream &operator>>(QDataStream &in, QNetworkCacheMetaData &metaData)
365{
366 QNetworkCacheMetaDataPrivate::load(in, metaData);
367 return in;
368}
369
370static inline QDataStream &operator>>(QDataStream &in, QNetworkCacheMetaData::AttributesMap &hash)
371{
372 hash.clear();
373 QDataStream::Status oldStatus = in.status();
374 in.resetStatus();
375 hash.clear();
376
377 quint32 n;
378 in >> n;
379
380 for (quint32 i = 0; i < n; ++i) {
381 if (in.status() != QDataStream::Ok)
382 break;
383
384 int k;
385 QVariant t;
386 in >> k >> t;
387 hash.insert(QNetworkRequest::Attribute(k), t);
388 }
389
390 if (in.status() != QDataStream::Ok)
391 hash.clear();
392 if (oldStatus != QDataStream::Ok)
393 in.setStatus(oldStatus);
394 return in;
395}
396
397void QNetworkCacheMetaDataPrivate::load(QDataStream &in, QNetworkCacheMetaData &metaData)
398{
399 auto *p = metaData.d.data();
400 in >> p->url;
401 in >> p->expirationDate;
402 in >> p->lastModified;
403 in >> p->saveToDisk;
404 in >> p->attributes;
405 in >> p->headers;
406}
407
408/*!
409 \class QAbstractNetworkCache
410 \since 4.5
411 \inmodule QtNetwork
412
413 \brief The QAbstractNetworkCache class provides the interface for cache implementations.
414
415 QAbstractNetworkCache is the base class for every standard cache that is used by
416 QNetworkAccessManager. QAbstractNetworkCache is an abstract class and cannot be
417 instantiated.
418
419 \sa QNetworkDiskCache
420*/
421
422/*!
423 Constructs an abstract network cache with the given \a parent.
424*/
425QAbstractNetworkCache::QAbstractNetworkCache(QObject *parent)
426 : QObject(*new QAbstractNetworkCachePrivate, parent)
427{
428}
429
430/*!
431 \internal
432*/
433QAbstractNetworkCache::QAbstractNetworkCache(QAbstractNetworkCachePrivate &dd, QObject *parent)
434 : QObject(dd, parent)
435{
436}
437
438/*!
439 Destroys the cache.
440
441 Any operations that have not been inserted are discarded.
442
443 \sa insert()
444 */
445QAbstractNetworkCache::~QAbstractNetworkCache()
446{
447}
448
449/*!
450 \fn QNetworkCacheMetaData QAbstractNetworkCache::metaData(const QUrl &url) = 0
451 Returns the meta data for the url \a url.
452
453 If the url is valid and the cache contains the data for url,
454 a valid QNetworkCacheMetaData is returned.
455
456 In the base class this is a pure virtual function.
457
458 \sa updateMetaData(), data()
459*/
460
461/*!
462 \fn void QAbstractNetworkCache::updateMetaData(const QNetworkCacheMetaData &metaData) = 0
463 Updates the cache meta date for the metaData's url to \a metaData
464
465 If the cache does not contains a cache item for the url then no action is taken.
466
467 In the base class this is a pure virtual function.
468
469 \sa metaData(), prepare()
470*/
471
472/*!
473 \fn QIODevice *QAbstractNetworkCache::data(const QUrl &url) = 0
474 Returns the data associated with \a url.
475
476 It is up to the application that requests the data to delete
477 the QIODevice when done with it.
478
479 If there is no cache for \a url, the url is invalid, or if there
480 is an internal cache error \nullptr is returned.
481
482 In the base class this is a pure virtual function.
483
484 \sa metaData(), prepare()
485*/
486
487/*!
488 \fn bool QAbstractNetworkCache::remove(const QUrl &url) = 0
489 Removes the cache entry for \a url, returning true if success otherwise false.
490
491 In the base class this is a pure virtual function.
492
493 \sa clear(), prepare()
494*/
495
496/*!
497 \fn QIODevice *QAbstractNetworkCache::prepare(const QNetworkCacheMetaData &metaData) = 0
498 Returns the device that should be populated with the data for
499 the cache item \a metaData. When all of the data has been written
500 insert() should be called. If metaData is invalid or the url in
501 the metadata is invalid \nullptr is returned.
502
503 The cache owns the device and will take care of deleting it when
504 it is inserted or removed.
505
506 To cancel a prepared inserted call remove() on the metadata's url.
507
508 In the base class this is a pure virtual function.
509
510 \sa remove(), updateMetaData(), insert()
511*/
512
513/*!
514 \fn void QAbstractNetworkCache::insert(QIODevice *device) = 0
515 Inserts the data in \a device and the prepared meta data into the cache.
516 After this function is called the data and meta data should be retrievable
517 using data() and metaData().
518
519 To cancel a prepared inserted call remove() on the metadata's url.
520
521 In the base class this is a pure virtual function.
522
523 \sa prepare(), remove()
524*/
525
526/*!
527 \fn qint64 QAbstractNetworkCache::cacheSize() const = 0
528 Returns the current size taken up by the cache. Depending upon
529 the cache implementation this might be disk or memory size.
530
531 In the base class this is a pure virtual function.
532
533 \sa clear()
534*/
535
536/*!
537 \fn void QAbstractNetworkCache::clear() = 0
538 Removes all items from the cache. Unless there was failures
539 clearing the cache cacheSize() should return 0 after a call to clear.
540
541 In the base class this is a pure virtual function.
542
543 \sa cacheSize(), remove()
544*/
545
546QT_END_NAMESPACE
547