📄 localsearch.cpp
字号:
//
// 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 + -