Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qnetworkaccessfilebackend.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
5#include "qfileinfo.h"
6#include "qdir.h"
7#include "private/qnoncontiguousbytedevice_p.h"
8
9#include <QtCore/QCoreApplication>
10#include <QtCore/QDateTime>
11
13
14using namespace Qt::StringLiterals;
15
17{
18 QStringList schemes;
19 schemes << QStringLiteral("file")
20 << QStringLiteral("qrc");
21#if defined(Q_OS_ANDROID)
22 schemes << QStringLiteral("assets");
23#endif
24 return schemes;
25}
26
29 const QNetworkRequest &request) const
30{
31 // is it an operation we know of?
32 switch (op) {
35 break;
36
37 default:
38 // no, we can't handle this operation
39 return nullptr;
40 }
41
42 QUrl url = request.url();
43 if (url.scheme().compare("qrc"_L1, Qt::CaseInsensitive) == 0
44#if defined(Q_OS_ANDROID)
45 || url.scheme().compare("assets"_L1, Qt::CaseInsensitive) == 0
46#endif
47 || url.isLocalFile()) {
49 } else if (!url.scheme().isEmpty() && url.authority().isEmpty() && (url.scheme().size() > 1)) {
50 // check if QFile could, in theory, open this URL via the file engines
51 // it has to be in the format:
52 // prefix:path/to/file
53 // or prefix:/path/to/file
54 //
55 // this construct here must match the one below in open()
57 if (fi.exists() || (op == QNetworkAccessManager::PutOperation && fi.dir().exists()))
59 }
60
61 return nullptr;
62}
63
64// We pass TargetType::Local even though it's kind of Networked but we're using a QFile to access
65// the resource so it cannot use proxies anyway
72
76
78{
79 QUrl url = this->url();
80
81 if (url.host() == "localhost"_L1)
83#if !defined(Q_OS_WIN)
84 // do not allow UNC paths on Unix
85 if (!url.host().isEmpty()) {
86 // we handle only local files
88 QCoreApplication::translate("QNetworkAccessFileBackend", "Request for opening non-local file %1").arg(url.toString()));
89 finished();
90 return;
91 }
92#endif // !defined(Q_OS_WIN)
93 if (url.path().isEmpty())
94 url.setPath("/"_L1);
95 setUrl(url);
96
98 if (fileName.isEmpty()) {
99 if (url.scheme() == "qrc"_L1) {
100 fileName = u':' + url.path();
101 } else {
102#if defined(Q_OS_ANDROID)
103 if (url.scheme() == "assets"_L1)
104 fileName = "assets:"_L1 + url.path();
105 else
106#endif
108 }
109 }
110 file.setFileName(fileName);
111
113 if (!loadFileInfo())
114 return;
115 }
116
117 QIODevice::OpenMode mode;
118 switch (operation()) {
121 break;
126 QMetaObject::invokeMethod(this, "uploadReadyReadSlot", Qt::QueuedConnection);
127 break;
128 default:
129 Q_ASSERT_X(false, "QNetworkAccessFileBackend::open",
130 "Got a request operation I cannot handle!!");
131 return;
132 }
133
135 bool opened = file.open(mode);
136 if (file.isSequential())
137 connect(&file, &QIODevice::readChannelFinished, this, [this]() { finished(); });
138
139 // could we open the file?
140 if (!opened) {
141 QString msg = QCoreApplication::translate("QNetworkAccessFileBackend", "Error opening %1: %2")
142 .arg(this->url().toString(), file.errorString());
143
144 // why couldn't we open the file?
145 // if we're opening for reading, either it doesn't exist, or it's access denied
146 // if we're opening for writing, not existing means it's access denied too
149 else
151 finished();
152 }
153}
154
156{
157 if (hasUploadFinished)
158 return;
159
160 forever {
162 qint64 haveRead = uploadByteDevice()->peek(data.data(), data.size());
163 if (haveRead == -1) {
164 // EOF
165 hasUploadFinished = true;
166 file.flush();
167 file.close();
168 finished();
169 break;
170 } else if (haveRead == 0) {
171 // nothing to read right now, we will be called again later
172 break;
173 } else {
174 qint64 haveWritten;
175 data.truncate(haveRead);
176 haveWritten = file.write(data);
177
178 if (haveWritten < 0) {
179 // write error!
180 QString msg = QCoreApplication::translate("QNetworkAccessFileBackend", "Write error writing to %1: %2")
181 .arg(url().toString(), file.errorString());
183
184 finished();
185 return;
186 } else {
187 uploadByteDevice()->skip(haveWritten);
188 }
189
190
191 file.flush();
192 }
193 }
194}
195
202
203bool QNetworkAccessFileBackend::loadFileInfo()
204{
205 QFileInfo fi(file);
208
209 // signal we're open
211
212 if (fi.isDir()) {
214 QCoreApplication::translate("QNetworkAccessFileBackend", "Cannot open %1: Path is a directory").arg(url().toString()));
215 finished();
216 return false;
217 }
218
219 return true;
220}
221
228
230{
232 return 0;
233 qint64 actuallyRead = file.read(data, maxlen);
234 if (actuallyRead <= 0) {
235 // EOF or error
236 if (file.error() != QFile::NoError) {
237 QString msg = QCoreApplication::translate("QNetworkAccessFileBackend", "Read error reading from %1: %2")
238 .arg(url().toString(), file.errorString());
240
241 finished();
242 return -1;
243 }
244
245 finished();
246 return actuallyRead;
247 }
248 if (!file.isSequential() && file.atEnd())
249 finished();
250 totalBytes += actuallyRead;
251 return actuallyRead;
252}
253
255
256#include "moc_qnetworkaccessfilebackend_p.cpp"
\inmodule QtCore
Definition qbytearray.h:57
static QString translate(const char *context, const char *key, const char *disambiguation=nullptr, int n=-1)
\threadsafe
bool flush()
Flushes any buffered data to the file.
bool atEnd() const override
Returns true if the end of the file has been reached; otherwise returns false.
FileError error() const
Returns the file error status.
bool isSequential() const override
Returns true if the file can only be manipulated sequentially; otherwise returns false.
void close() override
Calls QFileDevice::flush() and closes the file.
QFILE_MAYBE_NODISCARD bool open(OpenMode flags) override
Opens the file using OpenMode mode, returning true if successful; otherwise false.
Definition qfile.cpp:904
void setFileName(const QString &name)
Sets the name of the file.
Definition qfile.cpp:302
bool exists() const
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qfile.cpp:351
qint64 write(const char *data, qint64 len)
Writes at most maxSize bytes of data from data to the device.
qint64 peek(char *data, qint64 maxlen)
virtual qint64 bytesAvailable() const
Returns the number of bytes that are available for reading.
qint64 skip(qint64 maxSize)
QString errorString() const
Returns a human-readable description of the last device error that occurred.
void readChannelFinished()
qint64 read(char *data, qint64 maxlen)
Reads at most maxSize bytes from the device into data, and returns the number of bytes read.
QNetworkAccessBackend is the base class for implementing support for schemes used by QNetworkAccessMa...
QIODevice * uploadByteDevice()
Returns the upload byte device associated with the current request.
QNetworkAccessManager::Operation operation() const
Returns the operation which was requested when calling QNetworkAccessManager.
void readyRead()
Call this slot when you have more data available to notify the backend that we can attempt to read ag...
void finished()
Call this slot when there will be no more data available, regardless of whether the transfer was succ...
void setHeader(QNetworkRequest::KnownHeaders header, const QVariant &value)
Sets the value of the header to value.
QUrl url() const
Returns the current URL of the reply.
QIODevice * createUploadByteDevice()
Creates a QIODevice for the data provided to upload, if any.
TargetType
Use the values in this enum to specify what type of target the plugin supports.
void metaDataChanged()
Call this slot, if appropriate, after having processed and updated metadata (e.g.
void setUrl(const QUrl &url)
Sets the URL of the reply.
virtual QNetworkAccessBackend * create(QNetworkAccessManager::Operation op, const QNetworkRequest &request) const override
Override this method in your own class and return a heap-allocated instance of your class derived fro...
virtual QStringList supportedSchemes() const override
Override this method in your own derived class to let Qt know what schemes your class can handle.
void close() override
You must implement this function in your derived class.
qint64 bytesAvailable() const override
You must implement this function in your derived class.
void open() override
You must implement this in your derived class.
qint64 read(char *data, qint64 maxlen) override
Implement this function to support reading from the resource made available by your plugin.
Operation
Indicates the operation this reply is processing.
@ ContentOperationNotPermittedError
@ ProtocolInvalidOperationError
The QNetworkRequest class holds a request to be sent with QNetworkAccessManager.
QUrl url() const
Returns the URL this network request is referring to.
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2960
\inmodule QtCore
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:192
qsizetype size() const noexcept
Returns the number of characters in this string.
Definition qstring.h:186
int compare(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const noexcept
Definition qstring.cpp:6664
\inmodule QtCore
Definition qurl.h:94
bool isLocalFile() const
Definition qurl.cpp:3445
QString host(ComponentFormattingOptions=FullyDecoded) const
Returns the host of the URL if it is defined; otherwise an empty string is returned.
Definition qurl.cpp:2340
QString authority(ComponentFormattingOptions options=PrettyDecoded) const
Returns the authority of the URL if it is defined; otherwise an empty string is returned.
Definition qurl.cpp:2055
QString scheme() const
Returns the scheme of the URL.
Definition qurl.cpp:1991
@ RemoveFragment
Definition qurl.h:112
@ RemoveQuery
Definition qurl.h:111
@ RemoveAuthority
Definition qurl.h:109
void setHost(const QString &host, ParsingMode mode=DecodedMode)
Sets the host of the URL to host.
Definition qurl.cpp:2289
void setPath(const QString &path, ParsingMode mode=DecodedMode)
Sets the path of the URL to path.
Definition qurl.cpp:2414
QString toString(FormattingOptions options=FormattingOptions(PrettyDecoded)) const
Returns a string representation of the URL.
Definition qurl.cpp:2831
QString toLocalFile() const
Returns the path of this URL formatted as a local file path.
Definition qurl.cpp:3425
QString path(ComponentFormattingOptions options=FullyDecoded) const
Returns the path of the URL.
Definition qurl.cpp:2468
Combined button and popup list for selecting options.
@ CaseInsensitive
@ QueuedConnection
constexpr Initialization Uninitialized
DBusConnection const char DBusError * error
#define forever
Definition qforeach.h:78
#define SLOT(a)
Definition qobjectdefs.h:52
#define SIGNAL(a)
Definition qobjectdefs.h:53
GLenum mode
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
#define Q_ASSERT_X(cond, x, msg)
Definition qrandom.cpp:48
SSL_CTX int void * arg
#define QStringLiteral(str)
long long qint64
Definition qtypes.h:60
QUrl url("example.com")
[constructor-url-reference]
QNetworkRequest request(url)
char * toString(const MyType &t)
[31]
static bool invokeMethod(QObject *obj, const char *member, Qt::ConnectionType, QGenericReturnArgument ret, QGenericArgument val0=QGenericArgument(nullptr), QGenericArgument val1=QGenericArgument(), QGenericArgument val2=QGenericArgument(), QGenericArgument val3=QGenericArgument(), QGenericArgument val4=QGenericArgument(), QGenericArgument val5=QGenericArgument(), QGenericArgument val6=QGenericArgument(), QGenericArgument val7=QGenericArgument(), QGenericArgument val8=QGenericArgument(), QGenericArgument val9=QGenericArgument())
\threadsafe This is an overloaded member function, provided for convenience. It differs from the abov...