Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members

QueryHit.cpp

Go to the documentation of this file.
00001 //
00002 // QueryHit.cpp
00003 //
00004 // Copyright (c) Shareaza Development Team, 2002-2005.
00005 // This file is part of SHAREAZA (www.shareaza.com)
00006 //
00007 // Shareaza is free software; you can redistribute it
00008 // and/or modify it under the terms of the GNU General Public License
00009 // as published by the Free Software Foundation; either version 2 of
00010 // the License, or (at your option) any later version.
00011 //
00012 // Shareaza is distributed in the hope that it will be useful,
00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 // GNU General Public License for more details.
00016 //
00017 // You should have received a copy of the GNU General Public License
00018 // along with Shareaza; if not, write to the Free Software
00019 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020 //
00021 
00022 #include "StdAfx.h"
00023 #include "Shareaza.h"
00024 #include "Settings.h"
00025 #include "QuerySearch.h"
00026 #include "QueryHit.h"
00027 #include "Network.h"
00028 #include "G1Packet.h"
00029 #include "G2Packet.h"
00030 #include "EDPacket.h"
00031 #include "Transfer.h"
00032 #include "SchemaCache.h"
00033 #include "Schema.h"
00034 #include "ZLib.h"
00035 #include "XML.h"
00036 #include "GGEP.h"
00037 #include "VendorCache.h"
00038 #include "RouteCache.h"
00039 
00040 #include "SHA.h"
00041 #include "TigerTree.h"
00042 #include "ED2K.h"
00043 
00044 #ifdef _DEBUG
00045 #undef THIS_FILE
00046 static char THIS_FILE[]=__FILE__;
00047 #define new DEBUG_NEW
00048 #endif
00049 
00050 
00052 // CQueryHit construction
00053 
00054 CQueryHit::CQueryHit(PROTOCOLID nProtocol, GGUID* pSearchID)
00055 {
00056         m_pNext = NULL;
00057         
00058         if ( pSearchID != NULL )
00059                 m_pSearchID = *pSearchID;
00060         else
00061                 m_pSearchID = (GGUID&)GUID_NULL;
00062         
00063         m_nProtocol             = nProtocol;
00064         m_pClientID             = (GGUID&)GUID_NULL;
00065         m_pAddress.S_un.S_addr = 0;
00066         m_nPort                 = 0;
00067         m_nSpeed                = 0;
00068         m_pVendor               = VendorCache.m_pNull;
00069         
00070         m_bPush                 = TS_UNKNOWN;
00071         m_bBusy                 = TS_UNKNOWN;
00072         m_bStable               = TS_UNKNOWN;
00073         m_bMeasured             = TS_UNKNOWN;
00074         m_bChat                 = FALSE;
00075         m_bBrowseHost   = FALSE;
00076         
00077         m_nGroup                = 0;
00078         m_bSHA1                 = FALSE;
00079         m_bTiger                = FALSE;
00080         m_bED2K                 = FALSE;
00081         m_bBTH                  = FALSE;
00082         m_nIndex                = 0;
00083         m_bSize                 = FALSE;
00084         m_nSize                 = 0;
00085         m_nSources              = 0;
00086         m_nPartial              = 0;
00087         m_bPreview              = FALSE;
00088         m_nUpSlots              = 0;
00089         m_nUpQueue              = 0;    
00090         m_bCollection   = FALSE;
00091         
00092         m_pXML                  = NULL;
00093         m_nRating               = 0;
00094         
00095         m_bBogus                = FALSE;
00096         m_bMatched              = FALSE;
00097         m_bFiltered             = FALSE;
00098         m_bDownload             = FALSE;
00099         m_bNew                  = FALSE;
00100         m_bSelected             = FALSE;
00101         m_bResolveURL   = TRUE;
00102 }
00103 
00104 CQueryHit::~CQueryHit()
00105 {
00106         if ( m_pXML ) delete m_pXML;
00107 }
00108 
00110 // CQueryHit from G1 packet
00111 
00112 CQueryHit* CQueryHit::FromPacket(CG1Packet* pPacket, int* pnHops)
00113 {
00114         CQueryHit* pFirstHit    = NULL;
00115         CQueryHit* pLastHit             = NULL;
00116         CXMLElement* pXML               = NULL;
00117         GGUID pQueryID;
00118         
00119         if ( pPacket->m_nProtocol == PROTOCOL_G2 )
00120         {
00121                 GNUTELLAPACKET pG1;
00122                 if ( ! ((CG2Packet*)pPacket)->SeekToWrapped() ) return NULL;
00123                 pPacket->Read( &pG1, sizeof(pG1) );
00124                 
00125                 pQueryID = pG1.m_pGUID;
00126                 if ( pnHops ) *pnHops = pG1.m_nHops + 1;
00127         }
00128         else
00129         {
00130                 pQueryID = pPacket->m_pGUID;
00131                 if ( pnHops ) *pnHops = pPacket->m_nHops + 1;
00132         }
00133         
00134         try
00135         {
00136                 BYTE    nCount          = pPacket->ReadByte();
00137                 WORD    nPort           = pPacket->ReadShortLE();
00138                 DWORD   nAddress        = pPacket->ReadLongLE();
00139                 DWORD   nSpeed          = pPacket->ReadLongLE();
00140                 
00141                 if ( ! nCount ) AfxThrowUserException();
00142                 
00143                 while ( nCount-- )
00144                 {
00145                         CQueryHit* pHit = new CQueryHit( PROTOCOL_G1, &pQueryID );
00146                         if ( pFirstHit ) pLastHit->m_pNext = pHit;
00147                         else pFirstHit = pHit;
00148                         pLastHit = pHit;
00149                         
00150                         pHit->m_pAddress        = (IN_ADDR&)nAddress;
00151                         pHit->m_nPort           = nPort;
00152                         pHit->m_nSpeed          = nSpeed;
00153                         
00154                         pHit->ReadG1Packet( pPacket );
00155                 }
00156 
00157                 CVendor*        pVendor         = VendorCache.m_pNull;
00158                 BYTE            nPublicSize     = 0;
00159                 BYTE            nFlags[2]       = { 0, 0 };
00160                 WORD            nXMLSize        = 0;
00161                 BOOL            bChat           = FALSE;
00162                 BOOL            bBrowseHost     = FALSE;
00163 
00164                 if ( pPacket->GetRemaining() >= 16 + 5 )
00165                 {
00166                         CHAR szaVendor[ 4 ];
00167                         pPacket->Read( szaVendor, 4 );
00168                         TCHAR szVendor[5] = { szaVendor[0], szaVendor[1], szaVendor[2], szaVendor[3], 0 };
00169                         
00170                         pVendor         = VendorCache.Lookup( szVendor );
00171                         nPublicSize     = pPacket->ReadByte();
00172                 }
00173                 
00174                 if ( pVendor->m_bHTMLBrowse ) bBrowseHost = TRUE;
00175                 
00176                 if ( nPublicSize > pPacket->GetRemaining() - 16 ) AfxThrowUserException();
00177                 
00178                 if ( nPublicSize >= 2 )
00179                 {
00180                         nFlags[0]       = pPacket->ReadByte();
00181                         nFlags[1]       = pPacket->ReadByte();
00182                         nPublicSize -= 2;
00183                 }
00184                 
00185                 if ( nPublicSize >= 2 )
00186                 {
00187                         nXMLSize = pPacket->ReadShortLE();
00188                         nPublicSize -= 2;
00189                         if ( nPublicSize + nXMLSize > pPacket->GetRemaining() - 16 ) AfxThrowUserException();
00190                 }
00191                 
00192                 while ( nPublicSize-- ) pPacket->ReadByte();
00193                 
00194                 if ( pVendor->m_bChatFlag && pPacket->GetRemaining() >= 16 + nXMLSize + 1 )
00195                 {
00196                         bChat = pPacket->PeekByte() == 1;
00197                 }
00198                 
00199                 if ( pPacket->GetRemaining() < 16 + nXMLSize ) nXMLSize = 0;
00200                 
00201                 if ( ( nFlags[0] & G1_QHD_GGEP ) && ( nFlags[1] & G1_QHD_GGEP ) &&
00202                          Settings.Gnutella1.EnableGGEP )
00203                 {
00204                         ReadGGEP( pPacket, &bBrowseHost );
00205                 }
00206                 
00207                 if ( nXMLSize > 0 )
00208                 {
00209                         pPacket->Seek( 16 + nXMLSize, CG1Packet::seekEnd );
00210                         pXML = ReadXML( pPacket, nXMLSize );
00211                 }
00212                 
00213                 if ( ! nPort || Network.IsFirewalledAddress( &nAddress ) )
00214                 {
00215                         nFlags[0] |= G1_QHD_PUSH;
00216                         nFlags[1] |= G1_QHD_PUSH;
00217                 }
00218                 
00219                 GGUID pClientID;
00220                 
00221                 pPacket->Seek( 16, CG1Packet::seekEnd );
00222                 pPacket->Read( &pClientID, sizeof(pClientID) );
00223                 
00224                 DWORD nIndex = 0;
00225                 
00226                 for ( pLastHit = pFirstHit ; pLastHit ; pLastHit = pLastHit->m_pNext, nIndex++ )
00227                 {
00228                         pLastHit->ParseAttributes( &pClientID, pVendor, nFlags, bChat, bBrowseHost );
00229                         pLastHit->Resolve();
00230                         if ( pXML ) pLastHit->ParseXML( pXML, nIndex );
00231                 }
00232                 
00233                 CheckBogus( pFirstHit );
00234         }
00235         catch ( CException* pException )
00236         {
00237                 pException->Delete();
00238                 if ( pXML ) delete pXML;
00239                 if ( pFirstHit ) pFirstHit->Delete();
00240                 return NULL;
00241         }
00242         
00243         if ( pXML ) delete pXML;
00244         
00245         return pFirstHit;
00246 }
00247 
00249 // CQueryHit from G2 packet
00250 
00251 CQueryHit* CQueryHit::FromPacket(CG2Packet* pPacket, int* pnHops)
00252 {
00253         if ( pPacket->IsType( G2_PACKET_HIT_WRAP ) )
00254         {
00255                 return FromPacket( (CG1Packet*)pPacket );
00256         }
00257         
00258         if ( ! pPacket->m_bCompound ) return NULL;
00259         
00260         CQueryHit* pFirstHit    = NULL;
00261         CQueryHit* pLastHit             = NULL;
00262         CXMLElement* pXML               = NULL;
00263         
00264         GGUID           pSearchID;
00265         GGUID           pClientID, pIncrID;
00266         BOOL            bClientID       = FALSE;
00267         
00268         DWORD           nAddress        = 0;
00269         WORD            nPort           = 0;
00270         BOOL            bBusy           = FALSE;
00271         BOOL            bPush           = FALSE;
00272         BOOL            bStable         = TRUE;
00273         BOOL            bBrowseHost     = FALSE;
00274         BOOL            bPeerChat       = FALSE;
00275         CVendor*        pVendor         = VendorCache.m_pNull;
00276         
00277         CString         strNick;
00278         DWORD           nGroupState[8][4];
00279         
00280         ZeroMemory( nGroupState, sizeof(nGroupState) );
00281         
00282         try
00283         {
00284                 BOOL bCompound;
00285                 CHAR szType[9];
00286                 DWORD nLength;
00287                 
00288                 while ( pPacket->ReadPacket( szType, nLength, &bCompound ) )
00289                 {
00290                         DWORD nSkip = pPacket->m_nPosition + nLength;
00291                         
00292                         if ( bCompound )
00293                         {
00294                                 if ( strcmp( szType, "H" ) &&
00295                                          strcmp( szType, "HG" ) &&
00296                                          strcmp( szType, "UPRO" ) )
00297                                 {
00298                                         pPacket->SkipCompound( nLength );
00299                                 }
00300                         }
00301                         
00302                         if ( strcmp( szType, "H" ) == 0 && bCompound )
00303                         {
00304                                 CQueryHit* pHit = new CQueryHit( PROTOCOL_G2);
00305                                 
00306                                 if ( pFirstHit ) pLastHit->m_pNext = pHit;
00307                                 else pFirstHit = pHit;
00308                                 pLastHit = pHit;
00309                                 
00310                                 pHit->ReadG2Packet( pPacket, nLength );
00311                         }
00312                         else if ( strcmp( szType, "HG" ) == 0 && bCompound )
00313                         {
00314                                 DWORD nQueued = 0, nUploads = 0, nSpeed = 0;
00315                                 CHAR szInner[9];
00316                                 DWORD nInner;
00317                                 
00318                                 while ( pPacket->m_nPosition < nSkip && pPacket->ReadPacket( szInner, nInner ) )
00319                                 {
00320                                         DWORD nSkipInner = pPacket->m_nPosition + nInner;
00321                                         
00322                                         if ( strcmp( szInner, "SS" ) == 0 && nInner >= 7 )
00323                                         {
00324                                                 nQueued         = pPacket->ReadShortBE();
00325                                                 nUploads        = pPacket->ReadByte();
00326                                                 nSpeed          = pPacket->ReadLongBE();
00327                                         }
00328                                         
00329                                         pPacket->m_nPosition = nSkipInner;
00330                                 }
00331                                 
00332                                 if ( pPacket->m_nPosition < nSkip && nSpeed > 0 )
00333                                 {
00334                                         int nGroup = pPacket->ReadByte();
00335                                         
00336                                         if ( nGroup >= 0 && nGroup < 8 )
00337                                         {
00338                                                 nGroupState[ nGroup ][0] = TRUE;
00339                                                 nGroupState[ nGroup ][1] = nQueued;
00340                                                 nGroupState[ nGroup ][2] = nUploads;
00341                                                 nGroupState[ nGroup ][3] = nSpeed;
00342                                         }
00343                                 }
00344                         }
00345                         else if ( strcmp( szType, "NH" ) == 0 && nLength >= 6 )
00346                         {
00347                                 SOCKADDR_IN pHub;
00348                                 
00349                                 pHub.sin_addr.S_un.S_addr       = pPacket->ReadLongLE();
00350                                 pHub.sin_port                           = htons( pPacket->ReadShortBE() );
00351                                 
00352                                 pIncrID.n[15] ++;
00353                                 Network.NodeRoute->Add( &pIncrID, &pHub );
00354                         }
00355                         else if ( strcmp( szType, "GU" ) == 0 && nLength == 16 )
00356                         {
00357                                 pPacket->Read( &pClientID, sizeof(GGUID) );
00358                                 bClientID       = TRUE;
00359                                 pIncrID         = pClientID;
00360                         }
00361                         else if ( ( strcmp( szType, "NA" ) == 0 || strcmp( szType, "NI" ) == 0 ) && nLength >= 6 )
00362                         {
00363                                 nAddress        = pPacket->ReadLongLE();
00364                                 nPort           = pPacket->ReadShortBE();
00365                         }
00366                         else if ( strcmp( szType, "V" ) == 0 && nLength >= 4 )
00367                         {
00368                                 CString strVendor = pPacket->ReadString( 4 );
00369                                 pVendor = VendorCache.Lookup( strVendor );
00370                         }
00371                         else if ( strcmp( szType, "MD" ) == 0 )
00372                         {
00373                                 CString strXML  = pPacket->ReadString( nLength );
00374                                 LPCTSTR pszXML  = strXML;
00375                                 
00376                                 while ( pszXML && *pszXML )
00377                                 {
00378                                         CXMLElement* pPart = CXMLElement::FromString( pszXML, TRUE );
00379                                         if ( ! pPart ) break;
00380                                         
00381                                         if ( ! pXML ) pXML = new CXMLElement( NULL, _T("Metadata") );
00382                                         pXML->AddElement( pPart );
00383                                         
00384                                         pszXML = _tcsstr( pszXML + 1, _T("<?xml") );
00385                                 }
00386                         }
00387                         else if ( strcmp( szType, "UPRO" ) == 0 && bCompound )
00388                         {
00389                                 CHAR szInner[9];
00390                                 DWORD nInner;
00391                                 
00392                                 while ( pPacket->m_nPosition < nSkip && pPacket->ReadPacket( szInner, nInner ) )
00393                                 {
00394                                         DWORD nSkipInner = pPacket->m_nPosition + nInner;
00395                                         if ( strcmp( szInner, "NICK" ) == 0 )
00396                                         {
00397                                                 strNick = pPacket->ReadString( nInner );
00398                                         }
00399                                         pPacket->m_nPosition = nSkipInner;
00400                                 }
00401                         }
00402                         else if ( strcmp( szType, "BH" ) == 0 )
00403                         {
00404                                 bBrowseHost |= 1;
00405                         }
00406                         else if ( strcmp( szType, "BUP" ) == 0 )
00407                         {
00408                                 bBrowseHost |= 2;
00409                         }
00410                         else if ( strcmp( szType, "PCH" ) == 0 )
00411                         {
00412                                 bPeerChat = TRUE;
00413                         }
00414                         else if ( strcmp( szType, "BUSY" ) == 0 )
00415                         {
00416                                 bBusy = TRUE;
00417                         }
00418                         else if ( strcmp( szType, "UNSTA" ) == 0 )
00419                         {
00420                                 bStable = FALSE;
00421                         }
00422                         else if ( strcmp( szType, "FW" ) == 0 )
00423                         {
00424                                 bPush = TRUE;
00425                         }
00426                         else if ( strcmp( szType, "SS" ) == 0 && nLength > 0 )
00427                         {
00428                                 BYTE nStatus = pPacket->ReadByte();
00429                                 
00430                                 bBusy   = ( nStatus & G2_SS_BUSY ) ? TRUE : FALSE;
00431                                 bPush   = ( nStatus & G2_SS_PUSH ) ? TRUE : FALSE;
00432                                 bStable = ( nStatus & G2_SS_STABLE ) ? TRUE : FALSE;
00433                                 
00434                                 if ( nLength >= 1+4+2+1 )
00435                                 {
00436                                         nGroupState[0][0] = TRUE;
00437                                         nGroupState[0][3] = pPacket->ReadLongBE();
00438                                         nGroupState[0][1] = pPacket->ReadShortBE();
00439                                         nGroupState[0][2] = pPacket->ReadByte();
00440                                 }
00441                         }
00442                         
00443                         pPacket->m_nPosition = nSkip;
00444                 }
00445                 
00446                 if ( ! bClientID ) AfxThrowUserException();
00447                 if ( pPacket->GetRemaining() < 17 ) AfxThrowUserException();
00448                 
00449                 BYTE nHops = pPacket->ReadByte() + 1;
00450                 if ( pnHops ) *pnHops = nHops;
00451                 
00452                 pPacket->Read( &pSearchID, sizeof(GGUID) );
00453                 
00454                 if ( ! bPush ) bPush = ( nPort == 0 || Network.IsFirewalledAddress( &nAddress ) );
00455                 
00456                 DWORD nIndex = 0;
00457                 
00458                 for ( pLastHit = pFirstHit ; pLastHit ; pLastHit = pLastHit->m_pNext, nIndex++ )
00459                 {
00460                         if ( nGroupState[ pLastHit->m_nGroup ][0] == FALSE ) pLastHit->m_nGroup = 0;
00461                         
00462                         pLastHit->m_pSearchID   = pSearchID;
00463                         pLastHit->m_pClientID   = pClientID;
00464                         pLastHit->m_pAddress    = *(IN_ADDR*)&nAddress;
00465                         pLastHit->m_nPort               = nPort;
00466                         pLastHit->m_pVendor             = pVendor;
00467                         pLastHit->m_nSpeed              = nGroupState[ pLastHit->m_nGroup ][3];
00468                         pLastHit->m_bBusy               = bBusy   ? TS_TRUE : TS_FALSE;
00469                         pLastHit->m_bPush               = bPush   ? TS_TRUE : TS_FALSE;
00470                         pLastHit->m_bStable             = bStable ? TS_TRUE : TS_FALSE;
00471                         pLastHit->m_bMeasured   = pLastHit->m_bStable;
00472                         pLastHit->m_nUpSlots    = nGroupState[ pLastHit->m_nGroup ][2];
00473                         pLastHit->m_nUpQueue    = nGroupState[ pLastHit->m_nGroup ][1];
00474                         pLastHit->m_bChat               = bPeerChat;
00475                         pLastHit->m_bBrowseHost = bBrowseHost;
00476                         pLastHit->m_sNick               = strNick;
00477                         pLastHit->m_bPreview    &= pLastHit->m_bPush == TS_FALSE;
00478                         
00479                         if ( pLastHit->m_nUpSlots > 0 )
00480                         {
00481                                 pLastHit->m_bBusy = ( pLastHit->m_nUpSlots <= pLastHit->m_nUpQueue ) ? TS_TRUE : TS_FALSE;
00482                         }
00483                         
00484                         pLastHit->Resolve();
00485                         if ( pXML ) pLastHit->ParseXML( pXML, nIndex );
00486                 }
00487                 
00488                 CheckBogus( pFirstHit );
00489         }
00490         catch ( CException* pException )
00491         {
00492                 pException->Delete();
00493                 if ( pXML ) delete pXML;
00494                 if ( pFirstHit ) pFirstHit->Delete();
00495                 return NULL;
00496         }
00497         
00498         if ( pXML ) delete pXML;
00499         
00500         return pFirstHit;
00501 }
00502 
00504 // CQueryHit from ED2K packet
00505 
00506 CQueryHit* CQueryHit::FromPacket(CEDPacket* pPacket, SOCKADDR_IN* pServer, DWORD m_nServerFlags, GGUID* pSearchID )
00507 {
00508         CQueryHit* pFirstHit    = NULL;
00509         CQueryHit* pLastHit             = NULL;
00510         MD4 pHash;
00511         
00512         if ( pPacket->m_nType == ED2K_S2C_SEARCHRESULTS ||
00513                  pPacket->m_nType == ED2K_S2CG_SEARCHRESULT )
00514         {
00515                 DWORD nCount = 1;
00516                 
00517                 if ( pPacket->m_nType == ED2K_S2C_SEARCHRESULTS )
00518                 {
00519                         if ( pPacket->GetRemaining() < 4 ) return NULL;
00520                         nCount = pPacket->ReadLongLE();
00521                 }
00522                 
00523                 while ( nCount-- > 0 && pPacket->GetRemaining() >= sizeof(MD4) + 10 )
00524                 {
00525                         CQueryHit* pHit = new CQueryHit( PROTOCOL_ED2K, pSearchID );
00526                         if ( pFirstHit ) pLastHit->m_pNext = pHit;
00527                         else pFirstHit = pHit;
00528                         pLastHit = pHit;
00529 
00530                         // Enable chat for ed2k hits
00531                         pHit->m_bChat = TRUE;
00532                         
00533                         pHit->m_pVendor = VendorCache.m_pED2K;
00534                         if ( ! pHit->ReadEDPacket( pPacket, pServer, m_nServerFlags ) ) break;
00535                         pHit->Resolve();
00536 
00537                         if( pHit->m_bPush == TS_TRUE )
00538                         {
00539                                 //pHit->m_sNick         = _T("(Low ID)");
00540                                 pHit->m_nPort           = 0;
00541                         }
00542                 }
00543         }
00544         else if (       pPacket->m_nType == ED2K_S2C_FOUNDSOURCES ||
00545                                 pPacket->m_nType == ED2K_S2CG_FOUNDSOURCES )
00546         {
00547                 if ( pPacket->GetRemaining() < sizeof(MD4) + 1 ) return NULL;
00548                 pPacket->Read( &pHash, sizeof(MD4) );
00549 
00550                 BYTE nCount = pPacket->ReadByte();
00551                 
00552                 while ( nCount-- > 0 && pPacket->GetRemaining() >= 6 )
00553                 {
00554                         CQueryHit* pHit = new CQueryHit( PROTOCOL_ED2K, pSearchID );
00555                         if ( pFirstHit ) pLastHit->m_pNext = pHit;
00556                         else pFirstHit = pHit;
00557                         pLastHit = pHit;
00558                         
00559                         // Enable chat for ed2k hits
00560                         pHit->m_bChat = TRUE;
00561 
00562                         pHit->m_bED2K = TRUE;
00563                         pHit->m_pED2K = pHash;
00564                         pHit->m_pVendor = VendorCache.m_pED2K;
00565                         pHit->ReadEDAddress( pPacket, pServer );
00566                         pHit->Resolve();
00567                 }
00568         }
00569 
00570         // Enable chat for ed2k hits
00571         //pFirstHit->m_bChat = TRUE;
00572         
00573         // CheckBogus( pFirstHit );
00574         
00575         return pFirstHit;
00576 }
00577 
00579 // CQueryHit bogus checking
00580 
00581 BOOL CQueryHit::CheckBogus(CQueryHit* pFirstHit)
00582 {
00583         CString strBase, strTest;
00584         int nBogus = 0;
00585         
00586         if ( pFirstHit == NULL ) return TRUE;
00587         
00588         for ( CQueryHit* pHit = pFirstHit->m_pNext ; pHit ; pHit = pHit->m_pNext )
00589         {
00590                 LPCTSTR pszBase = pFirstHit->m_sName;
00591                 LPCTSTR pszTest = pHit->m_sName;
00592                 
00593                 if ( *pszBase == 0 || *pszTest == 0 ) continue;
00594                 
00595                 BOOL bDots = FALSE;
00596                 BOOL bDiff = FALSE;
00597                 
00598                 while ( TRUE )
00599                 {
00600                         while ( *pszBase && ( *pszBase == '!' || *pszBase == '@' || ! _istgraph( *pszBase ) ) ) pszBase++;
00601                         while ( *pszTest && ( *pszTest == '!' || *pszTest == '@' || ! _istgraph( *pszTest ) ) ) pszTest++;
00602                         
00603                         if ( ! *pszBase || ! *pszTest ) break;
00604                         
00605                         if ( *pszBase == '.' || *pszTest == '.' )
00606                         {
00607                                 bDots = TRUE;
00608                                 
00609                                 if ( *pszBase == '.' && *pszTest == '.' )
00610                                 {
00611                                         if ( bDiff )
00612                                         {
00613                                                 bDiff = FALSE;
00614                                                 break;
00615                                         }
00616                                 }
00617                                 else
00618                                 {
00619                                         bDiff = FALSE;
00620                                         break;
00621                                 }
00622                         }
00623                         
00624                         TCHAR cBaseChar = {0}; TCHAR cTestChar = {0};
00625                         if ( *pszBase == 0x3C2 )
00626                                 cBaseChar = ToLowerCase[ *pszBase + 1 ]; // replace the last greek sigma with an ordinary
00627                         else
00628                                 cBaseChar = ToLowerCase[ *pszBase ];
00629 
00630                         if ( *pszTest == 0x3C2 )
00631                                 cTestChar = ToLowerCase[ *pszTest + 1 ];
00632                         else
00633                                 cTestChar = ToLowerCase[ *pszTest ];
00634 
00635                         if ( ! bDiff && cBaseChar != cTestChar ) bDiff = TRUE;
00636                         
00637                         pszBase++;
00638                         pszTest++;
00639                 }
00640                 
00641                 if ( bDots && bDiff )
00642                 {
00643                         if ( ++nBogus >= 2 ) break;
00644                 }
00645         }
00646         
00647         if ( nBogus < 2 ) return FALSE;
00648         
00649         for ( CQueryHit* pHit = pFirstHit ; pHit ; pHit = pHit->m_pNext )
00650         {
00651                 pHit->m_bBogus = TRUE;
00652         }
00653         
00654         return TRUE;
00655 }
00656 
00658 // CQueryHit XML metadata reader
00659 
00660 CXMLElement* CQueryHit::ReadXML(CG1Packet* pPacket, int nSize)
00661 {
00662         BYTE* pRaw = new BYTE[ nSize ];
00663         pPacket->Read( pRaw, nSize );
00664         
00665         CString strXML;
00666         
00667         if ( nSize >= 9 && strncmp( (LPCSTR)pRaw, "{deflate}", 9 ) == 0 )
00668         {
00669                 BYTE* pText = (BYTE*)CZLib::Decompress( pRaw + 9, nSize - 10, (DWORD*)&nSize );
00670                 
00671                 if ( pText != NULL )
00672                 {
00673                         LPTSTR pOut = strXML.GetBuffer( nSize );
00674                         for ( int nPos = 0 ; nPos < nSize ; nPos++ ) pOut[ nPos ] = (TCHAR)pText[ nPos ];
00675                         strXML.ReleaseBuffer( nSize );
00676                         delete [] pText;
00677                 }
00678         }
00679         else if ( nSize >= 11 && strncmp( (LPCSTR)pRaw, "{plaintext}", 11 ) == 0 )
00680         {
00681                 LPCSTR pszRaw = (LPCSTR)pRaw + 11;
00682                 if ( strlen( pszRaw ) == (DWORD)nSize - 12 ) strXML = pszRaw;
00683         }
00684         else
00685         {
00686                 LPCSTR pszRaw = (LPCSTR)pRaw;
00687                 if ( strlen( pszRaw ) == (DWORD)nSize - 1 ) strXML = pszRaw;
00688         }
00689         
00690         delete [] pRaw;
00691         
00692         CXMLElement* pRoot      = NULL;
00693         LPCTSTR pszXML          = strXML;
00694         
00695         while ( pszXML && *pszXML )
00696         {
00697                 CXMLElement* pXML = CXMLElement::FromString( pszXML, TRUE );
00698                 if ( ! pXML ) break;
00699                 
00700                 if ( ! pRoot ) pRoot = new CXMLElement( NULL, _T("Metadata") );
00701                 pRoot->AddElement( pXML );
00702                 
00703                 pszXML = _tcsstr( pszXML + 1, _T("<?xml") );
00704         }
00705         
00706         return pRoot;
00707 }
00708 
00710 // CQueryHit GGEP reader
00711 
00712 BOOL CQueryHit::ReadGGEP(CG1Packet* pPacket, BOOL* pbBrowseHost)
00713 {
00714         CGGEPBlock pGGEP;
00715         
00716         if ( ! pGGEP.ReadFromPacket( pPacket ) ) return FALSE;
00717         
00718         if ( pGGEP.Find( _T("BH") ) ) *pbBrowseHost = TRUE;
00719         
00720         return TRUE;
00721 }
00722 
00724 // CQueryHit G1 result entry reader
00725 
00726 void CQueryHit::ReadG1Packet(CG1Packet* pPacket)
00727 {
00728         CString strData;
00729         
00730         m_nIndex        = pPacket->ReadLongLE();
00731         m_bSize         = TRUE;
00732         m_nSize         = pPacket->ReadLongLE();
00733 
00734         if ( Settings.Gnutella1.QueryHitUTF8 ) //Support UTF-8 Query
00735         {
00736                 m_sName = pPacket->ReadStringUTF8();    
00737         }
00738         else
00739         {
00740                 m_sName = pPacket->ReadString();
00741         }
00742 
00743         strData         = pPacket->ReadString();
00744         
00745         if ( m_sName.GetLength() > 160 )
00746         {
00747                 m_bBogus = TRUE;
00748         }
00749         else
00750         {
00751                 int nCurWord = 0, nMaxWord = 0;
00752                 
00753                 for ( LPCTSTR pszName = m_sName ; *pszName ; pszName++ )
00754                 {
00755                         if ( _istgraph( *pszName ) )
00756                         {
00757                                 nCurWord++;
00758                                 nMaxWord = max( nMaxWord, nCurWord );
00759                         }
00760                         else
00761                         {
00762                                 nCurWord = 0;
00763                         }
00764                 }
00765                 
00766                 if ( nMaxWord > 30 ) m_bBogus = TRUE;
00767         }
00768         
00769         LPCTSTR pszData = strData;
00770         LPCTSTR pszEnd  = pszData + _tcslen( pszData );
00771         
00772         while ( *pszData && pszData < pszEnd )
00773         {
00774                 if ( (BYTE)*pszData == GGEP_MAGIC )
00775                 {
00776                         if ( ! Settings.Gnutella1.EnableGGEP ) break;
00777                         
00778                         CGGEPBlock pGGEP;
00779                         pGGEP.ReadFromString( pszData );
00780                         
00781                         if ( CGGEPItem* pItem = pGGEP.Find( _T("H"), 21 ) )
00782                         {
00783                                 if ( pItem->m_pBuffer[0] > 0 && pItem->m_pBuffer[0] < 3 )
00784                                 {
00785                                         CopyMemory( &m_pSHA1, &pItem->m_pBuffer[1], 20 );
00786                                         m_bSHA1 = ! CSHA::IsNull(&m_pSHA1);
00787                                 }
00788                                 if ( pItem->m_pBuffer[0] == 2 && pItem->m_nLength >= 24 + 20 + 1 )
00789                                 {
00790                                         CopyMemory( &m_pTiger, &pItem->m_pBuffer[21], 24 );
00791                                         m_bTiger = ! CTigerNode::IsNull(&m_pTiger);
00792                                 }
00793                         }
00794                         else if ( CGGEPItem* pItem = pGGEP.Find( _T("u"), 5 + 32 ) )
00795                         {
00796                                 strData = pItem->ToString();
00797                                 
00798                                 m_bSHA1         |= CSHA::HashFromURN( strData, &m_pSHA1 );
00799                                 m_bTiger        |= CTigerNode::HashFromURN( strData, &m_pTiger );
00800                                 m_bED2K         |= CED2K::HashFromURN( strData, &m_pED2K );
00801                         }
00802                         
00803                         if ( CGGEPItem* pItem = pGGEP.Find( _T("ALT"), 6 ) )
00804                         {
00805                                 // the ip-addresses need not be stored, as they are sent upon the download request in the ALT-loc header
00806                                 m_nSources = pItem->m_nLength / 6;      // 6 bytes per source (see ALT GGEP extension specification)
00807                         }
00808                         
00809                         break;
00810                 }
00811                 
00812                 LPCTSTR pszSep = _tcschr( pszData, 0x1C );
00813                 int nLength = pszSep ? pszSep - pszData : _tcslen( pszData );
00814                 
00815                 if ( _tcsnicmp( pszData, _T("urn:"), 4 ) == 0 )
00816                 {
00817                         m_bSHA1         |= CSHA::HashFromURN( pszData, &m_pSHA1 );
00818                         m_bTiger        |= CTigerNode::HashFromURN( pszData, &m_pTiger );
00819                         m_bED2K         |= CED2K::HashFromURN( pszData, &m_pED2K );
00820                 }
00821                 else if ( nLength > 4 )
00822                 {
00823                         AutoDetectSchema( pszData );
00824                 }
00825                 
00826                 if ( pszSep ) pszData = pszSep + 1;
00827                 else break;
00828         }
00829 }
00830 
00832 // CQueryHit G1 attributes suffix
00833 
00834 void CQueryHit::ParseAttributes(GGUID* pClientID, CVendor* pVendor, BYTE* nFlags, BOOL bChat, BOOL bBrowseHost)
00835 {
00836         m_pClientID             = *pClientID;
00837         m_pVendor               = pVendor;
00838         m_bChat                 = bChat;
00839         m_bBrowseHost   = bBrowseHost;
00840         
00841         if ( nFlags[1] & G1_QHD_PUSH )
00842                 m_bPush         = ( nFlags[0] & G1_QHD_PUSH ) ? TS_TRUE : TS_FALSE;
00843         if ( nFlags[0] & G1_QHD_BUSY )
00844                 m_bBusy         = ( nFlags[1] & G1_QHD_BUSY ) ? TS_TRUE : TS_FALSE;
00845         if ( nFlags[0] & G1_QHD_STABLE )
00846                 m_bStable       = ( nFlags[1] & G1_QHD_STABLE ) ? TS_TRUE : TS_FALSE;
00847         if ( nFlags[0] & G1_QHD_SPEED )
00848                 m_bMeasured     = ( nFlags[1] & G1_QHD_SPEED ) ? TS_TRUE : TS_FALSE;
00849 }
00850 
00852 // CQueryHit G2 result entry reader
00853 
00854 void CQueryHit::ReadG2Packet(CG2Packet* pPacket, DWORD nLength)
00855 {
00856         DWORD nPacket, nEnd = pPacket->m_nPosition + nLength;
00857         CHAR szType[9];
00858         
00859         m_bResolveURL = FALSE;
00860         
00861         while ( pPacket->m_nPosition < nEnd && pPacket->ReadPacket( szType, nPacket ) )
00862         {
00863                 DWORD nSkip = pPacket->m_nPosition + nPacket;
00864                 
00865                 if ( strcmp( szType, "URN" ) == 0 )
00866                 {
00867                         CString strURN = pPacket->ReadString( nPacket );
00868                         if ( strURN.GetLength() + 1 >= (int)nPacket ) AfxThrowUserException();
00869                         nPacket -= strURN.GetLength() + 1;
00870                         
00871                         if ( nPacket >= 20 && strURN == _T("sha1") )
00872                         {
00873                                 pPacket->Read( &m_pSHA1, sizeof(SHA1) );
00874                                 m_bSHA1 = ! CSHA::IsNull(&m_pSHA1);
00875                         }
00876                         else if ( nPacket >= 44 && ( strURN == _T("bp") || strURN == _T("bitprint") ) )
00877                         {
00878                                 pPacket->Read( &m_pSHA1, sizeof(SHA1) );
00879                                 m_bSHA1 = ! CSHA::IsNull(&m_pSHA1);
00880 
00881                                 pPacket->Read( &m_pTiger, sizeof(TIGEROOT) );
00882                                 m_bTiger = ! CTigerNode::IsNull(&m_pTiger);
00883                         }
00884                         else if ( nPacket >= 24 && ( strURN == _T("ttr") || strURN == _T("tree:tiger/") ) )
00885                         {
00886                                 pPacket->Read( &m_pTiger, sizeof(TIGEROOT) );
00887                                 m_bTiger = ! CTigerNode::IsNull(&m_pTiger);
00888                         }
00889                         else if ( nPacket >= 16 && strURN == _T("ed2k") )
00890                         {
00891                                 m_bED2K = TRUE;
00892                                 pPacket->Read( &m_pED2K, sizeof(MD4) );
00893                         }
00894                         else if ( nPacket >= 20 && strURN == _T("btih") )
00895                         {
00896                                 m_bBTH = TRUE;
00897                                 pPacket->Read( &m_pBTH, sizeof(SHA1) );
00898                         }
00899                 }
00900                 else if ( strcmp( szType, "URL" ) == 0 )
00901                 {
00902                         if ( nPacket == 0 )
00903                         {
00904                                 m_bResolveURL = TRUE;
00905                         }
00906                         else
00907                         {
00908                                 m_sURL = pPacket->ReadString( nPacket );
00909                         }
00910                 }
00911                 else if ( strcmp( szType, "DN" ) == 0 )
00912                 {
00913                         if ( m_bSize )
00914                         {
00915                                 m_sName = pPacket->ReadString( nPacket );
00916                         }
00917                         else if ( nPacket > 4 )
00918                         {
00919                                 m_bSize = TRUE;
00920                                 m_nSize = pPacket->ReadLongBE();
00921                                 m_sName = pPacket->ReadString( nPacket - 4 );
00922                         }
00923                 }
00924                 else if ( strcmp( szType, "MD" ) == 0 && nPacket > 0 )
00925                 {
00926                         CString strXML = pPacket->ReadString( nPacket );
00927                         
00928                         if ( CXMLElement* pXML = CXMLElement::FromString( strXML ) )
00929                         {
00930                                 if ( CXMLAttribute* pURI = pXML->GetAttribute( CXMLAttribute::schemaName ) )
00931                                 {
00932                                         m_sSchemaPlural         = pXML->GetName();
00933                                         m_sSchemaURI            = pURI->GetValue();
00934                                         CXMLElement* pChild     = pXML->GetFirstElement();
00935                                         
00936                                         if ( pChild != NULL && m_sSchemaPlural.GetLength() > 0 && m_sSchemaURI.GetLength() > 0 )
00937                                         {
00938                                                 m_pXML->Delete();
00939                                                 m_pXML = pChild->Detach();
00940                                         }
00941                                 }
00942                                 else if ( CSchema* pSchema = SchemaCache.Guess( pXML->GetName() ) )
00943                                 {
00944                                         m_pXML->Delete();
00945                                         m_sSchemaPlural = pSchema->m_sPlural;
00946                                         m_sSchemaURI    = pSchema->m_sURI;
00947                                         m_pXML                  = pXML;
00948                                         pXML                    = NULL;
00949                                 }
00950                                 
00951                                 pXML->Delete();
00952                         }
00953                 }
00954                 else if ( strcmp( szType, "SZ" ) == 0 )
00955                 {
00956                         if ( nPacket == 4 )
00957                         {
00958                                 m_bSize = TRUE;
00959                                 m_nSize = pPacket->ReadLongBE();
00960                         }
00961                         else if ( nPacket == 8 )
00962                         {
00963                                 m_bSize = TRUE;
00964                                 m_nSize = pPacket->ReadInt64();
00965                         }
00966                 }
00967                 else if ( strcmp( szType, "G" ) == 0 && nPacket >= 1 )
00968                 {
00969                         m_nGroup = pPacket->ReadByte();
00970                         if ( m_nGroup < 0 ) m_nGroup = 0;
00971                         if ( m_nGroup > 7 ) m_nGroup = 7;
00972                 }
00973                 else if ( strcmp( szType, "ID" ) == 0 && nPacket >= 4 )
00974                 {
00975                         m_nIndex = pPacket->ReadLongBE();
00976                 }
00977                 else if ( strcmp( szType, "CSC" ) == 0 && nPacket >= 2 )
00978                 {
00979                         m_nSources = pPacket->ReadShortBE();
00980                 }
00981                 else if ( strcmp( szType, "PART" ) == 0 && nPacket >= 4 )
00982                 {
00983                         m_nPartial = pPacket->ReadLongBE();
00984                 }
00985                 else if ( strcmp( szType, "COM" ) == 0 )
00986                 {
00987                         CString strXML = pPacket->ReadString( nPacket );
00988                         
00989                         if ( CXMLElement* pComment = CXMLElement::FromString( strXML ) )
00990                         {
00991                                 m_nRating = -1;
00992                                 _stscanf( pComment->GetAttributeValue( _T("rating") ), _T("%i"), &m_nRating );
00993                                 m_nRating = max( 0, min( 6, m_nRating + 1 ) );
00994                                 m_sComments = pComment->GetValue();
00995                                 Replace( m_sComments, _T("{n}"), _T("\r\n") );
00996                                 delete pComment;
00997                         }
00998                 }
00999                 else if ( strcmp( szType, "PVU" ) == 0 )
01000                 {
01001                         if ( nPacket == 0 )
01002                         {
01003                                 m_bPreview = TRUE;
01004                         }
01005                         else
01006                         {
01007                                 m_bPreview = TRUE;
01008                                 m_sPreview = pPacket->ReadString( nPacket );
01009                         }
01010                 }
01011                 else if ( strcmp( szType, "BOGUS" ) == 0 )
01012                 {
01013                         m_bBogus = TRUE;
01014                 }
01015                 else if ( strcmp( szType, "COLLECT" ) == 0 )
01016                 {
01017                         m_bCollection = TRUE;
01018                 }
01019                 
01020                 pPacket->m_nPosition = nSkip;
01021         }
01022         
01023         if ( ! m_bSHA1 && ! m_bTiger && ! m_bED2K && ! m_bBTH ) AfxThrowUserException();
01024 }
01025 
01027 // CQueryHit ED2K result entry reader
01028 
01029 BOOL CQueryHit::ReadEDPacket(CEDPacket* pPacket, SOCKADDR_IN* pServer, DWORD m_nServerFlags )
01030 {
01031         CString strLength(_T("")), strBitrate(_T("")), strCodec(_T(""));
01032         DWORD nLength = 0;
01033         m_bED2K = TRUE;
01034         pPacket->Read( &m_pED2K, sizeof(MD4) );
01035         
01036         ReadEDAddress( pPacket, pServer );
01037         
01038         DWORD nTags = pPacket->ReadLongLE();
01039         
01040         while ( nTags-- > 0 )
01041         {
01042                 if ( pPacket->GetRemaining() < 1 ) return FALSE;
01043 
01044                 CEDTag pTag;
01045                 if ( ! pTag.Read( pPacket, m_nServerFlags ) ) 
01046                 {
01047                         theApp.Message( MSG_ERROR, _T("ED2K search result packet read error") ); //debug check
01048                         return FALSE;
01049                 }
01050         
01051                 if ( pTag.m_nKey == ED2K_FT_FILENAME )
01052                 {
01053                         m_sName = pTag.m_sValue;
01054                 }
01055                 else if ( pTag.m_nKey == ED2K_FT_FILESIZE )
01056                 {
01057                         m_bSize = TRUE;
01058                         m_nSize = pTag.m_nValue;
01059                 }
01060                 else if ( pTag.m_nKey == ED2K_FT_LASTSEENCOMPLETE )
01061                 {
01062                         //theApp.Message( MSG_SYSTEM,_T("Last seen complete"));
01063                 }
01064                 else if ( pTag.m_nKey == ED2K_FT_SOURCES )
01065                 {
01066                         m_nSources = pTag.m_nValue;
01067                         if ( m_nSources == 0 )
01068                                 m_bResolveURL = FALSE;
01069                         else
01070                                 m_nSources--;
01071                 }
01072                 else if ( pTag.m_nKey == ED2K_FT_COMPLETESOURCES )
01073                 {
01074                         if ( ! pTag.m_nValue ) // If there are no complete sources
01075                         {
01076                                 // Assume this file is 50% complete. (we can't tell yet, but at least this will warn the user)
01077                                 m_nPartial = (DWORD)m_nSize >> 2;
01078                                 //theApp.Message( MSG_SYSTEM, _T("ED2K_FT_COMPLETESOURCES tag reports no complete sources.") );                         
01079                         }
01080                         else
01081                         {
01082                                 //theApp.Message( MSG_SYSTEM, _T("ED2K_FT_COMPLETESOURCES tag reports complete sources present.") );
01083                         }
01084                 }
01085                 else if ( pTag.m_nKey == ED2K_FT_LENGTH )
01086                 {       // Length- new style (DWORD)
01087                         nLength = pTag.m_nValue;        
01088                 }
01089                 else if ( pTag.m_nKey == ED2K_FT_BITRATE )
01090                 {       // Bitrate- new style
01091                         strBitrate.Format( _T("%lu"), pTag.m_nValue );
01092                 }
01093                 else if  ( pTag.m_nKey == ED2K_FT_CODEC )
01094                 {       // Codec - new style
01095                         strCodec = pTag.m_sValue;
01096                 }
01097                 else if  ( pTag.m_nKey == ED2K_FT_FILERATING )
01098                 {       // File Rating
01099 
01100                         // The server returns rating as a full range (1-255).
01101                         // If the majority of ratings are "very good", take it up to "excellent"
01102 
01103                         m_nRating = ( pTag.m_nValue & 0xFF );
01104 
01105                         if ( m_nRating >= 250 )                 // Excellent
01106                                 m_nRating = 6;                   
01107                         else if ( m_nRating >= 220 )    // Very good
01108                                 m_nRating = 5;  
01109                         else if ( m_nRating >= 180 )    // Good
01110                                 m_nRating = 4;  
01111                         else if ( m_nRating >= 120 )    // Average
01112                                 m_nRating = 3;  
01113                         else if ( m_nRating >= 80 )             // Poor
01114                                 m_nRating = 2;
01115                         else                                                    // Fake
01116                                 m_nRating = 1;
01117 
01118                         // the percentage of clients that have given ratings is:
01119                         // = ( pTag.m_nValue >> 8 ) & 0xFF;
01120                         // We could use this in the future to weight the rating...
01121                 }
01122                 // Note: Maybe ignore these keys? They seem to have a lot of bad values....
01123                 else if ( ( pTag.m_nKey == 0 ) && ( pTag.m_nType == ED2K_TAG_STRING ) && ( pTag.m_sKey == _T("length") )  )
01124                 {       // Length- old style (As a string- x:x:x, x:x or x)
01125                         DWORD nSecs = 0, nMins = 0, nHours = 0;
01126 
01127                         if ( pTag.m_sValue.GetLength() < 3 )
01128                         {
01129                                 _stscanf( pTag.m_sValue, _T("%i"), &nSecs );
01130                         }
01131                         else if ( pTag.m_sValue.GetLength() < 6 )
01132                         {
01133                                 _stscanf( pTag.m_sValue, _T("%i:%i"), &nMins, &nSecs );
01134                         }
01135                         else 
01136                         {
01137                                 _stscanf( pTag.m_sValue, _T("%i:%i:%i"), &nHours, &nMins, &nSecs );
01138                         }
01139 
01140                         nLength = (nHours * 60 * 60) + (nMins * 60) + (nSecs);
01141                 }
01142                 else if ( ( pTag.m_nKey == 0 ) && ( pTag.m_nType == ED2K_TAG_INT ) && ( pTag.m_sKey == _T("bitrate") ) )
01143                 {       // Bitrate- old style                   
01144                         strBitrate.Format( _T("%lu"), pTag.m_nValue );
01145                 }
01146                 else if ( ( pTag.m_nKey == 0 ) && ( pTag.m_nType == ED2K_TAG_STRING ) && ( pTag.m_sKey == _T("codec") ) )
01147                 {       // Codec - old style
01148                         strCodec = pTag.m_sValue;
01149                 }
01150                 else
01151                 {
01152                         /*
01153                         //*** Debug check. Remove this when it's working
01154                         CString s;
01155                         s.Format ( _T("Tag: %u sTag: %s Type: %u"), pTag.m_nKey, pTag.m_sKey, pTag.m_nType );
01156                         theApp.Message( MSG_SYSTEM, s );
01157 
01158                         if ( pTag.m_nType == 2 )
01159                                 s.Format ( _T("Value: %s"), pTag.m_sValue);
01160                         else
01161                                 s.Format ( _T("Value: %d"), pTag.m_nValue);
01162                         theApp.Message( MSG_SYSTEM, s );
01163                         */
01164                 }
01165         }
01166 
01167         // Verify and set metadata
01168         CString strType;
01169 
01170         // Check we have a valid name
01171         if ( m_sName.GetLength() )
01172         {
01173                 int nExtPos = m_sName.ReverseFind( '.' );
01174                 if ( nExtPos > 0 ) 
01175                 {
01176                         strType = m_sName.Mid( nExtPos );
01177                         CharLower( strType.GetBuffer() );
01178                         strType.ReleaseBuffer();
01179                 }
01180         }
01181 
01182         // If we can determine type, we can add metadata
01183         if ( strType.GetLength() )
01184         {
01185                 // Determine type
01186                 // Note: Maybe should use library plug-in for this?
01187                 if ( strType == _T(".mp3") ||  strType == _T(".ogg") ||  strType == _T(".wav") ||  strType == _T(".mid") ||
01188                          strType == _T(".ape") || strType == _T(".mac") || strType == _T(".apl") || strType == _T(".ra"))
01189                 {       // Audio
01190                         m_sSchemaURI = CSchema::uriAudio;
01191 
01192                         // Add metadata
01193                         if ( nLength > 0 )
01194                         {
01195                                 strLength.Format( _T("%lu"), nLength );
01196                                 if ( m_pXML == NULL ) m_pXML = new CXMLElement( NULL, _T("audio") );
01197                                 m_pXML->AddAttribute( _T("seconds"), strLength );
01198                         }
01199                         if ( strBitrate.GetLength() )
01200                         {
01201                                 if ( m_pXML == NULL ) m_pXML = new CXMLElement( NULL, _T("audio") );
01202                                 m_pXML->AddAttribute( _T("bitrate"), strBitrate );
01203                         }/*
01204                         if ( strCodec.GetLength() )
01205                         {
01206                                 m_sSchemaURI = CSchema::uriVideo;
01207                                 if ( m_pXML == NULL ) m_pXML = new CXMLElement( NULL, _T("audio") );
01208                                 m_pXML->AddAttribute( _T("codec"), strCodec );
01209                         }*/
01210                 }
01211                 else if ( strType == _T(".avi") || strType == _T(".mpg") || strType == _T(".mpeg") || strType == _T(".ogm") || strType == _T(".mkv") ||
01212                                   strType == _T(".asf") || strType == _T(".wma") || strType == _T(".wmv") || strType == _T(".rm") )
01213                 {       // Video
01214                         m_sSchemaURI = CSchema::uriVideo;
01215                         
01216                         // Add metadata
01217                         if ( nLength > 0 )
01218                         {
01219                                 double nMins = (double)nLength / (double)60;    
01220                                 strLength.Format( _T("%.3f"), nMins );
01221                                 if ( m_pXML == NULL ) m_pXML = new CXMLElement( NULL, _T("video") );
01222                                 m_pXML->AddAttribute( _T("minutes"), strLength );
01223                         }/*
01224                         if ( strBitrate.GetLength() )
01225                         {
01226                                 if ( m_pXML == NULL ) m_pXML = new CXMLElement( NULL, _T("video") );
01227                                 m_pXML->AddAttribute( _T("bitrate"), strBitrate );
01228                         }*/
01229                         if ( strCodec.GetLength() )
01230                         {
01231                                 if ( m_pXML == NULL ) m_pXML = new CXMLElement( NULL, _T("video") );
01232                                 m_pXML->AddAttribute( _T("codec"), strCodec );
01233                         }
01234                 }
01235                 else if ( strType == _T(".exe") || strType == _T(".dll") || strType == _T(".iso") || strType == _T(".bin") || strType == _T(".cue") )
01236                 {       // Application
01237                         m_sSchemaURI = CSchema::uriApplication;
01238                 }
01239                 else if ( strType == _T(".jpg") || strType == _T(".jpeg") || strType == _T(".gif") || strType == _T(".png") || strType == _T(".bmp") )
01240                 {       // Image
01241                         m_sSchemaURI = CSchema::uriImage;
01242                 }
01243                 else if ( strType == _T(".pdf") || strType == _T(".doc") || strType == _T(".txt") || strType == _T(".xls") )
01244                 {       // Document
01245                         m_sSchemaURI = CSchema::uriBook;
01246                 }
01247         }
01248         
01249         return TRUE;
01250 }
01251 
01252 void CQueryHit::ReadEDAddress(CEDPacket* pPacket, SOCKADDR_IN* pServer)
01253 {
01254         DWORD nAddress = m_pAddress.S_un.S_addr = pPacket->ReadLongLE();
01255         m_nPort = pPacket->ReadShortLE();
01256         
01257         m_pClientID.w[0] = pServer->sin_addr.S_un.S_addr;
01258         m_pClientID.w[1] = htons( pServer->sin_port );
01259         m_pClientID.w[2] = nAddress;
01260         m_pClientID.w[3] = m_nPort;
01261         
01262         if ( nAddress == 0 )
01263         {
01264                 m_bResolveURL = FALSE;
01265                 m_bPush = TS_UNKNOWN;
01266         }
01267         else if ( CEDPacket::IsLowID( nAddress ) || Network.IsFirewalledAddress( &nAddress ) || ! m_nPort )
01268         {
01269                 m_bPush = TS_TRUE;
01270         }
01271         else
01272         {
01273                 m_bPush = TS_FALSE;
01274         }
01275 }
01276 
01278 // CQueryHit resolve
01279 
01280 void CQueryHit::Resolve()
01281 {
01282         if ( m_bPreview && m_bSHA1 && m_sPreview.IsEmpty() )
01283         {
01284                 m_sPreview.Format( _T("http://%s:%i/gnutella/preview/v1?%s"),
01285                         (LPCTSTR)CString( inet_ntoa( m_pAddress ) ), m_nPort,
01286                         (LPCTSTR)CSHA::HashToString( &m_pSHA1, TRUE ) );
01287         }
01288         
01289         if ( m_sURL.GetLength() )
01290         {
01291                 m_nSources ++;
01292                 return;
01293         }
01294         else if ( ! m_bResolveURL )
01295                 return;
01296         
01297         m_nSources++;
01298         
01299         if ( m_nProtocol == PROTOCOL_ED2K )
01300         {
01301                 if ( m_bPush == TS_TRUE )
01302                 {
01303                         m_sURL.Format( _T("ed2kftp://%lu@%s:%i/%s/%I64i/"),
01304                                 m_pClientID.w[2],
01305                                 (LPCTSTR)CString( inet_ntoa( (IN_ADDR&)m_pClientID.w[0] ) ),
01306                                 m_pClientID.w[1],
01307                                 (LPCTSTR)CED2K::HashToString( &m_pED2K ), m_nSize );
01308                 }
01309                 else
01310                 {
01311                         m_sURL.Format( _T("ed2kftp://%s:%i/%s/%I64i/"),
01312                                 (LPCTSTR)CString( inet_ntoa( m_pAddress ) ), m_nPort,
01313                                 (LPCTSTR)CED2K::HashToString( &m_pED2K ), m_nSize );
01314                 }
01315                 return;
01316         }
01317         
01318         if ( m_nIndex == 0 || m_bTiger || m_bED2K || Settings.Downloads.RequestHash )
01319         {
01320                 if ( m_bSHA1 )
01321                 {
01322                         m_sURL.Format( _T("http://%s:%i/uri-res/N2R?%s"),
01323                                 (LPCTSTR)CString( inet_ntoa( m_pAddress ) ), m_nPort,
01324                                 (LPCTSTR)CSHA::HashToString( &m_pSHA1, TRUE ) );
01325                         return;
01326                 }
01327                 else if ( m_bTiger )
01328                 {
01329                         m_sURL.Format( _T("http://%s:%i/uri-res/N2R?%s"),
01330                                 (LPCTSTR)CString( inet_ntoa( m_pAddress ) ), m_nPort,
01331                                 (LPCTSTR)CTigerNode::HashToString( &m_pTiger, TRUE ) );
01332                         return;
01333                 }
01334                 else if ( m_bED2K )
01335                 {
01336                         m_sURL.Format( _T("http://%s:%i/uri-res/N2R?%s"),
01337                                 (LPCTSTR)CString( inet_ntoa( m_pAddress ) ), m_nPort,
01338                                 (LPCTSTR)CED2K::HashToString( &m_pED2K, TRUE ) );
01339                         return;
01340                 }
01341         }
01342         
01343         if ( Settings.Downloads.RequestURLENC )
01344         {
01345                 m_sURL.Format( _T("http://%s:%i/get/%lu/%s"),
01346                         (LPCTSTR)CString( inet_ntoa( m_pAddress ) ), m_nPort, m_nIndex,
01347                         (LPCTSTR)CTransfer::URLEncode( m_sName ) );
01348         }
01349         else
01350         {
01351                 m_sURL.Format( _T("http://%s:%i/get/%lu/%s"),
01352                         (LPCTSTR)CString( inet_ntoa( m_pAddress ) ), m_nPort, m_nIndex,
01353                         (LPCTSTR)m_sName );
01354         }
01355 }
01356 
01358 // CQueryHit XML metadata suffix
01359 
01360 BOOL CQueryHit::ParseXML(CXMLElement* pMetaData, DWORD nRealIndex)
01361 {
01362         CString strRealIndex;
01363         strRealIndex.Format( _T("%i"), nRealIndex );
01364         
01365         for ( POSITION pos1 = pMetaData->GetElementIterator() ; pos1 && ! m_pXML ; )
01366         {
01367                 CXMLElement* pXML = pMetaData->GetNextElement( pos1 );
01368                 
01369                 for ( POSITION pos2 = pXML->GetElementIterator() ; pos2 ; )
01370                 {
01371                         CXMLElement* pHit               = pXML->GetNextElement( pos2 );
01372                         CXMLAttribute* pIndex   = pHit->GetAttribute( _T("index") );
01373                         
01374                         if ( pIndex != NULL && pIndex->GetValue() == strRealIndex )
01375                         {
01376                                 m_sSchemaPlural = pXML->GetName();
01377                                 m_sSchemaURI    = pXML->GetAttributeValue( CXMLAttribute::schemaName, _T("") );
01378                                 
01379                                 if ( m_sSchemaPlural.GetLength() > 0 && m_sSchemaURI.GetLength() > 0 )
01380                                 {
01381                                         if ( m_pXML ) delete m_pXML;
01382                                         m_pXML = pHit->Detach();
01383                                         pIndex->Delete();
01384                                 }
01385                                 
01386                                 break;
01387                         }
01388                 }
01389         }
01390         
01391         return m_pXML != NULL;
01392 }
01393 
01395 // CQueryHit schema auto-detect
01396 
01397 BOOL CQueryHit::AutoDetectSchema(LPCTSTR pszInfo)
01398 {
01399         if ( m_pXML ) return TRUE;
01400 
01401         if ( _tcsstr( pszInfo, _T(" Kbps") ) != NULL && _tcsstr( pszInfo,  _T(" kHz ") ) != NULL )
01402         {
01403                 if ( AutoDetectAudio( pszInfo ) ) return TRUE;
01404         }
01405         
01406         return FALSE;
01407 }
01408 
01409 BOOL CQueryHit::AutoDetectAudio(LPCTSTR pszInfo)
01410 {
01411         int nBitrate    = 0;
01412         int nFrequency  = 0;
01413         int nMinutes    = 0;
01414         int nSeconds    = 0;
01415         BOOL bVariable  = FALSE;
01416 
01417         if ( _stscanf( pszInfo, _T("%i Kbps %i kHz %i:%i"), &nBitrate, &nFrequency,
01418                 &nMinutes, &nSeconds ) != 4 )
01419         {
01420                 bVariable = TRUE;
01421                 if ( _stscanf( pszInfo, _T("%i Kbps(VBR) %i kHz %i:%i"), &nBitrate, &nFrequency,
01422                         &nMinutes, &nSeconds ) != 4 ) return FALSE;
01423         }
01424 
01425         m_sSchemaURI = CSchema::uriAudio;
01426 
01427         m_pXML = new CXMLElement( NULL, _T("audio") );
01428 
01429         CString strValue;
01430         strValue.Format( _T("%lu"), nMinutes * 60 + nSeconds );
01431         m_pXML->AddAttribute( _T("seconds"), strValue );
01432 
01433         strValue.Format( bVariable ? _T("%lu~") : _T("%lu"), nBitrate );
01434         m_pXML->AddAttribute( _T("bitrate"), strValue );
01435 
01436         return TRUE;
01437 }
01438 
01440 // CQueryHit copy and delete helpers
01441 
01442 void CQueryHit::Copy(CQueryHit* pOther)
01443 {
01444         if ( m_pXML ) delete m_pXML;
01445 
01446         m_pSearchID             = pOther->m_pSearchID;
01447         m_pClientID             = pOther->m_pClientID;
01448         m_pAddress              = pOther->m_pAddress;
01449         m_nPort                 = pOther->m_nPort;
01450         m_nSpeed                = pOther->m_nSpeed;
01451         m_sSpeed                = pOther->m_sSpeed;
01452         m_pVendor               = pOther->m_pVendor;
01453         m_bPush                 = pOther->m_bPush;
01454         m_bBusy                 = pOther->m_bBusy;
01455         m_bStable               = pOther->m_bStable;
01456         m_bMeasured             = pOther->m_bMeasured;
01457         m_bChat                 = pOther->m_bChat;
01458         m_bBrowseHost   = pOther->m_bBrowseHost;
01459 
01460         m_bSHA1                 = pOther->m_bSHA1;
01461         m_bTiger                = pOther->m_bTiger;
01462         m_bED2K                 = pOther->m_bED2K;
01463         m_sURL                  = pOther->m_sURL;
01464         m_sName                 = pOther->m_sName;
01465         m_nIndex                = pOther->m_nIndex;
01466         m_bSize                 = pOther->m_bSize;
01467         m_nSize                 = pOther->m_nSize;
01468         m_sSchemaURI    = pOther->m_sSchemaURI;
01469         m_sSchemaPlural = pOther->m_sSchemaPlural;
01470         m_pXML                  = pOther->m_pXML;
01471 
01472         m_bMatched              = pOther->m_bMatched;
01473         m_bBogus                = pOther->m_bBogus;
01474         m_bFiltered             = pOther->m_bFiltered;
01475         m_bDownload             = pOther->m_bDownload;
01476 
01477         if ( m_bSHA1 ) m_pSHA1 = pOther->m_pSHA1;
01478         if ( m_bTiger ) m_pTiger = pOther->m_pTiger;
01479         if ( m_bED2K ) m_pED2K = pOther->m_pED2K;
01480 
01481         pOther->m_pXML = NULL;
01482 }
01483 
01484 void CQueryHit::Delete()
01485 {
01486         for ( CQueryHit* pHit = this ; pHit ; )
01487         {
01488                 CQueryHit* pNext = pHit->m_pNext;
01489                 delete pHit;
01490                 pHit = pNext;
01491         }
01492 }
01493 
01495 // CQueryHit rating
01496 
01497 int CQueryHit::GetRating()
01498 {
01499         int nRating = 0;
01500         
01501         if ( m_bPush != TS_TRUE ) nRating += 4;
01502         if ( m_bBusy != TS_TRUE ) nRating += 2;
01503         if ( m_bStable == TS_TRUE ) nRating ++;
01504 
01505         return nRating;
01506 }
01507 
01509 // CQueryHit serialize
01510 
01511 void CQueryHit::Serialize(CArchive& ar, int nVersion)
01512 {
01513         if ( ar.IsStoring() )
01514         {
01515                 ar.Write( &m_pSearchID, sizeof(GGUID) );
01516                 
01517                 ar << m_nProtocol;
01518                 ar.Write( &m_pClientID, sizeof(GGUID) );
01519                 ar.Write( &m_pAddress, sizeof(IN_ADDR) );
01520                 ar << m_nPort;
01521                 ar << m_nSpeed;
01522                 ar << m_sSpeed;
01523                 ar << m_pVendor->m_sCode;
01524                 
01525                 ar << m_bPush;
01526                 ar << m_bBusy;
01527                 ar << m_bStable;
01528                 ar << m_bMeasured;
01529                 ar << m_nUpSlots;
01530                 ar << m_nUpQueue;
01531                 ar << m_bChat;
01532                 ar << m_bBrowseHost;
01533                 
01534                 ar << m_bSHA1;
01535                 if ( m_bSHA1 ) ar.Write( &m_pSHA1, sizeof(SHA1) );
01536                 ar << m_bTiger;
01537                 if ( m_bTiger ) ar.Write( &m_pTiger, sizeof(TIGEROOT) );
01538                 ar << m_bED2K;
01539                 if ( m_bED2K ) ar.Write( &m_pED2K, sizeof(MD4) );
01540 
01541                 ar << m_sURL;
01542                 ar << m_sName;
01543                 ar << m_nIndex;
01544                 ar << m_bSize;
01545                 ar << m_nSize;
01546                 ar << m_nSources;
01547                 ar << m_nPartial;
01548                 ar << m_bPreview;
01549                 ar << m_sPreview;
01550                 ar << m_bCollection;
01551                 
01552                 if ( m_pXML == NULL ) m_sSchemaURI.Empty();
01553                 ar << m_sSchemaURI;
01554                 ar << m_sSchemaPlural;
01555                 if ( m_sSchemaURI.GetLength() ) m_pXML->Serialize( ar );
01556                 ar << m_nRating;
01557                 ar << m_sComments;
01558                 
01559                 ar << m_bMatched;
01560                 ar << m_bBogus;
01561                 ar << m_bDownload;
01562         }
01563         else
01564         {
01565                 ar.Read( &m_pSearchID, sizeof(GGUID) );
01566                 
01567                 if ( nVersion >= 9 ) ar >> m_nProtocol;
01568                 ar.Read( &m_pClientID, sizeof(GGUID) );
01569                 ar.Read( &m_pAddress, sizeof(IN_ADDR) );
01570                 ar >> m_nPort;
01571                 ar >> m_nSpeed;
01572                 ar >> m_sSpeed;
01573                 ar >> m_sSchemaURI;
01574                 m_pVendor = VendorCache.Lookup( m_sSchemaURI );
01575 
01576                 ar >> m_bPush;
01577                 ar >> m_bBusy;
01578                 ar >> m_bStable;
01579                 ar >> m_bMeasured;
01580                 ar >> m_nUpSlots;
01581                 ar >> m_nUpQueue;
01582                 ar >> m_bChat;
01583                 ar >> m_bBrowseHost;
01584 
01585                 ar >> m_bSHA1;
01586                 if ( m_bSHA1 ) ar.Read( &m_pSHA1, sizeof(SHA1) );
01587                 ar >> m_bTiger;
01588                 if ( m_bTiger ) ar.Read( &m_pTiger, sizeof(TIGEROOT) );
01589                 ar >> m_bED2K;
01590                 if ( m_bED2K ) ar.Read( &m_pED2K, sizeof(MD4) );
01591 
01592                 ar >> m_sURL;
01593                 ar >> m_sName;
01594                 ar >> m_nIndex;
01595                 ar >> m_bSize;
01596                 
01597                 if ( nVersion >= 10 )
01598                 {
01599                         ar >> m_nSize;
01600                 }
01601                 else
01602                 {
01603                         DWORD nSize;
01604                         ar >> nSize;
01605                         m_nSize = nSize;
01606                 }
01607                 
01608                 ar >> m_nSources;
01609                 ar >> m_nPartial;
01610                 ar >> m_bPreview;
01611                 ar >> m_sPreview;
01612                 if ( nVersion >= 11 ) ar >> m_bCollection;
01613                 
01614                 ar >> m_sSchemaURI;
01615                 ar >> m_sSchemaPlural;
01616                 
01617                 if ( m_sSchemaURI.GetLength() )
01618                 {
01619                         m_pXML = new CXMLElement();
01620                         m_pXML->Serialize( ar );
01621                 }
01622                 
01623                 ar >> m_nRating;
01624                 ar >> m_sComments;
01625                 
01626                 ar >> m_bMatched;
01627                 ar >> m_bBogus;
01628                 ar >> m_bDownload;
01629                 
01630                 if ( m_nSources == 0 && m_sURL.GetLength() ) m_nSources = 1;
01631         }
01632 }

Generated on Thu Dec 15 10:39:46 2005 for Shareaza 2.2.1.0 by  doxygen 1.4.2