metaforce/metaforce-gui/DownloadManager.cpp

177 lines
5.8 KiB
C++
Raw Permalink Normal View History

#include "DownloadManager.hpp"
#include "Common.hpp"
2018-01-10 06:19:48 +00:00
#include <quazip.h>
#include <QDesktopServices>
2018-02-14 07:50:49 +00:00
#define KEY_PINNING 0
#if KEY_PINNING
static const char AxioDLPublicKeyPEM[] =
2018-12-08 05:19:40 +00:00
"-----BEGIN PUBLIC KEY-----\n"
"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvtshImzoP1a++9P5RK0k\n"
"btTOpwie7O7S/wWFZxwwbMezEPhjw2uu86TPqJe3P/1v+6xRKrEf9zFn/sKNygvD\n"
"bO64ZkJre4M46IYd0XxwIhiu7PBR+13CD+fqbrbYwPkoG090CP4MtZZN6mt5NAKB\n"
"QHoIj0wV5K/jJE9cBQxViwOqrxK05Cl/ivy0gRtpL7Ot6S+QHL3++rb6U2hWydIQ\n"
"kS+ucufKCIL77RcDwAc9vwNvzxf9EUU2pmq+EsEtLgRw3fR6BInoltOI8P9X5Wo6\n"
"/skeg92xZA++vv0neq5gjjDfa2A1zDgJRysz3Xps/AMlLOe55XCzXse9BpvChT+Z\n"
"pwIDAQAB\n"
"-----END PUBLIC KEY-----\n";
static const QSslKey AxioDLPublicKey = QSslKey({AxioDLPublicKeyPEM}, QSsl::Rsa, QSsl::Pem, QSsl::PublicKey);
2018-02-13 07:36:48 +00:00
static const char AxioDLEdgePublicKeyPEM[] =
2018-12-08 05:19:40 +00:00
"-----BEGIN PUBLIC KEY-----\n"
"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE4a8ZLg3LRU0FiK6m8g2pT3qVBTMA\n"
"K2Uu5VGl7iamdGpUjynQ4uYWMx+WXf2Qkh7UZZgYvA6UeWHEs3M6ME8T6g==\n"
"-----END PUBLIC KEY-----\n";
2018-02-13 07:36:48 +00:00
2018-12-08 05:19:40 +00:00
static const QSslKey AxioDLEdgePublicKey = QSslKey({AxioDLEdgePublicKeyPEM}, QSsl::Ec, QSsl::Pem, QSsl::PublicKey);
2018-02-14 07:50:49 +00:00
#endif
2018-02-13 07:36:48 +00:00
2018-12-08 05:19:40 +00:00
void DownloadManager::_validateCert(QNetworkReply* reply) {
2018-02-14 07:50:49 +00:00
#if KEY_PINNING
2018-12-08 05:19:40 +00:00
QSslCertificate peerCert = reply->sslConfiguration().peerCertificate();
QSslKey peerKey = peerCert.publicKey();
if (peerKey != AxioDLPublicKey && peerKey != AxioDLEdgePublicKey) {
const auto cn = peerCert.subjectInfo(QSslCertificate::CommonName);
if (cn.empty()) {
setError(QNetworkReply::SslHandshakeFailedError, tr("Certificate pinning mismatch"));
} else {
setError(QNetworkReply::SslHandshakeFailedError, tr("Certificate pinning mismatch \"%1\"").arg(cn.first()));
}
2018-12-08 05:19:40 +00:00
reply->abort();
}
2018-02-14 07:50:49 +00:00
#endif
}
static const QString Domain = QStringLiteral("https://releases.axiodl.com/");
static const QString Index = QStringLiteral("index.txt");
2018-12-08 05:19:40 +00:00
void DownloadManager::fetchIndex() {
2020-04-15 06:13:11 +00:00
if (m_indexInProgress != nullptr) {
2018-12-08 05:19:40 +00:00
return;
}
2018-12-08 05:19:40 +00:00
resetError();
const QString track = QSettings().value(QStringLiteral("update_track")).toString();
const auto url = QUrl(QStringLiteral("%1%2/%3/%4").arg(Domain, track, CurPlatformString, Index));
2018-12-08 05:19:40 +00:00
m_indexInProgress = m_netManager.get(QNetworkRequest(url));
connect(m_indexInProgress, &QNetworkReply::finished, this, &DownloadManager::indexFinished);
2021-02-26 23:57:15 +00:00
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
2020-06-24 15:44:00 +00:00
connect(m_indexInProgress, &QNetworkReply::errorOccurred, this, &DownloadManager::indexError);
2021-02-26 23:57:15 +00:00
#else
connect(m_indexInProgress, qOverload<QNetworkReply::NetworkError>(&QNetworkReply::error), this,
&DownloadManager::indexError);
2021-02-26 23:57:15 +00:00
#endif
connect(m_indexInProgress, &QNetworkReply::encrypted, this, &DownloadManager::indexValidateCert);
}
2018-12-08 05:19:40 +00:00
void DownloadManager::fetchBinary(const QString& str, const QString& outPath) {
2020-04-15 06:13:11 +00:00
if (m_binaryInProgress != nullptr) {
2018-12-08 05:19:40 +00:00
return;
}
2018-12-08 05:19:40 +00:00
resetError();
m_outPath = outPath;
const QString track = QSettings().value(QStringLiteral("update_track")).toString();
const auto url = QUrl(QStringLiteral("%1%2/%3/%4").arg(Domain, track, CurPlatformString, str));
#if PLATFORM_ZIP_DOWNLOAD
2018-12-08 05:19:40 +00:00
m_binaryInProgress = m_netManager.get(QNetworkRequest(url));
connect(m_binaryInProgress, &QNetworkReply::finished, this, &DownloadManager::binaryFinished);
2021-02-26 23:57:15 +00:00
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
2020-06-24 15:44:00 +00:00
connect(m_binaryInProgress, &QNetworkReply::errorOccurred, this, &DownloadManager::binaryError);
2021-02-26 23:57:15 +00:00
#else
connect(m_binaryInProgress, qOverload<QNetworkReply::NetworkError>(&QNetworkReply::error), this,
&DownloadManager::binaryError);
2021-02-26 23:57:15 +00:00
#endif
connect(m_binaryInProgress, &QNetworkReply::encrypted, this, &DownloadManager::binaryValidateCert);
connect(m_binaryInProgress, &QNetworkReply::downloadProgress, this, &DownloadManager::binaryDownloadProgress);
2018-12-08 05:19:40 +00:00
2020-04-15 06:13:11 +00:00
if (m_progBar != nullptr) {
2018-12-08 05:19:40 +00:00
m_progBar->setEnabled(true);
m_progBar->setValue(0);
}
#else
QDesktopServices::openUrl(url);
#endif
}
2018-12-08 05:19:40 +00:00
void DownloadManager::indexFinished() {
if (m_hasError)
return;
2018-12-08 05:19:40 +00:00
QStringList files;
2018-12-08 05:19:40 +00:00
while (!m_indexInProgress->atEnd()) {
QString line = QString::fromUtf8(m_indexInProgress->readLine()).trimmed();
if (line.isEmpty())
continue;
files.push_back(line);
}
2018-12-08 05:19:40 +00:00
if (m_indexCompletionHandler)
m_indexCompletionHandler(files);
2018-12-08 05:19:40 +00:00
m_indexInProgress->deleteLater();
m_indexInProgress = nullptr;
}
2018-12-08 05:19:40 +00:00
void DownloadManager::indexError(QNetworkReply::NetworkError error) {
setError(error, m_indexInProgress->errorString());
m_indexInProgress->deleteLater();
m_indexInProgress = nullptr;
}
2018-12-08 05:19:40 +00:00
void DownloadManager::indexValidateCert() { _validateCert(m_indexInProgress); }
2018-12-08 05:19:40 +00:00
void DownloadManager::binaryFinished() {
if (m_hasError)
return;
2018-12-08 05:19:40 +00:00
if (m_progBar)
m_progBar->setValue(100);
2018-12-08 05:19:40 +00:00
QByteArray all = m_binaryInProgress->readAll();
QBuffer buff(&all);
QuaZip zip(&buff);
if (!zip.open(QuaZip::mdUnzip)) {
setError(QNetworkReply::UnknownContentError, tr("Unable to open zip archive."));
m_binaryInProgress->deleteLater();
m_binaryInProgress = nullptr;
2018-12-08 05:19:40 +00:00
return;
}
if (m_completionHandler)
m_completionHandler(zip);
m_binaryInProgress->deleteLater();
m_binaryInProgress = nullptr;
}
2018-12-08 05:19:40 +00:00
void DownloadManager::binaryError(QNetworkReply::NetworkError error) {
setError(error, m_binaryInProgress->errorString());
m_binaryInProgress->deleteLater();
m_binaryInProgress = nullptr;
2018-12-08 05:19:40 +00:00
if (m_progBar)
m_progBar->setEnabled(false);
2018-12-08 05:19:40 +00:00
if (m_failedHandler)
m_failedHandler();
}
2018-12-08 05:19:40 +00:00
void DownloadManager::binaryValidateCert() { _validateCert(m_binaryInProgress); }
2018-12-08 05:19:40 +00:00
void DownloadManager::binaryDownloadProgress(qint64 bytesReceived, qint64 bytesTotal) {
if (m_progBar) {
if (bytesReceived == bytesTotal)
m_progBar->setValue(100);
else
m_progBar->setValue(int(bytesReceived * 100 / bytesTotal));
}
}