From 004db5e7e4e9ab6ac5b4730873c6b8f58da92930 Mon Sep 17 00:00:00 2001 From: Roland Reichwein Date: Sun, 22 Jan 2023 12:02:16 +0100 Subject: Storage bugfix, whiteboard xml implementation --- storage.cpp | 2 +- tests/test-storage.cpp | 17 +++++++++++------ tests/test-whiteboard.cpp | 8 ++++++-- whiteboard.cpp | 39 ++++++++++++++++++++++++++++----------- 4 files changed, 46 insertions(+), 20 deletions(-) diff --git a/storage.cpp b/storage.cpp index e7e9248..a7d5a36 100644 --- a/storage.cpp +++ b/storage.cpp @@ -186,7 +186,7 @@ std::string Storage::generate_id() for (int i = 0; i < 6; i++) { char c{static_cast('0' + uniform_dist(e1))}; if (c > '9') - c = c - '9' + 'a'; + c = c - '9' - 1 + 'a'; result.push_back(c); } diff --git a/tests/test-storage.cpp b/tests/test-storage.cpp index ce19c3e..d8259e1 100644 --- a/tests/test-storage.cpp +++ b/tests/test-storage.cpp @@ -210,15 +210,20 @@ TEST_F(StorageTest, revision_increment) TEST_F(StorageTest, generate_id) { Storage storage(*m_config); - std::string a{storage.generate_id()}; - std::string b{storage.generate_id()}; + for (int i = 0; i < 100; i++) { + std::string a{storage.generate_id()}; + std::string b{storage.generate_id()}; - EXPECT_NE(a, b); - EXPECT_NE(a, ""); - EXPECT_NE(b, ""); + EXPECT_NE(a, b); + EXPECT_NE(a, ""); + EXPECT_NE(b, ""); - EXPECT_GE(a.size(), 6); + EXPECT_GE(a.size(), 6); + for (char c: a + b) { + EXPECT_TRUE((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z')); + } + } } TEST_F(StorageTest, checksum32) diff --git a/tests/test-whiteboard.cpp b/tests/test-whiteboard.cpp index 4ed10ae..a472d64 100644 --- a/tests/test-whiteboard.cpp +++ b/tests/test-whiteboard.cpp @@ -234,11 +234,15 @@ TEST_F(WhiteboardTest, generate_id) wc.write("newid"); std::string result0 {wc.read()}; - ASSERT_EQ(result0.size(), 6); + ASSERT_TRUE(boost::algorithm::starts_with(result0, "newid")); + ASSERT_TRUE(boost::algorithm::ends_with(result0, "")); + ASSERT_EQ(result0.size(), 58); wc.write("newid"); std::string result1 {wc.read()}; - ASSERT_EQ(result1.size(), 6); + ASSERT_TRUE(boost::algorithm::starts_with(result1, "newid")); + ASSERT_TRUE(boost::algorithm::ends_with(result1, "")); + ASSERT_EQ(result1.size(), 58); ASSERT_NE(result0, result1); } diff --git a/whiteboard.cpp b/whiteboard.cpp index be8bcb0..6782385 100644 --- a/whiteboard.cpp +++ b/whiteboard.cpp @@ -8,11 +8,13 @@ #include #include +#include #include #include #include #include #include +#include #include #include #include @@ -30,6 +32,8 @@ #include #include +#include + #include "libreichwein/file.h" #include "config.h" @@ -76,6 +80,19 @@ void Whiteboard::storage_cleanup() } } +std::string make_xml(const std::initializer_list>& key_values) +{ + pt::ptree xml; + for (const auto& i: key_values) { + xml.put(fmt::format("serverinfo.{}", i.first), i.second); + } + + std::ostringstream oss; + // write_xml_element instead of write_xml to omit header + pt::xml_parser::write_xml_element(oss, {}, xml, -1, boost::property_tree::xml_writer_settings{}); + return oss.str(); +} + std::string Whiteboard::handle_request(const std::string& request) { try { @@ -93,7 +110,7 @@ std::string Whiteboard::handle_request(const std::string& request) std::string id {xml.get("request.id")}; std::string data {xml.get("request.data")}; m_storage->setDocument(id, data); - return {}; + return make_xml({{"type", "modify"}, {"revision", std::to_string(m_storage->getRevision(id)) }}); } else if (command == "getfile") { std::string id {xml.get("request.id")}; @@ -102,20 +119,19 @@ std::string Whiteboard::handle_request(const std::string& request) if (filedata.size() > 30000000) throw std::runtime_error("File too big"); - return filedata; + return make_xml({{"type", "getfile"}, {"data", filedata}, {"revision", std::to_string(m_storage->getRevision(id)) }}); } else if (command == "checkupdate") { std::string id {xml.get("request.id")}; - std::string checksum_s {xml.get("request.checksum")}; - uint32_t checksum{static_cast(stoul(checksum_s))}; + int request_revision {xml.get("request.revision")}; - std::string filedata {m_storage->getDocument(id)}; - if (checksum != m_storage->checksum32(filedata)) { - return filedata; + int revision {m_storage->getRevision(id)}; + if (revision != request_revision) { + return make_xml({{"type", "update"}, {"data", m_storage->getDocument(id)}, {"revision", std::to_string(revision) }}); } else { - return {}; + return {}; // no reply } } else if (command == "newid") { - return m_storage->generate_id(); + return make_xml({{"type", "newid"}, {"id", m_storage->generate_id()}}); } else if (command == "qrcode") { std::string url{xml.get("request.url")}; @@ -124,7 +140,7 @@ std::string Whiteboard::handle_request(const std::string& request) std::string pngdata {QRCode::getQRCode(url)}; - return pngdata; + return make_xml({{"type", "qrcode"}, {"png", pngdata}}); } else { throw std::runtime_error("Bad command: "s + command); } @@ -167,7 +183,8 @@ void Whiteboard::do_session(boost::asio::ip::tcp::socket socket) data = handle_request(data); buffer.consume(buffer.size()); boost::beast::ostream(buffer) << data; - ws.write(buffer.data()); + if (buffer.data().size() > 0) + ws.write(buffer.data()); } } catch (boost::beast::system_error const& se) { // This indicates that the session was closed -- cgit v1.2.3