⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 searchlist.cpp

📁 另外一款开放源码的高质量p2p源码软件
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//this file is part of eMule
//Copyright (C)2002 Merkur ( merkur-@users.sourceforge.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 "emule.h"
#include "SearchList.h"
#include "SearchParams.h"
#include "Packets.h"
#include "OtherFunctions.h"
#include "Preferences.h"
#include "UpDownClient.h"
#include "SafeFile.h"
#include "MMServer.h"
#include "SharedFileList.h"
#include "KnownFileList.h"
#include "DownloadQueue.h"
#include "PartFile.h"
#include "CxImage/xImage.h"
#include "kademlia/utils/uint128.h"
#include "emuledlg.h"
#include "SearchDlg.h"
#include "SearchListCtrl.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif


bool IsValidClientIPPort(uint32 nIP, uint16 nPort)
{
	return     nIP != 0
			&& nPort != 0
		    && (ntohl(nIP) != nPort)		// this filters most of the false data
			&& ((nIP & 0x000000FF) != 0)
			&& ((nIP & 0x0000FF00) != 0)
			&& ((nIP & 0x00FF0000) != 0)
			&& ((nIP & 0xFF000000) != 0);
}

void ConvertED2KTag(CTag*& pTag)
{
	if (pTag->tag.specialtag == 0 && pTag->tag.tagname != NULL)
	{
		static const struct
		{
			uint8	nID;
			uint8	nED2KType;
			LPCSTR	pszED2KName;
		} _aEmuleToED2KMetaTagsMap[] = 
		{
			// Artist, Album and Title are disabled because they should be already part of the filename
			// and would therefore be redundant information sent to the servers.. and the servers count the
			// amount of sent data!
			{ FT_MEDIA_ARTIST,  TAGTYPE_STRING, FT_ED2K_MEDIA_ARTIST },
			{ FT_MEDIA_ALBUM,   TAGTYPE_STRING, FT_ED2K_MEDIA_ALBUM },
			{ FT_MEDIA_TITLE,   TAGTYPE_STRING, FT_ED2K_MEDIA_TITLE },
			{ FT_MEDIA_LENGTH,  TAGTYPE_STRING, FT_ED2K_MEDIA_LENGTH },
			{ FT_MEDIA_LENGTH,  TAGTYPE_UINT32, FT_ED2K_MEDIA_LENGTH },
			{ FT_MEDIA_BITRATE, TAGTYPE_UINT32, FT_ED2K_MEDIA_BITRATE },
			{ FT_MEDIA_CODEC,   TAGTYPE_STRING, FT_ED2K_MEDIA_CODEC }
		};

		for (int j = 0; j < ARRSIZE(_aEmuleToED2KMetaTagsMap); j++)
		{
			if (    CmpED2KTagName(pTag->tag.tagname, _aEmuleToED2KMetaTagsMap[j].pszED2KName) == 0
				&& (   (pTag->IsStr() && _aEmuleToED2KMetaTagsMap[j].nED2KType == TAGTYPE_STRING)
					|| (pTag->IsInt() && _aEmuleToED2KMetaTagsMap[j].nED2KType == TAGTYPE_UINT32)))
			{
				if (pTag->IsStr())
				{
					if (_aEmuleToED2KMetaTagsMap[j].nID == FT_MEDIA_LENGTH)
					{
						UINT nMediaLength = 0;
						UINT hour = 0, min = 0, sec = 0;
						if (sscanf(pTag->tag.stringvalue, "%u : %u : %u", &hour, &min, &sec) == 3)
							nMediaLength = hour * 3600 + min * 60 + sec;
						else if (sscanf(pTag->tag.stringvalue, "%u : %u", &min, &sec) == 2)
							nMediaLength = min * 60 + sec;
						else if (sscanf(pTag->tag.stringvalue, "%u", &sec) == 1)
							nMediaLength = sec;

						CTag* tag = (nMediaLength != 0) ? new CTag(_aEmuleToED2KMetaTagsMap[j].nID, nMediaLength) : NULL;
						delete pTag;
						pTag = tag;
					}
					else
					{
						CTag* tag = (pTag->tag.stringvalue[0] != '\0') 
										? new CTag(_aEmuleToED2KMetaTagsMap[j].nID, pTag->tag.stringvalue) 
										: NULL;
						delete pTag;
						pTag = tag;
					}
				}
				else if (pTag->IsInt())
				{
					CTag* tag = (pTag->tag.intvalue != 0) 
									? new CTag(_aEmuleToED2KMetaTagsMap[j].nID, pTag->tag.intvalue) 
									: NULL;
					delete pTag;
					pTag = tag;
				}
				break;
			}
		}
	}
}


