00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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
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
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
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
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
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
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
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
00571
00572
00573
00574
00575 return pFirstHit;
00576 }
00577
00579
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 ];
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
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
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
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 )
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
00806 m_nSources = pItem->m_nLength / 6;
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
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
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
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") );
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
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 )
01075 {
01076
01077 m_nPartial = (DWORD)m_nSize >> 2;
01078
01079 }
01080 else
01081 {
01082
01083 }
01084 }
01085 else if ( pTag.m_nKey == ED2K_FT_LENGTH )
01086 {
01087 nLength = pTag.m_nValue;
01088 }
01089 else if ( pTag.m_nKey == ED2K_FT_BITRATE )
01090 {
01091 strBitrate.Format( _T("%lu"), pTag.m_nValue );
01092 }
01093 else if ( pTag.m_nKey == ED2K_FT_CODEC )
01094 {
01095 strCodec = pTag.m_sValue;
01096 }
01097 else if ( pTag.m_nKey == ED2K_FT_FILERATING )
01098 {
01099
01100
01101
01102
01103 m_nRating = ( pTag.m_nValue & 0xFF );
01104
01105 if ( m_nRating >= 250 )
01106 m_nRating = 6;
01107 else if ( m_nRating >= 220 )
01108 m_nRating = 5;
01109 else if ( m_nRating >= 180 )
01110 m_nRating = 4;
01111 else if ( m_nRating >= 120 )
01112 m_nRating = 3;
01113 else if ( m_nRating >= 80 )
01114 m_nRating = 2;
01115 else
01116 m_nRating = 1;
01117
01118
01119
01120
01121 }
01122
01123 else if ( ( pTag.m_nKey == 0 ) && ( pTag.m_nType == ED2K_TAG_STRING ) && ( pTag.m_sKey == _T("length") ) )
01124 {
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 {
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 {
01148 strCodec = pTag.m_sValue;
01149 }
01150 else
01151 {
01152
01153
01154
01155
01156
01157
01158
01159
01160
01161
01162
01163
01164 }
01165 }
01166
01167
01168 CString strType;
01169
01170
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
01183 if ( strType.GetLength() )
01184 {
01185
01186
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 {
01190 m_sSchemaURI = CSchema::uriAudio;
01191
01192
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
01205
01206
01207
01208
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 {
01214 m_sSchemaURI = CSchema::uriVideo;
01215
01216
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
01225
01226
01227
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 {
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 {
01241 m_sSchemaURI = CSchema::uriImage;
01242 }
01243 else if ( strType == _T(".pdf") || strType == _T(".doc") || strType == _T(".txt") || strType == _T(".xls") )
01244 {
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
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
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
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
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
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
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 }