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

📄 queryhashtable.cpp

📁 著名的下载软件核心Shareaza
💻 CPP
📖 第 1 页 / 共 2 页
字号:
			if ( nCount & 1 )
				pBuffer[ nCount >> 1 ] |= nPatch;
			else
				pBuffer[ nCount >> 1 ] = nPatch << 4;

			if ( nMask == 0x80 )
			{
				nMask = 1;
				pHashT ++;
				pHashS ++;
			}
			else
			{
				nMask <<= 1;
			}
		}

		pPatch->WriteZLib( pBuffer, nCount / 2 );
		pNeighbour->Send( pPatch );
	}
	
	delete [] pBuffer;
	m_bLive = TRUE;

	return TRUE;
}

//////////////////////////////////////////////////////////////////////
// CQueryHashTable packet handler

BOOL CQueryHashTable::OnPacket(CPacket* pPacket)
{
	if ( pPacket->m_nLength < 1 ) return FALSE;
	
	if ( pPacket->m_nProtocol == PROTOCOL_G1 )
	{
		CG1Packet* pG1 = (CG1Packet*)pPacket;
		if ( pG1->m_nTTL != 1 )   return FALSE;
		if ( pG1->m_nHops != 0 )  return FALSE;
	}
	else
	{
		CG2Packet* pG2 = (CG2Packet*)pPacket;
		DWORD nLength = pG2->m_nLength;
		if ( pG2->m_bCompound ) pG2->SkipCompound( nLength );
	}
	
	BYTE nVariant = pPacket->ReadByte();
	
	if ( nVariant == 0 )
	{
		return OnReset( pPacket );
	}
	else if ( nVariant == 1 )
	{
		return OnPatch( pPacket );
	}
	
	return FALSE;
}

//////////////////////////////////////////////////////////////////////
// CQueryHashTable reset handler

BOOL CQueryHashTable::OnReset(CPacket* pPacket)
{
	if ( pPacket->m_nLength != 6 ) return FALSE;
	
	DWORD nHashSize	= 0;
	
	BOOL bGrouped = m_pGroup != NULL;
	if ( bGrouped ) QueryHashMaster.Remove( this );
	
	if ( pPacket->m_nProtocol == PROTOCOL_G1 )
	{
		nHashSize	= pPacket->ReadLongLE();
		m_nInfinity	= pPacket->ReadByte();
	}
	else
	{
		nHashSize	= pPacket->ReadLongBE();
		m_nInfinity	= pPacket->ReadByte();
	}
	
	if ( nHashSize < 64 ) return FALSE;	// Minimum size
	
	if ( nHashSize != m_nHash || m_pHash == NULL )
	{
		if ( m_pHash ) delete [] m_pHash;
		m_pHash = NULL;
		
		for ( m_nHash = 1, m_nBits = 0 ; m_nHash < nHashSize ; m_nBits++ ) m_nHash *= 2;
		if ( m_nHash != nHashSize ) return FALSE;
		if ( m_nBits > 24 ) return FALSE;
		
		m_pHash	= new BYTE[ ( m_nHash >> 3 ) + 1 ];
	}
	
	FillMemory( m_pHash, ( m_nHash >> 3 ) + 1, 0xFF );
	
	if ( bGrouped ) QueryHashMaster.Add( this );
	
	m_bLive		= FALSE;
	m_nCookie	= GetTickCount();
	m_nCount	= 0;
	
	m_pBuffer->Clear();
	
	return TRUE;
}

//////////////////////////////////////////////////////////////////////
// CQueryHashTable patch handler

