diff --git a/libtransmission/session.cc b/libtransmission/session.cc index c34401662..f91ff5f97 100644 --- a/libtransmission/session.cc +++ b/libtransmission/session.cc @@ -1340,39 +1340,65 @@ namespace { namespace load_torrents_helpers { -void session_load_torrents(tr_session* session, tr_ctor* ctor, std::promise* loaded_promise) +[[nodiscard]] std::vector get_matching_files( + std::string const& folder, + std::function 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{}; + 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{}; 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* 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{}; + 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) diff --git a/libtransmission/torrent-metainfo.cc b/libtransmission/torrent-metainfo.cc index c92c7423d..9edf34382 100644 --- a/libtransmission/torrent-metainfo.cc +++ b/libtransmission/torrent-metainfo.cc @@ -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;