bool CTorrent::LoadTorrentFromFile(const QByteArray& InfoHash) { ASSERT(m_TorrentInfo == NULL); m_TorrentInfo = new CTorrentInfo(this); ASSERT(m_pHash.isNull()); m_pHash = CFileHashPtr(new CFileHash(HashTorrent)); m_pHash->SetHash(InfoHash); QString TorrentFile = QString(InfoHash.toHex()) + ".torrent"; if(m_TorrentInfo->LoadTorrentFile(theCore->m_TorrentManager->GetTorrentDir() + TorrentFile)) { if(m_TorrentInfo->GetInfoHash() == InfoHash) { CFile* pFile = GetFile(); if(pFile->GetFileSize() == 0) pFile->SetFileSize(m_TorrentInfo->GetTotalLength()); LoadPieceHashes(); if(m_TorrentInfo->IsMultiFile() && !pFile->IsMultiFile()) { CFileHashPtr pMasterHash = pFile->GetMasterHash(); if(!pMasterHash.isNull() && pMasterHash->GetHash() == InfoHash) { LogLine(LOG_DEBUG | LOG_ERROR, tr("The multi file %1 is missing its proper index, restoring form torrent").arg(pFile->GetFileName())); InstallMetadata(); } } if(!m_TorrentInfo->IsEmpty() && !pFile->IsComplete() && !pFile->GetPartMap()) SetupPartMap(); } else { LogLine(LOG_DEBUG | LOG_ERROR, tr("The torrent file %1 contains an invalid infohash").arg(TorrentFile)); delete m_TorrentInfo; m_TorrentInfo = new CTorrentInfo(this); m_TorrentInfo->SetInfoHash(InfoHash); } } else m_TorrentInfo->SetInfoHash(InfoHash); theCore->m_TorrentManager->RegisterInfoHash(m_TorrentInfo->GetInfoHash()); return true; // Note: that is always true even if we fail to load as we always wil be able to proceed one way or another }
bool CTorrent::InstallMetadata() { CFile* pFile = GetFile(); ASSERT(m_TorrentInfo); CPartMap* pPartMap = pFile->GetPartMap(); if(pPartMap && !CompareSubFiles(pPartMap)) { if(pFile->GetInspector()->BadMetaData(GetHash())) pPartMap = NULL; else return false; } if(m_pHash->Compare(pFile->GetMasterHash().data())) pFile->SetFileName(m_TorrentInfo->GetTorrentName()); bool bOpenIO = false; CJoinedPartMap* pJoinedParts = qobject_cast<CJoinedPartMap*>(pPartMap); if((pPartMap == NULL && !pFile->IsComplete()) || (pJoinedParts && pJoinedParts->GetLinks().isEmpty())) { bOpenIO = true; if(!pPartMap) pFile->SetFileSize(m_TorrentInfo->GetTotalLength()); SetupPartMap(); if(!pPartMap && !pFile->IsPending()) pFile->SetFilePath(); } LoadPieceHashes(); if(pFile->IsIncomplete() && pFile->GetMasterHash()->GetType() == HashTorrent) pFile->CleanUpHashes(); // Note: if neo is the masterhash the IO is already opened if(bOpenIO && !pFile->IsPending()) pFile->Resume(); return true; }
void CTorrent::SetupPartMap() { ASSERT(!m_TorrentInfo->IsEmpty()); CFile* pFile = GetFile(); // Single File if(!m_TorrentInfo->IsMultiFile()) { if(!pFile->GetPartMap()) pFile->SetPartMap(CPartMapPtr(new CSynced<CPartMap>(m_TorrentInfo->GetTotalLength()))); return; } // Multi File: CJoinedPartMap* pParts = qobject_cast<CJoinedPartMap*>(pFile->GetPartMap()); if(pParts) { ASSERT(!pParts->GetLinks().isEmpty()); return; // is already set up } pParts = new CJoinedPartMap(pFile->GetFileSize()); pFile->GetInspector()->SetIndexSource(HashTorrent); CFileList* pList = pFile->GetList(); uint64 Offset = 0; foreach(const CTorrentInfo::SFileInfo& SubFile, m_TorrentInfo->GetFiles()) { if(SubFile.Length == 0) { LogLine(LOG_DEBUG | LOG_WARNING, tr("Ignoring empty file '%1' in torrent '%2'").arg(SubFile.FileName).arg(pFile->GetFileName())); continue; } CFile* pSubFile = new CFile(); if(pFile->GetProperty("Temp").toBool()) pSubFile->SetProperty("Temp", true); QString Dir = pFile->GetFileDir(); Dir += pFile->GetFileName() + "/"; if(!SubFile.FilePath.isEmpty()) Dir += SubFile.FilePath.join("/") + "/"; pSubFile->SetFileDir(Dir); pSubFile->AddEmpty(HashTorrent, SubFile.FileName, SubFile.Length, pFile->IsPending()); // Note: SubFile->MasterHash is set in MasterFile->Resume uint64 uBegin = Offset; uint64 uEnd = Offset + SubFile.Length; Offset += SubFile.Length; CSharedPartMap* pSubParts = new CSharedPartMap(uEnd - uBegin); pSubFile->SetPartMap(CPartMapPtr(pSubParts)); pParts->SetupLink(uBegin, uEnd, pSubFile->GetFileID()); pSubParts->SetupLink(uBegin, uEnd, pFile->GetFileID()); pList->AddFile(pSubFile); if(!pSubFile->IsPending()) pSubFile->Resume(); if(pFile->IsPaused(true)) pSubFile->Pause(); else if(pFile->IsStarted()) pSubFile->Start(); } pFile->SetPartMap(CPartMapPtr(pParts)); }
void CTorrent::OnFileHashed() { CFile* pFile = GetFile(); ASSERT(m_TorrentInfo); if(m_TorrentInfo->IsEmpty()) // are we making a torrent { QStringList Shared = theCore->Cfg()->GetStringList("Content/Shared"); Shared.append(theCore->GetIncomingDir()); Shared.append(theCore->GetTempDir()); QList<CTorrentInfo::SFileInfo> Files; if(CJoinedPartMap* pParts = qobject_cast<CJoinedPartMap*>(pFile->GetPartMap())) { QMap<uint64, SPartMapLink*> Links = pParts->GetJoints(); for(QMap<uint64, SPartMapLink*>::iterator I = Links.end(); I != Links.begin();) { SPartMapLink* pLink = *(--I); CFile* pSubFile = pFile->GetList()->GetFileByID(pLink->ID); if(!pSubFile) { LogLine(LOG_DEBUG | LOG_ERROR, tr("A sub file of %1 has been being removed befoure the torrent was created").arg(pFile->GetFileName())); pFile->TorrentHashed(this, false); return; } CTorrentInfo::SFileInfo File; QString Root; QStringList Path = GetRelativeSharedPath(pSubFile->GetFilePath(), Shared, Root).split("/", QString::SkipEmptyParts); if(!Path.isEmpty()) { if(Path.count() > 1) Path.removeFirst(); File.FileName = Path.takeLast(); File.FilePath = Path; } else File.FileName = "unknown"; File.Length = pSubFile->GetFileSize(); Files.append(File); } } if(CFileHashTree* pHashTree = qobject_cast<CFileHashTree*>(m_pHash.data())) m_TorrentInfo->MakeMetadata(Files, pHashTree->GetPartSize(), QList<QByteArray>(), pHashTree->GetRootHash()); else if(CFileHashSet* pHashSet = qobject_cast<CFileHashSet*>(m_pHash.data())) m_TorrentInfo->MakeMetadata(Files, pHashSet->GetPartSize(), pHashSet->GetHashSet()); else { ASSERT(0); } if(!pFile->IsPending()) SaveTorrentToFile(); m_pHash->SetHash(m_TorrentInfo->GetInfoHash()); theCore->m_TorrentManager->RegisterInfoHash(m_TorrentInfo->GetInfoHash()); pFile->TorrentHashed(this, true); } else // we are importing a torrent { bool bMatch = false; if(CFileHashTree* pHashTree = qobject_cast<CFileHashTree*>(m_pHash.data())) bMatch = m_TorrentInfo->GetRootHash() == pHashTree->GetRootHash(); else if(CFileHashSet* pHashSet = qobject_cast<CFileHashSet*>(m_pHash.data())) bMatch = m_TorrentInfo->GetPieceHashes() == pHashSet->GetHashSet(); else { ASSERT(0); } if(bMatch) { if(!pFile->IsPending()) SaveTorrentToFile(); m_pHash->SetHash(m_TorrentInfo->GetInfoHash()); theCore->m_TorrentManager->RegisterInfoHash(m_TorrentInfo->GetInfoHash()); } pFile->TorrentHashed(this, bMatch); } }