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 | //#define QNETWORKACCESSCACHEBACKEND_DEBUG |
5 | |
6 | #include "qnetworkaccesscachebackend_p.h" |
7 | #include "qabstractnetworkcache.h" |
8 | #include "qfileinfo.h" |
9 | #include "qdir.h" |
10 | #include "qcoreapplication.h" |
11 | #include "qhash.h" |
12 | |
13 | QT_BEGIN_NAMESPACE |
14 | |
15 | QNetworkAccessCacheBackend::QNetworkAccessCacheBackend() |
16 | : QNetworkAccessBackend(QNetworkAccessBackend::TargetType::Local) |
17 | { |
18 | } |
19 | |
20 | QNetworkAccessCacheBackend::~QNetworkAccessCacheBackend() |
21 | { |
22 | } |
23 | |
24 | void QNetworkAccessCacheBackend::open() |
25 | { |
26 | if (operation() != QNetworkAccessManager::GetOperation || !sendCacheContents()) { |
27 | QString msg = QCoreApplication::translate(context: "QNetworkAccessCacheBackend", key: "Error opening %1") |
28 | .arg(a: this->url().toString()); |
29 | error(code: QNetworkReply::ContentNotFoundError, errorString: msg); |
30 | } else { |
31 | setAttribute(attribute: QNetworkRequest::SourceIsFromCacheAttribute, value: true); |
32 | } |
33 | finished(); |
34 | } |
35 | |
36 | bool QNetworkAccessCacheBackend::sendCacheContents() |
37 | { |
38 | setCachingEnabled(false); |
39 | QAbstractNetworkCache *nc = networkCache(); |
40 | if (!nc) |
41 | return false; |
42 | |
43 | QNetworkCacheMetaData item = nc->metaData(url: url()); |
44 | if (!item.isValid()) |
45 | return false; |
46 | |
47 | QNetworkCacheMetaData::AttributesMap attributes = item.attributes(); |
48 | setAttribute(attribute: QNetworkRequest::HttpStatusCodeAttribute, value: attributes.value(key: QNetworkRequest::HttpStatusCodeAttribute)); |
49 | setAttribute(attribute: QNetworkRequest::HttpReasonPhraseAttribute, value: attributes.value(key: QNetworkRequest::HttpReasonPhraseAttribute)); |
50 | |
51 | // set the raw headers |
52 | const QNetworkCacheMetaData::RawHeaderList rawHeaders = item.rawHeaders(); |
53 | for (const auto &header : rawHeaders) { |
54 | if (header.first.toLower() == "cache-control") { |
55 | const QByteArray cacheControlValue = header.second.toLower(); |
56 | if (cacheControlValue.contains(bv: "must-revalidate") |
57 | || cacheControlValue.contains(bv: "no-cache")) { |
58 | return false; |
59 | } |
60 | } |
61 | setRawHeader(header: header.first, value: header.second); |
62 | } |
63 | |
64 | // handle a possible redirect |
65 | QVariant redirectionTarget = attributes.value(key: QNetworkRequest::RedirectionTargetAttribute); |
66 | if (redirectionTarget.isValid()) { |
67 | setAttribute(attribute: QNetworkRequest::RedirectionTargetAttribute, value: redirectionTarget); |
68 | redirectionRequested(destination: redirectionTarget.toUrl()); |
69 | } |
70 | |
71 | // signal we're open |
72 | metaDataChanged(); |
73 | |
74 | if (operation() == QNetworkAccessManager::GetOperation) { |
75 | device = nc->data(url: url()); |
76 | if (!device) |
77 | return false; |
78 | device->setParent(this); |
79 | readyRead(); |
80 | } |
81 | |
82 | #if defined(QNETWORKACCESSCACHEBACKEND_DEBUG) |
83 | qDebug() << "Successfully sent cache:"<< url(); |
84 | #endif |
85 | return true; |
86 | } |
87 | |
88 | bool QNetworkAccessCacheBackend::start() |
89 | { |
90 | open(); |
91 | return true; |
92 | } |
93 | |
94 | void QNetworkAccessCacheBackend::close() { } |
95 | |
96 | qint64 QNetworkAccessCacheBackend::bytesAvailable() const |
97 | { |
98 | return device ? device->bytesAvailable() : qint64(0); |
99 | } |
100 | |
101 | qint64 QNetworkAccessCacheBackend::read(char *data, qint64 maxlen) |
102 | { |
103 | return device ? device->read(data, maxlen) : qint64(0); |
104 | } |
105 | |
106 | QT_END_NAMESPACE |
107 | |
108 |