diff --git a/libtransmission/announcer-http.cc b/libtransmission/announcer-http.cc index 8040d25c6..013dc907f 100644 --- a/libtransmission/announcer-http.cc +++ b/libtransmission/announcer-http.cc @@ -132,8 +132,8 @@ static tr_pex* listToPex(tr_variant* peerList, size_t* setme_len) continue; } - char const* ip = nullptr; - if (!tr_variantDictFindStr(peer, TR_KEY_ip, &ip, nullptr)) + auto ip = std::string_view{}; + if (!tr_variantDictFindStrView(peer, TR_KEY_ip, &ip)) { continue; } diff --git a/libtransmission/net.cc b/libtransmission/net.cc index b7ff39a0e..f865201e2 100644 --- a/libtransmission/net.cc +++ b/libtransmission/net.cc @@ -20,6 +20,7 @@ * DEALINGS IN THE SOFTWARE. *****************************************************************************/ +#include #include #include #include @@ -108,20 +109,35 @@ char const* tr_address_to_string(tr_address const* addr) bool tr_address_from_string(tr_address* dst, char const* src) { - bool success = false; - if (evutil_inet_pton(AF_INET, src, &dst->addr) == 1) { dst->type = TR_AF_INET; - success = true; - } - else if (evutil_inet_pton(AF_INET6, src, &dst->addr) == 1) - { - dst->type = TR_AF_INET6; - success = true; + return true; } - return success; + if (evutil_inet_pton(AF_INET6, src, &dst->addr) == 1) + { + dst->type = TR_AF_INET6; + return true; + } + + return false; +} + +bool tr_address_from_string(tr_address* dst, std::string_view src) +{ + // inet_pton() requires zero-terminated strings, + // so make a zero-terminated copy here on the stack. + auto buf = std::array{}; + if (std::size(src) >= std::size(buf)) + { + // shouldn't ever be that large; malformed address + return false; + } + + *std::copy(std::begin(src), std::end(src), std::begin(buf)) = '\0'; + + return tr_address_from_string(dst, std::data(buf)); } /* diff --git a/libtransmission/net.h b/libtransmission/net.h index 60aaf38a5..9a69e92d4 100644 --- a/libtransmission/net.h +++ b/libtransmission/net.h @@ -26,6 +26,8 @@ #error only libtransmission should #include this header. #endif +#include + #ifdef _WIN32 #include #include @@ -104,6 +106,8 @@ char const* tr_address_and_port_to_string(char* buf, size_t buflen, tr_address c bool tr_address_from_string(tr_address* setme, char const* string); +bool tr_address_from_string(tr_address* dst, std::string_view src); + bool tr_address_from_sockaddr_storage(tr_address* setme, tr_port* port, struct sockaddr_storage const* src); int tr_address_compare(tr_address const* a, tr_address const* b); diff --git a/libtransmission/rpcimpl.cc b/libtransmission/rpcimpl.cc index c2fd6a77a..cdd38a473 100644 --- a/libtransmission/rpcimpl.cc +++ b/libtransmission/rpcimpl.cc @@ -1694,14 +1694,11 @@ static void gotMetadataFromURL( tr_free(data); } -static bool isCurlURL(char const* filename) +static bool isCurlURL(std::string_view url) { - if (filename == nullptr) - { - return false; - } - - return strncmp(filename, "ftp://", 6) == 0 || strncmp(filename, "http://", 7) == 0 || strncmp(filename, "https://", 8) == 0; + auto constexpr Schemes = std::array{ "http"sv, "https"sv, "ftp"sv, "sftp"sv }; + auto const parsed = tr_urlParse(url); + return parsed && std::find(std::begin(Schemes), std::end(Schemes), parsed->scheme) != std::end(Schemes); } static auto fileListFromList(tr_variant* list) @@ -1727,13 +1724,13 @@ static char const* torrentAdd(tr_session* session, tr_variant* args_in, tr_varia { TR_ASSERT(idle_data != nullptr); - char const* filename = nullptr; - (void)tr_variantDictFindStr(args_in, TR_KEY_filename, &filename, nullptr); + auto filename = std::string_view{}; + (void)tr_variantDictFindStrView(args_in, TR_KEY_filename, &filename); - char const* metainfo_base64 = nullptr; - (void)tr_variantDictFindStr(args_in, TR_KEY_metainfo, &metainfo_base64, nullptr); + auto metainfo_base64 = std::string_view{}; + (void)tr_variantDictFindStrView(args_in, TR_KEY_metainfo, &metainfo_base64); - if (filename == nullptr && metainfo_base64 == nullptr) + if (std::empty(filename) && std::empty(metainfo_base64)) { return "no filename or metainfo specified"; } @@ -1805,38 +1802,38 @@ static char const* torrentAdd(tr_session* session, tr_variant* args_in, tr_varia tr_ctorSetFilePriorities(ctor, std::data(files), std::size(files), TR_PRI_HIGH); } - dbgmsg("torrentAdd: filename is \"%s\"", filename ? filename : " (null)"); + dbgmsg("torrentAdd: filename is \"%" TR_PRIsv "\"", TR_PRIsv_ARG(filename)); if (isCurlURL(filename)) { - struct add_torrent_idle_data* d = tr_new0(struct add_torrent_idle_data, 1); + auto* const d = tr_new0(struct add_torrent_idle_data, 1); d->data = idle_data; d->ctor = ctor; tr_webRunWithCookies(session, filename, cookies, gotMetadataFromURL, d); } else { - char* fname = tr_strdup(filename); - - if (fname == nullptr) + if (std::empty(filename)) { - auto len = size_t{}; - auto* const metainfo = static_cast(tr_base64_decode_str(metainfo_base64, &len)); - tr_ctorSetMetainfo(ctor, (uint8_t*)metainfo, len); - tr_free(metainfo); - } - else if (strncmp(fname, "magnet:?", 8) == 0) - { - tr_ctorSetMetainfoFromMagnetLink(ctor, fname); + std::string const metainfo = tr_base64_decode_str(metainfo_base64); + tr_ctorSetMetainfo(ctor, std::data(metainfo), std::size(metainfo)); } else { - tr_ctorSetMetainfoFromFile(ctor, fname); + // these two tr_ctorSet*() functions require zero-terminated strings + auto const filename_str = std::string{ filename }; + + if (tr_strvStartsWith(filename, "magnet:?"sv)) + { + tr_ctorSetMetainfoFromMagnetLink(ctor, filename_str.c_str()); + } + else + { + tr_ctorSetMetainfoFromFile(ctor, filename_str.c_str()); + } } addTorrentImpl(idle_data, ctor); - - tr_free(fname); } return nullptr; diff --git a/libtransmission/session.cc b/libtransmission/session.cc index f72969955..137f998b6 100644 --- a/libtransmission/session.cc +++ b/libtransmission/session.cc @@ -941,8 +941,8 @@ static void sessionSetImpl(void* vdata) free_incoming_peer_port(session); - if (!tr_variantDictFindStr(settings, TR_KEY_bind_address_ipv4, &strVal, nullptr) || - !tr_address_from_string(&b.addr, strVal) || b.addr.type != TR_AF_INET) + if (!tr_variantDictFindStrView(settings, TR_KEY_bind_address_ipv4, &sv) || !tr_address_from_string(&b.addr, sv) || + b.addr.type != TR_AF_INET) { b.addr = tr_inaddr_any; } @@ -950,8 +950,8 @@ static void sessionSetImpl(void* vdata) b.socket = TR_BAD_SOCKET; session->bind_ipv4 = static_cast(tr_memdup(&b, sizeof(struct tr_bindinfo))); - if (!tr_variantDictFindStr(settings, TR_KEY_bind_address_ipv6, &strVal, nullptr) || - !tr_address_from_string(&b.addr, strVal) || b.addr.type != TR_AF_INET6) + if (!tr_variantDictFindStrView(settings, TR_KEY_bind_address_ipv6, &sv) || !tr_address_from_string(&b.addr, sv) || + b.addr.type != TR_AF_INET6) { b.addr = tr_in6addr_any; }