all repos — mgba @ f6755a6e1b7b0cf2b944cd8ca842746f11d6bf82

mGBA Game Boy Advance Emulator

src/platform/qt/AbstractUpdater.cpp (view raw)

 1/* Copyright (c) 2013-2019 Jeffrey Pfau
 2 *
 3 * This Source Code Form is subject to the terms of the Mozilla Public
 4 * License, v. 2.0. If a copy of the MPL was not distributed with this
 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 6#include "AbstractUpdater.h"
 7
 8#include <QNetworkAccessManager>
 9#include <QNetworkReply>
10
11using namespace QGBA;
12
13AbstractUpdater::AbstractUpdater(QObject* parent)
14	: QObject(parent)
15	, m_netman(new QNetworkAccessManager(this))
16{
17}
18
19void AbstractUpdater::checkUpdate() {
20	QNetworkReply* reply = m_netman->get(QNetworkRequest(manifestLocation()));
21	chaseRedirects(reply, &AbstractUpdater::manifestDownloaded);
22}
23
24void AbstractUpdater::downloadUpdate() {
25	if (m_isUpdating) {
26		return;
27	}
28	if (m_manifest.isEmpty()) {
29		m_isUpdating = true;
30		checkUpdate();
31		return;
32	}
33	QUrl url = parseManifest(m_manifest);
34	if (!url.isValid()) {
35		emit updateDone(false);
36		return;
37	}
38	m_isUpdating = true;
39	QNetworkReply* reply = m_netman->get(QNetworkRequest(url));
40	chaseRedirects(reply, &AbstractUpdater::updateDownloaded);
41}
42
43void AbstractUpdater::chaseRedirects(QNetworkReply* reply, void (AbstractUpdater::*cb)(QNetworkReply*)) {
44	connect(reply, &QNetworkReply::finished, this, [this, reply, cb]() {
45		// TODO: check domains, etc
46		if (reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() / 100 == 3) {
47			QNetworkReply* newReply = m_netman->get(QNetworkRequest(reply->header(QNetworkRequest::LocationHeader).toString()));
48			chaseRedirects(newReply, cb);
49		} else {
50			(this->*cb)(reply);
51		}
52	});
53}
54
55void AbstractUpdater::manifestDownloaded(QNetworkReply* reply) {
56	m_manifest = reply->readAll();
57	QUrl url = parseManifest(m_manifest);
58	if (m_isUpdating) {
59		if (!url.isValid()) {
60			emit updateDone(false);
61		} else {
62			QNetworkReply* reply = m_netman->get(QNetworkRequest(url));
63			chaseRedirects(reply, &AbstractUpdater::updateDownloaded);
64		}
65	} else {
66		emit updateAvailable(url.isValid());
67	}
68}
69
70void AbstractUpdater::updateDownloaded(QNetworkReply* reply) {
71	m_isUpdating = false;
72	if (reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() / 100 != 2) {
73		emit updateDone(false);
74		return;
75	}
76	QFile f(destination());
77	if (!f.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
78		emit updateDone(false);
79		return;
80	}
81	while (true) {
82		QByteArray bytes = reply->read(4096);
83		if (!bytes.size()) {
84			break;
85		}
86		f.write(bytes);
87	}
88	f.flush();
89	f.close();
90	emit updateDone(true);
91}