summaryrefslogtreecommitdiffhomepage
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
parent2a4d96188afa83110b30931559732d4fd9bacab2 (diff)
Save data on file backend
-rw-r--r--html/index.html3
-rw-r--r--html/whiteboard.js72
-rw-r--r--whiteboard.cpp64
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);
}