Implement index downloading from axiodl.com

This commit is contained in:
Jack Andersen 2017-12-25 18:27:18 -10:00
parent cc63d4852f
commit d3223f0db4
13 changed files with 636 additions and 120 deletions

View File

@ -5,6 +5,7 @@ set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)
find_package(Qt5Widgets)
find_package(Qt5Network)
if(APPLE)
set(PLAT_SRCS MacOSSystemVersion.hpp MacOSSystemVersion.mm)
@ -30,10 +31,10 @@ add_executable(hecl-gui WIN32 MACOSX_BUNDLE
SysReqTableView.hpp SysReqTableView.cpp
VectorISATableView.hpp VectorISATableView.cpp
VectorISATableModel.hpp VectorISATableModelIntel.hpp
SysInstallReport.hpp SysInstallReport.cpp
${PLAT_SRCS} main.cpp)
DownloadManager.hpp DownloadManager.cpp
Common.hpp Common.cpp ${PLAT_SRCS} main.cpp)
set_target_properties(hecl-gui PROPERTIES
MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/platforms/mac/Info.plist")
target_link_libraries(hecl-gui ${Qt5Widgets_LIBRARIES} ${PLAT_LIBS} zeus)
target_link_libraries(hecl-gui ${Qt5Widgets_LIBRARIES} ${Qt5Network_LIBRARIES} ${PLAT_LIBS} zeus)

102
hecl-gui/Common.cpp Normal file
View File

@ -0,0 +1,102 @@
#include "Common.hpp"
#if __APPLE__
const QString CurPlatformString = QStringLiteral("macos");
#elif _WIN32
const QString CurPlatformString = QStringLiteral("win32");
#elif __linux__
const QString CurPlatformString = QStringLiteral("linux");
#else
#error HECL does not know which OS to fetch for
#endif
QString PlatformToString(Platform plat)
{
switch (plat)
{
case Platform::MacOS:
return QStringLiteral("macos");
case Platform::Win32:
return QStringLiteral("win32");
case Platform::Linux:
return QStringLiteral("linux");
default:
return QString();
}
}
#if ZEUS_ARCH_X86_64
const QString CurArchitectureString = QStringLiteral("x86_64");
#elif ZEUS_ARCH_X86
const QString CurArchitectureString = QStringLiteral("x86");
#elif ZEUS_ARCH_ARM
const QString CurArchitectureString = QStringLiteral("arm");
#elif ZEUS_ARCH_AARCH64
const QString CurArchitectureString = QStringLiteral("aarch64");
#else
#error HECL does not know which architecture to fetch for
#endif
Platform StringToPlatform(const QString& str)
{
for (int i = 1; i < int(Platform::MAXPlatform); ++i)
if (str.contains(PlatformToString(Platform(i)), Qt::CaseInsensitive))
return Platform(i);
return Platform::Invalid;
}
QString ArchitectureToString(Architecture arch)
{
switch (arch)
{
case Architecture::X86:
return QStringLiteral("x86");
case Architecture::X86_64:
return QStringLiteral("x86_64");
case Architecture::ARM:
return QStringLiteral("arm");
case Architecture::AARCH64:
return QStringLiteral("aarch64");
default:
return QString();
}
}
Architecture StringToArchitecture(const QString& str)
{
for (int i = 1; i < int(Architecture::MAXArchitecture); ++i)
if (str.contains(ArchitectureToString(Architecture(i)), Qt::CaseInsensitive))
return Architecture(i);
return Architecture::Invalid;
}
QString VectorISAToString(VectorISA visa)
{
switch (visa)
{
case VectorISA::X87:
return QStringLiteral("x87");
case VectorISA::SSE:
return QStringLiteral("sse");
case VectorISA::SSE2:
return QStringLiteral("sse2");
case VectorISA::SSE3:
return QStringLiteral("sse3");
case VectorISA::SSE41:
return QStringLiteral("sse41");
case VectorISA::AVX:
return QStringLiteral("avx");
case VectorISA::AVX2:
return QStringLiteral("avx2");
default:
return QString();
}
}
VectorISA StringToVectorISA(const QString& str)
{
for (int i = 1; i < int(VectorISA::MAXVectorISA); ++i)
if (str.contains(VectorISAToString(VectorISA(i)), Qt::CaseInsensitive))
return VectorISA(i);
return VectorISA::Invalid;
}

77
hecl-gui/Common.hpp Normal file
View File

@ -0,0 +1,77 @@
#ifndef GUI_COMMON_HPP
#define GUI_COMMON_HPP
#include <QString>
#include "zeus/Math.hpp"
enum class Platform
{
Invalid,
MacOS,
Win32,
Linux,
MAXPlatform
};
QString PlatformToString(Platform plat);
Platform StringToPlatform(const QString& str);
#if __APPLE__
constexpr Platform CurPlatform = Platform::MacOS;
#elif _WIN32
constexpr Platform CurPlatform = Platform::Win32;
#elif __linux__
constexpr Platform CurPlatform = Platform::Linux;
#endif
extern const QString CurPlatformString;
enum class Architecture
{
Invalid,
X86,
X86_64,
ARM,
AARCH64,
MAXArchitecture
};
QString ArchitectureToString(Architecture arch);
Architecture StringToArchitecture(const QString& str);
#if ZEUS_ARCH_X86_64
constexpr Architecture CurArchitecture = Architecture::X86_64;
#elif ZEUS_ARCH_X86
constexpr Architecture CurArchitecture = Architecture::X86;
#elif ZEUS_ARCH_ARM
constexpr Architecture CurArchitecture = Architecture::ARM;
#elif ZEUS_ARCH_AARCH64
constexpr Architecture CurArchitecture = Architecture::AARCH64;
#endif
extern const QString CurArchitectureString;
enum class VectorISA
{
Invalid,
X87,
SSE,
SSE2,
SSE3,
SSE41,
AVX,
AVX2,
MAXVectorISA
};
QString VectorISAToString(VectorISA visa);
VectorISA StringToVectorISA(const QString& str);
class URDEVersion
{
int m_version = -1;
VectorISA m_vectorISA;
public:
explicit URDEVersion(const QString& filename);
bool isValid() const { return m_version >= 0; }
};
#endif // GUI_COMMON_HPP

View File

@ -0,0 +1,166 @@
#include "DownloadManager.hpp"
#include "Common.hpp"
static const char AxioDLPublicKeyPEM[] =
"-----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);
void DownloadManager::_validateCert(QNetworkReply* reply)
{
QSslCertificate peerCert = reply->sslConfiguration().peerCertificate();
if (peerCert.publicKey() != AxioDLPublicKey)
{
auto cn = peerCert.subjectInfo(QSslCertificate::CommonName);
if (!cn.empty())
setError(QNetworkReply::SslHandshakeFailedError,
QStringLiteral("Certificate pinning mismatch \"") + cn.first() + "\"");
else
setError(QNetworkReply::SslHandshakeFailedError,
QStringLiteral("Certificate pinning mismatch"));
reply->abort();
}
}
static const QString Domain = QStringLiteral("https://releases.axiodl.com/");
static const QString Index = QStringLiteral("index.txt");
void DownloadManager::fetchIndex()
{
if (m_indexInProgress)
return;
resetError();
QString url = Domain + CurPlatformString + '/' + Index;
m_indexInProgress = m_netManager.get(QNetworkRequest(url));
connect(m_indexInProgress, SIGNAL(finished()),
this, SLOT(indexFinished()));
connect(m_indexInProgress, SIGNAL(error(QNetworkReply::NetworkError)),
this, SLOT(indexError(QNetworkReply::NetworkError)));
connect(m_indexInProgress, SIGNAL(encrypted()),
this, SLOT(indexValidateCert()));
}
void DownloadManager::fetchBinary(const QString& str, const QString& outPath)
{
if (m_binaryInProgress)
return;
resetError();
m_outPath = outPath;
QString url = Domain + CurPlatformString + '/' + str;
m_binaryInProgress = m_netManager.get(QNetworkRequest(url));
connect(m_binaryInProgress, SIGNAL(finished()),
this, SLOT(binaryFinished()));
connect(m_binaryInProgress, SIGNAL(error(QNetworkReply::NetworkError)),
this, SLOT(binaryError(QNetworkReply::NetworkError)));
connect(m_binaryInProgress, SIGNAL(encrypted()),
this, SLOT(binaryValidateCert()));
connect(m_binaryInProgress, SIGNAL(downloadProgress(qint64, qint64)),
this, SLOT(binaryDownloadProgress(qint64, qint64)));
if (m_progBar)
{
m_progBar->setEnabled(true);
m_progBar->setValue(0);
}
}
void DownloadManager::indexFinished()
{
if (m_hasError)
return;
QStringList files;
while (true)
{
if (m_indexInProgress->atEnd())
break;
QByteArray line = m_indexInProgress->readLine();
if (line.isEmpty())
continue;
files.push_back(QString::fromUtf8(line).trimmed());
}
if (m_indexCompletionHandler)
m_indexCompletionHandler(files);
m_indexInProgress->deleteLater();
m_indexInProgress = nullptr;
}
void DownloadManager::indexError(QNetworkReply::NetworkError error)
{
setError(error, m_indexInProgress->errorString());
m_indexInProgress->deleteLater();
m_indexInProgress = nullptr;
}
void DownloadManager::indexValidateCert()
{
_validateCert(m_indexInProgress);
}
void DownloadManager::binaryFinished()
{
if (m_hasError)
return;
if (m_progBar)
m_progBar->setValue(100);
QFile fp(m_outPath);
if (!fp.open(QIODevice::WriteOnly))
{
setError(QNetworkReply::ContentAccessDenied, fp.errorString());
m_binaryInProgress->deleteLater();
m_binaryInProgress = nullptr;
return;
}
fp.write(m_binaryInProgress->readAll());
fp.close();
if (m_completionHandler)
m_completionHandler(m_outPath);
m_binaryInProgress->deleteLater();
m_binaryInProgress = nullptr;
}
void DownloadManager::binaryError(QNetworkReply::NetworkError error)
{
setError(error, m_binaryInProgress->errorString());
m_binaryInProgress->deleteLater();
m_binaryInProgress = nullptr;
if (m_progBar)
m_progBar->setEnabled(false);
}
void DownloadManager::binaryValidateCert()
{
_validateCert(m_binaryInProgress);
}
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));
}
}

View File

@ -0,0 +1,69 @@
#ifndef GUI_DOWNLOADMANAGER_HPP
#define GUI_DOWNLOADMANAGER_HPP
#include <QObject>
#include <QtNetwork>
#include <QNetworkAccessManager>
#include <QProgressBar>
#include <QLabel>
class DownloadManager : public QObject
{
Q_OBJECT
QNetworkAccessManager m_netManager;
QNetworkReply* m_indexInProgress = nullptr;
QNetworkReply* m_binaryInProgress = nullptr;
QString m_outPath;
bool m_hasError = false;
QProgressBar* m_progBar = nullptr;
QLabel* m_errorLabel = nullptr;
std::function<void(const QStringList& index)> m_indexCompletionHandler;
std::function<void(const QString& file)> m_completionHandler;
void resetError()
{
m_hasError = false;
if (m_errorLabel)
m_errorLabel->setText(QString());
}
void setError(QNetworkReply::NetworkError error, const QString& errStr)
{
if (m_hasError && error == QNetworkReply::OperationCanceledError)
return;
m_hasError = true;
if (m_errorLabel)
m_errorLabel->setText(errStr);
}
void _validateCert(QNetworkReply* reply);
public:
explicit DownloadManager(QObject* parent = Q_NULLPTR)
: QObject(parent), m_netManager(this) {}
void connectWidgets(QProgressBar* progBar, QLabel* errorLabel,
std::function<void(const QStringList& index)>&& indexCompletionHandler,
std::function<void(const QString& file)>&& completionHandler)
{
m_progBar = progBar;
m_errorLabel = errorLabel;
m_indexCompletionHandler = std::move(indexCompletionHandler);
m_completionHandler = std::move(completionHandler);
}
void fetchIndex();
void fetchBinary(const QString& str, const QString& outPath);
bool hasError() const { return m_hasError; }
public slots:
void indexFinished();
void indexError(QNetworkReply::NetworkError error);
void indexValidateCert();
void binaryFinished();
void binaryError(QNetworkReply::NetworkError error);
void binaryValidateCert();
void binaryDownloadProgress(qint64 bytesReceived, qint64 bytesTotal);
};
#endif // GUI_DOWNLOADMANAGER_HPP

View File

@ -11,12 +11,26 @@ MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
m_ui(new Ui::MainWindow)
, m_heclProc(this)
, m_dlManager(this)
{
m_ui->setupUi(this);
m_ui->heclTabs->setCurrentIndex(0);
m_ui->splitter->setSizes({0,-1});
m_ui->aboutIcon->setPixmap(QApplication::windowIcon().pixmap(256, 256));
QFont mFont = QFontDatabase::systemFont(QFontDatabase::FixedFont);
mFont.setPointSize(m_ui->currentBinaryLabel->font().pointSize());
m_ui->currentBinaryLabel->setFont(mFont);
m_ui->recommendedBinaryLabel->setFont(mFont);
m_dlManager.connectWidgets(m_ui->downloadProgressBar, m_ui->downloadErrorLabel,
std::bind(&MainWindow::onIndexDownloaded, this, std::placeholders::_1),
std::bind(&MainWindow::onBinaryDownloaded, this, std::placeholders::_1));
initSlots();
m_dlManager.fetchIndex();
}
MainWindow::~MainWindow()
@ -546,6 +560,19 @@ void MainWindow::onReturnPressed()
m_path = m_ui->pathEdit->text();
}
void MainWindow::onIndexDownloaded(const QStringList& index)
{
m_ui->binaryComboBox->clear();
for (const QString& str : index)
m_ui->binaryComboBox->addItem(str);
m_ui->binaryComboBox->setEnabled(true);
}
void MainWindow::onBinaryDownloaded(const QString& file)
{
}
void MainWindow::initSlots()
{
#ifdef Q_OS_WIN

View File

@ -4,6 +4,7 @@
#include <QMainWindow>
#include <QProcess>
#include <memory>
#include "DownloadManager.hpp"
class QTextEdit;
class QTextCharFormat;
@ -18,6 +19,7 @@ class MainWindow : public QMainWindow
QString m_ansiString;
QString m_path;
QProcess m_heclProc;
DownloadManager m_dlManager;
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
@ -28,6 +30,8 @@ private slots:
void onReturnPressed();
private:
void initSlots();
void onIndexDownloaded(const QStringList& index);
void onBinaryDownloaded(const QString& file);
};
#endif // MAINWINDOW_HPP

File diff suppressed because one or more lines are too long

View File

@ -1,30 +0,0 @@
#include "SysInstallReport.hpp"
#include <QFontDatabase>
#include <QPushButton>
#include <QFormLayout>
SysInstallReport::SysInstallReport(QWidget* parent)
: QWidget(parent)
{
QFormLayout* formLayout = new QFormLayout(this);
QString labelText;
labelText.sprintf("Recommended URDE %s:", installEntity().toUtf8().data());
m_installFile = new QLabel("fetching...", this);
QFont mFont = QFontDatabase::systemFont(QFontDatabase::FixedFont);
mFont.setPointSize(m_installFile->font().pointSize());
m_installFile->setFont(mFont);
formLayout->addRow(labelText, m_installFile);
QHBoxLayout* buttonLayout = new QHBoxLayout(this);
QPushButton* b1 = new QPushButton("Install In Applications", this);
b1->setEnabled(false);
buttonLayout->addWidget(b1);
QPushButton* b2 = new QPushButton("Just Download", this);
b2->setEnabled(false);
buttonLayout->addWidget(b2);
formLayout->addRow(buttonLayout);
}

View File

@ -1,29 +0,0 @@
#ifndef GUI_SYSINSTALLREPORT_HPP
#define GUI_SYSINSTALLREPORT_HPP
#include <QWidget>
#include <QLabel>
class SysInstallReport : public QWidget
{
Q_OBJECT
QLabel* m_installFile;
public:
SysInstallReport(QWidget* parent = Q_NULLPTR);
virtual QString installEntity() const { return QStringLiteral("Binary"); }
virtual QString installFile(int version, QString os, QString architecture, QString vectorISA,
QString extension) const
{
QString ret;
if (!extension.isEmpty())
ret.sprintf("urde-%d-%s-%s-%s.%s", version, os.toUtf8().data(), architecture.toUtf8().data(),
vectorISA.toUtf8().data(), extension.toUtf8().data());
else
ret.sprintf("urde-%d-%s-%s-%s", version, os.toUtf8().data(), architecture.toUtf8().data(),
vectorISA.toUtf8().data());
return ret;
}
};
#endif // GUI_SYSINSTALLREPORT_HPP

