#include "../include/cmdman.h" #include "../include/global.h" #include #define DEBUGPRINT(x) debugprintfunc(x) //~ #define DEBUGPRINT(x) std::cerr << x //~ #define DEBUGPRINT(x) CmdMan::CmdMan(FileMan &fm, void (*dpf)(string)) : fileman(fm) { /* setup json stuff */ Json::CharReaderBuilder rbuilder; wbuilder.settings_["indentation"] = ""; reader = rbuilder.newCharReader(); doversion = false; loginpossible = false; dologin = false; dosignup = false; /* initialize execute command map */ execmap["help"] = &CmdMan::cmdHelp; execmap["status"] = &CmdMan::cmdStatus; execmap["disconnect"] = &CmdMan::cmdDisconnect; execmap["put"] = &CmdMan::cmdPut; execmap["get"] = &CmdMan::cmdGet; execmap["list"] = &CmdMan::cmdList; execmap["version"] = &CmdMan::cmdVersion; execmap["login"] = &CmdMan::cmdLogin; execmap["signup"] = &CmdMan::cmdSignup; execmap["putdata"] = &CmdMan::cmdPutdata; execmap["getdata"] = &CmdMan::cmdGetdata; execmap["listdata"] = &CmdMan::cmdListdata; /* initialize description map */ helpmap["help"] = descHelp; helpmap["status"] = descStatus; helpmap["disconnect"] = descDisconnect; helpmap["put"] = descPut; helpmap["get"] = descGet; helpmap["list"] = descList; /* initialize handle command map */ handlemap["status"] = &CmdMan::handleStatus; handlemap["close"] = &CmdMan::handleClose; handlemap["put"] = &CmdMan::handlePut; handlemap["get"] = &CmdMan::handleGet; handlemap["putdata"] = &CmdMan::handlePutdata; handlemap["getdata"] = &CmdMan::handleGetdata; handlemap["list"] = &CmdMan::handleList; handlemap["version"] = &CmdMan::handleVersion; handlemap["login"] = &CmdMan::handleLogin; handlemap["signup"] = &CmdMan::handleSignup; handlemap["listdata"] = &CmdMan::handleListdata; debugprintfunc = dpf; } CmdMan::~CmdMan() { delete reader; } CmdMan::CmdRet CmdMan::cmdHelp(vector args) { CmdRet retval; Json::Value root, arr; DEBUGPRINT(string(__PRETTY_FUNCTION__) + " begin"); map::iterator it; root["command"] = "help"; for (it = helpmap.begin(); it != helpmap.end(); it++) { arr.append(it->first + " - " + it->second); } root["names"] = arr; retval.type = print; retval.msg = root; return retval; } CmdMan::CmdRet CmdMan::cmdStatus(vector args) { CmdRet retval; DEBUGPRINT(string(__PRETTY_FUNCTION__) + " begin"); Json::Value root; root["command"] = "status"; retval.type = send; retval.msg = root; return retval; } CmdMan::CmdRet CmdMan::cmdDisconnect(vector args) { CmdRet retval; DEBUGPRINT(string(__PRETTY_FUNCTION__) + " begin"); Json::Value root; retval.type = send; if (loginpossible) { // not logged in, send appropriate login message instead of normal close root["login"] = false; root["user"] = ""; root["pass"] = ""; root["cancel"] = true; retval.type |= close; } else { root["command"] = "close"; } retval.msg = root; return retval; } CmdMan::CmdRet CmdMan::cmdPut(vector args) { CmdRet retval; DEBUGPRINT(string(__PRETTY_FUNCTION__) + " begin"); Json::Value root; if(args.size() < 1) { retval.type = error; root["accept"] = false; root["error"] = "not enough arguments, at least 1 argument required"; } else { bool opened = fileman.openPut(args[0]); root["command"] = "put"; root["file"] = fileman.getPutName(); if (opened) { root["size"] = fileman.getPutSize(); root["chunks"] = fileman.getPutChunks(); retval.type = send; } else { retval.type = error; root["accept"] = false; root["error"] = "couldnt open local file \"" + args[0] + "\""; } } retval.msg = root; return retval; } CmdMan::CmdRet CmdMan::cmdPutdata(vector args) { CmdRet retval; DEBUGPRINT(string(__PRETTY_FUNCTION__) + " begin"); Json::Value root; root["command"] = "putdata"; root["file"] = fileman.getPutName(); root["cancel"] = false; root["data"] = fileman.readBase64(); root["remaining"] = fileman .getPutRemainingChunks(); // number already decremented by readBase64 retval.type = send; retval.msg = root; return retval; } CmdMan::CmdRet CmdMan::cmdGet(vector args) { CmdRet retval; DEBUGPRINT(string(__PRETTY_FUNCTION__) + " begin"); Json::Value root; if(args.size() < 1) { retval.type = error; root["accept"] = false; root["error"] = "not enough arguments, at least 1 argument required"; } else { bool opened = fileman.openGet(args[0]); root["command"] = "get"; root["file"] = fileman.getGetName(); if (opened) { retval.type = send; } else { retval.type = error; root["accept"] = false; root["error"] = "local file \"" + args[0] + "\" already exists"; } } retval.msg = root; return retval; } CmdMan::CmdRet CmdMan::cmdGetdata(vector args) { CmdRet retval; DEBUGPRINT(string(__PRETTY_FUNCTION__) + " begin"); Json::Value root; root["command"] = "getdata"; root["file"] = fileman.getGetName(); root["chunk"] = fileman.getGetRemainingChunks(); root["cancel"] = false; retval.type = send; retval.msg = root; return retval; } CmdMan::CmdRet CmdMan::cmdList(vector args) { CmdRet retval; DEBUGPRINT(string(__PRETTY_FUNCTION__) + " begin"); Json::Value root; bool opened = fileman.openList(); root["command"] = "list"; if (opened) { retval.type = send; } else { retval.type = error; root["accept"] = false; root["names"] = ""; root["error"] = "cannot list, already listing"; } retval.msg = root; return retval; } CmdMan::CmdRet CmdMan::cmdListdata(vector args) { CmdRet retval; DEBUGPRINT(string(__PRETTY_FUNCTION__) + " begin"); Json::Value root; root["command"] = "listdata"; root["chunk"] = fileman.getListRemainingChunks(); root["cancel"] = false; retval.type = send; retval.msg = root; return retval; } CmdMan::CmdRet CmdMan::execute(string cmd, vector args) { DEBUGPRINT(string(__PRETTY_FUNCTION__) + " begin"); DEBUGPRINT(string(__PRETTY_FUNCTION__) + " using command \"" + cmd + "\" with arguments [ "); for (string s : args) DEBUGPRINT(s + " "); DEBUGPRINT("]"); map)>::iterator it = execmap.find(cmd); CmdRet retval; Json::Value root; root["command"] = cmd; if (it == 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 (loginpossible || dologin || 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")) { 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."; retval.msg = root; return retval; } } return (this->*(execmap[cmd]))(args); } /* login and signup commands */ CmdMan::CmdRet CmdMan::cmdLogin(vector args) { CmdRet retval; DEBUGPRINT(string(__PRETTY_FUNCTION__) + " begin"); Json::Value root; if(args.size() < 2) { retval.type = error; root["command"] = "login"; root["accept"] = false; root["error"] = "not enough arguments, at least 2 argument required"; } else { if (loginpossible) { dologin = true; loginpossible = false; root["user"] = args[0]; root["pass"] = args[1]; root["login"] = true; root["cancel"] = false; retval.type = send; } else { root["command"] = "login"; root["error"] = "Login not possible, because you already requested a login " "or you are logged in"; root["accept"] = false; retval.type = error; } } retval.msg = root; return retval; } CmdMan::CmdRet CmdMan::cmdSignup(vector args) { CmdRet retval; DEBUGPRINT(string(__PRETTY_FUNCTION__) + " begin"); Json::Value root; if(args.size() < 2) { retval.type = error; root["command"] = "signup"; root["accept"] = false; root["error"] = "not enough arguments, at least 2 argument required"; } else { if (loginpossible) { dosignup = true; loginpossible = false; root["user"] = args[0]; root["pass"] = args[1]; root["login"] = false; root["cancel"] = false; retval.type = send; } else { root["command"] = "signup"; root["error"] = "Signup not possible, because you already requested a " "login or you are logged in"; root["accept"] = false; retval.type = error; } } retval.msg = root; return retval; } /* internal commands */ CmdMan::CmdRet CmdMan::cmdVersion(vector args) { CmdRet retval; DEBUGPRINT(string(__PRETTY_FUNCTION__) + " begin"); Json::Value root; root["version"] = protocolVersion; retval.type = send; retval.msg = root; doversion = true; return retval; } CmdMan::CmdRet CmdMan::handle(Json::Value root) { CmdRet retval; Json::Value output; DEBUGPRINT(string(__PRETTY_FUNCTION__) + " begin"); if (doversion) root["command"] = "version"; else if (dosignup) root["command"] = "signup"; else if (dologin) root["command"] = "login"; DEBUGPRINT(string(__PRETTY_FUNCTION__) + " using json\n" + Json::writeString(wbuilder, root) + "\n"); string retmsg; map::iterator it = handlemap.find(root["command"].asString()); if (it == handlemap.end()) { retval.type = error; output["command"] = "error"; output["error"] = string(__PRETTY_FUNCTION__) + " unknown command \"" + root["command"].asString() + "\".\nEnsure code is implemented."; retval.msg = output; return retval; } return (this->*(handlemap[root["command"].asString()]))(root); } CmdMan::CmdRet CmdMan::handleStatus(Json::Value root) { CmdRet retval; DEBUGPRINT(string(__PRETTY_FUNCTION__) + " begin"); retval.type = print; retval.msg = root; return retval; } CmdMan::CmdRet CmdMan::handleClose(Json::Value root) { CmdRet retval; DEBUGPRINT(string(__PRETTY_FUNCTION__) + " begin"); retval.type = close; retval.msg = root; return retval; } CmdMan::CmdRet CmdMan::handlePut(Json::Value root) { CmdRet retval; Json::Value output; output["command"] = "put"; output["file"] = fileman.getPutName(); output["accept"] = false; DEBUGPRINT(string(__PRETTY_FUNCTION__) + " begin"); if (!root["accept"].asBool()) { retval.type = error; output["error"] = "Server reports: " + root["error"].asString(); fileman.cancelPut(); } else if (root["file"].asString() != fileman.getPutName()) { retval.type = error; output["error"] = "Server reports filename " + root["file"].asString() + " but actual filename is " + fileman.getPutName(); fileman.cancelPut(); } else { output["accept"] = true; output["error"] = ""; retval.type = print | send; retval.nextcommand = "putdata"; } retval.msg = output; return retval; } CmdMan::CmdRet CmdMan::handlePutdata(Json::Value root) { CmdRet retval; Json::Value output; DEBUGPRINT(string(__PRETTY_FUNCTION__) + " begin"); output["command"] = "putdata"; output["file"] = fileman.getPutName(); output["speed"] = 0.0f; // TODO output["cancel"] = true; if (root["received"].asInt() != fileman.getPutRemainingChunks()) { // the number of remaining chunks received from the daemon does not equal // the number stored at the client side retval.type = error; output["error"] = std::string("Server reports number of " "remaining chunks as ") + std::to_string(root["received"].asInt()) + " but actual number is " + std::to_string(fileman.getPutRemainingChunks()); fileman.cancelPut(); } else if (root["cancel"].asBool()) { retval.type = error; output["error"] = "Server reports: " + root["error"].asString(); fileman.cancelPut(); } else if (root["file"].asString() != fileman.getPutName()) { retval.type = error; output["error"] = "Server reports filename " + root["file"].asString() + " but actual filename is " + fileman.getPutName(); fileman.cancelPut(); } else { output["cancel"] = false; output["error"] = ""; // sent successfully if (!root["received"].asInt()) { // everything sent retval.type = print; // TODO //~ retval.msg = "succesfully uploaded file " + fileman.getPutName(); fileman.closePut(); } else { retval.type = print | send; retval.nextcommand = "putdata"; } } retval.msg = output; return retval; } CmdMan::CmdRet CmdMan::handleGet(Json::Value root) { CmdRet retval; Json::Value output; output["command"] = "get"; output["file"] = fileman.getGetName(); output["accept"] = false; DEBUGPRINT(string(__PRETTY_FUNCTION__) + " begin"); if (!root["accept"].asBool()) { retval.type = error; output["error"] = "Server reports: " + root["error"].asString(); } else if (root["file"].asString() != fileman.getGetName()) { retval.type = error; output["error"] = "Server reports filename " + root["file"].asString() + " but actual filename is " + fileman.getGetName(); } else { fileman.setGetChunks(root["chunks"].asInt()); output["accept"] = true; output["error"] = ""; retval.type = print | send; retval.nextcommand = "getdata"; } retval.msg = output; return retval; } CmdMan::CmdRet CmdMan::handleGetdata(Json::Value root) { CmdRet retval; Json::Value output; DEBUGPRINT(string(__PRETTY_FUNCTION__) + " begin"); output["command"] = "getdata"; output["file"] = fileman.getGetName(); output["speed"] = 0.0f; // TODO output["cancel"] = true; // the passed number of recieved chunks should equal the number of sent chunks if (root["remaining"].asInt() != fileman.getGetRemainingChunks()) { retval.type = error; output["error"] = std::string("Server reports number of remaining chunks as ") + std::to_string(root["remaining"].asInt()) + " but actual number is " + std::to_string(fileman.getGetRemainingChunks()); fileman.cancelGet(); } else if (root["cancel"].asBool()) { retval.type = error; output["error"] = "Server reports: " + root["error"].asString(); fileman.cancelGet(); } else if (root["file"].asString() != fileman.getGetName()) { retval.type = error; output["error"] = "Server reports filename " + root["file"].asString() + " but actual filename is " + fileman.getGetName(); fileman.cancelGet(); } else { output["cancel"] = false; output["error"] = ""; fileman.writeBase64(root["data"].asString()); // loaded successfully if (fileman.getGetRemainingChunks() < 0) { // everything sent retval.type = print; //~ retval.msg = "succesfully downloaded file " + fileman.getGetName(); fileman.closeGet(); } else { retval.type = print | send; retval.nextcommand = "getdata"; } } retval.msg = output; return retval; } CmdMan::CmdRet CmdMan::handleList(Json::Value root) { CmdRet retval; Json::Value output; // LOCALOUTPUT DEBUGPRINT(string(__PRETTY_FUNCTION__) + " begin"); output["command"] = "list"; output["names"] = ""; if (!root["accept"].asBool()) { retval.type = error; output["accept"] = false; output["error"] = "Server reports: " + root["error"].asString(); fileman.cancelList(); } else { fileman.setListChunks(root["chunks"].asInt()); retval.type = send; output["accept"] = true; retval.nextcommand = "listdata"; } retval.msg = output; return retval; } CmdMan::CmdRet CmdMan::handleListdata(Json::Value root) { CmdRet retval; Json::Value output, arr; DEBUGPRINT(string(__PRETTY_FUNCTION__) + " begin"); vector toadd; output["command"] = "list"; output["names"] = ""; output["accept"] = false; // the passed number of recieved chunks should equal the number of sent chunks if (root["remaining"].asInt() != fileman.getListRemainingChunks()) { retval.type = error; output["error"] = std::string("Server reports number of " "remaining chunks as ") + std::to_string(root["remaining"].asInt()) + " but actual number is " + std::to_string(fileman.getListRemainingChunks()); fileman.cancelList(); } else if (root["cancel"].asBool()) { retval.type = error; output["error"] = "Server reports: " + root["error"].asString(); fileman.cancelList(); } else { output["accept"] = true; for (Json::Value i : root["names"]) toadd.push_back(i.asString()); fileman.putListData(toadd); // loaded successfully if (fileman.getListRemainingChunks() < 0) { // everything sent retval.type = print; for (string s : fileman.getListData()) arr.append(s); output["names"] = arr; fileman.closeList(); } else { retval.type = send; retval.nextcommand = "listdata"; } } retval.msg = output; return retval; } CmdMan::CmdRet CmdMan::handleVersion(Json::Value root) { CmdRet retval; Json::Value output; // LOCALOUTPUT DEBUGPRINT(string(__PRETTY_FUNCTION__) + " begin"); output["command"] = "version"; output["serverversion"] = root["version"].asString(); output["clientversion"] = protocolVersion; if (!root["accept"].asBool()) { retval.type = error; output["accept"] = false; } else { retval.type = print | seton; output["accept"] = true; doversion = false; loginpossible = true; } retval.msg = output; return retval; } CmdMan::CmdRet CmdMan::handleLogin(Json::Value root) { CmdRet retval; Json::Value output; // LOCALOUTPUT DEBUGPRINT(string(__PRETTY_FUNCTION__) + " begin"); output["command"] = "login"; if (!root["accept"].asBool()) { retval.type = error; output["error"] = root["error"].asString(); output["accept"] = false; loginpossible = true; dologin = false; } else { retval.type = print | seton; output["error"] = ""; output["accept"] = true; dologin = false; } retval.msg = output; return retval; } CmdMan::CmdRet CmdMan::handleSignup(Json::Value root) { CmdRet retval; Json::Value output; // LOCALOUTPUT DEBUGPRINT(string(__PRETTY_FUNCTION__) + " begin"); output["command"] = "signup"; if (!root["accept"].asBool()) { retval.type = error; output["error"] = root["error"].asString(); output["accept"] = false; loginpossible = true; dosignup = false; } else { retval.type = print | seton; output["error"] = ""; output["accept"] = true; dosignup = false; } retval.msg = output; return retval; }