Mercurial > trustbridge
view ui/downloader.cpp @ 754:27043d74dc90
(Issue25) Align header contents in their own column.
We now also stretch column 3 so that the contents are aligned
with the descriptive labels without a space in between.
Sadly this causes the quit button to be resized to it's minimum
instead of sharing the space with the installation button as the
installation button is so large that it squeezes the push button.
author | Andre Heinecke <andre.heinecke@intevation.de> |
---|---|
date | Mon, 07 Jul 2014 12:38:33 +0200 |
parents | cb044efdaf0d |
children | 13cf42dbe9bd |
line wrap: on
line source
/* Copyright (C) 2014 by Bundesamt für Sicherheit in der Informationstechnik * Software engineering by Intevation GmbH * * This file is Free Software under the GNU GPL (v>=2) * and comes with ABSOLUTELY NO WARRANTY! * See LICENSE.txt for details. */ #include "downloader.h" #ifndef DOWNLOAD_SERVER #define DOWNLOAD_SERVER "https://www.intevation.de" #endif #include <QFile> #include <QDir> #include <QDebug> #include <QStandardPaths> #include <QLocale> #include <QSaveFile> #include <polarssl/net.h> #include <polarssl/ssl.h> #include <polarssl/entropy.h> #include <polarssl/ctr_drbg.h> #include <polarssl/error.h> #include <polarssl/certs.h> #define MAX_SW_SIZE 10485760 #define MAX_LIST_SIZE 1048576 Downloader::Downloader(QObject* parent, const QString& url, const QByteArray& certificate, const QDateTime& newestSW, const QDateTime& newestList, const QString& resourceSW, const QString& resourceList, bool downloadSW): QThread(parent), mLastModSW(newestSW), mLastModList(newestList), mResourceSW(resourceSW), mResourceList(resourceList), mDownloadSW(downloadSW), mSSLConnection(url, certificate) { } Downloader::~Downloader() { } QString Downloader::getDataDirectory() { QString candidate = QStandardPaths::writableLocation(QStandardPaths::DataLocation); if (candidate.isEmpty()) { qDebug() << "Could not find writeable locaction for me"; return QString(); } QDir cDir(candidate); if (!cDir.exists()) { if (!cDir.mkpath(candidate)) { qDebug() << "Could not create path to: " << candidate; return QString(); } } return cDir.absolutePath(); } QMap<QString, QString> Downloader::parseHeaders(QByteArray *data) { int bodyStart = data->indexOf("\r\n\r\n"); QMap<QString, QString> retval; QByteArray headers; QString response(*data); if (bodyStart == -1) { qDebug() << "Could not find header end."; emit error(tr("Invalid response"), SSLConnection::InvalidResponse); return retval; } /* Take the headers with one additional line break */ headers = data->left(bodyStart + 2); /* Chop off the head */ foreach (const QString& line, response.split("\r\n")) { int sepPos = -1; sepPos = line.indexOf(": "); if (sepPos == -1) { continue; } QString key = line.left(sepPos); QString value = line.right(line.size() - sepPos - 2); retval.insert(key, value); } *data = data->right(data->size() - bodyStart - 4); return retval; } QDateTime Downloader::getLastModifiedHeader(const QString &resource) { int ret = -1; QByteArray response; QLocale cLocale = QLocale::c(); QMap<QString, QString> headers; QString headRequest = QString::fromLatin1("HEAD %1 HTTP/1.0\r\n\r\n").arg(resource); ret = mSSLConnection.write(headRequest.toUtf8()); if (ret != 0) { emit error (tr("Connection lost"), SSLConnection::ConnectionLost); return QDateTime(); } response = mSSLConnection.read(1024); qDebug() << "Response from server was: " << response; if (response.isNull()) { qDebug() << "No response"; emit error (tr("Connection lost"), SSLConnection::ConnectionLost); return QDateTime(); } headers = parseHeaders(&response); const QString lastModified = headers.value("Last-Modified"); if (!lastModified.isEmpty()) { QDateTime candidate = cLocale.toDateTime(lastModified, "ddd, dd MMM yyyy HH:mm:ss' GMT'"); if (candidate.isValid()) { return candidate; } } emit error (tr("Invalid response from the server"), SSLConnection::InvalidResponse); return QDateTime(); } bool Downloader::downloadFile(const QString &resource, const QString &fileName, size_t maxSize) { int ret = -1; size_t bytesRead = 0; QString getRequest = QString::fromLatin1("GET %1 HTTP/1.0\r\n\r\n").arg(resource); QSaveFile outputFile(fileName); ret = mSSLConnection.write(getRequest.toUtf8()); // Open / Create the file to write to. if (!outputFile.open(QIODevice::WriteOnly)) { qDebug() << "Failed to open file"; return false; } if (ret != 0) { emit error(tr("Connection lost"), SSLConnection::ConnectionLost); return false; } bool inBody = false; QMap <QString, QString> headers; do { /* Read the response in 8KiB chunks */ int responseSize = 0; QByteArray response = mSSLConnection.read(8192); if (response.isNull()) { qDebug() << "Error reading response"; emit error(tr("Connection lost"), SSLConnection::ConnectionLost); return false; } responseSize = response.size(); if (!inBody) { headers = parseHeaders(&response); inBody = true; } outputFile.write(response); bytesRead += responseSize; if (responseSize < 8192) { /* Nothing more to read */ break; } /* TODO Emit progress */ } while (bytesRead < maxSize); return outputFile.commit(); } void Downloader::run() { int ret; QDateTime remoteModList; QDateTime remoteModSW; if (!mSSLConnection.initialized()) { emit error(tr("Failed to initialize SSL Module."), SSLConnection::ErrUnknown); return; } ret = mSSLConnection.connect(); if (ret != 0) { emit error(tr("Failed to connect."), mSSLConnection.getLastError()); return; } emit progress(tr("Connected"), 1, -1); remoteModSW = getLastModifiedHeader(mResourceSW); emit lastModifiedDate(remoteModSW); if (!remoteModSW.isValid()) { qDebug() << "Could not parse headers for Software"; return; } if (!mLastModSW.isValid() || remoteModSW > mLastModSW) { QString dataDirectory = getDataDirectory(); if (dataDirectory.isEmpty()) { qDebug() << "Failed to get data directory"; return; } QString fileName = dataDirectory.append("/SW-") .append(remoteModSW.toString("yyyyMMddHHmmss")) .append(".exe"); qDebug() << "fileName: " << fileName; if (mDownloadSW) { if (!downloadFile(mResourceSW, fileName, MAX_SW_SIZE)) { return; } } emit newSoftwareAvailable(fileName, remoteModSW); return; } remoteModList = getLastModifiedHeader(mResourceList); if (!remoteModList.isValid()) { qDebug() << "Could not parse headers for List"; return; } if (!mLastModList.isValid() || remoteModList > mLastModList) { QString dataDirectory = getDataDirectory(); if (dataDirectory.isEmpty()) { qDebug() << "Failed to get data directory"; return; } QString fileName = dataDirectory.append("/list-") .append(remoteModList.toString("yyyyMMddHHmmss")) .append(".txt"); qDebug() << "fileName: " << fileName; if (!downloadFile(mResourceList, fileName, MAX_LIST_SIZE)) { return; } emit newListAvailable(fileName, remoteModList); } emit progress(tr("Closing"), 1, -1); }