From 3a11c23efd6c035cafe58a7710ba72db76205e90 Mon Sep 17 00:00:00 2001 From: Chocobo1 Date: Mon, 26 Aug 2019 12:30:22 +0800 Subject: [PATCH 1/3] Fix wrong "added on" date This only happens for magnet links when its metadata has yet to be retrieved. Closes #11124. --- src/base/bittorrent/session.cpp | 9 +++++++++ src/base/bittorrent/torrenthandle.cpp | 3 ++- src/base/bittorrent/torrenthandle.h | 2 ++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/base/bittorrent/session.cpp b/src/base/bittorrent/session.cpp index 426ee20df..934eaf14f 100644 --- a/src/base/bittorrent/session.cpp +++ b/src/base/bittorrent/session.cpp @@ -2028,6 +2028,11 @@ bool Session::addTorrent_impl(CreateTorrentParams params, const MagnetUri &magne p.upload_limit = params.uploadLimit; p.download_limit = params.downloadLimit; +#if (LIBTORRENT_VERSION_NUM >= 10200) + if (params.addedTime.isValid()) + p.added_time = params.addedTime.toSecsSinceEpoch(); +#endif + // Preallocation mode p.storage_mode = isPreallocationEnabled() ? lt::storage_mode_allocate : lt::storage_mode_sparse; @@ -4464,6 +4469,10 @@ namespace torrentParams.firstLastPiecePriority = fast.dict_find_int_value("qBt-firstLastPiecePriority"); torrentParams.sequential = fast.dict_find_int_value("qBt-sequential"); + const lt::bdecode_node addedTimeNode = fast.dict_find("qBt-addedTime"); + if (addedTimeNode.type() == lt::bdecode_node::int_t) + torrentParams.addedTime = QDateTime::fromSecsSinceEpoch(addedTimeNode.int_value()); + queuePos = fast.dict_find_int_value("qBt-queuePosition"); return true; diff --git a/src/base/bittorrent/torrenthandle.cpp b/src/base/bittorrent/torrenthandle.cpp index 97b355c32..455ae6435 100644 --- a/src/base/bittorrent/torrenthandle.cpp +++ b/src/base/bittorrent/torrenthandle.cpp @@ -50,7 +50,6 @@ #endif #include -#include #include #include #include @@ -1775,6 +1774,8 @@ void TorrentHandle::handleSaveResumeDataAlert(const lt::save_resume_data_alert * // restored if qBittorrent quits before the metadata are retrieved: resumeData["qBt-firstLastPiecePriority"] = hasFirstLastPiecePriority(); resumeData["qBt-sequential"] = isSequentialDownload(); + + resumeData["qBt-addedTime"] = addedTime().toSecsSinceEpoch(); } else { const auto savePath = resumeData.find_key("save_path")->string(); diff --git a/src/base/bittorrent/torrenthandle.h b/src/base/bittorrent/torrenthandle.h index 7443024be..4a52a9b89 100644 --- a/src/base/bittorrent/torrenthandle.h +++ b/src/base/bittorrent/torrenthandle.h @@ -36,6 +36,7 @@ #include #include +#include #include #include #include @@ -83,6 +84,7 @@ namespace BitTorrent int downloadLimit; // for new torrents QVector filePriorities; + QDateTime addedTime; // for restored torrents qreal ratioLimit; int seedingTimeLimit; From f3ce76110b75730a790e5d2e6055910d9ed8cc2f Mon Sep 17 00:00:00 2001 From: Chocobo1 Date: Mon, 26 Aug 2019 14:25:16 +0800 Subject: [PATCH 2/3] Simplify code Instead of using dict_find_list() now we use the simpler dict_find() since we are going to check its validness anyway. --- src/base/bittorrent/session.cpp | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/src/base/bittorrent/session.cpp b/src/base/bittorrent/session.cpp index 934eaf14f..80bcd1467 100644 --- a/src/base/bittorrent/session.cpp +++ b/src/base/bittorrent/session.cpp @@ -171,11 +171,6 @@ namespace return output; } - bool isList(const lt::bdecode_node &entry) - { - return entry.type() == lt::bdecode_node::list_t; - } - QSet entryListToSet(const lt::bdecode_node &entry) { return entryListToSetImpl(entry); @@ -3667,13 +3662,13 @@ void Session::startUpTorrents() QStringList fastresumes = resumeDataDir.entryList( QStringList(QLatin1String("*.fastresume")), QDir::Files, QDir::Unsorted); - typedef struct + struct TorrentResumeData { QString hash; MagnetUri magnetUri; CreateTorrentParams addTorrentData; QByteArray data; - } TorrentResumeData; + }; int resumedTorrentsCount = 0; const auto startupTorrent = [this, &resumeDataDir, &resumedTorrentsCount](const TorrentResumeData ¶ms) @@ -4452,9 +4447,9 @@ namespace if (torrentParams.category.isEmpty()) // ************************************************************************************** torrentParams.category = fromLTString(fast.dict_find_string_value("qBt-category")); - // auto because the return type depends on the #if above. - const auto tagsEntry = fast.dict_find_list("qBt-tags"); - if (isList(tagsEntry)) + + const lt::bdecode_node tagsEntry = fast.dict_find("qBt-tags"); + if (tagsEntry.type() == lt::bdecode_node::list_t) torrentParams.tags = entryListToSet(tagsEntry); torrentParams.name = fromLTString(fast.dict_find_string_value("qBt-name")); torrentParams.hasSeedStatus = fast.dict_find_int_value("qBt-seedStatus"); From 09503b58fa9a90746d916cd0a4c84dde5a1fbab2 Mon Sep 17 00:00:00 2001 From: Chocobo1 Date: Mon, 26 Aug 2019 15:30:44 +0800 Subject: [PATCH 3/3] Clean up loadTorrentResumeData() --- src/base/bittorrent/session.cpp | 90 ++++++++++++++------------------- 1 file changed, 38 insertions(+), 52 deletions(-) diff --git a/src/base/bittorrent/session.cpp b/src/base/bittorrent/session.cpp index 80bcd1467..31035fabf 100644 --- a/src/base/bittorrent/session.cpp +++ b/src/base/bittorrent/session.cpp @@ -156,26 +156,6 @@ namespace return QString::fromUtf8(str.data(), static_cast(str.size())); } - template - QSet entryListToSetImpl(const Entry &entry) - { - Q_ASSERT(entry.type() == Entry::list_t); - QSet output; - for (int i = 0; i < entry.list_size(); ++i) { - const QString tag = fromLTString(entry.list_string_value_at(i)); - if (Session::isValidTag(tag)) - output.insert(tag); - else - qWarning() << QString("Dropping invalid stored tag: %1").arg(tag); - } - return output; - } - - QSet entryListToSet(const lt::bdecode_node &entry) - { - return entryListToSetImpl(entry); - } - QString normalizePath(const QString &path) { QString tmp = Utils::Fs::toUniformPath(path.trimmed()); @@ -4422,53 +4402,59 @@ namespace bool loadTorrentResumeData(const QByteArray &data, CreateTorrentParams &torrentParams, int &queuePos, MagnetUri &magnetUri) { + lt::error_code ec; + lt::bdecode_node root; + lt::bdecode(data.constData(), (data.constData() + data.size()), root, ec); + if (ec || (root.type() != lt::bdecode_node::dict_t)) return false; + torrentParams = CreateTorrentParams(); + torrentParams.restored = true; torrentParams.skipChecking = false; - - lt::error_code ec; - lt::bdecode_node fast; - lt::bdecode(data.constData(), data.constData() + data.size(), fast, ec); - if (ec || (fast.type() != lt::bdecode_node::dict_t)) return false; - + torrentParams.name = fromLTString(root.dict_find_string_value("qBt-name")); torrentParams.savePath = Profile::instance().fromPortablePath( - Utils::Fs::toUniformPath(fromLTString(fast.dict_find_string_value("qBt-savePath")))); - - LTString ratioLimitString = fast.dict_find_string_value("qBt-ratioLimit"); + Utils::Fs::toUniformPath(fromLTString(root.dict_find_string_value("qBt-savePath")))); + torrentParams.disableTempPath = root.dict_find_int_value("qBt-tempPathDisabled"); + torrentParams.sequential = root.dict_find_int_value("qBt-sequential"); + torrentParams.hasSeedStatus = root.dict_find_int_value("qBt-seedStatus"); + torrentParams.firstLastPiecePriority = root.dict_find_int_value("qBt-firstLastPiecePriority"); + torrentParams.hasRootFolder = root.dict_find_int_value("qBt-hasRootFolder"); + torrentParams.seedingTimeLimit = root.dict_find_int_value("qBt-seedingTimeLimit", TorrentHandle::USE_GLOBAL_SEEDING_TIME); + + const bool isAutoManaged = root.dict_find_int_value("auto_managed"); + const bool isPaused = root.dict_find_int_value("paused"); + torrentParams.paused = root.dict_find_int_value("qBt-paused", (isPaused && !isAutoManaged)); + torrentParams.forced = root.dict_find_int_value("qBt-forced", (!isPaused && !isAutoManaged)); + + const LTString ratioLimitString = root.dict_find_string_value("qBt-ratioLimit"); if (ratioLimitString.empty()) - torrentParams.ratioLimit = fast.dict_find_int_value("qBt-ratioLimit", TorrentHandle::USE_GLOBAL_RATIO * 1000) / 1000.0; + torrentParams.ratioLimit = root.dict_find_int_value("qBt-ratioLimit", TorrentHandle::USE_GLOBAL_RATIO * 1000) / 1000.0; else torrentParams.ratioLimit = fromLTString(ratioLimitString).toDouble(); - torrentParams.seedingTimeLimit = fast.dict_find_int_value("qBt-seedingTimeLimit", TorrentHandle::USE_GLOBAL_SEEDING_TIME); + // ************************************************************************************** // Workaround to convert legacy label to category // TODO: Should be removed in future - torrentParams.category = fromLTString(fast.dict_find_string_value("qBt-label")); + torrentParams.category = fromLTString(root.dict_find_string_value("qBt-label")); if (torrentParams.category.isEmpty()) // ************************************************************************************** - torrentParams.category = fromLTString(fast.dict_find_string_value("qBt-category")); - - const lt::bdecode_node tagsEntry = fast.dict_find("qBt-tags"); - if (tagsEntry.type() == lt::bdecode_node::list_t) - torrentParams.tags = entryListToSet(tagsEntry); - torrentParams.name = fromLTString(fast.dict_find_string_value("qBt-name")); - torrentParams.hasSeedStatus = fast.dict_find_int_value("qBt-seedStatus"); - torrentParams.disableTempPath = fast.dict_find_int_value("qBt-tempPathDisabled"); - torrentParams.hasRootFolder = fast.dict_find_int_value("qBt-hasRootFolder"); - - magnetUri = MagnetUri(fromLTString(fast.dict_find_string_value("qBt-magnetUri"))); - const bool isAutoManaged = fast.dict_find_int_value("auto_managed"); - const bool isPaused = fast.dict_find_int_value("paused"); - torrentParams.paused = fast.dict_find_int_value("qBt-paused", (isPaused && !isAutoManaged)); - torrentParams.forced = fast.dict_find_int_value("qBt-forced", (!isPaused && !isAutoManaged)); - torrentParams.firstLastPiecePriority = fast.dict_find_int_value("qBt-firstLastPiecePriority"); - torrentParams.sequential = fast.dict_find_int_value("qBt-sequential"); - - const lt::bdecode_node addedTimeNode = fast.dict_find("qBt-addedTime"); + torrentParams.category = fromLTString(root.dict_find_string_value("qBt-category")); + + const lt::bdecode_node tagsNode = root.dict_find("qBt-tags"); + if (tagsNode.type() == lt::bdecode_node::list_t) { + for (int i = 0; i < tagsNode.list_size(); ++i) { + const QString tag = fromLTString(tagsNode.list_string_value_at(i)); + if (Session::isValidTag(tag)) + torrentParams.tags << tag; + } + } + + const lt::bdecode_node addedTimeNode = root.dict_find("qBt-addedTime"); if (addedTimeNode.type() == lt::bdecode_node::int_t) torrentParams.addedTime = QDateTime::fromSecsSinceEpoch(addedTimeNode.int_value()); - queuePos = fast.dict_find_int_value("qBt-queuePosition"); + queuePos = root.dict_find_int_value("qBt-queuePosition"); + magnetUri = MagnetUri(fromLTString(root.dict_find_string_value("qBt-magnetUri"))); return true; }