View File

@ -60,25 +60,26 @@ public:
}
}
QString getISAString(int idx) const
VectorISA getISA(int idx) const
{
switch (idx)
{
case 0:
default:
return QStringLiteral("x87");
return VectorISA::Invalid;
case 0:
return VectorISA::X87;
case 1:
return QStringLiteral("sse");
return VectorISA::SSE;
case 2:
return QStringLiteral("sse2");
return VectorISA::SSE2;
case 3:
return QStringLiteral("sse3");
return VectorISA::SSE3;
case 4:
return QStringLiteral("sse41");
return VectorISA::SSE41;
case 5:
return QStringLiteral("avx");
return VectorISA::AVX;
case 6:
return QStringLiteral("avx2");
return VectorISA::AVX2;
}
}
};

View File

@ -2,7 +2,7 @@
#define GUI_VECTORISATABLEVIEW_HPP
#include <QTableView>
#include <zeus/Math.hpp>
#include "Common.hpp"
#if ZEUS_ARCH_X86_64 || ZEUS_ARCH_X86
#include "VectorISATableModelIntel.hpp"
@ -21,7 +21,7 @@ class VectorISATableView : public QTableView
public:
VectorISATableView(QWidget* parent = Q_NULLPTR);
void paintEvent(QPaintEvent* e) Q_DECL_OVERRIDE;
QString getISAString() const { return m_model.getISAString(m_maxISA); }
VectorISA getISA() const { return m_model.getISA(m_maxISA); }
};
#endif // GUI_VECTORISATABLEVIEW_HPP

View File

@ -38,10 +38,12 @@ int main(int argc, char* argv[])
darkPalette.setColor(QPalette::Window, QColor(53,53,53));
darkPalette.setColor(QPalette::WindowText, Qt::white);
darkPalette.setColor(QPalette::Base, QColor(25,25,25));
darkPalette.setColor(QPalette::Disabled, QPalette::Base, QColor(25,25,25,53));
darkPalette.setColor(QPalette::AlternateBase, QColor(53,53,53));
darkPalette.setColor(QPalette::ToolTipBase, Qt::white);
darkPalette.setColor(QPalette::ToolTipText, Qt::white);
darkPalette.setColor(QPalette::Text, Qt::white);
darkPalette.setColor(QPalette::Disabled, QPalette::Text, QColor(255,255,255,120));
darkPalette.setColor(QPalette::Button, QColor(53,53,53));
darkPalette.setColor(QPalette::Disabled, QPalette::Button, QColor(53,53,53,53));
darkPalette.setColor(QPalette::ButtonText, Qt::white);
@ -49,6 +51,7 @@ int main(int argc, char* argv[])
darkPalette.setColor(QPalette::BrightText, Qt::red);
darkPalette.setColor(QPalette::Link, QColor(42, 130, 218));
darkPalette.setColor(QPalette::Highlight, QColor(42, 130, 218));
darkPalette.setColor(QPalette::Disabled, QPalette::Highlight, QColor(42, 130, 218, 53));
darkPalette.setColor(QPalette::HighlightedText, Qt::black);
a.setPalette(darkPalette);