Qt 4.8
qnetworkaccessfilebackend.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
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 Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
43 #include "qfileinfo.h"
44 #include "qurlinfo.h"
45 #include "qdir.h"
46 #include "private/qnoncontiguousbytedevice_p.h"
47 
48 #include <QtCore/QCoreApplication>
49 
51 
54  const QNetworkRequest &request) const
55 {
56  // is it an operation we know of?
57  switch (op) {
60  break;
61 
62  default:
63  // no, we can't handle this operation
64  return 0;
65  }
66 
67  QUrl url = request.url();
68  if (url.scheme().compare(QLatin1String("qrc"), Qt::CaseInsensitive) == 0 || url.isLocalFile()) {
69  return new QNetworkAccessFileBackend;
70  } else if (!url.isEmpty() && url.authority().isEmpty()) {
71  // check if QFile could, in theory, open this URL via the file engines
72  // it has to be in the format:
73  // prefix:path/to/file
74  // or prefix:/path/to/file
75  //
76  // this construct here must match the one below in open()
78  // On Windows and Symbian the drive letter is detected as the scheme.
79  if (fi.exists() && (url.scheme().isEmpty() || (url.scheme().length() == 1)))
80  qWarning("QNetworkAccessFileBackendFactory: URL has no schema set, use file:// for files");
81  if (fi.exists() || (op == QNetworkAccessManager::PutOperation && fi.dir().exists()))
82  return new QNetworkAccessFileBackend;
83  }
84 
85  return 0;
86 }
87 
89  : uploadByteDevice(0), totalBytes(0), hasUploadFinished(false)
90 {
91 }
92 
94 {
95 }
96 
98 {
99  QUrl url = this->url();
100 
101  if (url.host() == QLatin1String("localhost"))
102  url.setHost(QString());
103 #if !defined(Q_OS_WIN)
104  // do not allow UNC paths on Unix
105  if (!url.host().isEmpty()) {
106  // we handle only local files
108  QCoreApplication::translate("QNetworkAccessFileBackend", "Request for opening non-local file %1").arg(url.toString()));
109  finished();
110  return;
111  }
112 #endif // !defined(Q_OS_WIN)
113  if (url.path().isEmpty())
114  url.setPath(QLatin1String("/"));
115  setUrl(url);
116 
117  QString fileName = url.toLocalFile();
118  if (fileName.isEmpty()) {
119  if (url.scheme() == QLatin1String("qrc"))
120  fileName = QLatin1Char(':') + url.path();
121  else
123  }
124  file.setFileName(fileName);
125 
127  if (!loadFileInfo())
128  return;
129  }
130 
131  QIODevice::OpenMode mode;
132  switch (operation()) {
134  mode = QIODevice::ReadOnly;
135  break;
140  QMetaObject::invokeMethod(this, "uploadReadyReadSlot", Qt::QueuedConnection);
141  break;
142  default:
143  Q_ASSERT_X(false, "QNetworkAccessFileBackend::open",
144  "Got a request operation I cannot handle!!");
145  return;
146  }
147 
148  mode |= QIODevice::Unbuffered;
149  bool opened = file.open(mode);
150 
151  // could we open the file?
152  if (!opened) {
153  QString msg = QCoreApplication::translate("QNetworkAccessFileBackend", "Error opening %1: %2")
154  .arg(this->url().toString(), file.errorString());
155 
156  // why couldn't we open the file?
157  // if we're opening for reading, either it doesn't exist, or it's access denied
158  // if we're opening for writing, not existing means it's access denied too
161  else
163  finished();
164  }
165 }
166 
168 {
169  if (hasUploadFinished)
170  return;
171 
172  forever {
173  qint64 haveRead;
174  const char *readPointer = uploadByteDevice->readPointer(-1, haveRead);
175  if (haveRead == -1) {
176  // EOF
177  hasUploadFinished = true;
178  file.flush();
179  file.close();
180  finished();
181  break;
182  } else if (haveRead == 0 || readPointer == 0) {
183  // nothing to read right now, we will be called again later
184  break;
185  } else {
186  qint64 haveWritten;
187  haveWritten = file.write(readPointer, haveRead);
188 
189  if (haveWritten < 0) {
190  // write error!
191  QString msg = QCoreApplication::translate("QNetworkAccessFileBackend", "Write error writing to %1: %2")
192  .arg(url().toString(), file.errorString());
194 
195  finished();
196  return;
197  } else {
198  uploadByteDevice->advanceReadPointer(haveWritten);
199  }
200 
201 
202  file.flush();
203  }
204  }
205 }
206 
208 {
210  file.close();
211  }
212 }
213 
215 {
216  Q_ASSERT_X(operation() == QNetworkAccessManager::GetOperation, "QNetworkAccessFileBackend",
217  "We're being told to download data but operation isn't GET!");
218 
220 }
221 
223 {
224  QFileInfo fi(file);
227 
228  // signal we're open
229  metaDataChanged();
230 
231  if (fi.isDir()) {
233  QCoreApplication::translate("QNetworkAccessFileBackend", "Cannot open %1: Path is a directory").arg(url().toString()));
234  finished();
235  return false;
236  }
237 
238  return true;
239 }
240 
242 {
243  qint64 wantToRead;
244  while ((wantToRead = nextDownstreamBlockSize()) > 0) {
245  // ### FIXME!!
246  // Obtain a pointer from the ringbuffer!
247  // Avoid extra copy
249  data.reserve(wantToRead);
250  qint64 actuallyRead = file.read(data.data(), wantToRead);
251  if (actuallyRead <= 0) {
252  // EOF or error
253  if (file.error() != QFile::NoError) {
254  QString msg = QCoreApplication::translate("QNetworkAccessFileBackend", "Read error reading from %1: %2")
255  .arg(url().toString(), file.errorString());
257 
258  finished();
259  return false;
260  }
261 
262  finished();
263  return true;
264  }
265 
266  data.resize(actuallyRead);
267  totalBytes += actuallyRead;
268 
269  QByteDataBuffer list;
270  list.append(data);
271  data.clear(); // important because of implicit sharing!
272  writeDownstreamData(list);
273  }
274  return true;
275 }
276 
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
char * data()
Returns a pointer to the data stored in the byte array.
Definition: qbytearray.h:429
QString toString(FormattingOptions options=None) const
Returns the human-displayable string representation of the URL.
Definition: qurl.cpp:5896
bool open(OpenMode flags)
Opens the file using OpenMode mode, returning true if successful; otherwise false.
Definition: qfile.cpp:1064
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:135
bool isEmpty() const
Returns true if the URL has no data; otherwise returns false.
Definition: qurl.cpp:4317
int length() const
Returns the number of characters in this string.
Definition: qstring.h:696
#define SLOT(a)
Definition: qobjectdefs.h:226
QString errorString() const
Returns a human-readable description of the last device error that occurred.
Definition: qiodevice.cpp:1671
Operation
Indicates the operation this reply is processing.
void setPath(const QString &path)
Sets the path of the URL to path.
Definition: qurl.cpp:4960
QLatin1String(DBUS_INTERFACE_DBUS))) Q_GLOBAL_STATIC_WITH_ARGS(QString
void append(QByteDataBuffer &other)
Definition: qbytedata_p.h:77
The QUrl class provides a convenient interface for working with URLs.
Definition: qurl.h:61
The QString class provides a Unicode character string.
Definition: qstring.h:83
QString host() const
Returns the host of the URL if it is defined; otherwise an empty string is returned.
Definition: qurl.cpp:4837
void setHost(const QString &host)
Sets the host of the URL to host.
Definition: qurl.cpp:4821
qint64 nextDownstreamBlockSize() const
QString path() const
Returns the path of the URL.
Definition: qurl.cpp:4977
QUrl url() const
Returns the URL this network request is referring to.
static QString translate(const char *context, const char *key, const char *disambiguation=0, Encoding encoding=CodecForTr)
virtual const char * readPointer(qint64 maximumLength, qint64 &len)=0
Return a byte pointer for at most maximumLength bytes of that device.
bool isLocalFile() const
Returns true if this URL is pointing to a local file path.
Definition: qurl.cpp:6453
qint64 read(char *data, qint64 maxlen)
Reads at most maxSize bytes from the device into data, and returns the number of bytes read...
Definition: qiodevice.cpp:791
bool exists() const
Returns true if the file specified by fileName() exists; otherwise returns false. ...
Definition: qfile.cpp:626
#define SIGNAL(a)
Definition: qobjectdefs.h:227
static QString toString(Register *reg, int type, bool *ok=0)
QNonContiguousByteDevice * createUploadByteDevice()
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
bool isDir() const
Returns true if this object points to a directory or to a symbolic link to a directory; otherwise ret...
Definition: qfileinfo.cpp:990
static bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
Creates a connection of the given type from the signal in the sender object to the method in the rece...
Definition: qobject.cpp:2580
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition: qstring.h:704
QString authority() const
Returns the authority of the URL if it is defined; otherwise an empty string is returned.
Definition: qurl.cpp:4592
bool flush()
Flushes any buffered data to the file.
Definition: qfile.cpp:1645
Q_CORE_EXPORT void qWarning(const char *,...)
static const char * data(const QByteArray &arr)
The QLatin1String class provides a thin wrapper around an US-ASCII/Latin-1 encoded string literal...
Definition: qstring.h:654
void setHeader(QNetworkRequest::KnownHeaders header, const QVariant &value)
__int64 qint64
Definition: qglobal.h:942
QNetworkAccessManager::Operation operation() const
QString toLocalFile() const
Returns the path of this URL formatted as a local file path.
Definition: qurl.cpp:6412
QString scheme() const
Returns the scheme of the URL.
Definition: qurl.cpp:4550
#define Q_ASSERT_X(cond, where, what)
Definition: qglobal.h:1837
QString arg(qlonglong a, int fieldwidth=0, int base=10, const QChar &fillChar=QLatin1Char(' ')) const Q_REQUIRED_RESULT
Definition: qstring.cpp:7186
void error(QNetworkReply::NetworkError code, const QString &errorString)
int compare(const QString &s) const
Definition: qstring.cpp:5037
qint64 size() const
Returns the file size in bytes.
Definition: qfileinfo.cpp:1248
virtual bool advanceReadPointer(qint64 amount)=0
The old readPointer is invalid after this call.
void setUrl(const QUrl &url)
virtual QNetworkAccessBackend * create(QNetworkAccessManager::Operation op, const QNetworkRequest &request) const
void resize(int size)
Sets the size of the byte array to size bytes.
void writeDownstreamData(QByteDataBuffer &list)
QNonContiguousByteDevice * uploadByteDevice
The QNetworkRequest class holds a request to be sent with QNetworkAccessManager.
static bool invokeMethod(QObject *obj, const char *member, Qt::ConnectionType, QGenericReturnArgument ret, QGenericArgument val0=QGenericArgument(0), 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())
Invokes the member (a signal or a slot name) on the object obj.
FileError error() const
Returns the file error status.
Definition: qfile.cpp:1984
qint64 write(const char *data, qint64 len)
Writes at most maxSize bytes of data from data to the device.
Definition: qiodevice.cpp:1342
The QFileInfo class provides system-independent file information.
Definition: qfileinfo.h:60
void reserve(int size)
Attempts to allocate memory for at least size bytes.
Definition: qbytearray.h:449
virtual void close()
Calls QFile::flush() and closes the file.
Definition: qfile.cpp:1680
static QString fileName(const QString &fileUrl)
The QLatin1Char class provides an 8-bit ASCII/Latin-1 character.
Definition: qchar.h:55
void clear()
Clears the contents of the byte array and makes it empty.
void setFileName(const QString &name)
Sets the name of the file.
Definition: qfile.cpp:494
QDateTime lastModified() const
Returns the date and time when the file was last modified.
Definition: qfileinfo.cpp:1296
#define forever
This macro is provided for convenience for writing infinite loops.
Definition: qglobal.h:2452