#include "../include/JsonCommander.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["put"] = &JsonCommander::executePut; commandsMap["putdata"] = &JsonCommander::executePutdata; commandsMap["get"] = &JsonCommander::executeGet; commandsMap["getdata"] = &JsonCommander::executeGetdata; } 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"; // TODO return real file list Json::Value array; array.append("some"); array.append("important"); array.append("data"); response.json["names"] = array; response.json["remaining"] = 0; 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(); } 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 data = base64::decodeVector(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; bool opened = fileManager.openGetFile(message["file"].asString(), this->getFileRemaining); if (opened) { 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 data = fileManager.readGet(); response.json["data"] = base64::encodeVector(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::testVersion(const Json::Value &message) { JsonCommander::Response response; response.json["version"] = this->protocolVersion; // check version string is the same if (message["version"].asString().compare(this->protocolVersion) == 0) { 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"] = ""; } else if (!message["login"].asBool()) { // TODO implement registration response.action = closeAndSend; response.json["accept"] = false; response.json["error"] = "registration is not yet implemented"; } else { response.action = closeAndSend; response.json["accept"] = false; response.json["error"] = "wrong username or password"; } return response; }