///////////////////////////////////////////////////////////////////////////////
// CSearchFile

CSearchFile::CSearchFile(const CSearchFile* copyfrom)
{
	md4cpy(m_abyFileHash, copyfrom->GetFileHash());
	SetFileSize(copyfrom->GetIntTagValue(FT_FILESIZE));
	SetFileName(copyfrom->GetStrTagValue(FT_FILENAME), false, false);
	SetFileType(copyfrom->GetFileType());
	m_nClientServerIP = copyfrom->GetClientServerIP();
	m_nClientID = copyfrom->GetClientID();
	m_nClientPort = copyfrom->GetClientPort();
	m_nClientServerPort = copyfrom->GetClientServerPort();
	m_pszDirectory = copyfrom->GetDirectory()? _tcsdup(copyfrom->GetDirectory()) : NULL;
	m_nSearchID = copyfrom->GetSearchID();
	m_nKademlia = copyfrom->IsKademlia();
	for (int i = 0; i < copyfrom->GetTags().GetCount(); i++)
		taglist.Add(new CTag(*copyfrom->GetTags().GetAt(i)));
	const CSimpleArray<SServer>& servers = copyfrom->GetServers();
	for (i = 0; i < servers.GetSize(); i++)
		AddServer(servers[i]);

	m_list_bExpanded = false;
	m_list_parent = const_cast<CSearchFile*>(copyfrom);
	m_list_childcount = 0;
	m_bPreviewPossible = false;
	m_eKnown = copyfrom->m_eKnown;
}

CSearchFile::CSearchFile(CFileDataIO* in_data, uint32 nSearchID, uint32 nServerIP, uint16 nServerPort, LPCTSTR pszDirectory, bool nKademlia)
{
	m_nKademlia = nKademlia;
	m_nSearchID = nSearchID;
	in_data->ReadHash16(m_abyFileHash);
	m_nClientID = in_data->ReadUInt32();
	m_nClientPort = in_data->ReadUInt16();
	if ((m_nClientID || m_nClientPort) && !IsValidClientIPPort(m_nClientID, m_nClientPort)){
		if (thePrefs.GetDebugServerSearchesLevel() > 1)
			Debug(_T("Filtered source from search result %s:%u\n"), DbgGetClientID(m_nClientID), m_nClientPort);
		m_nClientID = 0;
		m_nClientPort = 0;
	}
	UINT tagcount = in_data->ReadUInt32();
	// NSERVER2.EXE (lugdunum v16.38 patched for Win32) returns the ClientIP+Port of the client which offered that
	// file, even if that client has not filled the according fields in the OP_OFFERFILES packet with its IP+Port.
	//
	// 16.38.p73 (lugdunum) (propenprinz)
	//  *) does not return ClientIP+Port if the OP_OFFERFILES packet does not also contain it.
	//  *) if the OP_OFFERFILES packet does contain our HighID and Port the server returns that data at least when
	//     returning search results via TCP.
	if (thePrefs.GetDebugServerSearchesLevel() > 1)
		Debug(_T("Search Result: %s  Client=%u.%u.%u.%u:%u  Tags=%u\n"), md4str(m_abyFileHash), (uint8)m_nClientID,(uint8)(m_nClientID>>8),(uint8)(m_nClientID>>16),(uint8)(m_nClientID>>24), m_nClientPort, tagcount);

	for (UINT i = 0; i < tagcount; i++){
		CTag* toadd = new CTag(in_data);
		if (thePrefs.GetDebugServerSearchesLevel() > 1)
			Debug(_T("  %s\n"), toadd->GetFullInfo());
		ConvertED2KTag(toadd);
		if (toadd)
			taglist.Add(toadd);
	}

	// here we have two choices
	//	- if the server/client sent us a filetype, we could use it (though it could be wrong)
	//	- we always trust our filetype list and determine the filetype by the extension of the file
	//
	// if we received a filetype from server, we use it.
	// if we did not receive a filetype, we determine it by examining the file's extension.
	//
	// but, in no case, we will use the receive file type when adding this search result to the download queue, to avoid
	// that we are using 'wrong' file types in part files. (this has to be handled when creating the part files)
	LPCSTR pszFileType = GetStrTagValueA(FT_FILETYPE);
	SetFileName(GetStrTagValue(FT_FILENAME), false, pszFileType==NULL);
	SetFileSize(GetIntTagValue(FT_FILESIZE));
	if (pszFileType != NULL)
	{
		if (strcmp(pszFileType, ED2KFTSTR_PROGRAM)==0)
		{
			CStringA strDetailFileType = GetFileTypeByName(GetFileName());
			if (!strDetailFileType.IsEmpty())
				SetFileType(strDetailFileType);
			else
				SetFileType(pszFileType);
		}
		else
			SetFileType(pszFileType);
	}

	m_nClientServerIP = nServerIP;
	m_nClientServerPort = nServerPort;
	if (m_nClientServerIP && m_nClientServerPort){
		SServer server(m_nClientServerIP, m_nClientServerPort);
		server.m_uAvail = GetIntTagValue(FT_SOURCES);
		AddServer(server);
	}
	m_pszDirectory = pszDirectory ? _tcsdup(pszDirectory) : NULL;
	
	m_list_bExpanded = false;
	m_list_parent = NULL;
	m_list_childcount = 0;
	m_bPreviewPossible = false;
	m_eKnown = NotDetermined;
}

CSearchFile::CSearchFile(uint32 nSearchID, const uchar* pucFileHash, uint32 uFileSize, LPCTSTR pszFileName, int iFileType, int iAvailability)
{
	m_nSearchID = nSearchID;
	md4cpy(m_abyFileHash, pucFileHash);
	taglist.Add(new CTag(FT_FILESIZE, uFileSize));
	taglist.Add(new CTag(FT_FILENAME, pszFileName));
	taglist.Add(new CTag(FT_SOURCES, iAvailability));
	SetFileName(pszFileName);
	SetFileSize(uFileSize);

	m_nKademlia = 0;
	m_nClientID = 0;
	m_nClientPort = 0;
	m_nClientServerIP = 0;
	m_nClientServerPort = 0;
	m_pszDirectory = NULL;
	m_list_bExpanded = false;
	m_list_parent = NULL;
	m_list_childcount = 0;
	m_bPreviewPossible = false;
	m_eKnown = NotDetermined;
}

CSearchFile::~CSearchFile()
{
	for (int i = 0; i < taglist.GetSize();i++)
		delete taglist[i];
	if (m_pszDirectory)
		free(m_pszDirectory);
	for (int i = 0; i < m_listImages.GetSize(); i++)
		delete m_listImages[i];
}

uint32 CSearchFile::AddSources(uint32 count)
{
	for (int i = 0; i < taglist.GetSize(); i++)
	{
		CTag* pTag = taglist[i];
		if (pTag->tag.specialtag == FT_SOURCES)
		{
			if (m_nKademlia)
			{
				if (pTag->tag.intvalue < count)
					pTag->tag.intvalue = count;
			}
			else
				pTag->tag.intvalue += count;
			return pTag->tag.intvalue;
		}
	}

	// FT_SOURCES is not yet supported by clients, we may have to create such a tag..
	CTag* pTag = new CTag(FT_SOURCES, count);
	taglist.Add(pTag);
	return count;
}

uint32 CSearchFile::GetSourceCount() const
{
	return GetIntTagValue(FT_SOURCES);
}

uint32 CSearchFile::AddCompleteSources(uint32 count)
{
	for (int i = 0; i < taglist.GetSize(); i++)
	{
		CTag* pTag = taglist[i];
		if (pTag->tag.specialtag == FT_COMPLETE_SOURCES)
		{
			if (m_nKademlia)
			{
				if (pTag->tag.intvalue < count)
					pTag->tag.intvalue = count;
			}
			else
				pTag->tag.intvalue += count;
			return pTag->tag.intvalue;
		}
	}

	// FT_COMPLETE_SOURCES is not yet supported by all servers, we may have to create such a tag..
	CTag* pTag = new CTag(FT_COMPLETE_SOURCES, count);
	taglist.Add(pTag);
	return count;
}

uint32 CSearchFile::GetCompleteSourceCount() const
{
	return GetIntTagValue(FT_COMPLETE_SOURCES);
}



///////////////////////////////////////////////////////////////////////////////
// CSearchList

CSearchList::CSearchList(){
	outputwnd = 0;
	m_MobilMuleSearch = false;
}

CSearchList::~CSearchList(){
	Clear();
}

void CSearchList::Clear(){
	for(POSITION pos = list.GetHeadPosition(); pos != NULL; )
		delete list.GetNext(pos);
	list.RemoveAll();
}

