From 04a397afdeddf08173313be429648f6f3492045d Mon Sep 17 00:00:00 2001 From: "A. Wilcox" Date: Thu, 5 Dec 2019 03:36:39 -0600 Subject: Qt UI: Initial draft of outputting a HorizonScript file from the UI --- ui/qt5/CMakeLists.txt | 6 ++- ui/qt5/horizonwizard.cc | 119 ++++++++++++++++++++++++++++++++++++++++++++++++ ui/qt5/horizonwizard.hh | 18 ++++++++ 3 files changed, 142 insertions(+), 1 deletion(-) diff --git a/ui/qt5/CMakeLists.txt b/ui/qt5/CMakeLists.txt index 9ac6372..7fd1ebf 100644 --- a/ui/qt5/CMakeLists.txt +++ b/ui/qt5/CMakeLists.txt @@ -31,7 +31,11 @@ ENDIF(UNSUPPORTED_NONFREE_FIRMWARE) include_directories(${CMAKE_SOURCE_DIR}/3rdparty) add_executable(horizon-qt5 ${UI_SOURCES}) -target_link_libraries(horizon-qt5 Qt5::Network Qt5::Widgets) +target_link_libraries(horizon-qt5 Qt5::Network Qt5::Widgets crypto) + +IF("cxx_std_17" IN_LIST CMAKE_CXX_COMPILE_FEATURES) + set_property(TARGET horizon-qt5 PROPERTY CXX_STANDARD 17) +ENDIF() install(TARGETS horizon-qt5 DESTINATION bin) diff --git a/ui/qt5/horizonwizard.cc b/ui/qt5/horizonwizard.cc index bde4232..75598cb 100644 --- a/ui/qt5/horizonwizard.cc +++ b/ui/qt5/horizonwizard.cc @@ -16,6 +16,9 @@ #include #include #include +#include + +#include #include #include @@ -45,6 +48,8 @@ extern "C" { #include "rootpwpage.hh" #include "accountpage.hh" +#include "util/keymaps.hh" + static std::map help_id_map = { {HorizonWizard::Page_Intro, "intro"}, {HorizonWizard::Page_Input, "input"}, @@ -278,3 +283,117 @@ HorizonWizard::HorizonWizard(QWidget *parent) : QWizard(parent) { tain_now_set_stopwatch_g(); #endif /* HAS_INSTALL_ENV */ } + + +extern "C" char *do_a_crypt(const char *key, const char *setting, char *output); + +/*! Make a shadow-compliant crypt string out of +the_pw+. */ +char *encrypt_pw(const char *the_pw) { + unsigned char rawsalt[8]; + RAND_bytes(rawsalt, 8); + QByteArray salt_ba(reinterpret_cast(rawsalt), 8); + + const char *salt = ("$6$" + salt_ba.toBase64(QByteArray::OmitTrailingEquals) + .toStdString() + "$").c_str(); + char *result = new char[128]; + if(do_a_crypt(the_pw, salt, result) == nullptr) { + delete[] result; + return nullptr; + } + return result; +} + + +QString HorizonWizard::toHScript() { + QStringList lines; + + if(this->network) { + lines << "network true"; + + if(this->net_dhcp) { + lines << QString::fromStdString("netaddress " + + this->chosen_auto_iface + " dhcp"); + } else { + /* XXX TODO no manual page implemented yet */ + Q_ASSERT(false); + } + } else { + lines << "network false"; + } + + lines << ("hostname " + field("hostname").toString()); + + switch(this->pkgtype) { + case Mobile: + lines << "pkginstall powerdevil upower"; +#if __cplusplus >= 201703L + [[ fallthrough ]]; +#endif + case Standard: + lines << "pkginstall adelie-base-posix firefox-esr libreoffice " + "thunderbird vlc kde x11"; + break; + case Compact: + lines << "pkginstall adelie-base netsurf featherpad lxqt-desktop " + "abiword gnumeric xorg-apps xorg-drivers xorg-server"; + break; + case TextOnly: + lines << "pkginstall adelie-base links tmux"; + break; + case Custom: + lines << ("pkginstall " + packages.join(" ")); + break; + } + + char *root = encrypt_pw(field("rootpw").toString().toStdString().c_str()); + Q_ASSERT(root != nullptr); + lines << QString("rootpw ") + root; + delete[] root; + + /* XXX TODO someday we'll have language support */ + lines << "language en_GB.UTF-8"; + + auto iterator = valid_keymaps.begin(); + std::advance(iterator, field("keymap").toInt()); + lines << ("keymap " + QString::fromStdString(*iterator)); + +#ifdef NON_LIBRE_FIRMWARE + if(this->firmware) { + lines << "firmware true"; + } else { + lines << "firmware false"; + } +#endif /* NON_LIBRE_FIRWMARE */ + + lines << ("timezone " + + dynamic_cast(page(Page_DateTime))->selectedTimeZone()); + + for(auto &acctWidget : dynamic_cast(page(Page_Accounts))->accountWidgets) { + if(acctWidget->accountText().isEmpty()) break; + + char *userpw = encrypt_pw(acctWidget->passphraseText().toStdString().c_str()); + Q_ASSERT(userpw != nullptr); + + lines << ("username " + acctWidget->accountText()); + lines << ("useralias " + acctWidget->accountText() + " " + + acctWidget->personalText()); + lines << ("userpw " + acctWidget->accountText() + " " + userpw); + delete[] userpw; + if(acctWidget->isAdmin()) { + lines << ("usergroups " + acctWidget->accountText() + " " + + "users,lp,audio,cdrom,cdrw,scanner,camera,video,games,usb,kvm,wheel"); + } else { + lines << ("usergroups " + acctWidget->accountText() + " " + + "users,lp,audio,cdrom,cdrw,scanner,camera,video,games"); + } + } + + return lines.join("\n"); +} + + +#include + +void HorizonWizard::accept() { + std::cout << toHScript().toStdString() << std::endl; +} diff --git a/ui/qt5/horizonwizard.hh b/ui/qt5/horizonwizard.hh index 929c598..5be8c67 100644 --- a/ui/qt5/horizonwizard.hh +++ b/ui/qt5/horizonwizard.hh @@ -83,19 +83,37 @@ public: }; HorizonWizard(QWidget *parent = nullptr); + void accept(); + /*! Emit a HorizonScript file with the user's choices. */ + QString toHScript(); QShortcut *esc, *f1, *f3, *f6, *f8; + /*! The domain to use for downloading packages. + * @example distfiles.adelielinux.org + */ std::string mirror_domain; + /*! The version of Adélie to install. Typically "1.0". */ std::string version; #ifdef NON_LIBRE_FIRMWARE + /*! Determines whether firmware will be installed. */ bool firmware; #endif /* NON_LIBRE_FIRMWARE */ + /*! The currently probed network interfaces + * @note Only available in Installation Environment. */ std::map interfaces; + /*! Determines whether networking will be enabled. */ bool network; + /*! Determines whether to use DHCP. */ bool net_dhcp; + /*! Determines the network interface to use. */ std::string chosen_auto_iface; + /*! Determines the packages to install. */ PackageType pkgtype; + /*! If pkgtype is Custom, a list of packages to install. */ + QStringList packages; + /*! Determines whether to install GRUB. */ bool grub; + /*! Determines the kernel to install. */ std::string kernel; }; -- cgit v1.2.3-70-g09d2