1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2024-10-06 23:03:22 +02:00
GPXSee/src/downloader.cpp

135 lines
3.6 KiB
C++
Raw Normal View History

2015-11-23 02:33:01 +01:00
#include <QFile>
#include <QFileInfo>
#include <QNetworkRequest>
#include <QNetworkReply>
#include "config.h"
2015-11-23 02:33:01 +01:00
#include "downloader.h"
2015-11-24 10:05:28 +01:00
#if defined(Q_OS_LINUX)
#define PLATFORM_STR "Linux"
2015-11-24 10:05:28 +01:00
#elif defined(Q_OS_WIN32)
#define PLATFORM_STR "Windows"
2015-11-24 10:05:28 +01:00
#elif defined(Q_OS_MAC)
#define PLATFORM_STR "OS X"
#else
#define PLATFORM_STR "Unknown"
#endif
2016-04-01 23:14:57 +02:00
#define USER_AGENT \
APP_NAME "/" APP_VERSION " (" PLATFORM_STR "; Qt " QT_VERSION_STR ")"
2017-01-16 21:45:27 +01:00
#define ATTR_REDIRECT QNetworkRequest::RedirectionTargetAttribute
#define ATTR_FILE QNetworkRequest::User
#define ATTR_ORIGIN (QNetworkRequest::Attribute)(QNetworkRequest::User + 1)
#define ATTR_LEVEL (QNetworkRequest::Attribute)(QNetworkRequest::User + 2)
#define MAX_REDIRECT_LEVEL 5
Downloader::Downloader(QObject *parent) : QObject(parent)
2015-11-23 02:33:01 +01:00
{
2015-12-04 22:56:34 +01:00
connect(&_manager, SIGNAL(finished(QNetworkReply*)),
2015-11-23 02:33:01 +01:00
SLOT(downloadFinished(QNetworkReply*)));
}
2017-01-16 21:45:27 +01:00
bool Downloader::doDownload(const Download &dl, const Redirect &redirect)
2015-11-23 02:33:01 +01:00
{
QUrl url(dl.url());
2015-12-04 22:56:34 +01:00
if (_errorDownloads.contains(url))
return false;
if (_currentDownloads.contains(url))
return false;
2015-12-04 22:56:34 +01:00
2015-11-23 02:33:01 +01:00
QNetworkRequest request(url);
request.setAttribute(ATTR_FILE, QVariant(dl.file()));
2017-01-16 21:45:27 +01:00
if (!redirect.isNull()) {
request.setAttribute(ATTR_ORIGIN, QVariant(redirect.origin()));
request.setAttribute(ATTR_LEVEL, QVariant(redirect.level()));
}
request.setRawHeader("User-Agent", USER_AGENT);
2015-12-04 22:56:34 +01:00
QNetworkReply *reply = _manager.get(request);
2015-11-23 02:33:01 +01:00
_currentDownloads.insert(url, reply);
return true;
2015-11-23 02:33:01 +01:00
}
bool Downloader::saveToDisk(const QString &filename, QIODevice *data)
{
QFile file(filename);
if (!file.open(QIODevice::WriteOnly)) {
fprintf(stderr, "Error writing map tile: %s: %s\n",
2015-11-23 02:33:01 +01:00
qPrintable(filename), qPrintable(file.errorString()));
return false;
}
file.write(data->readAll());
file.close();
return true;
}
void Downloader::downloadFinished(QNetworkReply *reply)
{
QUrl url = reply->request().url();
2015-11-23 02:33:01 +01:00
if (reply->error()) {
QUrl origin = reply->request().attribute(ATTR_ORIGIN).toUrl();
if (origin.isEmpty()) {
_errorDownloads.insert(url);
fprintf(stderr, "Error downloading map tile: %s: %s\n",
url.toEncoded().constData(), qPrintable(reply->errorString()));
} else {
_errorDownloads.insert(origin);
fprintf(stderr, "Error downloading map tile: %s -> %s: %s\n",
origin.toEncoded().constData(), url.toEncoded().constData(),
qPrintable(reply->errorString()));
}
2015-11-23 02:33:01 +01:00
} else {
2017-01-16 21:45:27 +01:00
QUrl location = reply->attribute(ATTR_REDIRECT).toUrl();
QString filename = reply->request().attribute(ATTR_FILE)
2015-11-23 02:33:01 +01:00
.toString();
2017-01-16 21:45:27 +01:00
if (!location.isEmpty()) {
QUrl origin = reply->request().attribute(ATTR_ORIGIN).toUrl();
2017-01-16 21:45:27 +01:00
int level = reply->request().attribute(ATTR_LEVEL).toInt();
2017-01-17 10:37:02 +01:00
if (location == url) {
_errorDownloads.insert(url);
fprintf(stderr, "Error downloading map tile: %s: "
"redirect loop\n", url.toEncoded().constData());
} else if (level >= MAX_REDIRECT_LEVEL) {
_errorDownloads.insert(origin);
2017-01-16 21:45:27 +01:00
fprintf(stderr, "Error downloading map tile: %s: "
"redirect level limit reached\n",
origin.toEncoded().constData());
2017-01-17 10:37:02 +01:00
} else {
Redirect redirect(origin.isEmpty() ? url : origin, level + 1);
2017-01-16 21:45:27 +01:00
Download dl(location, filename);
doDownload(dl, redirect);
}
} else
2016-08-02 23:05:52 +02:00
if (!saveToDisk(filename, reply))
_errorDownloads.insert(url);
2015-11-23 02:33:01 +01:00
}
_currentDownloads.remove(url);
2015-11-23 02:33:01 +01:00
reply->deleteLater();
2015-12-04 22:56:34 +01:00
if (_currentDownloads.isEmpty())
2015-11-23 02:33:01 +01:00
emit finished();
}
bool Downloader::get(const QList<Download> &list)
2015-11-23 02:33:01 +01:00
{
bool finishEmitted = false;
2015-11-23 02:33:01 +01:00
for (int i = 0; i < list.count(); i++)
finishEmitted |= doDownload(list.at(i));
return finishEmitted;
2015-11-23 02:33:01 +01:00
}