Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 52 additions & 2 deletions src/websockets/Url.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ along with OpenOCPP. If not, see <http://www.gnu.org/licenses/>.

#include "Url.h"

#include <iomanip>
#include <regex>
#include <sstream>

namespace ocpp
{
Expand Down Expand Up @@ -46,9 +48,9 @@ Url::Url(const std::string& url)

// Convert path
m_path = match[10].str();
if (m_path.empty())
if (!m_path.empty())
{
m_path = "/";
m_path = encode(m_path);
}

// Convert port
Expand All @@ -68,11 +70,59 @@ Url::Url(const std::string& url)
m_is_valid = false;
}
}

// Rebuild URL
if (m_is_valid)
{
std::stringstream encoded_url;
encoded_url << m_protocol << "://";
if (!m_username.empty() || !m_password.empty())
{
encoded_url << m_username;
if (!m_password.empty())
{
encoded_url << ":" << m_password;
}
encoded_url << "@";
}
encoded_url << m_address;
if (m_port != 0)
{
encoded_url << ":" << m_port;
}
encoded_url << m_path;
m_url = encoded_url.str();
}
}
}

/** @brief Destructor */
Url::~Url() { }

/** @brief Encode an URL */
std::string Url::encode(const std::string& url) const
{
std::stringstream encoded_url;
encoded_url << std::hex;

for (const auto& c : url)
{
// Safe characters
if (((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z')) || ((c >= '0') && (c <= '9')) || (c == '/'))
{
// No encoding
encoded_url << c;
}
else
{
// Percent encoding
encoded_url << '%';
encoded_url << std::setw(2) << std::setfill('0') << static_cast<int>(c);
}
}

return encoded_url.str();
}

} // namespace websockets
} // namespace ocpp
3 changes: 3 additions & 0 deletions src/websockets/Url.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,9 @@ class Url
unsigned int m_port;
/** @brief Path part of the URL */
std::string m_path;

/** @brief Encode an URL */
std::string encode(const std::string& url) const;
};

} // namespace websockets
Expand Down
64 changes: 56 additions & 8 deletions tests/websockets/test_websockets_url.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,21 @@ TEST_SUITE("Nominal - hostname as string")
Url url("ftp://pif.com");

CHECK(url.isValid());
CHECK_EQ(url.url(), "ftp://pif.com");
CHECK_EQ(url.protocol(), "ftp");
CHECK_EQ(url.username(), "");
CHECK_EQ(url.password(), "");
CHECK_EQ(url.address(), "pif.com");
CHECK_EQ(url.port(), 0);
CHECK_EQ(url.path(), "/");
CHECK_EQ(url.path(), "");
}

TEST_CASE("Short URL with port")
{
Url url("ftp://pif.com:12345/");

CHECK(url.isValid());
CHECK_EQ(url.url(), "ftp://pif.com:12345/");
CHECK_EQ(url.protocol(), "ftp");
CHECK_EQ(url.username(), "");
CHECK_EQ(url.password(), "");
Expand All @@ -50,11 +52,12 @@ TEST_SUITE("Nominal - hostname as string")
CHECK_EQ(url.path(), "/");
}

TEST_CASE("URL wth path")
TEST_CASE("URL with path")
{
Url url("ftp://pif.com/paf/pouf");

CHECK(url.isValid());
CHECK_EQ(url.url(), "ftp://pif.com/paf/pouf");
CHECK_EQ(url.protocol(), "ftp");
CHECK_EQ(url.username(), "");
CHECK_EQ(url.password(), "");
Expand All @@ -68,6 +71,7 @@ TEST_SUITE("Nominal - hostname as string")
Url url("ftp://pif.com:12345/paf/pouf/");

CHECK(url.isValid());
CHECK_EQ(url.url(), "ftp://pif.com:12345/paf/pouf/");
CHECK_EQ(url.protocol(), "ftp");
CHECK_EQ(url.username(), "");
CHECK_EQ(url.password(), "");
Expand All @@ -76,37 +80,55 @@ TEST_SUITE("Nominal - hostname as string")
CHECK_EQ(url.path(), "/paf/pouf/");
}

