diff --git a/src/base/bittorrent/torrent.h b/src/base/bittorrent/torrent.h index cb5b78bd8..5ea973f21 100644 --- a/src/base/bittorrent/torrent.h +++ b/src/base/bittorrent/torrent.h @@ -40,6 +40,7 @@ #include "abstractfilestorage.h" class QBitArray; +class QByteArray; class QDateTime; class QUrl; @@ -301,6 +302,7 @@ namespace BitTorrent virtual void clearPeers() = 0; virtual QString createMagnetURI() const = 0; + virtual nonstd::expected exportToBuffer() const = 0; virtual nonstd::expected exportToFile(const Path &path) const = 0; TorrentID id() const; diff --git a/src/base/bittorrent/torrentimpl.cpp b/src/base/bittorrent/torrentimpl.cpp index 68e78703b..2b7a28e34 100644 --- a/src/base/bittorrent/torrentimpl.cpp +++ b/src/base/bittorrent/torrentimpl.cpp @@ -45,6 +45,7 @@ #include #endif +#include #include #include #include @@ -2250,7 +2251,7 @@ QString TorrentImpl::createMagnetURI() const return QString::fromStdString(lt::make_magnet_uri(m_nativeHandle)); } -nonstd::expected TorrentImpl::exportToFile(const Path &path) const +nonstd::expected TorrentImpl::exportTorrent() const { if (!hasMetadata()) return nonstd::make_unexpected(tr("Missing metadata")); @@ -2263,21 +2264,45 @@ nonstd::expected TorrentImpl::exportToFile(const Path &path) cons #else const std::shared_ptr torrentInfo = info().nativeInfo(); #endif - auto creator = lt::create_torrent(*torrentInfo); + lt::create_torrent creator {*torrentInfo}; for (const TrackerEntry &entry : asConst(trackers())) creator.add_tracker(entry.url.toStdString(), entry.tier); - const lt::entry torrentEntry = creator.generate(); - const nonstd::expected result = Utils::IO::saveToFile(path, torrentEntry); - if (!result) - return result.get_unexpected(); + return creator.generate(); } catch (const lt::system_error &err) { return nonstd::make_unexpected(QString::fromLocal8Bit(err.what())); } + return nonstd::make_unexpected(tr("Unexpected error")); +} + +nonstd::expected TorrentImpl::exportToBuffer() const +{ + const nonstd::expected preparationResult = exportTorrent(); + if (!preparationResult) + return preparationResult.get_unexpected(); + + // usually torrent size should be smaller than 1 MB, + // however there are >100 MB v2/hybrid torrent files out in the wild + QByteArray buffer; + buffer.reserve(1024 * 1024); + lt::bencode(std::back_inserter(buffer), preparationResult.value()); + return buffer; +} + +nonstd::expected TorrentImpl::exportToFile(const Path &path) const +{ + const nonstd::expected preparationResult = exportTorrent(); + if (!preparationResult) + return preparationResult.get_unexpected(); + + const nonstd::expected saveResult = Utils::IO::saveToFile(path, preparationResult.value()); + if (!saveResult) + return saveResult.get_unexpected(); + return {}; } diff --git a/src/base/bittorrent/torrentimpl.h b/src/base/bittorrent/torrentimpl.h index af6a297cf..0a6fe698a 100644 --- a/src/base/bittorrent/torrentimpl.h +++ b/src/base/bittorrent/torrentimpl.h @@ -229,7 +229,8 @@ namespace BitTorrent void clearPeers() override; QString createMagnetURI() const override; - nonstd::expected exportToFile(const Path &path) const; + nonstd::expected exportToBuffer() const override; + nonstd::expected exportToFile(const Path &path) const override; bool needSaveResumeData() const; @@ -283,6 +284,8 @@ namespace BitTorrent void endReceivedMetadataHandling(const Path &savePath, const PathList &fileNames); void reload(); + nonstd::expected exportTorrent() const; + Session *const m_session; lt::session *m_nativeSession; lt::torrent_handle m_nativeHandle;