#include "fbgui.h" #include "sysinfo.h" #include "loggerengine.h" #include "downloadmanager.h" #include "javascriptinterface.h" #include "sysinfolibsysfs.h" #include #include #include 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() { // test for libsys function //SysInfoLibsysfs* sil = new SysInfoLibsysfs(); //sil->getInfoAboutNetworkInterface(); //sil->getInfoMainboardSerial(); //SysInfo si; //qxtLog->debug() << si.getInfo("mbserial"); //si.getInfo("usb"); setupLayout(); createActions(); // initialize javascript interface JavascriptInterface* jsi = new JavascriptInterface(_webView->page()->mainFrame()); QObject::connect(jsi, SIGNAL(quitFbgui()), this, SLOT(close())); 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())); // show filler page _webView->load(QUrl("qrc:/html/preload.html")); // start watching for fileToTriggerURL watchForTrigger(); // set properties setWindowTitle("fbgui"); setAttribute(Qt::WA_QuitOnClose, true); setWindowFlags(Qt::FramelessWindowHint); showFullScreen(); } //------------------------------------------------------------------------------------------- // 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. */ void fbgui::createActions() { // CTRL + X to kill the gui _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 the directory to fileToTriggerURL exists QFileInfo fi(fileToTriggerURL); if (!fi.absoluteDir().exists()){ qxtLog->debug() << "[watcher] " << fi.absolutePath() << " does not exists!"; if (QDir::home().mkdir(fi.absolutePath())) qxtLog->debug() << "[watcher] Successfully created " << fi.absolutePath(); else qxtLog->debug() << "[watcher] Failed to create " << fi.absolutePath(); } else qxtLog->debug() << "[watcher] " << fi.absolutePath() << " exists!"; // check if fileToTriggerURL already exists if (fi.exists()){ qxtLog->debug() << "[watcher] " << fileToTriggerURL << " exists already!"; // try to remove it QFile file(fi.absoluteFilePath()); if (file.remove()) qxtLog->debug() << "[watcher] Purged: " << file.fileName(); else{ // this shouldn't happen ... qxtLog->debug() << "[watcher] Could not remove: " << file.fileName(); exit(EXIT_FAILURE); } } else { // watch the path where trigger file is expected qxtLog->debug() << "[watcher] Watching " << fi.absolutePath() << " for file: " << fi.fileName(); QStringList pathToWatch(fi.absolutePath()); _watcher = new QFileSystemWatcher(pathToWatch, this); QObject::connect(_watcher, SIGNAL(directoryChanged(const QString&)), this, SLOT(checkForTrigger(const QString&))); } } //------------------------------------------------------------------------------------------- /** * 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::checkForTrigger(const QString& dirname) { // check if fileToTriggerURL exists in the directory where the change occured QFileInfo tfi(fileToTriggerURL); QFileInfo fi(dirname + "/" + tfi.fileName()); if (fi.exists()){ qxtLog->debug() << "[watcher] " << fileToTriggerURL << " detected."; // load URL if host exists if (checkHost()) loadURL(); } else // do nothing / keep watching qxtLog->debug() << "[watcher] weird file!"; } //------------------------------------------------------------------------------------------- // Preparations for URL load //------------------------------------------------------------------------------------------- /** * This method checks if is connected to the internet. * * This method checks if is connected to the internet. */ bool fbgui::checkHost() const { QHostInfo hostInfo = QHostInfo::fromName(baseURL.host()); if (hostInfo.error() != QHostInfo::NoError){ qxtLog->debug() << "[gui] Lookup of " << baseURL.host() << "failed. Exiting..."; return false; } else{ qxtLog->debug() << "[gui] Lookup of " << baseURL.host() << " succeeded."; return true; } } //------------------------------------------------------------------------------------------- /** * This method loads the main screen. * * 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() { // disconnect _watcher, his job is done qxtLog->debug() << "[watcher] disconnected."; _watcher->disconnect(this); _watcher->deleteLater(); // memory problems with watcher qxtLog->debug() << "[gui] Loading URL..."; QByteArray postData = generatePOSTData(); qxtLog->debug() << "[gui] POST data: " << postData; QNetworkRequest req(baseURL); qApp->setOverrideCursor(QCursor(Qt::ArrowCursor)); _webView->load(req, QNetworkAccessManager::PostOperation, postData); } //------------------------------------------------------------------------------------------- /** * This method generates the POST data body. * * This method generates the POST data body. The body contains the * MAC address, an hardwarehas 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. * * @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 data.append(si.getInfo("mbserial").toUtf8()); 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(); serial = "10-23-43-55-67"; // tests } // 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); return postData; } //------------------------------------------------------------------------------------------- // Debug console setup / control //------------------------------------------------------------------------------------------- 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())); } //------------------------------------------------------------------------------------------- void fbgui::toggleDebugConsole() { if (_debugConsole->isVisible()) _debugConsole->hide(); else _debugConsole->show(); }