Line | Source Code | Coverage |
---|
1 | /**************************************************************************** | - |
2 | ** | - |
3 | ** Copyright (C) 2013 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 | | - |
42 | #include "qnetworkaccessfilebackend_p.h" | - |
43 | #include "qfileinfo.h" | - |
44 | #include "qurlinfo_p.h" | - |
45 | #include "qdir.h" | - |
46 | #include "private/qnoncontiguousbytedevice_p.h" | - |
47 | | - |
48 | #include <QtCore/QCoreApplication> | - |
49 | | - |
50 | QT_BEGIN_NAMESPACE | - |
51 | | - |
52 | QNetworkAccessBackend * | - |
53 | QNetworkAccessFileBackendFactory::create(QNetworkAccessManager::Operation op, | - |
54 | const QNetworkRequest &request) const | - |
55 | { | - |
56 | // is it an operation we know of? | - |
57 | switch (op) { | - |
58 | case QNetworkAccessManager::GetOperation: | - |
59 | case QNetworkAccessManager::PutOperation: | - |
60 | break; executed: break; Execution Count:47 | 47 |
61 | | - |
62 | default: | - |
63 | // no, we can't handle this operation | - |
64 | return 0; never executed: return 0; | 0 |
65 | } | - |
66 | | - |
67 | QUrl url = request.url(); executed (the execution status of this line is deduced): QUrl url = request.url(); | - |
68 | if (url.scheme().compare(QLatin1String("qrc"), Qt::CaseInsensitive) == 0 || url.isLocalFile()) { partially evaluated: url.scheme().compare(QLatin1String("qrc"), Qt::CaseInsensitive) == 0 no Evaluation Count:0 | yes Evaluation Count:47 |
evaluated: url.isLocalFile() yes Evaluation Count:39 | yes Evaluation Count:8 |
| 0-47 |
69 | return new QNetworkAccessFileBackend; executed: return new QNetworkAccessFileBackend; Execution Count:39 | 39 |
70 | } else if (!url.scheme().isEmpty() && url.authority().isEmpty() && (url.scheme().length() > 1)) { evaluated: !url.scheme().isEmpty() yes Evaluation Count:5 | yes Evaluation Count:3 |
evaluated: url.authority().isEmpty() yes Evaluation Count:4 | yes Evaluation Count:1 |
partially evaluated: (url.scheme().length() > 1) yes Evaluation Count:4 | no Evaluation Count:0 |
| 0-5 |
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() | - |
77 | QFileInfo fi(url.toString(QUrl::RemoveAuthority | QUrl::RemoveFragment | QUrl::RemoveQuery)); executed (the execution status of this line is deduced): QFileInfo fi(url.toString(QUrl::RemoveAuthority | QUrl::RemoveFragment | QUrl::RemoveQuery)); | - |
78 | if (fi.exists() || (op == QNetworkAccessManager::PutOperation && fi.dir().exists())) partially evaluated: fi.exists() yes Evaluation Count:4 | no Evaluation Count:0 |
never evaluated: op == QNetworkAccessManager::PutOperation never evaluated: fi.dir().exists() | 0-4 |
79 | return new QNetworkAccessFileBackend; executed: return new QNetworkAccessFileBackend; Execution Count:4 | 4 |
80 | } | 0 |
81 | | - |
82 | return 0; executed: return 0; Execution Count:4 | 4 |
83 | } | - |
84 | | - |
85 | QNetworkAccessFileBackend::QNetworkAccessFileBackend() | - |
86 | : uploadByteDevice(0), totalBytes(0), hasUploadFinished(false) | - |
87 | { | - |
88 | } executed: } Execution Count:43 | 43 |
89 | | - |
90 | QNetworkAccessFileBackend::~QNetworkAccessFileBackend() | - |
91 | { | - |
92 | } | - |
93 | | - |
94 | void QNetworkAccessFileBackend::open() | - |
95 | { | - |
96 | QUrl url = this->url(); executed (the execution status of this line is deduced): QUrl url = this->url(); | - |
97 | | - |
98 | if (url.host() == QLatin1String("localhost")) partially evaluated: url.host() == QLatin1String("localhost") no Evaluation Count:0 | yes Evaluation Count:43 |
| 0-43 |
99 | url.setHost(QString()); never executed: url.setHost(QString()); | 0 |
100 | #if !defined(Q_OS_WIN) | - |
101 | // do not allow UNC paths on Unix | - |
102 | if (!url.host().isEmpty()) { partially evaluated: !url.host().isEmpty() no Evaluation Count:0 | yes Evaluation Count:43 |
| 0-43 |
103 | // we handle only local files | - |
104 | error(QNetworkReply::ProtocolInvalidOperationError, never executed (the execution status of this line is deduced): error(QNetworkReply::ProtocolInvalidOperationError, | - |
105 | QCoreApplication::translate("QNetworkAccessFileBackend", "Request for opening non-local file %1").arg(url.toString())); never executed (the execution status of this line is deduced): QCoreApplication::translate("QNetworkAccessFileBackend", "Request for opening non-local file %1").arg(url.toString())); | - |
106 | finished(); never executed (the execution status of this line is deduced): finished(); | - |
107 | return; | 0 |
108 | } | - |
109 | #endif // !defined(Q_OS_WIN) | - |
110 | if (url.path().isEmpty()) partially evaluated: url.path().isEmpty() no Evaluation Count:0 | yes Evaluation Count:43 |
| 0-43 |
111 | url.setPath(QLatin1String("/")); never executed: url.setPath(QLatin1String("/")); | 0 |
112 | setUrl(url); executed (the execution status of this line is deduced): setUrl(url); | - |
113 | | - |
114 | QString fileName = url.toLocalFile(); executed (the execution status of this line is deduced): QString fileName = url.toLocalFile(); | - |
115 | if (fileName.isEmpty()) { evaluated: fileName.isEmpty() yes Evaluation Count:4 | yes Evaluation Count:39 |
| 4-39 |
116 | if (url.scheme() == QLatin1String("qrc")) partially evaluated: url.scheme() == QLatin1String("qrc") no Evaluation Count:0 | yes Evaluation Count:4 |
| 0-4 |
117 | fileName = QLatin1Char(':') + url.path(); never executed: fileName = QLatin1Char(':') + url.path(); | 0 |
118 | else | - |
119 | fileName = url.toString(QUrl::RemoveAuthority | QUrl::RemoveFragment | QUrl::RemoveQuery); executed: fileName = url.toString(QUrl::RemoveAuthority | QUrl::RemoveFragment | QUrl::RemoveQuery); Execution Count:4 | 4 |
120 | } | - |
121 | file.setFileName(fileName); executed (the execution status of this line is deduced): file.setFileName(fileName); | - |
122 | | - |
123 | if (operation() == QNetworkAccessManager::GetOperation) { evaluated: operation() == QNetworkAccessManager::GetOperation yes Evaluation Count:4 | yes Evaluation Count:39 |
| 4-39 |
124 | if (!loadFileInfo()) partially evaluated: !loadFileInfo() no Evaluation Count:0 | yes Evaluation Count:4 |
| 0-4 |
125 | return; | 0 |
126 | } executed: } Execution Count:4 | 4 |
127 | | - |
128 | QIODevice::OpenMode mode; executed (the execution status of this line is deduced): QIODevice::OpenMode mode; | - |
129 | switch (operation()) { | - |
130 | case QNetworkAccessManager::GetOperation: | - |
131 | mode = QIODevice::ReadOnly; executed (the execution status of this line is deduced): mode = QIODevice::ReadOnly; | - |
132 | break; executed: break; Execution Count:4 | 4 |
133 | case QNetworkAccessManager::PutOperation: | - |
134 | mode = QIODevice::WriteOnly | QIODevice::Truncate; executed (the execution status of this line is deduced): mode = QIODevice::WriteOnly | QIODevice::Truncate; | - |
135 | uploadByteDevice = createUploadByteDevice(); executed (the execution status of this line is deduced): uploadByteDevice = createUploadByteDevice(); | - |
136 | QObject::connect(uploadByteDevice, SIGNAL(readyRead()), this, SLOT(uploadReadyReadSlot())); executed (the execution status of this line is deduced): QObject::connect(uploadByteDevice, "2""readyRead()", this, "1""uploadReadyReadSlot()"); | - |
137 | QMetaObject::invokeMethod(this, "uploadReadyReadSlot", Qt::QueuedConnection); executed (the execution status of this line is deduced): QMetaObject::invokeMethod(this, "uploadReadyReadSlot", Qt::QueuedConnection); | - |
138 | break; executed: break; Execution Count:39 | 39 |
139 | default: | - |
140 | Q_ASSERT_X(false, "QNetworkAccessFileBackend::open", never executed (the execution status of this line is deduced): qt_noop(); | - |
141 | "Got a request operation I cannot handle!!"); | - |
142 | return; | 0 |
143 | } | - |
144 | | - |
145 | mode |= QIODevice::Unbuffered; executed (the execution status of this line is deduced): mode |= QIODevice::Unbuffered; | - |
146 | bool opened = file.open(mode); executed (the execution status of this line is deduced): bool opened = file.open(mode); | - |
147 | | - |
148 | // could we open the file? | - |
149 | if (!opened) { partially evaluated: !opened no Evaluation Count:0 | yes Evaluation Count:43 |
| 0-43 |
150 | QString msg = QCoreApplication::translate("QNetworkAccessFileBackend", "Error opening %1: %2") never executed (the execution status of this line is deduced): QString msg = QCoreApplication::translate("QNetworkAccessFileBackend", "Error opening %1: %2") | - |
151 | .arg(this->url().toString(), file.errorString()); never executed (the execution status of this line is deduced): .arg(this->url().toString(), file.errorString()); | - |
152 | | - |
153 | // why couldn't we open the file? | - |
154 | // if we're opening for reading, either it doesn't exist, or it's access denied | - |
155 | // if we're opening for writing, not existing means it's access denied too | - |
156 | if (file.exists() || operation() == QNetworkAccessManager::PutOperation) never evaluated: file.exists() never evaluated: operation() == QNetworkAccessManager::PutOperation | 0 |
157 | error(QNetworkReply::ContentAccessDenied, msg); never executed: error(QNetworkReply::ContentAccessDenied, msg); | 0 |
158 | else | - |
159 | error(QNetworkReply::ContentNotFoundError, msg); never executed: error(QNetworkReply::ContentNotFoundError, msg); | 0 |
160 | finished(); never executed (the execution status of this line is deduced): finished(); | - |
161 | } | 0 |
162 | } executed: } Execution Count:43 | 43 |
163 | | - |
164 | void QNetworkAccessFileBackend::uploadReadyReadSlot() | - |
165 | { | - |
166 | if (hasUploadFinished) evaluated: hasUploadFinished yes Evaluation Count:2 | yes Evaluation Count:148 |
| 2-148 |
167 | return; executed: return; Execution Count:2 | 2 |
168 | | - |
169 | forever { executed (the execution status of this line is deduced): for(;;) { | - |
170 | qint64 haveRead; executed (the execution status of this line is deduced): qint64 haveRead; | - |
171 | const char *readPointer = uploadByteDevice->readPointer(-1, haveRead); executed (the execution status of this line is deduced): const char *readPointer = uploadByteDevice->readPointer(-1, haveRead); | - |
172 | if (haveRead == -1) { evaluated: haveRead == -1 yes Evaluation Count:39 | yes Evaluation Count:692 |
| 39-692 |
173 | // EOF | - |
174 | hasUploadFinished = true; executed (the execution status of this line is deduced): hasUploadFinished = true; | - |
175 | file.flush(); executed (the execution status of this line is deduced): file.flush(); | - |
176 | file.close(); executed (the execution status of this line is deduced): file.close(); | - |
177 | finished(); executed (the execution status of this line is deduced): finished(); | - |
178 | break; executed: break; Execution Count:39 | 39 |
179 | } else if (haveRead == 0 || readPointer == 0) { evaluated: haveRead == 0 yes Evaluation Count:109 | yes Evaluation Count:583 |
partially evaluated: readPointer == 0 no Evaluation Count:0 | yes Evaluation Count:583 |
| 0-583 |
180 | // nothing to read right now, we will be called again later | - |
181 | break; executed: break; Execution Count:109 | 109 |
182 | } else { | - |
183 | qint64 haveWritten; executed (the execution status of this line is deduced): qint64 haveWritten; | - |
184 | haveWritten = file.write(readPointer, haveRead); executed (the execution status of this line is deduced): haveWritten = file.write(readPointer, haveRead); | - |
185 | | - |
186 | if (haveWritten < 0) { partially evaluated: haveWritten < 0 no Evaluation Count:0 | yes Evaluation Count:583 |
| 0-583 |
187 | // write error! | - |
188 | QString msg = QCoreApplication::translate("QNetworkAccessFileBackend", "Write error writing to %1: %2") never executed (the execution status of this line is deduced): QString msg = QCoreApplication::translate("QNetworkAccessFileBackend", "Write error writing to %1: %2") | - |
189 | .arg(url().toString(), file.errorString()); never executed (the execution status of this line is deduced): .arg(url().toString(), file.errorString()); | - |
190 | error(QNetworkReply::ProtocolFailure, msg); never executed (the execution status of this line is deduced): error(QNetworkReply::ProtocolFailure, msg); | - |
191 | | - |
192 | finished(); never executed (the execution status of this line is deduced): finished(); | - |
193 | return; | 0 |
194 | } else { | - |
195 | uploadByteDevice->advanceReadPointer(haveWritten); executed (the execution status of this line is deduced): uploadByteDevice->advanceReadPointer(haveWritten); | - |
196 | } executed: } Execution Count:583 | 583 |
197 | | - |
198 | | - |
199 | file.flush(); executed (the execution status of this line is deduced): file.flush(); | - |
200 | } executed: } Execution Count:583 | 583 |
201 | } | - |
202 | } executed: } Execution Count:148 | 148 |
203 | | - |
204 | void QNetworkAccessFileBackend::closeDownstreamChannel() | - |
205 | { | - |
206 | if (operation() == QNetworkAccessManager::GetOperation) { never evaluated: operation() == QNetworkAccessManager::GetOperation | 0 |
207 | file.close(); never executed (the execution status of this line is deduced): file.close(); | - |
208 | } | 0 |
209 | } | 0 |
210 | | - |
211 | void QNetworkAccessFileBackend::downstreamReadyWrite() | - |
212 | { | - |
213 | Q_ASSERT_X(operation() == QNetworkAccessManager::GetOperation, "QNetworkAccessFileBackend", executed (the execution status of this line is deduced): qt_noop(); | - |
214 | "We're being told to download data but operation isn't GET!"); | - |
215 | | - |
216 | readMoreFromFile(); executed (the execution status of this line is deduced): readMoreFromFile(); | - |
217 | } executed: } Execution Count:4 | 4 |
218 | | - |
219 | bool QNetworkAccessFileBackend::loadFileInfo() | - |
220 | { | - |
221 | QFileInfo fi(file); executed (the execution status of this line is deduced): QFileInfo fi(file); | - |
222 | setHeader(QNetworkRequest::LastModifiedHeader, fi.lastModified()); executed (the execution status of this line is deduced): setHeader(QNetworkRequest::LastModifiedHeader, fi.lastModified()); | - |
223 | setHeader(QNetworkRequest::ContentLengthHeader, fi.size()); executed (the execution status of this line is deduced): setHeader(QNetworkRequest::ContentLengthHeader, fi.size()); | - |
224 | | - |
225 | // signal we're open | - |
226 | metaDataChanged(); executed (the execution status of this line is deduced): metaDataChanged(); | - |
227 | | - |
228 | if (fi.isDir()) { partially evaluated: fi.isDir() no Evaluation Count:0 | yes Evaluation Count:4 |
| 0-4 |
229 | error(QNetworkReply::ContentOperationNotPermittedError, never executed (the execution status of this line is deduced): error(QNetworkReply::ContentOperationNotPermittedError, | - |
230 | QCoreApplication::translate("QNetworkAccessFileBackend", "Cannot open %1: Path is a directory").arg(url().toString())); never executed (the execution status of this line is deduced): QCoreApplication::translate("QNetworkAccessFileBackend", "Cannot open %1: Path is a directory").arg(url().toString())); | - |
231 | finished(); never executed (the execution status of this line is deduced): finished(); | - |
232 | return false; never executed: return false; | 0 |
233 | } | - |
234 | | - |
235 | return true; executed: return true; Execution Count:4 | 4 |
236 | } | - |
237 | | - |
238 | bool QNetworkAccessFileBackend::readMoreFromFile() | - |
239 | { | - |
240 | qint64 wantToRead; executed (the execution status of this line is deduced): qint64 wantToRead; | - |
241 | while ((wantToRead = nextDownstreamBlockSize()) > 0) { partially evaluated: (wantToRead = nextDownstreamBlockSize()) > 0 yes Evaluation Count:38 | no Evaluation Count:0 |
| 0-38 |
242 | // ### FIXME!! | - |
243 | // Obtain a pointer from the ringbuffer! | - |
244 | // Avoid extra copy | - |
245 | QByteArray data; executed (the execution status of this line is deduced): QByteArray data; | - |
246 | data.reserve(wantToRead); executed (the execution status of this line is deduced): data.reserve(wantToRead); | - |
247 | qint64 actuallyRead = file.read(data.data(), wantToRead); executed (the execution status of this line is deduced): qint64 actuallyRead = file.read(data.data(), wantToRead); | - |
248 | if (actuallyRead <= 0) { evaluated: actuallyRead <= 0 yes Evaluation Count:4 | yes Evaluation Count:34 |
| 4-34 |
249 | // EOF or error | - |
250 | if (file.error() != QFile::NoError) { partially evaluated: file.error() != QFile::NoError no Evaluation Count:0 | yes Evaluation Count:4 |
| 0-4 |
251 | QString msg = QCoreApplication::translate("QNetworkAccessFileBackend", "Read error reading from %1: %2") never executed (the execution status of this line is deduced): QString msg = QCoreApplication::translate("QNetworkAccessFileBackend", "Read error reading from %1: %2") | - |
252 | .arg(url().toString(), file.errorString()); never executed (the execution status of this line is deduced): .arg(url().toString(), file.errorString()); | - |
253 | error(QNetworkReply::ProtocolFailure, msg); never executed (the execution status of this line is deduced): error(QNetworkReply::ProtocolFailure, msg); | - |
254 | | - |
255 | finished(); never executed (the execution status of this line is deduced): finished(); | - |
256 | return false; never executed: return false; | 0 |
257 | } | - |
258 | | - |
259 | finished(); executed (the execution status of this line is deduced): finished(); | - |
260 | return true; executed: return true; Execution Count:4 | 4 |
261 | } | - |
262 | | - |
263 | data.resize(actuallyRead); executed (the execution status of this line is deduced): data.resize(actuallyRead); | - |
264 | totalBytes += actuallyRead; executed (the execution status of this line is deduced): totalBytes += actuallyRead; | - |
265 | | - |
266 | QByteDataBuffer list; executed (the execution status of this line is deduced): QByteDataBuffer list; | - |
267 | list.append(data); executed (the execution status of this line is deduced): list.append(data); | - |
268 | data.clear(); // important because of implicit sharing! executed (the execution status of this line is deduced): data.clear(); | - |
269 | writeDownstreamData(list); executed (the execution status of this line is deduced): writeDownstreamData(list); | - |
270 | } executed: } Execution Count:34 | 34 |
271 | return true; never executed: return true; | 0 |
272 | } | - |
273 | | - |
274 | QT_END_NAMESPACE | - |
275 | | - |
| | |