implemented support magnet URI extension, select specific file indices for download, BEP53 (#2578)
This commit is contained in:
parent
28f096e94e
commit
163d13e1d2
|
@ -1,3 +1,5 @@
|
|||
* implemented support magnet URI extension, select specific file indices
|
||||
for download, BEP53
|
||||
* make tracker keys multi-homed. remove set_key() function on session.
|
||||
* add API to query whether alerts have been dropped or not
|
||||
* add flags()/set_flags()/unset_flags() to torrent_handle, deprecate individual functions
|
||||
|
|
|
@ -51,6 +51,8 @@ extensions
|
|||
scale well with the size of the content.
|
||||
* share-mode. This is a special mode torrents can be put in to optimize share
|
||||
ratio rather than downloading the torrent.
|
||||
* supports the Magnet URI extension - Select specific file indices for
|
||||
download. `BEP 53`_.
|
||||
|
||||
.. _article: utp.html
|
||||
.. _extensions: manual-ref.html#extensions
|
||||
|
|
|
@ -48,4 +48,3 @@ constexpr download_priority_t top_priority{7};
|
|||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -258,6 +258,65 @@ namespace libtorrent {
|
|||
return p;
|
||||
}
|
||||
|
||||
auto select_pos = std::string::npos;
|
||||
string_view select = url_has_argument(uri, "so", &select_pos);
|
||||
while (!select.empty())
|
||||
{
|
||||
// parse the ranges or indices
|
||||
do
|
||||
{
|
||||
// accept only digits, '-' and ','
|
||||
if (std::any_of(select.begin(), select.end(), [](char c)
|
||||
{ return !is_digit(c) && c != '-' && c != ','; }))
|
||||
break;
|
||||
|
||||
string_view token;
|
||||
std::tie(token, select) = split_string(select, ',');
|
||||
|
||||
int idx1, idx2;
|
||||
// TODO: what's the right number here?
|
||||
constexpr int max_index = 10000; // can't risk out of memory
|
||||
|
||||
auto const divider = token.find_first_of('-');
|
||||
if (divider != std::string::npos) // it's a range
|
||||
{
|
||||
if (divider == 0) // no start index
|
||||
continue;
|
||||
if (divider == token.size() - 1) // no end index
|
||||
continue;
|
||||
|
||||
idx1 = std::atoi(token.substr(0, divider).to_string().c_str());
|
||||
if (idx1 < 0 || idx1 > max_index) // invalid index
|
||||
continue;
|
||||
idx2 = std::atoi(token.substr(divider + 1).to_string().c_str());
|
||||
if (idx2 < 0 || idx2 > max_index) // invalid index
|
||||
continue;
|
||||
|
||||
if (idx1 > idx2) // wrong range limits
|
||||
continue;
|
||||
}
|
||||
else // it's an index
|
||||
{
|
||||
idx1 = std::atoi(token.to_string().c_str());
|
||||
if (idx1 < 0 || idx1 > max_index) // invalid index
|
||||
continue;
|
||||
idx2 = idx1;
|
||||
}
|
||||
|
||||
if (int(p.file_priorities.size()) <= idx2)
|
||||
p.file_priorities.resize(std::size_t(idx2 + 1), dont_download);
|
||||
|
||||
for (int i = idx1; i <= idx2; i++)
|
||||
p.file_priorities[std::size_t(i)] = default_priority;
|
||||
|
||||
} while (!select.empty());
|
||||
|
||||
select_pos = find(uri, "&so=", select_pos);
|
||||
if (select_pos == std::string::npos) break;
|
||||
select_pos += 4;
|
||||
select = uri.substr(select_pos, find(uri, "&", select_pos) - select_pos);
|
||||
}
|
||||
|
||||
std::string::size_type peer_pos = std::string::npos;
|
||||
string_view peer = url_has_argument(uri, "x.pe", &peer_pos);
|
||||
while (!peer.empty())
|
||||
|
@ -265,7 +324,7 @@ namespace libtorrent {
|
|||
error_code e;
|
||||
tcp::endpoint endp = parse_endpoint(peer, e);
|
||||
if (!e)
|
||||
p.peers.push_back(endp);
|
||||
p.peers.push_back(std::move(endp));
|
||||
|
||||
peer_pos = find(uri, "&x.pe=", peer_pos);
|
||||
if (peer_pos == std::string::npos) break;
|
||||
|
@ -278,12 +337,12 @@ namespace libtorrent {
|
|||
string_view node = url_has_argument(uri, "dht", &node_pos);
|
||||
while (!node.empty())
|
||||
{
|
||||
std::string::size_type divider = node.find_last_of(':');
|
||||
std::string::size_type const divider = node.find_last_of(':');
|
||||
if (divider != std::string::npos)
|
||||
{
|
||||
int port = atoi(node.substr(divider + 1).to_string().c_str());
|
||||
if (port != 0)
|
||||
p.dht_nodes.push_back(std::make_pair(node.substr(0, divider).to_string(), port));
|
||||
int const port = std::atoi(node.substr(divider + 1).to_string().c_str());
|
||||
if (port > 0 && port < int(std::numeric_limits<std::uint16_t>::max()))
|
||||
p.dht_nodes.emplace_back(node.substr(0, divider).to_string(), port);
|
||||
}
|
||||
|
||||
node_pos = find(uri, "&dht=", node_pos);
|
||||
|
@ -297,7 +356,7 @@ namespace libtorrent {
|
|||
if (btih.size() == 40 + 9) aux::from_hex({&btih[9], 40}, info_hash.data());
|
||||
else if (btih.size() == 32 + 9)
|
||||
{
|
||||
std::string ih = base32decode(btih.substr(9));
|
||||
std::string const ih = base32decode(btih.substr(9));
|
||||
if (ih.size() != 20)
|
||||
{
|
||||
ec = errors::invalid_info_hash;
|
||||
|
|
|
@ -476,3 +476,128 @@ TORRENT_TEST(invalid_web_seed_escaping)
|
|||
TEST_CHECK(ec);
|
||||
}
|
||||
|
||||
TORRENT_TEST(parse_magnet_select_only)
|
||||
{
|
||||
error_code ec;
|
||||
add_torrent_params p = parse_magnet_uri("magnet:?xt=urn:btih:cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"
|
||||
"&dn=foo&so=0,2,4,6-8", ec);
|
||||
TEST_CHECK(!ec);
|
||||
|
||||
auto const yes = default_priority;
|
||||
auto const no = dont_download;
|
||||
std::vector<download_priority_t> result = std::vector<download_priority_t>
|
||||
{yes, no, yes, no, yes, no, yes, yes, yes};
|
||||
TEST_CHECK(p.file_priorities == result);
|
||||
}
|
||||
|
||||
TORRENT_TEST(parse_magnet_select_only_overlap_range)
|
||||
{
|
||||
error_code ec;
|
||||
add_torrent_params p = parse_magnet_uri("magnet:?xt=urn:btih:cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"
|
||||
"&dn=foo&so=0,2-4,3-5&dht=10.0.0.1:1337", ec);
|
||||
TEST_CHECK(!ec);
|
||||
|
||||
auto const yes = default_priority;
|
||||
auto const no = dont_download;
|
||||
std::vector<download_priority_t> result = std::vector<download_priority_t>
|
||||
{yes, no, yes, yes, yes, yes};
|
||||
TEST_CHECK(p.file_priorities == result);
|
||||
}
|
||||
|
||||
TORRENT_TEST(parse_magnet_select_only_multiple)
|
||||
{
|
||||
error_code ec;
|
||||
add_torrent_params p = parse_magnet_uri("magnet:?xt=urn:btih:cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"
|
||||
"&dn=foo&so=2-4&dht=10.0.0.1:1337&so=1", ec);
|
||||
TEST_CHECK(!ec);
|
||||
|
||||
auto const yes = default_priority;
|
||||
auto const no = dont_download;
|
||||
std::vector<download_priority_t> result = std::vector<download_priority_t>
|
||||
{no, yes, yes, yes, yes};
|
||||
TEST_CHECK(p.file_priorities == result);
|
||||
}
|
||||
|
||||
TORRENT_TEST(parse_magnet_select_only_invalid_index_and_range)
|
||||
{
|
||||
error_code ec;
|
||||
add_torrent_params p = parse_magnet_uri("magnet:?xt=urn:btih:cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"
|
||||
"&dn=foo&so=-4,3-,7-4,a,100000000&dht=10.0.0.1:1337&so=10", ec);
|
||||
TEST_CHECK(!ec);
|
||||
|
||||
auto const yes = default_priority;
|
||||
auto const no = dont_download;
|
||||
std::vector<download_priority_t> result = std::vector<download_priority_t>
|
||||
{no, no, no, no, no, no, no, no, no, no, yes};
|
||||
TEST_CHECK(p.file_priorities == result);
|
||||
}
|
||||
|
||||
TORRENT_TEST(parse_magnet_select_only_invalid_range1)
|
||||
{
|
||||
error_code ec;
|
||||
add_torrent_params p = parse_magnet_uri("magnet:?xt=urn:btih:cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"
|
||||
"&dn=foo&so=-4", ec);
|
||||
TEST_CHECK(!ec);
|
||||
|
||||
TEST_CHECK(p.file_priorities.empty());
|
||||
}
|
||||
|
||||
TORRENT_TEST(parse_magnet_select_only_invalid_range2)
|
||||
{
|
||||
error_code ec;
|
||||
add_torrent_params p = parse_magnet_uri("magnet:?xt=urn:btih:cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"
|
||||
"&dn=foo&so=3-", ec);
|
||||
TEST_CHECK(!ec);
|
||||
|
||||
TEST_CHECK(p.file_priorities.empty());
|
||||
}
|
||||
|
||||
TORRENT_TEST(parse_magnet_select_only_invalid_range3)
|
||||
{
|
||||
error_code ec;
|
||||
add_torrent_params p = parse_magnet_uri("magnet:?xt=urn:btih:cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"
|
||||
"&dn=foo&so=7-4", ec);
|
||||
TEST_CHECK(!ec);
|
||||
|
||||
TEST_CHECK(p.file_priorities.empty());
|
||||
}
|
||||
|
||||
TORRENT_TEST(parse_magnet_select_only_invalid_index_character)
|
||||
{
|
||||
error_code ec;
|
||||
add_torrent_params p = parse_magnet_uri("magnet:?xt=urn:btih:cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"
|
||||
"&dn=foo&so=a", ec);
|
||||
TEST_CHECK(!ec);
|
||||
|
||||
TEST_CHECK(p.file_priorities.empty());
|
||||
}
|
||||
|
||||
TORRENT_TEST(parse_magnet_select_only_invalid_index_value)
|
||||
{
|
||||
error_code ec;
|
||||
add_torrent_params p = parse_magnet_uri("magnet:?xt=urn:btih:cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"
|
||||
"&dn=foo&so=100000000", ec);
|
||||
TEST_CHECK(!ec);
|
||||
|
||||
TEST_CHECK(p.file_priorities.empty());
|
||||
}
|
||||
|
||||
TORRENT_TEST(parse_magnet_select_only_invalid_no_values)
|
||||
{
|
||||
error_code ec;
|
||||
add_torrent_params p = parse_magnet_uri("magnet:?xt=urn:btih:cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"
|
||||
"&dn=foo&so=&dht=10.0.0.1:1337&so=", ec);
|
||||
TEST_CHECK(!ec);
|
||||
|
||||
TEST_CHECK(p.file_priorities.empty());
|
||||
}
|
||||
|
||||
TORRENT_TEST(parse_magnet_select_only_invalid_quotes)
|
||||
{
|
||||
error_code ec;
|
||||
add_torrent_params p = parse_magnet_uri("magnet:?xt=urn:btih:cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"
|
||||
"&dn=foo&so=\"1,2\"", ec);
|
||||
TEST_CHECK(!ec);
|
||||
|
||||
TEST_CHECK(p.file_priorities.empty());
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue