00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "StdAfx.h"
00023 #include "Shareaza.h"
00024 #include "Settings.h"
00025 #include "Download.h"
00026 #include "Downloads.h"
00027 #include "DownloadSource.h"
00028 #include "DownloadTransferHTTP.h"
00029 #include "DownloadTransferFTP.h"
00030 #include "DownloadTransferED2K.h"
00031 #include "DownloadTransferBT.h"
00032 #include "FragmentedFile.h"
00033
00034 #include "Neighbours.h"
00035 #include "QueryHit.h"
00036 #include "Network.h"
00037 #include "VendorCache.h"
00038 #include "EDClients.h"
00039 #include "EDClient.h"
00040 #include "EDPacket.h"
00041 #include "SourceURL.h"
00042 #include "SHA.h"
00043
00044 #ifdef _DEBUG
00045 #undef THIS_FILE
00046 static char THIS_FILE[]=__FILE__;
00047 #define new DEBUG_NEW
00048 #endif
00049
00050
00052
00053
00054 CDownloadSource::CDownloadSource(CDownload* pDownload)
00055 : m_oAvailable( pDownload->m_nSize ), m_oPastFragments( pDownload->m_nSize )
00056 {
00057 Construct( pDownload );
00058 }
00059
00060 void CDownloadSource::Construct(CDownload* pDownload)
00061 {
00062 ASSERT( pDownload != NULL );
00063
00064 m_pDownload = pDownload;
00065 m_pPrev = NULL;
00066 m_pNext = NULL;
00067 m_pTransfer = NULL;
00068 m_bSelected = FALSE;
00069
00070 m_nProtocol = PROTOCOL_NULL;
00071 m_bGUID = FALSE;
00072 m_nPort = 0;
00073 m_nServerPort = 0;
00074
00075 m_nIndex = 0;
00076 m_bHashAuth = FALSE;
00077 m_bSHA1 = FALSE;
00078 m_bTiger = FALSE;
00079 m_bED2K = FALSE;
00080
00081 m_nSpeed = 0;
00082 m_bPushOnly = FALSE;
00083 m_bCloseConn = FALSE;
00084 m_bReadContent = FALSE;
00085 m_nGnutella = 0;
00086 m_bClientExtended=FALSE;
00087
00088 m_nSortOrder = 0xFFFFFFFF;
00089 m_nColour = -1;
00090 m_tAttempt = 0;
00091 m_nFailures = 0;
00092
00093 SYSTEMTIME pTime;
00094 GetSystemTime( &pTime );
00095 SystemTimeToFileTime( &pTime, &m_tLastSeen );
00096 }
00097
00098 CDownloadSource::~CDownloadSource()
00099 {
00100
00101
00102 }
00103
00105
00106
00107 CDownloadSource::CDownloadSource(CDownload* pDownload, CQueryHit* pHit)
00108 : m_oAvailable( pDownload->m_nSize ), m_oPastFragments( pDownload->m_nSize )
00109 {
00110 Construct( pDownload );
00111
00112 m_bPushOnly = pHit->m_bPush == TS_TRUE ? TRUE : FALSE;
00113
00114 m_sURL = pHit->m_sURL;
00115 m_pAddress = pHit->m_pAddress;
00116 m_nPort = pHit->m_nPort;
00117 m_nSpeed = pHit->m_bMeasured == TS_TRUE ? ( pHit->m_nSpeed * 128 ) : 0;
00118 m_sServer = pHit->m_pVendor->m_sName;
00119 m_sName = pHit->m_sName;
00120 m_nIndex = pHit->m_nIndex;
00121 m_bSHA1 = pHit->m_bSHA1;
00122 m_bTiger = pHit->m_bTiger;
00123 m_bED2K = pHit->m_bED2K;
00124
00125 if ( pHit->m_nProtocol == PROTOCOL_G1 || pHit->m_nProtocol == PROTOCOL_G2 )
00126 {
00127 m_bGUID = TRUE;
00128 m_pGUID = pHit->m_pClientID;
00129 m_bClientExtended = TRUE;
00130 }
00131 else if ( pHit->m_nProtocol == PROTOCOL_ED2K )
00132 {
00133 if ( ( m_sURL.Right( 3 ) == _T("/0/") ) && ( pDownload->m_nSize ) )
00134 {
00135 CString strTemp = m_sURL.Left( m_sURL.GetLength() - 2 );
00136 m_sURL.Format( _T("%s%I64i/"), strTemp, pDownload->m_nSize );
00137 }
00138 }
00139
00140 ResolveURL();
00141 }
00142
00144
00145
00146 CDownloadSource::CDownloadSource(CDownload* pDownload, DWORD nClientID, WORD nClientPort, DWORD nServerIP, WORD nServerPort, GGUID* pGUID)
00147 : m_oAvailable( pDownload->m_nSize ), m_oPastFragments( pDownload->m_nSize )
00148 {
00149 Construct( pDownload );
00150
00151 if ( m_bPushOnly = CEDPacket::IsLowID( nClientID ) )
00152 {
00153 m_sURL.Format( _T("ed2kftp://%lu@%s:%i/%s/%I64i/"),
00154 nClientID,
00155 (LPCTSTR)CString( inet_ntoa( (IN_ADDR&)nServerIP ) ), nServerPort,
00156 (LPCTSTR)CED2K::HashToString( &m_pDownload->m_pED2K ), m_pDownload->m_nSize );
00157 }
00158 else
00159 {
00160 m_sURL.Format( _T("ed2kftp://%s:%i/%s/%I64i/"),
00161 (LPCTSTR)CString( inet_ntoa( (IN_ADDR&)nClientID ) ), nClientPort,
00162 (LPCTSTR)CED2K::HashToString( &m_pDownload->m_pED2K ), m_pDownload->m_nSize );
00163 }
00164
00165 if ( m_bGUID = ( pGUID != NULL ) ) m_pGUID = *pGUID;
00166
00167 m_bED2K = TRUE;
00168 m_sServer = _T("eDonkey2000");
00169
00170 ResolveURL();
00171 }
00172
00174
00175
00176 CDownloadSource::CDownloadSource(CDownload* pDownload, SHA1* pGUID, IN_ADDR* pAddress, WORD nPort)
00177 : m_oAvailable( pDownload->m_nSize ), m_oPastFragments( pDownload->m_nSize )
00178 {
00179 Construct( pDownload );
00180
00181 if ( pGUID != NULL )
00182 {
00183 m_sURL.Format( _T("btc://%s:%i/%s/%s/"),
00184 (LPCTSTR)CString( inet_ntoa( *pAddress ) ), nPort,
00185 (LPCTSTR)CSHA::HashToString( pGUID ),
00186 (LPCTSTR)CSHA::HashToString( &pDownload->m_pBTH ) );
00187 }
00188 else
00189 {
00190 m_sURL.Format( _T("btc://%s:%i//%s/"),
00191 (LPCTSTR)CString( inet_ntoa( *pAddress ) ), nPort,
00192 (LPCTSTR)CSHA::HashToString( &pDownload->m_pBTH ) );
00193 }
00194
00195 m_bGUID = pGUID != NULL;
00196 m_sServer = _T("BitTorrent");
00197
00198 ResolveURL();
00199 }
00200
00202
00203
00204 CDownloadSource::CDownloadSource(CDownload* pDownload, LPCTSTR pszURL, BOOL bSHA1, BOOL bHashAuth, FILETIME* pLastSeen)
00205 : m_oAvailable( pDownload->m_nSize ), m_oPastFragments( pDownload->m_nSize )
00206 {
00207 Construct( pDownload );
00208
00209 ASSERT( pszURL != NULL );
00210 m_sURL = pszURL;
00211
00212 if ( ! ResolveURL() ) return;
00213
00214
00215 m_bHashAuth = bHashAuth;
00216
00217 if ( pLastSeen != NULL )
00218 {
00219 FILETIME tNow = m_tLastSeen;
00220 (LONGLONG&)tNow += 10000000;
00221 if ( CompareFileTime( pLastSeen, &tNow ) <= 0 ) m_tLastSeen = *pLastSeen;
00222 }
00223 }
00224
00226
00227
00228 BOOL CDownloadSource::ResolveURL()
00229 {
00230 CSourceURL pURL;
00231
00232 if ( ! pURL.Parse( m_sURL ) )
00233 {
00234 theApp.Message( MSG_ERROR, _T("Unable to parse URL: %s"), (LPCTSTR)m_sURL );
00235 return FALSE;
00236 }
00237
00238 m_bSHA1 |= pURL.m_bSHA1;
00239 m_bED2K |= pURL.m_bED2K;
00240
00241 m_nProtocol = pURL.m_nProtocol;
00242 m_pAddress = pURL.m_pAddress;
00243 m_nPort = pURL.m_nPort;
00244
00245 if ( m_nProtocol == PROTOCOL_ED2K )
00246 {
00247 m_pServerAddress = pURL.m_pServerAddress;
00248 m_nServerPort = pURL.m_nServerPort;
00249 if ( m_nServerPort ) m_bPushOnly = TRUE;
00250 }
00251 else if ( m_nProtocol == PROTOCOL_BT )
00252 {
00253 if ( m_bGUID = pURL.m_bBTC ) CopyMemory( &m_pGUID, &pURL.m_pBTC, 16 );
00254 }
00255
00256 return TRUE;
00257 }
00258
00260
00261
00262 void CDownloadSource::Serialize(CArchive& ar, int nVersion)
00263 {
00264 if ( ar.IsStoring() )
00265 {
00266 ar << m_sURL;
00267 ar << m_nProtocol;
00268
00269 ar << m_bGUID;
00270 if ( m_bGUID ) ar.Write( &m_pGUID, sizeof(GGUID) );
00271
00272 ar << m_nPort;
00273 if ( m_nPort ) ar.Write( &m_pAddress, sizeof(m_pAddress) );
00274 ar << m_nServerPort;
00275 if ( m_nServerPort ) ar.Write( &m_pServerAddress, sizeof(m_pServerAddress) );
00276
00277 ar << m_sName;
00278 ar << m_nIndex;
00279 ar << m_bHashAuth;
00280 ar << m_bSHA1;
00281 ar << m_bTiger;
00282 ar << m_bED2K;
00283
00284 ar << m_sServer;
00285 ar << m_sNick;
00286 ar << m_nSpeed;
00287 ar << m_bPushOnly;
00288 ar << m_bCloseConn;
00289 ar << m_bReadContent;
00290 ar.Write( &m_tLastSeen, sizeof(FILETIME) );
00291
00292 SerializeOut2( ar, m_oPastFragments );
00293 }
00294 else if ( nVersion >= 21 )
00295 {
00296 ar >> m_sURL;
00297 ar >> m_nProtocol;
00298
00299 ar >> m_bGUID;
00300 if ( m_bGUID ) ar.Read( &m_pGUID, sizeof(GGUID) );
00301
00302 ar >> m_nPort;
00303 if ( m_nPort ) ar.Read( &m_pAddress, sizeof(m_pAddress) );
00304 ar >> m_nServerPort;
00305 if ( m_nServerPort ) ar.Read( &m_pServerAddress, sizeof(m_pServerAddress) );
00306
00307 ar >> m_sName;
00308 ar >> m_nIndex;
00309 ar >> m_bHashAuth;
00310 ar >> m_bSHA1;
00311 ar >> m_bTiger;
00312 ar >> m_bED2K;
00313
00314 ar >> m_sServer;
00315 if ( nVersion >= 24 ) ar >> m_sNick;
00316 ar >> m_nSpeed;
00317 ar >> m_bPushOnly;
00318 ar >> m_bCloseConn;
00319 ar >> m_bReadContent;
00320 ar.Read( &m_tLastSeen, sizeof(FILETIME) );
00321
00322 SerializeIn2( ar, m_oPastFragments, nVersion );
00323
00324
00325 if ( _tcsncmp( m_sServer, _T("Shareaza"), 8 ) == 0 )
00326 m_bClientExtended = TRUE;
00327 if ( _tcsncmp( m_sServer, _T("RAZA"), 4 ) == 0 )
00328 m_bClientExtended = TRUE;
00329
00330 }
00331 else
00332 {
00333 DWORD nIndex;
00334 ar.Read( &m_pAddress, sizeof(m_pAddress) );
00335 ar >> m_nPort;
00336 ar >> m_nSpeed;
00337 ar >> nIndex;
00338 ar >> m_sName;
00339 if ( nVersion >= 4 ) ar >> m_sURL;
00340 if ( nVersion >= 21 ) ar >> m_nProtocol;
00341 ar >> m_bSHA1;
00342 if ( nVersion >= 13 ) ar >> m_bTiger;
00343 if ( nVersion >= 13 ) ar >> m_bED2K;
00344 if ( nVersion >= 10 ) ar >> m_bHashAuth;
00345
00346 if ( nVersion == 8 )
00347 {
00348 DWORD nV;
00349 ar >> nV;
00350 m_sServer.Format( _T("%c%c%c%c"), nV & 0xFF, ( nV >> 8 ) & 0xFF, ( nV >> 16 ) & 0xFF, nV >> 24 );
00351 }
00352 else if ( nVersion >= 9 )
00353 {
00354 ar >> m_sServer;
00355 }
00356
00357 ar >> m_bPushOnly;
00358 ar >> m_bReadContent;
00359 if ( nVersion >= 7 ) ar >> m_bCloseConn;
00360 if ( nVersion >= 12 ) ar.Read( &m_tLastSeen, sizeof(FILETIME) );
00361
00362 ar.Read( &m_pGUID, sizeof(GGUID) );
00363 ar.Read( &m_pGUID, sizeof(GGUID) );
00364 m_bGUID = m_pGUID != (GGUID&)GUID_NULL;
00365
00366 SerializeIn2( ar, m_oPastFragments, nVersion );
00367
00368 ResolveURL();
00369 }
00370 }
00371
00373
00374
00375 CDownloadTransfer* CDownloadSource::CreateTransfer()
00376 {
00377 ASSERT( m_pTransfer == NULL );
00378
00379 switch ( m_nProtocol )
00380 {
00381 case PROTOCOL_G1: return ( m_pTransfer = new CDownloadTransferHTTP( this ) );
00382 case PROTOCOL_G2: return ( m_pTransfer = new CDownloadTransferHTTP( this ) );
00383 case PROTOCOL_ED2K: return ( m_pTransfer = new CDownloadTransferED2K( this ) );
00384 case PROTOCOL_HTTP: return ( m_pTransfer = new CDownloadTransferHTTP( this ) );
00385 case PROTOCOL_FTP: return ( m_pTransfer = new CDownloadTransferFTP( this ) );
00386 case PROTOCOL_BT: return ( m_pTransfer = new CDownloadTransferBT( this, NULL ) );
00387 default: theApp.Message( MSG_ERROR, _T("Invalid protocol in CDownloadSource::CreateTransfer()") );
00388 return ( NULL );
00389 }
00390 }
00391
00393
00394
00395 void CDownloadSource::Remove(BOOL bCloseTransfer, BOOL bBan)
00396 {
00397 if ( m_pTransfer != NULL )
00398 {
00399 if ( bCloseTransfer )
00400 {
00401 m_pTransfer->Close( TS_TRUE );
00402 ASSERT( m_pTransfer == NULL );
00403 }
00404 else
00405 {
00406 m_pTransfer->m_pSource = NULL;
00407 m_pTransfer = NULL;
00408 }
00409 }
00410
00411 m_pDownload->RemoveSource( this, bBan );
00412 }
00413
00415
00416
00417 void CDownloadSource::OnFailure(BOOL bNondestructive)
00418 {
00419 if ( m_pTransfer != NULL )
00420 {
00421 m_pTransfer->SetState(dtsNull);
00422 m_pTransfer->m_pSource = NULL;
00423 m_pTransfer = NULL;
00424 }
00425
00426 DWORD nDelay = Settings.Downloads.RetryDelay * (DWORD)pow( 2, m_nFailures );
00427
00428 if ( m_nFailures < 20 )
00429 {
00430 if ( nDelay > 3600000 ) nDelay = 3600000;
00431 }
00432 else
00433 {
00434 if ( nDelay > 86400000 ) nDelay = 86400000;
00435 }
00436
00437 nDelay += GetTickCount();
00438
00439 int nMaxFailures = ( m_bReadContent ? 40 : 3 );
00440 if ( nMaxFailures < 20 && m_pDownload->GetSourceCount() > 20 ) nMaxFailures = 0;
00441
00442 m_pDownload->SetModified();
00443
00444 if ( bNondestructive || ( ++m_nFailures < nMaxFailures ) )
00445 {
00446 m_tAttempt = max( m_tAttempt, nDelay );
00447 }
00448 else
00449 {
00450 if ( Settings.Downloads.NeverDrop )
00451 {
00452 m_tAttempt = nDelay;
00453 }
00454 else
00455 {
00456 m_pDownload->RemoveSource( this, TRUE );
00457 }
00458 }
00459 }
00460
00462
00463
00464 void CDownloadSource::OnResume()
00465 {
00466 m_tAttempt = 0;
00467 }
00468
00470
00471
00472 void CDownloadSource::SetValid()
00473 {
00474 m_bReadContent = TRUE;
00475 m_nFailures = 0;
00476 m_pDownload->SetModified();
00477 }
00478
00479 void CDownloadSource::SetLastSeen()
00480 {
00481 SYSTEMTIME pTime;
00482 GetSystemTime( &pTime );
00483 SystemTimeToFileTime( &pTime, &m_tLastSeen );
00484 m_pDownload->SetModified();
00485 }
00486
00487 void CDownloadSource::SetGnutella(int nGnutella)
00488 {
00489 m_nGnutella |= nGnutella;
00490 m_pDownload->SetModified();
00491 }
00492
00494
00495
00496 BOOL CDownloadSource::CheckHash(const SHA1* pSHA1)
00497 {
00498 if ( m_pDownload->m_bSHA1 && ! m_bHashAuth )
00499 {
00500 if ( m_pDownload->m_pSHA1 != *pSHA1 ) return FALSE;
00501 }
00502 else
00503 {
00504 if ( m_pDownload->m_pTorrent.IsAvailable() ) return TRUE;
00505
00506 m_pDownload->m_bSHA1 = TRUE;
00507 m_pDownload->m_pSHA1 = *pSHA1;
00508 }
00509
00510 m_bSHA1 = TRUE;
00511 m_pDownload->SetModified();
00512
00513 return TRUE;
00514 }
00515
00516 BOOL CDownloadSource::CheckHash(const TIGEROOT* pTiger)
00517 {
00518 if ( m_pDownload->m_bTiger && ! m_bHashAuth )
00519 {
00520 if ( m_pDownload->m_pTiger != *pTiger ) return FALSE;
00521 }
00522 else
00523 {
00524 if ( m_pDownload->m_pTorrent.IsAvailable() ) return TRUE;
00525
00526 m_pDownload->m_bTiger = TRUE;
00527 m_pDownload->m_pTiger = *pTiger;
00528 }
00529
00530 m_bTiger = TRUE;
00531 m_pDownload->SetModified();
00532
00533 return TRUE;
00534 }
00535
00536 BOOL CDownloadSource::CheckHash(const MD4* pED2K)
00537 {
00538 if ( m_pDownload->m_bED2K && ! m_bHashAuth )
00539 {
00540 if ( memcmp( &m_pDownload->m_pED2K, pED2K, sizeof(MD4) ) ) return FALSE;
00541 }
00542 else
00543 {
00544 if ( m_pDownload->m_pTorrent.IsAvailable() ) return TRUE;
00545
00546 m_pDownload->m_bED2K = TRUE;
00547 m_pDownload->m_pED2K = *pED2K;
00548 }
00549
00550 m_bED2K = TRUE;
00551 m_pDownload->SetModified();
00552
00553 return TRUE;
00554 }
00555
00557
00558
00559 BOOL CDownloadSource::PushRequest()
00560 {
00561 if ( m_nProtocol == PROTOCOL_BT )
00562 {
00563 return FALSE;
00564 }
00565 else if ( m_nProtocol == PROTOCOL_ED2K )
00566 {
00567 if ( m_nServerPort == 0 ) return FALSE;
00568 if ( EDClients.IsFull() ) return TRUE;
00569
00570 CEDClient* pClient = EDClients.Connect( m_pAddress.S_un.S_addr, m_nPort,
00571 &m_pServerAddress, m_nServerPort, m_bGUID ? &m_pGUID : NULL );
00572
00573 if ( pClient != NULL && pClient->m_bConnected )
00574 {
00575 pClient->SeekNewDownload();
00576 return TRUE;
00577 }
00578
00579 if ( Neighbours.PushDonkey( m_pAddress.S_un.S_addr, &m_pServerAddress, m_nServerPort ) )
00580 {
00581 theApp.Message( MSG_DEFAULT, IDS_DOWNLOAD_PUSH_SENT, (LPCTSTR)m_pDownload->m_sRemoteName );
00582 m_tAttempt = GetTickCount() + Settings.Downloads.PushTimeout;
00583 return TRUE;
00584 }
00585 }
00586 else
00587 {
00588 if ( ! m_bGUID ) return FALSE;
00589
00590 if ( Network.SendPush( &m_pGUID, m_nIndex ) )
00591 {
00592 theApp.Message( MSG_DEFAULT, IDS_DOWNLOAD_PUSH_SENT, (LPCTSTR)m_pDownload->m_sRemoteName );
00593 m_tAttempt = GetTickCount() + Settings.Downloads.PushTimeout;
00594 return TRUE;
00595 }
00596 }
00597
00598 return FALSE;
00599 }
00600
00601 BOOL CDownloadSource::CheckPush(GGUID* pClientID)
00602 {
00603 return m_bGUID && ( m_pGUID == *pClientID );
00604 }
00605
00606 BOOL CDownloadSource::CheckDonkey(CEDClient* pClient)
00607 {
00608 if ( m_nProtocol != PROTOCOL_ED2K ) return FALSE;
00609
00610 if ( m_bGUID && pClient->m_bGUID ) return m_pGUID == pClient->m_pGUID;
00611
00612 if ( m_bPushOnly )
00613 {
00614 return m_pServerAddress.S_un.S_addr == pClient->m_pServer.sin_addr.S_un.S_addr &&
00615 m_pAddress.S_un.S_addr == pClient->m_nClientID;
00616 }
00617 else
00618 {
00619 return m_pAddress.S_un.S_addr == pClient->m_pHost.sin_addr.S_un.S_addr;
00620 }
00621 }
00622
00624
00625
00626 void CDownloadSource::AddFragment(QWORD nOffset, QWORD nLength, BOOL bMerge)
00627 {
00628 m_bReadContent = TRUE;
00629 m_oPastFragments.insert( FF::SimpleFragment( nOffset, nOffset + nLength ) );
00630 m_pDownload->SetModified();
00631 }
00632
00634
00635
00636 void CDownloadSource::SetAvailableRanges(LPCTSTR pszRanges)
00637 {
00638 m_oAvailable.clear();
00639
00640 if ( ! pszRanges || ! *pszRanges ) return;
00641 if ( _tcsnicmp( pszRanges, _T("bytes"), 5 ) ) return;
00642
00643 CString strRanges( pszRanges + 6 );
00644
00645 for ( strRanges += ',' ; strRanges.GetLength() ; )
00646 {
00647 CString strRange = strRanges.SpanExcluding( _T(", \t") );
00648 strRanges = strRanges.Mid( strRange.GetLength() + 1 );
00649
00650 strRange.TrimLeft();
00651 strRange.TrimRight();
00652 if ( strRange.Find( '-' ) < 0 ) continue;
00653
00654 QWORD nFirst = 0, nLast = 0;
00655
00656
00657 if ( _stscanf( strRange, _T("%I64i-%I64i"), &nFirst, &nLast ) == 2 && nLast > nFirst )
00658 {
00659 if( nFirst < m_oAvailable.limit() )
00660 {
00661
00662
00663 m_oAvailable.insert( FF::SimpleFragment( nFirst, min( nLast + 1, m_oAvailable.limit() ) ) );
00664 }
00665 }
00666 }
00667
00668 m_pDownload->SetModified();
00669 }
00670
00672
00673
00674 BOOL CDownloadSource::HasUsefulRanges() const
00675 {
00676 if ( m_oAvailable.empty() )
00677 {
00678 return m_pDownload->IsRangeUseful( 0, m_pDownload->m_nSize );
00679 }
00680 return m_pDownload->AreRangesUseful( m_oAvailable );
00681 }
00682
00684
00685
00686 BOOL CDownloadSource::TouchedRange(QWORD nOffset, QWORD nLength) const
00687 {
00688 if ( m_pTransfer != NULL && m_pTransfer->m_nState == dtsDownloading )
00689 {
00690 if ( m_pTransfer->m_nOffset + m_pTransfer->m_nLength > nOffset &&
00691 m_pTransfer->m_nOffset < nOffset + nLength )
00692 {
00693 return TRUE;
00694 }
00695 }
00696
00697 return overlaps( m_oPastFragments,
00698 FF::SimpleFragment( nOffset, nOffset + nLength ) );
00699 }
00700
00702
00703
00704 int CDownloadSource::GetColour()
00705 {
00706 if ( m_nColour >= 0 ) return m_nColour;
00707 m_nColour = m_pDownload->GetSourceColour();
00708 return m_nColour;
00709 }