123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662 |
- #include "../include/JsonCommander.h"
- #include "../include/Config.h"
- #include "../include/Notifications.h"
- #include "../include/Queue.h"
- #include "../include/UserManager.h"
- #include "../include/base64.h"
- JsonCommander::JsonCommander(FileManager &fileManager) : fileManager(fileManager) {
- commandsMap["status"] = &JsonCommander::executeStatus;
- commandsMap["close"] = &JsonCommander::executeClose;
- commandsMap["list"] = &JsonCommander::executeList;
- commandsMap["listdata"] = &JsonCommander::executeListData;
- commandsMap["put"] = &JsonCommander::executePut;
- commandsMap["putdata"] = &JsonCommander::executePutdata;
- commandsMap["get"] = &JsonCommander::executeGet;
- commandsMap["getdata"] = &JsonCommander::executeGetdata;
- commandsMap["head"] = &JsonCommander::executeHead;
- commandsMap["deleteme"] = &JsonCommander::executeDeleteMe;
- commandsMap["deletefile"] = &JsonCommander::executeDeleteFile;
- commandsMap["extendedstatus"] = &JsonCommander::executeExtendedStatus;
- commandsMap["notifications"] = &JsonCommander::executeNotifications;
- commandsMap["queue"] = &JsonCommander::executeQueue;
- commandsMap["dequeue"] = &JsonCommander::executeDequeue;
- }
- JsonCommander::~JsonCommander() {}
- JsonCommander::Response JsonCommander::execute(const Json::Value &message) {
- JsonCommander::Response response;
- Response (JsonCommander::*commandExecutor)(const Json::Value &) = commandsMap[message["command"].asString()];
- if (commandExecutor != nullptr) {
- response = (this->*commandExecutor)(message);
- } else {
- // command does not exist
- response.action = close;
- }
- return response;
- }
- JsonCommander::Response JsonCommander::executeStatus(const Json::Value &message) {
- JsonCommander::Response response;
- response.action = send;
- response.json["command"] = "status";
- // answer a real status message
- std::string status;
- if (this->fileManager.isUploading() && this->fileManager.isDownloading()) {
- status = "download and upload running";
- } else if (this->fileManager.isUploading()) {
- status = "upload running";
- } else if (this->fileManager.isDownloading()) {
- status = "download running";
- } else {
- status = "ok";
- }
- response.json["response"] = status;
- return response;
- }
- JsonCommander::Response JsonCommander::executeClose(const Json::Value &message) {
- JsonCommander::Response response;
- response.action = closeAndSend;
- response.json["command"] = "close";
- response.json["response"] = "bye";
- return response;
- }
- JsonCommander::Response JsonCommander::executeList(const Json::Value &message) {
- JsonCommander::Response response;
- response.action = send;
- response.json["command"] = "list";
- int chunks;
- if (fileManager.getRemainingListChunks() > 0) {
- response.json["accept"] = false;
- response.json["chunks"] = -1;
- response.json["items"] = -1;
- response.json["error"] = "there is already an open list command";
- } else if ((chunks = fileManager.openList()) == -1) { // TODO do we need to check? maybe. Think about it
- response.json["accept"] = false;
- response.json["chunks"] = -1;
- response.json["items"] = -1;
- response.json["error"] = "there is a filename which is too long";
- } else {
- response.json["accept"] = true;
- response.json["chunks"] = chunks;
- response.json["items"] = fileManager.getListSize();
- response.json["error"] = "";
- }
- return response;
- }
- JsonCommander::Response JsonCommander::executeListData(const Json::Value &message) {
- JsonCommander::Response response;
- response.action = send;
- response.json["command"] = "listdata";
- Json::Value array;
- const int remainingListchunks = fileManager.getRemainingListChunks();
- if (!message["chunk"].isInt() || !message["cancel"].isBool()) {
- response.action = closeAndSend;
- response.json["cancel"] = true;
- response.json["remaining"] = -1;
- response.json["names"] = Json::arrayValue;
- response.json["error"] = "incorrect listdata command request";
- } else if (remainingListchunks == 0) {
- response.json["cancel"] = true;
- response.json["remaining"] = -1;
- response.json["names"] = Json::arrayValue;
- response.json["error"] = "there are no chunks to send";
- } else if (message["cancel"].asBool()) {
- response.json["cancel"] = true;
- response.json["remaining"] = message["chunk"].asInt(); // so it can be associated to the request
- response.json["names"] = Json::arrayValue;
- response.json["error"] = "";
- fileManager.cancelList();
- } else if (remainingListchunks - 1 != message["chunk"].asInt()) {
- response.action = closeAndSend;
- response.json["cancel"] = true;
- response.json["remaining"] = -1;
- response.json["names"] = Json::arrayValue;
- response.json["error"] = "wrong chunk number";
- } else {
- std::vector<std::string> v = fileManager.getNextChunkFromList();
- for (int i = 0; i < v.size(); i++)
- array.append(v.at(i));
- response.json["remaining"] = message["chunk"].asInt();
- response.json["cancel"] = false;
- response.json["names"] = array;
- response.json["error"] = "";
- }
- return response;
- }
- JsonCommander::Response JsonCommander::executePut(const Json::Value &message) {
- JsonCommander::Response response;
- response.json["command"] = "put";
- response.json["file"] = message["file"].asString();
- if (!message["file"].isString() || !message["size"].isInt() || !message["chunks"].isInt()) {
- // if request is incomplete close connection
- response.action = closeAndSend;
- response.json["accept"] = false;
- response.json["error"] = "incorrect put command request";
- } else if (fileManager.isUploading()) {
- // if an upload is alread running deny request
- response.action = send;
- response.json["accept"] = false;
- response.json["error"] = "upload already running";
- } else if (message["chunks"].asInt() <= 0) {
- response.action = send;
- response.json["accept"] = false;
- response.json["error"] = "there must be at least one chunk";
- } else if (fileManager.checkFilename(message["file"].asString())) {
- // accept request
- response.action = send;
- bool opened = fileManager.openPutFile(message["file"].asString());
- if (opened) {
- response.json["accept"] = true;
- response.json["error"] = "";
- this->putFileReceived = message["chunks"].asInt();
- this->putSize = message["chunks"].asInt();
- } else {
- response.json["accept"] = false;
- response.json["error"] = "file already exists";
- }
- } else {
- // deny request if file name is not valid
- response.action = send;
- response.json["accept"] = false;
- response.json["error"] = "invalid file name";
- }
- return response;
- }
- JsonCommander::Response JsonCommander::executePutdata(const Json::Value &message) {
- JsonCommander::Response response;
- response.json["command"] = "putdata";
- response.json["file"] = message["file"].asString();
- response.json["received"] = message["remaining"].asInt();
- if (!message["file"].isString() || !message["data"].isString() || !message["remaining"].isInt() || !message["cancel"].isBool()) {
- // if request is incomplete close connection
- response.action = closeAndSend;
- response.json["cancel"] = true;
- response.json["error"] = "incorrect putdata command request";
- this->fileManager.cancelPut();
- } else if (!fileManager.isUploading()) {
- // no upload running -> command
- response.action = send;
- response.json["cancel"] = true;
- response.json["error"] = "no upload running";
- } else if (message["cancel"].asBool()) {
- response.action = send;
- response.json["cancel"] = true;
- response.json["error"] = "";
- this->fileManager.cancelPut();
- } else if (message["file"].asString().compare(fileManager.getPutBaseFileName()) == 0) {
- if (--this->putFileReceived == message["remaining"].asInt()) {
- // accept request
- response.action = send;
- response.json["cancel"] = false;
- response.json["error"] = "";
- const std::vector<char> data = base64::decode<std::vector<char>>(message["data"].asString());
- fileManager.writePut(data);
- this->putFileReceived = message["remaining"].asInt();
- if (this->putFileReceived == 0) {
- // close file after last chunk was received
- this->fileManager.closePutFile();
- }
- } else {
- // wrong remaining number
- response.action = send;
- response.json["cancel"] = true;
- response.json["error"] = "wrong remaining number";
- this->fileManager.cancelPut();
- }
- } else {
- // wrong file name
- response.action = send;
- response.json["cancel"] = true;
- response.json["error"] = "another file was already being uploaded";
- this->fileManager.cancelPut();
- }
- return response;
- }
- JsonCommander::Response JsonCommander::executeGet(const Json::Value &message) {
- JsonCommander::Response response;
- response.json["command"] = "get";
- response.json["file"] = message["file"].asString();
- if (!message["file"].isString()) {
- // if request is incomplete close connection
- response.action = closeAndSend;
- response.json["accept"] = false;
- response.json["chunks"] = -1;
- response.json["error"] = "incorrect get command request";
- } else if (fileManager.isDownloading()) {
- // if an upload is alread running deny request
- response.action = send;
- response.json["accept"] = false;
- response.json["chunks"] = -1;
- response.json["error"] = "download already running";
- } else if (fileManager.checkFilename(message["file"].asString())) {
- // accept request
- response.action = send;
- std::pair<bool, int> opened = fileManager.openGetFile(message["file"].asString());
- if (opened.first) {
- this->getFileRemaining = opened.second;
- this->getSize = opened.second;
- response.json["accept"] = true;
- response.json["chunks"] = this->getFileRemaining;
- response.json["error"] = "";
- } else {
- response.json["accept"] = false;
- response.json["chunks"] = -1;
- response.json["error"] = "file does not exist";
- }
- } else {
- // deny request if file name is not valid
- response.action = send;
- response.json["accept"] = false;
- response.json["chunks"] = -1;
- response.json["error"] = "invalid file name";
- }
- return response;
- }
- JsonCommander::Response JsonCommander::executeGetdata(const Json::Value &message) {
- JsonCommander::Response response;
- response.json["command"] = "getdata";
- response.json["file"] = message["file"].asString();
- response.json["remaining"] = message["chunk"].asInt();
- if (!message["file"].isString() || !message["chunk"].isInt() || !message["cancel"].isBool()) {
- // if request is incomplete close connection
- response.action = closeAndSend;
- response.json["cancel"] = true;
- response.json["data"] = "";
- response.json["error"] = "incorrect putdata command request";
- this->fileManager.closeGetFile();
- } else if (!fileManager.isDownloading()) {
- // no upload running -> command
- response.action = send;
- response.json["cancel"] = true;
- response.json["data"] = "";
- response.json["error"] = "no download running";
- } else if (message["cancel"].asBool()) {
- response.action = send;
- response.json["cancel"] = true;
- response.json["data"] = "";
- response.json["error"] = "";
- this->fileManager.closeGetFile();
- } else if (message["file"].asString().compare(fileManager.getGetBaseFileName()) == 0) {
- if (--this->getFileRemaining == message["chunk"].asInt()) {
- // accept request
- response.action = send;
- response.json["cancel"] = false;
- response.json["error"] = "";
- const std::vector<char> data = fileManager.readGet();
- response.json["data"] = base64::encode<std::vector<char>>(data);
- fileManager.writePut(data);
- if (this->getFileRemaining == 0) {
- // close file after last chunk was sent
- this->fileManager.closeGetFile();
- }
- } else {
- // wrong chunk number
- response.action = send;
- response.json["cancel"] = true;
- response.json["data"] = "";
- response.json["error"] = "wrong chunk number";
- this->fileManager.closeGetFile();
- }
- } else {
- // wrong file name
- response.action = send;
- response.json["cancel"] = true;
- response.json["data"] = "";
- response.json["error"] = "another file was already being downloaded";
- this->fileManager.closeGetFile();
- }
- return response;
- }
- JsonCommander::Response JsonCommander::executeHead(const Json::Value &message) {
- JsonCommander::Response response;
- response.action = send;
- response.json["command"] = "head";
- if (!message["file"].isString()) {
- response.json["accept"] = false;
- response.json["file"] = "";
- response.json["data"] = "";
- response.json["error"] = "incorrect head command request";
- } else {
- std::pair<std::vector<char>, FileManager::Error> res = fileManager.getBytesFromFile(message["file"].asString(), 4);
- switch (res.second) {
- case FileManager::Error::no_error:
- response.json["accept"] = true;
- response.json["file"] = message["file"].asString();
- response.json["data"] = base64::encode<std::vector<char>>(res.first);
- response.json["error"] = "";
- break;
- case FileManager::Error::no_such_file:
- response.json["accept"] = false;
- response.json["file"] = message["file"].asString();
- response.json["data"] = "";
- response.json["error"] = "no such file";
- break;
- case FileManager::Error::file_too_small:
- response.json["accept"] = false;
- response.json["file"] = message["file"].asString();
- response.json["data"] = "";
- response.json["error"] = "file is smaller than specified size";
- break;
- default:
- response.action = closeAndSend;
- response.json["accept"] = false;
- response.json["file"] = message["file"];
- response.json["data"] = "";
- response.json["error"] = "internal error. Please fix this!!!";
- }
- }
- return response;
- }
- JsonCommander::Response JsonCommander::executeDeleteMe(const Json::Value &message) {
- JsonCommander::Response response;
- response.json["command"] = "deleteme";
- if (!message["pass"].isString()) {
- response.action = closeAndSend;
- response.json["accept"] = false;
- response.json["error"] = "incorrect deleteme command request";
- } else if (UserManager::deleteUser(currentUser, message["pass"].asString())) {
- // success
- response.action = closeAndSend;
- response.json["accept"] = true;
- response.json["error"] = "";
- } else {
- response.action = send;
- response.json["accept"] = false;
- response.json["error"] = "wrong password";
- }
- return response;
- }
- JsonCommander::Response JsonCommander::testVersion(const Json::Value &message) {
- JsonCommander::Response response;
- response.json["major"] = this->protocolMajorVersion;
- response.json["minor"] = this->protocolMinorVersion;
- if (!message["major"].isInt() || !message["minor"].isInt()) {
- response.action = closeAndSend;
- response.json["accept"] = false;
- } else if (message["major"].asInt() == this->protocolMajorVersion && message["minor"].asInt() <= this->protocolMinorVersion) {
- response.action = send;
- response.json["accept"] = true;
- } else {
- response.action = closeAndSend;
- response.json["accept"] = false;
- }
- return response;
- }
- JsonCommander::Response JsonCommander::checkLogin(const Json::Value &message) {
- JsonCommander::Response response;
- if (!message["login"].isBool() || !message["user"].isString() || !message["pass"].isString() || !message["cancel"].isBool()) {
- // invalid login request
- response.action = closeAndSend;
- response.json["accept"] = false;
- response.json["error"] = "invalid login request";
- } else if (message["cancel"].asBool()) {
- response.action = close;
- } else if (message["login"].asBool() && UserManager::isAllowed(message["user"].asString(), message["pass"].asString())) {
- // credential check
- response.action = send;
- response.json["accept"] = true;
- response.json["error"] = "";
- currentUser = message["user"].asString();
- } else if (!message["login"].asBool()) {
- // add user. Check if already exists before
- if (!UserManager::addUser(message["user"].asString(), message["pass"].asString())) {
- response.action = closeAndSend;
- response.json["accept"] = false;
- response.json["error"] = "user does already exist";
- } else {
- response.action = send;
- response.json["accept"] = true;
- response.json["error"] = "";
- currentUser = message["user"].asString();
- }
- } else {
- // reject user
- response.action = closeAndSend;
- response.json["accept"] = false;
- response.json["error"] = "wrong username or password";
- }
- return response;
- }
- JsonCommander::Response JsonCommander::executeDeleteFile(const Json::Value &message) {
- JsonCommander::Response response;
- response.json["command"] = "deletefile";
- if (!message["file"].isString()) {
- response.action = closeAndSend;
- response.json["accept"] = false;
- response.json["error"] = "incorrect deletefile command request";
- response.json["file"] = "";
- } else {
- response.action = send;
- FileManager::Error err = fileManager.deleteFile(message["file"].asString());
- switch (err) {
- case FileManager::Error::no_error:
- response.json["accept"] = true;
- response.json["error"] = "";
- response.json["file"] = message["file"];
- break;
- case FileManager::Error::not_allowed:
- response.json["accept"] = false;
- response.json["error"] = "deleting files is disabled";
- response.json["file"] = message["file"];
- break;
- case FileManager::Error::no_such_file:
- response.json["accept"] = false;
- response.json["error"] = "no such file";
- response.json["file"] = message["file"];
- break;
- default:
- response.action = closeAndSend;
- response.json["accept"] = false;
- response.json["error"] = "internal error. Please fix this!!!";
- response.json["file"] = message["file"];
- }
- }
- return response;
- }
- JsonCommander::Response JsonCommander::executeExtendedStatus(const Json::Value &message) {
- JsonCommander::Response response;
- response.json["command"] = "extendedstatus";
- // get status from client server transfers
- int index = 0;
- if (fileManager.isUploading()) {
- response.json["transfersclientserver"][index]["upload"] = true;
- response.json["transfersclientserver"][index]["file"] = fileManager.getPutBaseFileName();
- int progress = 0;
- if (this->putSize != 0) {
- double d = (double)this->putFileReceived / (double)this->putSize;
- progress = (int)(d * 100);
- }
- response.json["transfersclientserver"][index]["progress"] = progress;
- index++;
- }
- if (fileManager.isDownloading()) {
- response.json["transfersclientserver"][index]["upload"] = false;
- response.json["transfersclientserver"][index]["file"] = fileManager.getGetBaseFileName();
- int progress = 0;
- if (this->getSize != 0) {
- double d = 1 - ((double)this->getFileRemaining / (double)this->getSize);
- progress = (int)(d * 100);
- }
- response.json["transfersclientserver"][index]["progress"] = progress;
- }
- // get status from covert channel
- index = 0;
- if (Queue::channel != nullptr && Queue::channel->isTransferRunning()) {
- response.json["transfersserverserver"][index]["type"] = Config::getValue("passiveMode").compare("true") == 0 ? "download" : "upload";
- response.json["transfersserverserver"][index]["file"] = Queue::curTransfer;
- auto rawprogress = Queue::channel->getProgress();
- double d = ((double)rawprogress.first / (double)rawprogress.second);
- int progress = (int)(d * 100);
- response.json["transfersserverserver"][index]["progress"] = progress;
- std::time_t startTime = Queue::channel->getTransferStart();
- std::time_t curTime = std::time(nullptr);
- std::time_t diffTime = curTime - startTime;
- double speed = (double)rawprogress.first / (double)diffTime;
- response.json["transfersserverserver"][index]["speed"] = speed;
- response.json["transfersserverserver"][index]["method"] = Config::getValue("covertChannelMode");
- index++;
- }
- for (int i = 0; i < Queue::queue.size(); i++) {
- response.json["transfersserverserver"][index]["type"] = "queued";
- response.json["transfersserverserver"][index]["file"] = Queue::queue[i];
- response.json["transfersserverserver"][index]["progress"] = 0;
- response.json["transfersserverserver"][index]["speed"] = 0;
- response.json["transfersserverserver"][index]["method"] = Config::getValue("covertChannelMode");
- index++;
- }
- response.json["accept"] = true;
- response.json["error"] = "";
- response.action = send;
- return response;
- }
- JsonCommander::Response JsonCommander::executeNotifications(const Json::Value &message) {
- JsonCommander::Response response;
- response.json["command"] = "notifications";
- Json::Value array;
- std::vector<std::string> v = Notifications::getMessages(currentUser);
- for (int i = 0; i < v.size(); i++)
- array.append(v.at(i));
- response.action = send;
- response.json["messages"] = array;
- response.json["accept"] = true;
- response.json["error"] = "";
- return response;
- }
- JsonCommander::Response JsonCommander::executeQueue(const Json::Value &message) {
- JsonCommander::Response response;
- response.json["command"] = "queue";
- if (!message["file"].isString()) {
- response.action = closeAndSend;
- response.json["file"] = "";
- response.json["accept"] = false;
- response.json["error"] = "invalid request";
- } else {
- bool res = Queue::push(message["file"].asString());
- if (res) {
- response.action = send;
- response.json["file"] = message["file"].asString();
- response.json["accept"] = true;
- response.json["error"] = "";
- } else {
- response.action = send;
- response.json["file"] = message["file"].asString();
- response.json["accept"] = false;
- response.json["error"] = "file could not be queued";
- }
- }
- return response;
- }
- JsonCommander::Response JsonCommander::executeDequeue(const Json::Value &message) {
- JsonCommander::Response response;
- response.json["command"] = "dequeue";
- if (!message["file"].isString()) {
- response.action = closeAndSend;
- response.json["file"] = "";
- response.json["accept"] = false;
- response.json["error"] = "invalid request";
- } else {
- bool res = Queue::remove(message["file"].asString());
- if (res) {
- response.action = send;
- response.json["file"] = message["file"].asString();
- response.json["accept"] = true;
- response.json["error"] = "";
- } else {
- response.action = send;
- response.json["file"] = message["file"].asString();
- response.json["accept"] = false;
- response.json["error"] = "cannot remove this file from queue";
- }
- }
- return response;
- }
|