00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "StdAfx.h"
00027 #include "Shareaza.h"
00028 #include "Settings.h"
00029 #include "MatchObjects.h"
00030 #include "QuerySearch.h"
00031 #include "QueryHit.h"
00032 #include "Library.h"
00033 #include "SharedFile.h"
00034 #include "Schema.h"
00035 #include "Security.h"
00036 #include "ShellIcons.h"
00037 #include "VendorCache.h"
00038 #include "Downloads.h"
00039 #include "Transfers.h"
00040 #include "XML.h"
00041
00042 #include "TigerTree.h"
00043 #include "SHA.h"
00044 #include "ED2K.h"
00045
00046 #include "CtrlMatch.h"
00047 #include "LiveList.h"
00048 #include "ResultFilters.h"
00049
00050 #ifdef _DEBUG
00051 #undef THIS_FILE
00052 static char THIS_FILE[]=__FILE__;
00053 #define new DEBUG_NEW
00054 #endif
00055
00056 #define MAP_SIZE 256
00057 #define BUFFER_GROW 64
00058
00059
00061
00062
00063 CMatchList::CMatchList()
00064 {
00065 m_pResultFilters = new CResultFilters;
00066 m_pResultFilters->Load();
00067
00068 int nDefaultFilter = m_pResultFilters->m_nDefault;
00069
00070 if ( ( nDefaultFilter != NONE ) && ( (int)m_pResultFilters->m_nFilters >= nDefaultFilter + 1 ) )
00071 {
00072 m_sFilter = m_pResultFilters->m_pFilters[nDefaultFilter]->m_sFilter;
00073 m_bFilterBusy = m_pResultFilters->m_pFilters[nDefaultFilter]->m_bFilterBusy;
00074 m_bFilterPush = m_pResultFilters->m_pFilters[nDefaultFilter]->m_bFilterPush;
00075 m_bFilterUnstable = m_pResultFilters->m_pFilters[nDefaultFilter]->m_bFilterUnstable;
00076 m_bFilterReject = m_pResultFilters->m_pFilters[nDefaultFilter]->m_bFilterReject;
00077 m_bFilterLocal = m_pResultFilters->m_pFilters[nDefaultFilter]->m_bFilterLocal;
00078 m_bFilterBogus = m_pResultFilters->m_pFilters[nDefaultFilter]->m_bFilterBogus;
00079 m_bFilterDRM = m_pResultFilters->m_pFilters[nDefaultFilter]->m_bFilterDRM;
00080 m_bFilterAdult = m_pResultFilters->m_pFilters[nDefaultFilter]->m_bFilterAdult;
00081 m_nFilterMinSize = m_pResultFilters->m_pFilters[nDefaultFilter]->m_nFilterMinSize;
00082 m_nFilterMaxSize = m_pResultFilters->m_pFilters[nDefaultFilter]->m_nFilterMaxSize;
00083 m_nFilterSources = m_pResultFilters->m_pFilters[nDefaultFilter]->m_nFilterSources;
00084 }
00085 else
00086 {
00087 m_bFilterBusy = ( Settings.Search.FilterMask & ( 1 << 0 ) ) > 0;
00088 m_bFilterPush = ( Settings.Search.FilterMask & ( 1 << 1 ) ) > 0;
00089 m_bFilterUnstable = ( Settings.Search.FilterMask & ( 1 << 2 ) ) > 0;
00090 m_bFilterReject = ( Settings.Search.FilterMask & ( 1 << 3 ) ) > 0;
00091 m_bFilterLocal = ( Settings.Search.FilterMask & ( 1 << 4 ) ) > 0;
00092 m_bFilterBogus = ( Settings.Search.FilterMask & ( 1 << 5 ) ) > 0;
00093 m_bFilterDRM = ( Settings.Search.FilterMask & ( 1 << 6 ) ) > 0;
00094 m_bFilterAdult = ( Settings.Search.FilterMask & ( 1 << 7 ) ) > 0;
00095 m_nFilterMinSize = 1;
00096 m_nFilterMaxSize = 0;
00097 m_nFilterSources = 1;
00098 }
00099
00100 m_nSortColumn = -1;
00101 m_bSortDir = 1;
00102 m_pSchema = NULL;
00103 m_bNew = FALSE;
00104
00105 m_pFiles = NULL;
00106 m_nFiles = 0;
00107 m_nItems = 0;
00108 m_nFilteredFiles = 0;
00109 m_nFilteredHits = 0;
00110 m_nGnutellaHits = 0;
00111 m_nED2KHits = 0;
00112
00113 m_nBuffer = 0;
00114 m_pSizeMap = new CMatchFile*[ MAP_SIZE ];
00115 m_pMapSHA1 = new CMatchFile*[ MAP_SIZE ];
00116 m_pMapTiger = new CMatchFile*[ MAP_SIZE ];
00117 m_pMapED2K = new CMatchFile*[ MAP_SIZE ];
00118 m_pszFilter = NULL;
00119 m_pColumns = NULL;
00120 m_nColumns = 0;
00121
00122 ClearUpdated();
00123
00124 ZeroMemory( m_pSizeMap, 4 * MAP_SIZE );
00125 ZeroMemory( m_pMapSHA1, 4 * MAP_SIZE );
00126 ZeroMemory( m_pMapTiger, 4 * MAP_SIZE );
00127 ZeroMemory( m_pMapED2K, 4 * MAP_SIZE );
00128
00129 SetSortColumn( MATCH_COL_COUNT, TRUE );
00130 }
00131
00132 CMatchList::~CMatchList()
00133 {
00134 Clear();
00135
00136 if ( m_pColumns ) delete [] m_pColumns;
00137
00138 if ( m_pszFilter ) delete [] m_pszFilter;
00139
00140 delete [] m_pMapED2K;
00141 delete [] m_pMapTiger;
00142 delete [] m_pMapSHA1;
00143 delete [] m_pSizeMap;
00144
00145 if ( m_pFiles ) delete [] m_pFiles;
00146
00147 delete m_pResultFilters;
00148 }
00149
00151
00152
00153 void CMatchList::AddHits(CQueryHit* pHit, CQuerySearch* pFilter, BOOL bRequire)
00154 {
00155 CSingleLock pLock( &m_pSection, TRUE );
00156 CMatchFile **pMap, *pSeek;
00157
00158 while ( pHit )
00159 {
00160 CQueryHit* pNext = pHit->m_pNext;
00161
00162 if ( Security.IsDenied( &pHit->m_pAddress, pHit->m_sName ) )
00163 {
00164 delete pHit;
00165 pHit = pNext;
00166 continue;
00167 }
00168
00169 pHit->m_bNew = m_bNew;
00170
00171 if ( pFilter != NULL )
00172 {
00173 pHit->m_bMatched = pFilter->Match(
00174 pHit->m_sName, pHit->m_nSize, pHit->m_sSchemaURI, pHit->m_pXML,
00175 pHit->m_bSHA1 ? &pHit->m_pSHA1 : NULL,
00176 pHit->m_bTiger ? &pHit->m_pTiger : NULL,
00177 pHit->m_bED2K ? &pHit->m_pED2K : NULL );
00178
00179 if ( bRequire && ! pHit->m_bMatched )
00180 {
00181 delete pHit;
00182 pHit = pNext;
00183 continue;
00184 }
00185
00186 if ( Settings.Search.SchemaTypes && pFilter->m_pSchema && ! pHit->m_bBogus )
00187 {
00188 if ( pFilter->m_pSchema->CheckURI( pHit->m_sSchemaURI ) )
00189 {
00190 pHit->m_bBogus = FALSE;
00191 }
00192 else
00193 {
00194 pHit->m_bBogus = ! pFilter->m_pSchema->FilterType( pHit->m_sName, TRUE );
00195 }
00196 }
00197 }
00198 else
00199 {
00200 pHit->m_bMatched = TRUE;
00201 }
00202
00203 FilterHit( pHit );
00204
00205 CMatchFile* pFile = NULL;
00206 BOOL bHadSHA1 = FALSE;
00207 BOOL bHadTiger = FALSE;
00208 BOOL bHadED2K = FALSE;
00209 int nHadCount = 0;
00210 int nHadFiltered = 0;
00211 BOOL bHad[3];
00212 PROTOCOLID nProtocol= pHit->m_nProtocol;
00213
00214 if ( pHit->m_bSHA1 )
00215 {
00216 pMap = m_pMapSHA1 + ( pHit->m_pSHA1.n[0] );
00217
00218 for ( pSeek = *pMap ; pSeek ; pSeek = pSeek->m_pNextSHA1 )
00219 {
00220 if ( pSeek->m_pSHA1 == pHit->m_pSHA1 )
00221 {
00222 nHadCount = pSeek->GetItemCount();
00223 nHadFiltered = pSeek->m_nFiltered;
00224
00225 bHad[0] = pSeek->m_bSHA1;
00226 bHad[1] = pSeek->m_bTiger;
00227 bHad[2] = pSeek->m_bED2K;
00228
00229 if ( pSeek->Add( pHit, TRUE ) )
00230 {
00231 pFile = pSeek;
00232 bHadSHA1 |= bHad[0];
00233 bHadTiger |= bHad[1];
00234 bHadED2K |= bHad[2];
00235 break;
00236 }
00237 }
00238 }
00239 }
00240 if ( pFile == NULL && pHit->m_bTiger )
00241 {
00242 pMap = m_pMapTiger + ( pHit->m_pTiger.n[0] );
00243
00244 for ( pSeek = *pMap ; pSeek ; pSeek = pSeek->m_pNextTiger )
00245 {
00246 if ( pSeek->m_pTiger == pHit->m_pTiger )
00247 {
00248 nHadCount = pSeek->GetItemCount();
00249 nHadFiltered = pSeek->m_nFiltered;
00250
00251 bHad[0] = pSeek->m_bSHA1;
00252 bHad[1] = pSeek->m_bTiger;
00253 bHad[2] = pSeek->m_bED2K;
00254
00255 if ( pSeek->Add( pHit, TRUE ) )
00256 {
00257 pFile = pSeek;
00258 bHadSHA1 |= bHad[0];
00259 bHadTiger |= bHad[1];
00260 bHadED2K |= bHad[2];
00261 break;
00262 }
00263 }
00264 }
00265 }
00266 if ( pFile == NULL && pHit->m_bED2K )
00267 {
00268 pMap = m_pMapED2K + ( pHit->m_pED2K.n[0] );
00269
00270 for ( pSeek = *pMap ; pSeek ; pSeek = pSeek->m_pNextED2K )
00271 {
00272 if ( pSeek->m_pED2K == pHit->m_pED2K )
00273 {
00274 nHadCount = pSeek->GetItemCount();
00275 nHadFiltered = pSeek->m_nFiltered;
00276
00277 bHad[0] = pSeek->m_bSHA1;
00278 bHad[1] = pSeek->m_bTiger;
00279 bHad[2] = pSeek->m_bED2K;
00280
00281 if ( pSeek->Add( pHit, TRUE ) )
00282 {
00283 pFile = pSeek;
00284 bHadSHA1 |= bHad[0];
00285 bHadTiger |= bHad[1];
00286 bHadED2K |= bHad[2];
00287
00288 break;
00289 }
00290 }
00291 }
00292 }
00293
00294 if ( pFile == NULL && ( ( ! pHit->m_bSHA1 && ! pHit->m_bTiger && ! pHit->m_bED2K ) || ! Settings.General.HashIntegrity ) )
00295 {
00296 pMap = m_pSizeMap + (DWORD)( pHit->m_nSize & 0xFF );
00297
00298 for ( pSeek = *pMap ; pSeek ; pSeek = pSeek->m_pNextSize )
00299 {
00300 if ( pSeek->m_nSize == pHit->m_nSize )
00301 {
00302 bHadSHA1 = pSeek->m_bSHA1;
00303 bHadTiger = pSeek->m_bTiger;
00304 bHadED2K = pSeek->m_bED2K;
00305 nHadCount = pSeek->GetItemCount();
00306 nHadFiltered = pSeek->m_nFiltered;
00307
00308 if ( pSeek->Add( pHit ) )
00309 {
00310 pFile = pSeek;
00311 break;
00312 }
00313 }
00314 }
00315 if ( ! pFile ) bHadSHA1 = bHadTiger = bHadED2K = FALSE;
00316 }
00317
00318 if ( pFile != NULL )
00319 {
00320 pMap = m_pFiles;
00321
00322 for ( DWORD nCount = m_nFiles ; nCount ; nCount--, pMap++ )
00323 {
00324 if ( *pMap == pFile )
00325 {
00326 if ( m_nSortColumn >= 0 )
00327 {
00328 UpdateRange( m_nFiles - nCount );
00329 MoveMemory( pMap, pMap + 1, ( nCount - 1 ) << 2 );
00330 m_nFiles--;
00331 InsertSorted( pFile );
00332 }
00333 else
00334 {
00335 UpdateRange( m_nFiles - nCount, m_nFiles - nCount );
00336 }
00337
00338 break;
00339 }
00340 }
00341
00342 if ( nHadCount )
00343 {
00344 m_nItems -= nHadCount;
00345 m_nFilteredFiles --;
00346 m_nFilteredHits -= nHadFiltered;
00347
00348 switch ( nProtocol )
00349 {
00350 case PROTOCOL_G1:
00351 case PROTOCOL_G2:
00352 m_nGnutellaHits -= nHadFiltered;
00353 break;
00354 case PROTOCOL_ED2K:
00355 m_nED2KHits -= nHadFiltered;
00356 break;
00357 }
00358 }
00359 }
00360 else
00361 {
00362 pFile = new CMatchFile( this, pHit );
00363 pFile->m_bNew = m_bNew;
00364
00365 pMap = m_pSizeMap + (DWORD)( pFile->m_nSize & 0xFF );
00366 pFile->m_pNextSize = *pMap;
00367 *pMap = pFile;
00368
00369 if ( m_nFiles + 1 > m_nBuffer )
00370 {
00371 m_nBuffer += BUFFER_GROW;
00372 CMatchFile** pFiles = new CMatchFile*[ m_nBuffer ];
00373
00374 if ( m_pFiles )
00375 {
00376 CopyMemory( pFiles, m_pFiles, m_nFiles << 2 );
00377 delete [] m_pFiles;
00378 }
00379
00380 m_pFiles = pFiles;
00381 }
00382
00383 if ( m_nSortColumn >= 0 )
00384 {
00385 InsertSorted( pFile );
00386 }
00387 else
00388 {
00389 UpdateRange( m_nFiles );
00390 m_pFiles[ m_nFiles++ ] = pFile;
00391 }
00392 }
00393
00394 if ( ! bHadSHA1 && pFile->m_bSHA1 )
00395 {
00396 pMap = m_pMapSHA1 + ( pFile->m_pSHA1.n[0] );
00397 pFile->m_pNextSHA1 = *pMap;
00398 *pMap = pFile;
00399 }
00400 if ( ! bHadTiger && pFile->m_bTiger )
00401 {
00402 pMap = m_pMapTiger + ( pFile->m_pTiger.n[0] );
00403 pFile->m_pNextTiger = *pMap;
00404 *pMap = pFile;
00405 }
00406 if ( ! bHadED2K && pFile->m_bED2K )
00407 {
00408 pMap = m_pMapED2K + ( pFile->m_pED2K.n[0] );
00409 pFile->m_pNextED2K = *pMap;
00410 *pMap = pFile;
00411 }
00412
00413 nHadCount = pFile->GetItemCount();
00414
00415 if ( nHadCount )
00416 {
00417 m_nItems += nHadCount;
00418 m_nFilteredFiles ++;
00419 m_nFilteredHits += pFile->m_nFiltered;
00420
00421 switch ( nProtocol )
00422 {
00423 case PROTOCOL_G1:
00424 case PROTOCOL_G2:
00425 m_nGnutellaHits += pFile->m_nFiltered;
00426 break;
00427 case PROTOCOL_ED2K:
00428 m_nED2KHits += pFile->m_nFiltered;
00429 break;
00430 }
00431
00432 }
00433
00434 pHit = pNext;
00435 }
00436 }
00437
00439
00440
00441 void CMatchList::InsertSorted(CMatchFile* pFile)
00442 {
00443 int nFirst = 0;
00444 for ( int nLast = m_nFiles - 1 ; nLast >= nFirst ; )
00445 {
00446 DWORD nMiddle = ( nFirst + nLast ) >> 1;
00447
00448 if ( pFile->Compare( m_pFiles[ nMiddle ] ) == m_bSortDir )
00449 {
00450 nFirst = nMiddle + 1;
00451 }
00452 else
00453 {
00454 nLast = nMiddle - 1;
00455 }
00456 }
00457
00458 MoveMemory( m_pFiles + nFirst + 1, m_pFiles + nFirst, ( m_nFiles - nFirst ) << 2 );
00459 m_pFiles[ nFirst ] = pFile;
00460 m_nFiles++;
00461 UpdateRange( nFirst );
00462 }
00463
00465
00466
00467 DWORD CMatchList::FileToItem(CMatchFile* pFile)
00468 {
00469 CSingleLock pLock( &m_pSection, TRUE );
00470
00471 CMatchFile** pLoop = m_pFiles;
00472
00473 for ( DWORD nCount = 0 ; nCount < m_nFiles ; nCount++, pLoop++ )
00474 {
00475 if ( *pLoop == pFile ) return nCount;
00476 }
00477
00478 return 0xFFFFFFFF;
00479 }
00480
00482
00483
00484 void CMatchList::Clear()
00485 {
00486 CSingleLock pLock( &m_pSection, TRUE );
00487
00488 if ( m_pFiles )
00489 {
00490 CMatchFile** pLoop = m_pFiles;
00491
00492 for ( DWORD nCount = m_nFiles ; nCount ; nCount--, pLoop++ )
00493 {
00494 if ( *pLoop ) delete (*pLoop);
00495 }
00496 }
00497
00498 m_nFiles = 0;
00499 m_nItems = 0;
00500 m_nFilteredFiles = 0;
00501 m_nFilteredHits = 0;
00502
00503 m_pSelectedFiles.RemoveAll();
00504 m_pSelectedHits.RemoveAll();
00505
00506 ZeroMemory( m_pSizeMap, 4 * MAP_SIZE );
00507 ZeroMemory( m_pMapSHA1, 4 * MAP_SIZE );
00508 ZeroMemory( m_pMapTiger, 4 * MAP_SIZE );
00509 ZeroMemory( m_pMapED2K, 4 * MAP_SIZE );
00510
00511 UpdateRange();
00512 }
00513
00515
00516
00517 BOOL CMatchList::Select(CMatchFile* pFile, CQueryHit* pHit, BOOL bSelected)
00518 {
00519 if ( pHit != NULL )
00520 {
00521 if ( pHit->m_bSelected == bSelected ) return FALSE;
00522 pHit->m_bSelected = bSelected;
00523
00524 if ( bSelected )
00525 m_pSelectedHits.AddTail( pHit );
00526 else
00527 m_pSelectedHits.RemoveAt( m_pSelectedHits.Find( pHit ) );
00528 }
00529 else
00530 {
00531 if ( pFile->m_bSelected == bSelected ) return FALSE;
00532 pFile->m_bSelected = bSelected;
00533
00534 if ( bSelected )
00535 m_pSelectedFiles.AddTail( pFile );
00536 else
00537 m_pSelectedFiles.RemoveAt( m_pSelectedFiles.Find( pFile ) );
00538 }
00539
00540 if ( pFile != NULL )
00541 {
00542 DWORD nIndex = FileToItem( pFile );
00543 UpdateRange( nIndex, nIndex );
00544 }
00545
00546 return TRUE;
00547 }
00548
00549 CMatchFile* CMatchList::GetSelectedFile(BOOL bFromHit) const
00550 {
00551 if ( m_pSelectedFiles.GetCount() != 1 )
00552 {
00553 if ( bFromHit == FALSE ) return NULL;
00554
00555 CQueryHit* pHit = GetSelectedHit();
00556 if ( pHit == NULL ) return NULL;
00557
00558 CMatchFile** pLoop = m_pFiles;
00559
00560 for ( DWORD nCount = m_nFiles ; nCount ; nCount--, pLoop++ )
00561 {
00562 if ( (*pLoop)->Check( pHit ) ) return *pLoop;
00563 }
00564
00565 return NULL;
00566 }
00567
00568 return (CMatchFile*)m_pSelectedFiles.GetHead();
00569 }
00570
00571 CQueryHit* CMatchList::GetSelectedHit() const
00572 {
00573 if ( m_pSelectedHits.GetCount() != 1 )
00574 {
00575 if ( m_pSelectedFiles.GetCount() != 1 ) return NULL;
00576 CMatchFile* pFile = (CMatchFile*)m_pSelectedFiles.GetHead();
00577 return pFile->m_nFiltered == 1 ? pFile->m_pHits : NULL;
00578 }
00579
00580 return (CQueryHit*)m_pSelectedHits.GetHead();
00581 }
00582
00583 int CMatchList::GetSelectedCount() const
00584 {
00585 return m_pSelectedFiles.GetCount() + m_pSelectedHits.GetCount();
00586 }
00587
00588 BOOL CMatchList::ClearSelection()
00589 {
00590 CSingleLock pLock( &m_pSection, TRUE );
00591
00592 CMatchFile** pLoop = m_pFiles;
00593 BOOL bChanged = FALSE;
00594
00595 for ( DWORD nCount = 0 ; nCount < m_nFiles ; nCount++, pLoop++ )
00596 {
00597 if ( (*pLoop)->m_bSelected )
00598 {
00599 UpdateRange( nCount, nCount );
00600 (*pLoop)->m_bSelected = FALSE;
00601 bChanged = TRUE;
00602 }
00603
00604 for ( CQueryHit* pHit = (*pLoop)->m_pHits ; pHit ; pHit = pHit->m_pNext )
00605 {
00606 if ( pHit->m_bSelected )
00607 {
00608 UpdateRange( nCount, nCount );
00609 pHit->m_bSelected = FALSE;
00610 bChanged = TRUE;
00611 }
00612 }
00613 }
00614
00615 m_pSelectedFiles.RemoveAll();
00616 m_pSelectedHits.RemoveAll();
00617
00618 return bChanged;
00619 }
00620
00622
00623
00624 void CMatchList::Filter()
00625 {
00626 CSingleLock pLock( &m_pSection, TRUE );
00627
00628 Settings.Search.FilterMask = 0;
00629
00630 if ( m_bFilterBusy ) Settings.Search.FilterMask |= ( 1 << 0 );
00631 if ( m_bFilterPush ) Settings.Search.FilterMask |= ( 1 << 1 );
00632 if ( m_bFilterUnstable ) Settings.Search.FilterMask |= ( 1 << 2 );
00633 if ( m_bFilterReject ) Settings.Search.FilterMask |= ( 1 << 3 );
00634 if ( m_bFilterLocal ) Settings.Search.FilterMask |= ( 1 << 4 );
00635 if ( m_bFilterBogus ) Settings.Search.FilterMask |= ( 1 << 5 );
00636 if ( m_bFilterDRM ) Settings.Search.FilterMask |= ( 1 << 6 );
00637 if ( m_bFilterAdult ) Settings.Search.FilterMask |= ( 1 << 7 );
00638
00639 if ( m_pszFilter ) delete [] m_pszFilter;
00640 m_pszFilter = NULL;
00641
00642 if ( m_sFilter.GetLength() )
00643 {
00644 LPCTSTR pszPtr = m_sFilter;
00645 BOOL bQuote = FALSE;
00646 BOOL bNot = FALSE;
00647 int nWordLen = 3;
00648
00649 CStringList pWords;
00650
00651 int nStart = 0, nPos = 0;
00652 for ( ; *pszPtr ; nPos++, pszPtr++ )
00653 {
00654 if ( *pszPtr == '\"' || ( ! bQuote && ( *pszPtr == ' ' || *pszPtr == '\t' || *pszPtr == '-' ) ) )
00655 {
00656 if ( nStart < nPos )
00657 {
00658 pWords.AddTail( ( bNot ? '-' : '+' ) + m_sFilter.Mid( nStart, nPos - nStart ) );
00659 nWordLen += ( nPos - nStart ) + 2;
00660 }
00661
00662 nStart = nPos + 1;
00663
00664 if ( *pszPtr == '\"' )
00665 {
00666 bQuote = ! bQuote;
00667 }
00668 else if ( *pszPtr == '-' && ! bQuote )
00669 {
00670 bNot = TRUE;
00671 }
00672
00673 if ( bNot && ! bQuote && *pszPtr != '-' ) bNot = FALSE;
00674 }
00675 }
00676
00677 if ( nStart < nPos )
00678 {
00679 pWords.AddTail( ( bNot ? '-' : '+' ) + m_sFilter.Mid( nStart, nPos - nStart ) );
00680 nWordLen += ( nPos - nStart ) + 2;
00681 }
00682
00683 m_pszFilter = new TCHAR[ nWordLen ];
00684 LPTSTR pszFilter = m_pszFilter;
00685
00686 for ( POSITION pos = pWords.GetHeadPosition() ; pos ; )
00687 {
00688 CString strWord = pWords.GetNext( pos );
00689 CopyMemory( pszFilter, (LPCTSTR)strWord, sizeof(TCHAR) * ( strWord.GetLength() + 1 ) );
00690 pszFilter += strWord.GetLength() + 1;
00691 }
00692
00693 *pszFilter++ = 0;
00694 *pszFilter++ = 0;
00695 }
00696
00697 CMatchFile** pLoop = m_pFiles;
00698
00699 m_nItems = 0;
00700 m_nFilteredFiles = 0;
00701 m_nFilteredHits = 0;
00702
00703 for ( DWORD nCount = m_nFiles, nItems = 0 ; nCount ; nCount--, pLoop++ )
00704 {
00705 if ( nItems = (*pLoop)->Filter() )
00706 {
00707 m_nItems += nItems;
00708 m_nFilteredFiles ++;
00709 m_nFilteredHits += (*pLoop)->m_nFiltered;
00710 }
00711 else
00712 {
00713 if ( (*pLoop)->m_bSelected ) Select( *pLoop, NULL, FALSE );
00714 }
00715 }
00716
00717 SetSortColumn( m_nSortColumn, m_bSortDir < 0 );
00718 UpdateRange();
00719 }
00720
00722
00723
00724 BOOL CMatchList::FilterHit(CQueryHit* pHit)
00725 {
00726 pHit->m_bFiltered = FALSE;
00727
00728 if ( m_bFilterBusy && pHit->m_bBusy == TS_TRUE ) return FALSE;
00729
00730 if ( m_bFilterPush && pHit->m_bPush == TS_TRUE ) return FALSE;
00731 if ( m_bFilterUnstable && pHit->m_bStable == TS_FALSE ) return FALSE;
00732 if ( m_bFilterReject && pHit->m_bMatched == FALSE ) return FALSE;
00733 if ( m_bFilterBogus && pHit->m_bBogus ) return FALSE;
00734
00735 if ( m_nFilterMinSize > 0 && pHit->m_nSize < m_nFilterMinSize ) return FALSE;
00736 if ( m_nFilterMaxSize > 0 && pHit->m_nSize > m_nFilterMaxSize ) return FALSE;
00737
00738 if ( m_pszFilter )
00739 {
00740 LPCTSTR pszName = pHit->m_sName;
00741
00742 for ( LPCTSTR pszFilter = m_pszFilter ; *pszFilter ; )
00743 {
00744 if ( *pszFilter == '-' )
00745 {
00746 if ( _tcsistr( pszName, pszFilter + 1 ) != NULL ) return FALSE;
00747 }
00748 else
00749 {
00750 if ( _tcsistr( pszName, pszFilter + 1 ) == NULL ) return FALSE;
00751 }
00752
00753 pszFilter += _tcslen( pszFilter + 1 ) + 2;
00754 }
00755 }
00756
00757 if ( pHit->m_nSpeed )
00758 pHit->m_sSpeed = Settings.SmartVolume( pHit->m_nSpeed, TRUE, TRUE );
00759 else
00760 pHit->m_sSpeed.Empty();
00761
00762 if ( AdultFilter.IsHitAdult( pHit->m_sName ) )
00763 {
00764 if ( Settings.Search.AdultFilter ) return FALSE;
00765 if ( m_bFilterAdult ) return FALSE;
00766 }
00767
00768 return ( pHit->m_bFiltered = TRUE );
00769 }
00770
00772
00773
00774 void CMatchList::SelectSchema(CSchema* pSchema, CPtrList* pColumns)
00775 {
00776 CSingleLock pLock( &m_pSection, TRUE );
00777
00778 CMatchFile** pLoop = m_pFiles;
00779
00780 for ( DWORD nCount = m_nFiles ; nCount ; nCount--, pLoop++ )
00781 {
00782 if ( (*pLoop)->m_pColumns )
00783 {
00784 delete [] (*pLoop)->m_pColumns;
00785 (*pLoop)->m_pColumns = NULL;
00786 (*pLoop)->m_nColumns = 0;
00787 }
00788 }
00789
00790 if ( m_pColumns ) delete [] m_pColumns;
00791 m_pColumns = NULL;
00792 m_nColumns = 0;
00793 m_pSchema = pSchema;
00794
00795 if ( ! pSchema || ! pColumns ) return;
00796
00797 m_pColumns = new CSchemaMember*[ pColumns->GetCount() ];
00798
00799 for ( POSITION pos = pColumns->GetHeadPosition() ; pos ; )
00800 {
00801 m_pColumns[ m_nColumns++ ] = (CSchemaMember*)pColumns->GetNext( pos );
00802 }
00803
00804 Filter();
00805 }
00806
00808
00809
00810 void CMatchList::SetSortColumn(int nColumn, BOOL bDirection)
00811 {
00812 m_nSortColumn = nColumn;
00813 m_bSortDir = bDirection ? -1 : 1;
00814
00815 if ( m_nSortColumn < 0 || ! m_nFiles ) return;
00816
00817 int nFirst = 0;
00818 int nLast = m_nFiles - 1;
00819 DWORD nStack = 0;
00820
00821 int nStackFirst[128];
00822 int nStackLast[128];
00823
00824 for ( ; ; )
00825 {
00826 if ( nLast - nFirst <= 16 )
00827 {
00828 int nIndex;
00829 CMatchFile* pPrevious = m_pFiles[ nFirst ];
00830 CMatchFile* pCurrent;
00831
00832 for ( nIndex = nFirst + 1 ; nIndex <= nLast ; ++nIndex )
00833 {
00834 pCurrent = m_pFiles[ nIndex ];
00835
00836 if ( pPrevious->Compare( pCurrent ) == m_bSortDir )
00837 {
00838 int nIndex2;
00839 m_pFiles[ nIndex ] = pPrevious;
00840
00841 for ( nIndex2 = nIndex - 1 ; nIndex2 > nFirst ; )
00842 {
00843 CMatchFile* pTemp = m_pFiles[ nIndex2 - 1 ];
00844
00845 if ( pTemp->Compare( pCurrent ) == m_bSortDir )
00846 {
00847 m_pFiles[ nIndex2-- ] = pTemp;
00848 }
00849 else break;
00850 }
00851 m_pFiles[ nIndex2 ] = pCurrent;
00852 }
00853 else
00854 {
00855 pPrevious = pCurrent;
00856 }
00857 }
00858 }
00859 else
00860 {
00861 CMatchFile* pPivot;
00862 {
00863 CMatchFile* pTemp;
00864 DWORD nMiddle = ( nFirst + nLast ) >> 1;
00865
00866 pTemp = m_pFiles[ nFirst ];
00867 if ( pTemp->Compare( m_pFiles[ nLast ] ) == m_bSortDir )
00868 {
00869 m_pFiles[ nFirst ] = m_pFiles[ nLast ]; m_pFiles[ nLast ] = pTemp;
00870 }
00871
00872 pTemp = m_pFiles[ nMiddle ];
00873 if ( m_pFiles[ nFirst ]->Compare( pTemp ) == m_bSortDir )
00874 {
00875 m_pFiles[ nMiddle ] = m_pFiles[ nFirst ]; m_pFiles[ nFirst ] = pTemp;
00876 }
00877
00878 pTemp = m_pFiles[ nLast ];
00879 if ( m_pFiles[ nMiddle ]->Compare( pTemp ) == m_bSortDir )
00880 {
00881 m_pFiles[ nLast ] = m_pFiles[ nMiddle ]; m_pFiles[ nMiddle ] = pTemp;
00882 }
00883 pPivot = m_pFiles[ nMiddle ];
00884 }
00885 {
00886 DWORD nUp;
00887 {
00888 DWORD nDown = nFirst;
00889 nUp = nLast;
00890
00891 for ( ; ; )
00892 {
00893 do
00894 {
00895 ++nDown;
00896 } while ( pPivot->Compare( m_pFiles[ nDown ] ) == m_bSortDir );
00897 do
00898 {
00899 --nUp;
00900 } while ( m_pFiles[ nUp ]->Compare( pPivot ) == m_bSortDir );
00901
00902 if ( nUp > nDown )
00903 {
00904 CMatchFile* pTemp = m_pFiles[ nDown ];
00905 m_pFiles[ nDown ] = m_pFiles[ nUp ];
00906 m_pFiles[ nUp ] = pTemp;
00907 }
00908 else
00909 break;
00910 }
00911 }
00912 {
00913 if ( ( nUp - nFirst + 1 ) >= ( nLast - nUp ) )
00914 {
00915 nStackFirst[ nStack ] = nFirst;
00916 nStackLast[ nStack++ ] = nUp;
00917
00918 nFirst = nUp + 1;
00919 }
00920 else
00921 {
00922 nStackFirst[ nStack ] = nUp + 1;
00923 nStackLast[ nStack++ ] = nLast;
00924
00925 nLast = nUp;
00926 }
00927 }
00928 continue;
00929 }
00930 }
00931
00932 if ( nStack > 0 )
00933 {
00934 nFirst = nStackFirst[ --nStack ];
00935 nLast = nStackLast[ nStack ];
00936 }
00937 else
00938 break;
00939 }
00940
00941 UpdateRange();
00942 }
00943
00945
00946
00947 void CMatchList::UpdateRange(DWORD nMin, DWORD nMax)
00948 {
00949 m_nUpdateMin = min( m_nUpdateMin, nMin );
00950 m_nUpdateMax = max( m_nUpdateMax, nMax );
00951 m_bUpdated = TRUE;
00952 }
00953
00954 void CMatchList::ClearUpdated()
00955 {
00956 m_bUpdated = FALSE;
00957 m_nUpdateMin = 0xFFFFFFFF;
00958 m_nUpdateMax = 0;
00959 }
00960
00962
00963
00964 void CMatchList::ClearNew()
00965 {
00966 CSingleLock pLock( &m_pSection, TRUE );
00967
00968 for ( DWORD nFile = 0 ; nFile < m_nFiles ; nFile++ )
00969 {
00970 m_pFiles[ nFile ]->ClearNew();
00971 }
00972
00973 m_bNew = TRUE;
00974 }
00975
00977
00978
00979 void CMatchList::Serialize(CArchive& ar)
00980 {
00981 int nVersion = 11;
00982
00983 if ( ar.IsStoring() )
00984 {
00985 ar << nVersion;
00986
00987 ar << m_sFilter;
00988 ar << m_bFilterBusy;
00989 ar << m_bFilterPush;
00990 ar << m_bFilterUnstable;
00991 ar << m_bFilterReject;
00992 ar << m_bFilterLocal;
00993 ar << m_bFilterBogus;
00994 ar << m_nFilterMinSize;
00995 ar << m_nFilterMaxSize;
00996 ar << m_nFilterSources;
00997 ar << m_nSortColumn;
00998 ar << m_bSortDir;
00999
01000 ar.WriteCount( m_nFiles );
01001
01002 for ( DWORD nFile = 0 ; nFile < m_nFiles ; nFile++ )
01003 {
01004 CMatchFile* pFile = m_pFiles[ nFile ];
01005 pFile->Serialize( ar, nVersion );
01006 }
01007 }
01008 else
01009 {
01010 ar >> nVersion;
01011 if ( nVersion < 8 ) AfxThrowUserException();
01012
01013 ar >> m_sFilter;
01014 ar >> m_bFilterBusy;
01015 ar >> m_bFilterPush;
01016 ar >> m_bFilterUnstable;
01017 ar >> m_bFilterReject;
01018 ar >> m_bFilterLocal;
01019 ar >> m_bFilterBogus;
01020
01021 if ( nVersion >= 10 )
01022 {
01023 ar >> m_nFilterMinSize;
01024 ar >> m_nFilterMaxSize;
01025 }
01026 else
01027 {
01028 DWORD nInt32;
01029 ar >> nInt32; m_nFilterMinSize = nInt32;
01030 ar >> nInt32; m_nFilterMaxSize = nInt32;
01031 }
01032
01033 ar >> m_nFilterSources;
01034 ar >> m_nSortColumn;
01035 ar >> m_bSortDir;
01036
01037 m_nFiles = m_nBuffer = ar.ReadCount();
01038 m_pFiles = new CMatchFile*[ m_nFiles ];
01039 ZeroMemory( m_pFiles, sizeof(CMatchFile*) * m_nFiles );
01040
01041 for ( DWORD nFile = 0 ; nFile < m_nFiles ; nFile++ )
01042 {
01043 CMatchFile* pFile = new CMatchFile( this );
01044 m_pFiles[ nFile ] = pFile;
01045 pFile->Serialize( ar, nVersion );
01046
01047 CMatchFile** pMap = m_pSizeMap + (DWORD)( pFile->m_nSize & 0xFF );
01048 pFile->m_pNextSize = *pMap;
01049 *pMap = pFile;
01050
01051 if ( pFile->m_bSHA1 )
01052 {
01053 pMap = m_pMapSHA1 + ( pFile->m_pSHA1.n[0] );
01054 pFile->m_pNextSHA1 = *pMap;
01055 *pMap = pFile;
01056 }
01057 if ( pFile->m_bTiger )
01058 {
01059 pMap = m_pMapTiger + ( pFile->m_pTiger.n[0] );
01060 pFile->m_pNextTiger = *pMap;
01061 *pMap = pFile;
01062 }
01063 if ( pFile->m_bED2K )
01064 {
01065 pMap = m_pMapED2K + ( pFile->m_pED2K.n[0] );
01066 pFile->m_pNextED2K = *pMap;
01067 *pMap = pFile;
01068 }
01069 }
01070
01071 Filter();
01072 }
01073 }
01074
01075
01077
01078
01079 CMatchFile::CMatchFile(CMatchList* pList, CQueryHit* pHit)
01080 {
01081 m_pList = pList;
01082 m_pHits = NULL;
01083 m_pBest = NULL;
01084 m_nTotal = NULL;
01085 m_nFiltered = 0;
01086 m_nSources = 0;
01087
01088 m_pNextSize = NULL;
01089 m_pNextSHA1 = NULL;
01090 m_pNextTiger = NULL;
01091 m_pNextED2K = NULL;
01092
01093 m_bSHA1 = FALSE;
01094 m_bTiger = FALSE;
01095 m_bED2K = FALSE;
01096 m_nSize = pHit ? pHit->m_nSize : 0;
01097 m_sSize = Settings.SmartVolume( m_nSize, FALSE );
01098
01099 m_bBusy = TS_UNKNOWN;
01100 m_bPush = TS_UNKNOWN;
01101 m_bStable = TS_UNKNOWN;
01102 m_bPreview = FALSE;
01103 m_nSpeed = 0;
01104 m_nRating = 0;
01105 m_nRated = 0;
01106 m_bDRM = FALSE;
01107 m_bCollection = FALSE;
01108
01109 m_bExpanded = Settings.Search.ExpandMatches;
01110 m_bSelected = FALSE;
01111 m_bExisting = FALSE;
01112 m_bDownload = FALSE;
01113 m_bNew = FALSE;
01114 m_bOneValid = FALSE;
01115 m_nShellIndex = -1;
01116 m_pColumns = NULL;
01117 m_nColumns = 0;
01118 m_pPreview = NULL;
01119 m_nPreview = 0;
01120
01121 if ( pHit ) Add( pHit );
01122 }
01123
01124 CMatchFile::~CMatchFile()
01125 {
01126 while ( m_pHits )
01127 {
01128 CQueryHit* pNext = m_pHits->m_pNext;
01129 delete m_pHits;
01130 m_pHits = pNext;
01131 }
01132
01133 if ( m_pColumns ) delete [] m_pColumns;
01134 if ( m_pPreview ) delete [] m_pPreview;
01135 }
01136
01138
01139
01140 BOOL CMatchFile::Add(CQueryHit* pHit, BOOL bForce)
01141 {
01142 if ( pHit->m_nSize != m_nSize ) return FALSE;
01143
01144 if ( ! bForce )
01145 {
01146 if ( m_bSHA1 && ( pHit->m_bSHA1 || Settings.General.HashIntegrity ) )
01147 {
01148 if ( ! pHit->m_bSHA1 ) return FALSE;
01149 if ( m_pSHA1 != pHit->m_pSHA1 ) return FALSE;
01150 bForce = TRUE;
01151 }
01152 else if ( ! m_bSHA1 && pHit->m_bSHA1 && Settings.General.HashIntegrity && m_pHits )
01153 {
01154 return FALSE;
01155 }
01156 }
01157
01158 BOOL bSubstituted = FALSE;
01159
01160 if ( m_pHits )
01161 {
01162 for ( CQueryHit* pOld = m_pHits ; pOld ; pOld = pOld->m_pNext )
01163 {
01164 BOOL bName = _tcsicmp( pHit->m_sName, pOld->m_sName ) == 0;
01165
01166 if ( ! bForce && bName ) bForce = TRUE;
01167
01168 if ( bName && pHit->m_pAddress.S_un.S_addr == pOld->m_pAddress.S_un.S_addr &&
01169 pHit->m_nPort == pOld->m_nPort )
01170 {
01171 if ( pOld->m_bFiltered )
01172 {
01173 m_nFiltered --;
01174 m_nSources -= pOld->GetSources();
01175 m_nSpeed -= pOld->m_nSpeed;
01176 }
01177
01178 pOld->Copy( pHit );
01179 delete pHit;
01180
01181 pHit = pOld;
01182 bForce = bSubstituted = TRUE;
01183 break;
01184 }
01185 }
01186
01187 if ( ! bForce ) return FALSE;
01188 }
01189
01190 if ( ! bSubstituted )
01191 {
01192 pHit->m_pNext = m_pHits;
01193 m_pHits = pHit;
01194 m_nTotal++;
01195 }
01196
01197 CSingleLock pLock1( &Library.m_pSection );
01198 BOOL bLocked = FALSE;
01199
01200 if ( ! m_bSHA1 && pHit->m_bSHA1 )
01201 {
01202 m_pSHA1 = pHit->m_pSHA1;
01203 m_bSHA1 = TRUE;
01204
01205 if ( ! m_bExisting && pLock1.Lock( 100 ) )
01206 {
01207 if ( CLibraryFile* pExisting = LibraryMaps.LookupFileBySHA1( &m_pSHA1 ) )
01208 m_bExisting = pExisting->IsAvailable() ? 1 : 2;
01209 bLocked = TRUE;
01210 }
01211 }
01212
01213 if ( ! m_bTiger && pHit->m_bTiger )
01214 {
01215 m_pTiger = pHit->m_pTiger;
01216 m_bTiger = TRUE;
01217
01218 if ( ! m_bExisting && ( bLocked || pLock1.Lock( 100 ) ) )
01219 {
01220 if ( CLibraryFile* pExisting = LibraryMaps.LookupFileByTiger( &m_pTiger ) )
01221 m_bExisting = pExisting->IsAvailable() ? 1 : 2;
01222 bLocked = TRUE;
01223 }
01224 }
01225
01226 if ( ! m_bED2K && pHit->m_bED2K )
01227 {
01228 m_pED2K = pHit->m_pED2K;
01229 m_bED2K = TRUE;
01230
01231 if ( ! m_bExisting && ( bLocked || pLock1.Lock( 100 ) ) )
01232 {
01233 if ( CLibraryFile* pExisting = LibraryMaps.LookupFileByED2K( &m_pED2K ) )
01234 m_bExisting = pExisting->IsAvailable() ? 1 : 2;
01235 bLocked = TRUE;
01236 }
01237 }
01238
01239 if ( bLocked ) pLock1.Unlock();
01240
01241 if ( ! m_bDownload && ! m_bExisting && ( m_bSHA1 || m_bTiger || m_bED2K ) )
01242 {
01243 CSingleLock pLock2( &Transfers.m_pSection );
01244
01245 if ( pLock2.Lock( 50 ) )
01246 {
01247 if ( m_bSHA1 && Downloads.FindBySHA1( &m_pSHA1 ) != NULL )
01248 {
01249 m_bDownload = TRUE;
01250 }
01251 else if ( m_bTiger && Downloads.FindByTiger( &m_pTiger ) != NULL )
01252 {
01253 m_bDownload = TRUE;
01254 }
01255 else if ( m_bED2K && Downloads.FindByED2K( &m_pED2K ) != NULL )
01256 {
01257 m_bDownload = TRUE;
01258 }
01259 }
01260 }
01261
01262 if ( pHit->m_bFiltered ) Added( pHit );
01263
01264 if ( ! m_bOneValid && ! pHit->m_bBogus && pHit->m_bMatched ) m_bOneValid = TRUE;
01265
01266 return TRUE;
01267 }
01268
01270
01271
01272 BOOL CMatchFile::Check(CQueryHit* pHit) const
01273 {
01274 for ( CQueryHit* pOld = m_pHits ; pOld ; pOld = pOld->m_pNext )
01275 {
01276 if ( pOld == pHit ) return TRUE;
01277 }
01278
01279 return FALSE;
01280 }
01281
01283
01284
01285 BOOL CMatchFile::Expand(BOOL bExpand)
01286 {
01287 if ( m_bExpanded == bExpand ) return FALSE;
01288
01289 m_pList->m_nItems -= GetItemCount();
01290 m_bExpanded = bExpand;
01291 m_pList->m_nItems += GetItemCount();
01292
01293 if ( ! m_bExpanded )
01294 {
01295 for ( CQueryHit* pHit = m_pHits ; pHit ; pHit = pHit->m_pNext )
01296 {
01297 if ( pHit->m_bSelected ) m_pList->Select( this, pHit, FALSE );
01298 }
01299 }
01300
01301 m_pList->UpdateRange( m_pList->FileToItem( this ) );
01302
01303 return TRUE;
01304 }
01305
01307
01308
01309 DWORD CMatchFile::Filter()
01310 {
01311 m_bBusy = TS_UNKNOWN;
01312 m_bPush = TS_UNKNOWN;
01313 m_bStable = TS_UNKNOWN;
01314 m_bPreview = FALSE;
01315 m_nSpeed = 0;
01316 m_nRating = 0;
01317 m_nRated = 0;
01318 m_bDRM = FALSE;
01319 m_bCollection = FALSE;
01320
01321 m_nFiltered = 0;
01322 m_nSources = 0;
01323 m_pBest = NULL;
01324
01325 for ( CQueryHit* pHit = m_pHits ; pHit ; pHit = pHit->m_pNext )
01326 {
01327 if ( m_pList->FilterHit( pHit ) )
01328 {
01329 Added( pHit );
01330 }
01331 else if ( pHit->m_bSelected )
01332 {
01333 m_pList->Select( this, pHit, FALSE );
01334 }
01335 }
01336
01337 if ( m_pBest == NULL ) return 0;
01338 if ( m_pList->m_bFilterLocal && m_bExisting ) return 0;
01339 if ( m_pList->m_bFilterDRM && m_bDRM ) return 0;
01340
01341 if ( m_nSources < m_pList->m_nFilterSources ) return 0;
01342
01343
01344 if ( m_nFiltered == 1 || ! m_bExpanded )
01345 return 1;
01346 else
01347 return m_nFiltered + 1;
01348 }
01349
01351
01352
01353 void CMatchFile::Added(CQueryHit* pHit)
01354 {
01355 m_pBest = pHit;
01356
01357 m_nFiltered ++;
01358 m_nSources += pHit->GetSources();
01359 m_nSpeed += pHit->m_nSpeed;
01360
01361 if ( m_nFiltered && m_nSpeed )
01362 m_sSpeed = Settings.SmartVolume( m_nFiltered ? m_nSpeed / m_nFiltered : 0, TRUE, TRUE );
01363 else
01364 m_sSpeed.Empty();
01365
01366 if ( pHit->GetSources() > 0 )
01367 {
01368 if ( pHit->m_bPush == TS_FALSE )
01369 m_bPush = TS_FALSE;
01370 else if ( pHit->m_bPush == TS_TRUE && m_bPush == TS_UNKNOWN )
01371 m_bPush = TS_TRUE;
01372
01373 if ( pHit->m_bBusy == TS_FALSE )
01374 m_bBusy = TS_FALSE;
01375 else if ( pHit->m_bBusy == TS_TRUE && m_bBusy == TS_UNKNOWN )
01376 m_bBusy = TS_TRUE;
01377
01378 if ( pHit->m_bStable == TS_TRUE )
01379 m_bStable = TS_TRUE;
01380 else if ( pHit->m_bStable == TS_FALSE && m_bStable == TS_UNKNOWN )
01381 m_bStable = TS_FALSE;
01382
01383 m_bPreview |= pHit->m_bPreview;
01384 }
01385
01386 m_bCollection |= ( pHit->m_bCollection && ! pHit->m_bBogus );
01387
01388 if ( pHit->m_nRating )
01389 {
01390 m_nRating += pHit->m_nRating;
01391 m_nRated ++;
01392 }
01393
01394 if ( m_nShellIndex == -1 )
01395 {
01396 LPCTSTR pszExt = _tcsrchr( pHit->m_sName, '.' );
01397 m_nShellIndex = pszExt ? ShellIcons.Get( pszExt, 16 ) : 0;
01398 }
01399
01400 BOOL bSchema;
01401
01402 if ( m_pList->m_pSchema &&
01403 ( bSchema = m_pList->m_pSchema->CheckURI( pHit->m_sSchemaURI ) || pHit->m_bSHA1 ) )
01404 {
01405 if ( m_pColumns == NULL )
01406 {
01407 m_nColumns = m_pList->m_nColumns;
01408 m_pColumns = new CString[ m_nColumns ];
01409 }
01410
01411 CSchemaMember** pMember = m_pList->m_pColumns;
01412 CString strValue;
01413
01414 for ( int nCount = 0 ; nCount < m_nColumns ; nCount ++, pMember ++ )
01415 {
01416 if ( _tcsicmp( (*pMember)->m_sName, _T("SHA1") ) == 0 )
01417 {
01418 if ( pHit->m_bSHA1 )
01419 {
01420 m_pColumns[ nCount ] = CSHA::HashToString( &m_pSHA1 );
01421 }
01422 }
01423 else if ( bSchema )
01424 {
01425 strValue = (*pMember)->GetValueFrom( pHit->m_pXML, NULL, TRUE );
01426 if ( strValue.GetLength() ) m_pColumns[ nCount ] = strValue;
01427 }
01428 }
01429 }
01430 else if ( m_pColumns != NULL )
01431 {
01432 delete [] m_pColumns;
01433 m_pColumns = NULL;
01434 m_nColumns = 0;
01435 }
01436
01437 if ( ! m_bDRM && pHit->m_pXML != NULL )
01438 {
01439 if ( pHit->m_pXML->GetAttributeValue( _T("DRM") ).GetLength() > 0 )
01440 m_bDRM = TRUE;
01441 }
01442
01443 if ( m_bDownload ) pHit->m_bDownload = TRUE;
01444 }
01445
01447
01448
01449 void CMatchFile::ClearNew()
01450 {
01451 m_bNew = FALSE;
01452 for ( CQueryHit* pHit = m_pHits ; pHit ; pHit = pHit->m_pNext )
01453 pHit->m_bNew = FALSE;
01454 }
01455
01457
01458
01459 int CMatchFile::Compare(CMatchFile* pFile) const
01460 {
01461 register int x, y;
01462
01463
01464
01465
01466
01467
01468
01469
01470 switch ( m_pList->m_nSortColumn )
01471 {
01472 case MATCH_COL_NAME:
01473 x = _tcsicoll( m_pHits->m_sName, pFile->m_pHits->m_sName );
01474 if ( ! x ) return 0;
01475 return x > 0 ? 1 : -1;
01476
01477 case MATCH_COL_TYPE:
01478 {
01479 LPCTSTR pszType1 = _tcsrchr( m_pHits->m_sName, '.' );
01480 LPCTSTR pszType2 = _tcsrchr( pFile->m_pHits->m_sName, '.' );
01481 if ( ! pszType1 ) return ( pszType2 ? -1 : 0 );
01482 if ( ! pszType2 ) return 1;
01483 x = _tcsicmp( pszType1, pszType2 );
01484 if ( ! x ) return 0;
01485 return x > 0 ? 1 : -1;
01486 }
01487
01488 case MATCH_COL_SIZE:
01489 return m_nSize == pFile->m_nSize ? 0 : ( m_nSize > pFile->m_nSize ? 1 : -1 );
01490
01491 case MATCH_COL_RATING:
01492 x = m_nRated ? m_nRating / m_nRated : 0;
01493 y = pFile->m_nRated ? pFile->m_nRating / pFile->m_nRated : 0;
01494 return x == y ? 0 : ( x > y ? 1 : -1 );
01495
01496 case MATCH_COL_STATUS:
01497 x = y = 0;
01498 if ( m_bPush != TS_TRUE ) x += 4;
01499 if ( m_bBusy != TS_TRUE ) x += 2;
01500 if ( m_bStable == TS_TRUE ) x ++;
01501 if ( pFile->m_bPush != TS_TRUE ) y += 4;
01502 if ( pFile->m_bBusy != TS_TRUE ) y += 2;
01503 if ( pFile->m_bStable == TS_TRUE ) y ++;
01504 return x == y ? 0 : ( x > y ? 1 : -1 );
01505
01506 case MATCH_COL_COUNT:
01507 return m_nSources == pFile->m_nSources ? 0 : ( m_nSources > pFile->m_nSources ? 1 : -1 );
01508
01509 case MATCH_COL_CLIENT:
01510 {
01511 LPCTSTR pszType1 = ( m_nFiltered == 1 ) ? (LPCTSTR)m_pHits->m_pVendor->m_sName : NULL;
01512 LPCTSTR pszType2 = ( pFile->m_nFiltered == 1 ) ? (LPCTSTR)pFile->m_pHits->m_pVendor->m_sName : NULL;
01513 if ( ! pszType1 ) return ( pszType2 ? -1 : 0 );
01514 if ( ! pszType2 ) return 1;
01515 x = _tcsicmp( pszType1, pszType2 );
01516 if ( ! x ) return 0;
01517 return x > 0 ? 1 : -1;
01518 }
01519
01520 case MATCH_COL_SPEED:
01521 x = m_nFiltered ? m_nSpeed / m_nFiltered : 0;
01522 y = pFile->m_nFiltered ? pFile->m_nSpeed / pFile->m_nFiltered : 0;
01523 return x == y ? 0 : ( x > y ? 1 : -1 );
01524
01525 default:
01526 if ( ! m_pColumns ) return ( pFile->m_pColumns ? -1 : 0 );
01527 else if ( ! pFile->m_pColumns ) return 1;
01528
01529 x = ( m_pList->m_nSortColumn - MATCH_COL_MAX >= m_nColumns );
01530 y = ( m_pList->m_nSortColumn - MATCH_COL_MAX >= pFile->m_nColumns );
01531 if ( x ) return ( y ? 0 : -1 );
01532 else if ( y ) return 1;
01533
01534 {
01535 LPCTSTR pszA = m_pColumns[ m_pList->m_nSortColumn - MATCH_COL_MAX ];
01536 LPCTSTR pszB = pFile->m_pColumns[ m_pList->m_nSortColumn - MATCH_COL_MAX ];
01537
01538 #if 0
01539 if ( *pszA && *pszB &&
01540 ( pszA[ _tcslen( pszA ) - 1 ] == 'k' || pszA[ _tcslen( pszA ) - 1 ] == '~' )
01541 &&
01542 ( pszB[ _tcslen( pszB ) - 1 ] == 'k' || pszB[ _tcslen( pszB ) - 1 ] == '~' ) )
01543 {
01544 x = CLiveList::SortProc( pszA, pszB, TRUE );
01545 }
01546 else
01547 {
01548 x = _tcsicoll( m_pColumns[ m_pList->m_nSortColumn - MATCH_COL_MAX ],
01549 pFile->m_pColumns[ m_pList->m_nSortColumn - MATCH_COL_MAX ] );
01550 }
01551 #else
01552 x = CLiveList::SortProc( pszA, pszB );
01553 #endif
01554 }
01555 if ( ! x ) return 0;
01556 return x > 0 ? 1 : -1;
01557 }
01558 }
01559
01561
01562
01563 CString CMatchFile::GetURN() const
01564 {
01565 CString strURN;
01566
01567 if ( m_bSHA1 && m_bTiger )
01568 {
01569 strURN = _T("urn:bitprint:")
01570 + CSHA::HashToString( &m_pSHA1 ) + '.'
01571 + CTigerNode::HashToString( &m_pTiger );
01572 }
01573 else if ( m_bSHA1 )
01574 {
01575 strURN = CSHA::HashToString( &m_pSHA1, TRUE );
01576 }
01577 else if ( m_bTiger )
01578 {
01579 strURN = CTigerNode::HashToString( &m_pTiger, TRUE );
01580 }
01581 else if ( m_bED2K )
01582 {
01583 strURN = CED2K::HashToString( &m_pED2K, TRUE );
01584 }
01585
01586 return strURN;
01587 }
01588
01590
01591
01592 void CMatchFile::Serialize(CArchive& ar, int nVersion)
01593 {
01594 if ( ar.IsStoring() )
01595 {
01596 ar << m_nSize;
01597 ar << m_sSize;
01598 ar << m_bSHA1;
01599 if ( m_bSHA1 ) ar.Write( &m_pSHA1, sizeof(SHA1) );
01600 ar << m_bTiger;
01601 if ( m_bTiger ) ar.Write( &m_pTiger, sizeof(TIGEROOT) );
01602 ar << m_bED2K;
01603 if ( m_bED2K ) ar.Write( &m_pED2K, sizeof(MD4) );
01604
01605 ar << m_bBusy;
01606 ar << m_bPush;
01607 ar << m_bStable;
01608 ar << m_nSpeed;
01609 ar << m_sSpeed;
01610 ar << m_bExpanded;
01611 ar << m_bExisting;
01612 ar << m_bDownload;
01613 ar << m_bOneValid;
01614
01615 if ( m_pPreview == NULL ) m_nPreview = 0;
01616 ar.WriteCount( m_nPreview );
01617 if ( m_nPreview > 0 ) ar.Write( m_pPreview, m_nPreview );
01618
01619 ar.WriteCount( m_nTotal );
01620 CPtrArray pHits;
01621
01622 CQueryHit* pHit = m_pHits;
01623 for ( ; pHit ; pHit = pHit->m_pNext )
01624 {
01625 pHits.Add( pHit );
01626 }
01627
01628 for ( int nHit = m_nTotal - 1 ; nHit >= 0 ; nHit-- )
01629 {
01630 pHit = (CQueryHit*)pHits.GetAt( nHit );
01631 pHit->Serialize( ar, nVersion );
01632 }
01633 }
01634 else
01635 {
01636 if ( nVersion >= 10 )
01637 {
01638 ar >> m_nSize;
01639 }
01640 else
01641 {
01642 DWORD nSize;
01643 ar >> nSize;
01644 m_nSize = nSize;
01645 }
01646
01647 ar >> m_sSize;
01648 ar >> m_bSHA1;
01649 if ( m_bSHA1 ) ar.Read( &m_pSHA1, sizeof(SHA1) );
01650 ar >> m_bTiger;
01651 if ( m_bTiger ) ar.Read( &m_pTiger, sizeof(TIGEROOT) );
01652 ar >> m_bED2K;
01653 if ( m_bED2K ) ar.Read( &m_pED2K, sizeof(MD4) );
01654
01655 ar >> m_bBusy;
01656 ar >> m_bPush;
01657 ar >> m_bStable;
01658 ar >> m_nSpeed;
01659 ar >> m_sSpeed;
01660 ar >> m_bExpanded;
01661 ar >> m_bExisting;
01662 ar >> m_bDownload;
01663 ar >> m_bOneValid;
01664
01665 if ( m_nPreview = ar.ReadCount() )
01666 {
01667 m_pPreview = new BYTE[ m_nPreview ];
01668 ar.Read( m_pPreview, m_nPreview );
01669 }
01670
01671 m_nTotal = ar.ReadCount();
01672
01673 for ( int nCount = m_nTotal ; nCount > 0 ; nCount-- )
01674 {
01675 CQueryHit* pNext = new CQueryHit( PROTOCOL_NULL );
01676 pNext->m_pNext = m_pHits;
01677 m_pHits = pNext;
01678 m_pHits->Serialize( ar, nVersion );
01679 }
01680 }
01681 }