From c0b6b199a9878bc1e95907200501211c09c1e66c Mon Sep 17 00:00:00 2001 From: Niklas Goby Date: Wed, 23 Nov 2011 11:56:19 +0100 Subject: created modules --- src/fbgui.cpp | 492 ---------------------------------------------------------- 1 file changed, 492 deletions(-) delete mode 100644 src/fbgui.cpp (limited to 'src/fbgui.cpp') diff --git a/src/fbgui.cpp b/src/fbgui.cpp deleted file mode 100644 index 22a2ac6..0000000 --- a/src/fbgui.cpp +++ /dev/null @@ -1,492 +0,0 @@ -#include "fbgui.h" -#include "sysinfo.h" -#include "loggerengine.h" -#include "downloadmanager.h" -#include "javascriptinterface.h" - -#include -#include -#include -#include - -QThread dmThread; -QString logFilePath(""); -QString ipConfigFilePath(""); -QString binPath(""); -QUrl baseURL(""); -QString downloadPath(""); -int updateInterval = -1; -QString fileToTriggerURL(""); -QString serialLocation(""); -QString sessionID(""); -int debugMode = -1; - -//------------------------------------------------------------------------------------------- -/** - * A constructor. - * - * The constructor of the fbgui class. It initializes the main objects - * which are needed while the program is running. - * The appearance of the webView is here also defined. - * - * @see JavascriptInterface - * @see DownloadManager - */ -fbgui::fbgui() { -} -fbgui::~fbgui() { - dmThread.quit(); -} - - - -/** - * init function. - */ -void fbgui::init() { - // start fbgui - qxtLog->debug() << "Initializing fbgui..."; - - setupLayout(); - createActions(); - - // initialize javascript interface - JavascriptInterface* jsi = new JavascriptInterface( - _webView->page()->mainFrame()); - QObject::connect(jsi, SIGNAL(quitFbgui()), this, SLOT(close())); - QObject::connect(jsi, SIGNAL(shutDownClient()), this, - SLOT(performShutDown())); - QObject::connect(_webView->page()->mainFrame(), SIGNAL( - javaScriptWindowObjectCleared()), jsi, SLOT(attachToDOM())); - - // initialize download manager - DownloadManager* dm = new DownloadManager(); - QObject::connect(dm, SIGNAL(downloadInfo(const QString&, const double&)), - jsi, SLOT(downloadInfo(const QString&, const double&))); - QObject::connect(dm, SIGNAL(notify(const QString&)), jsi, - SLOT(notify(const QString&))); - QObject::connect(jsi, SIGNAL(requestFile(const QString&)), dm, - SLOT(downloadFile(const QString&))); - QObject::connect( - dm, - SIGNAL(updateProgress(const int&, const double&, const QString&)), - jsi, - SLOT(updateProgressBar(const int&, const double&, const QString&))); - QObject::connect(dm, SIGNAL(downloadQueueEmpty()), jsi, SLOT( - callbackOnFinished())); - QObject::connect(dm, SIGNAL(downloadQueueEmpty()), this, SLOT(loadSystem())); - - // move download manager to its own thread - dm->moveToThread(&dmThread); - dmThread.start(); - - // show "waiting for internet" page until triggered. - if (debugMode > -1) { - _webView->load(QUrl("qrc:/html/preload-debug.html")); - } else { - _webView->load(QUrl("qrc:/html/preload.html")); - } - - // watcher is not needed anymore since we guarantee internet connection with the networkDiscovery. - // start watching for fileToTriggerURL - //watchForTrigger(); - loadURL(); - - // set properties - setWindowTitle("fbgui"); - setAttribute(Qt::WA_QuitOnClose, true); - setWindowFlags(Qt::FramelessWindowHint); - showFullScreen(); - this->show(); -} -//------------------------------------------------------------------------------------------- -// Layout / actions setup -//------------------------------------------------------------------------------------------- -/** - * This method sets the used Layout. - * - * This method sets the used Layout. Possible layout are: - * - browser mode: only the browser is visible - * - debug mode: the screen is divided into the browser and a debug - * out console - */ -void fbgui::setupLayout() { - // setup layout of the gui: debug split or browser - _webView = new QWebView(this); - if (debugMode == 1) { - // split main window in browser & debug console - createDebugConsole(); - _splitter = new QSplitter(Qt::Vertical, this); - _splitter->addWidget(_webView); - _splitter->addWidget(_debugConsole); - setCentralWidget(_splitter); - } else - setCentralWidget(_webView); -} -//------------------------------------------------------------------------------------------- -/** - * This method enables a shortcut for closing the program. - * The shortcut itself is not configurable: CTRL + X - */ -void fbgui::createActions() { - _quit = new QAction(tr("&quit"), this); - _quit->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_X)); - this->addAction(_quit); - connect(_quit, SIGNAL(triggered()), this, SLOT(close())); -} -//------------------------------------------------------------------------------------------- -// File system watching -//------------------------------------------------------------------------------------------- -/** - * This method sets a "watchdog" to a special file. - * - * This method sets a "watchdog" to a special file. If needed it creates the - * file which it has to watch over. It than connects a QFileSystemWatcher with - * this file. If changes happen to this file, the - * fbgui::checkForTrigger(const QString& dirname) method will be called. - * - */ -void fbgui::watchForTrigger() { - // check if fileToTriggerURL already exists - QFile file(fileToTriggerURL); - if (file.exists()) { - qxtLog->debug() << "[watcher] " << fileToTriggerURL << " found."; - // try to load URL - loadURL(); - } else { - // create it - if (file.open(QIODevice::WriteOnly)) { - qxtLog->debug() << "[gui] Created: " << fileToTriggerURL; - file.close(); - } else { - qxtLog->debug() << "[gui] Creation of " << fileToTriggerURL - << " failed!"; - qxtLog->debug() << "[gui] Exiting in 5 seconds..."; - QTimer::singleShot(5000, this, SLOT(close())); - } - } - // watch the path to trigger file - qxtLog->debug() << "[watcher] Watching " << fileToTriggerURL; - _watcher = new QFileSystemWatcher(QStringList(fileToTriggerURL), this); -QObject::connect(_watcher, SIGNAL(fileChanged(const QString&)), this, SLOT(prepareURLLoad())); - -} -//------------------------------------------------------------------------------------------- -/** - * This method checks if the trigger was valid. - * - * This method checks if the trigger was valid. If yes, - * we have received an IP Address an can load the main screen. - * If not, something some error happened. - * - * @see fbgui::checkHost() - * @see fbgui::loadURL() - */ -void fbgui::prepareURLLoad() { - qxtLog->debug() << "[watcher] " << fileToTriggerURL << " changed!"; - // disconnect _watcher, his job is done - qxtLog->debug() << "[watcher] disconnected."; - _watcher->disconnect(this); - _watcher->deleteLater(); - // try to load URL - loadURL(); -} -//------------------------------------------------------------------------------------------- -// Preparations for URL load -//------------------------------------------------------------------------------------------- -/** - * This method checks the existance of the host. - * - * This method checks if the host exists / can be found. - * The host is from the URL given through the configuration. - */ -bool fbgui::checkHost() const { - QHostInfo hostInfo = QHostInfo::fromName(baseURL.host()); - if (hostInfo.error() != QHostInfo::NoError) { - qxtLog->debug() << "[gui] Lookup of " << baseURL.host() << "failed."; - qxtLog->debug() << "[gui] Host can not be reached."; - return false; - } else { - qxtLog->debug() << "[gui] Lookup of " << baseURL.host() << " succeeded."; - return true; - } -} -//------------------------------------------------------------------------------------------- -/** - * This method tries loads the URL. - * - * This method loads the main screen via an POST request. If also disconnects the watcher - * of the file, (Watcher is set in the fbgui::watchForTrigger() method). - * and generates the POST data body. - * - * @see fbgui::watchForTrigger() - * @see fbgui::generatePOSTData() - */ -void fbgui::loadURL() { - if (checkHost()) { - qxtLog->debug() << "[gui] Loading URL: " << baseURL.toString() << " ..."; - - // Generate POST identification data needed by PBS. - QByteArray postData = generatePOSTData(); - QNetworkRequest req(baseURL); - - // show cursor again since user is about to interact. - //QWSServer::instance()->setCursorVisible(true); - QObject::connect(_webView, SIGNAL(loadFinished(bool)), this, SLOT(loadURLDone(bool))); - _webView->load(req, QNetworkAccessManager::PostOperation, postData); - } - // TODO: error page if no host. -} -void fbgui::loadURLDone(bool success) { - // done contains the success of the loading: false / true - if (!success) { - qxtLog->debug() << "[gui] Loading failed. URL: " - << _webView->url().toString(); - qxtLog->debug() << "[gui] You can quit with CTRL + X ..."; - // TODO handle failure properly... - } else { - qxtLog->debug() << "[gui] Loaded URL: " << _webView->url().toString(); - } -} -//------------------------------------------------------------------------------------------- -/** - * This method generates the POST data body. - * - * This method generates the POST data body. The body contains the - * MAC address, an hardwarehash and a specific serial number. - * The hardwarehash is a MD5 hash over the MAC address and the - * mainboard serial number. - * The specific serial number is set at the creation of the usb boot stick. - * This file has to be present on the directory specified in - * the configuration for this to work. - * - * @see SysInfo::getMACAddress() - * @see SysInfo::getMainboardSerial() - */ -QByteArray fbgui::generatePOSTData() { - qxtLog->debug() << "[gui] Generating POST data..."; - // use MAC address as base data - SysInfo si; - QByteArray data(si.getInfo("mac").toUtf8()); - // append mainboard serial to the mac address for more unique hardwarehash - QByteArray mbserial(si.getInfo("mbserial").toUtf8()); - if (!mbserial.isEmpty()) - data.append(mbserial); - else { - qxtLog->debug() - << "[gui] Mainboard serial was empty. Not appending to base hash data."; - } - qxtLog->debug() << "[post] Hashing: " << data; - // generate MD5 hash of data - QByteArray hash = QCryptographicHash::hash(data, QCryptographicHash::Md5); - qxtLog->debug() << "[post] MD5 Hash: " << hash.toHex(); - - // fetch serial number from usb - QByteArray serial; - QFile file(serialLocation); - if (!file.open(QIODevice::ReadOnly)) { - qxtLog->debug() << "[post] No such file: " << file.fileName(); - } - // everything ok, read data - serial = file.readAll(); - file.close(); - serial.chop(1); // chop EOF - qxtLog->debug() << "[post] Serial number is: " << serial; - - // construct final byte array - QByteArray postData("mac="); - postData.append(si.getInfo("mac")); - postData.append("&hardwarehash=" + hash.toHex()); - postData.append("&serialnumber=" + serial); - qxtLog->debug() << "[post] POST data: " << postData; - return postData; -} - -//------------------------------------------------------------------------------------------- -// Shutdown / Reboot of the client -//------------------------------------------------------------------------------------------- -// TODO One function for reboot and shutdown, with parameter for the action. -// for example: doSystemCall(_REBOOT_); -/** - * This method performs the shutdown of the client. - * - * This method performs the shutdown of the client. It is triggered by the - * JavascriptInterface::shutDownClient() signal which will be emited in the - * JavascriptInterface::shutDown() method. - * This method writes the character 'o' in /proc/sysrq-trigger - * which will shutdown the computer immediatly. - * (See linux magic keys) - * - * @see JavascriptInterface::shutDownClient() - * @see JavascriptInterface::shutDown() - */ -void fbgui::performShutDown() { - QFile file("/proc/sysrq-trigger"); - if (file.open(QIODevice::WriteOnly)) { - file.write("o"); - file.close(); - } else { - qxtLog->debug() << "[gui] Could not open /proc/sysrq-trigger"; - } -} -//------------------------------------------------------------------------------------------- -/** - * This method performs the reboot of the client. - * - * This method performs the reboot of the client. It is triggered by the - * JavascriptInterface::rebootClient() signal which will be emited in the - * JavascriptInterface::reboot() method. - * This method writes the character 'b' in /proc/sysrq-trigger - * which will shutdown the computer immediatly. - * (See linux magic keys) - * - * @see JavascriptInterface::rebootClient() - * @see JavascriptInterface::reboot() - */ -void fbgui::performReboot() { - QFile file("/proc/sysrq-trigger"); - if (file.open(QIODevice::WriteOnly)) { - file.write("b"); - file.close(); - } else { - qxtLog->debug() << "[gui] Could not open /proc/sysrq-trigger"; - } -} -//------------------------------------------------------------------------------------------- -// Preparing Kernel Switch per kexec (initiating Stage 3) -//------------------------------------------------------------------------------------------- -void fbgui::loadSystem() { - //show loading system page. - //_webView->disconnect(this); - //QObject::connect(_webView, SIGNAL(loadFinished(bool)), this, SLOT(prepareKexec())); - _webView->load(QUrl("qrc:/html/loadsystem.html")); - QTimer::singleShot(1000, this, SLOT(prepareKexec())); -} -//------------------------------------------------------------------------------------------- -/** - * This method prepares kexec. - * - * The kernel command line file that should have been downloaded from the Preboot-Server - * and the ip config file (created by udhcpc) are merged into the final completed KCL. - * - * A process is then started to load the kernel, initramfs and kcl into kexec. - * The process tries to execute kexec -l with these parameters. - * - * If this succeeds, runKexec() is called - * - * @see fbgui::runKexec() - * - */ -void fbgui::prepareKexec() { - - qxtLog->debug() << "[gui] Preparing kexec ..."; - // try to read KCL file that was downloaded. - QFile file(downloadPath + "/kcl"); - if (!file.open(QIODevice::ReadOnly)) { - qxtLog->debug() << "[gui] No such file: " << file.fileName(); - } - // everything ok, read data. - QString kcl = file.readAll(); - file.close(); - qxtLog->debug() << "[gui] KCL from PBS: " << kcl; - - // try to read ipconfig file generated by udhcpc. - file.setFileName("/tmp/ip_config_fbgui"); - if (!file.open(QIODevice::ReadOnly)) { - qxtLog->debug() << "[gui] No such file: " << file.fileName(); - } - // everything ok, read data. - QString ipConfig = file.readAll(); - file.close(); - qxtLog->debug() << "[gui] IP config: " << ipConfig; - - // append ipConfig - kcl.append(" ip="); - kcl.append(ipConfig); - qxtLog->debug() << "[gui] Complete KCL: " << kcl; - - // load the kernel + initramfs + append of kcl into kexec. - QProcess *process = new QProcess(this); - QString cmdline = "kexec -l " + downloadPath.toUtf8() + "/kernel --initrd=" - + downloadPath.toUtf8() + "/initramfs --append=\"" + kcl.toUtf8() - + "\""; - qxtLog->debug() << "[gui] kexec cmdline: " << cmdline; - process->start(cmdline); - bool ret = process->waitForFinished(); - if (!ret) { - qxtLog->debug() << "[gui] Failed to execute: " << cmdline; - qxtLog->debug() << "[gui] Exiting in 5 seconds..."; - QTimer::singleShot(5000, this, SLOT(close())); - } else { - qxtLog->debug() << "[gui] Kexec load was successfull."; - if (debugMode < 0) { - // if process successfully finished, try to run kexec -e - runKexec(); - } else { - qxtLog->debug() - << "[gui] Skipping execution of kexec - open debug shell."; - qxtLog->debug() - << "[gui] To start the system execute \"kexec -e\" in your shell."; - close(); - } - } -} -//------------------------------------------------------------------------------------------- -/** - * This method tries to execute: kexec -e - * - * This method tries to execute: kexec -e - * - */ -void fbgui::runKexec() { - QProcess *process = new QProcess(this); - process->start("kexec -e"); - if (!process->waitForStarted()) { - qxtLog->debug() << "[gui] Failed to execute: kexec -e"; - qxtLog->debug() << "[gui] Exiting in 5 seconds..."; - QTimer::singleShot(5000, this, SLOT(close())); - //TODO: Handle failure properly... - } -} -//------------------------------------------------------------------------------------------- -// Debug console setup / control -//------------------------------------------------------------------------------------------- -/** - * This method creates a debug console as a widget. - * - * It is basicly a QTextEdit widget as provided by QT's Framework. - * An action to toggle this widget is implemented (CTRL + D). - * - * @see fbgui::toggleDebugConsole() - */ -void fbgui::createDebugConsole() { - // create the debug console widget - _debugConsole = new QTextEdit(this); - _debugConsole->setWindowFlags(Qt::FramelessWindowHint); - // fanciness - QPalette pal; - pal.setColor(QPalette::Base, Qt::black); - _debugConsole->setPalette(pal); - _debugConsole->setTextColor(Qt::white); - // enable custom logger engine - qxtLog->addLoggerEngine("fb_logger", new LoggerEngine_fb(_debugConsole)); - //qxtLog->initLoggerEngine("fb_logger"); - qxtLog->setMinimumLevel("fb_logger", QxtLogger::DebugLevel); - // CTRL + D toggles debug window - _toggleDebugConsole = new QAction(tr("&toggleDebug"), this); - _toggleDebugConsole->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_D)); - addAction(_toggleDebugConsole); - connect(_toggleDebugConsole, SIGNAL(triggered()), this, SLOT( - toggleDebugConsole())); -} -//------------------------------------------------------------------------------------------- -/** - * This method toggles the debug console. - * - * Toggle the visibility of the debug console if the action _toggleDebugConsole is triggered. - * - * @see fbgui::createDebugConsole() - */ -void fbgui::toggleDebugConsole() { - (_debugConsole->isVisible()) ? _debugConsole->hide() : _debugConsole->show(); -} -- cgit v1.2.3-55-g7522