diff --git a/src/kamokan_impl/pastie_response.cpp b/src/kamokan_impl/pastie_response.cpp index 7219a21..2a423f2 100644 --- a/src/kamokan_impl/pastie_response.cpp +++ b/src/kamokan_impl/pastie_response.cpp @@ -63,28 +63,6 @@ namespace kamokan { }) ); } - - bool is_valid_token (const boost::string_view& parToken, uint32_t parMaxLen) { - if (parToken.empty()) - return false; - if (parMaxLen > 0 and parToken.size() > parMaxLen) - return false; - - auto it_mark = std::find(parToken.begin(), parToken.end(), '?'); - if (parToken.begin() == it_mark) - return false; - for (auto it_ch = parToken.begin(); it_ch != it_mark; ++it_ch) { - if (*it_ch < 'a' or *it_ch > 'z') { - spdlog::get("statuslog")->info( - "Token's byte {} is invalid; value={}", - it_ch - parToken.begin(), - static_cast(*it_ch) - ); - return false; - } - } - return true; - } } //unnamed namespace PastieResponse::PastieResponse ( @@ -132,16 +110,13 @@ namespace kamokan { void PastieResponse::on_mustache_prepare (mstch::map& parContext) { boost::string_view token = cgi::drop_arguments(cgi_env().request_uri_relative()); - Storage::RetrievedPastie pastie_info = this->storage().retrieve_pastie(token); + Storage::RetrievedPastie pastie_info = + storage().retrieve_pastie(token, settings().as("max_token_length")); - if (not is_valid_token(token, settings().as("max_token_length"))) { - m_token_invalid = true; + m_token_invalid = not pastie_info.valid_token; + m_pastie_not_found = not pastie_info.pastie; + if (m_token_invalid or m_pastie_not_found) return; - } - if (not pastie_info.pastie) { - m_pastie_not_found = true; - return; - } srchilite::SourceHighlight highlighter; highlighter.setDataDir(settings().as("langmap_dir")); diff --git a/src/kamokan_impl/storage.cpp b/src/kamokan_impl/storage.cpp index 07e6655..de0325a 100644 --- a/src/kamokan_impl/storage.cpp +++ b/src/kamokan_impl/storage.cpp @@ -56,8 +56,37 @@ namespace kamokan { Storage::SubmissionResult make_submission_result (tawashi::ErrorReasons parError) { return Storage::SubmissionResult { std::string(), boost::make_optional(parError) }; } + + bool is_valid_token (const boost::string_view& parToken, uint32_t parMaxLen) { + if (parToken.empty()) + return false; + if (parMaxLen > 0 and parToken.size() > parMaxLen) + return false; + + auto it_mark = std::find(parToken.begin(), parToken.end(), '?'); + if (parToken.begin() == it_mark) + return false; + for (auto it_ch = parToken.begin(); it_ch != it_mark; ++it_ch) { + if (*it_ch < 'a' or *it_ch > 'z') { + spdlog::get("statuslog")->info( + "Token's byte {} is invalid; value={}", + it_ch - parToken.begin(), + static_cast(*it_ch) + ); + return false; + } + } + return true; + } } //unnamed namespace + Storage::RetrievedPastie::RetrievedPastie() : + pastie(), + self_destructed(false), + valid_token(false) + { + } + Storage::Storage (const Kakoune::SafePtr& parSettings) : m_redis(nullptr), m_settings(parSettings) @@ -137,11 +166,15 @@ namespace kamokan { return make_submission_result(ErrorReasons::PastieNotSaved); } - auto Storage::retrieve_pastie (const boost::string_view& parToken) const -> RetrievedPastie { + auto Storage::retrieve_pastie (const boost::string_view& parToken, uint32_t parMaxTokenLen) const -> RetrievedPastie { using opt_string = redis::IncRedis::opt_string; using opt_string_list = redis::IncRedis::opt_string_list; RetrievedPastie retval; + retval.valid_token = is_valid_token(parToken, parMaxTokenLen); + if (not retval.valid_token) + return retval; + opt_string_list pastie_reply = m_redis->hmget(parToken, "pastie", "selfdes"); retval.pastie = (pastie_reply and not pastie_reply->empty() ? (*pastie_reply)[0] : opt_string()); opt_string selfdes = (pastie_reply and not pastie_reply->size() > 1 ? (*pastie_reply)[1] : opt_string()); diff --git a/src/kamokan_impl/storage.hpp b/src/kamokan_impl/storage.hpp index ee52749..4d6594d 100644 --- a/src/kamokan_impl/storage.hpp +++ b/src/kamokan_impl/storage.hpp @@ -24,6 +24,7 @@ #include #include #include +#include namespace redis { class IncRedis; @@ -39,8 +40,13 @@ namespace kamokan { boost::optional error; }; struct RetrievedPastie { + RetrievedPastie(); + RetrievedPastie (boost::optional&& parPastie, bool parSelfDestructed, bool parValidToken); + ~RetrievedPastie() = default; + boost::optional pastie; bool self_destructed; + bool valid_token; }; explicit Storage (const Kakoune::SafePtr& parSettings); @@ -57,7 +63,7 @@ namespace kamokan { const std::string& parRemoteIP ) const; - kamokan_virtual_testing RetrievedPastie retrieve_pastie (const boost::string_view& parToken) const; + kamokan_virtual_testing RetrievedPastie retrieve_pastie (const boost::string_view& parToken, uint32_t parMaxTokenLen) const; #if defined(KAMOKAN_WITH_TESTING) const SettingsBag& settings() const; @@ -67,4 +73,15 @@ namespace kamokan { std::unique_ptr m_redis; Kakoune::SafePtr m_settings; }; + + inline Storage::RetrievedPastie::RetrievedPastie ( + boost::optional&& parPastie, + bool parSelfDestructed, + bool parValidToken + ) : + pastie(std::move(parPastie)), + self_destructed(parSelfDestructed), + valid_token(parValidToken) + { + } } //namespace kamokan diff --git a/test/simulation/fake_storage.cpp b/test/simulation/fake_storage.cpp index 49eac66..2553e15 100644 --- a/test/simulation/fake_storage.cpp +++ b/test/simulation/fake_storage.cpp @@ -62,7 +62,7 @@ namespace kamokan { return submission_res; } - Storage::RetrievedPastie FakeStorage::retrieve_pastie (const boost::string_view& parToken) const { + Storage::RetrievedPastie FakeStorage::retrieve_pastie (const boost::string_view& parToken, uint32_t parMaxTokenLen) const { auto it_found = std::find_if( m_submitted_pasties.begin(), m_submitted_pasties.end(), @@ -70,10 +70,12 @@ namespace kamokan { return pastie.token == parToken; } ); - if (m_submitted_pasties.end() == it_found) - return RetrievedPastie {boost::optional(), false}; + if (parToken.size() > static_cast(parMaxTokenLen)) + return RetrievedPastie (boost::optional(), false, false); + else if (m_submitted_pasties.end() == it_found) + return RetrievedPastie (boost::optional(), false, true); else - return RetrievedPastie {boost::make_optional(it_found->text), it_found->self_destruct}; + return RetrievedPastie (boost::make_optional(it_found->text), it_found->self_destruct, true); } const std::vector& FakeStorage::submitted_pasties() const { diff --git a/test/simulation/fake_storage.hpp b/test/simulation/fake_storage.hpp index a7a8f9a..c038dbe 100644 --- a/test/simulation/fake_storage.hpp +++ b/test/simulation/fake_storage.hpp @@ -52,7 +52,7 @@ namespace kamokan { const std::string& parRemoteIP ) const override; - kamokan_virtual_testing Storage::RetrievedPastie retrieve_pastie (const boost::string_view& parToken) const override; + kamokan_virtual_testing Storage::RetrievedPastie retrieve_pastie (const boost::string_view& parToken, uint32_t parMaxTokenLen) const override; const std::vector& submitted_pasties() const;