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 | 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 | */ |
247 | QNetworkCacheMetaData::RawHeaderList QNetworkCacheMetaData::() const |
248 | { |
249 | return d->headers; |
250 | } |
251 | |
252 | /*! |
253 | Sets the raw headers to \a list. |
254 | |
255 | \sa rawHeaders() |
256 | */ |
257 | void QNetworkCacheMetaData::(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 | */ |
265 | QDateTime 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 | */ |
273 | void 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 | */ |
281 | QDateTime 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 | */ |
289 | void 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 | */ |
301 | QNetworkCacheMetaData::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 | */ |
313 | void 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 | */ |
326 | QDataStream &operator<<(QDataStream &out, const QNetworkCacheMetaData &metaData) |
327 | { |
328 | QNetworkCacheMetaDataPrivate::save(out, metaData); |
329 | return out; |
330 | } |
331 | |
332 | static 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 | |
344 | void 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 | */ |
364 | QDataStream &operator>>(QDataStream &in, QNetworkCacheMetaData &metaData) |
365 | { |
366 | QNetworkCacheMetaDataPrivate::load(in, metaData); |
367 | return in; |
368 | } |
369 | |
370 | static 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 | |
397 | void 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 | */ |
425 | QAbstractNetworkCache::QAbstractNetworkCache(QObject *parent) |
426 | : QObject(*new QAbstractNetworkCachePrivate, parent) |
427 | { |
428 | } |
429 | |
430 | /*! |
431 | \internal |
432 | */ |
433 | QAbstractNetworkCache::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 | */ |
445 | QAbstractNetworkCache::~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 | |
546 | QT_END_NAMESPACE |
547 | |