TEST_CASE("URL with port and encoded path")
{
Url url("ftp://pif.com:12345/paf [ pouf / + BIM_bam) = boum ] 10.11.12.13!");

CHECK(url.isValid());
CHECK_EQ(url.url(),
R"(ftp://pif.com:12345/paf%20%5b%20pouf%20/%20%20%2b%20BIM%5fbam%29%20%3d%20boum%20%5d%2010%2e11%2e12%2e13%21)");
CHECK_EQ(url.protocol(), "ftp");
CHECK_EQ(url.username(), "");
CHECK_EQ(url.password(), "");
CHECK_EQ(url.address(), "pif.com");
CHECK_EQ(url.port(), 12345);
CHECK_EQ(url.path(), R"(/paf%20%5b%20pouf%20/%20%20%2b%20BIM%5fbam%29%20%3d%20boum%20%5d%2010%2e11%2e12%2e13%21)");
}

TEST_CASE("URL with username and port")
{
Url url("ftp://yip76-84@pif.com:12345");

CHECK(url.isValid());
CHECK_EQ(url.url(), "ftp://yip76-84@pif.com:12345");
CHECK_EQ(url.protocol(), "ftp");
CHECK_EQ(url.username(), "yip76-84");
CHECK_EQ(url.password(), "");
CHECK_EQ(url.address(), "pif.com");
CHECK_EQ(url.port(), 12345);
CHECK_EQ(url.path(), "/");
CHECK_EQ(url.path(), "");
}

TEST_CASE("URL with username, password and port")
{
Url url("ftp://yip76-84:£uiU*^gh#@pif.com:12345");

CHECK(url.isValid());
CHECK_EQ(url.url(), "ftp://yip76-84:£uiU*^gh#@pif.com:12345");
CHECK_EQ(url.protocol(), "ftp");
CHECK_EQ(url.username(), "yip76-84");
CHECK_EQ(url.password(), "£uiU*^gh#");
CHECK_EQ(url.address(), "pif.com");
CHECK_EQ(url.port(), 12345);
CHECK_EQ(url.path(), "/");
CHECK_EQ(url.path(), "");
}

TEST_CASE("URL with username, password, port and path")
{
Url url("ftp://yip76-84:£uiU*^gh#@pif.com:12345/paf/pouf/");

CHECK(url.isValid());
CHECK_EQ(url.url(), "ftp://yip76-84:£uiU*^gh#@pif.com:12345/paf/pouf/");
CHECK_EQ(url.protocol(), "ftp");
CHECK_EQ(url.username(), "yip76-84");
CHECK_EQ(url.password(), "£uiU*^gh#");
Expand All @@ -121,6 +143,7 @@ TEST_SUITE("Nominal - hostname as string")
Url url2(url1);

CHECK_EQ(url1.isValid(), url2.isValid());
CHECK_EQ(url1.url(), url2.url());
CHECK_EQ(url1.protocol(), url2.protocol());
CHECK_EQ(url1.username(), url2.username());
CHECK_EQ(url1.password(), url2.password());
Expand All @@ -137,6 +160,7 @@ TEST_SUITE("Nominal - hostname as string")
url2 = url1;

CHECK_EQ(url1.isValid(), url2.isValid());
CHECK_EQ(url1.url(), url2.url());
CHECK_EQ(url1.protocol(), url2.protocol());
CHECK_EQ(url1.username(), url2.username());
CHECK_EQ(url1.password(), url2.password());
Expand All @@ -153,19 +177,21 @@ TEST_SUITE("Nominal - hostname as IP address")
Url url("ftp://10.189.70.3");

CHECK(url.isValid());
CHECK_EQ(url.url(), "ftp://10.189.70.3");
CHECK_EQ(url.protocol(), "ftp");
CHECK_EQ(url.username(), "");
CHECK_EQ(url.password(), "");
CHECK_EQ(url.address(), "10.189.70.3");
CHECK_EQ(url.port(), 0);
CHECK_EQ(url.path(), "/");
CHECK_EQ(url.path(), "");
}

TEST_CASE("Short URL with port")
{
Url url("ftp://10.189.70.3:12345/");

CHECK(url.isValid());
CHECK_EQ(url.url(), "ftp://10.189.70.3:12345/");
CHECK_EQ(url.protocol(), "ftp");
CHECK_EQ(url.username(), "");
CHECK_EQ(url.password(), "");
Expand All @@ -174,11 +200,12 @@ TEST_SUITE("Nominal - hostname as IP address")
CHECK_EQ(url.path(), "/");
}

