Browse Source

Merge branch '93-us50-keyfile-in-gui' into 'develop'

Resolve "US50: Keyfile selection in GUI"

Closes #93

See merge request tobias.wach/ccats!96
Wach, Tobias Alexander 4 years ago
parent
commit
8f47371ab7

+ 7 - 0
cli/include/cmdman.h

@@ -97,6 +97,13 @@ private:
 	 */
 	map<string, string> helpmap;
 
+	/**
+	 * Vectors containing command strings that should either be usable in any
+	 * state or after connecting but not logging in
+	 */
+	vector<string> cmdAllowAlways = {"help", "keyfile", "closekey", "exit"};
+	vector<string> cmdAllowAfterConnect = {"login", "signup", "disconnect"};
+
 	/**
 	 * Help strings and method prototypes for commands to be used by a user
 	 */

+ 22 - 9
cli/src/cmdman.cpp

@@ -414,27 +414,40 @@ CmdMan::CmdRet CmdMan::execute(string cmd, vector<string> args) {
 	for (string s : args)
 		DEBUGPRINT(s + " ");
 	DEBUGPRINT("]");
-	map<string, CmdRet (CmdMan::*)(vector<string>)>::iterator it = execmap.find(cmd);
+	map<string, CmdRet (CmdMan::*)(vector<string>)>::iterator execit = execmap.find(cmd);
+	vector<string>::const_iterator alwaysit;
+	vector<string>::const_iterator connectit;
+	for (alwaysit = cmdAllowAlways.cbegin(); alwaysit != cmdAllowAlways.cend(); alwaysit++)
+		if (*alwaysit == cmd)
+			break;
+	for (connectit = cmdAllowAfterConnect.cbegin(); connectit != cmdAllowAfterConnect.cend(); connectit++)
+		if (*connectit == cmd)
+			break;
 	CmdRet retval;
 	Json::Value root;
 	root["command"] = cmd;
-	if (it == execmap.end()) {
+	if (execit == execmap.end()) {
 		retval.type = error;
 		root["command"] = "error";
 		root["error"] = string(__PRETTY_FUNCTION__) + " unknown command \"" + cmd + "\".\ntype help to list available commands.";
 		retval.msg = root;
 		return retval;
-	} else if (!cmd.compare("help") || !cmd.compare("exit")) {
-		// allow help and exit in all cases
+	} else if (alwaysit != cmdAllowAlways.cend()) {
+		// Command should be usable in all cases
 	} else if (currentState == loginpossible || currentState == dologin || currentState == dosignup) {
 		DEBUGPRINT("execute does login");
-		DEBUGPRINT(string("comparison is ") +
-		           std::to_string(cmd.compare("login") && cmd.compare("signup") && cmd.compare("disconnect") && cmd.compare("help")));
-		if (cmd.compare("login") && cmd.compare("signup") && cmd.compare("disconnect") && cmd.compare("help")) {
+		DEBUGPRINT(string("cmd is in usable commands ") + std::to_string(connectit != cmdAllowAfterConnect.end()));
+		if (connectit == cmdAllowAfterConnect.cend()) {
+			// Command was NOT in list of usable commands after login
+			string allowedCommands;
+			for (string s : cmdAllowAlways)
+				allowedCommands += s + " ";
+			for (string s : cmdAllowAfterConnect)
+				allowedCommands += s + " ";
+
 			retval.type = error;
 			root["command"] = "error";
-			root["error"] = string("Not logged in. Available commands are limited to ") + "login" + ", " + "signup" + " and " + "disconnect" + "\n" +
-			                "Use help for usage of these commands.";
+			root["error"] = string("Not logged in. Available commands are limited to ") + allowedCommands + "\n" + "Use help for usage of these commands.";
 			retval.msg = root;
 			return retval;
 		}

+ 2 - 0
cli/src/ioman.cpp

@@ -569,6 +569,8 @@ void IoMan::run() {
 	rl_replace_line("", 0);
 	rl_redisplay();
 
+	rl_clear_history();
+
 	// Remove the handler
 	rl_callback_handler_remove();
 }

+ 2 - 2
cli/test/cmdman_test.cpp

@@ -3167,8 +3167,8 @@ TEST(testCommandsWithRequiredLogin, NotLoggedInOrNotConnected) {
 	CmdMan::CmdRet retval1, retval2, retval3;
 
 	// prepare cmd/args
-	std::vector<std::string> cmds = {"put",  "get",        "list",     "extendedlist", "putdata",  "getdata",       "listdata", "extendedlistdata",
-	                                 "head", "deletefile", "deleteme", "keyfile",      "closekey", "extendedstatus"};
+	std::vector<std::string> cmds = {"put",  "get",        "list",     "extendedlist",  "putdata", "getdata", "listdata", "extendedlistdata",
+	                                 "head", "deletefile", "deleteme", "extendedstatus"};
 	// as every command works fine with too many args, we will simply pass three to all of them
 	std::vector<std::string> args = {"arg1", "arg2", "arg3"};
 

+ 5 - 0
gui/include/cmdmanager.h

@@ -27,6 +27,9 @@ void cleanInternalList();
 
 void executeCmd(std::string cmd, Json::Value root);
 
+void setCachedIP(QString ip);
+void setCachedPort(QString port);
+
 void handleError(Json::Value root);
 void handleStatus(Json::Value root);
 void handleClose(Json::Value root);
@@ -46,6 +49,8 @@ void handleNotifications(Json::Value root);
 void handleQueue(Json::Value root);
 void handleDequeue(Json::Value root);
 void handleExtendedStatus(Json::Value root);
+void handleKeyfile(Json::Value root);
+void handleClosekey(Json::Value root);
 } // namespace CmdManager
 
 #endif // CMDMANAGER_H

+ 6 - 2
gui/include/qmlhandler.h

@@ -51,7 +51,9 @@ signals:
 
 	// Settings
 	void closeWindow();
-	void loadSettings(int covertMethod, bool saveIP, bool saveUsername, QString cliPath);
+	void loadSettings(bool saveIP, bool saveUsername, QString cliPath, QString keyPath);
+	void keyfileStatus(bool success, QString msg);
+	void keyfileClosedOK();
 
 	// Delete Me Popup
 	void deleteMePopupSetStatus(QString status);
@@ -119,10 +121,12 @@ public slots:
 	void onMessagesSendButton(QString msg);
 
 	// Settings
+	void onKeyfileSelected(QString path);
+	void onKeyfileClosed();
 	void onSettingsDeleteMeButton(QString password);
 	void onSettingsRevertChangesButton();
 	void onSettingsResetButton();
-	void onSettingsSaveButton(int covertMethod, bool saveIP, bool saveUsername, QString cliPath);
+	void onSettingsSaveButton(bool saveIP, bool saveUsername, QString cliPath, QString keyPath);
 
 	// Ip Popup
 	void onIpPopupConnectButton(QString ip, bool saveAsDefault);

+ 1 - 1
gui/src/Forms/Connect/IpPopup.ui.qml

@@ -61,7 +61,7 @@ Popup {
             placeholderText: "IP-Address"
             horizontalAlignment: Text.AlignHCenter
             validator: RegExpValidator {
-                regExp: /^(\d|[1-9]\d|1\d\d|2([0-4]\d|5[0-5]))\.(\d|[1-9]\d|1\d\d|2([0-4]\d|5[0-5]))\.(\d|[1-9]\d|1\d\d|2([0-4]\d|5[0-5]))\.(\d|[1-9]\d|1\d\d|2([0-4]\d|5[0-5]))$/
+                regExp: /^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(:[0-9]+)?$/
             }
             // @disable-check M222
             Keys.onReturnPressed: ipPopupConnectButton.activate()

+ 1 - 1
gui/src/Forms/Receiving/ReceivingFileTemplate.ui.qml

@@ -76,7 +76,7 @@ Item {
             verticalAlignment: Text.AlignVCenter
             horizontalAlignment: Text.AlignHCenter
             text: fileDecryptableText
-            color: "#ffffff"
+            color: (fileDecryptableText == "decryptable") ? "#3fdf3f" : (fileDecryptableText == "undecryptable") ? "#df3f3f" : "#ffffff"
         }
 
         Button {

+ 98 - 31
gui/src/Forms/Settings/SettingsForm.ui.qml

@@ -17,10 +17,26 @@ Page {
             window.close()
         }
         onLoadSettings: {
-            settingsCovertMethodPicker.currentIndex = covertMethod
             settingsSaveIpSwitch.checked = saveIP
             settingsSaveUsernameSwitch.checked = saveUsername
-            settingsCliPath.text = "CLI-Path:     " + cliPath
+            settingsCliPath.text = "CLI-Path:   " + cliPath
+            settingsKeyPath.text = "CLI-Path:   " + keyPath
+        }
+        onKeyfileStatus: {
+            if(success) {
+                settingsKeyStatus.text = "Keyfile: OK"
+                settingsKeyStatus.color = "#3fdf3f"
+            }
+            else {
+                settingsKeyStatus.text = "Keyfile: Error"
+                settingsKeyStatus.color = "#df3f3f"
+                settingsKeyPath.text = msg
+            }
+        }
+        onKeyfileClosedOK: {
+            settingsKeyStatus.text = "Keyfile:"
+            settingsKeyStatus.color = "#ffffff"
+            settingsKeyPath.text = "   "
         }
     }
 
@@ -43,7 +59,7 @@ Page {
                     Layout.preferredWidth: 400
                     Layout.preferredHeight: 50
                     color: "#ffffff"
-                    text: "Covert Channel Method:"
+                    text: "Autofill default IP on start:"
                     verticalAlignment: Text.AlignVCenter
                     horizontalAlignment: Text.AlignLeft
                     font.pixelSize: 20
@@ -54,30 +70,43 @@ Page {
                     Layout.preferredWidth: 400
                     Layout.preferredHeight: 50
                     color: "#ffffff"
-                    text: "Autofill default IP on start:"
+                    text: "Autofill default username on start:"
                     verticalAlignment: Text.AlignVCenter
                     horizontalAlignment: Text.AlignLeft
                     font.pixelSize: 20
                 }
 
                 Text {
+                    id: settingsCliPath
                     Layout.alignment: Qt.AlignCenter
                     Layout.preferredWidth: 400
                     Layout.preferredHeight: 50
                     color: "#ffffff"
-                    text: "Autofill default username on start:"
+                    text: "CLI-Path:   "
                     verticalAlignment: Text.AlignVCenter
                     horizontalAlignment: Text.AlignLeft
                     font.pixelSize: 20
                 }
 
                 Text {
-                    id: settingsCliPath
+                    id: settingsKeyStatus
                     Layout.alignment: Qt.AlignCenter
                     Layout.preferredWidth: 400
                     Layout.preferredHeight: 50
                     color: "#ffffff"
-                    text: "CLI-Path:   "
+                    text: "Keyfile:"
+                    verticalAlignment: Text.AlignVCenter
+                    horizontalAlignment: Text.AlignLeft
+                    font.pixelSize: 20
+                }
+
+                Text {
+                    id: settingsKeyPath
+                    Layout.alignment: Qt.AlignCenter
+                    Layout.preferredWidth: 400
+                    Layout.preferredHeight: 50
+                    color: "#ffffff"
+                    text: "   "
                     verticalAlignment: Text.AlignVCenter
                     horizontalAlignment: Text.AlignLeft
                     font.pixelSize: 20
@@ -100,25 +129,6 @@ Page {
                 Layout.preferredWidth: 500
                 Layout.preferredHeight: parent.height
 
-                ComboBox {
-                    id: settingsCovertMethodPicker
-                    Layout.alignment: Qt.AlignCenter
-                    Layout.preferredHeight: 50
-                    Layout.preferredWidth: 400
-
-                    model: ListModel {
-                        ListElement {
-                            text: "Method 1"
-                        }
-                        ListElement {
-                            text: "Method 2"
-                        }
-                        ListElement {
-                            text: "Method 3"
-                        }
-                    }
-                }
-
                 Switch {
                     id: settingsSaveIpSwitch
                     Layout.alignment: Qt.AlignCenter
@@ -144,7 +154,7 @@ Page {
                     Layout.alignment: Qt.AlignCenter
                     Layout.preferredHeight: 50
                     Layout.preferredWidth: 220
-                    text: "Change (req. restart)"
+                    text: "Change (needs restart)"
                     font.pixelSize: 20
                     // @disable-check M223
                     onClicked: {
@@ -153,6 +163,37 @@ Page {
                     }
                 }
 
+                ColumnLayout {
+                    Layout.alignment: Qt.AlignCenter
+                    Button {
+                        id: settingsChangeKeyfilePathButton
+                        Layout.alignment: Qt.AlignCenter
+                        Layout.preferredHeight: 50
+                        Layout.preferredWidth: 220
+                        text: "Select"
+                        font.pixelSize: 20
+                        // @disable-check M223
+                        onClicked: {
+                            // @disable-check M222
+                            settingsKeyfileDialog.open()
+                        }
+                    }
+
+                    Button {
+                        id: settingsDisableKeyfile
+                        Layout.alignment: Qt.AlignCenter
+                        Layout.preferredHeight: 50
+                        Layout.preferredWidth: 220
+                        text: "Close Keyfile"
+                        font.pixelSize: 20
+                        // @disable-check M223
+                        onClicked: {
+                            // @disable-check M222
+                            _qmlHandler.onKeyfileClosed()
+                        }
+                    }
+                }
+
                 Button {
                     id: settingsDeleteMeButton
                     Layout.alignment: Qt.AlignCenter
@@ -173,7 +214,6 @@ Page {
             Layout.alignment: Qt.AlignCenter
             Layout.preferredWidth: parent.width
             Layout.preferredHeight: 2
-            Layout.bottomMargin: 30
             color: Material.accent
         }
 
@@ -190,7 +230,9 @@ Page {
                 Layout.preferredHeight: 50
                 text: "Select defaults"
                 font.pixelSize: 20
+                // @disable-check M223
                 onClicked: {
+                    // @disable-check M222
                     _qmlHandler.onSettingsResetButton()
                 }
             }
@@ -202,12 +244,17 @@ Page {
                 Layout.preferredHeight: 50
                 text: "Save Changes"
                 font.pixelSize: 20
+                // @disable-check M223
                 onClicked: {
+                    // @disable-check M222
                     _qmlHandler.onSettingsSaveButton(
-                                settingsCovertMethodPicker.currentIndex,
                                 settingsSaveIpSwitch.checked,
                                 settingsSaveUsernameSwitch.checked,
-                                settingsCliPath.text.replace("CLI-Path:     ",
+                                // @disable-check M222
+                                settingsCliPath.text.replace("CLI-Path:   ",
+                                                             ""),
+                                // @disable-check M222
+                                settingsKeyPath.text.replace("   ",
                                                              ""))
                 }
             }
@@ -219,7 +266,9 @@ Page {
                 Layout.preferredHeight: 50
                 text: "Revert Changes"
                 font.pixelSize: 20
+                // @disable-check M223
                 onClicked: {
+                    // @disable-check M222
                     _qmlHandler.onSettingsRevertChangesButton()
                 }
             }
@@ -233,14 +282,32 @@ Page {
         folder: shortcuts.home
         // @disable-check M223
         onAccepted: {
-            // @disable-check M222
             var path = settingsCliDialog.fileUrl.toString()
+            // @disable-check M222
             path = path.replace(/^(file:\/{2})/, "")
             settingsCliPath.text = "CLI-Path:   " + path
         }
     }
 
+    FileDialog {
+        id: settingsKeyfileDialog
+        title: "Select keyfile to use"
+        folder: shortcuts.home
+        // @disable-check M223
+        onAccepted: {
+            var path = settingsKeyfileDialog.fileUrl.toString()
+            // @disable-check M222
+            path = path.replace(/^(file:\/{2})/, "")
+            settingsKeyPath.text = "   " + path
+            // @disable-check M222
+            _qmlHandler.onKeyfileSelected(path)
+        }
+    }
+
     DeleteMePopup {
         id: deleteMePopup
     }
 }
+
+
+

+ 22 - 7
gui/src/climanager.cpp

@@ -29,7 +29,7 @@ thread statusLoopThread;
 namespace CliManager {
 
 QMLHandler *qmlHandler;
-bool programActive = true;
+bool programActive = false;
 bool loggedin = false;
 int inpipefd[2];
 int outpipefd[2];
@@ -46,17 +46,23 @@ void CliManager::writeToCli(QString command) {
 
 void CliManager::onExit() {
 	// stop threads
-	CliManager::setProgramActive(false);
-	readPipeLoopThread.join();
-	notificationsLoopThread.join();
-	statusLoopThread.join();
-
-	writeToCli("exit");
+	if (programActive) {
+		writeToCli("exit");
+		CliManager::setProgramActive(false);
+		readPipeLoopThread.join();
+		notificationsLoopThread.join();
+		statusLoopThread.join();
+	}
 }
 
 void CliManager::setQmlHandler(QMLHandler *q) { qmlHandler = q; }
 
 void CliManager::init() {
+	qInfo() << QString::fromStdString(string("InitCLI with path ") + Config::getValue("CLI-Path"));
+	if (!Config::getValue("CLI-Path").size()) {
+		qInfo() << "Empty CLI-Path!";
+		return;
+	}
 	pipe(inpipefd);
 	pipe(outpipefd);
 
@@ -78,6 +84,13 @@ void CliManager::init() {
 	close(outpipefd[0]);
 	close(inpipefd[1]);
 
+	setProgramActive(true);
+
+	if (Config::getValue("Keyfile-Path").size()) {
+		QString cmd = QString("keyfile ") + Config::getValue("Keyfile-Path").c_str();
+		writeToCli(cmd);
+	}
+
 	// start threads
 	readPipeLoopThread = thread(&CliManager::readPipeLoop);
 	notificationsLoopThread = thread(&CliManager::notificationsLoop);
@@ -132,6 +145,8 @@ void CliManager::readPipeLoop() {
 			pollCount = 0;
 			readOffset = 0;
 			if (waitpid(childpid, NULL, WNOHANG)) {
+				qInfo() << "CLI has exited/did not launch";
+				setProgramActive(false);
 				// nonzero means error or childid has changed state
 				// for us that means child has exited -> CLI is dead
 				break;

+ 30 - 2
gui/src/cmdmanager.cpp

@@ -9,6 +9,8 @@
 using namespace std;
 
 namespace CmdManager {
+QString cachedIP;
+QString cachedPort;
 QMLHandler *qmlHandler;
 map<string, void (*)(Json::Value)> cmdmap;
 map<string, struct fileEntry> filemap;
@@ -34,6 +36,8 @@ void CmdManager::init() {
 	cmdmap["queue"] = &CmdManager::handleQueue;
 	cmdmap["dequeue"] = &CmdManager::handleDequeue;
 	cmdmap["extendedstatus"] = &CmdManager::handleExtendedStatus;
+	cmdmap["keyfile"] = &CmdManager::handleKeyfile;
+	cmdmap["closekey"] = &CmdManager::handleClosekey;
 
 	filemap.clear();
 }
@@ -104,6 +108,9 @@ void CmdManager::executeCmd(string cmd, Json::Value root) {
 	cmdmap[cmd](root);
 }
 
+void CmdManager::setCachedIP(QString ip) { cachedIP = ip; }
+void CmdManager::setCachedPort(QString port) { cachedPort = port; }
+
 void CmdManager::handleError(Json::Value root) { emit qmlHandler->log(root["error"].asString().c_str()); }
 
 void CmdManager::handleStatus(Json::Value root) { emit qmlHandler->footerSetStatus(root["response"].asString().c_str()); }
@@ -170,11 +177,11 @@ void CmdManager::handleVersion(Json::Value root) {
 void CmdManager::handleLogin(Json::Value root) {
 	if (root["accept"] == true) {
 		emit qmlHandler->loginSignupPopupClose();
-		CliManager::writeToCli("extendedlist");
 		CliManager::loggedin = true;
-		qmlHandler->loadSettingsToGUI();
 	} else {
+		QString cmd = "connect " + cachedIP + " " + cachedPort;
 		emit qmlHandler->loginSetStatus(root["error"].asString().c_str());
+		CliManager::writeToCli(cmd);
 		emit qmlHandler->loginEnableLoginButton();
 	}
 }
@@ -182,8 +189,11 @@ void CmdManager::handleLogin(Json::Value root) {
 void CmdManager::handleSignup(Json::Value root) {
 	if (root["accept"] == true) {
 		emit qmlHandler->loginSignupPopupClose();
+		CliManager::loggedin = true;
 	} else {
+		QString cmd = "connect " + cachedIP + " " + cachedPort;
 		emit qmlHandler->signupSetStatus(root["error"].asString().c_str());
+		CliManager::writeToCli(cmd);
 		emit qmlHandler->signupEnableRegisterButton();
 	}
 }
@@ -298,3 +308,21 @@ void CmdManager::handleExtendedStatus(Json::Value root) {
 		emitFileList();
 	}
 }
+
+void CmdManager::handleKeyfile(Json::Value root) {
+	QString errorMessage;
+	if (root["accept"] == false) {
+		errorMessage = QString::fromStdString(string("Error when setting keyfile file " + root["file"].asString() + ":\n" + root["error"].asString()));
+		emit qmlHandler->log(errorMessage);
+	}
+	emit qmlHandler->keyfileStatus(root["accept"].asBool(), errorMessage);
+}
+
+void CmdManager::handleClosekey(Json::Value root) {
+	if (root["accept"] == false) {
+		QString errorMessage = QString::fromStdString(string("Error when closing keyfile:\n" + root["error"].asString()));
+		emit qmlHandler->log(errorMessage);
+	} else {
+		emit qmlHandler->keyfileClosedOK();
+	}
+}

+ 18 - 16
gui/src/config.cpp

@@ -3,27 +3,27 @@
 
 namespace Config {
 std::map<std::string, std::string> configuration;
-bool configValid;
-std::string configPath = "config.txt";
-std::string configKeys[] = {"Autofill-IP", "Default-IP", "Autofill-Username", "Default-Username", "CLI-Path", "Covert-Channel-Method"};
+bool configValid = false;
+bool configInitialized = false;
+std::string configPath = "configGUI.txt";
+std::vector<std::string> configKeys = {"Autofill-IP", "Default-IP", "Autofill-Username", "Default-Username", "CLI-Path", "Keyfile-Path"};
 } // namespace Config
 
 void Config::setupDefaultConfig() {
 	configuration.clear();
+	for (std::string s : configKeys)
+		configuration.insert(std::pair<std::string, std::string>(s, ""));
 	setValue(configKeys[0], "0");
 	setValue(configKeys[1], "0.0.0.0");
 	setValue(configKeys[2], "0");
 	setValue(configKeys[3], "user");
-	setValue(configKeys[5], "0");
+	configInitialized = true;
+	configValid = true;
 }
 
 bool Config::checkConfig() {
-	if (!configValid || configuration.size() != (sizeof(configKeys) / sizeof(*configKeys)))
+	if (!configValid || configuration.size() != configKeys.size())
 		return false;
-	for (int i = 0; i < (sizeof(configKeys) / sizeof(*configKeys)); i++) {
-		if (getValue(configKeys[i]) == "")
-			return false;
-	}
 
 	std::string autofill_ip = getValue("Autofill-IP");
 	if (autofill_ip != "0" && autofill_ip != "1")
@@ -33,18 +33,16 @@ bool Config::checkConfig() {
 	if (autofill_user != "0" && autofill_user != "1")
 		return false;
 
-	std::istringstream iss(getValue("Covert-Channel-Method"));
-	int covert_method;
-	if (!(iss >> covert_method))
-		return false;
-
 	return true;
 }
 
 bool Config::loadFile() {
-	std::ifstream ifile(configPath);
 	std::string line;
 
+	if (!configInitialized)
+		setupDefaultConfig();
+	std::ifstream ifile(configPath);
+
 	if (ifile.is_open()) {
 		while (getline(ifile, line)) {
 			std::stringstream ss(line);
@@ -57,7 +55,7 @@ bool Config::loadFile() {
 				// One line doesn't have the format *=*
 				configValid = false;
 			} else {
-				configuration.insert(std::pair<std::string, std::string>(v.at(0), v.at(1)));
+				configuration[v.at(0)] = v.at(1);
 			}
 		}
 		configValid = true;
@@ -68,6 +66,10 @@ bool Config::loadFile() {
 
 void Config::saveFile() {
 	std::ofstream file;
+
+	if (!configInitialized)
+		setupDefaultConfig();
+
 	file.open(configPath);
 	for (auto const &x : configuration) {
 		file << x.first << "=" << x.second << std::endl;

+ 38 - 23
gui/src/qmlhandler.cpp

@@ -13,6 +13,7 @@
 #include <unistd.h>
 
 #include "../include/climanager.h"
+#include "../include/cmdmanager.h"
 #include "../include/config.h"
 #include "../include/jsonhandler.h"
 #include "../include/qmlhandler.h"
@@ -29,20 +30,14 @@ QMLHandler::QMLHandler(QObject *parent) : QObject(parent) {}
 void QMLHandler::loadSettingsToGUI() {
 	stringstream ss;
 
-	int covertMethod;
-	ss << Config::getValue("Covert-Channel-Method");
-	ss >> covertMethod;
-
-	bool saveIP;
-	ss << Config::getValue("Autofill-IP");
-	ss >> saveIP;
-
-	bool saveUsername;
-	ss << Config::getValue("Autofill-Username");
-	ss >> saveUsername;
+	// The space is needed to get the stringstream to perform proper formatting of multiple values
+	bool saveIP, saveUsername;
+	ss << Config::getValue("Autofill-IP") << " " << Config::getValue("Autofill-Username");
+	ss >> saveIP >> saveUsername;
 
 	QString cliPath = QString::fromStdString(Config::getValue("CLI-Path"));
-	emit loadSettings(covertMethod, saveIP, saveUsername, cliPath);
+	QString keyPath = QString::fromStdString(Config::getValue("Keyfile-Path"));
+	emit loadSettings(saveIP, saveUsername, cliPath, keyPath);
 }
 
 // ### QML Handlers ###
@@ -50,14 +45,10 @@ void QMLHandler::loadSettingsToGUI() {
 void QMLHandler::onStart() {
 	bool configExists = Config::loadFile();
 
-	if (configExists == true) {
+	if (configExists) {
 		// Config exists
-		if (Config::checkConfig() == true) {
+		if (Config::checkConfig()) {
 			// Config is valid
-			if (!ifstream(Config::getValue("CLI-Path"))) {
-				// Invalid CLI Path
-				emit invalidCliPathPopupOpen();
-			}
 			if (Config::getValue("Autofill-IP") == "1") {
 				emit ipPopupSetIP(QString::fromStdString(Config::getValue("Default-IP")));
 				emit ipPopupCheckSaveCheckbox();
@@ -66,6 +57,13 @@ void QMLHandler::onStart() {
 				emit loginSetUsername(QString::fromStdString(Config::getValue("Default-Username")));
 				emit loginSignupCheckSaveCheckbox();
 			}
+			if (!ifstream(Config::getValue("CLI-Path"))) {
+				// Invalid CLI Path
+				emit invalidCliPathPopupOpen();
+			} else {
+				// Everything OK, init CLI
+				CliManager::init();
+			}
 		} else {
 			// Config is invalid
 			emit invalidConfigPopupOpen();
@@ -75,20 +73,20 @@ void QMLHandler::onStart() {
 		Config::setupDefaultConfig();
 		emit noConfigFoundPopupOpen();
 	}
-
-	CliManager::init();
 }
 
 // No Config Found Popup
 void QMLHandler::onNoConfigFoundPopupContinueButton(QString cli_path) {
 	Config::setValue("CLI-Path", cli_path.toUtf8().constData());
 	Config::saveFile();
+	onStart();
 }
 
 // Invalid Cli Path Popup
 void QMLHandler::onInvalidCliPathPopupContinueButton(QString cli_path) {
 	Config::setValue("CLI-Path", cli_path.toUtf8().constData());
 	Config::saveFile();
+	onStart();
 }
 
 void QMLHandler::onInvalidCliPathPopupQuitButton() { emit closeWindow(); }
@@ -140,12 +138,18 @@ void QMLHandler::onReceivingConfirmDeleteFileButton(QString fileName) {
 void QMLHandler::onMessagesSendButton(QString msg) { emit message(msg); }
 
 // Settings
+void QMLHandler::onKeyfileSelected(QString path) {
+	QString command = "keyfile \"" + path + "\"";
+	CliManager::writeToCli(command);
+}
+void QMLHandler::onKeyfileClosed() { CliManager::writeToCli("closekey"); }
 void QMLHandler::onSettingsDeleteMeButton(QString password) {
 	QString command = "deleteme " + password;
 	CliManager::writeToCli(command);
 }
 
 void QMLHandler::onSettingsRevertChangesButton() {
+	Config::loadFile();
 	loadSettingsToGUI();
 	emit log("Settings changes reverted.");
 }
@@ -158,18 +162,26 @@ void QMLHandler::onSettingsResetButton() {
 	emit log("Settings resetted to default.");
 }
 
-void QMLHandler::onSettingsSaveButton(int covertMethod, bool saveIP, bool saveUsername, QString cliPath) {
-	Config::setValue("Covert-Channel-Method", to_string(covertMethod));
+void QMLHandler::onSettingsSaveButton(bool saveIP, bool saveUsername, QString cliPath, QString keyPath) {
 	Config::setValue("Autofill-IP", to_string(saveIP));
 	Config::setValue("Autofill-Username", to_string(saveUsername));
 	Config::setValue("CLI-Path", cliPath.toUtf8().constData());
+	Config::setValue("Keyfile-Path", keyPath.toUtf8().constData());
 	Config::saveFile();
 	emit log("Settings saved.");
 }
 
 // Ip Popup
 void QMLHandler::onIpPopupConnectButton(QString ip, bool saveAsDefault) {
-	QString command = "connect " + ip;
+	QStringList ipport = ip.split(":");
+	QString command = "connect " + ipport[0];
+
+	CmdManager::setCachedIP(ipport[0]);
+	if (ipport.size() > 1) {
+		command += " " + ipport[1];
+		CmdManager::setCachedPort(ipport[1]);
+	}
+
 	CliManager::writeToCli(command);
 
 	emit ipPopupDisableConnectButton();
@@ -177,6 +189,7 @@ void QMLHandler::onIpPopupConnectButton(QString ip, bool saveAsDefault) {
 		Config::setValue("Default-IP", ip.toUtf8().constData());
 		Config::setValue("Autofill-IP", "1");
 		Config::saveFile();
+		loadSettingsToGUI();
 	}
 }
 
@@ -189,6 +202,7 @@ void QMLHandler::onLoginLoginButton(QString username, QString password, bool sav
 		Config::setValue("Default-Username", username.toUtf8().constData());
 		Config::setValue("Autofill-Username", "1");
 		Config::saveFile();
+		loadSettingsToGUI();
 	}
 }
 
@@ -205,6 +219,7 @@ void QMLHandler::onSignupRegisterButton(QString username, QString passwordOne, Q
 		Config::setValue("Default-Username", username.toUtf8().constData());
 		Config::setValue("Autofill-Username", "1");
 		Config::saveFile();
+		loadSettingsToGUI();
 	}
 }