From b325af980ff76d859792c61017bcbd85e4e9baa9 Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Fri, 16 Jun 2017 19:00:49 +0100 Subject: [PATCH] Make a generic pastie retrieval base class. This is useful for implementing the EditResponse class. --- src/kamokan_impl/CMakeLists.txt | 1 + src/kamokan_impl/pastie_response.cpp | 66 ++-------- src/kamokan_impl/pastie_response.hpp | 10 +- .../pastie_retrieving_response.cpp | 113 ++++++++++++++++++ .../pastie_retrieving_response.hpp | 44 +++++++ 5 files changed, 169 insertions(+), 65 deletions(-) create mode 100644 src/kamokan_impl/pastie_retrieving_response.cpp create mode 100644 src/kamokan_impl/pastie_retrieving_response.hpp diff --git a/src/kamokan_impl/CMakeLists.txt b/src/kamokan_impl/CMakeLists.txt index e48f297..edc2c0b 100644 --- a/src/kamokan_impl/CMakeLists.txt +++ b/src/kamokan_impl/CMakeLists.txt @@ -20,6 +20,7 @@ add_library(${PROJECT_NAME} STATIC quick_submit_paste_response.cpp storage.cpp string_conv.cpp + pastie_retrieving_response.cpp ) target_include_directories(${PROJECT_NAME} diff --git a/src/kamokan_impl/pastie_response.cpp b/src/kamokan_impl/pastie_response.cpp index 2a423f2..f7dadc9 100644 --- a/src/kamokan_impl/pastie_response.cpp +++ b/src/kamokan_impl/pastie_response.cpp @@ -27,10 +27,6 @@ #include #include #include -#include -#include -#include -#include namespace kamokan { namespace { @@ -40,29 +36,6 @@ namespace kamokan { //TODO: make sure the file exists or throw or do something return parSettings.as("highlight_css"); } - - mstch::array pastie_to_numbered_lines (boost::string_view parPastie) { - using boost::string_view; - using string_view_iterator = string_view::const_iterator; - using boost::split_iterator; - using boost::token_finder; - using boost::adaptors::transformed; - using MatchRange = boost::iterator_range; - - int line_num = 1; - return boost::copy_range( - boost::make_iterator_range( - split_iterator(parPastie, token_finder([](char c){return '\n'==c;})), - split_iterator() - ) | - transformed([&line_num,parPastie](const MatchRange& r) { - return mstch::map { - {"number", line_num++}, - {"line", parPastie.substr(r.begin() - parPastie.begin(), r.size())} - }; - }) - ); - } } //unnamed namespace PastieResponse::PastieResponse ( @@ -70,23 +43,14 @@ namespace kamokan { std::ostream* parStreamOut, const Kakoune::SafePtr& parCgiEnv ) : - Response(parSettings, parStreamOut, parCgiEnv, true), + PastieRetrievingResponse(parSettings, parStreamOut, parCgiEnv), m_langmap_dir(parSettings->as("langmap_dir")), m_plain_text(false), - m_syntax_highlight(true), - m_pastie_not_found(false), - m_token_invalid(false) + m_syntax_highlight(true) { } - tawashi::HttpHeader PastieResponse::on_process() { - using tawashi::ErrorReasons; - - if (m_pastie_not_found) - return make_error_redirect(ErrorReasons::PastieNotFound); - if (m_token_invalid) - return make_error_redirect(ErrorReasons::InvalidToken); - + tawashi::HttpHeader PastieResponse::on_retrieving_process() { auto get = cgi_env().query_string_split(); const std::string& query_str(cgi_env().query_string()); if (get["m"] == "plain" or query_str.empty()) { @@ -108,16 +72,7 @@ namespace kamokan { return tawashi::make_header_type_html(); } - void PastieResponse::on_mustache_prepare (mstch::map& parContext) { - boost::string_view token = cgi::drop_arguments(cgi_env().request_uri_relative()); - Storage::RetrievedPastie pastie_info = - storage().retrieve_pastie(token, settings().as("max_token_length")); - - 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; - + std::string PastieResponse::on_pastie_prepare (std::string&& parPastie) { srchilite::SourceHighlight highlighter; highlighter.setDataDir(settings().as("langmap_dir")); highlighter.setGenerateEntireDoc(false); @@ -134,14 +89,13 @@ namespace kamokan { std::string processed_pastie; if (m_syntax_highlight) { - //TODO: redirect to "pastie not found" if !pastie - processed_pastie = std::move(*pastie_info.pastie); + processed_pastie = std::move(parPastie); } else { tawashi::Escapist houdini; std::ostringstream oss; oss << R"(
)";
-			oss << houdini.escape_html(*pastie_info.pastie) << "
\n"; + oss << houdini.escape_html(parPastie) << "\n"; processed_pastie = oss.str(); } @@ -152,13 +106,7 @@ namespace kamokan { processed_pastie = oss.str(); } - parContext["pastie"] = std::move(processed_pastie); - parContext["pastie_lines"] = pastie_to_numbered_lines( - boost::get(parContext["pastie"]) - ); - parContext["self_destructed"] = pastie_info.self_destructed; - parContext["pastie_token"] = token; - parContext["pastie_page"] = true; + return processed_pastie; } std::string PastieResponse::on_mustache_retrieve() { diff --git a/src/kamokan_impl/pastie_response.hpp b/src/kamokan_impl/pastie_response.hpp index d7d9715..7773fa4 100644 --- a/src/kamokan_impl/pastie_response.hpp +++ b/src/kamokan_impl/pastie_response.hpp @@ -17,12 +17,12 @@ #pragma once -#include "response.hpp" +#include "pastie_retrieving_response.hpp" #include #include namespace kamokan { - class PastieResponse : public Response { + class PastieResponse final : public PastieRetrievingResponse { public: PastieResponse ( const Kakoune::SafePtr& parSettings, @@ -34,15 +34,13 @@ namespace kamokan { virtual boost::string_view page_basename() const override { return boost::string_view("pastie"); } private: - virtual tawashi::HttpHeader on_process() override; - virtual void on_mustache_prepare (mstch::map& parContext) override; virtual std::string on_mustache_retrieve() override; + virtual std::string on_pastie_prepare (std::string&& parPastie) override; + virtual tawashi::HttpHeader on_retrieving_process() override; std::string m_lang_file; std::string m_langmap_dir; bool m_plain_text; bool m_syntax_highlight; - bool m_pastie_not_found; - bool m_token_invalid; }; } //namespace kamokan diff --git a/src/kamokan_impl/pastie_retrieving_response.cpp b/src/kamokan_impl/pastie_retrieving_response.cpp new file mode 100644 index 0000000..0a0bdf4 --- /dev/null +++ b/src/kamokan_impl/pastie_retrieving_response.cpp @@ -0,0 +1,113 @@ +/* Copyright 2017, Michele Santullo + * This file is part of "kamokan". + * + * "kamokan" is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * "kamokan" is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with "kamokan". If not, see . + */ + +#include "pastie_retrieving_response.hpp" +#include "cgi_env.hpp" +#include "settings_bag.hpp" +#include "error_reasons.hpp" +#include +#include +#include +#include +#include +#include +#include + +namespace kamokan { + namespace { + mstch::array pastie_to_numbered_lines (boost::string_view parPastie) { + using boost::string_view; + using string_view_iterator = string_view::const_iterator; + using boost::split_iterator; + using boost::token_finder; + using boost::adaptors::transformed; + using MatchRange = boost::iterator_range; + + int line_num = 1; + return boost::copy_range( + boost::make_iterator_range( + split_iterator(parPastie, token_finder([](char c){return '\n'==c;})), + split_iterator() + ) | + transformed([&line_num,parPastie](const MatchRange& r) { + return mstch::map { + {"number", line_num++}, + {"line", parPastie.substr(r.begin() - parPastie.begin(), r.size())} + }; + }) + ); + } + + boost::string_view get_search_token (const cgi::Env& parCgiEnv) { + return cgi::drop_arguments(parCgiEnv.request_uri_relative()); + } + } //unnamed namespace + + PastieRetrievingResponse::PastieRetrievingResponse ( + const Kakoune::SafePtr& parSettings, + std::ostream* parStreamOut, + const Kakoune::SafePtr& parCgiEnv + ) : + Response(parSettings, parStreamOut, parCgiEnv, true) + { + } + + tawashi::HttpHeader PastieRetrievingResponse::on_process() { + using tawashi::ErrorReasons; + + boost::string_view token = get_search_token(cgi_env()); + m_pastie_info = + storage().retrieve_pastie(token, settings().as("max_token_length")); + + if (this->token_invalid()) { + assert(this->pastie_not_found()); + return make_error_redirect(ErrorReasons::InvalidToken); + } + if (this->pastie_not_found()) + return make_error_redirect(ErrorReasons::PastieNotFound); + + assert(m_pastie_info.pastie); + assert(not token_invalid()); + assert(not pastie_not_found()); + + return this->on_retrieving_process(); + } + + void PastieRetrievingResponse::on_mustache_prepare (mstch::map& parContext) { + assert(m_pastie_info.pastie); + assert(not token_invalid()); + assert(not pastie_not_found()); + + parContext["pastie"] = + this->on_pastie_prepare(std::move(*m_pastie_info.pastie)); + parContext["pastie_lines"] = pastie_to_numbered_lines( + boost::get(parContext["pastie"]) + ); + parContext["self_destructed"] = m_pastie_info.self_destructed; + parContext["pastie_token"] = get_search_token(cgi_env()); + parContext["pastie_page"] = true; + } + + bool PastieRetrievingResponse::token_invalid() const { + assert(m_pastie_info.valid_token or not m_pastie_info.pastie); + return not m_pastie_info.valid_token; + } + + bool PastieRetrievingResponse::pastie_not_found() const { + return not m_pastie_info.pastie; + } +} //namespace kamokan diff --git a/src/kamokan_impl/pastie_retrieving_response.hpp b/src/kamokan_impl/pastie_retrieving_response.hpp new file mode 100644 index 0000000..ff4e876 --- /dev/null +++ b/src/kamokan_impl/pastie_retrieving_response.hpp @@ -0,0 +1,44 @@ +/* Copyright 2017, Michele Santullo + * This file is part of "kamokan". + * + * "kamokan" is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * "kamokan" is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with "kamokan". If not, see . + */ + +#pragma once + +#include "response.hpp" +#include + +namespace kamokan { + class PastieRetrievingResponse : public Response { + public: + PastieRetrievingResponse ( + const Kakoune::SafePtr& parSettings, + std::ostream* parStreamOut, + const Kakoune::SafePtr& parCgiEnv + ); + + protected: + bool pastie_not_found() const; + bool token_invalid() const; + + private: + virtual tawashi::HttpHeader on_process() override final; + virtual void on_mustache_prepare (mstch::map& parContext) override final; + virtual std::string on_pastie_prepare (std::string&& parPastie) = 0; + virtual tawashi::HttpHeader on_retrieving_process() = 0; + + Storage::RetrievedPastie m_pastie_info; + }; +} //namespace kamokan