mirror of
https://github.com/d47081/qBittorrent.git
synced 2025-01-11 07:18:08 +00:00
Merge pull request #16573 from glassez/resume-data
Prevent loading resume data with inconsistent ID
This commit is contained in:
commit
b3ca2ea179
@ -4546,53 +4546,62 @@ 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 torrentIDv2 = TorrentID::fromInfoHash(infoHash);
|
||||||
|
const auto torrentIDv1 = TorrentID::fromInfoHash(lt::info_hash_t(infoHash.v1));
|
||||||
|
if (torrentID == torrentIDv2)
|
||||||
{
|
{
|
||||||
const auto torrentIDv1 = TorrentID::fromInfoHash(lt::info_hash_t(infoHash.v1));
|
if (isHybrid && indexedTorrents.contains(torrentIDv1))
|
||||||
const auto torrentIDv2 = TorrentID::fromInfoHash(infoHash);
|
|
||||||
if (torrentID == torrentIDv2)
|
|
||||||
{
|
{
|
||||||
if (indexedTorrents.contains(torrentIDv1))
|
// if we don't have metadata, try to find it in alternative "resume data"
|
||||||
|
if (!resumeData.ltAddTorrentParams.ti)
|
||||||
{
|
{
|
||||||
// if we has no metadata trying to find it in alternative "resume data"
|
const std::optional<LoadTorrentParams> loadAltResumeDataResult = startupStorage->load(torrentIDv1);
|
||||||
if (!resumeData.ltAddTorrentParams.ti)
|
if (loadAltResumeDataResult)
|
||||||
{
|
resumeData.ltAddTorrentParams.ti = loadAltResumeDataResult->ltAddTorrentParams.ti;
|
||||||
const std::optional<LoadTorrentParams> loadAltResumeDataResult = startupStorage->load(torrentIDv1);
|
|
||||||
if (loadAltResumeDataResult)
|
|
||||||
{
|
|
||||||
LoadTorrentParams altResumeData = *loadAltResumeDataResult;
|
|
||||||
resumeData.ltAddTorrentParams.ti = altResumeData.ltAddTorrentParams.ti;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove alternative "resume data" and skip the attempt to load it
|
|
||||||
m_resumeDataStorage->remove(torrentIDv1);
|
|
||||||
skippedIDs.insert(torrentIDv1);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
// remove alternative "resume data" and skip the attempt to load it
|
||||||
{
|
|
||||||
torrentID = torrentIDv2;
|
|
||||||
needStore = true;
|
|
||||||
m_resumeDataStorage->remove(torrentIDv1);
|
m_resumeDataStorage->remove(torrentIDv1);
|
||||||
|
skippedIDs.insert(torrentIDv1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (torrentID == torrentIDv1)
|
||||||
|
{
|
||||||
|
torrentID = torrentIDv2;
|
||||||
|
needStore = true;
|
||||||
|
m_resumeDataStorage->remove(torrentIDv1);
|
||||||
|
|
||||||
if (indexedTorrents.contains(torrentID))
|
if (indexedTorrents.contains(torrentID))
|
||||||
|
{
|
||||||
|
skippedIDs.insert(torrentID);
|
||||||
|
|
||||||
|
const std::optional<LoadTorrentParams> loadPreferredResumeDataResult = startupStorage->load(torrentID);
|
||||||
|
if (loadPreferredResumeDataResult)
|
||||||
{
|
{
|
||||||
skippedIDs.insert(torrentID);
|
std::shared_ptr<lt::torrent_info> ti = resumeData.ltAddTorrentParams.ti;
|
||||||
|
resumeData = *loadPreferredResumeDataResult;
|
||||||
const std::optional<LoadTorrentParams> loadPreferredResumeDataResult = startupStorage->load(torrentID);
|
if (!resumeData.ltAddTorrentParams.ti)
|
||||||
if (loadPreferredResumeDataResult)
|
resumeData.ltAddTorrentParams.ti = ti;
|
||||||
{
|
|
||||||
LoadTorrentParams preferredResumeData = *loadPreferredResumeDataResult;
|
|
||||||
std::shared_ptr<lt::torrent_info> ti = resumeData.ltAddTorrentParams.ti;
|
|
||||||
if (!preferredResumeData.ltAddTorrentParams.ti)
|
|
||||||
preferredResumeData.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
|
||||||
|
|
||||||
if (m_resumeDataStorage != startupStorage)
|
if (m_resumeDataStorage != startupStorage)
|
||||||
|
@ -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,7 +1575,8 @@ void TorrentImpl::reload()
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_nativeHandle = m_nativeSession->add_torrent(p);
|
m_nativeHandle = m_nativeSession->add_torrent(p);
|
||||||
m_nativeHandle.queue_position_set(queuePos);
|
if (queuePos >= lt::queue_position_t {})
|
||||||
|
m_nativeHandle.queue_position_set(queuePos);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TorrentImpl::pause()
|
void TorrentImpl::pause()
|
||||||
@ -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…
Reference in New Issue
Block a user