comparison ui/downloader.cpp @ 910:eaed02defe6a

More SSLConnection refactoring. Fixes curl downloader.
author Andre Heinecke <andre.heinecke@intevation.de>
date Mon, 18 Aug 2014 18:51:33 +0200
parents d1c951b3012d
children 75085f7adc78
comparison
equal deleted inserted replaced
909:18e3ad073b38 910:eaed02defe6a
76 } 76 }
77 } 77 }
78 return cDir.absolutePath(); 78 return cDir.absolutePath();
79 } 79 }
80 80
81 QMap<QString, QString> Downloader::parseHeaders(QByteArray *data)
82 {
83 int bodyStart = data->indexOf("\r\n\r\n");
84 QMap<QString, QString> retval;
85 QByteArray headers;
86 QString response(*data);
87 if (bodyStart == -1) {
88 qDebug() << "Could not find header end.";
89 emit error(tr("Invalid response"),
90 SSLConnection::InvalidResponse);
91 return retval;
92 }
93
94 /* Take the headers with one additional line break */
95 headers = data->left(bodyStart + 2);
96 /* Chop off the head */
97
98 foreach (const QString& line, response.split("\r\n")) {
99 int sepPos = -1;
100 sepPos = line.indexOf(": ");
101 if (sepPos == -1) {
102 continue;
103 }
104 QString key = line.left(sepPos);
105 QString value = line.right(line.size() - sepPos - 2);
106
107 retval.insert(key, value);
108 }
109
110 *data = data->right(data->size() - bodyStart - 4);
111 return retval;
112 }
113
114 QDateTime Downloader::getLastModifiedHeader(const QString &resource) {
115 int ret = -1;
116 QByteArray response;
117 QLocale cLocale = QLocale::c();
118 QMap<QString, QString> headers;
119 QString headRequest =
120 QString::fromLatin1("HEAD %1 HTTP/1.0\r\n\r\n").arg(resource);
121
122 ret = mSSLConnection->write(headRequest.toUtf8());
123 if (ret != 0) {
124 emit error (tr("Connection lost"), SSLConnection::ConnectionLost);
125 return QDateTime();
126 }
127
128 response = mSSLConnection->read(1024);
129
130 qDebug() << "Response from server was: " << response;
131
132 if (response.isNull()) {
133 qDebug() << "No response";
134 emit error (tr("Connection lost"), SSLConnection::ConnectionLost);
135 return QDateTime();
136 }
137
138 headers = parseHeaders(&response);
139 const QString lastModified = headers.value("Last-Modified");
140 if (!lastModified.isEmpty()) {
141 QDateTime candidate = cLocale.toDateTime(lastModified,
142 "ddd, dd MMM yyyy HH:mm:ss' GMT'");
143 if (candidate.isValid()) {
144 return candidate;
145 }
146 }
147 emit error (tr("Invalid response from the server"), SSLConnection::InvalidResponse);
148 return QDateTime();
149 }
150
151 bool Downloader::downloadFile(const QString &resource,
152 const QString &fileName,
153 size_t maxSize)
154 {
155 int ret = -1;
156 size_t bytesRead = 0;
157 QString getRequest =
158 QString::fromLatin1("GET %1 HTTP/1.0\r\n\r\n").arg(resource);
159
160 QSaveFile outputFile(fileName);
161
162 ret = mSSLConnection->write(getRequest.toUtf8());
163
164 // Open / Create the file to write to.
165 if (!outputFile.open(QIODevice::WriteOnly)) {
166 qDebug() << "Failed to open file";
167 return false;
168 }
169
170 if (ret != 0) {
171 emit error(tr("Connection lost"), SSLConnection::ConnectionLost);
172 return false;
173 }
174
175 bool inBody = false;
176 QMap <QString, QString> headers;
177 do {
178 /* Read the response in 8KiB chunks */
179 int responseSize = 0;
180 QByteArray response = mSSLConnection->read(8192);
181 if (response.isNull()) {
182 qDebug() << "Error reading response";
183 emit error(tr("Connection lost"), SSLConnection::ConnectionLost);
184 return false;
185 }
186 responseSize = response.size();
187 if (!inBody) {
188 headers = parseHeaders(&response);
189 inBody = true;
190 }
191 outputFile.write(response);
192 bytesRead += responseSize;
193 if (responseSize < 8192) {
194 /* Nothing more to read */
195 break;
196 }
197 /* TODO Emit progress */
198 } while (bytesRead < maxSize);
199
200 return outputFile.commit();
201 }
202 81
203 void Downloader::run() { 82 void Downloader::run() {
204 int ret; 83 int ret;
205 QDateTime remoteModList; 84 QDateTime remoteModList;
206 QDateTime remoteModSW; 85 QDateTime remoteModSW;
218 return; 97 return;
219 } 98 }
220 99
221 emit progress(tr("Connected"), 1, -1); 100 emit progress(tr("Connected"), 1, -1);
222 101
223 remoteModSW = getLastModifiedHeader(mResourceSW); 102 remoteModSW = mSSLConnection->getLastModifiedHeader(mResourceSW);
224 emit lastModifiedDate(remoteModSW); 103 emit lastModifiedDate(remoteModSW);
225 104
226 if (!remoteModSW.isValid()) { 105 if (!remoteModSW.isValid()) {
106 emit error (tr("Connection failed."), SSLConnection::InvalidResponse);
227 qDebug() << "Could not parse headers for Software"; 107 qDebug() << "Could not parse headers for Software";
228 return; 108 return;
229 } 109 }
230 110
231 if (!mLastModSW.isValid() || remoteModSW > mLastModSW) { 111 if (!mLastModSW.isValid() || remoteModSW > mLastModSW) {
245 #endif 125 #endif
246 126
247 qDebug() << "fileName: " << fileName; 127 qDebug() << "fileName: " << fileName;
248 128
249 if (mDownloadSW) { 129 if (mDownloadSW) {
250 if (!downloadFile(mResourceSW, fileName, MAX_SW_SIZE)) { 130 if (!mSSLConnection->downloadFile(mResourceSW, fileName, MAX_SW_SIZE)) {
131 emit error(tr("Failed to download File"), SSLConnection::ConnectionLost);
251 qDebug() << "Failed to download software update."; 132 qDebug() << "Failed to download software update.";
252 return; 133 return;
253 } 134 }
254 QFile::setPermissions(fileName, QFileDevice::ReadOwner | 135 QFile::setPermissions(fileName, QFileDevice::ReadOwner |
255 QFileDevice::WriteOwner | 136 QFileDevice::WriteOwner |
258 139
259 emit newSoftwareAvailable(fileName, remoteModSW); 140 emit newSoftwareAvailable(fileName, remoteModSW);
260 return; 141 return;
261 } 142 }
262 143
263 remoteModList = getLastModifiedHeader(mResourceList); 144 remoteModList = mSSLConnection->getLastModifiedHeader(mResourceList);
264 if (!remoteModList.isValid()) { 145 if (!remoteModList.isValid()) {
146 emit error (tr("Connection failed."), SSLConnection::InvalidResponse);
265 qDebug() << "Could not parse headers for List"; 147 qDebug() << "Could not parse headers for List";
266 return; 148 return;
267 } 149 }
268 150
269 if (!mLastModList.isValid() || remoteModList > mLastModList) { 151 if (!mLastModList.isValid() || remoteModList > mLastModList) {
278 .append(remoteModList.toString("yyyyMMddHHmmss")) 160 .append(remoteModList.toString("yyyyMMddHHmmss"))
279 .append(".txt"); 161 .append(".txt");
280 162
281 qDebug() << "fileName: " << fileName; 163 qDebug() << "fileName: " << fileName;
282 164
283 if (!downloadFile(mResourceList, fileName, MAX_LIST_SIZE)) { 165 if (!mSSLConnection->downloadFile(mResourceList, fileName, MAX_LIST_SIZE)) {
284 return; 166 return;
285 } 167 }
286 168
287 emit newListAvailable(fileName, remoteModList); 169 emit newListAvailable(fileName, remoteModList);
288 } 170 }

http://wald.intevation.org/projects/trustbridge/