Browse Source

merge master for daemon

Missingmew 5 years ago
parent
commit
80618c6bb1

+ 174 - 0
Client-Server Protocol.md

@@ -0,0 +1,174 @@
+# Client-Server Protocol
+
+Protocol version: "0.1"
+
+## 1. Start a connection
+
+To start a connection you have to check the versions and verify the login.
+Only if step 1.1 and 1.2 have been accomplished a usable connection is negotiated.
+
+### 1.1 Version check
+Client:
+```
+{
+	"version": string
+}
+```
+
+
+Server:
+```
+{
+	"version": string,
+	"accept": bool
+}
+```
+
+If `accept` is `true` the connection is valid. Else the connection will be terminated after the server answered.
+
+### 1.2 Login
+Client:
+```
+{
+	"user": string,
+	"pass": string
+}
+```
+
+Server:
+```
+{
+	"accept": bool
+}
+```
+
+If `accept` is `true` the connection is valid and the user is logged in. Else the connection will be terminated after the server answered.
+
+
+## 2. Sending commands
+
+Commands can be sent by the client after a connection has been negotiated (See 1).
+Commands can be used unrelated to each other.
+
+### 2.1 Status command
+Client:
+```
+{
+	"command": "status"
+}
+```
+
+Server:
+```
+{
+	"command": "status",
+	"response": string
+}
+```
+
+### 2.2 List command
+Client:
+```
+{
+	"command": "list"
+}
+```
+
+Server:
+```
+{
+	"command": "put",
+	"names": string[],
+	"remaining": int
+}
+```
+The server loops this until all names have been sent and `remaining` hits `0`.
+
+
+### 2.3 Put command
+Client:
+```
+{
+	"command": "put",
+	"file": string,
+	"size": int
+}
+```
+
+Server:
+```
+{
+	"command": "put",
+	"accept": bool
+}
+```
+If `accept` is `true` the connection is valid and the client can start sending the file. Else the put request was rejected and is hereby canceled.
+<br /><br />
+Client:
+```
+{
+	"command": "put",
+	"data": string,
+	"remaining": int,
+	"cancel": bool
+}
+```
+`data` is a base64 string and contains a piece of the file. The client will loop this until the file is completely sent.
+`remaining` is a counter how many chunks will follow and the transfer is over after it hits `0`.
+If `cancel` is `true` the file transfer will be canceled.
+
+
+### 2.4 Get command
+Client:
+```
+{
+	"command": "get",
+	"file": string
+}
+```
+
+Server:
+```
+{
+	"command": "get",
+	"accept": bool
+}
+```
+If `accept` is `true` the connection is valid and the server can start sending the file. Else the get request was rejected and is hereby canceled.
+<br /><br />
+Server:
+```
+{
+	"command": "get",
+	"data": string,
+	"remaining": int,
+	"cancel": bool
+}
+```
+`data` is a base64 string and contains a piece of the file. The server will loop this until the file is completely sent.
+`remaining` is a counter how many chunks will follow and the transfer is over after it hits `0`.
+If `cancel` is `true` the file transfer will be canceled.
+
+
+### TODO
+
+
+## 3. Close connection
+
+### 3.1 Close command
+
+Client:
+```
+{
+	"command": "close"
+}
+```
+
+
+Server:
+```
+{
+	"command": "close",
+	"response": "bye"
+}
+```

+ 6 - 0
cli/src/main.cpp

@@ -12,6 +12,8 @@
 #define sizeofarr(a) (sizeof(a) / sizeof(a[0]))
 
 namespace bpo = boost::program_options;
+namespace bai = boost::asio;
+using bai::ip::tcp;
 
 typedef enum {
   CMD_HELP,
@@ -43,6 +45,10 @@ CMD commands[]{{CMD_HELP, "help", "show help"},
                {CMD_SETUP, "setup", "configure server at IP"},
                {CMD_LOG, "log", "show log from IP"}};
 
+/*  takes a string in str and checks if it is a valid command
+    returns the matching COMMANDTYPES or CMD_UNKNOWN
+    if isshort is nonzero, only the first character of str will be checked
+*/
 COMMANDTYPES getCommand(char *str, unsigned int isshort) {
   COMMANDTYPES ret = CMD_UNKNOWN;
   char temp[COMMANDLEN + 1] = {0};

+ 5 - 3
daemon/CMakeLists.txt

@@ -5,15 +5,17 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
 
 project(ccats)
 
-add_executable(ccats src/main.cpp src/Sniffer.cpp)
+add_executable(ccats src/main.cpp src/Sniffer.cpp src/Server.cpp)
 
 # use pkg-config to fix building on debian unstable
 find_package(PkgConfig REQUIRED)
 pkg_check_modules(TINS REQUIRED libtins>=4.2 libpcap)
+pkg_check_modules(JSONCPP REQUIRED jsoncpp)
 
-find_package(Threads)
+
+find_package(Threads REQUIRED)
 find_package(Boost 1.67 REQUIRED COMPONENTS system)
 # find_package(libtins 4.2 REQUIRED)
 
 include_directories(${Boost_INCLUDE_DIR})
-target_link_libraries(ccats PRIVATE ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES} ${TINS_LIBRARIES} ${PCAP_LIBRARIES})
+target_link_libraries(ccats PRIVATE ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES} ${TINS_LIBRARIES} ${PCAP_LIBRARIES} ${JSONCPP_LIBRARIES})

+ 178 - 0
daemon/include/Server.h

@@ -0,0 +1,178 @@
+#ifndef SERVER_H
+#define SERVER_H
+
+#include <boost/asio.hpp>
+#include <boost/bind.hpp>
+#include <boost/enable_shared_from_this.hpp>
+
+using namespace boost::asio;
+using ip::tcp;
+
+/**
+ * @class con_handler
+ *
+ * Handler for a connection.
+ *
+ * Handles and manages a connection between client and server.
+ */
+class con_handler : public boost::enable_shared_from_this<con_handler> {
+private:
+  tcp::socket sock;
+  const std::string message = "Hello From Server!";
+
+  const std::string protocolVersion = "0.1";
+
+  /**
+   * max buffer length
+   */
+  enum { max_length = 1024 };
+
+  /**
+   * data buffer
+   */
+  char data[max_length];
+
+public:
+  /**
+   * Pointer to a con_handler.
+   */
+  typedef boost::shared_ptr<con_handler> pointer;
+
+  /**
+   * con_handler constructor
+   *
+   * Creates a con_handler
+   *
+   * @param io_service connection info
+   */
+  con_handler(basic_socket_acceptor<ip::tcp>::executor_type &io_service);
+
+  /**
+   * con_handler destructor.
+   */
+  ~con_handler();
+
+  /**
+   * Creates a new con_handler.
+   *
+   * Allocates a new con_hanlder and returns the pointer.
+   *
+   * @param io_service connection info
+   *
+   * @return con_handler pointer
+   */
+  static pointer
+  create(basic_socket_acceptor<ip::tcp>::executor_type &io_service);
+
+  /**
+   * socket getter
+   *
+   * Returns the socket of the connection.
+   *
+   * @return the socket
+   */
+  tcp::socket &socket();
+
+  /**
+   * Starts a connection.
+   *
+   * Negotiates a connection and sets everything important to the connection up.
+   */
+  void start();
+
+  /**
+   * Read handler
+   *
+   * Will be called if something from the client has been received.
+   *
+   * @param err error
+   * @param bytes_transferred amount of transferred bytes
+   */
+  void handle_read(const boost::system::error_code &err,
+                   size_t bytes_transferred);
+
+  /**
+   * Read handler
+   *
+   * Will be called if the server expected a version and received something.
+   *
+   * @param err error
+   * @param bytes_transferred amount of transferred bytes
+   */
+  void handle_read_version(const boost::system::error_code &err,
+                           size_t bytes_transferred);
+
+  /**
+   * Read handler
+   *
+   * Will be called after the version was verifyed. Checks login data.
+   *
+   * @param err error
+   * @param bytes_transferred amount of transferred bytes
+   */
+  void handle_read_login(const boost::system::error_code &err,
+                         size_t bytes_transferred);
+
+  /**
+   * Read handler
+   *
+   * Will be called after the version and login was verifyed. Executes commands.
+   *
+   * @param err error
+   * @param bytes_transferred amount of transferred bytes
+   */
+  void handle_read_command(const boost::system::error_code &err,
+                           size_t bytes_transferred);
+
+  /**
+   * Write handler
+   *
+   * Will be called if the server sends something.
+   *
+   * @param err error
+   * @param bytes_transferred amount of transferred bytes
+   */
+  void handle_write(const boost::system::error_code &err,
+                    size_t bytes_transferred);
+};
+
+/**
+ * @class Server
+ *
+ * boost server
+ *
+ * boost server which creates the handler for the connections.
+ */
+class Server {
+private:
+  tcp::acceptor acceptor_;
+
+  /**
+   * Accepts traffic
+   */
+  void start_accept();
+
+public:
+  /**
+   * Creates a boost server
+   *
+   * @param io_service connection info
+   */
+  Server(io_service &io_service);
+
+  /**
+   * Destroys the server
+   */
+  ~Server();
+
+  /**
+   * Handles traffic?
+   *
+   * @param connection con_handler
+   * @param err error
+   */
+  void handle_accept(con_handler::pointer connection,
+                     const boost::system::error_code &err);
+};
+
+#endif

