Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qnetworkaccesscachebackend.cpp
Go to the documentation of this file.
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// Qt-Security score:significant reason:default
4
5//#define QNETWORKACCESSCACHEBACKEND_DEBUG
6
9#include "qfileinfo.h"
10#include "qdir.h"
12#include "qhash.h"
13
15
16using namespace Qt::StringLiterals;
17
18QNetworkAccessCacheBackend::QNetworkAccessCacheBackend()
19 : QNetworkAccessBackend(QNetworkAccessBackend::TargetType::Local)
20{
21}
22
23QNetworkAccessCacheBackend::~QNetworkAccessCacheBackend()
24{
25}
26
27void QNetworkAccessCacheBackend::open()
28{
29 if (operation() != QNetworkAccessManager::GetOperation || !sendCacheContents()) {
30 QString msg = QCoreApplication::translate("QNetworkAccessCacheBackend", "Error opening %1")
31 .arg(this->url().toString());
32 error(QNetworkReply::ContentNotFoundError, msg);
33 } else {
34 setAttribute(QNetworkRequest::SourceIsFromCacheAttribute, true);
35 }
36 finished();
37}
38
39bool QNetworkAccessCacheBackend::sendCacheContents()
40{
41 setCachingEnabled(false);
42 QAbstractNetworkCache *nc = networkCache();
43 if (!nc)
44 return false;
45
46 QNetworkCacheMetaData item = nc->metaData(url());
47 if (!item.isValid())
48 return false;
49
50 QNetworkCacheMetaData::AttributesMap attributes = item.attributes();
51 setAttribute(QNetworkRequest::HttpStatusCodeAttribute,
52 attributes.value(QNetworkRequest::HttpStatusCodeAttribute));
53 setAttribute(QNetworkRequest::HttpReasonPhraseAttribute,
54 attributes.value(QNetworkRequest::HttpReasonPhraseAttribute));
55
56 // set the headers
57 auto headers = item.headers();
58 const auto cacheControlValue = QLatin1StringView(
59 headers.value(QHttpHeaders::WellKnownHeader::CacheControl));
60 // RFC 9111 Section 5.2 Cache Control
61 if (cacheControlValue.contains("must-revalidate"_L1, Qt::CaseInsensitive)
62 || cacheControlValue.contains("no-cache"_L1, Qt::CaseInsensitive)) {
63 return false;
64 }
65 setHeaders(std::move(headers));
66
67 // handle a possible redirect
68 QVariant redirectionTarget = attributes.value(QNetworkRequest::RedirectionTargetAttribute);
69 if (redirectionTarget.isValid()) {
70 setAttribute(QNetworkRequest::RedirectionTargetAttribute, redirectionTarget);
71 redirectionRequested(redirectionTarget.toUrl());
72 }
73
74 // signal we're open
75 metaDataChanged();
76
77 if (operation() == QNetworkAccessManager::GetOperation) {
78 device = nc->data(url());
79 if (!device)
80 return false;
81 device->setParent(this);
82 readyRead();
83 }
84
85#if defined(QNETWORKACCESSCACHEBACKEND_DEBUG)
86 qDebug() << "Successfully sent cache:" << url();
87#endif
88 return true;
89}
90
91bool QNetworkAccessCacheBackend::start()
92{
93 open();
94 return true;
95}
96
97void QNetworkAccessCacheBackend::close() { }
98
99qint64 QNetworkAccessCacheBackend::bytesAvailable() const
100{
101 return device ? device->bytesAvailable() : qint64(0);
102}
103
104qint64 QNetworkAccessCacheBackend::read(char *data, qint64 maxlen)
105{
106 return device ? device->read(data, maxlen) : qint64(0);
107}
108
109QT_END_NAMESPACE