1
0
Fork 0
mirror of https://github.com/KingDuckZ/kamokan.git synced 2024-11-23 00:33:44 +00:00

Add CurlWrapper class and use it to escape GET/POST values.

Use the new code to print the values from the request.
This commit is contained in:
King_DuckZ 2017-04-06 20:15:44 +01:00
parent 6a502df135
commit cc20a8ccfb
10 changed files with 143 additions and 17 deletions

View file

@ -1,6 +1,7 @@
project(tawashi CXX)
find_package(Boost 1.53.0 REQUIRED COMPONENTS program_options filesystem system)
find_package(CURL REQUIRED)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
@ -15,15 +16,18 @@ add_executable(${PROJECT_NAME}
cgi_env.cpp
num_to_token.cpp
cgi_post.cpp
curl_wrapper.cpp
)
target_include_directories(${PROJECT_NAME} SYSTEM
PRIVATE ${Boost_INCLUDE_DIRS}
PRIVATE ${TAWASHI_SOURCE_ROOT}/lib/bette-enums
PRIVATE ${CURL_INCLUDE_DIR}
)
target_link_libraries(${PROJECT_NAME}
PRIVATE ${Boost_LIBRARIES}
PRIVATE incredis
${CURL_LIBRARIES}
)
target_compile_definitions(${PROJECT_NAME}
PRIVATE BOOST_SPIRIT_USE_PHOENIX_V3=1

View file

@ -29,7 +29,6 @@ namespace tawashi {
using boost::spirit::ascii::space;
using boost::spirit::qi::raw;
using boost::spirit::qi::char_;
using boost::spirit::qi::int_;
using boost::string_ref;
using VerNum = boost::spirit::qi::uint_parser<uint16_t, 10, 1, 1>;
using RuleType = boost::spirit::qi::rule<std::string::const_iterator, string_ref(), boost::spirit::ascii::space_type>;
@ -143,8 +142,14 @@ namespace tawashi {
return m_cgi_env[CGIVars::SERVER_SOFTWARE];
}
KeyValueList CGIEnv::query_string_split() const {
return split_env_vars(m_cgi_env[CGIVars::QUERY_STRING]);
CGIEnv::GetMapType CGIEnv::query_string_split() const {
GetMapType retval;
const auto urlencoded_values = split_env_vars(m_cgi_env[CGIVars::QUERY_STRING]);
retval.reserve(urlencoded_values.size());
for (auto& itm : urlencoded_values) {
retval[m_curl.url_unescape(itm.first)] = m_curl.url_unescape(itm.second);
}
return retval;
}
std::ostream& CGIEnv::print_all (std::ostream& parStream, const char* parNewline) const {

View file

@ -2,12 +2,14 @@
#include "split_get_vars.hpp"
#include "duckhandy/compatibility.h"
#include "curl_wrapper.hpp"
#include <vector>
#include <string>
#include <boost/utility/string_ref.hpp>
#include <cstdint>
#include <iostream>
#include <boost/optional.hpp>
#include <boost/container/flat_map.hpp>
namespace tawashi {
class CGIEnv {
@ -18,6 +20,8 @@ namespace tawashi {
uint16_t minor;
};
typedef boost::container::flat_map<std::string, std::string> GetMapType;
CGIEnv();
~CGIEnv() noexcept;
@ -39,11 +43,12 @@ namespace tawashi {
boost::optional<VersionInfo> server_protocol() const a_pure;
const std::string& server_software() const;
KeyValueList query_string_split() const a_pure;
GetMapType query_string_split() const a_pure;
std::ostream& print_all (std::ostream& parStream, const char* parNewline) const;
private:
std::vector<std::string> m_cgi_env;
CurlWrapper m_curl;
};
} //namespace tawashi

View file

@ -1,6 +1,7 @@
#include "cgi_post.hpp"
#include "cgi_env.hpp"
#include "split_get_vars.hpp"
#include "curl_wrapper.hpp"
#include <iostream>
#include <iterator>
#include <algorithm>
@ -31,8 +32,9 @@ namespace tawashi {
std::back_inserter(original_data)
);
CurlWrapper curl;
for (auto& itm : split_env_vars(original_data)) {
map[itm.first] = itm.second;
map[curl.url_unescape(itm.first)] = curl.url_unescape(itm.second);
}
}

View file

@ -1,13 +1,13 @@
#pragma once
#include <boost/container/flat_map.hpp>
#include <boost/utility/string_ref.hpp>
#include <string>
namespace tawashi {
class CGIEnv;
namespace cgi {
typedef boost::container::flat_map<boost::string_ref, boost::string_ref> PostMapType;
typedef boost::container::flat_map<std::string, std::string> PostMapType;
const PostMapType& read_post (const CGIEnv& parEnv);
} //namespace cgi

87
src/curl_wrapper.cpp Normal file
View file

@ -0,0 +1,87 @@
#include "curl_wrapper.hpp"
#include <curl/curl.h>
#include <cassert>
#include <ciso646>
#if !defined(NDEBUG)
# define CURL_WRAPPER_VERBOSE
#endif
#if defined(CURL_WRAPPER_VERBOSE)
# include <iostream>
#endif
namespace tawashi {
namespace {
struct CurlDeleter {
void operator() (CURL* parCurl) const {
#if defined(CURL_WRAPPER_VERBOSE)
std::cout << "Deleting CURL* " << parCurl << " and cleaning up\n";
#endif
assert(parCurl);
curl_easy_cleanup(parCurl);
curl_global_cleanup();
}
};
struct CurlBufferDeleter {
void operator() (char* parPtr) {
assert(parPtr);
curl_free(parPtr);
}
};
typedef std::unique_ptr<char, CurlBufferDeleter> CurlBufferPointer;
CurlWrapper::CurlPtr get_new_curl() {
static std::weak_ptr<CURL> curl;
#if defined(CURL_WRAPPER_VERBOSE)
std::cout << "CURL object requested\n";
#endif
auto shared = curl.lock();
if (not shared) {
#if defined(CURL_WRAPPER_VERBOSE)
std::cout << "CURL weak pointer has expired! Calling curl_global_init()\n";
#endif
if (curl_global_init(CURL_GLOBAL_ALL))
return CurlWrapper::CurlPtr();
#if defined(CURL_WRAPPER_VERBOSE)
std::cout << "Calling curl_easy_init()\n";
#endif
shared.reset(curl_easy_init(), CurlDeleter());
if (not shared) {
curl_global_cleanup();
return CurlWrapper::CurlPtr();
}
curl = shared;
}
#if defined(CURL_WRAPPER_VERBOSE)
std::cout << "CURL shared pointer ready: " << shared.get() << '\n';
#endif
assert(shared);
return shared;
}
} //unnamed namespace
CurlWrapper::CurlWrapper() :
m_curl(get_new_curl())
{
assert(m_curl);
}
CurlWrapper::~CurlWrapper() noexcept = default;
std::string CurlWrapper::url_escape (const boost::string_ref& parText) const {
const CurlBufferPointer buff(curl_easy_escape(m_curl.get(), parText.data(), parText.size()));
return std::string(buff.get());
}
std::string CurlWrapper::url_unescape (const boost::string_ref& parText) const {
int outLen;
const CurlBufferPointer buff(curl_easy_unescape(m_curl.get(), parText.data(), parText.size(), &outLen));
return std::string(buff.get(), outLen);
}
} //namespace tawashi

24
src/curl_wrapper.hpp Normal file
View file

@ -0,0 +1,24 @@
#pragma once
#include <boost/utility/string_ref.hpp>
#include <string>
#include <memory>
typedef void CURL;
namespace tawashi {
class CurlWrapper {
public:
typedef std::shared_ptr<CURL> CurlPtr;
CurlWrapper();
CurlWrapper (const CurlWrapper&) = delete;
~CurlWrapper() noexcept;
std::string url_escape (const boost::string_ref& parText) const;
std::string url_unescape (const boost::string_ref& parText) const;
private:
CurlPtr m_curl;
};
} //namespace tawashi

View file

@ -1,10 +1,9 @@
#include "incredis/incredis.hpp"
#include "submit_form_response.hpp"
#include "cgi_env.hpp"
#include "cgi_post.hpp"
#include <iostream>
#include <string>
#include <algorithm>
#include <iterator>
//www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4150.pdf
@ -30,10 +29,10 @@ int main() {
std::cout << "Content length: \"" << in_len << "\"\n<br>\n";
cgi_env.print_all(std::cout, "<br>\n");
std::string input;
if (in_len > 0)
std::copy_n(std::istream_iterator<char>(std::cin), in_len, std::back_inserter(input));
std::cout << input << '\n';
for (auto& itm : tawashi::cgi::read_post(cgi_env)) {
std::cout << "Key: \"" << itm.first << "\"<br>\nValue: \"" <<
itm.second << "\"<br>\n";
}
auto ver = cgi_env.gateway_interface();
if (ver)

View file

@ -9,7 +9,7 @@
#include <boost/range/algorithm/find.hpp>
namespace tawashi {
KeyValueList split_env_vars (const std::string& parList) {
RawKeyValueList split_env_vars (const std::string& parList) {
using MatchRange = boost::iterator_range<std::string::const_iterator>;
using boost::token_finder;
using boost::adaptors::transformed;
@ -23,7 +23,7 @@ namespace tawashi {
//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<KeyValueList>(
return boost::copy_range<RawKeyValueList>(
make_iterator_range(
split_iterator<std::string::const_iterator>(parList, token_finder([](char c){return '&'==c;})),
split_iterator<std::string::const_iterator>()

View file

@ -6,7 +6,7 @@
#include <utility>
namespace tawashi {
typedef std::vector<std::pair<boost::string_ref, boost::string_ref>> KeyValueList;
typedef std::vector<std::pair<boost::string_ref, boost::string_ref>> RawKeyValueList;
KeyValueList split_env_vars ( const std::string& parCommaSeparatedList ) a_pure;
RawKeyValueList split_env_vars ( const std::string& parCommaSeparatedList ) a_pure;
} //namespace tawashi