void CSearchList::RemoveResults(uint32 nSearchID)
{
	// this will not delete the item from the window, make sure your code does it if you call this
	ASSERT( outputwnd );
	for (POSITION pos = list.GetHeadPosition(); pos != NULL;)
	{
		POSITION posLast = pos;
		CSearchFile* cur_file =	list.GetNext(pos);
		if (cur_file->GetSearchID() == nSearchID)
		{
			list.RemoveAt(posLast);
			delete cur_file;
		}
	}
}

void CSearchList::ShowResults(uint32 nSearchID)
{
	ASSERT( outputwnd );
	outputwnd->SetRedraw(false);
	for (POSITION pos = list.GetHeadPosition(); pos != 0;)
	{
		const CSearchFile* cur_file = list.GetNext(pos);
		if (cur_file->GetSearchID() == nSearchID && cur_file->GetListParent() == NULL)
			outputwnd->AddResult(cur_file);
	}
	outputwnd->SetRedraw(true);
}

void CSearchList::RemoveResult(CSearchFile* todel)
{
	for (POSITION pos = list.GetHeadPosition(); pos != 0;)
	{
		POSITION posLast = pos;
		CSearchFile* cur_file = list.GetNext(pos);
		if (cur_file == todel)
		{
			theApp.emuledlg->searchwnd->RemoveResult(todel);
			list.RemoveAt(posLast);
			delete todel;
			return;
		}
	}
}

void CSearchList::NewSearch(CSearchListCtrl* in_wnd, CStringA strResultFileType, uint32 nSearchID, bool MobilMuleSearch)
{
	if (in_wnd)
		outputwnd = in_wnd;

	m_strResultFileType = strResultFileType;
	m_nCurrentSearch = nSearchID;
	m_foundFilesCount.SetAt(nSearchID,0);
	m_foundSourcesCount.SetAt(nSearchID,0);
	m_MobilMuleSearch = MobilMuleSearch;
}

uint16 CSearchList::ProcessSearchanswer(char* in_packet, uint32 size, 
										CUpDownClient* Sender, bool* pbMoreResultsAvailable, LPCTSTR pszDirectory)
{
	ASSERT( Sender != NULL );
	// Elandal: Assumes sizeof(void*) == sizeof(uint32)
	uint32 nSearchID = (uint32)Sender;
	SSearchParams* pParams = new SSearchParams;
	pParams->strExpression = Sender->GetUserName();
	pParams->dwSearchID = nSearchID;
	pParams->bClientSharedFiles = true;
	if (theApp.emuledlg->searchwnd->CreateNewTab(pParams)){
		m_foundFilesCount.SetAt(nSearchID,0);
		m_foundSourcesCount.SetAt(nSearchID,0);
	}
	else{
		delete pParams;
		pParams = NULL;
	}

	CSafeMemFile packet((BYTE*)in_packet,size);
	UINT results = packet.ReadUInt32();
	for (UINT i = 0; i < results; i++){
		CSearchFile* toadd = new CSearchFile(&packet, nSearchID, 0, 0, pszDirectory);
		if (Sender){
			toadd->SetClientID(Sender->GetIP());
			toadd->SetClientPort(Sender->GetUserPort());
			toadd->SetClientServerIP(Sender->GetServerIP());
			toadd->SetClientServerPort(Sender->GetServerPort());
			if (Sender->GetServerIP() && Sender->GetServerPort()){
				CSearchFile::SServer server(Sender->GetServerIP(), Sender->GetServerPort());
				server.m_uAvail = 1;
				toadd->AddServer(server);
			}			
			toadd->SetPreviewPossible( Sender->GetPreviewSupport() && ED2KFT_VIDEO == GetED2KFileTypeID(toadd->GetFileName()) );
		}
		AddToList(toadd, true);
	}

	if (pbMoreResultsAvailable)
		*pbMoreResultsAvailable = false;
	int iAddData = (int)(packet.GetLength() - packet.GetPosition());
	if (iAddData == 1){
		uint8 ucMore = packet.ReadUInt8();
		if (ucMore == 0x00 || ucMore == 0x01){
			if (pbMoreResultsAvailable)
				*pbMoreResultsAvailable = (bool)ucMore;
			if (thePrefs.GetDebugClientTCPLevel() > 0)
				Debug(_T("  Client search answer(%s): More=%u\n"), Sender->GetUserName(), ucMore);
		}
		else{
			if (thePrefs.GetDebugClientTCPLevel() > 0)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -