fix: some torrents think they are magnets (#5025)

This commit is contained in:
Charles Kerr 2023-02-25 07:11:19 -06:00 committed by GitHub
parent 81f8ceb0f9
commit 47fd150bab
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 77 additions and 49 deletions

View File

@ -1340,39 +1340,65 @@ namespace
{
namespace load_torrents_helpers
{
void session_load_torrents(tr_session* session, tr_ctor* ctor, std::promise<size_t>* loaded_promise)
[[nodiscard]] std::vector<std::string> get_matching_files(
std::string const& folder,
std::function<bool(std::string_view)> const& test)
{
auto const& dirname = session->torrentDir();
auto const info = tr_sys_path_get_info(dirname);
auto const odir = info && info->isFolder() ? tr_sys_dir_open(dirname.c_str()) : TR_BAD_SYS_DIR;
auto n_torrents = size_t{};
if (odir != TR_BAD_SYS_DIR)
if (auto const info = tr_sys_path_get_info(folder); !info || !info->isFolder())
{
char const* name = nullptr;
while ((name = tr_sys_dir_read_name(odir)) != nullptr)
return {};
}
auto const odir = tr_sys_dir_open(folder.c_str());
if (odir == TR_BAD_SYS_DIR)
{
return {};
}
auto filenames = std::vector<std::string>{};
for (;;)
{
char const* const name = tr_sys_dir_read_name(odir);
if (name == nullptr)
{
if (!tr_strvEndsWith(name, ".torrent"sv) && !tr_strvEndsWith(name, ".magnet"sv))
{
continue;
}
// is a magnet link?
if (auto const path = tr_pathbuf{ dirname, '/', name }; !tr_ctorSetMetainfoFromFile(ctor, path.sv(), nullptr))
{
if (auto buf = std::vector<char>{}; tr_loadFile(path, buf))
{
tr_ctorSetMetainfoFromMagnetLink(ctor, std::string_view{ std::data(buf), std::size(buf) }, nullptr);
}
}
if (tr_torrentNew(ctor, nullptr) != nullptr)
{
++n_torrents;
}
tr_sys_dir_close(odir);
return filenames;
}
tr_sys_dir_close(odir);
if (test(name))
{
filenames.emplace_back(name);
}
}
}
void session_load_torrents(tr_session* session, tr_ctor* ctor, std::promise<size_t>* loaded_promise)
{
auto n_torrents = size_t{};
auto const& folder = session->torrentDir();
for (auto const& name : get_matching_files(folder, [](auto const& name) { return tr_strvEndsWith(name, ".torrent"sv); }))
{
auto const path = tr_pathbuf{ folder, '/', name };
if (tr_ctorSetMetainfoFromFile(ctor, path.sv(), nullptr) && tr_torrentNew(ctor, nullptr) != nullptr)
{
++n_torrents;
}
}
auto buf = std::vector<char>{};
for (auto const& name : get_matching_files(folder, [](auto const& name) { return tr_strvEndsWith(name, ".magnet"sv); }))
{
auto const path = tr_pathbuf{ folder, '/', name };
if (tr_loadFile(path, buf) &&
tr_ctorSetMetainfoFromMagnetLink(ctor, std::string_view{ std::data(buf), std::size(buf) }, nullptr) &&
tr_torrentNew(ctor, nullptr) != nullptr)
{
++n_torrents;
}
}
if (n_torrents != 0U)

View File

@ -510,12 +510,6 @@ private:
bool finish(Context const& context)
{
// Support Transmission <= 3.0 magnets stored in torrent format.
if (tm_.has_magnet_info_hash_)
{
return true;
}
// bittorrent 1.0 spec
// http://bittorrent.org/beps/bep_0003.html
//
@ -529,26 +523,34 @@ private:
tm_.files_.add(tm_.name_, length_);
}
if (tm_.fileCount() == 0)
if (auto const has_metainfo = tm_.infoDictSize() != 0U; has_metainfo)
{
if (!tr_error_is_set(context.error))
// do some sanity checks to make sure the torrent looks sane
if (tm_.fileCount() == 0)
{
tr_error_set(context.error, EINVAL, "no files found");
if (!tr_error_is_set(context.error))
{
tr_error_set(context.error, EINVAL, "no files found");
}
return false;
}
return false;
if (piece_size_ == 0)
{
if (!tr_error_is_set(context.error))
{
tr_error_set(context.error, EINVAL, fmt::format("invalid piece size: {}", piece_size_));
}
return false;
}
tm_.block_info_.initSizes(tm_.files_.totalSize(), piece_size_);
return true;
}
if (piece_size_ == 0)
{
if (!tr_error_is_set(context.error))
{
tr_error_set(context.error, EINVAL, fmt::format("invalid piece size: {}", piece_size_));
}
return false;
}
tm_.block_info_.initSizes(tm_.files_.totalSize(), piece_size_);
return true;
// no metainfo; might be a Transmission 3.00-style magnet file
auto const ok = tm_.has_magnet_info_hash_;
return ok;
}
static constexpr std::string_view AcodecKey = "acodec"sv;