+ 1 - 1
daemon/include/Sniffer.h

@@ -46,7 +46,7 @@ public:
    *
    * @param filterString pcap filter string
    */
-  void setFilter(std::string filterString);
+  void setFilter(const std::string &filterString);
 
 private:
   /**

+ 314 - 0
daemon/src/Server.cpp

@@ -0,0 +1,314 @@
+#include "../include/Server.h"
+#include <iostream>
+#include <jsoncpp/json/json.h>
+
+using namespace boost::asio;
+using ip::tcp;
+
+/***************
+ * con_handler *
+ ***************/
+
+con_handler::con_handler(
+    basic_socket_acceptor<ip::tcp>::executor_type &io_service)
+    : sock(io_service) {}
+
+con_handler::~con_handler() {}
+
+con_handler::pointer
+con_handler::create(basic_socket_acceptor<ip::tcp>::executor_type &io_service) {
+  return pointer(new con_handler(io_service));
+}
+
+tcp::socket &con_handler::socket() { return sock; }
+
+void con_handler::start() {
+
+  sock.async_read_some(buffer(data, max_length),
+                       boost::bind(&con_handler::handle_read_version,
+                                   shared_from_this(), placeholders::error,
+                                   placeholders::bytes_transferred));
+}
+
+void con_handler::handle_read(const boost::system::error_code &err,
+                              size_t bytes_transferred) {
+  if (!err) {
+    std::cout << this->data << std::endl;
+  } else {
+    std::cerr << "error: " << err.message() << std::endl;
+    sock.close();
+  }
+}
+
+void con_handler::handle_read_version(const boost::system::error_code &err,
+                                      size_t bytes_transferred) {
+  if (!err) {
+    // set up json stuff
+    JSONCPP_STRING err;
+    Json::Value root;
+    Json::CharReaderBuilder builder;
+    const std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
+
+    // parse data
+    if (!reader->parse(this->data, this->data + bytes_transferred, &root,
+                       &err)) {
+      std::cerr << "Json error: " << err << std::endl << "data: " << this->data;
+      sock.close();
+    }
+
+    // create answer
+    Json::Value answer;
+    Json::StreamWriterBuilder stringBuilder;
+
+    answer["version"] = this->protocolVersion;
+
+    // check version string
+    if (root["version"].compare(this->protocolVersion) == 0) {
+      answer["accept"] = true;
+      const std::string answerString = Json::writeString(stringBuilder, answer);
+
+      // send answer
+      sock.async_write_some(buffer(answerString, max_length),
+                            boost::bind(&con_handler::handle_write,
+                                        shared_from_this(), placeholders::error,
+                                        placeholders::bytes_transferred));
+
+      // read next data
+      sock.async_read_some(buffer(data, max_length),
+                           boost::bind(&con_handler::handle_read_login,
+                                       shared_from_this(), placeholders::error,
+                                       placeholders::bytes_transferred));
+    } else {
+      answer["accept"] = false;
+      const std::string answerString = Json::writeString(stringBuilder, answer);
+
+      // send answer
+      sock.async_write_some(buffer(answerString, max_length),
+                            boost::bind(&con_handler::handle_write,
+                                        shared_from_this(), placeholders::error,
+                                        placeholders::bytes_transferred));
+      // close connection
+      sock.close();
+    }
+
+  } else {
+    std::cerr << "error: " << err.message() << std::endl;
+    sock.close();
+  }
+}
+
+void con_handler::handle_read_login(const boost::system::error_code &err,
+                                    size_t bytes_transferred) {
+  if (!err) {
+    // set up json stuff
+    JSONCPP_STRING err;
+    Json::Value root;
+    Json::CharReaderBuilder builder;
+    const std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
+
+    // parse data
+    if (!reader->parse(this->data, this->data + bytes_transferred, &root,
+                       &err)) {
+      std::cerr << "Json error: " << err << std::endl << "data: " << this->data;
+      sock.close();
+    }
+
+    Json::Value answer;
+    Json::StreamWriterBuilder stringBuilder;
+
+    // user credentials
+    // TODO check user credentials!!!
+    if (root["user"].compare("user") == 0 &&
+        root["pass"].compare("pass") == 0) {
+      answer["accept"] = true;
+      const std::string answerString = Json::writeString(stringBuilder, answer);
+
+      // send answer
+      sock.async_write_some(buffer(answerString, max_length),
+                            boost::bind(&con_handler::handle_write,
+                                        shared_from_this(), placeholders::error,
+                                        placeholders::bytes_transferred));
+
+      // read next data
+      sock.async_read_some(buffer(data, max_length),
+                           boost::bind(&con_handler::handle_read_command,
+                                       shared_from_this(), placeholders::error,
+                                       placeholders::bytes_transferred));
+    } else {
+      answer["accept"] = false;
+      const std::string answerString = Json::writeString(stringBuilder, answer);
+
+      // send answer
+      sock.async_write_some(buffer(answerString, max_length),
+                            boost::bind(&con_handler::handle_write,
+                                        shared_from_this(), placeholders::error,
+                                        placeholders::bytes_transferred));
+      // close connection
+      sock.close();
+    }
+
+  } else {
+    std::cerr << "error: " << err.message() << std::endl;
+    sock.close();
+  }
+}
+
+void con_handler::handle_read_command(const boost::system::error_code &err,
+                                      size_t bytes_transferred) {
+  if (!err) {
+    // set up json stuff
+    JSONCPP_STRING err;
+    Json::Value root;
+    Json::CharReaderBuilder builder;
+    const std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
+
+    // parse data
+    if (!reader->parse(this->data, this->data + bytes_transferred, &root,
+                       &err)) {
+      std::cerr << "Json error: " << err << std::endl << "data: " << this->data;
+      sock.close();
+    }
+
+    Json::Value answer;
+    Json::StreamWriterBuilder stringBuilder;
+
+    // check command
+    if (root["command"].compare("status") == 0) {
+      answer["command"] = "status";
+
+      // TODO answer a real status message
+      answer["response"] = "This is a status message :)";
+      const std::string answerString = Json::writeString(stringBuilder, answer);
+
+      // send answer
+      sock.async_write_some(buffer(answerString, max_length),
+                            boost::bind(&con_handler::handle_write,
+                                        shared_from_this(), placeholders::error,
+                                        placeholders::bytes_transferred));
+
+      // read next data
+      sock.async_read_some(buffer(data, max_length),
+                           boost::bind(&con_handler::handle_read_command,
+                                       shared_from_this(), placeholders::error,
+                                       placeholders::bytes_transferred));
+    } else if (root["command"].compare("list") == 0) {
+      answer["command"] = "list";
+
+      // TODO look for real data
+      Json::Value array;
+      array.append("some");
+      array.append("important");
+      array.append("data");
+      answer["names"] = array;
+      answer["remaining"] = 0;
+
+      const std::string answerString = Json::writeString(stringBuilder, answer);
+      // send answer
+      sock.async_write_some(buffer(answerString, max_length),
+                            boost::bind(&con_handler::handle_write,
+                                        shared_from_this(), placeholders::error,
+                                        placeholders::bytes_transferred));
+
+      // read next data
+      sock.async_read_some(buffer(data, max_length),
+                           boost::bind(&con_handler::handle_read_command,
+                                       shared_from_this(), placeholders::error,
+                                       placeholders::bytes_transferred));
+    } else if (root["command"].compare("put") == 0) {
+      answer["command"] = "put";
+
+      // TODO establish real connection and receive file
+      answer["accept"] = false;
+
+      const std::string answerString = Json::writeString(stringBuilder, answer);
+      // send answer
+      sock.async_write_some(buffer(answerString, max_length),
+                            boost::bind(&con_handler::handle_write,
+                                        shared_from_this(), placeholders::error,
+                                        placeholders::bytes_transferred));
+
+      // read next data
+      sock.async_read_some(buffer(data, max_length),
+                           boost::bind(&con_handler::handle_read_command,
+                                       shared_from_this(), placeholders::error,
+                                       placeholders::bytes_transferred));
+    } else if (root["command"].compare("get") == 0) {
+      answer["command"] = "get";
+
+      // TODO establish real connection and send file
+      answer["accept"] = false;
+
+      const std::string answerString = Json::writeString(stringBuilder, answer);
+      // send answer
+      sock.async_write_some(buffer(answerString, max_length),
+                            boost::bind(&con_handler::handle_write,
+                                        shared_from_this(), placeholders::error,
+                                        placeholders::bytes_transferred));
+
+      // read next data
+      sock.async_read_some(buffer(data, max_length),
+                           boost::bind(&con_handler::handle_read_command,
+                                       shared_from_this(), placeholders::error,
+                                       placeholders::bytes_transferred));
+    } else if (root["command"].compare("close") == 0) {
+      answer["command"] = "close";
+      answer["response"] = "bye";
+      const std::string answerString = Json::writeString(stringBuilder, answer);
+
+      // send answer
+      sock.async_write_some(buffer(answerString, max_length),
+                            boost::bind(&con_handler::handle_write,
+                                        shared_from_this(), placeholders::error,
+                                        placeholders::bytes_transferred));
+
+      // close connection
+      sock.close();
+    } else {
+      // TODO handle error
+
+      // close connection
+      sock.close();
+    }
+
+  } else {
+    std::cerr << "error: " << err.message() << std::endl;
+    sock.close();
+  }
+}
+
+void con_handler::handle_write(const boost::system::error_code &err,
+                               size_t bytes_transferred) {
+  if (!err) {
+    std::cout << "Hello World!" << std::endl;
+  } else {
+    std::cerr << "error: " << err.message() << std::endl;
+    sock.close();
+  }
+}
+
+/**********
+ * Server *
+ **********/
+
+void Server::start_accept() {
+  auto executor = acceptor_.get_executor();
+  con_handler::pointer connection = con_handler::create(executor);
+  acceptor_.async_accept(connection->socket(),
+                         boost::bind(&Server::handle_accept, this, connection,
+                                     placeholders::error));
+}
+
+Server::Server(io_service &io_service)
+    : acceptor_(io_service, tcp::endpoint(tcp::v4(), 1234)) {
+  start_accept();
+}
+
+Server::~Server() {}
+
+void Server::handle_accept(con_handler::pointer connection,
+                           const boost::system::error_code &err) {
+  if (!err) {
+    connection->start();
+  }
+  start_accept();
+}

+ 1 - 1
daemon/src/Sniffer.cpp

@@ -21,7 +21,7 @@ void Sniffer::startSniffing() {
   sniffer->sniff_loop(make_sniffer_handler(this, &Sniffer::handle));
 }
 
-void Sniffer::setFilter(std::string filterString) {
+void Sniffer::setFilter(const std::string &filterString) {
   sniffer->set_filter(filterString);
 }
 

+ 10 - 90
daemon/src/main.cpp

@@ -1,109 +1,29 @@
-#include <boost/asio.hpp>
-#include <boost/bind.hpp>
-#include <boost/enable_shared_from_this.hpp>
 #include <iostream>
+#include <thread>
 
+#include "../include/Server.h"
 #include "../include/Sniffer.h"
 
-using namespace boost::asio;
-using ip::tcp;
-using std::cout;
-using std::endl;
-
-class con_handler : public boost::enable_shared_from_this<con_handler> {
-private:
-  tcp::socket sock;
-  std::string message = "Hello From Server!";
-  enum { max_length = 1024 };
-  char data[max_length];
-
-public:
-  typedef boost::shared_ptr<con_handler> pointer;
-  con_handler(basic_socket_acceptor<ip::tcp>::executor_type &io_service)
-      : sock(io_service) {}
-
-  static pointer
-  create(basic_socket_acceptor<ip::tcp>::executor_type &io_service) {
-    return pointer(new con_handler(io_service));
-  }
-
-  tcp::socket &socket() { return sock; }
-
-  void start() {
-    sock.async_read_some(buffer(data, max_length),
-                         boost::bind(&con_handler::handle_read,
-                                     shared_from_this(), placeholders::error,
-                                     placeholders::bytes_transferred));
-
-    sock.async_write_some(buffer(message, max_length),
-                          boost::bind(&con_handler::handle_write,
-                                      shared_from_this(), placeholders::error,
-                                      placeholders::bytes_transferred));
-  }
-
-  void handle_read(const boost::system::error_code &err,
-                   size_t bytes_transferred) {
-    if (!err) {
-      cout << data << endl;
-    } else {
-      std::cerr << "error: " << err.message() << std::endl;
-      sock.close();
-    }
-  }
-
-  void handle_write(const boost::system::error_code &err,
-                    size_t bytes_transferred) {
-    if (!err) {
-      cout << "Hello World!" << endl;
-    } else {
-      std::cerr << "error: " << err.message() << endl;
-      sock.close();
-    }
-  }
-};
-
-class Server {
-private:
-  tcp::acceptor acceptor_;
-  void start_accept() {
-    auto executor = acceptor_.get_executor();
-    con_handler::pointer connection = con_handler::create(executor);
-    acceptor_.async_accept(connection->socket(),
-                           boost::bind(&Server::handle_accept, this, connection,
-                                       placeholders::error));
-  }
-
-public:
-  Server(io_service &io_service)
-      : acceptor_(io_service, tcp::endpoint(tcp::v4(), 1234)) {
-    start_accept();
-  }
-  void handle_accept(con_handler::pointer connection,
-                     const boost::system::error_code &err) {
-    if (!err) {
-      connection->start();
-    }
-    start_accept();
-  }
-};
+using namespace std;
 
 int main(int argc, char *argv[]) {
   if (argc < 2) {
-    std::cout << "Usage: " << argv[0] << " <interface>" << std::endl
-              << std::endl;
+    cout << "Usage: " << argv[0] << " <interface>" << endl << endl;
     return 0;
   }
 
-  const std::string interface = argv[1];
+  const string interface = argv[1];
   Sniffer sniffer(interface);
-  sniffer.startSniffing();
+  thread snifferThread(&Sniffer::startSniffing, sniffer);
 
   try {
     io_service io_service;
     Server server(io_service);
     io_service.run();
-  } catch (std::exception &e) {
-    std::cerr << e.what() << endl;
+  } catch (exception &e) {
+    cerr << e.what() << endl;
   }
+
+  snifferThread.join();
   return 0;
 }

+ 2 - 0
gui/CMakeLists.txt

@@ -5,6 +5,8 @@ project(CCats-GUI LANGUAGES CXX)
 set(CMAKE_INCLUDE_CURRENT_DIR ON)
 set(CMAKE_AUTOMOC ON)
 set(CMAKE_AUTORCC ON)
+set(CMAKE_CXX_STANDARD 11)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
 
 find_package(Threads)
 find_package(Boost 1.67 REQUIRED COMPONENTS system)

+ 28 - 0
gui/src/ReceivingForm.ui.qml

@@ -0,0 +1,28 @@
+import QtQuick 2.12
+import QtQuick.Controls 2.5
+
+Page {
+    width: 1280
+    height: 670
+    title: "Receiving"
+
+    Label {
+        color: "#000000"
+        text: "Why are we not using C# :/"
+        font.pointSize: 30
+        anchors.verticalCenterOffset: 1
+        anchors.horizontalCenterOffset: 1
+        z: 3
+        anchors.centerIn: parent
+    }
+
+    Rectangle {
+        id: rectangle
+        x: 0
+        y: 0
+        width: 1280
+        height: 670
+        color: "#ffffff"
+        z: 2
+    }
+}

+ 50 - 0
gui/src/SendingForm.ui.qml

@@ -0,0 +1,50 @@
+import QtQuick 2.12
+import QtQuick.Controls 2.5
+import QtQuick.Dialogs 1.0
+
+Page {
+    width: 1280
+    height: 670
+
+    title: qsTr("Sending")
+
+    Connections {
+      target: _qmlHandler
+      onSetFileUrlText: {
+        fileUrlText.text = signalText
+      }
+    }
+
+    Button {
+        id: selectFileButton
+        x: 510
+        y: 291
+        width: 260
+        height: 89
+        text: qsTr("Select File")
+        font.pointSize: 16
+        onClicked: {fileDialog.open()}
+    }
+
+    Text {
+        id: fileUrlText
+        x: 54
+        y: 427
+        width: 1172
+        height: 52
+        color: "#ffffff"
+        text: qsTr("")
+        verticalAlignment: Text.AlignVCenter
+        horizontalAlignment: Text.AlignHCenter
+        font.pixelSize: 23
+    }
+
+    FileDialog {
+      id: fileDialog
+      title: "Please choose a file"
+      folder: shortcuts.home
+      onAccepted: {
+        _qmlHandler.onSelectFile(fileDialog.fileUrl)
+      }
+    }
+}

+ 11 - 12
gui/src/main.cpp

@@ -1,6 +1,8 @@
 #include <QGuiApplication>
 #include <QObject>
 #include <QQmlApplicationEngine>
+#include <QQmlComponent>
+#include <QQmlContext>
 #include <csignal>
 #include <cstdio>
 #include <cstdlib>
@@ -18,6 +20,8 @@ int outpipefd[2];
 char buf[1024];
 
 int main(int argc, char *argv[]) {
+  qInfo() << "Program Start";
+
   pid_t pid = 0;
   char msg[256];
   int status;
@@ -45,29 +49,24 @@ int main(int argc, char *argv[]) {
   close(outpipefd[0]);
   close(inpipefd[1]);
 
-  // ########## GUI CODE ##########
+  // ########## Load GUI ##########
 
   QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
 
+  // This has to be here to fix warnings
+  QCoreApplication::setOrganizationName("CCats");
+
   QGuiApplication app(argc, argv);
 
   QQmlApplicationEngine engine;
-  engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
-
-  if (engine.rootObjects().isEmpty())
-    return -1;
 
   QMLHandler qmlHandler;
 
-  QObject *statusButton =
-      engine.rootObjects().first()->findChild<QObject *>("getstatusbutton");
+  engine.rootContext()->setContextProperty("_qmlHandler", &qmlHandler);
 
-  QObject::connect(statusButton, SIGNAL(clicked()), &qmlHandler,
-                   SLOT(onGetStatusClick()));
+  QQmlComponent component(&engine, QUrl(QStringLiteral("qrc:/main.qml")));
 
-  QObject::connect(&qmlHandler, SIGNAL(setStatusMessage(QVariant)),
-                   engine.rootObjects().first(),
-                   SLOT(setStatusMessage(QVariant)));
+  QObject *object = component.create();
 
   return app.exec();
 }

+ 46 - 29
gui/src/main.qml

@@ -1,40 +1,57 @@
-import QtQuick 2.9
-import QtQuick.Window 2.2
-import QtQuick.Controls 1.5
+import QtQuick 2.12
+import QtQuick.Controls 2.5
 
-Window {
+ApplicationWindow {
+    id: window
     visible: true
     width: 1280
     height: 720
-    color: "#191919"
-    title: qsTr("Covert Channel | Control Panel")
+    title: qsTr("Covert Channel - Control Panel")
 
-    function setStatusMessage(text) {
-        statusmessage.text = text
+    header: ToolBar {
+        contentHeight: 50
+
+        ToolButton {
+            id: toolButton
+            text: stackView.depth > 1 ? "\u25C0" : "\u2630"
+            font.pixelSize: Qt.application.font.pixelSize * 1.6
+            onClicked: {
+                if (stackView.depth > 1) {
+                    stackView.pop()
+                } else {
+                    drawer.open()
+                }
+            }
+        }
+
+        Label {
+            text: stackView.currentItem.title
+            anchors.centerIn: parent
+        }
     }
 
-    Text {
-        id: statusmessage
-        objectName: "statusmessage"
-        x: 210
-        y: 583
-        width: 861
-        height: 109
-        color: "#ffffff"
-        text: qsTr("")
-        font.family: "Courier"
-        horizontalAlignment: Text.AlignHCenter
-        fontSizeMode: Text.FixedSize
-        font.pixelSize: 59
+    Drawer {
+        id: drawer
+        width: window.width * 0.66
+        height: 50
+
+        Column {
+            anchors.fill: parent
+
+            ItemDelegate {
+                text: qsTr("Receiving")
+                width: parent.width
+                onClicked: {
+                    stackView.push("ReceivingForm.ui.qml")
+                    drawer.close()
+                }
+            }
+        }
     }
 
-    Button {
-        id: getstatusbutton
-        objectName: "getstatusbutton"
-        x: 504
-        y: 183
-        width: 273
-        height: 73
-        text: qsTr("Get Daemon Status")
+    StackView {
+        id: stackView
+        initialItem: "SendingForm.ui.qml"
+        anchors.fill: parent
     }
 }

+ 3 - 0
gui/src/qml.qrc

@@ -1,5 +1,8 @@
 <RCC>
     <qresource prefix="/">
         <file>main.qml</file>
+        <file>SendingForm.ui.qml</file>
+        <file>ReceivingForm.ui.qml</file>
+        <file>qtquickcontrols2.conf</file>
     </qresource>
 </RCC>

+ 9 - 11
gui/src/qmlhandler.cpp

@@ -1,17 +1,15 @@
 #include "qmlhandler.h"
+#include <string>
 
-#include <unistd.h>
+using namespace std;
 
-extern int inpipefd[2];
-extern int outpipefd[2];
-extern char buf[1024];
+string fileUrl;
 
 QMLHandler::QMLHandler(QObject *parent) : QObject(parent) {}
 
-void QMLHandler::onGetStatusClick() {
-  read(inpipefd[0], buf, 1024);
-  buf[1023] = 0;
-  buf[strlen(buf)] = 0;
-  qInfo() << buf;
-  emit setStatusMessage("Check Terminal plz");
-}
+void QMLHandler::onSelectFile(QUrl url) {
+  qInfo() << "File Selected: " << url.toString();
+  emit setFileUrlText("Selected File: " + url.toString());
+
+  fileUrl = url.toString().toStdString();
+}

+ 3 - 2
gui/src/qmlhandler.h

@@ -3,6 +3,7 @@
 
 #include <QDebug>
 #include <QObject>
+#include <QUrl>
 
 class QMLHandler : public QObject {
   Q_OBJECT
@@ -11,10 +12,10 @@ public:
   explicit QMLHandler(QObject *parent = 0);
 
 signals:
-  void setStatusMessage(QVariant text);
+  void setFileUrlText(QString signalText);
 
 public slots:
-  void onGetStatusClick();
+  void onSelectFile(QUrl url);
 };
 
 #endif // CCATS_GUI_QMLHANDLER_H

+ 13 - 0
gui/src/qtquickcontrols2.conf

@@ -0,0 +1,13 @@
+; This file can be edited to change the style of the application
+; Read "Qt Quick Controls 2 Configuration File" for details:
+; http://doc.qt.io/qt-5/qtquickcontrols2-configuration.html
+
+[Controls]
+Style=Material
+
+[Material]
+Theme=Dark
+;Accent=BlueGrey
+;Primary=BlueGray
+;Foreground=Brown
+;Background=Grey