From 056904c90b62a34b45a4f9e40204ac69af60d232 Mon Sep 17 00:00:00 2001 From: Gioacchino Mazzurco Date: Mon, 11 Nov 2019 11:14:28 +0100 Subject: [PATCH] Improve RsUrl Fix a bug in RsUrl::fromString eating one character when parsing URL string with IPv6 host Offer explicit conversion from sockaddr_storage --- libretroshare/src/util/rsurl.cc | 35 ++++++++++++++++++++++++++------- libretroshare/src/util/rsurl.h | 5 ++++- 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/libretroshare/src/util/rsurl.cc b/libretroshare/src/util/rsurl.cc index e625815e4..dd01d7384 100644 --- a/libretroshare/src/util/rsurl.cc +++ b/libretroshare/src/util/rsurl.cc @@ -1,6 +1,6 @@ /* * RetroShare - * Copyright (C) 2018 Gioacchino Mazzurco + * Copyright (C) 2018-2019 Gioacchino Mazzurco * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as @@ -17,15 +17,16 @@ */ -#include "rsurl.h" -#include "serialiser/rstypeserializer.h" - #include #include #include #include #include +#include "rsurl.h" +#include "serialiser/rstypeserializer.h" +#include "util/rsnet.h" + using namespace std; RsUrl::RsUrl() : mPort(0), mHasPort(false) {} @@ -33,6 +34,26 @@ RsUrl::RsUrl() : mPort(0), mHasPort(false) {} RsUrl::RsUrl(const std::string& urlStr) : mPort(0), mHasPort(false) { fromString(urlStr); } +RsUrl::RsUrl(const sockaddr_storage& addr): mPort(0), mHasPort(false) +{ + switch(addr.ss_family) + { + case AF_INET: setScheme("ipv4"); break; + case AF_INET6: setScheme("ipv6"); break; + default: + { + std::string addrDump; + sockaddr_storage_dump(addr, &addrDump); + RsErr() << __PRETTY_FUNCTION__ << " got invalid addr: " << addrDump + << std::endl; + return; + } + } + + setHost(sockaddr_storage_iptostring(addr)); + setPort(sockaddr_storage_port(addr)); +} + RsUrl& RsUrl::fromString(const std::string& urlStr) { size_t endI = urlStr.size()-1; @@ -55,7 +76,7 @@ RsUrl& RsUrl::fromString(const std::string& urlStr) { if(++hostBeginI >= endI) return *this; hostEndI = urlStr.find(ipv6WrapClose, hostBeginI); - mHost = urlStr.substr(hostBeginI, hostEndI - hostBeginI - 1); + mHost = urlStr.substr(hostBeginI, hostEndI - hostBeginI); ++hostEndI; } else @@ -250,10 +271,10 @@ RsUrl& RsUrl::setFragment(const std::string& fragment) size_t boundary = len-2; // % Encoded char must be at least 2 hex char for (size_t i = 0; i < len; ++i) { - if(str[i] == '%' && i < boundary) { - decoded << static_cast(std::stoi(str.substr(++i, 2), 0, 16)); + decoded << static_cast(std::stoi( + str.substr(++i, 2), nullptr, 16 )); ++i; } else decoded << str[i]; diff --git a/libretroshare/src/util/rsurl.h b/libretroshare/src/util/rsurl.h index f02c7f636..0610585c5 100644 --- a/libretroshare/src/util/rsurl.h +++ b/libretroshare/src/util/rsurl.h @@ -22,6 +22,8 @@ #include "serialiser/rsserializable.h" +struct sockaddr_storage; + /** * Very simplistic and minimal URL helper class for RetroShare, after looking * for a small and self-contained C/C++ URL parsing and manipulation library, @@ -36,7 +38,8 @@ struct RsUrl : RsSerializable { RsUrl(); - RsUrl(const std::string& urlStr); + explicit RsUrl(const std::string& urlStr); + explicit RsUrl(const sockaddr_storage& ssas); RsUrl& fromString(const std::string& urlStr); std::string toString() const;