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