diff options
author | Roland Reichwein <mail@reichwein.it> | 2022-11-22 19:07:31 +0100 |
---|---|---|
committer | Roland Reichwein <mail@reichwein.it> | 2022-11-22 19:07:31 +0100 |
commit | 9487db69020bfa7b91d70ee62b97441ef6c9ece4 (patch) | |
tree | e4092abdd0243c5935146b7815edd5e1ff309c2d | |
parent | 2a4d96188afa83110b30931559732d4fd9bacab2 (diff) |
Save data on file backend
-rw-r--r-- | html/index.html | 3 | ||||
-rw-r--r-- | html/whiteboard.js | 72 | ||||
-rw-r--r-- | whiteboard.cpp | 64 |
3 files changed, 130 insertions, 9 deletions
diff --git a/html/index.html b/html/index.html index 64eae90..fdd56dc 100644 --- a/html/index.html +++ b/html/index.html @@ -14,6 +14,9 @@ <textarea rows="30" cols="80" id="board" name="board"></textarea> <br/> <br/> + <button class="button" onclick="on_new_page();">New page</button> + <br/> + <br/> Reichwein.IT Whiteboard by <a href="https://www.reichwein.it">https://www.reichwein.it</a><br/> </div> diff --git a/html/whiteboard.js b/html/whiteboard.js index 2b35180..9018f92 100644 --- a/html/whiteboard.js +++ b/html/whiteboard.js @@ -6,6 +6,12 @@ function init() { function init_board() { var xhr = new XMLHttpRequest(); + const searchParams = (new URL(document.location)).searchParams; + if (!searchParams.has('id')) { + redirect_to_new_page(); + return; + } + // run on data received back xhr.onreadystatechange = function() { if (this.readyState == 3) { @@ -47,7 +53,7 @@ function init_board() { requestElement.appendChild(commandElement); var idElement = xmlDocument.createElement("id"); - idElement.appendChild(document.createTextNode("id1")); + idElement.appendChild(document.createTextNode(get_id())); requestElement.appendChild(idElement); xhr.open("POST", "whiteboard.fcgi", true); @@ -58,7 +64,65 @@ function init_board() { //set_status("Please wait while server prepares " + filename + " ..."); } -function on_modify() { +function get_id() +{ + const searchParams = (new URL(document.location)).searchParams; + return searchParams.get('id'); +} + +function on_new_page() +{ + redirect_to_new_page(); +} + +function redirect_to_new_page() +{ + var xhr = new XMLHttpRequest(); + + // run on data received back + xhr.onreadystatechange = function() { + if (this.readyState == 3) { + //set_status("Please wait while downloading " + filename + " ..."); + return; + } + if (this.readyState != 4) { + return; + } + if (this.status != 200) { + //set_status("Server Error while retrieving " + filename + ", status: " + this.status + " " + this.statusText); + return; + } + + var id = this.responseText; + //alert("location=" + document.location.href); + var new_location = document.location.href; + var pos = new_location.search("\\?"); + if (pos >= 0) + new_location = new_location.substring(0, pos); + new_location += '?id=' + id; + + window.location.href = new_location; + //set_status(""); // OK + } + + var parser = new DOMParser(); + var xmlDocument = parser.parseFromString("<request></request>", "text/xml"); + + var requestElement = xmlDocument.getElementsByTagName("request")[0]; + + var commandElement = xmlDocument.createElement("command"); + commandElement.appendChild(document.createTextNode("newid")); + requestElement.appendChild(commandElement); + + xhr.open("POST", "whiteboard.fcgi", true); + xhr.setRequestHeader("Content-type", "text/xml"); + xhr.send(xmlDocument); + + //set_status("Please wait while server prepares " + filename + " ..."); +} + +function on_modify() +{ var xhr = new XMLHttpRequest(); // run on data received back @@ -88,7 +152,7 @@ function on_modify() { requestElement.appendChild(commandElement); var idElement = xmlDocument.createElement("id"); - idElement.appendChild(document.createTextNode("id1")); + idElement.appendChild(document.createTextNode(get_id())); requestElement.appendChild(idElement); var dataElement = xmlDocument.createElement("data"); @@ -155,7 +219,7 @@ function checkupdate() { requestElement.appendChild(commandElement); var idElement = xmlDocument.createElement("id"); - idElement.appendChild(document.createTextNode("id1")); + idElement.appendChild(document.createTextNode(get_id())); requestElement.appendChild(idElement); var checksumElement = xmlDocument.createElement("checksum"); 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); } |