From 1bdc60b8d233723021562217daf54c84ff8758da Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 14 Apr 2025 21:03:10 +0100 Subject: [PATCH] fs: dedup functions, fix absolute paths in cfg fixes #2 closes #12 --- src/config/Config.cpp | 12 +++--------- src/core/Crypto.cpp | 21 ++++----------------- src/core/Handler.cpp | 19 ++++++------------- src/helpers/FsUtils.cpp | 30 ++++++++++++++++++++++++++++++ src/helpers/FsUtils.hpp | 11 +++++++++++ 5 files changed, 54 insertions(+), 39 deletions(-) create mode 100644 src/helpers/FsUtils.cpp create mode 100644 src/helpers/FsUtils.hpp diff --git a/src/config/Config.cpp b/src/config/Config.cpp index b843501..d9d170d 100644 --- a/src/config/Config.cpp +++ b/src/config/Config.cpp @@ -2,18 +2,12 @@ #include +#include "../helpers/FsUtils.hpp" #include "../GlobalState.hpp" -static std::string readFileAsText(const std::string& path) { - std::ifstream ifs(path); - auto res = std::string((std::istreambuf_iterator(ifs)), (std::istreambuf_iterator())); - if (res.back() == '\n') - res.pop_back(); - return res; -} - CConfig::CConfig() { - auto json = glz::read_jsonc(readFileAsText(g_pGlobalState->cwd + "/" + g_pGlobalState->configPath)); + auto json = glz::read_jsonc( + NFsUtils::readFileAsString(NFsUtils::isAbsolute(g_pGlobalState->configPath) ? g_pGlobalState->configPath : g_pGlobalState->cwd + "/" + g_pGlobalState->configPath).value()); if (!json.has_value()) throw std::runtime_error("No config / bad config format"); diff --git a/src/core/Crypto.cpp b/src/core/Crypto.cpp index 8f55e1d..eb1ea44 100644 --- a/src/core/Crypto.cpp +++ b/src/core/Crypto.cpp @@ -3,9 +3,9 @@ #include "../GlobalState.hpp" #include "../config/Config.hpp" #include "../debug/log.hpp" +#include "../helpers/FsUtils.hpp" #include -#include #include #include @@ -16,28 +16,15 @@ constexpr const char* KEY_FILENAME = "privateKey.key"; -static std::string dataDir() { - static const std::string dir = std::filesystem::canonical(g_pGlobalState->cwd + "/" + g_pConfig->m_config.data_dir).string(); - return dir; -} - -static std::string readFileAsText(const std::string& path) { - std::ifstream ifs(path); - auto res = std::string((std::istreambuf_iterator(ifs)), (std::istreambuf_iterator())); - if (res.back() == '\n') - res.pop_back(); - return res; -} - CCrypto::CCrypto() { - if (!std::filesystem::exists(dataDir() + "/" + KEY_FILENAME)) { + if (!std::filesystem::exists(NFsUtils::dataDir() + "/" + KEY_FILENAME)) { Debug::log(LOG, "No private key, generating one."); if (!genKey()) { Debug::log(CRIT, "Couldn't generate a key."); throw std::runtime_error("Keygen failed"); } } else { - auto f = fopen((dataDir() + "/" + KEY_FILENAME).c_str(), "r"); + auto f = fopen((NFsUtils::dataDir() + "/" + KEY_FILENAME).c_str(), "r"); PEM_read_PrivateKey(f, &m_evpPkey, nullptr, nullptr); fclose(f); } @@ -113,7 +100,7 @@ bool CCrypto::genKey() { return false; } - auto f = fopen((dataDir() + "/" + KEY_FILENAME).c_str(), "w"); + auto f = fopen((NFsUtils::dataDir() + "/" + KEY_FILENAME).c_str(), "w"); PEM_write_PrivateKey(f, m_evpPkey, nullptr, nullptr, 0, nullptr, nullptr); fclose(f); diff --git a/src/core/Handler.cpp b/src/core/Handler.cpp index 6937a2f..65a0ee1 100644 --- a/src/core/Handler.cpp +++ b/src/core/Handler.cpp @@ -11,8 +11,8 @@ #include "../debug/log.hpp" #include "../GlobalState.hpp" #include "../config/Config.hpp" +#include "../helpers/FsUtils.hpp" -#include #include #include #include @@ -26,13 +26,6 @@ constexpr const uint64_t TOKEN_MAX_AGE_MS = 1000 * 60 * 60; // 1hr constexpr const char* TOKEN_COOKIE_NAME = "checkpoint-token"; // -static std::string readFileAsText(const std::string& path) { - std::ifstream ifs(path); - auto res = std::string((std::istreambuf_iterator(ifs)), (std::istreambuf_iterator())); - if (res.back() == '\n') - res.pop_back(); - return res; -} static std::string generateNonce() { static std::random_device dev; @@ -186,8 +179,8 @@ void CServerHandler::onRequest(const Pistache::Http::Request& req, Pistache::Htt } if (isResourceCheckpoint(req.resource())) { - response.send(Pistache::Http::Code::Ok, - readFileAsText(g_pGlobalState->cwd + "/" + g_pConfig->m_config.html_dir + "/" + req.resource().substr(req.resource().find("checkpoint/") + 11))); + // no directory traversal is possible when resource is checkpoint + response.send(Pistache::Http::Code::Ok, NFsUtils::readFileAsString(NFsUtils::htmlPath(req.resource().substr(req.resource().find("checkpoint/") + 11))).value()); return; } @@ -282,10 +275,10 @@ void CServerHandler::challengeSubmitted(const Pistache::Http::Request& req, Pist } void CServerHandler::serveStop(const Pistache::Http::Request& req, Pistache::Http::ResponseWriter& response) { - static const auto PATH = std::filesystem::canonical(g_pGlobalState->cwd + "/" + g_pConfig->m_config.html_dir).string(); - static const auto PAGE_INDEX = readFileAsText(PATH + "/index.min.html"); + static const auto PAGE_INDEX = NFsUtils::readFileAsString(NFsUtils::htmlPath("/index.min.html")).value(); + static const auto PAGE_ROOT = PAGE_INDEX.substr(0, PAGE_INDEX.find_last_of("/") + 1); CTinylates page(PAGE_INDEX); - page.setTemplateRoot(PATH); + page.setTemplateRoot(PAGE_ROOT); const auto NONCE = generateNonce(); const auto DIFFICULTY = 4; diff --git a/src/helpers/FsUtils.cpp b/src/helpers/FsUtils.cpp new file mode 100644 index 0000000..42cd4dc --- /dev/null +++ b/src/helpers/FsUtils.cpp @@ -0,0 +1,30 @@ +#include "FsUtils.hpp" + +#include + +#include "../GlobalState.hpp" +#include "../config/Config.hpp" + +bool NFsUtils::isAbsolute(const std::string& sv) { + return sv.size() > 0 && (*sv.begin() == '/' || *sv.begin() == '~'); +} + +std::expected NFsUtils::readFileAsString(const std::string& path) { + std::ifstream ifs(path); + if (!ifs.good()) + return std::unexpected("No file"); + auto res = std::string((std::istreambuf_iterator(ifs)), (std::istreambuf_iterator())); + if (res.back() == '\n') + res.pop_back(); + return res; +} + +std::string NFsUtils::htmlPath(const std::string& resource) { + static const std::string htmlRoot = isAbsolute(g_pConfig->m_config.html_dir) ? g_pConfig->m_config.html_dir : g_pGlobalState->cwd + "/" + g_pConfig->m_config.html_dir; + return htmlRoot + "/" + resource; +} + +std::string NFsUtils::dataDir() { + static const std::string dataRoot = isAbsolute(g_pConfig->m_config.data_dir) ? g_pConfig->m_config.data_dir : g_pGlobalState->cwd + "/" + g_pConfig->m_config.data_dir; + return dataRoot; +} diff --git a/src/helpers/FsUtils.hpp b/src/helpers/FsUtils.hpp new file mode 100644 index 0000000..d391a60 --- /dev/null +++ b/src/helpers/FsUtils.hpp @@ -0,0 +1,11 @@ +#pragma once + +#include +#include + +namespace NFsUtils { + bool isAbsolute(const std::string& path); + std::expected readFileAsString(const std::string& path); + std::string htmlPath(const std::string& resource); + std::string dataDir(); +}; \ No newline at end of file