#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(); currentState = connectionpossible; /* initialize execute command map */ execmap["help"] = &CmdMan::cmdHelp; execmap["status"] = &CmdMan::cmdStatus; execmap["extendedstatus"] = &CmdMan::cmdExtendedstatus; execmap["disconnect"] = &CmdMan::cmdDisconnect; execmap["put"] = &CmdMan::cmdPut; execmap["get"] = &CmdMan::cmdGet; execmap["list"] = &CmdMan::cmdList; execmap["extendedlist"] = &CmdMan::cmdExtendedlist; execmap["version"] = &CmdMan::cmdVersion; execmap["login"] = &CmdMan::cmdLogin; execmap["signup"] = &CmdMan::cmdSignup; execmap["putdata"] = &CmdMan::cmdPutdata; execmap["getdata"] = &CmdMan::cmdGetdata; execmap["listdata"] = &CmdMan::cmdListdata; execmap["extendedlistdata"] = &CmdMan::cmdExtendedlistdata; execmap["head"] = &CmdMan::cmdHead; execmap["deletefile"] = &CmdMan::cmdDeletefile; execmap["deleteme"] = &CmdMan::cmdDeleteme; execmap["keyfile"] = &CmdMan::cmdKeyfile; execmap["closekey"] = &CmdMan::cmdClosekey; execmap["queue"] = &CmdMan::cmdQueue; execmap["dequeue"] = &CmdMan::cmdDequeue; execmap["notifications"] = &CmdMan::cmdNotifications; execmap["connect"] = &CmdMan::cmdConnect; execmap["exit"] = &CmdMan::cmdExit; /* initialize description map */ helpmap["help"] = descHelp; helpmap["status"] = descStatus; helpmap["extendedstatus"] = descExtendedstatus; helpmap["disconnect"] = descDisconnect; helpmap["put"] = descPut; helpmap["get"] = descGet; helpmap["list"] = descList; helpmap["extendedlist"] = descExtendedlist; helpmap["head"] = descHead; helpmap["login"] = descLogin; helpmap["signup"] = descSignup; helpmap["deletefile"] = descDeletefile; helpmap["deleteme"] = descDeleteme; helpmap["keyfile"] = descKeyfile; helpmap["closekey"] = descClosekey; helpmap["queue"] = descQueue; helpmap["dequeue"] = descDequeue; helpmap["notifications"] = descNotifications; helpmap["connect"] = descConnect; helpmap["exit"] = descExit; /* initialize handle command map */ handlemap["status"] = &CmdMan::handleStatus; handlemap["extendedstatus"] = &CmdMan::handleExtendedstatus; 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["extendedlist"] = &CmdMan::handleExtendedlist; handlemap["version"] = &CmdMan::handleVersion; handlemap["login"] = &CmdMan::handleLogin; handlemap["signup"] = &CmdMan::handleSignup; handlemap["listdata"] = &CmdMan::handleListdata; handlemap["extendedlistdata"] = &CmdMan::handleExtendedlistdata; handlemap["head"] = &CmdMan::handleHead; handlemap["deletefile"] = &CmdMan::handleDeletefile; handlemap["deleteme"] = &CmdMan::handleDeleteme; handlemap["queue"] = &CmdMan::handleQueue; handlemap["dequeue"] = &CmdMan::handleDequeue; handlemap["notifications"] = &CmdMan::handleNotifications; debugprintfunc = dpf; } CmdMan::~CmdMan() { delete reader; } void CmdMan::stateSetConnectionOk() { currentState = versionpossible; } void CmdMan::stateSetDisconnected() { currentState = connectionpossible; fileman.cancelGet(); fileman.cancelPut(); fileman.cancelList(); } 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"; if (currentState == normal) { retval.type = send; } else if (currentState == connectionpossible || currentState == disconnecttoexit || currentState == disconnecttoexitearly) { retval.type = print; root["response"] = "You are not connected."; } else { retval.type = print; root["response"] = "Connected to " + ip + ":" + std::to_string(port) + ". Not logged in."; } retval.msg = root; return retval; } CmdMan::CmdRet CmdMan::cmdExtendedstatus(vector args) { CmdRet retval; DEBUGPRINT(string(__PRETTY_FUNCTION__) + " begin"); Json::Value root; root["command"] = "extendedstatus"; 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 (currentState == loginpossible || currentState == disconnecttoexitearly) { // not logged in, send appropriate login message instead of normal close root["login"] = false; root["user"] = ""; root["pass"] = ""; root["cancel"] = true; retval.type |= close | noanswerexpected; if (currentState == disconnecttoexitearly) { retval.nextcommand = "exit"; } currentState = connectionpossible; } 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["command"] = "error"; root["error"] = "Not enough arguments, put requires at least 1 argument."; } else { root["command"] = "put"; if (fileman.isPutting()) { retval.type = error; root["file"] = args[0]; root["accept"] = false; root["error"] = "already putting file \"" + fileman.getPutName() + "\""; } else { bool opened = fileman.openPut(args[0]); if (opened) { root["file"] = fileman.getPutName(); root["size"] = fileman.getPutSize(); root["chunks"] = fileman.getPutChunks(); retval.type = send; } else { retval.type = error; root["file"] = fileman.pathToFilename(args[0]); 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"; if (!fileman.isPutting()) { root["error"] = "Client cannot handle input (received command \"putdata\")."; retval.type = error; } else { 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["command"] = "error"; root["error"] = "Not enough arguments, get requires at least 1 argument."; } else { root["command"] = "get"; if (fileman.isGetting()) { retval.type = error; root["file"] = args[0]; root["accept"] = false; root["error"] = "already getting file \"" + fileman.getGetName() + "\""; } else { bool opened = fileman.openGet(args[0]); root["file"] = fileman.getGetName(); if (opened) { root["file"] = fileman.getGetName(); retval.type = send; } else { root["file"] = fileman.pathToFilename(args[0]); root["accept"] = false; root["error"] = "local file \"" + args[0] + "\" already exists"; retval.type = error; } } } retval.msg = root; return retval; } CmdMan::CmdRet CmdMan::cmdGetdata(vector args) { CmdRet retval; DEBUGPRINT(string(__PRETTY_FUNCTION__) + " begin"); Json::Value root; root["command"] = "getdata"; if (!fileman.isGetting()) { root["error"] = "Client cannot handle input (received command \"getdata\")."; retval.type = error; } else { 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(false); 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; if (!fileman.isListingSimple()) { root["command"] = "list"; root["error"] = "Client cannot handle input (received command \"listdata\")."; retval.type = error; } else { root["command"] = "listdata"; root["chunk"] = fileman.getListRemainingChunks(); root["cancel"] = false; retval.type = send; } retval.msg = root; return retval; } CmdMan::CmdRet CmdMan::cmdExtendedlist(vector args) { CmdRet retval; DEBUGPRINT(string(__PRETTY_FUNCTION__) + " begin"); Json::Value root; bool opened = fileman.openList(true); root["command"] = "extendedlist"; 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::cmdExtendedlistdata(vector args) { CmdRet retval; DEBUGPRINT(string(__PRETTY_FUNCTION__) + " begin"); Json::Value root; if (!fileman.isListingExtended()) { root["command"] = "extendedlist"; root["error"] = "Client cannot handle input (received command \"listdata\")."; retval.type = error; } else { root["command"] = "extendedlistdata"; root["chunk"] = fileman.getListRemainingChunks(); root["cancel"] = false; retval.type = send; } retval.msg = root; return retval; } CmdMan::CmdRet CmdMan::cmdHead(vector args) { CmdRet retval; DEBUGPRINT(string(__PRETTY_FUNCTION__) + " begin"); Json::Value root; if (args.size() < 1) { retval.type = error; root["command"] = "error"; root["accept"] = false; root["error"] = "Not enough arguments, head requires at least 1 argument."; } else { root["command"] = "head"; root["file"] = args[0]; retval.type = send; } retval.msg = root; return retval; } CmdMan::CmdRet CmdMan::cmdDeletefile(vector args) { CmdRet retval; DEBUGPRINT(string(__PRETTY_FUNCTION__) + " begin"); Json::Value root; if (args.size() < 1) { retval.type = error; root["command"] = "error"; root["accept"] = false; root["error"] = "Not enough arguments, deletefile requires at least 1 argument."; } else { root["command"] = "deletefile"; root["file"] = args[0]; retval.type = send; } retval.msg = root; return retval; } CmdMan::CmdRet CmdMan::cmdConnect(vector args) { CmdRet retval; DEBUGPRINT(string(__PRETTY_FUNCTION__) + " begin"); Json::Value root; if (args.size() < 1) { retval.type = error; root["command"] = "error"; root["accept"] = false; root["error"] = "Not enough arguments, connect requires at least 1 argument."; } else if (currentState != connectionpossible) { retval.type = error; root["command"] = "error"; // analogous to execute() method when command unavailable root["error"] = "Connecting not possible, you are already connected to a server."; } else { // set internal ip and port fields first ip = args[0]; if (args.size() < 2) { port = 1234; } else { port = (unsigned int)stoul(args[1]); } // construct json retval.type = connect; root["command"] = "connect"; root["address"] = ip; root["port"] = port; } 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("]"); cmdmutex.lock(); map)>::iterator execit = execmap.find(cmd); vector::const_iterator alwaysit; vector::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 (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; cmdmutex.unlock(); return retval; } 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("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 ") + allowedCommands + "\n" + "Use help for usage of these commands."; retval.msg = root; cmdmutex.unlock(); return retval; } } else if (currentState == versionpossible || currentState == doversion) { DEBUGPRINT("execute does version"); DEBUGPRINT(string("comparison is ") + std::to_string(cmd.compare("version"))); if (cmd.compare("version")) { retval.type = error; root["command"] = "error"; root["error"] = string("Version not checked yet. No commands avalable."); retval.msg = root; cmdmutex.unlock(); return retval; } } else if (currentState == connectionpossible) { DEBUGPRINT("execute does connect"); DEBUGPRINT(string("comparison is ") + std::to_string(cmd.compare("connect"))); if (cmd.compare("version") && cmd.compare("connect")) { retval.type = error; root["command"] = "error"; root["error"] = "Not connected. Please connect."; retval.msg = root; cmdmutex.unlock(); return retval; } } retval = (this->*(execmap[cmd]))(args); cmdmutex.unlock(); return retval; } CmdMan::CmdRet CmdMan::cmdDeleteme(vector args) { CmdRet retval; DEBUGPRINT(string(__PRETTY_FUNCTION__) + " begin"); Json::Value root; if (args.size() < 1) { retval.type = error; root["command"] = "error"; root["error"] = "Not enough arguments, deleteme requires at least 1 argument."; } else { retval.type = send; root["command"] = "deleteme"; root["pass"] = args[0]; } retval.msg = root; return retval; } CmdMan::CmdRet CmdMan::cmdKeyfile(vector args) { CmdRet retval; Json::Value root; DEBUGPRINT(string(__PRETTY_FUNCTION__) + " begin"); if (args.size() < 1) { retval.type = error; root["command"] = "error"; root["error"] = "Not enough arguments, keyfile requires at least 1 argument."; } else { DEBUGPRINT(string(__PRETTY_FUNCTION__) + " haveargs"); root["command"] = "keyfile"; if (!fileman.openKey(args[0])) { DEBUGPRINT(string(__PRETTY_FUNCTION__) + " openkey fail"); root["accept"] = false; root["file"] = args[0]; root["error"] = string("couldnt open keyfile, openssl reports: ") + fileman.getOpensslError(); retval.type = error; } else { DEBUGPRINT(string(__PRETTY_FUNCTION__) + " openkey good"); root["accept"] = true; root["file"] = args[0]; retval.type = print; } } retval.msg = root; return retval; } CmdMan::CmdRet CmdMan::cmdClosekey(vector args) { CmdRet retval; Json::Value root; DEBUGPRINT(string(__PRETTY_FUNCTION__) + " begin"); root["command"] = "closekey"; if (!fileman.closeKey()) { root["accept"] = false; root["error"] = "couldnt close keyfile. ensure no put or get is running"; retval.type = error; } else { root["accept"] = true; retval.type = print; } retval.msg = root; return retval; } CmdMan::CmdRet CmdMan::cmdExit(vector args) { CmdRet retval; Json::Value root; DEBUGPRINT(string(__PRETTY_FUNCTION__) + " begin"); root["command"] = "exit"; if (currentState != connectionpossible) { // we are connected, disconnect first retval.nextcommand = "disconnect"; if (currentState == loginpossible) currentState = disconnecttoexitearly; else currentState = disconnecttoexit; retval.type = none; } else { retval.type = exit; } retval.msg = root; return retval; } /* 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"] = "error"; root["error"] = "Not enough arguments, login requires at least 2 arguments."; } else { if (currentState == loginpossible) { currentState = dologin; root["user"] = username = 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"] = "error"; root["error"] = "Not enough arguments, signup requires at least 2 arguments."; } else { if (currentState == loginpossible) { currentState = dosignup; root["user"] = username = 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; } CmdMan::CmdRet CmdMan::cmdQueue(vector args) { CmdRet retval; DEBUGPRINT(string(__PRETTY_FUNCTION__) + " begin"); Json::Value root; if (args.size() < 1) { retval.type = error; root["command"] = "error"; root["error"] = "Not enough arguments, queue requires at least 1 argument."; } else { root["command"] = "queue"; root["file"] = args[0]; retval.type = send; } retval.msg = root; return retval; } CmdMan::CmdRet CmdMan::cmdDequeue(vector args) { CmdRet retval; DEBUGPRINT(string(__PRETTY_FUNCTION__) + " begin"); Json::Value root; if (args.size() < 1) { retval.type = error; root["command"] = "error"; root["error"] = "Not enough arguments, dequeue requires at least 1 argument."; } else { root["command"] = "dequeue"; root["file"] = args[0]; retval.type = send; } retval.msg = root; return retval; } /* internal commands */ CmdMan::CmdRet CmdMan::cmdVersion(vector args) { CmdRet retval; DEBUGPRINT(string(__PRETTY_FUNCTION__) + " begin"); Json::Value root; if (currentState == versionpossible) { root["major"] = protocolMajorVersion; root["minor"] = protocolMinorVersion; retval.type = send; currentState = doversion; } else { retval.type = error; root["command"] = "error"; root["error"] = "Executing version command not possible. Type help to list available commands."; } retval.msg = root; return retval; } CmdMan::CmdRet CmdMan::cmdNotifications(vector args) { CmdRet retval; DEBUGPRINT(string(__PRETTY_FUNCTION__) + " begin"); Json::Value root; root["command"] = "notifications"; retval.type = send; retval.msg = root; return retval; } CmdMan::CmdRet CmdMan::handle(Json::Value root) { CmdRet retval; Json::Value output; DEBUGPRINT(string(__PRETTY_FUNCTION__) + " begin"); cmdmutex.lock(); if (currentState == doversion) root["command"] = "version"; else if (currentState == dosignup) root["command"] = "signup"; else if (currentState == 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; cmdmutex.unlock(); return retval; } retval = (this->*(handlemap[root["command"].asString()]))(root); cmdmutex.unlock(); return retval; } CmdMan::CmdRet CmdMan::handleStatus(Json::Value root) { CmdRet retval; Json::Value output; DEBUGPRINT(string(__PRETTY_FUNCTION__) + " begin"); retval.type = print; output["command"] = "status"; output["response"] = username + "@" + ip + ":" + std::to_string(port) + " - Status: " + root["response"].asString(); retval.msg = output; return retval; } CmdMan::CmdRet CmdMan::handleExtendedstatus(Json::Value root) { CmdRet retval; DEBUGPRINT(string(__PRETTY_FUNCTION__) + " begin"); if (!root["accept"].asBool()) { retval.type = error; } else { retval.type = print; } retval.msg = root; return retval; } CmdMan::CmdRet CmdMan::handleClose(Json::Value root) { CmdRet retval; Json::Value output; DEBUGPRINT(string(__PRETTY_FUNCTION__) + " begin"); output["command"] = "disconnect"; output["accept"] = true; retval.type = close | print; retval.msg = output; if (currentState == disconnecttoexit) { retval.nextcommand = "exit"; } currentState = connectionpossible; 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 (!fileman.isPutting()) { retval.type = error; output["error"] = "Server responds to put message which was never sent."; } 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["cancel"] = true; if (root["cancel"].asBool()) { retval.type = error; output["error"] = "Server reports: " + root["error"].asString(); fileman.cancelPut(); } else if (!fileman.isPutting()) { retval.type = error; output["error"] = "Server responds to put message which was never sent."; } else 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["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; 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(); fileman.cancelGet(); } else if (!fileman.isGetting()) { retval.type = error; output["error"] = "Server responds to get message which was never sent."; } 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 { 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["cancel"] = true; if (root["cancel"].asBool()) { retval.type = error; output["error"] = "Server reports: " + root["error"].asString(); fileman.cancelGet(); } else if (!fileman.isGetting()) { retval.type = error; output["error"] = "Server responds to get message which was never sent."; } else 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["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 (!root["remaining"].asInt()) { // everything received retval.type = print; 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 if (root["items"].asInt() == 0) { retval.type = print; output["accept"] = false; output["error"] = "There are no files stored on the server."; fileman.closeList(); } else if (!fileman.isListingSimple()) { retval.type = error; output["accept"] = false; output["error"] = "Server responds to list message which was never sent."; } 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; if (root["cancel"].asBool()) { retval.type = error; output["error"] = "Server reports: " + root["error"].asString(); fileman.cancelList(); } else if (!fileman.isListingSimple()) { retval.type = error; output["error"] = "Server responds to list message which was never sent."; } else if (root["remaining"].asInt() != fileman.getListRemainingChunks()) { // the passed number of recieved chunks should equal the number of sent chunks 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 { output["accept"] = true; for (Json::Value i : root["names"]) toadd.push_back(i); fileman.putListData(toadd); // loaded successfully if (root["remaining"] <= 0) { // everything sent retval.type = print; for (Json::Value s : fileman.getListData()) arr.append(s.asString()); output["names"] = arr; fileman.closeList(); } else { retval.type = send; retval.nextcommand = "listdata"; } } retval.msg = output; return retval; } CmdMan::CmdRet CmdMan::handleExtendedlist(Json::Value root) { CmdRet retval; Json::Value output, files; // LOCALOUTPUT DEBUGPRINT(string(__PRETTY_FUNCTION__) + " begin"); output["command"] = "extendedlist"; output["files"] = files; if (!root["accept"].asBool()) { retval.type = error; output["accept"] = false; output["error"] = "Server reports: " + root["error"].asString(); fileman.cancelList(); } else if (root["items"].asInt() == 0) { retval.type = print; output["accept"] = false; output["error"] = "There are no files stored on the server."; fileman.closeList(); } else if (!fileman.isListingExtended()) { retval.type = error; output["accept"] = false; output["error"] = "Server responds to list message which was never sent."; } else { fileman.setListChunks(root["chunks"].asInt()); retval.type = send; output["accept"] = true; retval.nextcommand = "extendedlistdata"; } retval.msg = output; return retval; } CmdMan::CmdRet CmdMan::handleExtendedlistdata(Json::Value root) { CmdRet retval; Json::Value output, arr, files; DEBUGPRINT(string(__PRETTY_FUNCTION__) + " begin"); vector toadd; output["command"] = "extendedlist"; output["files"] = files; output["accept"] = false; if (root["cancel"].asBool()) { retval.type = error; output["error"] = "Server reports: " + root["error"].asString(); fileman.cancelList(); } else if (!fileman.isListingExtended()) { retval.type = error; output["error"] = "Server responds to list message which was never sent."; } else if (root["remaining"].asInt() != fileman.getListRemainingChunks()) { // the passed number of recieved chunks should equal the number of sent chunks 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 { output["accept"] = true; for (Json::Value i : root["files"]) toadd.push_back(i); fileman.putListData(toadd); // loaded successfully if (root["remaining"] <= 0) { // everything sent retval.type = print; for (Json::Value s : fileman.getListData()) arr.append(s); output["files"] = arr; fileman.closeList(); } else { retval.type = send; retval.nextcommand = "extendedlistdata"; } } 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"] = std::to_string(root["major"].asInt()) + "." + std::to_string(root["minor"].asInt()); output["clientversion"] = std::to_string(protocolMajorVersion) + "." + std::to_string(protocolMinorVersion); if (!root["accept"].asBool()) { retval.type = error | close; output["accept"] = false; currentState = connectionpossible; } else { retval.type = print; output["accept"] = true; currentState = loginpossible; } 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 | close; output["error"] = root["error"].asString(); output["accept"] = false; currentState = connectionpossible; } else { retval.type = print; output["error"] = ""; output["accept"] = true; currentState = normal; } 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; currentState = loginpossible; } else { retval.type = print; output["error"] = ""; output["accept"] = true; currentState = normal; } retval.msg = output; return retval; } CmdMan::CmdRet CmdMan::handleHead(Json::Value root) { CmdRet retval; DEBUGPRINT(string(__PRETTY_FUNCTION__) + " begin"); if (!root["accept"].asBool()) { Json::Value output; output["command"] = "head"; output["file"] = root["file"]; output["error"] = "Server reports: " + root["error"].asString(); output["accept"] = false; retval.type = error; retval.msg = output; } else { retval.type = print; retval.msg = root; } return retval; } CmdMan::CmdRet CmdMan::handleDeletefile(Json::Value root) { CmdRet retval; DEBUGPRINT(string(__PRETTY_FUNCTION__) + " begin"); if (!root["accept"].asBool()) { Json::Value output; output["command"] = "deletefile"; output["file"] = root["file"]; output["error"] = "Server reports: " + root["error"].asString(); output["accept"] = false; retval.type = error; retval.msg = output; } else { retval.type = print; retval.msg = root; } return retval; } CmdMan::CmdRet CmdMan::handleDeleteme(Json::Value root) { CmdRet retval; DEBUGPRINT(string(__PRETTY_FUNCTION__) + " begin"); if (!root["accept"].asBool()) { retval.type = error; } else { retval.type = close | print; currentState = connectionpossible; } retval.msg = root; return retval; } CmdMan::CmdRet CmdMan::handleQueue(Json::Value root) { CmdRet retval; DEBUGPRINT(string(__PRETTY_FUNCTION__) + " begin"); if (root["accept"].asBool()) { retval.type = print; } else { retval.type = error; } retval.msg = root; return retval; } CmdMan::CmdRet CmdMan::handleDequeue(Json::Value root) { CmdRet retval; DEBUGPRINT(string(__PRETTY_FUNCTION__) + " begin"); if (root["accept"].asBool()) { retval.type = print; } else { retval.type = error; } retval.msg = root; return retval; } CmdMan::CmdRet CmdMan::handleNotifications(Json::Value root) { CmdRet retval; DEBUGPRINT(string(__PRETTY_FUNCTION__) + " begin"); if (root["accept"].asBool()) { retval.type = print; } else { retval.type = error; } retval.msg = root; return retval; }