📄 sharedfilelist.cpp
字号:
//this file is part of eMule
//Copyright (C)2002 Merkur ( devs@emule-project.net / http://www.emule-project.net )
//
//This program is free software; you can redistribute it and/or
//modify it under the terms of the GNU General Public License
//as published by the Free Software Foundation; either
//version 2 of the License, or (at your option) any later version.
//
//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//GNU General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with this program; if not, write to the Free Software
//Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#include "stdafx.h"
#include <io.h>
#include "emule.h"
#include "SharedFileList.h"
#include "KnownFileList.h"
#include "Packets.h"
#include "Kademlia/Kademlia/Kademlia.h"
#include "kademlia/kademlia/search.h"
#include "kademlia/kademlia/prefs.h"
#define NOMD4MACROS
#include "kademlia/utils/md4.h"
#include "DownloadQueue.h"
#include "Statistics.h"
#include "Preferences.h"
#include "OtherFunctions.h"
#include "KnownFile.h"
#include "Sockets.h"
#include "SafeFile.h"
#include "Server.h"
#include "UpDownClient.h"
#include "PartFile.h"
#include "emuledlg.h"
#include "SharedFilesWnd.h"
#include "StringConversion.h"
#include "ClientList.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
typedef CSimpleArray<CKnownFile*> CSimpleKnownFileArray;
///////////////////////////////////////////////////////////////////////////////
// CPublishKeyword
class CPublishKeyword
{
public:
CPublishKeyword(const CStringW& rstrKeyword)
{
m_strKeyword = rstrKeyword;
ASSERT( rstrKeyword.GetLength() >= 3 );
KadGetKeywordHash(rstrKeyword, &m_nKadID);
SetNextPublishTime(0);
SetPublishedCount(0);
}
const Kademlia::CUInt128& GetKadID() const { return m_nKadID; }
const CStringW& GetKeyword() const { return m_strKeyword; }
int GetRefCount() const { return m_aFiles.GetSize(); }
const CSimpleKnownFileArray& GetReferences() const { return m_aFiles; }
UINT GetNextPublishTime() const { return m_tNextPublishTime; }
void SetNextPublishTime(UINT tNextPublishTime) { m_tNextPublishTime = tNextPublishTime; }
UINT GetPublishedCount() const { return m_uPublishedCount; }
void SetPublishedCount(UINT uPublishedCount) { m_uPublishedCount = uPublishedCount; }
void IncPublishedCount() { m_uPublishedCount++; }
BOOL AddRef(CKnownFile* pFile)
{
if (m_aFiles.Find(pFile) != -1)
{
ASSERT(0);
return FALSE;
}
return m_aFiles.Add(pFile);
}
int RemoveRef(CKnownFile* pFile)
{
m_aFiles.Remove(pFile);
return m_aFiles.GetSize();
}
void RemoveAllReferences()
{
m_aFiles.RemoveAll();
}
void RotateReferences(int iRotateSize)
{
if (m_aFiles.GetSize() > iRotateSize)
{
CKnownFile** ppRotated = (CKnownFile**)malloc(m_aFiles.m_nAllocSize * sizeof(*m_aFiles.GetData()));
if (ppRotated != NULL)
{
memcpy(ppRotated, m_aFiles.GetData() + iRotateSize, (m_aFiles.GetSize() - iRotateSize) * sizeof(*m_aFiles.GetData()));
memcpy(ppRotated + m_aFiles.GetSize() - iRotateSize, m_aFiles.GetData(), iRotateSize * sizeof(*m_aFiles.GetData()));
free(m_aFiles.GetData());
m_aFiles.m_aT = ppRotated;
}
}
}
protected:
CStringW m_strKeyword;
Kademlia::CUInt128 m_nKadID;
UINT m_tNextPublishTime;
UINT m_uPublishedCount;
CSimpleKnownFileArray m_aFiles;
};
///////////////////////////////////////////////////////////////////////////////
// CPublishKeywordList
class CPublishKeywordList
{
public:
CPublishKeywordList();
~CPublishKeywordList();
void AddKeywords(CKnownFile* pFile);
void RemoveKeywords(CKnownFile* pFile);
void RemoveAllKeywords();
void RemoveAllKeywordReferences();
void PurgeUnreferencedKeywords();
int GetCount() const { return m_lstKeywords.GetCount(); }
CPublishKeyword* GetNextKeyword();
void ResetNextKeyword();
UINT GetNextPublishTime() const { return m_tNextPublishKeywordTime; }
void SetNextPublishTime(UINT tNextPublishKeywordTime) { m_tNextPublishKeywordTime = tNextPublishKeywordTime; }
#ifdef _DEBUG
void Dump();
#endif
protected:
// can't use a CMap - too many disadvantages in processing the 'list'
//CTypedPtrMap<CMapStringToPtr, CString, CPublishKeyword*> m_lstKeywords;
CTypedPtrList<CPtrList, CPublishKeyword*> m_lstKeywords;
POSITION m_posNextKeyword;
UINT m_tNextPublishKeywordTime;
CPublishKeyword* FindKeyword(const CStringW& rstrKeyword, POSITION* ppos = NULL) const;
};
CPublishKeywordList::CPublishKeywordList()
{
ResetNextKeyword();
SetNextPublishTime(0);
}
CPublishKeywordList::~CPublishKeywordList()
{
RemoveAllKeywords();
}
CPublishKeyword* CPublishKeywordList::GetNextKeyword()
{
if (m_posNextKeyword == NULL)
{
m_posNextKeyword = m_lstKeywords.GetHeadPosition();
if (m_posNextKeyword == NULL)
return NULL;
}
return m_lstKeywords.GetNext(m_posNextKeyword);
}
void CPublishKeywordList::ResetNextKeyword()
{
m_posNextKeyword = m_lstKeywords.GetHeadPosition();
}
CPublishKeyword* CPublishKeywordList::FindKeyword(const CStringW& rstrKeyword, POSITION* ppos) const
{
POSITION pos = m_lstKeywords.GetHeadPosition();
while (pos)
{
POSITION posLast = pos;
CPublishKeyword* pPubKw = m_lstKeywords.GetNext(pos);
if (pPubKw->GetKeyword() == rstrKeyword)
{
if (ppos)
*ppos = posLast;
return pPubKw;
}
}
return NULL;
}
void CPublishKeywordList::AddKeywords(CKnownFile* pFile)
{
const Kademlia::WordList& wordlist = pFile->GetKadKeywords();
ASSERT( wordlist.size() > 0 );
Kademlia::WordList::const_iterator it;
for (it = wordlist.begin(); it != wordlist.end(); it++)
{
const CStringW& strKeyword = *it;
CPublishKeyword* pPubKw = FindKeyword(strKeyword);
if (pPubKw == NULL)
{
pPubKw = new CPublishKeyword(strKeyword);
m_lstKeywords.AddTail(pPubKw);
SetNextPublishTime(0);
}
pPubKw->AddRef(pFile);
}
}
void CPublishKeywordList::RemoveKeywords(CKnownFile* pFile)
{
const Kademlia::WordList& wordlist = pFile->GetKadKeywords();
//ASSERT( wordlist.size() > 0 );
Kademlia::WordList::const_iterator it;
for (it = wordlist.begin(); it != wordlist.end(); it++)
{
const CStringW& strKeyword = *it;
POSITION pos;
CPublishKeyword* pPubKw = FindKeyword(strKeyword, &pos);
if (pPubKw != NULL)
{
if (pPubKw->RemoveRef(pFile) == 0)
{
if (pos == m_posNextKeyword)
(void)m_lstKeywords.GetNext(m_posNextKeyword);
m_lstKeywords.RemoveAt(pos);
delete pPubKw;
SetNextPublishTime(0);
}
}
}
}
void CPublishKeywordList::RemoveAllKeywords()
{
POSITION pos = m_lstKeywords.GetHeadPosition();
while (pos)
delete m_lstKeywords.GetNext(pos);
m_lstKeywords.RemoveAll();
ResetNextKeyword();
SetNextPublishTime(0);
}
void CPublishKeywordList::RemoveAllKeywordReferences()
{
POSITION pos = m_lstKeywords.GetHeadPosition();
while (pos)
m_lstKeywords.GetNext(pos)->RemoveAllReferences();
}
void CPublishKeywordList::PurgeUnreferencedKeywords()
{
POSITION pos = m_lstKeywords.GetHeadPosition();
while (pos)
{
POSITION posLast = pos;
CPublishKeyword* pPubKw = m_lstKeywords.GetNext(pos);
if (pPubKw->GetRefCount() == 0)
{
if (posLast == m_posNextKeyword)
(void)m_lstKeywords.GetNext(m_posNextKeyword);
m_lstKeywords.RemoveAt(posLast);
delete pPubKw;
SetNextPublishTime(0);
}
}
}
#ifdef _DEBUG
void CPublishKeywordList::Dump()
{
int i = 0;
POSITION pos = m_lstKeywords.GetHeadPosition();
while (pos)
{
CPublishKeyword* pPubKw = m_lstKeywords.GetNext(pos);
TRACE(_T("%3u: %-10ls ref=%u %s\n"), i, pPubKw->GetKeyword(), pPubKw->GetRefCount(), CastSecondsToHM(pPubKw->GetNextPublishTime()));
i++;
}
}
#endif
///////////////////////////////////////////////////////////////////////////////
// CSharedFileList
CSharedFileList::CSharedFileList(CServerConnect* in_server)
{
server = in_server;
output = 0;
m_Files_map.InitHashTable(1031);
m_keywords = new CPublishKeywordList;
m_lastPublishED2K = 0;
m_lastPublishED2KFlag = true;
m_currFileSrc = 0;
m_lastPublishKadSrc = 0;
m_currFileKey = 0;
m_lastProcessPublishKadKeywordList = 0;
FindSharedFiles();
}
CSharedFileList::~CSharedFileList(){
while (!waitingforhash_list.IsEmpty()){
UnknownFile_Struct* nextfile = waitingforhash_list.RemoveHead();
delete nextfile;
}
// SLUGFILLER: SafeHash
while (!currentlyhashing_list.IsEmpty()){
UnknownFile_Struct* nextfile = currentlyhashing_list.RemoveHead();
delete nextfile;
}
// SLUGFILLER: SafeHash
delete m_keywords;
}
void CSharedFileList::FindSharedFiles()
{
if (!m_Files_map.IsEmpty())
{
POSITION pos = m_Files_map.GetStartPosition();
while (pos)
{
POSITION posLast = pos;
CCKey key;
CKnownFile* cur_file;
m_Files_map.GetNextAssoc(pos, key, cur_file);
if (cur_file->IsKindOf(RUNTIME_CLASS(CPartFile))
&& !theApp.downloadqueue->IsPartFile(cur_file)
&& !theApp.knownfiles->IsFilePtrInList(cur_file)
&& _taccess(cur_file->GetFilePath(), 0) == 0)
continue;
m_UnsharedFiles_map.SetAt(CSKey(cur_file->GetFileHash()), true);
m_Files_map.RemoveKey(key);
}
ASSERT( theApp.downloadqueue );
if (theApp.downloadqueue)
theApp.downloadqueue->AddPartFilesToShare(); // read partfiles
}
// khaos::kmod+ Fix: Shared files loaded multiple times.
CStringList l_sAdded;
CString stemp;
CString tempDir;
CString ltempDir;
stemp=thePrefs.GetIncomingDir();
stemp.MakeLower();
if (stemp.Right(1)!=_T("\\"))
stemp+=_T("\\");
l_sAdded.AddHead( stemp );
AddFilesFromDirectory(l_sAdded.GetHead());
if (thePrefs.GetCatCount()>1) {
for (int ix=1;ix<thePrefs.GetCatCount();ix++)
{
tempDir=CString( thePrefs.GetCatPath(ix) );
ltempDir=tempDir;ltempDir.MakeLower();
if (ltempDir.Right(1)!=_T("\\"))
ltempDir+=_T("\\");
if( l_sAdded.Find( ltempDir ) ==NULL ) {
l_sAdded.AddHead( ltempDir );
AddFilesFromDirectory(tempDir);
}
}
}
for (POSITION pos = thePrefs.shareddir_list.GetHeadPosition();pos != 0;)
{
tempDir = thePrefs.shareddir_list.GetNext(pos);
ltempDir= tempDir;
ltempDir.MakeLower();
if (ltempDir.Right(1)!=_T("\\"))
ltempDir+=_T("\\");
if( l_sAdded.Find( ltempDir ) ==NULL ) {
l_sAdded.AddHead( ltempDir );
AddFilesFromDirectory(tempDir);
}
}
// khaos::kmod-
if (waitingforhash_list.IsEmpty())
AddLogLine(false,GetResString(IDS_SHAREDFOUND), m_Files_map.GetCount());
else
AddLogLine(false,GetResString(IDS_SHAREDFOUNDHASHING), m_Files_map.GetCount(), waitingforhash_list.GetCount());
HashNextFile();
}
void CSharedFileList::AddFilesFromDirectory(const CString& rstrDirectory)
{
CFileFind ff;
CString searchpath;
searchpath.Format(_T("%s\\*"),rstrDirectory);
bool end = !ff.FindFile(searchpath,0);
if (end)
return;
while (!end)
{
end = !ff.FindNextFile();
if (ff.IsDirectory() || ff.IsDots() || ff.IsSystem() || ff.IsTemporary() || ff.GetLength()==0 || ff.GetLength()>=4294967295)
continue;
// ignore real(!) LNK files
TCHAR szExt[_MAX_EXT];
_tsplitpath(ff.GetFileName(), NULL, NULL, NULL, szExt);
if (_tcsicmp(szExt, _T(".lnk")) == 0){
SHFILEINFO info;
if (SHGetFileInfo(ff.GetFilePath(), 0, &info, sizeof(info), SHGFI_ATTRIBUTES) && (info.dwAttributes & SFGAO_LINK)){
CComPtr<IShellLink> pShellLink;
if (SUCCEEDED(pShellLink.CoCreateInstance(CLSID_ShellLink))){
CComQIPtr<IPersistFile> pPersistFile = pShellLink;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -