Browse Source

Merge pull request #16573 from glassez/resume-data

Prevent loading resume data with inconsistent ID
adaptive-webui-19844
Vladimir Golovnev 3 years ago committed by GitHub
parent
commit
b3ca2ea179
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 39
      src/base/bittorrent/session.cpp
  2. 33
      src/base/bittorrent/torrentimpl.cpp

39
src/base/bittorrent/session.cpp

@ -4546,23 +4546,19 @@ void Session::startUpTorrents()
const lt::info_hash_t infoHash = (resumeData.ltAddTorrentParams.ti const lt::info_hash_t infoHash = (resumeData.ltAddTorrentParams.ti
? resumeData.ltAddTorrentParams.ti->info_hashes() ? resumeData.ltAddTorrentParams.ti->info_hashes()
: resumeData.ltAddTorrentParams.info_hashes); : resumeData.ltAddTorrentParams.info_hashes);
if (infoHash.has_v1() && infoHash.has_v2()) const bool isHybrid = infoHash.has_v1() && infoHash.has_v2();
{
const auto torrentIDv1 = TorrentID::fromInfoHash(lt::info_hash_t(infoHash.v1));
const auto torrentIDv2 = TorrentID::fromInfoHash(infoHash); const auto torrentIDv2 = TorrentID::fromInfoHash(infoHash);
const auto torrentIDv1 = TorrentID::fromInfoHash(lt::info_hash_t(infoHash.v1));
if (torrentID == torrentIDv2) if (torrentID == torrentIDv2)
{ {
if (indexedTorrents.contains(torrentIDv1)) if (isHybrid && indexedTorrents.contains(torrentIDv1))
{ {
// if we has no metadata trying to find it in alternative "resume data" // if we don't have metadata, try to find it in alternative "resume data"
if (!resumeData.ltAddTorrentParams.ti) if (!resumeData.ltAddTorrentParams.ti)
{ {
const std::optional<LoadTorrentParams> loadAltResumeDataResult = startupStorage->load(torrentIDv1); const std::optional<LoadTorrentParams> loadAltResumeDataResult = startupStorage->load(torrentIDv1);
if (loadAltResumeDataResult) if (loadAltResumeDataResult)
{ resumeData.ltAddTorrentParams.ti = loadAltResumeDataResult->ltAddTorrentParams.ti;
LoadTorrentParams altResumeData = *loadAltResumeDataResult;
resumeData.ltAddTorrentParams.ti = altResumeData.ltAddTorrentParams.ti;
}
} }
// remove alternative "resume data" and skip the attempt to load it // remove alternative "resume data" and skip the attempt to load it
@ -4570,7 +4566,7 @@ void Session::startUpTorrents()
skippedIDs.insert(torrentIDv1); skippedIDs.insert(torrentIDv1);
} }
} }
else else if (torrentID == torrentIDv1)
{ {
torrentID = torrentIDv2; torrentID = torrentIDv2;
needStore = true; needStore = true;
@ -4583,15 +4579,28 @@ void Session::startUpTorrents()
const std::optional<LoadTorrentParams> loadPreferredResumeDataResult = startupStorage->load(torrentID); const std::optional<LoadTorrentParams> loadPreferredResumeDataResult = startupStorage->load(torrentID);
if (loadPreferredResumeDataResult) if (loadPreferredResumeDataResult)
{ {
LoadTorrentParams preferredResumeData = *loadPreferredResumeDataResult;
std::shared_ptr<lt::torrent_info> ti = resumeData.ltAddTorrentParams.ti; std::shared_ptr<lt::torrent_info> ti = resumeData.ltAddTorrentParams.ti;
if (!preferredResumeData.ltAddTorrentParams.ti) resumeData = *loadPreferredResumeDataResult;
preferredResumeData.ltAddTorrentParams.ti = ti; if (!resumeData.ltAddTorrentParams.ti)
resumeData.ltAddTorrentParams.ti = ti;
resumeData = preferredResumeData;
} }
} }
} }
else
{
LogMsg(tr("Failed to resume torrent: inconsistent torrent ID is detected. Torrent: \"%1\"")
.arg(torrentID.toString()), Log::WARNING);
continue;
}
#else
const lt::sha1_hash infoHash = (resumeData.ltAddTorrentParams.ti
? resumeData.ltAddTorrentParams.ti->info_hash()
: resumeData.ltAddTorrentParams.info_hash);
if (torrentID != TorrentID::fromInfoHash(infoHash))
{
LogMsg(tr("Failed to resume torrent: inconsistent torrent ID is detected. Torrent: \"%1\"")
.arg(torrentID.toString()), Log::WARNING);
continue;
} }
#endif #endif

