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

MatchObjects.cpp

Go to the documentation of this file.
00001 //
00002 // MatchObjects.cpp
00003 //
00004 //      Date:                   "$Date: 2005/10/15 10:18:04 $"
00005 //      Revision:               "$Revision: 1.19 $"
00006 //  Last change by:     "$Author: mogthecat $"
00007 //
00008 // Copyright (c) Shareaza Development Team, 2002-2005.
00009 // This file is part of SHAREAZA (www.shareaza.com)
00010 //
00011 // Shareaza is free software; you can redistribute it
00012 // and/or modify it under the terms of the GNU General Public License
00013 // as published by the Free Software Foundation; either version 2 of
00014 // the License, or (at your option) any later version.
00015 //
00016 // Shareaza is distributed in the hope that it will be useful,
00017 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00018 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019 // GNU General Public License for more details.
00020 //
00021 // You should have received a copy of the GNU General Public License
00022 // along with Shareaza; if not, write to the Free Software
00023 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
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 // CMatchList construction
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 // CMatchList add hits
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 // CMatchList insert to a sorted array
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 // CMatchList searching
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 // CMatchList clear
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 // CMatchList selection
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 // CMatchList filter
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 // CMatchList hit filtering
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         //if ( m_bFilterPush && pHit->m_bPush == TS_TRUE && pHit->m_nProtocol != PROTOCOL_ED2K ) return FALSE;
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;                // Global adult filter
00765                 if ( m_bFilterAdult ) return FALSE;                                             // Local adult filter
00766         }
00767         
00768         return ( pHit->m_bFiltered = TRUE );
00769 }
00770 
00772 // CMatchList schema selection
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 // CMatchList sort column selection
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 // CMatchList updates
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 // CMatchList clear new
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 // CMatchList serialize
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 // CMatchFile construction
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 // CMatchFile add
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 // CMatchFile check
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 // CMatchFile expand/collapse
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 // CMatchFile filter
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;        // If we filtered all hits, don't try to display
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         // if ( m_nFiltered < m_pList->m_nFilterSources ) return 0;
01343 
01344         if ( m_nFiltered == 1 || ! m_bExpanded )
01345                 return 1;
01346         else
01347                 return m_nFiltered + 1;
01348 }
01349 
01351 // CMatchFile averaging
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 // CMatchFile clear new
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 // CMatchFile compare (for sort)
01458 
01459 int CMatchFile::Compare(CMatchFile* pFile) const
01460 {
01461         register int x, y;
01462         
01463         /*
01464         if ( m_bCollection != pFile->m_bCollection )
01465         {
01466                 return m_bCollection ? -m_pList->m_bSortDir : m_pList->m_bSortDir;
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 // CMatchFile URN
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 // CMatchFile serialize
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 }

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