userioman.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. #include "../include/userioman.h"
  2. #include <iostream>
  3. #include <readline/readline.h>
  4. #include <vector>
  5. UserIoMan::UserIoMan(bool usessl, bool beverbose) : IoMan(usessl) {
  6. /* setup json stuff */
  7. Json::CharReaderBuilder rbuilder;
  8. wbuilder.settings_["indentation"] = "";
  9. reader = rbuilder.newCharReader();
  10. verbose = beverbose;
  11. /* initialize print command map */
  12. printmap["error"] = &UserIoMan::printError;
  13. printmap["connect"] = &UserIoMan::printConnect;
  14. printmap["help"] = &UserIoMan::printHelp;
  15. printmap["extendedstatus"] = &UserIoMan::printExtendedstatus;
  16. printmap["status"] = &UserIoMan::printStatus;
  17. printmap["disconnect"] = &UserIoMan::printDisconnect;
  18. printmap["put"] = &UserIoMan::printPut;
  19. printmap["get"] = &UserIoMan::printGet;
  20. printmap["list"] = &UserIoMan::printList;
  21. printmap["version"] = &UserIoMan::printVersion;
  22. printmap["login"] = &UserIoMan::printLogin;
  23. printmap["signup"] = &UserIoMan::printSignup;
  24. printmap["putdata"] = &UserIoMan::printPutdata;
  25. printmap["getdata"] = &UserIoMan::printGetdata;
  26. printmap["head"] = &UserIoMan::printHead;
  27. printmap["deletefile"] = &UserIoMan::printDeletefile;
  28. printmap["deleteme"] = &UserIoMan::printDeleteme;
  29. printmap["queue"] = &UserIoMan::printQueue;
  30. printmap["dequeue"] = &UserIoMan::printDequeue;
  31. printmap["keyfile"] = &UserIoMan::printKeyfile;
  32. printmap["closekey"] = &UserIoMan::printClosekey;
  33. printmap["notifications"] = &UserIoMan::printNotifications;
  34. }
  35. UserIoMan::~UserIoMan() { delete reader; }
  36. void UserIoMan::printMessage(std::string msg, OutMsgType type) {
  37. Json::Value root;
  38. msgmutex.lock();
  39. char *savedline = rl_copy_text(0, rl_end);
  40. int savedpoint = rl_point;
  41. rl_set_prompt("");
  42. rl_replace_line("", 0);
  43. rl_redisplay();
  44. switch (type) {
  45. case normal:
  46. case error: {
  47. // this should never happen outside of development
  48. if (!reader->parse(msg.c_str(), msg.c_str() + msg.size(), &root, &jsonerror)) {
  49. printMessage(string(__PRETTY_FUNCTION__) + " couldnt parse json data: " + jsonerror, debug);
  50. } else {
  51. printJson(root);
  52. }
  53. break;
  54. }
  55. case debug: {
  56. if (verbose)
  57. std::cerr << msg << std::endl;
  58. break;
  59. }
  60. }
  61. rl_set_prompt(getCmdPrompt().c_str());
  62. rl_replace_line(savedline, 0);
  63. rl_point = savedpoint;
  64. rl_redisplay();
  65. free(savedline);
  66. msgmutex.unlock();
  67. }
  68. void UserIoMan::printWelcomeMessage() {
  69. std::cout << "please login by entering \"login <username> <password>\" \nor "
  70. "sign up and log in with \"signup <username> <password>\""
  71. << std::endl;
  72. }
  73. std::string UserIoMan::getCmdPrompt() { return "ccats> "; }
  74. void UserIoMan::printJson(Json::Value root) {
  75. map<string, void (UserIoMan::*)(Json::Value)>::iterator it = printmap.find(root["command"].asString());
  76. if (it == printmap.end()) {
  77. // this should never happen outside of development
  78. printMessage(string(__PRETTY_FUNCTION__) + " unknown command \"" + root["command"].asString() + "\".\nensure code is implemented.", debug);
  79. return;
  80. }
  81. (this->*(printmap[root["command"].asString()]))(root);
  82. }
  83. void UserIoMan::printError(Json::Value root) { std::cout << "Error: " << root["error"].asString() << std::endl; }
  84. void UserIoMan::printConnect(Json::Value root) {
  85. if (!root["accept"].asBool()) {
  86. std::cout << "Couldnt connect to " << root["address"].asString() << ":" << root["port"].asUInt() << std::endl
  87. << "Reason: " << root["error"].asString() << std::endl;
  88. }
  89. }
  90. void UserIoMan::printHelp(Json::Value root) {
  91. std::cout << "Available commands are: " << std::endl;
  92. for (Json::Value i : root["names"])
  93. std::cout << i.asString() << std::endl;
  94. }
  95. void UserIoMan::printStatus(Json::Value root) { std::cout << "Server reports status: " << root["response"].asString() << std::endl; }
  96. void UserIoMan::printExtendedstatus(Json::Value root) {
  97. if (!root["accept"].asBool()) {
  98. std::cout << "Listing transfers failed. Server reports: " << root["error"].asString() << std::endl;
  99. } else {
  100. if (!root["transfersclientserver"].empty()) {
  101. std::cout << std::endl << "Transfers between clients and server:" << std::endl;
  102. /*
  103. * EXAMPLE:
  104. * type progress file
  105. * download 99% foobar.txt
  106. * upload 1% baz.html
  107. */
  108. std::cout << "type progress file" << std::endl;
  109. for (Json::Value val : root["transfersclientserver"]) {
  110. std::string type = val["upload"].asBool() ? "upload" : "download";
  111. std::string progress = std::to_string(val["progress"].asInt());
  112. std::string file = val["file"].asString();
  113. char output[21];
  114. std::snprintf(output, 21, "%-8s %7.7s%% ", type.c_str(), progress.c_str());
  115. std::cout << output << file << std::endl;
  116. }
  117. }
  118. if (!root["transfersserverserver"].empty()) {
  119. std::cout << std::endl << "Transfers between different servers:" << std::endl;
  120. /*
  121. * EXAMPLE:
  122. * type progress method bytes/sec file
  123. * download 99% method0000001 9000.01 foobar.txt
  124. * queued 1% urgent field 42.00 baz.html
  125. *
  126. * Too long method strings get truncated, unexpectedly high speeds are shown (with less pretty format), e.g.:
  127. *
  128. * download 95% too long stri 340282346638528859811704183484516925440.00 filename.zip
  129. */
  130. std::cout << "type progress method bytes/sec file" << std::endl;
  131. for (Json::Value val : root["transfersserverserver"]) {
  132. std::string type = val["type"].asString();
  133. std::string progress = std::to_string(val["progress"].asInt());
  134. std::string method = val["method"].asString();
  135. float speed = val["speed"].asFloat();
  136. std::string file = val["file"].asString();
  137. // size of 80 is just enough for maximum possible float value to fit as string
  138. char output[80];
  139. std::snprintf(output, 80, "%-8s %7.7s%% %-13.13s %15.2f ", type.c_str(), progress.c_str(), method.c_str(), speed);
  140. std::cout << output << file << std::endl;
  141. }
  142. }
  143. if (root["transfersclientserver"].empty() && root["transfersserverserver"].empty()) {
  144. std::cout << "No transfers running." << std::endl;
  145. } else {
  146. std::cout << std::endl;
  147. }
  148. }
  149. }
  150. void UserIoMan::printDisconnect(Json::Value root) {
  151. if (!root["accept"].asBool()) {
  152. std::cout << "Disconnect failed." << std::endl;
  153. } else {
  154. std::cout << "Disconnect successful." << std::endl;
  155. }
  156. }
  157. void UserIoMan::printPut(Json::Value root) {
  158. if (!root["accept"].asBool()) {
  159. if (root.isMember("file")) {
  160. std::cout << "Upload request for file " << root["file"].asString() << " failed: " << root["error"].asString() << std::endl;
  161. } else {
  162. std::cout << "Upload request failed: " << root["error"].asString() << std::endl;
  163. }
  164. } else
  165. std::cout << "Begin uploading file " << root["file"].asString() << std::endl;
  166. }
  167. void UserIoMan::printGet(Json::Value root) {
  168. if (!root["accept"].asBool()) {
  169. if (root.isMember("file")) {
  170. std::cout << "Download request for file " << root["file"].asString() << " failed: " << root["error"].asString() << std::endl;
  171. } else {
  172. std::cout << "Download request failed: " << root["error"].asString() << std::endl;
  173. }
  174. } else
  175. std::cout << "Begin downloading file " << root["file"].asString() << std::endl;
  176. }
  177. void UserIoMan::printList(Json::Value root) {
  178. if (!root["accept"].asBool()) {
  179. std::cout << "Listing files failed: " << root["error"].asString() << std::endl;
  180. } else {
  181. std::cout << "Listing files stored on server: " << std::endl;
  182. for (Json::Value i : root["names"])
  183. std::cout << i.asString() << std::endl;
  184. std::cout << "End of list." << std::endl;
  185. }
  186. }
  187. void UserIoMan::printVersion(Json::Value root) {
  188. if (!root["accept"].asBool()) {
  189. std::cout << "Version check failed. Server reports " << root["serverversion"].asString() << " but client is " << root["clientversion"].asString()
  190. << std::endl;
  191. } else
  192. std::cout << "Version check ok." << std::endl;
  193. }
  194. void UserIoMan::printLogin(Json::Value root) {
  195. if (!root["accept"].asBool()) {
  196. std::cout << "Login failed: " << root["error"].asString() << std::endl;
  197. } else
  198. std::cout << "Login ok." << std::endl;
  199. }
  200. void UserIoMan::printSignup(Json::Value root) {
  201. if (!root["accept"].asBool()) {
  202. std::cout << "Signup failed: " << root["error"].asString() << std::endl;
  203. } else
  204. std::cout << "Signup ok. You are now logged in." << std::endl;
  205. }
  206. void UserIoMan::printDeleteme(Json::Value root) {
  207. if (!root["accept"].asBool()) {
  208. std::cout << "User deletion failed: " << root["error"].asString() << std::endl;
  209. } else
  210. std::cout << "User deletion ok. You are now disconnected from the server." << std::endl;
  211. }
  212. void UserIoMan::printPutdata(Json::Value root) {}
  213. void UserIoMan::printGetdata(Json::Value root) {}
  214. void UserIoMan::printListdata(Json::Value root) {}
  215. void UserIoMan::printHead(Json::Value root) {
  216. if (!root["accept"].asBool())
  217. std::cout << "Request of the first four bytes failed. " << root["error"].asString() << std::endl;
  218. else
  219. std::cout << "First four bytes of file " << root["file"].asString() << " are: " << root["data"].asString() << std::endl;
  220. }
  221. void UserIoMan::printDeletefile(Json::Value root) {
  222. if (!root["accept"].asBool())
  223. std::cout << "Deletion of file " << root["file"] << " failed. " << root["error"].asString() << std::endl;
  224. else
  225. std::cout << "File " << root["file"] << " deleted succesfully" << std::endl;
  226. }
  227. void UserIoMan::printKeyfile(Json::Value root) {
  228. if (!root["accept"].asBool())
  229. std::cout << "Couldnt select keyfile " << root["file"].asString() << ": " << root["error"].asString() << std::endl;
  230. else
  231. std::cout << "Using keyfile " << root["file"].asString() << std::endl;
  232. }
  233. void UserIoMan::printClosekey(Json::Value root) {
  234. if (!root["accept"].asBool())
  235. std::cout << "Failed to close key: " << root["error"].asString() << std::endl;
  236. else
  237. std::cout << "Key closed." << std::endl;
  238. }
  239. void UserIoMan::printQueue(Json::Value root) {
  240. if (!root["accept"].asBool())
  241. std::cout << "Queueing of file " << root["file"] << " failed. " << root["error"].asString() << std::endl;
  242. else
  243. std::cout << "File " << root["file"] << " queued succesfully" << std::endl;
  244. }
  245. void UserIoMan::printDequeue(Json::Value root) {
  246. if (!root["accept"].asBool())
  247. std::cout << "Dequeueing of file " << root["file"] << " failed. " << root["error"].asString() << std::endl;
  248. else
  249. std::cout << "File " << root["file"] << " dequeued succesfully" << std::endl;
  250. }
  251. void UserIoMan::printNotifications(Json::Value root) {
  252. if (!root["accept"].asBool()) {
  253. std::cout << "Failed to get notifications: " << root["error"].asString() << std::endl;
  254. } else {
  255. std::cout << "New notifications:" << std::endl;
  256. for (Json::Value i : root["messages"])
  257. std::cout << "\033[94m" << i.asString() << std::endl;
  258. std::cout << "\033[0m " << std::endl;
  259. }
  260. }