TEST_CASE("URL wth path")
TEST_CASE("URL with path")
{
Url url("ftp://10.189.70.3/paf/pouf");

CHECK(url.isValid());
CHECK_EQ(url.url(), "ftp://10.189.70.3/paf/pouf");
CHECK_EQ(url.protocol(), "ftp");
CHECK_EQ(url.username(), "");
CHECK_EQ(url.password(), "");
Expand All @@ -192,6 +219,7 @@ TEST_SUITE("Nominal - hostname as IP address")
Url url("ftp://10.189.70.3:12345/paf/pouf/");

CHECK(url.isValid());
CHECK_EQ(url.url(), "ftp://10.189.70.3:12345/paf/pouf/");
CHECK_EQ(url.protocol(), "ftp");
CHECK_EQ(url.username(), "");
CHECK_EQ(url.password(), "");
Expand All @@ -200,37 +228,55 @@ TEST_SUITE("Nominal - hostname as IP address")
CHECK_EQ(url.path(), "/paf/pouf/");
}

TEST_CASE("URL with port and encoded path")
{
Url url("ftp://10.189.70.3:12345/paf [ pouf / + BIM_bam) = boum ] 10.11.12.13!");

CHECK(url.isValid());
CHECK_EQ(url.url(),
R"(ftp://10.189.70.3:12345/paf%20%5b%20pouf%20/%20%20%2b%20BIM%5fbam%29%20%3d%20boum%20%5d%2010%2e11%2e12%2e13%21)");
CHECK_EQ(url.protocol(), "ftp");
CHECK_EQ(url.username(), "");
CHECK_EQ(url.password(), "");
CHECK_EQ(url.address(), "10.189.70.3");
CHECK_EQ(url.port(), 12345);
CHECK_EQ(url.path(), R"(/paf%20%5b%20pouf%20/%20%20%2b%20BIM%5fbam%29%20%3d%20boum%20%5d%2010%2e11%2e12%2e13%21)");
}

TEST_CASE("URL with username and port")
{
Url url("ftp://yip76-84@10.189.70.3:12345");

CHECK(url.isValid());
CHECK_EQ(url.url(), "ftp://yip76-84@10.189.70.3:12345");
CHECK_EQ(url.protocol(), "ftp");
CHECK_EQ(url.username(), "yip76-84");
CHECK_EQ(url.password(), "");
CHECK_EQ(url.address(), "10.189.70.3");
CHECK_EQ(url.port(), 12345);
CHECK_EQ(url.path(), "/");
CHECK_EQ(url.path(), "");
}

TEST_CASE("URL with username, password and port")
{
Url url("ftp://yip76-84:£uiU*^gh#@10.189.70.3:12345");

CHECK(url.isValid());
CHECK_EQ(url.url(), "ftp://yip76-84:£uiU*^gh#@10.189.70.3:12345");
CHECK_EQ(url.protocol(), "ftp");
CHECK_EQ(url.username(), "yip76-84");
CHECK_EQ(url.password(), "£uiU*^gh#");
CHECK_EQ(url.address(), "10.189.70.3");
CHECK_EQ(url.port(), 12345);
CHECK_EQ(url.path(), "/");
CHECK_EQ(url.path(), "");
}

TEST_CASE("URL with username, password, port and path")
{
Url url("ftp://yip76-84:£uiU*^gh#@10.189.70.3:12345/paf/pouf/");

CHECK(url.isValid());
CHECK_EQ(url.url(), "ftp://yip76-84:£uiU*^gh#@10.189.70.3:12345/paf/pouf/");
CHECK_EQ(url.protocol(), "ftp");
CHECK_EQ(url.username(), "yip76-84");
CHECK_EQ(url.password(), "£uiU*^gh#");
Expand All @@ -245,6 +291,7 @@ TEST_SUITE("Nominal - hostname as IP address")
Url url2(url1);

CHECK_EQ(url1.isValid(), url2.isValid());
CHECK_EQ(url1.url(), url2.url());
CHECK_EQ(url1.protocol(), url2.protocol());
CHECK_EQ(url1.username(), url2.username());
CHECK_EQ(url1.password(), url2.password());
Expand All @@ -261,6 +308,7 @@ TEST_SUITE("Nominal - hostname as IP address")
url2 = url1;

CHECK_EQ(url1.isValid(), url2.isValid());
CHECK_EQ(url1.url(), url2.url());
CHECK_EQ(url1.protocol(), url2.protocol());
CHECK_EQ(url1.username(), url2.username());
CHECK_EQ(url1.password(), url2.password());
Expand Down