33
src/base/bittorrent/torrentimpl.cpp

@ -287,7 +287,8 @@ TorrentImpl::TorrentImpl(Session *session, lt::session *nativeSession
const std::shared_ptr<const lt::torrent_info> currentInfo = m_nativeHandle.torrent_file(); const std::shared_ptr<const lt::torrent_info> currentInfo = m_nativeHandle.torrent_file();
const lt::file_storage &fileStorage = currentInfo->files(); const lt::file_storage &fileStorage = currentInfo->files();
const std::vector<lt::download_priority_t> filePriorities = const std::vector<lt::download_priority_t> filePriorities =
resized(m_ltAddTorrentParams.file_priorities, fileStorage.num_files(), LT::toNative(DownloadPriority::Normal)); resized(m_ltAddTorrentParams.file_priorities, fileStorage.num_files()
, LT::toNative(m_ltAddTorrentParams.file_priorities.empty() ? DownloadPriority::Normal : DownloadPriority::Ignored));
for (int i = 0; i < filesCount; ++i) for (int i = 0; i < filesCount; ++i)
{ {
const lt::file_index_t nativeIndex = m_torrentInfo.nativeIndexes().at(i); const lt::file_index_t nativeIndex = m_torrentInfo.nativeIndexes().at(i);
@ -1507,21 +1508,19 @@ void TorrentImpl::updatePeerCount(const QString &trackerUrl, const lt::tcp::endp
void TorrentImpl::endReceivedMetadataHandling(const Path &savePath, const PathList &fileNames) void TorrentImpl::endReceivedMetadataHandling(const Path &savePath, const PathList &fileNames)
{ {
Q_ASSERT(m_filePaths.isEmpty()); Q_ASSERT(m_filePaths.isEmpty());
Q_ASSERT(m_indexMap.isEmpty());
lt::add_torrent_params &p = m_ltAddTorrentParams; lt::add_torrent_params &p = m_ltAddTorrentParams;
const std::shared_ptr<lt::torrent_info> metadata = std::const_pointer_cast<lt::torrent_info>(m_nativeHandle.torrent_file()); const std::shared_ptr<lt::torrent_info> metadata = std::const_pointer_cast<lt::torrent_info>(m_nativeHandle.torrent_file());
m_torrentInfo = TorrentInfo(*metadata); m_torrentInfo = TorrentInfo(*metadata);
m_indexMap.reserve(filesCount());
m_filePriorities.reserve(filesCount()); m_filePriorities.reserve(filesCount());
const auto nativeIndexes = m_torrentInfo.nativeIndexes(); const auto nativeIndexes = m_torrentInfo.nativeIndexes();
const std::vector<lt::download_priority_t> filePriorities = const std::vector<lt::download_priority_t> filePriorities =
resized(p.file_priorities, metadata->files().num_files(), LT::toNative(DownloadPriority::Normal)); resized(p.file_priorities, metadata->files().num_files()
, LT::toNative(p.file_priorities.empty() ? DownloadPriority::Normal : DownloadPriority::Ignored));
for (int i = 0; i < fileNames.size(); ++i) for (int i = 0; i < fileNames.size(); ++i)
{ {
const auto nativeIndex = nativeIndexes.at(i); const auto nativeIndex = nativeIndexes.at(i);
m_indexMap[nativeIndex] = i;
Path filePath = fileNames.at(i); Path filePath = fileNames.at(i);
p.renamed_files[nativeIndex] = filePath.toString().toStdString(); p.renamed_files[nativeIndex] = filePath.toString().toStdString();
@ -1534,10 +1533,7 @@ void TorrentImpl::endReceivedMetadataHandling(const Path &savePath, const PathLi
} }
p.save_path = savePath.toString().toStdString(); p.save_path = savePath.toString().toStdString();
p.ti = metadata; p.ti = metadata;
p.file_priorities = filePriorities;
const int internalFilesCount = p.ti->files().num_files(); // including .pad files
// Use qBittorrent default priority rather than libtorrent's (4)
p.file_priorities = std::vector(internalFilesCount, LT::toNative(DownloadPriority::Normal));
reload(); reload();
@ -1579,6 +1575,7 @@ void TorrentImpl::reload()
} }
m_nativeHandle = m_nativeSession->add_torrent(p); m_nativeHandle = m_nativeSession->add_torrent(p);
if (queuePos >= lt::queue_position_t {})
m_nativeHandle.queue_position_set(queuePos); m_nativeHandle.queue_position_set(queuePos);
} }
@ -1765,6 +1762,8 @@ void TorrentImpl::handleSaveResumeDataAlert(const lt::save_resume_data_alert *p)
{ {
if (m_maintenanceJob == MaintenanceJob::HandleMetadata) if (m_maintenanceJob == MaintenanceJob::HandleMetadata)
{ {
Q_ASSERT(m_indexMap.isEmpty());
m_ltAddTorrentParams = p->params; m_ltAddTorrentParams = p->params;
m_ltAddTorrentParams.have_pieces.clear(); m_ltAddTorrentParams.have_pieces.clear();
@ -1772,8 +1771,21 @@ void TorrentImpl::handleSaveResumeDataAlert(const lt::save_resume_data_alert *p)
TorrentInfo metadata = TorrentInfo(*m_nativeHandle.torrent_file()); TorrentInfo metadata = TorrentInfo(*m_nativeHandle.torrent_file());
const auto nativeIndexes = metadata.nativeIndexes();
PathList filePaths = metadata.filePaths(); PathList filePaths = metadata.filePaths();
applyContentLayout(filePaths, m_contentLayout); applyContentLayout(filePaths, m_contentLayout);
const auto &renamedFiles = m_ltAddTorrentParams.renamed_files;
m_indexMap.reserve(filePaths.size());
for (int i = 0; i < filePaths.size(); ++i)
{
const auto nativeIndex = nativeIndexes.at(i);
m_indexMap[nativeIndex] = i;
if (const auto it = renamedFiles.find(nativeIndex); it != renamedFiles.cend())
filePaths[i] = Path(it->second);
}
m_session->findIncompleteFiles(metadata, savePath(), downloadPath(), filePaths); m_session->findIncompleteFiles(metadata, savePath(), downloadPath(), filePaths);
} }
else else
@ -1902,6 +1914,9 @@ void TorrentImpl::handleFileRenameFailedAlert(const lt::file_rename_failed_alert
void TorrentImpl::handleFileCompletedAlert(const lt::file_completed_alert *p) void TorrentImpl::handleFileCompletedAlert(const lt::file_completed_alert *p)
{ {
if (m_maintenanceJob == MaintenanceJob::HandleMetadata)
return;
if (m_session->isAppendExtensionEnabled()) if (m_session->isAppendExtensionEnabled())
{ {
const int fileIndex = m_indexMap.value(p->index, -1); const int fileIndex = m_indexMap.value(p->index, -1);

Loading…
Cancel
Save