📄 querysearch.cpp
字号:
pPacket->Read( &m_pSHA1, sizeof(SHA1) );
}
else if ( nLength >= 44 && ( strURN == _T("bp") || strURN == _T("bitprint") ) )
{
m_bSHA1 = TRUE;
pPacket->Read( &m_pSHA1, sizeof(SHA1) );
m_bTiger = TRUE;
pPacket->Read( &m_pTiger, sizeof(TIGEROOT) );
}
else if ( nLength >= 24 && ( strURN == _T("ttr") || strURN == _T("tree:tiger/") ) )
{
m_bTiger = TRUE;
pPacket->Read( &m_pTiger, sizeof(TIGEROOT) );
}
else if ( nLength >= 16 && strURN == _T("ed2k") )
{
m_bED2K = TRUE;
pPacket->Read( &m_pED2K, sizeof(MD4) );
}
else if ( nLength >= 20 && strURN == _T("btih") )
{
m_bBTH = TRUE;
pPacket->Read( &m_pBTH, sizeof(SHA1) );
}
}
else if ( strcmp( szType, "DN" ) == 0 )
{
m_sSearch = pPacket->ReadString( nLength );
}
else if ( strcmp( szType, "MD" ) == 0 )
{
CString strXML = pPacket->ReadString( nLength );
m_pXML->Delete();
m_pXML = CXMLElement::FromString( strXML );
m_pSchema = NULL;
if ( m_pXML != NULL )
{
if ( CXMLAttribute *pURI = m_pXML->GetAttribute( CXMLAttribute::schemaName ) )
{
m_pSchema = SchemaCache.Get( pURI->GetValue() );
}
else if ( m_pSchema = SchemaCache.Guess( m_pXML->GetName() ) )
{
CXMLElement* pRoot = m_pSchema->Instantiate( TRUE );
pRoot->AddElement( m_pXML );
m_pXML = pRoot;
}
}
}
else if ( strcmp( szType, "SZR" ) == 0 )
{
if ( nLength == 8 )
{
m_nMinSize = pPacket->ReadLongBE();
m_nMaxSize = pPacket->ReadLongBE();
if ( m_nMaxSize == 0xFFFFFFFF ) m_nMaxSize = SIZE_UNKNOWN;
}
else if ( nLength == 16 )
{
m_nMinSize = pPacket->ReadInt64();
m_nMaxSize = pPacket->ReadInt64();
}
}
else if ( strcmp( szType, "G1" ) == 0 )
{
m_bAndG1 = TRUE;
}
pPacket->m_nPosition = nOffset;
}
if ( pPacket->GetRemaining() < 16 ) return FALSE;
pPacket->Read( &m_pGUID, sizeof(GGUID) );
return CheckValid();
}
//////////////////////////////////////////////////////////////////////
// CQuerySearch validity check
BOOL CQuerySearch::CheckValid()
{
BuildWordList();
if ( m_nWords == 1 )
{
if ( _tcsicmp( *m_pWordPtr, _T("mp3") ) == 0 ||
_tcsicmp( *m_pWordPtr, _T("mpg") ) == 0 ||
_tcsicmp( *m_pWordPtr, _T("avi") ) == 0 ||
_tcsicmp( *m_pWordPtr, _T("ogg") ) == 0 ||
_tcsicmp( *m_pWordPtr, _T("mpg") ) == 0 ||
_tcsicmp( *m_pWordPtr, _T("sex") ) == 0 ||
_tcsicmp( *m_pWordPtr, _T("fuck") ) == 0 )
{
return FALSE;
}
}
return m_nWords || m_bSHA1 || m_bTiger || m_bED2K || m_bBTH;
}
//////////////////////////////////////////////////////////////////////
// CQuerySearch schema SHA1 to raw SHA1
BOOL CQuerySearch::GetHashFromXML()
{
if ( ! m_pXML || m_bSHA1 ) return FALSE;
if ( CXMLElement* pBody = m_pXML->GetFirstElement() )
{
CString strHash = pBody->GetAttributeValue( _T("SHA1"), NULL );
m_bSHA1 = CSHA::HashFromString( strHash, &m_pSHA1 );
if ( m_bSHA1 )
{
CXMLAttribute* pAttribute = pBody->GetAttribute( _T("SHA1") );
if ( pAttribute ) pAttribute->Delete();
}
}
return m_bSHA1;
}
//////////////////////////////////////////////////////////////////////
// CQuerySearch matching
BOOL CQuerySearch::Match(LPCTSTR pszFilename, QWORD nSize, LPCTSTR pszSchemaURI, CXMLElement* pXML, SHA1* pSHA1, TIGEROOT* pTiger, MD4* pED2K)
{
if ( nSize < m_nMinSize || nSize > m_nMaxSize ) return FALSE;
if ( m_bSHA1 )
{
return pSHA1 != NULL && ( m_pSHA1 == *pSHA1 );
}
else if ( m_bTiger )
{
return pTiger != NULL && ( m_pTiger == *pTiger );
}
else if ( m_bED2K )
{
return pED2K != NULL && ( memcmp( &m_pED2K, pED2K, sizeof(MD4) ) == 0 );
}
if ( pszSchemaURI && *pszSchemaURI && pXML )
{
TRISTATE bResult = MatchMetadata( pszSchemaURI, pXML );
if ( bResult != TS_UNKNOWN ) return ( bResult == TS_TRUE );
if ( m_sSearch.GetLength() > 0 )
{
if ( MatchMetadataShallow( pszSchemaURI, pXML ) ) return TRUE;
}
}
return m_sSearch.GetLength() && WordMatch( pszFilename, m_sSearch );
}
TRISTATE CQuerySearch::MatchMetadata(LPCTSTR pszSchemaURI, CXMLElement* pXML)
{
if ( ! m_pSchema || ! m_pXML ) return TS_UNKNOWN;
if ( ! pszSchemaURI || ! *pszSchemaURI || ! pXML ) return TS_UNKNOWN;
if ( ! m_pSchema->CheckURI( pszSchemaURI ) ) return TS_FALSE;
CXMLElement* pRoot = m_pXML->GetFirstElement();
int nCount = 0;
for ( POSITION pos = m_pSchema->GetMemberIterator() ; pos ; )
{
CSchemaMember* pMember = m_pSchema->GetNextMember( pos );
CString strSearch = pMember->GetValueFrom( pRoot );
CString strTarget = pMember->GetValueFrom( pXML );
if ( strSearch.GetLength() )
{
if ( strTarget.GetLength() )
{
if ( pMember->m_bNumeric )
{
if ( ! NumberMatch( strTarget, strSearch ) ) return TS_FALSE;
}
else
{
if ( ! WordMatch( strTarget, strSearch ) ) return TS_FALSE;
}
nCount++;
}
else
{
return TS_FALSE;
}
}
}
return ( nCount > 0 ) ? TS_TRUE : TS_UNKNOWN;
}
BOOL CQuerySearch::MatchMetadataShallow(LPCTSTR pszSchemaURI, CXMLElement* pXML)
{
if ( ! pXML || m_sSearch.IsEmpty() ) return FALSE;
if ( CSchema* pSchema = SchemaCache.Get( pszSchemaURI ) )
{
for ( POSITION pos = pSchema->GetMemberIterator() ; pos ; )
{
CSchemaMember* pMember = pSchema->GetNextMember( pos );
if ( pMember->m_bSearched )
{
CString strTarget = pMember->GetValueFrom( pXML, _T(""), FALSE );
if ( WordMatch( strTarget, m_sSearch ) ) return TRUE;
}
}
}
else
{
for ( POSITION pos = pXML->GetAttributeIterator() ; pos ; )
{
CXMLAttribute* pAttribute = pXML->GetNextAttribute( pos );
CString strTarget = pAttribute->GetValue();
if ( WordMatch( strTarget, m_sSearch ) ) return TRUE;
}
}
return FALSE;
}
BOOL CQuerySearch::WordMatch(LPCTSTR pszString, LPCTSTR pszFind)
{
LPCTSTR pszWord = pszFind;
LPCTSTR pszPtr = pszFind;
BOOL bQuote = FALSE;
BOOL bNegate = FALSE;
BOOL bSpace = TRUE;
int nCount = 0;
for ( ; *pszPtr ; pszPtr++ )
{
if ( ( bQuote && *pszPtr == '\"' ) || ( ! bQuote && ( *pszPtr <= ' ' || *pszPtr == '\t' || *pszPtr == '-' || *pszPtr == '\"' ) ) )
{
if ( pszWord < pszPtr )
{
if ( bNegate )
{
if ( _tcsnistr( pszString, pszWord, pszPtr - pszWord ) ) return FALSE;
}
else
{
if ( ! _tcsnistr( pszString, pszWord, pszPtr - pszWord ) ) return FALSE;
}
nCount++;
}
pszWord = pszPtr + 1;
if ( *pszPtr == '\"' )
{
bQuote = ! bQuote;
bSpace = TRUE;
}
else if ( *pszPtr == '-' && bSpace && ! bQuote )
{
bNegate = TRUE;
bSpace = FALSE;
}
else
{
bSpace = ( *pszPtr == ' ' );
}
if ( bNegate && ! bQuote && *pszPtr != '-' ) bNegate = FALSE;
}
else
{
bSpace = FALSE;
}
}
if ( pszWord < pszPtr )
{
if ( bNegate )
{
if ( _tcsnistr( pszString, pszWord, pszPtr - pszWord ) ) return FALSE;
}
else
{
if ( ! _tcsnistr( pszString, pszWord, pszPtr - pszWord ) ) return FALSE;
}
nCount++;
}
return nCount > 0;
}
BOOL CQuerySearch::NumberMatch(const CString& strValue, const CString& strRange)
{
double nValue, nMinimum, nMaximum;
if ( _stscanf( strValue, _T("%lf"), &nValue ) != 1 ) return FALSE;
int nPos = strRange.Find( '-' );
if ( nPos < 0 )
{
return _stscanf( strRange, _T("%lf"), &nMinimum ) == 1 && nValue == nMinimum;
}
else if ( nPos == 0 )
{
return _stscanf( (LPCTSTR)strRange + 1, _T("%lf"), &nMaximum ) && nValue <= nMaximum;
}
else if ( nPos == strRange.GetLength() - 1 )
{
return _stscanf( strRange, _T("%lf"), &nMinimum ) && nValue >= nMinimum;
}
else
{
if ( _stscanf( strRange.Left( nPos ), _T("%lf"), &nMinimum ) != 1 ||
_stscanf( strRange.Mid( nPos + 1 ), _T("%lf"), &nMaximum ) != 1 ) return FALSE;
return nValue >= nMinimum && nValue <= nMaximum;
}
}
//////////////////////////////////////////////////////////////////////
// CQuerySearch word list builder
void CQuerySearch::BuildWordList()
{
m_nWords = 0;
m_sSearch.MakeLower();
AddStringToWordList( m_sSearch );
if ( m_pXML == NULL ) return;
if ( CXMLElement* pXML = m_pXML->GetFirstElement() )
{
if ( m_pSchema != NULL )
{
for ( POSITION pos = m_pSchema->GetMemberIterator() ; pos ; )
{
CSchemaMember* pMember = m_pSchema->GetNextMember( pos );
if ( pMember->m_bIndexed )
{
if ( CXMLAttribute* pAttribute = pXML->GetAttribute( pMember->m_sName ) )
{
pAttribute->m_sValue.MakeLower();
AddStringToWordList( pAttribute->m_sValue );
}
}
}
}
else
{
for ( POSITION pos = pXML->GetAttributeIterator() ; pos ; )
{
CXMLAttribute* pAttribute = pXML->GetNextAttribute( pos );
pAttribute->m_sValue.MakeLower();
AddStringToWordList( pAttribute->m_sValue );
}
}
}
}
void CQuerySearch::AddStringToWordList(LPCTSTR pszString)
{
if ( ! *pszString ) return;
LPCTSTR pszWord = pszString;
LPCTSTR pszPtr = pszString;
BOOL bQuote = FALSE;
BOOL bNegate = FALSE;
BOOL bSpace = TRUE;
for ( ; *pszPtr ; pszPtr++ )
{
if ( IsCharacter( *pszPtr ) )
{
bSpace = FALSE;
}
else
{
if ( ! bNegate && pszWord + 1 < pszPtr && IsWord( pszWord, 0, pszPtr - pszWord ) )
{
if ( ( m_nWords & 0x1F ) == 0 )
{
LPCTSTR* pWordPtr = new LPCTSTR[ ( m_nWords | 0x1F ) + 1 ];
DWORD* pWordLen = new DWORD[ ( m_nWords | 0x1F ) + 1 ];
if ( m_pWordPtr )
{
CopyMemory( pWordPtr, m_pWordPtr, 4 * m_nWords );
CopyMemory( pWordLen, m_pWordLen, 4 * m_nWords );
delete [] m_pWordPtr;
delete [] m_pWordLen;
}
m_pWordPtr = pWordPtr;
m_pWordLen = pWordLen;
}
m_pWordPtr[ m_nWords ] = pszWord;
m_pWordLen[ m_nWords ] = pszPtr - pszWord;
m_nWords++;
}
pszWord = pszPtr + 1;
if ( *pszPtr == '\"' )
{
bQuote = ! bQuote;
bSpace = TRUE;
}
else if ( *pszPtr == '-' && bSpace && ! bQuote )
{
bNegate = TRUE;
bSpace = FALSE;
}
else
{
bSpace = ( *pszPtr == ' ' );
}
if ( bNegate && ! bQuote && *pszPtr != '-' ) bNegate = FALSE;
}
}
if ( ! bNegate && pszWord + 1 < pszPtr && IsWord( pszWord, 0, pszPtr - pszWord ) )
{
if ( ( m_nWords & 0x1F ) == 0 )
{
LPCTSTR* pWordPtr = new LPCTSTR[ ( m_nWords | 0x1F ) + 1 ];
DWORD* pWordLen = new DWORD[ ( m_nWords | 0x1F ) + 1 ];
if ( m_pWordPtr )
{
CopyMemory( pWordPtr, m_pWordPtr, 4 * m_nWords );
CopyMemory( pWordLen, m_pWordLen, 4 * m_nWords );
delete [] m_pWordPtr;
delete [] m_pWordLen;
}
m_pWordPtr = pWordPtr;
m_pWordLen = pWordLen;
}
m_pWordPtr[ m_nWords ] = pszWord;
m_pWordLen[ m_nWords ] = pszPtr - pszWord;
m_nWords++;
}
}
//////////////////////////////////////////////////////////////////////
// CQuerySearch serialization
void CQuerySearch::Serialize(CArchive& ar)
{
int nVersion = 6;
CString strURI;
if ( ar.IsStoring() )
{
ar << nVersion;
ar.Write( &m_pGUID, sizeof(GGUID) );
ar << m_sSearch;
ar << m_bSHA1;
if ( m_bSHA1 ) ar.Write( &m_pSHA1, sizeof(SHA1) );
ar << m_bTiger;
if ( m_bTiger ) ar.Write( &m_pTiger, sizeof(TIGEROOT) );
ar << m_bED2K;
if ( m_bED2K ) ar.Write( &m_pED2K, sizeof(MD4) );
ar << m_bBTH;
if ( m_bBTH ) ar.Write( &m_pBTH, sizeof(SHA1) );
if ( m_pSchema != NULL && m_pXML != NULL )
{
ar << m_pSchema->m_sURI;
m_pXML->Serialize( ar );
}
else
{
ar << strURI;
}
ar << m_bWantURL;
ar << m_bWantDN;
ar << m_bWantXML;
ar << m_bWantCOM;
ar << m_bWantPFS;
}
else
{
ar >> nVersion;
if ( nVersion < 4 ) AfxThrowUserException();
ar.Read( &m_pGUID, sizeof(GGUID) );
ar >> m_sSearch;
ar >> m_bSHA1;
if ( m_bSHA1 ) ar.Read( &m_pSHA1, sizeof(SHA1) );
ar >> m_bTiger;
if ( m_bTiger ) ar.Read( &m_pTiger, sizeof(TIGEROOT) );
ar >> m_bED2K;
if ( m_bED2K ) ar.Read( &m_pED2K, sizeof(MD4) );
if ( nVersion >= 6 ) ar >> m_bBTH;
if ( m_bBTH ) ar.Read( &m_pBTH, sizeof(SHA1) );
ar >> strURI;
if ( strURI.GetLength() )
{
m_pSchema = SchemaCache.Get( strURI );
m_pXML = new CXMLElement();
m_pXML->Serialize( ar );
}
if ( nVersion >= 5 )
{
ar >> m_bWantURL;
ar >> m_bWantDN;
ar >> m_bWantXML;
ar >> m_bWantCOM;
ar >> m_bWantPFS;
}
BuildWordList();
}
}
//////////////////////////////////////////////////////////////////////
// CQuerySearch open window
CSearchWnd* CQuerySearch::OpenWindow()
{
if ( this == NULL ) return NULL;
BuildWordList();
if ( ! CheckValid() ) return NULL;
return new CSearchWnd( this );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -