Browse Source

Parse torrent info separately from resume data

PR #17639.
adaptive-webui-19844
Vladimir Golovnev 2 years ago committed by GitHub
parent
commit
77dd8bd27b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 54
      src/base/bittorrent/bencoderesumedatastorage.cpp
  2. 15
      src/base/bittorrent/dbresumedatastorage.cpp

54
src/base/bittorrent/bencoderesumedatastorage.cpp

@ -201,37 +201,34 @@ void BitTorrent::BencodeResumeDataStorage::loadQueue(const Path &queueFilename)
BitTorrent::LoadResumeDataResult BitTorrent::BencodeResumeDataStorage::loadTorrentResumeData(const QByteArray &data, const QByteArray &metadata) const BitTorrent::LoadResumeDataResult BitTorrent::BencodeResumeDataStorage::loadTorrentResumeData(const QByteArray &data, const QByteArray &metadata) const
{ {
const QByteArray allData = ((metadata.isEmpty() || data.isEmpty())
? data : (data.chopped(1) + metadata.mid(1)));
lt::error_code ec; lt::error_code ec;
const lt::bdecode_node root = lt::bdecode(allData, ec); const lt::bdecode_node resumeDataRoot = lt::bdecode(data, ec);
if (ec) if (ec)
return nonstd::make_unexpected(tr("Cannot parse resume data: %1").arg(QString::fromStdString(ec.message()))); return nonstd::make_unexpected(tr("Cannot parse resume data: %1").arg(QString::fromStdString(ec.message())));
if (root.type() != lt::bdecode_node::dict_t) if (resumeDataRoot.type() != lt::bdecode_node::dict_t)
return nonstd::make_unexpected(tr("Cannot parse resume data: invalid foormat")); return nonstd::make_unexpected(tr("Cannot parse resume data: invalid format"));
LoadTorrentParams torrentParams; LoadTorrentParams torrentParams;
torrentParams.restored = true; torrentParams.restored = true;
torrentParams.category = fromLTString(root.dict_find_string_value("qBt-category")); torrentParams.category = fromLTString(resumeDataRoot.dict_find_string_value("qBt-category"));
torrentParams.name = fromLTString(root.dict_find_string_value("qBt-name")); torrentParams.name = fromLTString(resumeDataRoot.dict_find_string_value("qBt-name"));
torrentParams.hasSeedStatus = root.dict_find_int_value("qBt-seedStatus"); torrentParams.hasSeedStatus = resumeDataRoot.dict_find_int_value("qBt-seedStatus");
torrentParams.firstLastPiecePriority = root.dict_find_int_value("qBt-firstLastPiecePriority"); torrentParams.firstLastPiecePriority = resumeDataRoot.dict_find_int_value("qBt-firstLastPiecePriority");
torrentParams.seedingTimeLimit = root.dict_find_int_value("qBt-seedingTimeLimit", Torrent::USE_GLOBAL_SEEDING_TIME); torrentParams.seedingTimeLimit = resumeDataRoot.dict_find_int_value("qBt-seedingTimeLimit", Torrent::USE_GLOBAL_SEEDING_TIME);
torrentParams.savePath = Profile::instance()->fromPortablePath( torrentParams.savePath = Profile::instance()->fromPortablePath(
Path(fromLTString(root.dict_find_string_value("qBt-savePath")))); Path(fromLTString(resumeDataRoot.dict_find_string_value("qBt-savePath"))));
torrentParams.useAutoTMM = torrentParams.savePath.isEmpty(); torrentParams.useAutoTMM = torrentParams.savePath.isEmpty();
if (!torrentParams.useAutoTMM) if (!torrentParams.useAutoTMM)
{ {
torrentParams.downloadPath = Profile::instance()->fromPortablePath( torrentParams.downloadPath = Profile::instance()->fromPortablePath(
Path(fromLTString(root.dict_find_string_value("qBt-downloadPath")))); Path(fromLTString(resumeDataRoot.dict_find_string_value("qBt-downloadPath"))));
} }
// TODO: The following code is deprecated. Replace with the commented one after several releases in 4.4.x. // TODO: The following code is deprecated. Replace with the commented one after several releases in 4.4.x.
// === BEGIN DEPRECATED CODE === // // === BEGIN DEPRECATED CODE === //
const lt::bdecode_node contentLayoutNode = root.dict_find("qBt-contentLayout"); const lt::bdecode_node contentLayoutNode = resumeDataRoot.dict_find("qBt-contentLayout");
if (contentLayoutNode.type() == lt::bdecode_node::string_t) if (contentLayoutNode.type() == lt::bdecode_node::string_t)
{ {
const QString contentLayoutStr = fromLTString(contentLayoutNode.string_value()); const QString contentLayoutStr = fromLTString(contentLayoutNode.string_value());
@ -239,7 +236,7 @@ BitTorrent::LoadResumeDataResult BitTorrent::BencodeResumeDataStorage::loadTorre
} }
else else
{ {
const bool hasRootFolder = root.dict_find_int_value("qBt-hasRootFolder"); const bool hasRootFolder = resumeDataRoot.dict_find_int_value("qBt-hasRootFolder");
torrentParams.contentLayout = (hasRootFolder ? TorrentContentLayout::Original : TorrentContentLayout::NoSubfolder); torrentParams.contentLayout = (hasRootFolder ? TorrentContentLayout::Original : TorrentContentLayout::NoSubfolder);
} }
// === END DEPRECATED CODE === // // === END DEPRECATED CODE === //
@ -248,13 +245,13 @@ BitTorrent::LoadResumeDataResult BitTorrent::BencodeResumeDataStorage::loadTorre
// fromLTString(root.dict_find_string_value("qBt-contentLayout")), TorrentContentLayout::Default); // fromLTString(root.dict_find_string_value("qBt-contentLayout")), TorrentContentLayout::Default);
// === END REPLACEMENT CODE === // // === END REPLACEMENT CODE === //
const lt::string_view ratioLimitString = root.dict_find_string_value("qBt-ratioLimit"); const lt::string_view ratioLimitString = resumeDataRoot.dict_find_string_value("qBt-ratioLimit");
if (ratioLimitString.empty()) if (ratioLimitString.empty())
torrentParams.ratioLimit = root.dict_find_int_value("qBt-ratioLimit", Torrent::USE_GLOBAL_RATIO * 1000) / 1000.0; torrentParams.ratioLimit = resumeDataRoot.dict_find_int_value("qBt-ratioLimit", Torrent::USE_GLOBAL_RATIO * 1000) / 1000.0;
else else
torrentParams.ratioLimit = fromLTString(ratioLimitString).toDouble(); torrentParams.ratioLimit = fromLTString(ratioLimitString).toDouble();
const lt::bdecode_node tagsNode = root.dict_find("qBt-tags"); const lt::bdecode_node tagsNode = resumeDataRoot.dict_find("qBt-tags");
if (tagsNode.type() == lt::bdecode_node::list_t) if (tagsNode.type() == lt::bdecode_node::list_t)
{ {
for (int i = 0; i < tagsNode.list_size(); ++i) for (int i = 0; i < tagsNode.list_size(); ++i)
@ -266,7 +263,24 @@ BitTorrent::LoadResumeDataResult BitTorrent::BencodeResumeDataStorage::loadTorre
lt::add_torrent_params &p = torrentParams.ltAddTorrentParams; lt::add_torrent_params &p = torrentParams.ltAddTorrentParams;
p = lt::read_resume_data(root, ec); p = lt::read_resume_data(resumeDataRoot, ec);
if (!metadata.isEmpty())
{
const lt::bdecode_node torentInfoRoot = lt::bdecode(metadata, ec);
if (ec)
return nonstd::make_unexpected(tr("Cannot parse torrent info: %1").arg(QString::fromStdString(ec.message())));
if (torentInfoRoot.type() != lt::bdecode_node::dict_t)
return nonstd::make_unexpected(tr("Cannot parse torrent info: invalid format"));
const auto torrentInfo = std::make_shared<lt::torrent_info>(torentInfoRoot, ec);
if (ec)
return nonstd::make_unexpected(tr("Cannot parse torrent info: %1").arg(QString::fromStdString(ec.message())));
p.ti = torrentInfo;
}
p.save_path = Profile::instance()->fromPortablePath( p.save_path = Profile::instance()->fromPortablePath(
Path(fromLTString(p.save_path))).toString().toStdString(); Path(fromLTString(p.save_path))).toString().toStdString();
@ -287,7 +301,7 @@ BitTorrent::LoadResumeDataResult BitTorrent::BencodeResumeDataStorage::loadTorre
} }
const bool hasMetadata = (p.ti && p.ti->is_valid()); const bool hasMetadata = (p.ti && p.ti->is_valid());
if (!hasMetadata && !root.dict_find("info-hash")) if (!hasMetadata && !resumeDataRoot.dict_find("info-hash"))
return nonstd::make_unexpected(tr("Resume data is invalid: neither metadata nor info-hash was found")); return nonstd::make_unexpected(tr("Resume data is invalid: neither metadata nor info-hash was found"));
return torrentParams; return torrentParams;

15
src/base/bittorrent/dbresumedatastorage.cpp

@ -224,17 +224,20 @@ namespace BitTorrent
} }
const QByteArray bencodedResumeData = query.value(DB_COLUMN_RESUMEDATA.name).toByteArray(); const QByteArray bencodedResumeData = query.value(DB_COLUMN_RESUMEDATA.name).toByteArray();
const QByteArray bencodedMetadata = query.value(DB_COLUMN_METADATA.name).toByteArray();
const QByteArray allData = ((bencodedMetadata.isEmpty() || bencodedResumeData.isEmpty())
? bencodedResumeData
: (bencodedResumeData.chopped(1) + bencodedMetadata.mid(1)));
lt::error_code ec; lt::error_code ec;
const lt::bdecode_node root = lt::bdecode(allData, ec); const lt::bdecode_node resumeDataRoot = lt::bdecode(bencodedResumeData, ec);
lt::add_torrent_params &p = resumeData.ltAddTorrentParams; lt::add_torrent_params &p = resumeData.ltAddTorrentParams;
p = lt::read_resume_data(root, ec); p = lt::read_resume_data(resumeDataRoot, ec);
if (const QByteArray bencodedMetadata = query.value(DB_COLUMN_METADATA.name).toByteArray(); !bencodedMetadata.isEmpty())
{
const lt::bdecode_node torentInfoRoot = lt::bdecode(bencodedMetadata, ec);
p.ti = std::make_shared<lt::torrent_info>(torentInfoRoot, ec);
}
p.save_path = Profile::instance()->fromPortablePath(Path(fromLTString(p.save_path))) p.save_path = Profile::instance()->fromPortablePath(Path(fromLTString(p.save_path)))
.toString().toStdString(); .toString().toStdString();

Loading…
Cancel
Save