42 #include "qfilenetworkreply_p.h" |
42 #include "qfilenetworkreply_p.h" |
43 |
43 |
44 #include "QtCore/qdatetime.h" |
44 #include "QtCore/qdatetime.h" |
45 #include <QtCore/QCoreApplication> |
45 #include <QtCore/QCoreApplication> |
46 #include <QtCore/QFileInfo> |
46 #include <QtCore/QFileInfo> |
|
47 #include <QDebug> |
47 |
48 |
48 QT_BEGIN_NAMESPACE |
49 QT_BEGIN_NAMESPACE |
49 |
50 |
50 QFileNetworkReplyPrivate::QFileNetworkReplyPrivate() |
51 QFileNetworkReplyPrivate::QFileNetworkReplyPrivate() |
51 : QNetworkReplyPrivate(), realFileSize(0), finished(false) |
52 : QNetworkReplyPrivate(), realFileSize(0) |
52 { |
53 { |
53 } |
|
54 |
|
55 QFileNetworkReply::QFileNetworkReply(QObject *parent, const QNetworkRequest &req) |
|
56 : QNetworkReply(*new QFileNetworkReplyPrivate(), parent) |
|
57 { |
|
58 setRequest(req); |
|
59 setUrl(req.url()); |
|
60 setOperation(QNetworkAccessManager::GetOperation); |
|
61 QMetaObject::invokeMethod(this, "_q_startOperation", Qt::QueuedConnection); |
|
62 QNetworkReply::open(QIODevice::ReadOnly); |
|
63 } |
54 } |
64 |
55 |
65 QFileNetworkReply::~QFileNetworkReply() |
56 QFileNetworkReply::~QFileNetworkReply() |
66 { |
57 { |
67 } |
58 } |
68 |
59 |
69 // This code is mostly inspired by QNetworkAccessFileBackend |
60 QFileNetworkReply::QFileNetworkReply(QObject *parent, const QNetworkRequest &req, const QNetworkAccessManager::Operation op) |
70 // We also use its translation context for error messages |
61 : QNetworkReply(*new QFileNetworkReplyPrivate(), parent) |
71 void QFileNetworkReplyPrivate::_q_startOperation() |
|
72 { |
62 { |
73 Q_Q(QFileNetworkReply); |
63 setRequest(req); |
|
64 setUrl(req.url()); |
|
65 setOperation(op); |
|
66 QNetworkReply::open(QIODevice::ReadOnly); |
74 |
67 |
75 QUrl url = q->url(); |
68 qRegisterMetaType<QNetworkReply::NetworkError>("QNetworkReply::NetworkError"); |
|
69 |
|
70 QFileNetworkReplyPrivate *d = (QFileNetworkReplyPrivate*) d_func(); |
|
71 |
|
72 QUrl url = req.url(); |
76 if (url.host() == QLatin1String("localhost")) |
73 if (url.host() == QLatin1String("localhost")) |
77 url.setHost(QString()); |
74 url.setHost(QString()); |
78 |
75 |
79 #if !defined(Q_OS_WIN) |
76 #if !defined(Q_OS_WIN) |
80 // do not allow UNC paths on Unix |
77 // do not allow UNC paths on Unix |
81 if (!url.host().isEmpty()) { |
78 if (!url.host().isEmpty()) { |
82 // we handle only local files |
79 // we handle only local files |
83 QString msg = QCoreApplication::translate("QNetworkAccessFileBackend", "Request for opening non-local file %1").arg(url.toString()); |
80 QString msg = QCoreApplication::translate("QNetworkAccessFileBackend", "Request for opening non-local file %1").arg(url.toString()); |
84 q->setError(QNetworkReply::ProtocolInvalidOperationError, msg); |
81 setError(QNetworkReply::ProtocolInvalidOperationError, msg); |
85 emit q->error(QNetworkReply::ProtocolInvalidOperationError); |
82 QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection, |
86 doFinished(); |
83 Q_ARG(QNetworkReply::NetworkError, QNetworkReply::ProtocolInvalidOperationError)); |
|
84 QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection); |
87 return; |
85 return; |
88 } |
86 } |
89 #endif |
87 #endif |
90 if (url.path().isEmpty()) |
88 if (url.path().isEmpty()) |
91 url.setPath(QLatin1String("/")); |
89 url.setPath(QLatin1String("/")); |
92 q->setUrl(url); |
90 setUrl(url); |
93 |
91 |
94 |
92 |
95 QString fileName = url.toLocalFile(); |
93 QString fileName = url.toLocalFile(); |
96 if (fileName.isEmpty()) { |
94 if (fileName.isEmpty()) { |
97 fileName = url.toString(QUrl::RemoveAuthority | QUrl::RemoveFragment | QUrl::RemoveQuery); |
95 fileName = url.toString(QUrl::RemoveAuthority | QUrl::RemoveFragment | QUrl::RemoveQuery); |
98 } |
96 } |
99 realFile.setFileName(fileName); |
97 d->realFile.setFileName(fileName); |
100 |
98 |
101 QFileInfo fi(realFile); |
99 QFileInfo fi(d->realFile); |
102 if (fi.isDir()) { |
100 if (fi.isDir()) { |
103 QString msg = QCoreApplication::translate("QNetworkAccessFileBackend", "Cannot open %1: Path is a directory").arg(url.toString()); |
101 QString msg = QCoreApplication::translate("QNetworkAccessFileBackend", "Cannot open %1: Path is a directory").arg(url.toString()); |
104 q->setError(QNetworkReply::ContentOperationNotPermittedError, msg); |
102 setError(QNetworkReply::ContentOperationNotPermittedError, msg); |
105 emit q->error(QNetworkReply::ContentOperationNotPermittedError); |
103 QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection, |
106 doFinished(); |
104 Q_ARG(QNetworkReply::NetworkError, QNetworkReply::ContentOperationNotPermittedError)); |
|
105 QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection); |
107 return; |
106 return; |
108 } |
107 } |
109 |
108 |
110 bool opened = realFile.open(QIODevice::ReadOnly | QIODevice::Unbuffered); |
109 bool opened = d->realFile.open(QIODevice::ReadOnly | QIODevice::Unbuffered); |
111 |
110 |
112 // could we open the file? |
111 // could we open the file? |
113 if (!opened) { |
112 if (!opened) { |
114 QString msg = QCoreApplication::translate("QNetworkAccessFileBackend", "Error opening %1: %2") |
113 QString msg = QCoreApplication::translate("QNetworkAccessFileBackend", "Error opening %1: %2") |
115 .arg(realFile.fileName(), realFile.errorString()); |
114 .arg(d->realFile.fileName(), d->realFile.errorString()); |
116 |
115 |
117 if (realFile.exists()) { |
116 if (d->realFile.exists()) { |
118 q->setError(QNetworkReply::ContentAccessDenied, msg); |
117 setError(QNetworkReply::ContentAccessDenied, msg); |
119 emit q->error(QNetworkReply::ContentAccessDenied); |
118 QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection, |
|
119 Q_ARG(QNetworkReply::NetworkError, QNetworkReply::ContentAccessDenied)); |
120 } else { |
120 } else { |
121 q->setError(QNetworkReply::ContentNotFoundError, msg); |
121 setError(QNetworkReply::ContentNotFoundError, msg); |
122 emit q->error(QNetworkReply::ContentNotFoundError); |
122 QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection, |
|
123 Q_ARG(QNetworkReply::NetworkError, QNetworkReply::ContentNotFoundError)); |
123 } |
124 } |
124 doFinished(); |
125 QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection); |
125 return; |
126 return; |
126 } |
127 } |
127 |
128 |
128 realFileSize = fi.size(); |
129 d->realFileSize = fi.size(); |
129 q->setHeader(QNetworkRequest::LastModifiedHeader, fi.lastModified()); |
130 setHeader(QNetworkRequest::LastModifiedHeader, fi.lastModified()); |
130 q->setHeader(QNetworkRequest::ContentLengthHeader, realFileSize); |
131 setHeader(QNetworkRequest::ContentLengthHeader, d->realFileSize); |
131 |
132 |
132 emit q->metaDataChanged(); |
133 QMetaObject::invokeMethod(this, "metaDataChanged", Qt::QueuedConnection); |
133 emit q->downloadProgress(realFileSize, realFileSize); |
134 QMetaObject::invokeMethod(this, "downloadProgress", Qt::QueuedConnection, |
134 emit q->readyRead(); |
135 Q_ARG(qint64, d->realFileSize), Q_ARG(qint64, d->realFileSize)); |
135 doFinished(); |
136 QMetaObject::invokeMethod(this, "readyRead", Qt::QueuedConnection); |
|
137 QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection); |
136 } |
138 } |
137 |
139 |
138 bool QFileNetworkReplyPrivate::isFinished() const |
140 bool QFileNetworkReplyPrivate::isFinished() const |
139 { |
141 { |
140 return finished; |
142 return true; |
141 } |
143 } |
142 |
|
143 void QFileNetworkReplyPrivate::doFinished() |
|
144 { |
|
145 Q_Q(QFileNetworkReply); |
|
146 finished = true; |
|
147 emit q->finished(); |
|
148 } |
|
149 |
|
150 |
144 |
151 void QFileNetworkReply::close() |
145 void QFileNetworkReply::close() |
152 { |
146 { |
153 Q_D(QFileNetworkReply); |
147 Q_D(QFileNetworkReply); |
154 QNetworkReply::close(); |
148 QNetworkReply::close(); |
155 d->realFile.close(); |
149 d->realFile.close(); |
156 |
|
157 if (!d->finished) |
|
158 d->doFinished(); |
|
159 } |
150 } |
160 |
151 |
161 void QFileNetworkReply::abort() |
152 void QFileNetworkReply::abort() |
162 { |
153 { |
163 Q_D(QFileNetworkReply); |
154 Q_D(QFileNetworkReply); |
164 QNetworkReply::close(); |
155 QNetworkReply::close(); |
165 d->realFile.close(); |
156 d->realFile.close(); |
166 |
|
167 if (!d->finished) |
|
168 d->doFinished(); |
|
169 } |
157 } |
170 |
158 |
171 qint64 QFileNetworkReply::bytesAvailable() const |
159 qint64 QFileNetworkReply::bytesAvailable() const |
172 { |
160 { |
173 Q_D(const QFileNetworkReply); |
161 Q_D(const QFileNetworkReply); |