📄 knownfile.cpp
字号:
if ( m_pAICHHashSet->VerifyHashTree(true) ){
m_pAICHHashSet->SetStatus(AICH_HASHSETCOMPLETE);
if (!m_pAICHHashSet->SaveHashSet()){
theApp.QueueLogLine(true, GetResString(IDS_SAVEACFAILED));
}
}
else{
// now something went pretty wrong
theApp.QueueDebugLogLine(true,_T("Failed to calculate AICH Hashset from file %s"), GetFileName());
}
if (!hashcount){
md4cpy(m_abyFileHash, lasthash);
delete[] lasthash; // i_a: memleak
}
else {
hashlist.Add(lasthash);
uchar* buffer = new uchar[hashlist.GetCount()*16];
for (int i = 0; i < hashlist.GetCount(); i++)
md4cpy(buffer+(i*16), hashlist[i]);
CreateHashFromString(buffer, hashlist.GetCount()*16, m_abyFileHash);
delete[] buffer;
}
if (pvProgressParam && theApp.emuledlg && theApp.emuledlg->IsRunning()){
ASSERT( ((CKnownFile*)pvProgressParam)->IsKindOf(RUNTIME_CLASS(CKnownFile)) );
ASSERT( ((CKnownFile*)pvProgressParam)->GetFileSize() == GetFileSize() );
UINT uProgress = 100;
ASSERT( uProgress <= 100 );
VERIFY( PostMessage(theApp.emuledlg->GetSafeHwnd(), TM_FILEOPPROGRESS, uProgress, (LPARAM)pvProgressParam) );
}
// set lastwrite date
struct _stat fileinfo = {0};
_fstat(file->_file, &fileinfo);
m_tUtcLastModified = fileinfo.st_mtime;
AdjustNTFSDaylightFileTime(m_tUtcLastModified, strFilePath);
fclose(file);
file = NULL;
// Add filetags
UpdateMetaDataTags();
UpdatePartsInfo();
return true;
}
bool CKnownFile::CreateAICHHashSetOnly()
{
ASSERT( !IsPartFile() );
m_pAICHHashSet->FreeHashSet();
FILE* file = _tfsopen(GetFilePath(), _T("rbS"), _SH_DENYNO); // can not use _SH_DENYWR because we may access a completing part file
if (!file){
theApp.QueueLogLine(false, GetResString(IDS_ERR_FILEOPEN) + _T(" - %hs"), GetFilePath(), _T(""), strerror(errno));
return false;
}
// we are reading the file data later in 8K blocks, adjust the internal file stream buffer accordingly
setvbuf(file, NULL, _IOFBF, 1024*8*2);
// create aichhashset
uint32 togo = m_nFileSize;
for (uint16 hashcount = 0; togo >= PARTSIZE; ) {
CAICHHashTree* pBlockAICHHashTree = m_pAICHHashSet->m_pHashTree.FindHash(hashcount*PARTSIZE, PARTSIZE);
ASSERT( pBlockAICHHashTree != NULL );
CreateHashFromFile(file, PARTSIZE, NULL, pBlockAICHHashTree);
// SLUGFILLER: SafeHash - quick fallback
if (theApp.emuledlg==NULL || !theApp.emuledlg->IsRunning()){ // in case of shutdown while still hashing
fclose(file);
return false;
}
togo -= PARTSIZE;
hashcount++;
}
if (togo != 0){
CAICHHashTree* pBlockAICHHashTree = m_pAICHHashSet->m_pHashTree.FindHash(hashcount*PARTSIZE, togo);
ASSERT( pBlockAICHHashTree != NULL );
CreateHashFromFile(file, togo, NULL, pBlockAICHHashTree);
}
m_pAICHHashSet->ReCalculateHash(false);
if ( m_pAICHHashSet->VerifyHashTree(true) ){
m_pAICHHashSet->SetStatus(AICH_HASHSETCOMPLETE);
if (!m_pAICHHashSet->SaveHashSet()){
theApp.QueueLogLine(true, GetResString(IDS_SAVEACFAILED));
}
}
else{
// now something went pretty wrong
theApp.QueueDebugLogLine(true,_T("Failed to calculate AICH Hashset from file %s"), GetFileName());
}
fclose(file);
file = NULL;
return true;
}
void CKnownFile::SetFileSize(uint32 nFileSize)
{
CAbstractFile::SetFileSize(nFileSize);
m_pAICHHashSet->SetFileSize(nFileSize);
// Examples of parthashs, hashsets and filehashs for different filesizes
// according the ed2k protocol
//----------------------------------------------------------------------
//
//File size: 3 bytes
//File hash: 2D55E87D0E21F49B9AD25F98531F3724
//Nr. hashs: 0
//
//
//File size: 1*PARTSIZE
//File hash: A72CA8DF7F07154E217C236C89C17619
//Nr. hashs: 2
//Hash[ 0]: 4891ED2E5C9C49F442145A3A5F608299
//Hash[ 1]: 31D6CFE0D16AE931B73C59D7E0C089C0 *special part hash*
//
//
//File size: 1*PARTSIZE + 1 byte
//File hash: 2F620AE9D462CBB6A59FE8401D2B3D23
//Nr. hashs: 2
//Hash[ 0]: 121795F0BEDE02DDC7C5426D0995F53F
//Hash[ 1]: C329E527945B8FE75B3C5E8826755747
//
//
//File size: 2*PARTSIZE
//File hash: A54C5E562D5E03CA7D77961EB9A745A4
//Nr. hashs: 3
//Hash[ 0]: B3F5CE2A06BF403BFB9BFFF68BDDC4D9
//Hash[ 1]: 509AA30C9EA8FC136B1159DF2F35B8A9
//Hash[ 2]: 31D6CFE0D16AE931B73C59D7E0C089C0 *special part hash*
//
//
//File size: 3*PARTSIZE
//File hash: 5E249B96F9A46A18FC2489B005BF2667
//Nr. hashs: 4
//Hash[ 0]: 5319896A2ECAD43BF17E2E3575278E72
//Hash[ 1]: D86EF157D5E49C5ED502EDC15BB5F82B
//Hash[ 2]: 10F2D5B1FCB95C0840519C58D708480F
//Hash[ 3]: 31D6CFE0D16AE931B73C59D7E0C089C0 *special part hash*
//
//
//File size: 3*PARTSIZE + 1 byte
//File hash: 797ED552F34380CAFF8C958207E40355
//Nr. hashs: 4
//Hash[ 0]: FC7FD02CCD6987DCF1421F4C0AF94FB8
//Hash[ 1]: 2FE466AF8A7C06DA3365317B75A5ACFE
//Hash[ 2]: 873D3BF52629F7C1527C6E8E473C1C30
//Hash[ 3]: BCE50BEE7877BB07BB6FDA56BFE142FB
//
// File size Data parts ED2K parts ED2K part hashs
// ---------------------------------------------------------------
// 1..PARTSIZE-1 1 1 0(!)
// PARTSIZE 1 2(!) 2(!)
// PARTSIZE+1 2 2 2
// PARTSIZE*2 2 3(!) 3(!)
// PARTSIZE*2+1 3 3 3
if (nFileSize == 0){
ASSERT(0);
m_iPartCount = 0;
m_iED2KPartCount = 0;
m_iED2KPartHashCount = 0;
return;
}
// nr. of data parts
ASSERT( (uint64)(((uint64)nFileSize + (PARTSIZE - 1)) / PARTSIZE) <= (UINT)USHRT_MAX );
m_iPartCount = ((uint64)nFileSize + (PARTSIZE - 1)) / PARTSIZE;
// nr. of parts to be used with OP_FILESTATUS
m_iED2KPartCount = nFileSize / PARTSIZE + 1;
// nr. of parts to be used with OP_HASHSETANSWER
m_iED2KPartHashCount = nFileSize / PARTSIZE;
if (m_iED2KPartHashCount != 0)
m_iED2KPartHashCount += 1;
}
// needed for memfiles. its probably better to switch everything to CFile...
bool CKnownFile::LoadHashsetFromFile(CFileDataIO* file, bool checkhash){
uchar checkid[16];
file->ReadHash16(checkid);
//TRACE("File size: %u (%u full parts + %u bytes)\n", GetFileSize(), GetFileSize()/PARTSIZE, GetFileSize()%PARTSIZE);
//TRACE("File hash: %s\n", md4str(checkid));
ASSERT( hashlist.GetCount() == 0 );
UINT parts = file->ReadUInt16();
//TRACE("Nr. hashs: %u\n", (UINT)parts);
for (UINT i = 0; i < parts; i++){
uchar* cur_hash = new uchar[16];
file->ReadHash16(cur_hash);
//TRACE("Hash[%3u]: %s\n", i, md4str(cur_hash));
hashlist.Add(cur_hash);
}
// SLUGFILLER: SafeHash - always check for valid hashlist
if (!checkhash){
md4cpy(m_abyFileHash, checkid);
if (parts <= 1) // nothing to check
return true;
}
else if (md4cmp(m_abyFileHash, checkid)){
// delete hashset
for (int i = 0; i < hashlist.GetSize(); i++)
delete[] hashlist[i];
hashlist.RemoveAll();
return false; // wrong file?
}
else{
if (parts != GetED2KPartHashCount()){
// delete hashset
for (int i = 0; i < hashlist.GetSize(); i++)
delete[] hashlist[i];
hashlist.RemoveAll();
return false;
}
}
// SLUGFILLER: SafeHash
if (!hashlist.IsEmpty()){
uchar* buffer = new uchar[hashlist.GetCount()*16];
for (int i = 0; i < hashlist.GetCount(); i++)
md4cpy(buffer+(i*16), hashlist[i]);
CreateHashFromString(buffer, hashlist.GetCount()*16, checkid);
delete[] buffer;
}
if (!md4cmp(m_abyFileHash, checkid))
return true;
else{
// delete hashset
for (int i = 0; i < hashlist.GetSize(); i++)
delete[] hashlist[i];
hashlist.RemoveAll();
return false;
}
}
bool CKnownFile::SetHashset(const CArray<uchar*, uchar*>& aHashset)
{
// delete hashset
for (int i = 0; i < hashlist.GetSize(); i++)
delete[] hashlist[i];
hashlist.RemoveAll();
// set new hash
for (int i = 0; i < aHashset.GetSize(); i++)
{
uchar* pucHash = new uchar[16];
md4cpy(pucHash, aHashset.GetAt(i));
hashlist.Add(pucHash);
}
// verify new hash
if (hashlist.IsEmpty())
return true;
uchar aucHashsetHash[16];
uchar* buffer = new uchar[hashlist.GetCount()*16];
for (int i = 0; i < hashlist.GetCount(); i++)
md4cpy(buffer+(i*16), hashlist[i]);
CreateHashFromString(buffer, hashlist.GetCount()*16, aucHashsetHash);
delete[] buffer;
bool bResult = (md4cmp(aucHashsetHash, m_abyFileHash) == 0);
if (!bResult)
{
// delete hashset
for (int i = 0; i < hashlist.GetSize(); i++)
delete[] hashlist[i];
hashlist.RemoveAll();
}
return bResult;
}
bool CKnownFile::LoadTagsFromFile(CFileDataIO* file)
{
UINT tagcount = file->ReadUInt32();
for (UINT j = 0; j < tagcount; j++){
CTag* newtag = new CTag(file, false);
switch (newtag->GetNameID()){
case FT_FILENAME:{
ASSERT( newtag->IsStr() );
if (newtag->IsStr()){
#ifdef _UNICODE
if (GetFileName().IsEmpty())
#endif
SetFileName(newtag->GetStr());
}
delete newtag;
break;
}
case FT_FILESIZE:{
ASSERT( newtag->IsInt() );
if (newtag->IsInt())
{
SetFileSize(newtag->GetInt());
m_AvailPartFrequency.SetSize(GetPartCount());
for (uint32 i = 0; i < GetPartCount();i++)
m_AvailPartFrequency[i] = 0;
}
delete newtag;
break;
}
case FT_ATTRANSFERED:{
ASSERT( newtag->IsInt() );
if (newtag->IsInt())
statistic.alltimetransferred = newtag->GetInt();
delete newtag;
break;
}
case FT_ATTRANSFEREDHI:{
ASSERT( newtag->IsInt() );
if (newtag->IsInt())
{
uint32 hi,low;
low=statistic.alltimetransferred;
hi = newtag->GetInt();
uint64 hi2;
hi2=hi;
hi2=hi2<<32;
statistic.alltimetransferred=low+hi2;
}
delete newtag;
break;
}
case FT_ATREQUESTED:{
ASSERT( newtag->IsInt() );
if (newtag->IsInt())
statistic.alltimerequested = newtag->GetInt();
delete newtag;
break;
}
case FT_ATACCEPTED:{
ASSERT( newtag->IsInt() );
if (newtag->IsInt())
statistic.alltimeaccepted = newtag->GetInt();
delete newtag;
break;
}
case FT_ULPRIORITY:{
ASSERT( newtag->IsInt() );
if (newtag->IsInt())
{
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_NORMAL;
m_bAutoUpPriority = false;
}
}
delete newtag;
break;
}
case FT_KADLASTPUBLISHSRC:{
ASSERT( newtag->IsInt() );
if (newtag->IsInt())
m_lastPublishTimeKadSrc = newtag->GetInt();
delete newtag;
break;
}
case FT_FLAGS:
// Misc. Flags
// ------------------------------------------------------------------------------
// Bits 3-0: Meta data version
// 0 = Unknown
// 1 = we have created that meta data by examining the file contents.
// Bits 31-4: Reserved
ASSERT( newtag->IsInt() );
if (newtag->IsInt())
m_uMetaDataVer = newtag->GetInt() & 0x0F;
delete newtag;
break;
// old tags: as long as they are not needed, take the chance to purge them
case FT_PERMISSIONS:
ASSERT( newtag->IsInt() );
delete newtag;
break;
case FT_KADLASTPUBLISHKEY:
ASSERT( newtag->IsInt() );
delete newtag;
break;
case FT_AICH_HASH:{
if(!newtag->IsStr()){
//ASSERT( false ); uncomment later
break;
}
CAICHHash hash;
if (DecodeBase32(newtag->GetStr(),hash) == CAICHHash::GetHashSize())
m_pAICHHashSet->SetMasterHash(hash, AICH_HASHSETCOMPLETE);
else
ASSERT( false );
delete newtag;
break;
}
default:
ConvertED2KTag(newtag);
if (newtag)
taglist.Add(newtag);
}
}
// 05-J鋘-2004 [bc]: ed2k and Kad are already full of totally wrong and/or not properly attached meta data. Take
// the chance to clean any available meta data tags and provide only tags which were determined by us.
// It's a brute force method, but that wrong meta data is driving me crazy because wrong meta data is even worse than
// missing meta data.
if (m_uMetaDataVer == 0)
RemoveMetaDataTags();
return true;
}
bool CKnownFile::LoadDateFromFile(CFileDataIO* file){
m_tUtcLastModified = file->ReadUInt32();
return true;
}
bool CKnownFile::LoadFromFile(CFileDataIO* file){
// SLUGFILLER: SafeHash - load first, verify later
bool ret1 = LoadDateFromFile(file);
bool ret2 = LoadHashsetFromFile(file,false);
bool ret3 = LoadTagsFromFile(file);
UpdatePartsInfo();
return ret1 && ret2 && ret3 && GetED2KPartHashCount()==GetHashCount();// Final hash-count verification, needs to be done after the tags are loaded.
// SLUGFILLER: SafeHash
}
bool CKnownFile::WriteToFile(CFileDataIO* file)
{
// date
file->WriteUInt32(m_tUtcLastModified);
// hashset
file->WriteHash16(m_abyFileHash);
UINT parts = hashlist.GetCount();
file->WriteUInt16(parts);
for (UINT i = 0; i < parts; i++)
file->WriteHash16(hashlist[i]);
uint32 uTagCount = 0;
ULONG uTagCountFilePos = (ULONG)file->GetPosition();
file->WriteUInt32(uTagCount);
#ifdef _UNICODE
if (WriteOptED2KUTF8Tag(file, GetFileName(), FT_FILENAME))
uTagCount++;
#endif
CTag nametag(FT_FILENAME, GetFileName());
nametag.WriteTagToFile(file);
uTagCount++;
CTag sizetag(FT_FILESIZE, m_nFileSize);
sizetag.WriteTagToFile(file);
uTagCount++;
// statistic
if (statistic.alltimetransferred){
CTag attag1(FT_ATTRANSFERED, (uint32)statistic.alltimetransferred);
attag1.WriteTagToFile(file);
uTagCount++;
CTag attag4(FT_ATTRANSFEREDHI, (uint32)(statistic.alltimetransferred >> 32));
attag4.WriteTagToFile(file);
uTagCount++;
}
if (statistic.GetAllTimeRequests()){
CTag attag2(FT_ATREQUESTED, statistic.GetAllTimeRequests());
attag2.WriteTagToFile(file);
uTagCount++;
}
if (statistic.GetAllTimeAccepts()){
CTag attag3(FT_ATACCEPTED, statistic.GetAllTimeAccepts());
attag3.WriteTagToFile(file);
uTagCount++;
}
// priority N permission
CTag priotag(FT_ULPRIORITY, IsAutoUpPriority() ? PR_AUTO : m_iUpPriority);
priotag.WriteTagToFile(file);
uTagCount++;
//AICH Filehash
if (m_pAICHHashSet->HasValidMasterHash() && (m_pAICHHashSet->GetStatus() == AICH_HASHSETCOMPLETE || m_pAICHHashSet->GetStatus() == AICH_VERIFIED)){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -