📄 knownfile.cpp
字号:
#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)){
CTag aichtag(FT_AICH_HASH, m_pAICHHashSet->GetMasterHash().GetString());
aichtag.WriteTagToFile(file);
uTagCount++;
}
if (m_lastPublishTimeKadSrc){
CTag kadLastPubSrc(FT_KADLASTPUBLISHSRC, m_lastPublishTimeKadSrc);
kadLastPubSrc.WriteTagToFile(file);
uTagCount++;
}
if (m_uMetaDataVer > 0)
{
// 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( m_uMetaDataVer <= 0x0F );
uint32 uFlags = m_uMetaDataVer & 0x0F;
CTag tagFlags(FT_FLAGS, uFlags);
tagFlags.WriteTagToFile(file);
uTagCount++;
}
//other tags
for (int j = 0; j < taglist.GetCount(); j++){
if (taglist[j]->IsStr() || taglist[j]->IsInt()){
taglist[j]->WriteTagToFile(file);
uTagCount++;
}
}
file->Seek(uTagCountFilePos, CFile::begin);
file->WriteUInt32(uTagCount);
file->Seek(0, CFile::end);
return true;
}
void CKnownFile::CreateHash(CFile* pFile, UINT Length, uchar* pMd4HashOut, CAICHHashTree* pShaHashOut) const
{
ASSERT( pFile != NULL );
ASSERT( pMd4HashOut != NULL || pShaHashOut != NULL );
uint32 Required = Length;
uchar X[64*128];
uint32 posCurrentEMBlock = 0;
uint32 nIACHPos = 0;
CAICHHashAlgo* pHashAlg = m_pAICHHashSet->GetNewHashAlgo();
CMD4 md4;
while (Required >= 64){
uint32 len = Required / 64;
if (len > sizeof(X)/(64 * sizeof(X[0])))
len = sizeof(X)/(64 * sizeof(X[0]));
pFile->Read(&X, len*64);
// SHA hash needs 180KB blocks
if (pShaHashOut != NULL){
if (nIACHPos + len*64 >= EMBLOCKSIZE){
uint32 nToComplete = EMBLOCKSIZE - nIACHPos;
pHashAlg->Add(X, nToComplete);
ASSERT( nIACHPos + nToComplete == EMBLOCKSIZE );
pShaHashOut->SetBlockHash(EMBLOCKSIZE, posCurrentEMBlock, pHashAlg);
posCurrentEMBlock += EMBLOCKSIZE;
pHashAlg->Reset();
pHashAlg->Add(X+nToComplete,(len*64) - nToComplete);
nIACHPos = (len*64) - nToComplete;
}
else{
pHashAlg->Add(X, len*64);
nIACHPos += len*64;
}
}
if (pMd4HashOut != NULL){
md4.Add(X, len*64);
}
Required -= len*64;
}
Required = Length % 64;
if (Required != 0){
pFile->Read(&X, Required);
if (pShaHashOut != NULL){
if (nIACHPos + Required >= EMBLOCKSIZE){
uint32 nToComplete = EMBLOCKSIZE - nIACHPos;
pHashAlg->Add(X, nToComplete);
ASSERT( nIACHPos + nToComplete == EMBLOCKSIZE );
pShaHashOut->SetBlockHash(EMBLOCKSIZE, posCurrentEMBlock, pHashAlg);
posCurrentEMBlock += EMBLOCKSIZE;
pHashAlg->Reset();
pHashAlg->Add(X+nToComplete, Required - nToComplete);
nIACHPos = Required - nToComplete;
}
else{
pHashAlg->Add(X, Required);
nIACHPos += Required;
}
}
}
if (pShaHashOut != NULL){
if(nIACHPos > 0){
pShaHashOut->SetBlockHash(nIACHPos, posCurrentEMBlock, pHashAlg);
posCurrentEMBlock += nIACHPos;
}
ASSERT( posCurrentEMBlock == Length );
VERIFY( pShaHashOut->ReCalculateHash(pHashAlg, false) );
}
if (pMd4HashOut != NULL){
md4.Add(X, Required);
md4.Finish();
md4cpy(pMd4HashOut, md4.GetHash());
}
delete pHashAlg;
}
bool CKnownFile::CreateHash(FILE* fp, UINT uSize, uchar* pucHash, CAICHHashTree* pShaHashOut) const
{
bool bResult = false;
CStdioFile file(fp);
try
{
CreateHash(&file, uSize, pucHash, pShaHashOut);
bResult = true;
}
catch(CFileException* ex)
{
ex->Delete();
}
return bResult;
}
bool CKnownFile::CreateHash(const uchar* pucData, UINT uSize, uchar* pucHash, CAICHHashTree* pShaHashOut) const
{
bool bResult = false;
CMemFile file(const_cast<uchar*>(pucData), uSize);
try
{
CreateHash(&file, uSize, pucHash, pShaHashOut);
bResult = true;
}
catch(CFileException* ex)
{
ex->Delete();
}
return bResult;
}
uchar* CKnownFile::GetPartHash(uint16 part) const {
if (part >= hashlist.GetCount())
return 0;
return hashlist[part];
}
void CAbstractFile::SetFileName(LPCTSTR pszFileName, bool bReplaceInvalidFileSystemChars, bool bAutoSetFileType)
{
m_strFileName = pszFileName;
if (bReplaceInvalidFileSystemChars){
m_strFileName.Replace(_T('/'), _T('-'));
m_strFileName.Replace(_T('>'), _T('-'));
m_strFileName.Replace(_T('<'), _T('-'));
m_strFileName.Replace(_T('*'), _T('-'));
m_strFileName.Replace(_T(':'), _T('-'));
m_strFileName.Replace(_T('?'), _T('-'));
m_strFileName.Replace(_T('\"'), _T('-'));
m_strFileName.Replace(_T('\\'), _T('-'));
m_strFileName.Replace(_T('|'), _T('-'));
}
if (bAutoSetFileType)
SetFileType(GetFileTypeByName(m_strFileName));
}
void CAbstractFile::SetFileType(LPCTSTR pszFileType)
{
m_strFileType = pszFileType;
}
CString CAbstractFile::GetFileTypeDisplayStr() const
{
CString strFileTypeDisplayStr(GetFileTypeDisplayStrFromED2KFileType(GetFileType()));
if (strFileTypeDisplayStr.IsEmpty())
strFileTypeDisplayStr = GetFileType();
return strFileTypeDisplayStr;
}
void CAbstractFile::SetFileHash(const uchar* pucFileHash)
{
md4cpy(m_abyFileHash, pucFileHash);
}
bool CAbstractFile::HasNullHash() const
{
return isnulmd4(m_abyFileHash);
}
uint32 CAbstractFile::GetIntTagValue(uint8 tagname) const
{
for (int i = 0; i < taglist.GetSize(); i++){
const CTag* pTag = taglist[i];
if (pTag->GetNameID()==tagname && pTag->IsInt())
return pTag->GetInt();
}
return NULL;
}
bool CAbstractFile::GetIntTagValue(uint8 tagname, uint32& ruValue) const
{
for (int i = 0; i < taglist.GetSize(); i++){
const CTag* pTag = taglist[i];
if (pTag->GetNameID()==tagname && pTag->IsInt()){
ruValue = pTag->GetInt();
return true;
}
}
return false;
}
uint32 CAbstractFile::GetIntTagValue(LPCSTR tagname) const
{
for (int i = 0; i < taglist.GetSize(); i++){
const CTag* pTag = taglist[i];
if (pTag->GetNameID()==0 && pTag->IsInt() && CmpED2KTagName(pTag->GetName(), tagname)==0)
return pTag->GetInt();
}
return NULL;
}
const CString& CAbstractFile::GetStrTagValue(uint8 tagname) const
{
for (int i = 0; i < taglist.GetSize(); i++){
const CTag* pTag = taglist[i];
if (pTag->GetNameID()==tagname && pTag->IsStr())
return pTag->GetStr();
}
static const CString _strEmpty;
return _strEmpty;
}
const CString& CAbstractFile::GetStrTagValue(LPCSTR tagname) const
{
for (int i = 0; i < taglist.GetSize(); i++){
const CTag* pTag = taglist[i];
if (pTag->GetNameID()==0 && pTag->IsStr() && CmpED2KTagName(pTag->GetName(), tagname)==0)
return pTag->GetStr();
}
static const CString _strEmpty;
return _strEmpty;
}
CTag* CAbstractFile::GetTag(uint8 tagname, uint8 tagtype) const
{
for (int i = 0; i < taglist.GetSize(); i++){
CTag* pTag = taglist[i];
if (pTag->GetNameID()==tagname && pTag->GetType()==tagtype)
return pTag;
}
return NULL;
}
CTag* CAbstractFile::GetTag(LPCSTR tagname, uint8 tagtype) const
{
for (int i = 0; i < taglist.GetSize(); i++){
CTag* pTag = taglist[i];
if (pTag->GetNameID()==0 && pTag->GetType()==tagtype && CmpED2KTagName(pTag->GetName(), tagname)==0)
return pTag;
}
return NULL;
}
CTag* CAbstractFile::GetTag(uint8 tagname) const
{
for (int i = 0; i < taglist.GetSize(); i++){
CTag* pTag = taglist[i];
if (pTag->GetNameID()==tagname)
return pTag;
}
return NULL;
}
CTag* CAbstractFile::GetTag(LPCSTR tagname) const
{
for (int i = 0; i < taglist.GetSize(); i++){
CTag* pTag = taglist[i];
if (pTag->GetNameID()==0 && CmpED2KTagName(pTag->GetName(), tagname)==0)
return pTag;
}
return NULL;
}
void CAbstractFile::AddTagUnique(CTag* pTag)
{
for (int i = 0; i < taglist.GetSize(); i++){
const CTag* pCurTag = taglist[i];
if ( ( (pCurTag->GetNameID()!=0 && pCurTag->GetNameID()==pTag->GetNameID())
|| (pCurTag->GetName()!=NULL && pTag->GetName()!=NULL && CmpED2KTagName(pCurTag->GetName(), pTag->GetName())==0)
)
&& pCurTag->GetType() == pTag->GetType()){
delete pCurTag;
taglist.SetAt(i, pTag);
return;
}
}
taglist.Add(pTag);
}
Packet* CKnownFile::CreateSrcInfoPacket(CUpDownClient* forClient) const
{
if(m_ClientUploadList.IsEmpty())
return NULL;
CSafeMemFile data(1024);
uint16 nCount = 0;
data.WriteHash16(forClient->GetUploadFileID());
data.WriteUInt16(nCount);
uint32 cDbgNoSrc = 0;
for( POSITION pos = m_ClientUploadList.GetHeadPosition();pos != 0;)
{
const CUpDownClient *cur_src = m_ClientUploadList.GetNext(pos);
if(cur_src->HasLowID() || cur_src == forClient || !(cur_src->GetUploadState() == US_UPLOADING || cur_src->GetUploadState() == US_ONUPLOADQUEUE))
continue;
if (!cur_src->IsEd2kClient())
continue;
bool bNeeded = false;
uint8* rcvstatus = forClient->GetUpPartStatus();
if( rcvstatus )
{
uint8* srcstatus = cur_src->GetUpPartStatus();
if( srcstatus )
{
if( cur_src->GetUpPartCount() == forClient->GetUpPartCount() )
{
for (int x = 0; x < GetPartCount(); x++ )
{
if( srcstatus[x] && !rcvstatus[x] )
{
// We know the recieving client needs a chunk from this client.
bNeeded = true;
break;
}
}
}
else
{
// should never happen
if (thePrefs.GetVerbose())
DEBUG_ONLY(AddDebugLogLine(false,_T("*** %hs - found source (%s) with wrong partcount (%u) attached to file \"%s\" (partcount=%u)"), __FUNCTION__, cur_src->DbgGetClientInfo(), cur_src->GetUpPartCount(), GetFileName(), GetPartCount()));
}
}
else
{
cDbgNoSrc++;
// This client doesn't support upload chunk status. So just send it and hope for the best.
bNeeded = true;
}
}
else
{
TRACE(_T("CKnownFile::CreateSrcInfoPacket, requesting client has no chunk status - %s"), forClient->DbgGetClientInfo());
// remote client does not support upload chunk status, search sources which have at least one complete part
// we could even sort the list of sources by available chunks to return as much sources as possible which
// have the most available chunks. but this could be a noticeable performance problem.
uint8* srcstatus = cur_src->GetUpPartStatus();
if( srcstatus )
{
for (int x = 0; x < GetPartCount(); x++ )
{
if( srcstatus[x] )
{
// this client has at least one chunk
bNeeded = true;
break;
}
}
}
else
{
// This client doesn't support upload chunk status. So just send it and hope for the best.
bNeeded = true;
}
}
if( bNeeded )
{
nCount++;
uint32 dwID;
if(forClient->GetSourceExchangeVersion() > 2)
dwID = cur_src->GetUserIDHybrid();
else
dwID = cur_src->GetIP();
data.WriteUInt32(dwID);
data.WriteUInt16(cur_src->GetUserPort());
data.WriteUInt32(cur_src->GetServerIP());
data.WriteUInt16(cur_src->GetServerPort());
if (forClient->GetSourceExchangeVersion() > 1)
data.WriteHash16(cur_src->GetUserHash());
if (nCount > 500)
break;
}
}
TRACE(_T("CKnownFile::CreateSrcInfoPacket: Out of %u clients, %u had no valid chunk status\n\r"),m_ClientUploadList.GetCount(), cDbgNoSrc);
if (!nCount)
return 0;
data.Seek(16,0);
data.WriteUInt16(nCount);
Packet* result = new Packet(&data, OP_EMULEPROT);
result->opcode = OP_ANSWERSOURCES;
// 16+2+501*(4+2+4+2+16) = 14046 bytes max.
if ( result->size > 354 )
result->PackPacket();
if (thePrefs.GetDebugSourceExchange())
AddDebugLogLine(false, _T("SXSend: Client source response; Count=%u, %s, File=\"%s\""), nCount, forClient->DbgGetClientInfo(), GetFileName());
return result;
}
void CKnownFile::LoadComment()
{
CIni ini(thePrefs.GetFileCommentsFilePath(), md4str(GetFileHash()));
m_strComment = ini.GetStringUTF8(_T("Comment")).Left(MAXFILECOMMENTLEN);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -