summaryrefslogtreecommitdiffhomepage
path: root/whiteboard.cpp
diff options
context:
space:
mode:
authorRoland Reichwein <mail@reichwein.it>2022-11-22 19:07:31 +0100
committerRoland Reichwein <mail@reichwein.it>2022-11-22 19:07:31 +0100
commit9487db69020bfa7b91d70ee62b97441ef6c9ece4 (patch)
treee4092abdd0243c5935146b7815edd5e1ff309c2d /whiteboard.cpp
parent2a4d96188afa83110b30931559732d4fd9bacab2 (diff)
Save data on file backend
Diffstat (limited to 'whiteboard.cpp')
-rw-r--r--whiteboard.cpp64
1 files changed, 59 insertions, 5 deletions
diff --git a/whiteboard.cpp b/whiteboard.cpp
index b6b3a8d..09674b5 100644
--- a/whiteboard.cpp
+++ b/whiteboard.cpp
@@ -9,6 +9,7 @@
#include <iostream>
#include <functional>
#include <filesystem>
+#include <random>
#include <regex>
#include <string>
#include <unordered_map>
@@ -26,18 +27,65 @@ namespace fs = std::filesystem;
namespace {
- uint32_t checksum32(const std::string& s) {
+ uint32_t checksum32(const std::string& s)
+ {
uint32_t result{0};
for (int i = 0; i < s.size(); i++) {
result = ((result >> 1) | ((result & 1) << 31)) ^ (s[i] & 0xFF);
}
return result & 0x7FFFFFFF;
}
+
+ std::string generate_id()
+ {
+ static std::random_device r;
+ static std::default_random_engine e1(r());
+ static std::uniform_int_distribution<int> uniform_dist(0, 15);
+
+ std::string result;
+ for (int i = 0; i < 6; i++) {
+ char c{static_cast<char>('0' + uniform_dist(e1))};
+ if (c > '9')
+ c = c - '9' + 'a';
+ result.push_back(c);
+ }
+ return result;
+ }
+
+ fs::path data_path;
+
+ void setFileById(const std::string& data, const std::string& id)
+ {
+ fs::path path{data_path / id};
+
+ // skip if it doesn't exists
+ if (data.empty() && !fs::exists(path))
+ return;
+
+ // clean up immediately, if appropriate
+ if (data.empty()) {
+ fs::remove(path);
+ return;
+ }
+
+ File::setFile(path, data);
+ }
+
+ std::string getFileById(const std::string& id)
+ {
+ fs::path path{data_path / id};
+
+ if (!fs::exists(path))
+ return {};
+
+ return File::getFile(path);
+ }
}
int main(void)
{
Config config;
+ data_path = config.getDataPath();
int result = FCGX_Init();
if (result != 0) { // error on init
@@ -58,8 +106,6 @@ int main(void)
return 1;
}
- std::string filedata {""}; // initial content
-
while (FCGX_Accept_r(&request) >= 0) {
try {
char* method = FCGX_GetParam("REQUEST_METHOD", request.envp);
@@ -81,13 +127,16 @@ int main(void)
pt::xml_parser::read_xml(ss, xml);
std::string command {xml.get<std::string>("request.command")};
- std::string id {xml.get<std::string>("request.id")};
if (command == "modify") {
+ std::string id {xml.get<std::string>("request.id")};
std::string data {xml.get<std::string>("request.data")};
- filedata = data;
+ setFileById(data, id);
FCGX_PutS("Content-Type: text/plain\r\n\r\n", request.out);
} else if (command == "getfile") {
+ std::string id {xml.get<std::string>("request.id")};
+
+ std::string filedata {getFileById(id)};
if (filedata.size() > 30000000)
throw std::runtime_error("File too big");
@@ -96,12 +145,14 @@ int main(void)
FCGX_FPrintF(request.out, "Content-Length: %d\r\n\r\n", filedata.size());
FCGX_PutStr(filedata.c_str(), filedata.size(), request.out);
} else if (command == "checkupdate") {
+ std::string id {xml.get<std::string>("request.id")};
std::string checksum_s {xml.get<std::string>("request.checksum")};
uint32_t checksum{static_cast<uint32_t>(stoul(checksum_s))};
//std::cout << "Checksum JS: " << checksum_s << std::endl;
//std::cout << "Checksum C++: " << checksum32(filedata) << std::endl;
+ std::string filedata {getFileById(id)};
if (checksum != checksum32(filedata)) {
//std::cout << "Sending change..." << std::endl;
FCGX_PutS("Content-Type: application/octet-stream\r\n", request.out);
@@ -112,6 +163,9 @@ int main(void)
FCGX_PutS("Content-Type: text/plain\r\n\r\n", request.out);
FCGX_PutS("No change.\r\n", request.out);
}
+ } else if (command == "newid") {
+ FCGX_PutS("Content-Type: text/plain\r\n\r\n", request.out);
+ FCGX_PutS(generate_id().c_str(), request.out);
} else {
throw std::runtime_error("Bad command: "s + command);
}