refactor: tr_urlIsValid*() now takes a std::string_view (#2078)
* refactor: tr_urlIsValid*() now take a string_view arg
This commit is contained in:
parent
da51a17c30
commit
feaf12a205
|
@ -470,7 +470,7 @@ static char* fix_webseed_url(tr_info const* inf, char const* url_in)
|
||||||
tr_strstrip(url);
|
tr_strstrip(url);
|
||||||
size_t const len = strlen(url);
|
size_t const len = strlen(url);
|
||||||
|
|
||||||
if (tr_urlIsValid(url, len))
|
if (tr_urlIsValid(url))
|
||||||
{
|
{
|
||||||
if (inf->fileCount > 1 && len > 0 && url[len - 1] != '/')
|
if (inf->fileCount > 1 && len > 0 && url[len - 1] != '/')
|
||||||
{
|
{
|
||||||
|
|
|
@ -211,7 +211,7 @@ static void handle_upload(struct evhttp_request* req, struct tr_rpc_server* serv
|
||||||
|
|
||||||
auto test = tr_variant{};
|
auto test = tr_variant{};
|
||||||
auto have_source = bool{ false };
|
auto have_source = bool{ false };
|
||||||
if (tr_urlIsValid(body.c_str(), body_len))
|
if (tr_urlIsValid({ body.c_str(), body_len }))
|
||||||
{
|
{
|
||||||
tr_variantDictAddRaw(args, TR_KEY_filename, body.c_str(), body_len);
|
tr_variantDictAddRaw(args, TR_KEY_filename, body.c_str(), body_len);
|
||||||
have_source = true;
|
have_source = true;
|
||||||
|
|
|
@ -810,63 +810,6 @@ void tr_hex_to_binary(void const* vinput, void* voutput, size_t byte_length)
|
||||||
****
|
****
|
||||||
***/
|
***/
|
||||||
|
|
||||||
static bool isValidURLChars(char const* url, size_t url_len)
|
|
||||||
{
|
|
||||||
static char const rfc2396_valid_chars
|
|
||||||
[] = "abcdefghijklmnopqrstuvwxyz" /* lowalpha */
|
|
||||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" /* upalpha */
|
|
||||||
"0123456789" /* digit */
|
|
||||||
"-_.!~*'()" /* mark */
|
|
||||||
";/?:@&=+$," /* reserved */
|
|
||||||
"<>#%<\"" /* delims */
|
|
||||||
"{}|\\^[]`"; /* unwise */
|
|
||||||
|
|
||||||
if (url == nullptr)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (char const *c = url, *end = url + url_len; c < end && *c != '\0'; ++c)
|
|
||||||
{
|
|
||||||
if (memchr(rfc2396_valid_chars, *c, sizeof(rfc2396_valid_chars) - 1) == nullptr)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool tr_urlIsValidTracker(char const* url)
|
|
||||||
{
|
|
||||||
if (url == nullptr)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t const url_len = strlen(url);
|
|
||||||
|
|
||||||
return isValidURLChars(url, url_len) && tr_urlParse({ url, url_len }) &&
|
|
||||||
(memcmp(url, "http://", 7) == 0 || memcmp(url, "https://", 8) == 0 || memcmp(url, "udp://", 6) == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool tr_urlIsValid(char const* url, size_t url_len)
|
|
||||||
{
|
|
||||||
if (url == nullptr)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (url_len == TR_BAD_SIZE)
|
|
||||||
{
|
|
||||||
url_len = strlen(url);
|
|
||||||
}
|
|
||||||
|
|
||||||
return isValidURLChars(url, url_len) && tr_urlParse({ url, url_len }) &&
|
|
||||||
(memcmp(url, "http://", 7) == 0 || memcmp(url, "https://", 8) == 0 || memcmp(url, "ftp://", 6) == 0 ||
|
|
||||||
memcmp(url, "sftp://", 7) == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool tr_addressIsIP(char const* str)
|
bool tr_addressIsIP(char const* str)
|
||||||
{
|
{
|
||||||
tr_address tmp;
|
tr_address tmp;
|
||||||
|
@ -914,8 +857,30 @@ static std::string_view getPortForScheme(std::string_view scheme)
|
||||||
return "-1"sv;
|
return "-1"sv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool urlCharsAreValid(std::string_view url)
|
||||||
|
{
|
||||||
|
// rfc2396
|
||||||
|
auto constexpr ValidChars = std::string_view{
|
||||||
|
"abcdefghijklmnopqrstuvwxyz" // lowalpha
|
||||||
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" // upalpha
|
||||||
|
"0123456789" // digit
|
||||||
|
"-_.!~*'()" // mark
|
||||||
|
";/?:@&=+$," // reserved
|
||||||
|
"<>#%<\"" // delims
|
||||||
|
"{}|\\^[]`" // unwise
|
||||||
|
};
|
||||||
|
|
||||||
|
return !std::empty(url) &&
|
||||||
|
std::all_of(std::begin(url), std::end(url), [&ValidChars](auto ch) { return ValidChars.find(ch) != ValidChars.npos; });
|
||||||
|
}
|
||||||
|
|
||||||
std::optional<tr_parsed_url_t> tr_urlParse(std::string_view url)
|
std::optional<tr_parsed_url_t> tr_urlParse(std::string_view url)
|
||||||
{
|
{
|
||||||
|
if (!urlCharsAreValid(url))
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
// scheme
|
// scheme
|
||||||
auto key = "://"sv;
|
auto key = "://"sv;
|
||||||
auto pos = url.find(key);
|
auto pos = url.find(key);
|
||||||
|
@ -953,6 +918,20 @@ std::optional<tr_parsed_url_t> tr_urlParse(std::string_view url)
|
||||||
return tr_parsed_url_t{ scheme, host, path, portstr, port };
|
return tr_parsed_url_t{ scheme, host, path, portstr, port };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool tr_urlIsValidTracker(std::string_view url)
|
||||||
|
{
|
||||||
|
auto constexpr Schemes = std::array<std::string_view, 3>{ "http"sv, "https"sv, "udp"sv };
|
||||||
|
auto const parsed = tr_urlParse(url);
|
||||||
|
return parsed && std::find(std::begin(Schemes), std::end(Schemes), parsed->scheme) != std::end(Schemes);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool tr_urlIsValid(std::string_view url)
|
||||||
|
{
|
||||||
|
auto constexpr Schemes = std::array<std::string_view, 5>{ "http"sv, "https"sv, "ftp"sv, "sftp"sv, "udp"sv };
|
||||||
|
auto const parsed = tr_urlParse(url);
|
||||||
|
return parsed && std::find(std::begin(Schemes), std::end(Schemes), parsed->scheme) != std::end(Schemes);
|
||||||
|
}
|
||||||
|
|
||||||
bool tr_urlParse(char const* url, size_t url_len, char** setme_scheme, char** setme_host, int* setme_port, char** setme_path)
|
bool tr_urlParse(char const* url, size_t url_len, char** setme_scheme, char** setme_host, int* setme_port, char** setme_path)
|
||||||
{
|
{
|
||||||
if (url_len == TR_BAD_SIZE)
|
if (url_len == TR_BAD_SIZE)
|
||||||
|
|
|
@ -281,10 +281,10 @@ void tr_hex_to_binary(void const* input, void* output, size_t byte_length) TR_GN
|
||||||
bool tr_addressIsIP(char const* address);
|
bool tr_addressIsIP(char const* address);
|
||||||
|
|
||||||
/** @brief return true if the url is a http or https or UDP url that Transmission understands */
|
/** @brief return true if the url is a http or https or UDP url that Transmission understands */
|
||||||
bool tr_urlIsValidTracker(char const* url);
|
bool tr_urlIsValidTracker(std::string_view url);
|
||||||
|
|
||||||
/** @brief return true if the url is a [ http, https, ftp, sftp ] url that Transmission understands */
|
/** @brief return true if the url is a [ http, https, ftp, sftp ] url that Transmission understands */
|
||||||
bool tr_urlIsValid(char const* url, size_t url_len);
|
bool tr_urlIsValid(std::string_view url);
|
||||||
|
|
||||||
struct tr_parsed_url_t
|
struct tr_parsed_url_t
|
||||||
{
|
{
|
||||||
|
|
|
@ -296,6 +296,19 @@ TEST_F(UtilsTest, url)
|
||||||
EXPECT_EQ("/some/path"sv, parsed->path);
|
EXPECT_EQ("/some/path"sv, parsed->path);
|
||||||
EXPECT_EQ("8080"sv, parsed->portstr);
|
EXPECT_EQ("8080"sv, parsed->portstr);
|
||||||
EXPECT_EQ(8080, parsed->port);
|
EXPECT_EQ(8080, parsed->port);
|
||||||
|
|
||||||
|
EXPECT_FALSE(tr_urlIsValid("hello world"sv));
|
||||||
|
EXPECT_FALSE(tr_urlIsValid("http://www.💩.com/announce/"sv));
|
||||||
|
EXPECT_TRUE(tr_urlIsValid("http://www.example.com/announce/"sv));
|
||||||
|
EXPECT_FALSE(tr_urlIsValid(""sv));
|
||||||
|
EXPECT_FALSE(tr_urlIsValid("com"sv));
|
||||||
|
EXPECT_FALSE(tr_urlIsValid("www.example.com"sv));
|
||||||
|
EXPECT_FALSE(tr_urlIsValid("://www.example.com"sv));
|
||||||
|
EXPECT_FALSE(tr_urlIsValid("zzz://www.example.com"sv)); // syntactically valid, but unsupported scheme
|
||||||
|
EXPECT_TRUE(tr_urlIsValid("https://www.example.com"sv));
|
||||||
|
|
||||||
|
EXPECT_TRUE(tr_urlIsValid("sftp://www.example.com"sv));
|
||||||
|
EXPECT_FALSE(tr_urlIsValidTracker("sftp://www.example.com"sv)); // unsupported tracker scheme
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(UtilsTest, trHttpUnescape)
|
TEST_F(UtilsTest, trHttpUnescape)
|
||||||
|
|
Loading…
Reference in New Issue