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 | |
14 | QT_BEGIN_NAMESPACE |
15 | |
16 | class QNetworkCacheMetaDataPrivate : public QSharedData |
17 | { |
18 | |
19 | public: |
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 ; |
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 | }; |
45 | Q_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 | */ |
85 | QNetworkCacheMetaData::QNetworkCacheMetaData() |
86 | : d(new QNetworkCacheMetaDataPrivate) |
87 | { |
88 | } |
89 | |
90 | /*! |
91 | Destroys the network cache meta data. |
92 | */ |
93 | QNetworkCacheMetaData::~QNetworkCacheMetaData() |
94 | { |
95 | // QSharedDataPointer takes care of freeing d |
96 | } |
97 | |
98 | /*! |
99 | Constructs a copy of the \a other QNetworkCacheMetaData. |
100 | */ |
101 | QNetworkCacheMetaData::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 | */ |
109 | QNetworkCacheMetaData &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 | */ |
128 | bool 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 | */ |
148 | bool 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 | */ |
165 | bool 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 | */ |
176 | void 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 | */ |
186 | QUrl 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 | */ |
198 | void 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 | */ |
212 | QNetworkCacheMetaData::RawHeaderList QNetworkCacheMetaData::() const |
213 | { |
214 | return d->headers; |
215 | } |
216 | |
217 | /*! |
218 | Sets the raw headers to \a list. |
219 | |
220 | \sa rawHeaders() |
221 | */ |
222 | void QNetworkCacheMetaData::(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 | */ |
230 | QDateTime 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 | */ |
238 | void 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 | */ |
246 | QDateTime 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 | */ |
254 | void 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 | */ |
266 | QNetworkCacheMetaData::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 | */ |
278 | void 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 | */ |
291 | QDataStream &operator<<(QDataStream &out, const QNetworkCacheMetaData &metaData) |
292 | { |
293 | QNetworkCacheMetaDataPrivate::save(out, metaData); |
294 | return out; |
295 | } |
296 | |
297 | static 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 | |
309 | void 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 | */ |
329 | QDataStream &operator>>(QDataStream &in, QNetworkCacheMetaData &metaData) |
330 | { |
331 | QNetworkCacheMetaDataPrivate::load(in, metaData); |
332 | return in; |
333 | } |
334 | |
335 | static 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 | |
362 | void 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 | */ |
390 | QAbstractNetworkCache::QAbstractNetworkCache(QObject *parent) |
391 | : QObject(*new QAbstractNetworkCachePrivate, parent) |
392 | { |
393 | } |
394 | |
395 | /*! |
396 | \internal |
397 | */ |
398 | QAbstractNetworkCache::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 | */ |
410 | QAbstractNetworkCache::~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 | |
511 | QT_END_NAMESPACE |
512 | |
513 | #include "moc_qabstractnetworkcache.cpp" |
514 | |