diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt index a9a51945..95a10d02 100644 --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -11,6 +11,7 @@ set(CORE_SRC "util/base64.cpp" "util/util.cpp" "util/Log.cpp" + "util/HTTP.cpp" "tunnel/TransitTunnel.cpp" "tunnel/Tunnel.cpp" "tunnel/TunnelGateway.cpp" diff --git a/core/util/HTTP.cpp b/core/util/HTTP.cpp new file mode 100644 index 00000000..2addeda3 --- /dev/null +++ b/core/util/HTTP.cpp @@ -0,0 +1,60 @@ +#include "HTTP.h" +#include +#include + +namespace i2p { +namespace util { +namespace http { + +void Request::parseRequestLine(const std::string& line) +{ + std::stringstream ss(line); + ss >> method; + ss >> uri; +} + +void Request::parseHeaderLine(const std::string& line) +{ + const std::size_t pos = line.find_first_of(':'); + headers[boost::trim_copy(line.substr(0, pos))] = boost::trim_copy(line.substr(pos + 1)); +} + +Request::Request(const std::string& data) +{ + std::stringstream ss(data); + std::string line; + std::getline(ss, line); + parseRequestLine(line); + + while(std::getline(ss, line)) + parseHeaderLine(line); +} + +std::string Request::getMethod() const +{ + return method; +} + +std::string Request::getUri() const +{ + return uri; +} + +std::string Request::getHost() const +{ + return host; +} + +int Request::getPort() const +{ + return port; +} + +std::string Request::getHeader(const std::string& name) const +{ + return headers.at(name); +} + +} +} +} diff --git a/core/util/HTTP.h b/core/util/HTTP.h new file mode 100644 index 00000000..ceb3d931 --- /dev/null +++ b/core/util/HTTP.h @@ -0,0 +1,42 @@ +#ifndef _HTTP_H__ +#define _HTTP_H__ + +#include +#include + +namespace i2p { +namespace util { +namespace http { + +class Request { + void parseRequestLine(const std::string& line); + void parseHeaderLine(const std::string& line); +public: + Request(const std::string& data); + + std::string getMethod() const; + + std::string getUri() const; + + std::string getHost() const; + + int getPort() const; + + /** + * @throw std::out_of_range if no such header exists + */ + std::string getHeader(const std::string& name) const; + +private: + std::string method; + std::string uri; + std::string host; + int port; + std::map headers; +}; + +} +} +} + +#endif // _HTTP_H__ diff --git a/core/util/util.cpp b/core/util/util.cpp index cb53e786..a576bd09 100644 --- a/core/util/util.cpp +++ b/core/util/util.cpp @@ -193,6 +193,11 @@ namespace filesystem return pathTunnelsConfigFile; } + boost::filesystem::path GetWebuiDataDir() + { + return GetDataDir() / "webui"; + } + boost::filesystem::path GetDefaultDataDir() { // Custom path, or default path: diff --git a/core/util/util.h b/core/util/util.h index 29f68de5..0fb000ed 100644 --- a/core/util/util.h +++ b/core/util/util.h @@ -80,6 +80,10 @@ namespace util */ boost::filesystem::path GetDefaultDataDir(); + /** + * @return the default directory for webui data + */ + boost::filesystem::path GetWebuiDataDir(); /** * Read a configuration file and store its contents in the given maps. diff --git a/tests/Utility.cpp b/tests/Utility.cpp index dbbe2bb6..8317669f 100644 --- a/tests/Utility.cpp +++ b/tests/Utility.cpp @@ -1,5 +1,6 @@ #include #include "util/util.h" +#include "util/HTTP.h" BOOST_AUTO_TEST_SUITE(UtilityTests) @@ -88,4 +89,29 @@ BOOST_AUTO_TEST_CASE(ParseUrlPassword) BOOST_CHECK_EQUAL(url("").pass_, ""); } +BOOST_AUTO_TEST_CASE(ParseHTTPRequestNoHeaders) +{ + Request req1("GET /index.html HTTP/1.1"); + Request req2("POST / HTTP/1.0\r\n"); + BOOST_CHECK_EQUAL(req1.getMethod(), "GET"); + BOOST_CHECK_EQUAL(req1.getUri(), "/index.html"); + BOOST_CHECK_EQUAL(req2.getMethod(), "POST"); + BOOST_CHECK_EQUAL(req2.getUri(), "/"); +} + +BOOST_AUTO_TEST_CASE(ParseHTTPRequestWithHeaders) +{ + Request req1( + "GET /index.html HTTP/1.1\r\n" + "Host: localhost\r\n" + ); + Request req2( + "POST / HTTP/1.1\r\n" + "Host: localhost:123 \r\n" + ); + BOOST_CHECK_EQUAL(req1.getHeader("Host"), "localhost"); + BOOST_CHECK_EQUAL(req2.getHeader("Host"), "localhost:123"); +} + + BOOST_AUTO_TEST_SUITE_END()