BOOL CQueryHashTable::OnPatch(CPacket* pPacket)
{
	if ( pPacket->m_nLength < 5 ) return FALSE;
	if ( m_pHash == NULL ) return FALSE;
	if ( m_pBuffer == NULL ) return FALSE;
	
	BYTE nSequence		= pPacket->ReadByte();
	BYTE nMaximum		= pPacket->ReadByte();
	BYTE nCompression	= pPacket->ReadByte();
	BYTE nBits			= pPacket->ReadByte();
	
	if ( nBits != 1 && nBits != 4 && nBits != 8 ) return FALSE;
	if ( nSequence < 1 || nSequence > nMaximum ) return FALSE;
	if ( nCompression > 1 ) return FALSE;
	
	if ( nSequence == 1 ) m_pBuffer->Clear();
	
	m_pBuffer->Add(	pPacket->m_pBuffer + pPacket->m_nPosition,
					pPacket->m_nLength - pPacket->m_nPosition );
	
	if ( nSequence < nMaximum ) return TRUE;
	
	if ( nCompression == 1 )
	{
		if ( ! m_pBuffer->Inflate( m_nHash + 4 ) )
		{
			m_pBuffer->Clear();
			return FALSE;
		}
	}
	
	if ( m_pBuffer->m_nLength != m_nHash / ( 8 / nBits ) )
	{
		m_pBuffer->Clear();
		return FALSE;
	}
	
	BYTE* pData		= m_pBuffer->m_pBuffer;
	BYTE* pHash		= m_pHash;
	
	BOOL bGroup		= ( m_pGroup != NULL && m_pGroup->m_nHash == m_nHash );
	BYTE* pGroup	= bGroup ? m_pGroup->m_pHash : NULL;
	
	if ( nBits == 1 )
	{
		for ( DWORD nPosition = ( m_nHash >> 3 ) ; nPosition ; nPosition--, pHash++, pData++ )
		{
			for ( BYTE nMask = 1 ; ; nMask <<= 1 )
			{
				if ( *pData & nMask )
				{
					if ( *pHash & nMask )
					{
						m_nCount ++;
						*pHash &= ~nMask;
						if ( bGroup )
						{
#ifdef _DEBUG
							ASSERT( *pGroup < 255 );
							if ( *pGroup == 0 ) m_pGroup->m_nCount++;
#endif
							(*pGroup) ++;
						}
					}
					else
					{
						m_nCount --;
						*pHash |= nMask;
						
						if ( bGroup )
						{
#ifdef _DEBUG
							ASSERT( *pGroup );
							if ( *pGroup == 1 ) m_pGroup->m_nCount--;
#endif
							(*pGroup) --;
						}
					}
				}
				
				pGroup++;
				if ( nMask == 0x80 ) break;
			}
		}
	}
	else
	{
		BYTE nMask = 1;
		
		for ( DWORD nPosition = 0 ; nPosition < m_nHash ; nPosition++, pData++, pGroup++ )
		{
			if ( nBits == 8 )
			{
				if ( *pData )
				{
					if ( *pHash & nMask )
					{
						m_nCount++;
						*pHash &= ~nMask;
						if ( bGroup ) (*pGroup) ++;
					}
					else
					{
						m_nCount--;
						*pHash |= nMask;
						if ( bGroup ) (*pGroup) --;
					}
				}
			}
			else
			{
				if ( *pData & 0xF0 )
				{
					if ( *pHash & nMask )
					{
						m_nCount++;
						*pHash &= ~nMask;
						if ( bGroup ) (*pGroup) ++;
					}
					else
					{
						m_nCount--;
						*pHash |= nMask;
						if ( bGroup ) (*pGroup) --;
					}
				}
				
				if ( ++nPosition >= m_nHash ) return FALSE;
				pGroup ++;
				nMask <<= 1;
				
				if ( *pData & 0x0F )
				{
					if ( *pHash & nMask )
					{
						m_nCount++;
						*pHash &= ~nMask;
						if ( bGroup ) *pGroup ++;
					}
					else
					{
						m_nCount--;
						*pHash |= nMask;
						if ( bGroup ) *pGroup --;
					}
				}
			}
			
			if ( nMask == 0x80 )
			{
				pHash++;
				nMask = 1;
			}
			else
			{
				nMask <<= 1;
			}
		}
	}
	
	m_bLive		= TRUE;
	m_nCookie	= GetTickCount();
	
	if ( bGroup ) QueryHashMaster.Invalidate();
	
	return TRUE;
}

//////////////////////////////////////////////////////////////////////
// CQueryHashTable add phrases and words

int CQueryHashTable::AddPhrase(LPCTSTR pszPhrase)
{
	if ( m_pHash == NULL ) return 0;
	
	LPCTSTR pszPtr = pszPhrase;
	int nCount = 0;
	
	for ( int nStart = 0, nPos = 0 ; *pszPtr ; nPos++, pszPtr++ )
	{
		if ( ! IsCharacter( *pszPtr ) )
		{
			if ( nStart < nPos )
			{
				nCount += Add( pszPhrase, nStart, nPos - nStart );
			}
			
			nStart = nPos + 1;
		}
	}
	
	if ( nStart < nPos )
	{
		nCount += Add( pszPhrase, nStart, nPos - nStart );
	}
	
	return nCount;
}

int CQueryHashTable::AddString(LPCTSTR pszString)
{
	if ( m_pHash == NULL ) return 0;
	return Add( pszString, 0, _tcslen( pszString ) );
}

int CQueryHashTable::Add(LPCTSTR pszString, int nStart, int nLength)
{
	if ( ! nLength || ! IsWord( pszString, nStart, nLength ) ) return 0;
	
	m_nCookie = GetTickCount();
	
	DWORD nHash	= HashWord( pszString, nStart, nLength, m_nBits );
	BYTE* pHash	= m_pHash + ( nHash >> 3 );
	BYTE nMask	= 1 << ( nHash & 7 );
	
	if ( *pHash & nMask )
	{
		m_nCount++;
		*pHash &= ~nMask;
	}
	
	if ( nLength >= 5 )
	{
		nHash	= HashWord( pszString, nStart, nLength - 1, m_nBits );
		pHash	= m_pHash + ( nHash >> 3 );
		nMask	= 1 << ( nHash & 7 );
		
		if ( *pHash & nMask )
		{
			m_nCount++;
			*pHash &= ~nMask;
		}
		
		nHash	= HashWord( pszString, nStart, nLength - 2, m_nBits );
		pHash	= m_pHash + ( nHash >> 3 );
		nMask	= 1 << ( nHash & 7 );
		
		if ( *pHash & nMask )
		{
			m_nCount++;
			*pHash &= ~nMask;
		}
		
		return 3;
	}
	
	return 1;
}

//////////////////////////////////////////////////////////////////////
// CQueryHashTable check phrases and words

BOOL CQueryHashTable::CheckPhrase(LPCTSTR pszPhrase)
{
	if ( ! m_bLive || m_pHash == NULL || ! *pszPhrase ) return TRUE;

	int nWordCount	= 0;
	int nWordHits	= 0;

	LPCTSTR pszPtr	= pszPhrase;
	BOOL bNegate	= FALSE;
	BOOL bSpace		= TRUE;

	for ( int nStart = 0, nPos = 0 ; *pszPtr ; nPos++, pszPtr++ )
	{
		if ( IsCharacter( *pszPtr ) )
		{
			bSpace = FALSE;
		}
		else
		{
			if ( nStart < nPos && ! bNegate && IsWord( pszPhrase, nStart, nPos - nStart ) )
			{
				nWordCount++;
				DWORD nHash	= HashWord( pszPhrase, nStart, nPos - nStart, m_nBits );
				BYTE* pHash	= m_pHash + ( nHash >> 3 );
				BYTE nMask	= 1 << ( nHash & 7 );
				if ( ! ( *pHash & nMask ) ) nWordHits++;
			}
			
			nStart	= nPos + 1;
			bNegate = bSpace && ( *pszPtr == '-' );
			bSpace	= ( *pszPtr == ' ' );
		}
	}
	
	if ( nStart < nPos && ! bNegate && IsWord( pszPhrase, nStart, nPos - nStart ) )
	{
		nWordCount++;
		DWORD nHash	= HashWord( pszPhrase, nStart, nPos - nStart, m_nBits );
		BYTE* pHash	= m_pHash + ( nHash >> 3 );
		BYTE nMask	= 1 << ( nHash & 7 );
		if ( ! ( *pHash & nMask ) ) nWordHits++;
	}
	
	return ( nWordCount >= 3 ) ? ( nWordHits * 3 / nWordCount >= 2 ) : ( nWordHits == nWordCount );
}

BOOL CQueryHashTable::CheckString(LPCTSTR pszString)
{
	if ( ! m_bLive || m_pHash == NULL || ! *pszString ) return TRUE;

	DWORD nHash	= HashWord( pszString, 0, _tcslen( pszString ), m_nBits );
	BYTE* pHash	= m_pHash + ( nHash >> 3 );
	BYTE nMask	= 1 << ( nHash & 7 );

	return ! ( *pHash & nMask );
}

//////////////////////////////////////////////////////////////////////
// CQueryHashTable check query object

BOOL CQueryHashTable::Check(CQuerySearch* pSearch)
{
	if ( ! m_bLive || m_pHash == NULL ) return TRUE;
	
	if ( pSearch->m_bSHA1 || pSearch->m_bED2K || pSearch->m_bBTH )
	{
		if ( pSearch->m_bSHA1 )
		{
			if ( CheckString( CSHA::HashToString( &pSearch->m_pSHA1, TRUE ) ) ) return TRUE;
		}
		
		if ( pSearch->m_bED2K )
		{
			if ( CheckString( CED2K::HashToString( &pSearch->m_pED2K, TRUE ) ) ) return TRUE;
		}
		
		if ( pSearch->m_bBTH )
		{
			if ( CheckString( _T("urn:btih:") + CSHA::HashToString( &pSearch->m_pBTH, FALSE ) ) ) return TRUE;
		}
		
		return FALSE;
	}
	
	LPCTSTR* pWordPtr	= pSearch->m_pWordPtr;
	DWORD* pWordLen		= pSearch->m_pWordLen;
	DWORD nWordHits		= 0;
	
	for ( int nWord = pSearch->m_nWords ; nWord > 0 ; nWord--, pWordPtr++, pWordLen++ )
	{
		if ( **pWordPtr == '-' ) continue;
		
		DWORD nHash	= HashWord( *pWordPtr, 0, *pWordLen, m_nBits );
		BYTE* pHash	= m_pHash + ( nHash >> 3 );
		BYTE nMask	= 1 << ( nHash & 7 );
		if ( ! ( *pHash & nMask ) ) nWordHits++;
	}
	
	return ( pSearch->m_nWords >= 3 ) ? ( nWordHits * 3 / pSearch->m_nWords >= 2 ) : ( nWordHits == pSearch->m_nWords );
}

//////////////////////////////////////////////////////////////////////
// CQueryHashTable hash functions

DWORD CQueryHashTable::HashWord(LPCTSTR pszString, int nStart, int nLength, int nBits)
{
	DWORD nNumber	= 0;
	int nByte		= 0;

	pszString += nStart;

	for ( int nChar = 0 ; nChar < nLength ; nChar++, pszString++ )
	{
		int nValue = tolower( *pszString ) & 0xFF; 

		nValue = nValue << ( nByte * 8 );
		nByte = ( nByte + 1 ) & 3;

		nNumber = nNumber ^ nValue;
	}

	return HashNumber( nNumber, nBits );
}

DWORD CQueryHashTable::HashNumber(DWORD nNumber, int nBits)
{
	unsigned __int64 nProduct	= (unsigned __int64)nNumber * (unsigned __int64)0x4F1BBCDC;
	unsigned __int64 nHash		= nProduct << 32;
	nHash = nHash >> ( 32 + ( 32 - nBits ) );
	return (DWORD)nHash;
}

//////////////////////////////////////////////////////////////////////
// CQueryHashTable calculate percent full

int CQueryHashTable::GetPercent()
{
	if ( ! m_pHash || ! m_nHash ) return 0;
	return m_nCount * 100 / m_nHash;
}

⌨️ 快捷键说明

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