void CAICHRecoveryHashSet::AddStoredAICHHash(CAICHHash Hash) { #ifdef _DEBUG if (m_liAICHHashsStored.Find(Hash) != NULL) { theApp.QueueDebugLogLine(false, _T("AICH hash storing is not unique - %s"), Hash.GetString()); ASSERT( false ); } #endif m_liAICHHashsStored.AddTail(Hash); }
bool CAICHRecoveryHashSet::LoadHashSet(){ if (m_eStatus != AICH_HASHSETCOMPLETE){ ASSERT( false ); return false; } if ( !m_pHashTree.m_bHashValid || m_pHashTree.m_nDataSize != m_pOwner->GetFileSize() || m_pHashTree.m_nDataSize == 0){ ASSERT( false ); return false; } CString fullpath = thePrefs.GetMuleDirectory(EMULE_CONFIGDIR); fullpath.Append(KNOWN2_MET_FILENAME); CSafeFile file; CFileException fexp; if (!file.Open(fullpath,CFile::modeCreate|CFile::modeRead|CFile::modeNoTruncate|CFile::osSequentialScan|CFile::typeBinary|CFile::shareDenyNone, &fexp)){ if (fexp.m_cause != CFileException::fileNotFound){ CString strError(_T("Failed to load ") KNOWN2_MET_FILENAME _T(" file")); TCHAR szError[MAX_CFEXP_ERRORMSG]; if (fexp.GetErrorMessage(szError, ARRSIZE(szError))){ strError += _T(" - "); strError += szError; } theApp.QueueLogLine(true, _T("%s"), strError); } return false; } try { //setvbuf(file.m_pStream, NULL, _IOFBF, 16384); uint8 header = file.ReadUInt8(); if (header != KNOWN2_MET_VERSION){ AfxThrowFileException(CFileException::endOfFile, 0, file.GetFileName()); } CAICHHash CurrentHash; uint32 nExistingSize = (UINT)file.GetLength(); uint32 nHashCount; while (file.GetPosition() < nExistingSize){ CurrentHash.Read(&file); if (m_pHashTree.m_Hash == CurrentHash){ // found Hashset uint32 nExpectedCount = (uint32)((PARTSIZE/EMBLOCKSIZE + ((PARTSIZE % EMBLOCKSIZE != 0)? 1 : 0)) * (m_pHashTree.m_nDataSize/PARTSIZE)); if (m_pHashTree.m_nDataSize % PARTSIZE != 0) nExpectedCount += (uint32)((m_pHashTree.m_nDataSize % PARTSIZE)/EMBLOCKSIZE + (((m_pHashTree.m_nDataSize % PARTSIZE) % EMBLOCKSIZE != 0)? 1 : 0)); nHashCount = file.ReadUInt32(); if (nHashCount != nExpectedCount){ theApp.QueueDebugLogLine(true, _T("Failed to load HashSet: Available Hashs and expected hashcount differ!")); return false; } //uint32 dbgPos = file.GetPosition(); if (!m_pHashTree.LoadLowestLevelHashs(&file)){ theApp.QueueDebugLogLine(true, _T("Failed to load HashSet: LoadLowestLevelHashs failed!")); return false; } //uint32 dbgHashRead = (file.GetPosition()-dbgPos)/HASHSIZE; if (!ReCalculateHash(false)){ theApp.QueueDebugLogLine(true, _T("Failed to load HashSet: Calculating loaded hashs failed!")); return false; } if (CurrentHash != m_pHashTree.m_Hash){ theApp.QueueDebugLogLine(true, _T("Failed to load HashSet: Calculated Masterhash differs from given Masterhash - hashset corrupt!")); return false; } return true; } nHashCount = file.ReadUInt32(); if (file.GetPosition() + nHashCount*HASHSIZE > nExistingSize){ AfxThrowFileException(CFileException::endOfFile, 0, file.GetFileName()); } // skip the rest of this hashset file.Seek(nHashCount*HASHSIZE, CFile::current); } theApp.QueueDebugLogLine(true, _T("Failed to load HashSet: HashSet not found!")); } catch(CFileException* error){ if (error->m_cause == CFileException::endOfFile) theApp.QueueLogLine(true, GetResString(IDS_ERR_MET_BAD), KNOWN2_MET_FILENAME); else{ TCHAR buffer[MAX_CFEXP_ERRORMSG]; error->GetErrorMessage(buffer, ARRSIZE(buffer)); theApp.QueueLogLine(true,GetResString(IDS_ERR_SERVERMET_UNKNOWN),buffer); } error->Delete(); } return false; }
void CKeyEntry::ReadPublishTrackingDataFromFile(CDataIO* pData, bool bIncludesAICH){ // format: <AICH HashCount 2><{AICH Hash Indexed} HashCount> <Names_Count 4><{<Name string><PopularityIndex 4>} Names_Count> // <PublisherCount 4><{<IP 4><Time 4><AICH Idx 2>} PublisherCount> ASSERT( m_aAICHHashs.IsEmpty() ); ASSERT( m_anAICHHashPopularity.IsEmpty() ); if (bIncludesAICH) { uint16 nAICHHashCount = pData->ReadUInt16(); for (uint16 i = 0; i < nAICHHashCount; i++) { CAICHHash hash; pData->ReadArray(hash.GetRawHash(), CAICHHash::GetHashSize()); m_aAICHHashs.Add(hash); m_anAICHHashPopularity.Add(0); } } ASSERT( m_listFileNames.IsEmpty() ); uint32 nNameCount = pData->ReadUInt32(); for (uint32 i = 0; i < nNameCount; i++){ structFileNameEntry sToAdd; sToAdd.m_fileName = pData->ReadStringUTF8(); sToAdd.m_uPopularityIndex = pData->ReadUInt32(); m_listFileNames.AddTail(sToAdd); } ASSERT( m_pliPublishingIPs == NULL ); m_pliPublishingIPs = new CList<structPublishingIP>(); uint32 nIPCount = pData->ReadUInt32(); uint32 nDbgLastTime = 0; for (uint32 i = 0; i < nIPCount; i++){ structPublishingIP sToAdd; sToAdd.m_uIP = pData->ReadUInt32(); ASSERT( sToAdd.m_uIP != 0 ); sToAdd.m_tLastPublish = pData->ReadUInt32(); ASSERT( nDbgLastTime <= (uint32)sToAdd.m_tLastPublish ); // shoudl always be sorted oldest first nDbgLastTime = sToAdd.m_tLastPublish; // read hash index and update popularity index if (bIncludesAICH) { sToAdd.m_byAICHHashIdx = pData->ReadUInt16(); if (sToAdd.m_byAICHHashIdx != _UI16_MAX) { if (sToAdd.m_byAICHHashIdx >= m_aAICHHashs.GetCount()) { // should never happen ASSERT( false ); DebugLogError(_T("CKeyEntry::ReadPublishTrackingDataFromFile - Out of Index AICH Hash index value while loading keywords")); sToAdd.m_byAICHHashIdx = _UI16_MAX; } else m_anAICHHashPopularity[sToAdd.m_byAICHHashIdx]++; } } else sToAdd.m_byAICHHashIdx = _UI16_MAX; AdjustGlobalPublishTracking(sToAdd.m_uIP, true, _T("")); m_pliPublishingIPs->AddTail(sToAdd); } RecalcualteTrustValue(); #ifdef _DEBUG if (m_aAICHHashs.GetCount() == 1) DebugLog(_T("Loaded 1 AICH Hash (%s, publishers %u of %u) for file %s"), m_aAICHHashs[0].GetString(), m_anAICHHashPopularity[0], m_pliPublishingIPs->GetCount(), m_uSourceID.ToHexString()); else if (m_aAICHHashs.GetCount() > 1) { DebugLogWarning(_T("Loaded multiple (%u) AICH Hashs for file %s, dumping..."), m_aAICHHashs.GetCount(), m_uSourceID.ToHexString()); for (int i = 0; i < m_aAICHHashs.GetCount(); i++) DebugLog(_T("%s - %u out of %u publishers"), m_aAICHHashs[i].GetString(), m_anAICHHashPopularity[i], m_pliPublishingIPs->GetCount()); } //if (GetTrustValue() < 1.0f) //DEBUG_ONLY( DebugLog(_T("Loaded %u different names, %u different publishIPs (trustvalue = %.2f) for file %s"), nNameCount, nIPCount, GetTrustValue(), m_uSourceID.ToHexString()) ); #endif }
bool CAICHHashSet::LoadHashSet() { if (m_eStatus != AICH_HASHSETCOMPLETE) { wxFAIL; return false; } if ( !m_pHashTree.m_bHashValid || m_pHashTree.m_nDataSize != m_pOwner->GetFileSize() || m_pHashTree.m_nDataSize == 0) { wxFAIL; return false; } wxString fullpath = theApp->ConfigDir + KNOWN2_MET_FILENAME; CFile file(fullpath, CFile::read); if (!file.IsOpened()) { if (wxFileExists(fullpath)) { wxString strError(wxT("Failed to load ") KNOWN2_MET_FILENAME wxT(" file")); AddDebugLogLineM( true, logSHAHashSet, strError); } return false; } try { uint8 header = file.ReadUInt8(); if (header != KNOWN2_MET_VERSION) { AddDebugLogLineM( true, logSHAHashSet, wxT("Loading failed: Current file is not a met-file!")); return false; } CAICHHash CurrentHash; uint64 nExistingSize = file.GetLength(); uint32 nHashCount; while (file.GetPosition() < nExistingSize) { CurrentHash.Read(&file); if (m_pHashTree.m_Hash == CurrentHash) { // found Hashset uint32 nExpectedCount = (PARTSIZE/EMBLOCKSIZE + ((PARTSIZE % EMBLOCKSIZE != 0)? 1 : 0)) * (m_pHashTree.m_nDataSize/PARTSIZE); if (m_pHashTree.m_nDataSize % PARTSIZE != 0) { nExpectedCount += (m_pHashTree.m_nDataSize % PARTSIZE)/EMBLOCKSIZE + (((m_pHashTree.m_nDataSize % PARTSIZE) % EMBLOCKSIZE != 0)? 1 : 0); } nHashCount = file.ReadUInt32(); if (nHashCount != nExpectedCount) { AddDebugLogLineM( true, logSHAHashSet, wxT("Failed to load HashSet: Available Hashs and expected hashcount differ!")); return false; } if (!m_pHashTree.LoadLowestLevelHashs(&file)) { AddDebugLogLineM( true, logSHAHashSet, wxT("Failed to load HashSet: LoadLowestLevelHashs failed!")); return false; } if (!ReCalculateHash(false)) { AddDebugLogLineM( true, logSHAHashSet, wxT("Failed to load HashSet: Calculating loaded hashs failed!")); return false; } if (CurrentHash != m_pHashTree.m_Hash) { AddDebugLogLineM( true, logSHAHashSet, wxT("Failed to load HashSet: Calculated Masterhash differs from given Masterhash - hashset corrupt!")); return false; } return true; } nHashCount = file.ReadUInt32(); if (file.GetPosition() + nHashCount*HASHSIZE > nExistingSize) { AddDebugLogLineM( true, logSHAHashSet, wxT("Saving failed: File contains fewer entries than specified!")); return false; } // skip the rest of this hashset file.Seek(nHashCount*HASHSIZE, wxFromCurrent); } AddDebugLogLineM( true, logSHAHashSet, wxT("Failed to load HashSet: HashSet not found!")); } catch (const CSafeIOException& e) { AddDebugLogLineM(true, logSHAHashSet, wxT("IO error while loading AICH HashSet: ") + e.what()); } return false; }
// this function is only allowed to be called right after successfully calculating the hashset (!) // will delete the hashset, after saving to free the memory bool CAICHHashSet::SaveHashSet() { if (m_eStatus != AICH_HASHSETCOMPLETE) { wxFAIL; return false; } if ( !m_pHashTree.m_bHashValid || m_pHashTree.m_nDataSize != m_pOwner->GetFileSize()) { wxFAIL; return false; } try { const wxString fullpath = theApp->ConfigDir + KNOWN2_MET_FILENAME; const bool exists = wxFile::Exists(fullpath); CFile file(fullpath, exists ? CFile::read_write : CFile::write); if (!file.IsOpened()) { AddDebugLogLineM( true, logSHAHashSet, wxT("Failed to save HashSet: opening met file failed!")); return false; } uint64 nExistingSize = file.GetLength(); if (nExistingSize) { uint8 header = file.ReadUInt8(); if (header != KNOWN2_MET_VERSION) { AddDebugLogLineM( true, logSHAHashSet, wxT("Saving failed: Current file is not a met-file!")); return false; } AddDebugLogLineM( false, logSHAHashSet, wxString::Format(wxT("Met file is version 0x%2.2x."),header)); } else { file.WriteUInt8(KNOWN2_MET_VERSION); // Update the recorded size, in order for the sanity check below to work. nExistingSize += 1; } // first we check if the hashset we want to write is already stored CAICHHash CurrentHash; while (file.GetPosition() < nExistingSize) { CurrentHash.Read(&file); if (m_pHashTree.m_Hash == CurrentHash) { // this hashset if already available, no need to save it again return true; } uint32 nHashCount = file.ReadUInt32(); if (file.GetPosition() + nHashCount*HASHSIZE > nExistingSize) { AddDebugLogLineM( true, logSHAHashSet, wxT("Saving failed: File contains fewer entries than specified!")); return false; } // skip the rest of this hashset file.Seek(nHashCount*HASHSIZE, wxFromCurrent); } // write hashset m_pHashTree.m_Hash.Write(&file); uint32 nHashCount = (PARTSIZE/EMBLOCKSIZE + ((PARTSIZE % EMBLOCKSIZE != 0)? 1 : 0)) * (m_pHashTree.m_nDataSize/PARTSIZE); if (m_pHashTree.m_nDataSize % PARTSIZE != 0) { nHashCount += (m_pHashTree.m_nDataSize % PARTSIZE)/EMBLOCKSIZE + (((m_pHashTree.m_nDataSize % PARTSIZE) % EMBLOCKSIZE != 0)? 1 : 0); } file.WriteUInt32(nHashCount); if (!m_pHashTree.WriteLowestLevelHashs(&file, 0, true, true)) { // thats bad... really file.SetLength(nExistingSize); AddDebugLogLineM( true, logSHAHashSet, wxT("Failed to save HashSet: WriteLowestLevelHashs() failed!")); return false; } if (file.GetLength() != nExistingSize + (nHashCount+1)*HASHSIZE + 4) { // thats even worse file.SetLength(nExistingSize); AddDebugLogLineM( true, logSHAHashSet, wxT("Failed to save HashSet: Calculated and real size of hashset differ!")); return false; } AddDebugLogLineM( false, logSHAHashSet, wxString::Format(wxT("Sucessfully saved eMuleAC Hashset, %u Hashs + 1 Masterhash written"), nHashCount)); } catch (const CSafeIOException& e) { AddDebugLogLineM(true, logSHAHashSet, wxT("IO error while saving AICH HashSet: ") + e.what()); return false; } FreeHashSet(); return true; }
bool CKnownFile::LoadTagsFromFile(const CFileDataIO* file) { uint32 tagcount = file->ReadUInt32(); for (uint32 j = 0; j != tagcount; ++j) { CTag newtag(*file, true); switch(newtag.GetNameID()){ case FT_FILENAME: if (GetFileName().IsOk()) { // Unlike eMule, we actually prefer the second // filename tag, since we use it to specify the // 'universial' filename (see CPath::ToUniv). CPath path = CPath::FromUniv(newtag.GetStr()); // May be invalid, if from older versions where // unicoded filenames be saved as empty-strings. if (path.IsOk()) { SetFileName(path); } } else { SetFileName(CPath(newtag.GetStr())); } break; case FT_FILESIZE: SetFileSize(newtag.GetInt()); m_AvailPartFrequency.clear(); m_AvailPartFrequency.insert( m_AvailPartFrequency.begin(), GetPartCount(), 0); break; case FT_ATTRANSFERRED: statistic.alltimetransferred += newtag.GetInt(); break; case FT_ATTRANSFERREDHI: statistic.alltimetransferred = (((uint64)newtag.GetInt()) << 32) + ((uint64)statistic.alltimetransferred); break; case FT_ATREQUESTED: statistic.alltimerequested = newtag.GetInt(); break; case FT_ATACCEPTED: statistic.alltimeaccepted = newtag.GetInt(); break; case FT_ULPRIORITY: m_iUpPriority = newtag.GetInt(); if( m_iUpPriority == PR_AUTO ){ m_iUpPriority = PR_HIGH; m_bAutoUpPriority = true; } else { if ( m_iUpPriority != PR_VERYLOW && m_iUpPriority != PR_LOW && m_iUpPriority != PR_NORMAL && m_iUpPriority != PR_HIGH && m_iUpPriority != PR_VERYHIGH && m_iUpPriority != PR_POWERSHARE) { m_iUpPriority = PR_NORMAL; } m_bAutoUpPriority = false; } break; case FT_PERMISSIONS: // Ignore it, it's not used anymore. break; case FT_AICH_HASH: { CAICHHash hash; bool hashSizeOk = hash.DecodeBase32(newtag.GetStr()) == CAICHHash::GetHashSize(); wxASSERT(hashSizeOk); if (hashSizeOk) { m_pAICHHashSet->SetMasterHash(hash, AICH_HASHSETCOMPLETE); } break; } case FT_KADLASTPUBLISHSRC: SetLastPublishTimeKadSrc( newtag.GetInt(), 0 ); if(GetLastPublishTimeKadSrc() > (uint32)time(NULL)+KADEMLIAREPUBLISHTIMES) { //There may be a posibility of an older client that saved a random number here.. This will check for that.. SetLastPublishTimeKadSrc(0, 0); } break; case FT_KADLASTPUBLISHNOTES: SetLastPublishTimeKadNotes( newtag.GetInt() ); break; case FT_KADLASTPUBLISHKEY: // Just purge it wxASSERT( newtag.IsInt() ); break; default: // Store them here and write them back on saving. m_taglist.push_back(newtag); } } return true; }