From 7f01ee52fe901994713441defa9d28644e83aa10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?A=20C=C5=93ur?= Date: Wed, 22 Jun 2022 05:47:57 +0800 Subject: [PATCH] Set torrent file's metainfo for magnets (#3322) --- libtransmission/torrent-magnet.cc | 34 +++++++++++++++++++++++++++++++ libtransmission/torrent-magnet.h | 7 +++++++ libtransmission/torrent.cc | 27 ++++++++++++++++++++++-- libtransmission/transmission.h | 7 +++++++ macosx/Controller.h | 6 ------ macosx/Controller.mm | 13 ++++++++++-- 6 files changed, 84 insertions(+), 10 deletions(-) diff --git a/libtransmission/torrent-magnet.cc b/libtransmission/torrent-magnet.cc index 02cd6b73c..c34ec077d 100644 --- a/libtransmission/torrent-magnet.cc +++ b/libtransmission/torrent-magnet.cc @@ -236,6 +236,40 @@ static void tr_buildMetainfoExceptInfoDict(tr_torrent_metainfo const& tm, tr_var } } +bool tr_torrentUseMetainfoFromFile( + tr_torrent* tor, + tr_torrent_metainfo const* metainfo, + char const* filename_in, + tr_error** error) +{ + // add .torrent file + if (!tr_sys_path_copy(filename_in, tor->torrentFile(), error)) + { + return false; + } + + // remove .magnet file + tr_sys_path_remove(tor->magnetFile()); + + // tor should keep this metainfo + tor->setMetainfo(*metainfo); + + if (tor->incompleteMetadata) + { + incompleteMetadataFree(tor->incompleteMetadata); + tor->incompleteMetadata = nullptr; + } + tor->isStopping = true; + tor->magnetVerify = true; + if (tr_sessionGetPaused(tor->session)) + { + tor->startAfterVerify = false; + } + tor->markEdited(); + + return true; +} + static bool useNewMetainfo(tr_torrent* tor, tr_incomplete_metadata const* m, tr_error** error) { // test the info_dict checksum diff --git a/libtransmission/torrent-magnet.h b/libtransmission/torrent-magnet.h index 7613add54..713cc1aa5 100644 --- a/libtransmission/torrent-magnet.h +++ b/libtransmission/torrent-magnet.h @@ -16,6 +16,7 @@ #include "transmission.h" struct tr_torrent; +struct tr_torrent_metainfo; // defined by BEP #9 inline constexpr int METADATA_PIECE_SIZE = 1024 * 16; @@ -29,3 +30,9 @@ bool tr_torrentGetNextMetadataRequest(tr_torrent* tor, time_t now, int* setme); bool tr_torrentSetMetadataSizeHint(tr_torrent* tor, int64_t metadata_size); double tr_torrentGetMetadataPercent(tr_torrent const* tor); + +bool tr_torrentUseMetainfoFromFile( + tr_torrent* tor, + tr_torrent_metainfo const* metainfo, + char const* filename, + tr_error** error); diff --git a/libtransmission/torrent.cc b/libtransmission/torrent.cc index 7dc228261..008567fdc 100644 --- a/libtransmission/torrent.cc +++ b/libtransmission/torrent.cc @@ -111,6 +111,31 @@ tr_torrent* tr_torrentFindFromObfuscatedHash(tr_session* session, tr_sha1_digest return nullptr; } +bool tr_torrentSetMetainfoFromFile(tr_torrent* tor, tr_torrent_metainfo* metainfo, char const* filename) +{ + if (tr_torrentHasMetadata(tor)) + { + return false; + } + + tr_error* error = nullptr; + tr_torrentUseMetainfoFromFile(tor, metainfo, filename, &error); + + if (error != nullptr) + { + tor->setLocalError(fmt::format( + _("Couldn't use metaInfo from '{path}' for '{magnet}': {error} ({error_code})"), + fmt::arg("path", filename), + fmt::arg("magnet", tor->magnet()), + fmt::arg("error", error->message), + fmt::arg("error_code", error->code))); + tr_error_clear(&error); + return false; + } + + return true; +} + bool tr_torrent::isPieceTransferAllowed(tr_direction direction) const { TR_ASSERT(tr_isDirection(direction)); @@ -816,8 +841,6 @@ static void torrentInit(tr_torrent* tor, tr_ctor const* ctor) fmt::arg("error_code", error->code))); tr_error_clear(&error); } - - tr_error_clear(&error); } tor->torrent_announcer = tr_announcerAddTorrent(tor, onTrackerResponse, nullptr); diff --git a/libtransmission/transmission.h b/libtransmission/transmission.h index 7c4932c0f..0c9fbe801 100644 --- a/libtransmission/transmission.h +++ b/libtransmission/transmission.h @@ -993,6 +993,13 @@ tr_torrent* tr_torrentFindFromMetainfo(tr_session*, tr_torrent_metainfo const*); tr_torrent* tr_torrentFindFromMagnetLink(tr_session* session, char const* link); +/** + * @brief Set metainfo if possible. + * @return True if given metainfo was set. + * + */ +bool tr_torrentSetMetainfoFromFile(tr_torrent* torrent, tr_torrent_metainfo* metainfo, char const* filename); + /** * @return this torrent's name. */ diff --git a/macosx/Controller.h b/macosx/Controller.h index 4a2aa6931..3313b20b8 100644 --- a/macosx/Controller.h +++ b/macosx/Controller.h @@ -13,15 +13,9 @@ @class AddMagnetWindowController; @class AddWindowController; -@class Badger; -@class DragOverlayWindow; -@class FilterBarController; -@class InfoWindowController; @class MessageWindowController; @class PrefsController; -@class StatusBarController; @class Torrent; -@class URLSheetWindowController; typedef NS_ENUM(unsigned int, addType) { // ADD_MANUAL, diff --git a/macosx/Controller.mm b/macosx/Controller.mm index b1ef031b8..b3c7182a8 100644 --- a/macosx/Controller.mm +++ b/macosx/Controller.mm @@ -1111,9 +1111,18 @@ static void removeKeRangerRansomware() continue; } - if (tr_torrentFindFromMetainfo(self.fLib, &metainfo) != nullptr) // dupe torrent + auto foundTorrent = tr_torrentFindFromMetainfo(self.fLib, &metainfo); + if (foundTorrent != nullptr) // dupe torrent { - [self duplicateOpenAlert:@(metainfo.name().c_str())]; + if (tr_torrentHasMetadata(foundTorrent)) + { + [self duplicateOpenAlert:@(metainfo.name().c_str())]; + } + // foundTorrent is a magnet, fill it with file's metainfo + else if (!tr_torrentSetMetainfoFromFile(foundTorrent, &metainfo, torrentPath.UTF8String)) + { + [self duplicateOpenAlert:@(metainfo.name().c_str())]; + } continue; }