diff --git a/html/error.html.mstch b/html/error.html.mstch new file mode 100644 index 0000000..4c3b835 --- /dev/null +++ b/html/error.html.mstch @@ -0,0 +1,13 @@ +{{> head}} + +
+ + {{> topbar}} + +

An error occurred: {{error_message}}

+ +
+ + + + diff --git a/src/tawashi/main.cpp b/src/tawashi/main.cpp index 1074f08..d58b720 100644 --- a/src/tawashi/main.cpp +++ b/src/tawashi/main.cpp @@ -19,6 +19,7 @@ #include "submit_paste_response.hpp" #include "pastie_response.hpp" #include "index_response.hpp" +#include "error_response.hpp" #include "response_factory.hpp" #include "cgi_env.hpp" #include "ini_file.hpp" @@ -54,8 +55,13 @@ namespace { } template - std::unique_ptr make_response (const Kakoune::SafePtr& parSettings, const Kakoune::SafePtr& parCgiEnv) { - return static_cast>(std::make_unique(parSettings, &std::cout, parCgiEnv)); + std::unique_ptr make_response ( + const Kakoune::SafePtr& parSettings, + const Kakoune::SafePtr& parCgiEnv + ) { + return static_cast>( + std::make_unique(parSettings, &std::cout, parCgiEnv) + ); } void fill_defaults (tawashi::SettingsBag& parSettings) { @@ -80,6 +86,7 @@ int main (int parArgc, char* parArgv[], char* parEnvp[]) { using tawashi::IndexResponse; using tawashi::SubmitPasteResponse; using tawashi::PastieResponse; + using tawashi::ErrorResponse; using tawashi::Response; //Prepare the logger @@ -108,6 +115,7 @@ int main (int parArgc, char* parArgv[], char* parEnvp[]) { resp_factory.register_maker("index.cgi", &make_response); resp_factory.register_maker("", &make_response); resp_factory.register_maker("paste.cgi", &make_response); + resp_factory.register_maker("error.cgi", &make_response); resp_factory.register_jolly_maker(&make_response); std::unique_ptr response = resp_factory.make_response(cgi_env->path_info().substr(1)); diff --git a/src/tawashi_implem/CMakeLists.txt b/src/tawashi_implem/CMakeLists.txt index fffa90f..38c4283 100644 --- a/src/tawashi_implem/CMakeLists.txt +++ b/src/tawashi_implem/CMakeLists.txt @@ -24,6 +24,7 @@ add_library(${PROJECT_NAME} STATIC settings_bag.cpp sanitized_utf8.cpp tiger.c + error_response.cpp ) target_include_directories(${PROJECT_NAME} diff --git a/src/tawashi_implem/error_reasons.hpp b/src/tawashi_implem/error_reasons.hpp new file mode 100644 index 0000000..5320e8c --- /dev/null +++ b/src/tawashi_implem/error_reasons.hpp @@ -0,0 +1,26 @@ +/* Copyright 2017, Michele Santullo + * This file is part of "tawashi". + * + * "tawashi" 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. + * + * "tawashi" 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 "tawashi". If not, see . + */ + +#pragma once + +namespace tawashi { + enum ErrorReasons : int { + PostLengthNotInRange, + PastieNotSaved, + UserFlooding + }; +} //namespace tawashi diff --git a/src/tawashi_implem/error_response.cpp b/src/tawashi_implem/error_response.cpp new file mode 100644 index 0000000..b762aa9 --- /dev/null +++ b/src/tawashi_implem/error_response.cpp @@ -0,0 +1,34 @@ +/* Copyright 2017, Michele Santullo + * This file is part of "tawashi". + * + * "tawashi" 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. + * + * "tawashi" 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 "tawashi". If not, see . + */ + +#include "error_response.hpp" +#include + +namespace tawashi { + ErrorResponse::ErrorResponse ( + const Kakoune::SafePtr& parSettings, + std::ostream* parStreamOut, + const Kakoune::SafePtr& parCgiEnv + ) : + Response(parSettings, parStreamOut, parCgiEnv, false) + { + } + + void ErrorResponse::on_mustache_prepare (mstch::map& parContext) { + parContext["error_message"] = "No error"; + } +} //namespace tawashi diff --git a/src/tawashi_implem/error_response.hpp b/src/tawashi_implem/error_response.hpp new file mode 100644 index 0000000..12e4339 --- /dev/null +++ b/src/tawashi_implem/error_response.hpp @@ -0,0 +1,39 @@ +/* Copyright 2017, Michele Santullo + * This file is part of "tawashi". + * + * "tawashi" 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. + * + * "tawashi" 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 "tawashi". If not, see . + */ + +#pragma once + +#include "response.hpp" +#include + +namespace tawashi { + class ErrorResponse : public Response { + public: + ErrorResponse ( + const Kakoune::SafePtr& parSettings, + std::ostream* parStreamOut, + const Kakoune::SafePtr& parCgiEnv + ); + + protected: + virtual boost::string_ref page_basename() const override { return boost::string_ref("error"); } + + private: + virtual void on_mustache_prepare (mstch::map& parContext) override; + }; +} //namespace tawashi + diff --git a/src/tawashi_implem/response.hpp b/src/tawashi_implem/response.hpp index b84f01b..e4e71cc 100644 --- a/src/tawashi_implem/response.hpp +++ b/src/tawashi_implem/response.hpp @@ -53,8 +53,10 @@ namespace tawashi { const Kakoune::SafePtr& parCgiEnv, bool parWantRedis ); - const cgi::Env& cgi_env() const; + void change_type (Types parRespType, std::string&& parValue); + + const cgi::Env& cgi_env() const; const boost::string_ref& base_uri() const; virtual boost::string_ref page_basename() const = 0; redis::IncRedis& redis() const; diff --git a/src/tawashi_implem/submit_paste_response.cpp b/src/tawashi_implem/submit_paste_response.cpp index 1b0820d..2d168cf 100644 --- a/src/tawashi_implem/submit_paste_response.cpp +++ b/src/tawashi_implem/submit_paste_response.cpp @@ -123,16 +123,20 @@ namespace tawashi { if (pastie.size() < settings.as("min_pastie_size")) return; if (max_sz and pastie.size() > max_sz) { - if (settings.as("truncate_long_pasties")) + if (settings.as("truncate_long_pasties")) { pastie = pastie.substr(0, max_sz); - else + } + else { + error_redirect(1, ErrorReasons::PostLengthNotInRange); return; + } } //TODO: replace boost's lexical_cast with mine when I have some checks //over invalid inputs const uint32_t duration_int = std::max(std::min((duration.empty() ? 86400U : boost::lexical_cast(duration)), 2628000U), 1U); boost::optional token = submit_to_redis(pastie, duration_int, lang); + if (token) { std::ostringstream oss; oss << base_uri() << '/' << *token; @@ -140,9 +144,12 @@ namespace tawashi { oss << '?' << lang; this->change_type(Response::Location, oss.str()); } + else { + return; + } } - boost::optional SubmitPasteResponse::submit_to_redis (const boost::string_ref& parText, uint32_t parExpiry, const boost::string_ref& parLang) const { + boost::optional SubmitPasteResponse::submit_to_redis (const boost::string_ref& parText, uint32_t parExpiry, const boost::string_ref& parLang) { auto& redis = this->redis(); if (not redis.is_connected()) return boost::optional(); @@ -150,6 +157,7 @@ namespace tawashi { std::string ip_hash = hashed_ip(cgi_env().remote_addr()); if (redis.get(ip_hash)) { //please wait and submit again + error_redirect(1, ErrorReasons::UserFlooding); return boost::optional(); } @@ -167,6 +175,13 @@ namespace tawashi { return boost::make_optional(token); } + error_redirect(1, ErrorReasons::PastieNotSaved); return boost::optional(); } + + void SubmitPasteResponse::error_redirect (int parCode, ErrorReasons parReason) { + std::ostringstream oss; + oss << base_uri() << "/error.cgi?code=" << parCode << "&reason=" << parReason; + this->change_type(Response::Location, oss.str()); + } } //namespace tawashi diff --git a/src/tawashi_implem/submit_paste_response.hpp b/src/tawashi_implem/submit_paste_response.hpp index 55ad0f5..bf53ffa 100644 --- a/src/tawashi_implem/submit_paste_response.hpp +++ b/src/tawashi_implem/submit_paste_response.hpp @@ -18,6 +18,7 @@ #pragma once #include "response.hpp" +#include "error_reasons.hpp" #include #include #include @@ -36,7 +37,8 @@ namespace tawashi { private: virtual void on_process() override; - boost::optional submit_to_redis (const boost::string_ref& parText, uint32_t parExpiry, const boost::string_ref& parLang) const; + boost::optional submit_to_redis (const boost::string_ref& parText, uint32_t parExpiry, const boost::string_ref& parLang); + void error_redirect (int parCode, ErrorReasons parReason); std::string m_error_message; };