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
13QT_BEGIN_NAMESPACE
14
15QNetworkAccessCacheBackend::QNetworkAccessCacheBackend()
16 : QNetworkAccessBackend(QNetworkAccessBackend::TargetType::Local)
17{
18}
19
20QNetworkAccessCacheBackend::~QNetworkAccessCacheBackend()
21{
22}
23
24void 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
36bool 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
88bool QNetworkAccessCacheBackend::start()
89{
90 open();
91 return true;
92}
93
94void QNetworkAccessCacheBackend::close() { }
95
96qint64 QNetworkAccessCacheBackend::bytesAvailable() const
97{
98 return device ? device->bytesAvailable() : qint64(0);
99}
100
101qint64 QNetworkAccessCacheBackend::read(char *data, qint64 maxlen)
102{
103 return device ? device->read(data, maxlen) : qint64(0);
104}
105
106QT_END_NAMESPACE
107
108

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