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

📄 localsearch.cpp

📁 p2p软件
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//
// LocalSearch.cpp
//
// Copyright (c) Shareaza Development Team, 2002-2004.
// This file is part of SHAREAZA (www.shareaza.com)
//
// Shareaza 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.
//
// Shareaza 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 Shareaza; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//

#include "StdAfx.h"
#include "Shareaza.h"
#include "Settings.h"
#include "LocalSearch.h"

#include "Library.h"
#include "LibraryFolders.h"
#include "SharedFile.h"
#include "SharedFolder.h"
#include "AlbumFolder.h"

#include "QuerySearch.h"
#include "GProfile.h"
#include "Network.h"
#include "Neighbours.h"
#include "Neighbour.h"
#include "Datagrams.h"
#include "G1Packet.h"
#include "G2Packet.h"
#include "Buffer.h"
#include "ZLib.h"
#include "GGEP.h"
#include "BTClients.h"

#include "Transfers.h"
#include "Downloads.h"
#include "Download.h"
#include "Uploads.h"
#include "UploadQueue.h"
#include "UploadQueues.h"

#include "XML.h"
#include "Schema.h"
#include "SchemaCache.h"

#include "SHA.h"
#include "TigerTree.h"
#include "ED2K.h"

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


//////////////////////////////////////////////////////////////////////
// CLocalSearch construction

CLocalSearch::CLocalSearch(CQuerySearch* pSearch, CNeighbour* pNeighbour, BOOL bWrapped)
{
	m_pSearch		= pSearch;
	m_pNeighbour	= pNeighbour;
	m_pEndpoint		= NULL;
	m_pBuffer		= NULL;
	m_nTTL			= Settings.Gnutella1.MaximumTTL - 3;
	m_nProtocol		= pNeighbour->m_nProtocol;
	m_bWrapped		= bWrapped;
	m_pPacket		= NULL;
	
	if ( m_bWrapped ) m_nProtocol = PROTOCOL_G1;
}

CLocalSearch::CLocalSearch(CQuerySearch* pSearch, SOCKADDR_IN* pEndpoint)
{
	m_pSearch		= pSearch;
	m_pNeighbour	= NULL;
	m_pEndpoint		= pEndpoint;
	m_pBuffer		= NULL;
	m_nTTL			= Settings.Gnutella1.MaximumTTL - 3;
	m_nProtocol		= PROTOCOL_G2;
	m_bWrapped		= FALSE;
	m_pPacket		= NULL;
}

CLocalSearch::CLocalSearch(CQuerySearch* pSearch, CBuffer* pBuffer, PROTOCOLID nProtocol)
{
	m_pSearch		= pSearch;
	m_pNeighbour	= NULL;
	m_pEndpoint		= NULL;
	m_pBuffer		= pBuffer;
	m_nTTL			= Settings.Gnutella1.MaximumTTL - 3;
	m_nProtocol		= nProtocol;
	m_bWrapped		= FALSE;
	m_pPacket		= NULL;
}

CLocalSearch::~CLocalSearch()
{
	GetXMLString();
}

//////////////////////////////////////////////////////////////////////
// CLocalSearch execute

int CLocalSearch::Execute(int nMaximum)
{
	if ( m_pBuffer == NULL )
	{
		if ( UploadQueues.GetQueueRemaining() == 0 ) return 0;
	}
	
	if ( nMaximum < 0 ) nMaximum = Settings.Gnutella.MaxHits;
	
	if ( m_pSearch )
	{
		m_pGUID = m_pSearch->m_pGUID;
	}
	else
	{
		Network.CreateID( &m_pGUID );
	}
	
	int nCount = ExecuteSharedFiles( nMaximum );
	
	if ( m_pSearch != NULL && m_pSearch->m_bWantPFS && m_nProtocol == PROTOCOL_G2 )
	{
		if ( nMaximum == 0 || nCount < nMaximum )
		{
			nCount += ExecutePartialFiles( nMaximum ? nMaximum - nCount : 0 );
		}
	}
	
	return nCount;
}

//////////////////////////////////////////////////////////////////////
// CLocalSearch execute shared files

int CLocalSearch::ExecuteSharedFiles(int nMaximum)
{
	CPtrList* pFiles = Library.Search( m_pSearch, nMaximum );
	if ( pFiles == NULL ) return 0;
	
	int nHits = pFiles->GetCount();
	
	while ( pFiles->GetCount() )
	{
		int nInThisPacket = min( pFiles->GetCount(), (int)Settings.Gnutella.HitsPerPacket );
		
		CreatePacket( nInThisPacket );
		
		for ( int nHitA = 0, nHitB = 0 ; nHitA < nInThisPacket ; nHitA++ )
		{
			CLibraryFile* pFile = (CLibraryFile*)pFiles->RemoveHead();
			if ( AddHit( pFile, nHitB ) ) nHitB ++;
		}
		
		WriteTrailer();
		if ( nHitB > 0 ) DispatchPacket(); else DestroyPacket();
	}
	
	delete pFiles;
	Library.Unlock();
	
	return nHits;
}

//////////////////////////////////////////////////////////////////////
// CLocalSearch add file hit

BOOL CLocalSearch::AddHit(CLibraryFile* pFile, int nIndex)
{
	ASSERT( m_pPacket != NULL );
	
	if ( m_nProtocol == PROTOCOL_G1 )
	{
		if ( ! AddHitG1( pFile, nIndex ) ) return FALSE;
	}
	else
	{
		if ( ! AddHitG2( pFile, nIndex ) ) return FALSE;
	}
	
	return TRUE;
}

BOOL CLocalSearch::AddHitG1(CLibraryFile* pFile, int nIndex)
{
	if ( ! pFile->IsAvailable() ) return FALSE;
	
	m_pPacket->WriteLongLE( pFile->m_nIndex );
	m_pPacket->WriteLongLE( (DWORD)min( pFile->GetSize(), 0xFFFFFFFF ) );
	m_pPacket->WriteString( pFile->m_sName );
	
	if ( pFile->m_bSHA1 )
	{
		CString strHash = CSHA::HashToString( &pFile->m_pSHA1, TRUE );
		m_pPacket->WriteString( strHash );
		
		/*
		CGGEPBlock pBlock;
		
		CGGEPItem* pItem = pBlock.Add( _T("H") );
		pItem->WriteByte( 1 );
		pItem->Write( &pFile->m_pSHA1, 20 );
		
		pBlock.Write( m_pPacket );
		m_pPacket->WriteByte( 0 );
		*/
	}
	else if ( pFile->m_bTiger )
	{
		CString strHash = CTigerNode::HashToString( &pFile->m_pTiger, TRUE );
		m_pPacket->WriteString( strHash );
	}
	else if ( pFile->m_bED2K )
	{
		CString strHash = CED2K::HashToString( &pFile->m_pED2K, TRUE );
		m_pPacket->WriteString( strHash );
	}
	else
	{
		m_pPacket->WriteByte( 0 );
	}
	
	if ( pFile->m_pSchema != NULL && pFile->m_pMetadata != NULL && ( m_pSearch == NULL || m_pSearch->m_bWantXML ) )
	{
		AddMetadata( pFile->m_pSchema, pFile->m_pMetadata, nIndex );
	}
	
	return TRUE;
}

BOOL CLocalSearch::AddHitG2(CLibraryFile* pFile, int nIndex)
{
	CG2Packet* pPacket = (CG2Packet*)m_pPacket;
	CString strMetadata, strComment;
	BOOL bCollection = FALSE;
	BOOL bPreview = FALSE;
	DWORD nGroup = 0;
	
	// Pass 1: Calculate child group size
	
	if ( pFile->m_bTiger && pFile->m_bSHA1 )
	{
		nGroup += 5 + 3 + sizeof(SHA1) + sizeof(TIGEROOT);
	}
	else if ( pFile->m_bTiger )
	{
		nGroup += 5 + 4 + sizeof(TIGEROOT);
	}
	else if ( pFile->m_bSHA1 )
	{
		nGroup += 5 + 5 + sizeof(SHA1);
	}
	
	if ( pFile->m_bED2K )
	{
		nGroup += 5 + 5 + sizeof(MD4);
	}
	
	if ( m_pSearch == NULL || m_pSearch->m_bWantDN )
	{
		if ( pFile->GetSize() <= 0xFFFFFFFF )
		{
			nGroup += 8 + pPacket->GetStringLen( pFile->m_sName );
		}
		else
		{
			nGroup += 4 + 8;
			nGroup += 4 + pPacket->GetStringLen( pFile->m_sName );
		}
		
		if ( LPCTSTR pszType = _tcsrchr( pFile->m_sName, '.' ) )
		{
			if ( _tcsicmp( pszType, _T(".co") ) == 0 ||
				 _tcsicmp( pszType, _T(".collection") ) == 0 )
			{
				if ( ! pFile->m_bBogus )
				{
					nGroup += 2 + 7;
					bCollection = TRUE;
				}
			}
		}
	}
	
	if ( pFile->IsAvailable() && ( m_pSearch == NULL || m_pSearch->m_bWantURL ) )
	{
		nGroup += 5;
		if ( pFile->m_pSources.GetCount() ) nGroup += 7;
		
		if ( Settings.Uploads.SharePreviews )
		{
			if (	pFile->m_bCachedPreview ||
					_tcsistr( pFile->m_sName, _T(".jpg") ) ||
					_tcsistr( pFile->m_sName, _T(".png") ) )
			{
				bPreview = TRUE;
			}
		}
		
		if ( bPreview ) nGroup += 5;
	}
	
	if ( pFile->m_pMetadata != NULL && ( m_pSearch == NULL || m_pSearch->m_bWantXML ) )
	{
		strMetadata = pFile->m_pMetadata->ToString();
		int nMetadata = pPacket->GetStringLen( strMetadata );
		nGroup += 4 + nMetadata;
		if ( nMetadata > 0xFF )
		{
			nGroup ++;
			if ( nMetadata > 0xFFFF ) nGroup ++;
		}
	}
	
	if ( m_pSearch == NULL || m_pSearch->m_bWantCOM )
	{
		if ( pFile->m_nRating > 0 || pFile->m_sComments.GetLength() > 0 )
		{
			if ( pFile->m_nRating > 0 )
			{
				strComment.Format( _T("<comment rating=\"%i\">"), pFile->m_nRating - 1 );
				CXMLNode::ValueToString( pFile->m_sComments, strComment );
				if ( strComment.GetLength() > 2048 ) strComment = strComment.Left( 2048 );
				strComment += _T("</comment>");
			}
			else
			{
				strComment = _T("<comment>");
				CXMLNode::ValueToString( pFile->m_sComments, strComment );
				if ( strComment.GetLength() > 2048 ) strComment = strComment.Left( 2048 );
				strComment += _T("</comment>");
			}
			
			Replace( strComment, _T("\r\n"), _T("{n}") );
			int nComment = pPacket->GetStringLen( strComment );
			nGroup += 5 + nComment;
			if ( nComment > 0xFF )
			{
				nGroup ++;
				if ( nComment > 0xFFFF ) nGroup ++;
			}
		}
		
		if ( pFile->m_bBogus ) nGroup += 7;
	}
	else
	{
		if ( ! pFile->IsAvailable() ) return FALSE;
	}
	
	if ( m_pSearch == NULL ) nGroup += 8;
	
	nGroup += 4;
	
	// Pass 2: Write the child packet
	
	pPacket->WritePacket( "H", nGroup, TRUE );
	
	if ( pFile->m_bTiger && pFile->m_bSHA1 )
	{
		pPacket->WritePacket( "URN", 3 + sizeof(SHA1) + sizeof(TIGEROOT) );
		pPacket->WriteString( "bp" );
		pPacket->Write( &pFile->m_pSHA1, sizeof(SHA1) );
		pPacket->Write( &pFile->m_pTiger, sizeof(TIGEROOT) );
	}
	else if ( pFile->m_bTiger )
	{
		pPacket->WritePacket( "URN", 4 + sizeof(TIGEROOT) );
		pPacket->WriteString( "ttr" );
		pPacket->Write( &pFile->m_pTiger, sizeof(TIGEROOT) );
	}
	else if ( pFile->m_bSHA1 )
	{
		pPacket->WritePacket( "URN", 5 + sizeof(SHA1) );
		pPacket->WriteString( "sha1" );
		pPacket->Write( &pFile->m_pSHA1, sizeof(SHA1) );
	}
	
	if ( pFile->m_bED2K )
	{
		pPacket->WritePacket( "URN", 5 + sizeof(MD4) );
		pPacket->WriteString( "ed2k" );
		pPacket->Write( &pFile->m_pED2K, sizeof(MD4) );
	}
	
	if ( m_pSearch == NULL || m_pSearch->m_bWantDN )
	{
		if ( pFile->GetSize() <= 0xFFFFFFFF )
		{
			pPacket->WritePacket( "DN", pPacket->GetStringLen( pFile->m_sName ) + 4 );
			pPacket->WriteLongBE( (DWORD)pFile->GetSize() );
			pPacket->WriteString( pFile->m_sName, FALSE );
		}
		else
		{
			pPacket->WritePacket( "SZ", 8 );
			pPacket->WriteInt64( pFile->GetSize() );
			pPacket->WritePacket( "DN", pPacket->GetStringLen( pFile->m_sName ) );
			pPacket->WriteString( pFile->m_sName, FALSE );
		}
		
		if ( bCollection ) pPacket->WritePacket( "COLLECT", 0 );
	}
	
	{
		CSingleLock pQueueLock( &UploadQueues.m_pSection, TRUE );
		
		CUploadQueue* pQueue = UploadQueues.SelectQueue( PROTOCOL_HTTP, pFile );
		pPacket->WritePacket( "G", 1 );
		pPacket->WriteByte( pQueue ? pQueue->m_nIndex + 1 : 0 );
	}
	
	if ( pFile->IsAvailable() && ( m_pSearch == NULL || m_pSearch->m_bWantURL ) )
	{
		pPacket->WritePacket( "URL", 0 );
		
		if ( int nCount = pFile->m_pSources.GetCount() )
		{
			pPacket->WritePacket( "CSC", 2 );
			pPacket->WriteShortBE( (WORD)nCount );
		}
		
		if ( bPreview )
		{
			pPacket->WritePacket( "PVU", 0 );
		}
	}
	
	if ( strMetadata.GetLength() )
	{
		pPacket->WritePacket( "MD", pPacket->GetStringLen( strMetadata ) );
		pPacket->WriteString( strMetadata, FALSE );
	}
	
	if ( m_pSearch == NULL || m_pSearch->m_bWantCOM )
	{
		if ( strComment.GetLength() )
		{
			pPacket->WritePacket( "COM", pPacket->GetStringLen( strComment ) );
			pPacket->WriteString( strComment, FALSE );
		}
		
		if ( pFile->m_bBogus ) pPacket->WritePacket( "BOGUS", 0 );
	}
	
	if ( m_pSearch == NULL )
	{
		pPacket->WritePacket( "ID", 4 );
		pPacket->WriteLongBE( pFile->m_nIndex );
	}
	
	return TRUE;
}

//////////////////////////////////////////////////////////////////////
// CLocalSearch execute partial files

int CLocalSearch::ExecutePartialFiles(int nMaximum)
{
	ASSERT( m_nProtocol == PROTOCOL_G2 );
	ASSERT( m_pSearch != NULL );
	
	if ( m_pSearch->m_bTiger == FALSE && m_pSearch->m_bSHA1 == FALSE &&
		 m_pSearch->m_bED2K  == FALSE && m_pSearch->m_bBTH == FALSE ) return 0;
	
	CSingleLock pLock( &Transfers.m_pSection );
	if ( ! pLock.Lock( 50 ) ) return 0;
	
	int nCount = 0;
	m_pPacket = NULL;
	
	for ( POSITION pos = Downloads.GetIterator() ; pos ; )
	{
		CDownload* pDownload = Downloads.GetNext( pos );
		
		if ( ! pDownload->IsShared() ) continue;
		
		if (	( m_pSearch->m_bTiger && pDownload->m_bTiger && m_pSearch->m_pTiger == pDownload->m_pTiger )
			||	( m_pSearch->m_bSHA1  && pDownload->m_bSHA1  && m_pSearch->m_pSHA1  == pDownload->m_pSHA1 )
			||	( m_pSearch->m_bED2K  && pDownload->m_bED2K  && m_pSearch->m_pED2K  == pDownload->m_pED2K )
			||	( m_pSearch->m_bBTH   && pDownload->m_bBTH   && m_pSearch->m_pBTH   == pDownload->m_pBTH ) )
		{
			if ( pDownload->m_bBTH || pDownload->IsStarted() )
			{
				if ( m_pPacket == NULL ) CreatePacketG2();
				AddHit( pDownload, nCount++ );
			}
		}
	}
	
	if ( m_pPacket != NULL )
	{
		WriteTrailerG2();
		DispatchPacket();
	}
	
	return nCount;
}

//////////////////////////////////////////////////////////////////////
// CLocalSearch add download hit

void CLocalSearch::AddHit(CDownload* pDownload, int nIndex)
{
	ASSERT( m_pPacket != NULL );
	CG2Packet* pPacket = (CG2Packet*)m_pPacket;
	DWORD nGroup = 2 + 4 + 4;
	CString strURL;
	
	if ( pDownload->m_bTiger && pDownload->m_bSHA1 )
	{
		nGroup += 5 + 3 + sizeof(SHA1) + sizeof(TIGEROOT);
	}
	else if ( pDownload->m_bSHA1 )
	{
		nGroup += 5 + 5 + sizeof(SHA1);
	}
	else if ( pDownload->m_bTiger )
	{
		nGroup += 5 + 4 + sizeof(TIGEROOT);
	}
	
	if ( pDownload->m_bED2K )
	{
		nGroup += 5 + 5 + sizeof(MD4);
	}
	
	if ( pDownload->m_bBTH )
	{

⌨️ 快捷键说明

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