From fea5b738df1c2594e6f5608904e80eacbee7ea06 Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Tue, 4 Apr 2017 20:58:40 +0100 Subject: [PATCH] First commit --- .gitmodules | 6 +++++ CMakeLists.txt | 8 ++++++ lib/better-enums | 1 + lib/incredis | 1 + src/CMakeLists.txt | 24 ++++++++++++++++++ src/envy.cpp | 17 +++++++++++++ src/envy.hpp | 29 ++++++++++++++++++++++ src/get_env.cpp | 33 +++++++++++++++++++++++++ src/get_env.hpp | 24 ++++++++++++++++++ src/main.cpp | 48 ++++++++++++++++++++++++++++++++++++ src/response.cpp | 17 +++++++++++++ src/response.hpp | 21 ++++++++++++++++ src/split_get_vars.cpp | 43 ++++++++++++++++++++++++++++++++ src/split_get_vars.hpp | 10 ++++++++ src/submit_form_response.cpp | 20 +++++++++++++++ src/submit_form_response.hpp | 13 ++++++++++ 16 files changed, 315 insertions(+) create mode 100644 .gitmodules create mode 100644 CMakeLists.txt create mode 160000 lib/better-enums create mode 160000 lib/incredis create mode 100644 src/CMakeLists.txt create mode 100644 src/envy.cpp create mode 100644 src/envy.hpp create mode 100644 src/get_env.cpp create mode 100644 src/get_env.hpp create mode 100644 src/main.cpp create mode 100644 src/response.cpp create mode 100644 src/response.hpp create mode 100644 src/split_get_vars.cpp create mode 100644 src/split_get_vars.hpp create mode 100644 src/submit_form_response.cpp create mode 100644 src/submit_form_response.hpp diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..cf06646 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,6 @@ +[submodule "lib/incredis"] + path = lib/incredis + url = https://github.com/KingDuckZ/incredis.git +[submodule "lib/better-enums"] + path = lib/better-enums + url = https://github.com/aantron/better-enums diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..a11b359 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,8 @@ +cmake_minimum_required(VERSION 3.3 FATAL_ERROR) +list (APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules) +project(tawashi_top) + +set(TAWSHI_SOURCE_ROOT "${CMAKE_CURRENT_SOURCE_DIR}") + +add_subdirectory(lib/incredis) +add_subdirectory(src) diff --git a/lib/better-enums b/lib/better-enums new file mode 160000 index 0000000..37d8f98 --- /dev/null +++ b/lib/better-enums @@ -0,0 +1 @@ +Subproject commit 37d8f987ca939af846a2d29a8f8198f9bf3ac4b7 diff --git a/lib/incredis b/lib/incredis new file mode 160000 index 0000000..ee0767e --- /dev/null +++ b/lib/incredis @@ -0,0 +1 @@ +Subproject commit ee0767e52c73402f7832bf84b2f00b36aae62c2d diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..d1b2167 --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,24 @@ +project(tawashi CXX) + +find_package(Boost 1.53.0 REQUIRED COMPONENTS program_options filesystem system) + +set(CMAKE_CXX_STANDARD 14) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +add_executable(${PROJECT_NAME} + main.cpp + split_get_vars.cpp + response.cpp + submit_form_response.cpp + get_env.cpp + envy.cpp +) + +target_include_directories(${PROJECT_NAME} SYSTEM + PRIVATE ${Boost_INCLUDE_DIRS} + PRIVATE ${TAWASHI_SOURCE_ROOT}/lib/bette-enums +) +target_link_libraries(${PROJECT_NAME} + PRIVATE ${Boost_LIBRARIES} + PRIVATE incredis +) diff --git a/src/envy.cpp b/src/envy.cpp new file mode 100644 index 0000000..d0d07dc --- /dev/null +++ b/src/envy.cpp @@ -0,0 +1,17 @@ +#include "envy.hpp" +#include "get_env.hpp" + +namespace tawashi { + std::vector get_cgi_vars() { + using boost::string_ref; + + std::vector retlist; + retlist.reserve(CGIVars::_size()); + + for (CGIVars var : CGIVars::_values()) { + auto value = get_env_as(var._to_string(), ""); + retlist.push_back(std::string(value.data(), value.size())); + } + return retlist; + } +} //namespace tawashi diff --git a/src/envy.hpp b/src/envy.hpp new file mode 100644 index 0000000..0b1020b --- /dev/null +++ b/src/envy.hpp @@ -0,0 +1,29 @@ +#pragma once + +#include +#include +#include "enum.h" + +namespace tawashi { + BETTER_ENUM(CGIVars, std::size_t, + AUTH_TYPE = 0, + CONTENT_LENGTH, + CONTENT_TYPE, + GATEWAY_INTERFACE, + PATH_INFO, + PATH_TRANSLATED, + QUERY_STRING, + REMOTE_ADDR, + REMOTE_HOST, + REMOTE_IDENT, + REMOTE_USER, + REQUEST_METHOD, + SCRIPT_NAME, + SERVER_NAME, + SERVER_PORT, + SERVER_PROTOCOL, + SERVER_SOFTWARE + ); + + std::vector get_cgi_vars(); +} //namespace tawashi diff --git a/src/get_env.cpp b/src/get_env.cpp new file mode 100644 index 0000000..8dbf83e --- /dev/null +++ b/src/get_env.cpp @@ -0,0 +1,33 @@ +#include "get_env.hpp" +#include "duckhandy/lexical_cast.hpp" +#include + +namespace tawashi { + boost::optional get_env (const char* parName) { + using boost::string_ref; + using boost::make_optional; + using boost::optional; + + const char* const raw_getvar = secure_getenv(parName); + return (raw_getvar ? make_optional(string_ref(raw_getvar)) : optional()); + } + + template <> + std::string get_env_as (const char* parName, const std::string& parDefault) { + auto var = get_env(parName); + return (var ? std::string(var->data(), var->size()) : parDefault); + } + + template <> + boost::string_ref get_env_as (const char* parName, const boost::string_ref& parDefault) { + auto var = get_env(parName); + return (var ? *var : parDefault); + } + + template <> + std::size_t get_env_as (const char* parName, const std::size_t& parDefault) { + using dhandy::lexical_cast; + auto var = get_env(parName); + return (var ? lexical_cast(*var) : parDefault); + } +} //namespace tawashi diff --git a/src/get_env.hpp b/src/get_env.hpp new file mode 100644 index 0000000..30c85d2 --- /dev/null +++ b/src/get_env.hpp @@ -0,0 +1,24 @@ +#pragma once + +#include +#include +#if !defined(_GNU_SOURCE) +# define _GNU_SOURCE +#endif +#include +#include +#include + +namespace tawashi { + boost::optional get_env (const char* parName); + + template + A get_env_as (const char* parName, const A& parDefault); + + template <> + std::string get_env_as (const char* parName, const std::string& parDefault); + template <> + boost::string_ref get_env_as (const char* parName, const boost::string_ref& parDefault); + template <> + std::size_t get_env_as (const char* parName, const std::size_t& parDefault); +} //namespace tawashi diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..3f6bad3 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,48 @@ +#include "incredis/incredis.hpp" +#include "split_get_vars.hpp" +#include "submit_form_response.hpp" +#include "envy.hpp" +#include "duckhandy/lexical_cast.hpp" +#include +#include +#include +#include + +//www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4150.pdf + +namespace { +} //unnamed namespace + +int main() { + using boost::string_ref; + using dhandy::lexical_cast; + + std::vector env = tawashi::get_cgi_vars(); + //std::cout << "Content-type:text/plain\n\n"; + const std::string& getvar = env[tawashi::CGIVars::QUERY_STRING]; + //std::cout << "QUERY_STRING = \"" << getvar << "\"\n"; + + redis::IncRedis incredis("127.0.0.1", 6379); + + tawashi::SubmitFormResponse resp; + resp.send(); + + for (auto& pair : tawashi::split_env_vars(getvar)) { + std::cout << "first:\t\"" << pair.first << + "\"\tsecond:\t\"" << pair.second << "\"\n"; + } + + const std::size_t in_len = lexical_cast(env[tawashi::CGIVars::CONTENT_LENGTH]); + std::cout << "\n
\n"; + std::cout << "Content length: \"" << in_len << "\"\n
\n"; + + for (std::size_t z = 0; z < env.size(); ++z) { + std::cout << tawashi::CGIVars::_from_integral(z) << " = \"" << env[z] << "\"
\n"; + } + std::string input; + if (in_len > 0) + std::copy_n(std::istream_iterator(std::cin), in_len, std::back_inserter(input)); + std::cout << input << '\n'; + + return 0; +} diff --git a/src/response.cpp b/src/response.cpp new file mode 100644 index 0000000..7f3bf14 --- /dev/null +++ b/src/response.cpp @@ -0,0 +1,17 @@ +#include "response.hpp" +#include + +namespace tawashi { + Response::Response (std::string&& parType) : + m_content_type(std::move(parType)) + { + } + + Response::~Response() noexcept = default; + + void Response::send() { + std::cout << "Content-type:" << m_content_type << "\n\n"; + this->on_send(std::cout); + std::cout.flush(); + } +} //namespace tawashi diff --git a/src/response.hpp b/src/response.hpp new file mode 100644 index 0000000..f43f08f --- /dev/null +++ b/src/response.hpp @@ -0,0 +1,21 @@ +#pragma once + +#include +#include + +namespace tawashi { + class Response { + public: + virtual ~Response() noexcept; + + void send(); + + protected: + Response (std::string&& parType); + + private: + virtual void on_send (std::ostream& parStream) = 0; + + std::string m_content_type; + }; +} //namespace tawashi diff --git a/src/split_get_vars.cpp b/src/split_get_vars.cpp new file mode 100644 index 0000000..176f25a --- /dev/null +++ b/src/split_get_vars.cpp @@ -0,0 +1,43 @@ +#include "split_get_vars.hpp" +#include +#include +#include +#include +#include +#include +#include +#include + +namespace tawashi { + std::vector> split_env_vars (const std::string& parList) { + using MatchRange = boost::iterator_range; + using boost::token_finder; + using boost::adaptors::transformed; + using boost::adaptors::filtered; + using boost::string_ref; + using boost::split_iterator; + using boost::make_iterator_range; + using boost::range::find; + + //See: + //https://stackoverflow.com/questions/27999941/how-to-use-boostsplit-with-booststring-ref-in-boost-1-55 + //http://www.boost.org/doc/libs/1_60_0/doc/html/boost/algorithm/token_finder.html + //https://stackoverflow.com/questions/20781090/difference-between-boostsplit-vs-boostiter-split + return boost::copy_range>>( + make_iterator_range( + split_iterator(parList, token_finder([](char c){return '&'==c;})), + split_iterator() + ) | + filtered([](const MatchRange& r){ return not r.empty(); }) | + transformed([](const MatchRange& r){ + auto eq = find(r, '='); + if (r.empty()) + return std::pair(); + if (r.end() == eq) + return std::make_pair(string_ref(&*r.begin(), r.size()), string_ref()); + else + return std::make_pair(string_ref(&*r.begin(), eq - r.begin()), string_ref(&*(eq + 1), r.size() - (eq - r.begin() + 1))); + }) + ); + } +} //namespace tawashi diff --git a/src/split_get_vars.hpp b/src/split_get_vars.hpp new file mode 100644 index 0000000..7f5cd40 --- /dev/null +++ b/src/split_get_vars.hpp @@ -0,0 +1,10 @@ +#pragma once + +#include "duckhandy/compatibility.h" +#include +#include +#include + +namespace tawashi { + std::vector> split_env_vars ( const std::string& parCommaSeparatedList ) a_pure; +} //namespace tawashi diff --git a/src/submit_form_response.cpp b/src/submit_form_response.cpp new file mode 100644 index 0000000..d962c6f --- /dev/null +++ b/src/submit_form_response.cpp @@ -0,0 +1,20 @@ +#include "submit_form_response.hpp" + +namespace tawashi { + SubmitFormResponse::SubmitFormResponse() : + Response("text/html") + { + } + + void SubmitFormResponse::on_send (std::ostream& parStream) { + parStream << + R"( +
+ +
+ +
+
+)"; + } +} //namespace tawashi diff --git a/src/submit_form_response.hpp b/src/submit_form_response.hpp new file mode 100644 index 0000000..94bd5a1 --- /dev/null +++ b/src/submit_form_response.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include "response.hpp" + +namespace tawashi { + class SubmitFormResponse : public Response { + public: + SubmitFormResponse(); + + private: + virtual void on_send (std::ostream& parStream) override; + }; +} //namespace tawashi