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:
parent
6a502df135
commit
cc20a8ccfb
10 changed files with 143 additions and 17 deletions
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
87
src/curl_wrapper.cpp
Normal 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
24
src/curl_wrapper.hpp
Normal 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
|
11
src/main.cpp
11
src/main.cpp
|
@ -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)
|
||||
|
|
|
@ -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>()
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue