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 "Downloads.h"
00026 #include "DownloadWithSources.h"
00027 #include "DownloadSource.h"
00028 #include "Network.h"
00029 #include "Neighbours.h"
00030 #include "Transfer.h"
00031 #include "QueryHit.h"
00032 #include "SourceURL.h"
00033 #include "Schema.h"
00034 #include "SchemaCache.h"
00035 #include "XML.h"
00036 #include "SHA.h"
00037 #include "MD4.h"
00038 #include "TigerTree.h"
00039
00040 #ifdef _DEBUG
00041 #undef THIS_FILE
00042 static char THIS_FILE[]=__FILE__;
00043 #define new DEBUG_NEW
00044 #endif
00045
00046
00048
00049
00050 CDownloadWithSources::CDownloadWithSources()
00051 {
00052 m_pSourceFirst = NULL;
00053 m_pSourceLast = NULL;
00054 m_nSourceCount = 0;
00055 m_pXML = NULL;
00056 }
00057
00058 CDownloadWithSources::~CDownloadWithSources()
00059 {
00060 ClearSources();
00061 if ( m_pXML != NULL ) delete m_pXML;
00062 }
00063
00065
00066
00067 int CDownloadWithSources::GetSourceCount(BOOL bNoPush, BOOL bSane) const
00068 {
00069 if ( ! bNoPush && ! bSane ) return m_nSourceCount;
00070
00071 DWORD tNow = GetTickCount();
00072 int nCount = 0;
00073
00074 for ( CDownloadSource* pSource = m_pSourceFirst ; pSource ; pSource = pSource->m_pNext )
00075 {
00076 if ( ! bNoPush || ! pSource->m_bPushOnly )
00077 {
00078 if ( ! bSane ||
00079 pSource->m_tAttempt < tNow ||
00080 pSource->m_tAttempt - tNow <= 900000 )
00081 {
00082 nCount++;
00083 }
00084 }
00085 }
00086
00087 return nCount;
00088 }
00089
00090
00091 int CDownloadWithSources::GetBTSourceCount(BOOL bNoPush) const
00092 {
00093 DWORD tNow = GetTickCount();
00094 int nCount = 0;
00095
00096 for ( CDownloadSource* pSource = m_pSourceFirst ; pSource ; pSource = pSource->m_pNext )
00097 {
00098 if ( ( pSource->m_nProtocol == PROTOCOL_BT ) &&
00099 ( pSource->m_tAttempt < tNow || pSource->m_tAttempt - tNow <= 900000 ) &&
00100 ( ! pSource->m_bPushOnly || ! bNoPush ) )
00101 {
00102 nCount++;
00103 }
00104 }
00105
00106
00107
00108
00109
00110 return nCount;
00111 }
00112
00113 int CDownloadWithSources::GetED2KCompleteSourceCount() const
00114 {
00115
00116 DWORD tNow = GetTickCount();
00117 int nCount = 0;
00118
00119 for ( CDownloadSource* pSource = m_pSourceFirst ; pSource ; pSource = pSource->m_pNext )
00120 {
00121 if ( ( ! pSource->m_bPushOnly ) &&
00122 ( pSource->m_tAttempt < tNow || pSource->m_tAttempt - tNow <= 900000 ) &&
00123 ( pSource->m_nProtocol == PROTOCOL_ED2K ) &&
00124 ( pSource->m_oAvailable.empty() ) )
00125
00126 {
00127 nCount++;
00128 }
00129 }
00130
00131
00132
00133
00134
00135 return nCount;
00136 }
00137
00138 BOOL CDownloadWithSources::CheckSource(CDownloadSource* pCheck) const
00139 {
00140 for ( CDownloadSource* pSource = m_pSourceFirst ; pSource ; pSource = pSource->m_pNext )
00141 {
00142 if ( pSource == pCheck ) return TRUE;
00143 }
00144
00145 return FALSE;
00146 }
00147
00149
00150
00151 void CDownloadWithSources::ClearSources()
00152 {
00153 for ( CDownloadSource* pSource = GetFirstSource() ; pSource ; )
00154 {
00155 CDownloadSource* pNext = pSource->m_pNext;
00156 delete pSource;
00157 pSource = pNext;
00158 }
00159
00160 m_pSourceFirst = m_pSourceLast = NULL;
00161 m_nSourceCount = 0;
00162
00163 SetModified();
00164 }
00165
00167
00168
00169 BOOL CDownloadWithSources::AddSourceHit(CQueryHit* pHit, BOOL bForce)
00170 {
00171 BOOL bHash = FALSE;
00172
00173 if ( ! bForce )
00174 {
00175 if ( m_bSHA1 && pHit->m_bSHA1 )
00176 {
00177 if ( m_pSHA1 != pHit->m_pSHA1 ) return FALSE;
00178 bHash = TRUE;
00179 }
00180 else if ( m_bTiger && pHit->m_bTiger )
00181 {
00182 if ( m_pTiger != pHit->m_pTiger ) return FALSE;
00183 bHash = TRUE;
00184 }
00185 if ( m_bED2K && pHit->m_bED2K )
00186 {
00187 if ( m_pED2K != pHit->m_pED2K ) return FALSE;
00188 bHash = TRUE;
00189 }
00190 if ( m_bBTH && pHit->m_bBTH )
00191 {
00192 if ( m_pBTH != pHit->m_pBTH ) return FALSE;
00193 bHash = TRUE;
00194 }
00195 }
00196
00197 if ( ! bHash && ! bForce )
00198 {
00199 if ( Settings.General.HashIntegrity ) return FALSE;
00200
00201 if ( m_sRemoteName.IsEmpty() || pHit->m_sName.IsEmpty() ) return FALSE;
00202 if ( m_nSize == SIZE_UNKNOWN || ! pHit->m_bSize ) return FALSE;
00203
00204 if ( m_nSize != pHit->m_nSize ) return FALSE;
00205 if ( m_sRemoteName.CompareNoCase( pHit->m_sName ) ) return FALSE;
00206 }
00207
00208 if ( ! m_bSHA1 && pHit->m_bSHA1 )
00209 {
00210 m_bSHA1 = TRUE;
00211 m_pSHA1 = pHit->m_pSHA1;
00212 }
00213 if ( ! m_bTiger && pHit->m_bTiger )
00214 {
00215 m_bTiger = TRUE;
00216 m_pTiger = pHit->m_pTiger;
00217 }
00218 if ( ! m_bED2K && pHit->m_bED2K )
00219 {
00220 m_bED2K = TRUE;
00221 m_pED2K = pHit->m_pED2K;
00222 }
00223
00224 if ( m_nSize == SIZE_UNKNOWN && pHit->m_bSize )
00225 {
00226 m_nSize = pHit->m_nSize;
00227 }
00228
00229 if ( m_sRemoteName.IsEmpty() && pHit->m_sName.GetLength() )
00230 {
00231 m_sRemoteName = pHit->m_sName;
00232 }
00233
00234 if ( Settings.Downloads.Metadata && m_pXML == NULL )
00235 {
00236 if ( pHit->m_pXML != NULL && pHit->m_sSchemaPlural.GetLength() )
00237 {
00238 m_pXML = new CXMLElement( NULL, pHit->m_sSchemaPlural );
00239 m_pXML->AddAttribute( _T("xmlns:xsi"), CXMLAttribute::xmlnsInstance );
00240 m_pXML->AddAttribute( CXMLAttribute::schemaName, pHit->m_sSchemaURI );
00241 m_pXML->AddElement( pHit->m_pXML->Clone() );
00242
00243 if ( CSchema* pSchema = SchemaCache.Get( pHit->m_sSchemaURI ) )
00244 {
00245 pSchema->Validate( m_pXML, TRUE );
00246 }
00247 }
00248 }
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259 if ( pHit->m_sURL.IsEmpty() ) return TRUE;
00260
00261 return AddSourceInternal( new CDownloadSource( (CDownload*)this, pHit ) );
00262 }
00263
00265
00266
00267 BOOL CDownloadWithSources::AddSourceED2K(DWORD nClientID, WORD nClientPort, DWORD nServerIP, WORD nServerPort, GGUID* pGUID)
00268 {
00269 return AddSourceInternal( new CDownloadSource( (CDownload*)this, nClientID, nClientPort, nServerIP, nServerPort, pGUID ) );
00270 }
00271
00272 BOOL CDownloadWithSources::AddSourceBT(SHA1* pGUID, IN_ADDR* pAddress, WORD nPort)
00273 {
00274
00275 if ( Network.IsFirewalledAddress( pAddress, Settings.Connection.IgnoreOwnIP ) )
00276 return FALSE;
00277
00278
00279 if ( ( Settings.Connection.IgnoreOwnIP ) && ( pAddress->S_un.S_addr == Network.m_pHost.sin_addr.S_un.S_addr ) )
00280 return FALSE;
00281
00282 return AddSourceInternal( new CDownloadSource( (CDownload*)this, pGUID, pAddress, nPort ) );
00283 }
00284
00286
00287
00288 BOOL CDownloadWithSources::AddSourceURL(LPCTSTR pszURL, BOOL bURN, FILETIME* pLastSeen)
00289 {
00290 if ( pszURL == NULL ) return FALSE;
00291 if ( *pszURL == 0 ) return FALSE;
00292
00293 BOOL bHashAuth = FALSE;
00294 CSourceURL pURL;
00295
00296 if ( *pszURL == '@' )
00297 {
00298 bHashAuth = TRUE;
00299 pszURL++;
00300 }
00301
00302 if ( ! pURL.Parse( pszURL ) ) return FALSE;
00303
00304 if ( bURN )
00305 {
00306 if ( pURL.m_pAddress.S_un.S_addr == Network.m_pHost.sin_addr.S_un.S_addr ) return FALSE;
00307 if ( Network.IsFirewalledAddress( &pURL.m_pAddress, TRUE ) ) return FALSE;
00308 }
00309
00310 if ( m_pFailedSources.Find( pszURL ) != NULL ) return FALSE;
00311
00312 if ( pURL.m_bSHA1 && m_bSHA1 )
00313 {
00314 if ( m_pSHA1 != pURL.m_pSHA1 ) return FALSE;
00315 }
00316
00317 if ( m_sRemoteName.IsEmpty() && _tcslen( pszURL ) > 9 )
00318 {
00319 m_sRemoteName = &pszURL[8];
00320
00321 int nPos = m_sRemoteName.ReverseFind( '/' );
00322
00323 if ( nPos >= 0 )
00324 {
00325 m_sRemoteName = m_sRemoteName.Mid( nPos + 1 ).SpanExcluding( _T("?") );
00326 m_sRemoteName = CTransfer::URLDecode( m_sRemoteName );
00327 }
00328 else
00329 {
00330 m_sRemoteName.Empty();
00331 }
00332
00333 if ( m_sRemoteName.IsEmpty() ) m_sRemoteName = _T("default.htm");
00334 }
00335
00336 return AddSourceInternal( new CDownloadSource( (CDownload*)this, pszURL, bURN, bHashAuth, pLastSeen ) );
00337 }
00338
00340
00341
00342 int CDownloadWithSources::AddSourceURLs(LPCTSTR pszURLs, BOOL bURN)
00343 {
00344 CString strURLs( pszURLs );
00345 BOOL bQuote = FALSE;
00346
00347 for ( int nScan = 0 ; nScan < strURLs.GetLength() ; nScan++ )
00348 {
00349 if ( strURLs[ nScan ] == '\"' )
00350 {
00351 bQuote = ! bQuote;
00352 strURLs.SetAt( nScan, ' ' );
00353 }
00354 else if ( strURLs[ nScan ] == ',' && bQuote )
00355 {
00356 strURLs.SetAt( nScan, '`' );
00357 }
00358 }
00359
00360 strURLs += ',';
00361
00362 int nCount = 0;
00363 for ( ; ; )
00364 {
00365 int nPos = strURLs.Find( ',' );
00366 if ( nPos < 0 ) break;
00367
00368 CString strURL = strURLs.Left( nPos );
00369 strURLs = strURLs.Mid( nPos + 1 );
00370 strURL.TrimLeft();
00371
00372 FILETIME tSeen = { 0, 0 };
00373 BOOL bSeen = FALSE;
00374
00375 if ( _tcsistr( strURL, _T("://") ) != NULL )
00376 {
00377 nPos = strURL.ReverseFind( ' ' );
00378
00379 if ( nPos > 0 )
00380 {
00381 CString strTime = strURL.Mid( nPos + 1 );
00382 strURL = strURL.Left( nPos );
00383 strURL.TrimRight();
00384 bSeen = TimeFromString( strTime, &tSeen );
00385 }
00386
00387 for ( int nScan = 0 ; nScan < strURL.GetLength() ; nScan++ )
00388 {
00389 if ( strURL[ nScan ] == '`' ) strURL.SetAt( nScan, ',' );
00390 }
00391 }
00392 else
00393 {
00394 nPos = strURL.Find( ':' );
00395 if ( nPos < 1 ) continue;
00396
00397 int nPort = 0;
00398 _stscanf( strURL.Mid( nPos + 1 ), _T("%i"), &nPort );
00399 strURL.Truncate( nPos );
00400 USES_CONVERSION;
00401 DWORD nAddress = inet_addr( T2CA( strURL ) );
00402 strURL.Empty();
00403
00404 if ( ! Network.IsFirewalledAddress( &nAddress, TRUE ) && nPort != 0 && nAddress != INADDR_NONE )
00405 {
00406 if ( m_bSHA1 )
00407 {
00408 strURL.Format( _T("http://%s:%i/uri-res/N2R?%s"),
00409 (LPCTSTR)CString( inet_ntoa( *(IN_ADDR*)&nAddress ) ),
00410 nPort, (LPCTSTR)CSHA::HashToString( &m_pSHA1, TRUE ) );
00411 }
00412 }
00413 }
00414
00415 if ( AddSourceURL( strURL, bURN, bSeen ? &tSeen : NULL ) ) nCount++;
00416 }
00417
00418 return nCount;
00419 }
00420
00422
00423
00424 BOOL CDownloadWithSources::AddSourceInternal(CDownloadSource* pSource)
00425 {
00426
00427 if ( ! pSource->m_bPushOnly )
00428 {
00429
00430 if ( pSource->m_pAddress.S_un.S_un_b.s_b1 == 0 )
00431 {
00432 delete pSource;
00433 return FALSE;
00434 }
00435
00436
00437 if ( Network.m_pHost.sin_addr.S_un.S_addr == pSource->m_pAddress.S_un.S_addr )
00438 {
00439 if ( ( ( pSource->m_nServerPort == 0 ) && (Settings.Connection.InPort == pSource->m_nPort ) )
00440 || ( Settings.Connection.IgnoreOwnIP ) )
00441 {
00442 delete pSource;
00443 return FALSE;
00444 }
00445 }
00446 }
00447 else if ( pSource->m_nProtocol == PROTOCOL_ED2K )
00448 {
00449
00450 if ( pSource->m_pServerAddress.S_un.S_un_b.s_b1 == 0 )
00451 {
00452 delete pSource;
00453 return FALSE;
00454 }
00455 }
00456
00457
00458 if ( pSource->m_bGUID )
00459 {
00460 if ( ( pSource->m_pGUID.w[0] == 0 ) && ( pSource->m_pGUID.w[1] == 0 ) &&
00461 ( pSource->m_pGUID.w[2] == 0 ) && ( pSource->m_pGUID.w[3] == 0 ) )
00462 {
00463
00464 pSource->m_bGUID = FALSE;
00465 }
00466 }
00467
00468 for ( CDownloadSource* pExisting = m_pSourceFirst ; pExisting ; pExisting = pExisting->m_pNext )
00469 {
00470 if ( pExisting->Equals( pSource ) )
00471 {
00472 if ( pExisting->m_pTransfer != NULL ||
00473 ( pExisting->m_nProtocol == PROTOCOL_HTTP && pSource->m_nProtocol != PROTOCOL_HTTP ) )
00474 {
00475 delete pSource;
00476 return FALSE;
00477 }
00478 else
00479 {
00480 pSource->m_tAttempt = pExisting->m_tAttempt;
00481 pExisting->Remove( TRUE, FALSE );
00482 break;
00483 }
00484 }
00485 }
00486
00487 m_nSourceCount ++;
00488
00489 pSource->m_pPrev = m_pSourceLast;
00490 pSource->m_pNext = NULL;
00491
00492 if ( m_pSourceLast != NULL )
00493 {
00494 m_pSourceLast->m_pNext = pSource;
00495 m_pSourceLast = pSource;
00496 }
00497 else
00498 {
00499 m_pSourceFirst = m_pSourceLast = pSource;
00500 }
00501
00502 SetModified();
00503
00504 return TRUE;
00505 }
00506
00508
00509
00510 CString CDownloadWithSources::GetSourceURLs(CStringList* pState, int nMaximum, PROTOCOLID nProtocol, CDownloadSource* pExcept)
00511 {
00512 CString strSources, strURL;
00513
00514 for ( CDownloadSource* pSource = GetFirstSource() ; pSource ; pSource = pSource->m_pNext )
00515 {
00516 if ( pSource != pExcept && pSource->m_bPushOnly == FALSE &&
00517 pSource->m_nFailures == 0 && pSource->m_bReadContent &&
00518 ( pSource->m_bSHA1 || pSource->m_bED2K ) &&
00519 ( pState == NULL || pState->Find( pSource->m_sURL ) == NULL ) )
00520 {
00521 if ( pState != NULL ) pState->AddTail( pSource->m_sURL );
00522
00523
00524
00525 if ( ( nProtocol == PROTOCOL_HTTP ) && ( pSource->m_nProtocol != PROTOCOL_HTTP ) ) continue;
00526 if ( ( nProtocol == PROTOCOL_G1 ) && ( pSource->m_nGnutella != 1 ) ) continue;
00527
00528
00529
00530 strURL = pSource->m_sURL;
00531 Replace( strURL, _T(","), _T("%2C") );
00532
00533 if ( strSources.GetLength() > 0 ) strSources += _T(", ");
00534 strSources += strURL;
00535 strSources += ' ';
00536 strSources += TimeToString( &pSource->m_tLastSeen );
00537
00538 if ( nMaximum == 1 ) break;
00539 else if ( nMaximum > 1 ) nMaximum --;
00540 }
00541 }
00542
00543 if ( strSources.Find( _T("Zhttp://") ) >= 0 ) strSources.Empty();
00544
00545 return strSources;
00546 }
00547
00549
00550
00551 BOOL CDownloadWithSources::OnQueryHits(CQueryHit* pHits)
00552 {
00553 for ( ; pHits ; pHits = pHits->m_pNext )
00554 {
00555 if ( pHits->m_sURL.GetLength() ) AddSourceHit( pHits );
00556 }
00557
00558 return TRUE;
00559 }
00560
00562
00563
00564 void CDownloadWithSources::RemoveOverlappingSources(QWORD nOffset, QWORD nLength)
00565 {
00566 for ( CDownloadSource* pSource = GetFirstSource() ; pSource ; )
00567 {
00568 CDownloadSource* pNext = pSource->m_pNext;
00569
00570 if ( pSource->TouchedRange( nOffset, nLength ) )
00571 {
00572 theApp.Message( MSG_ERROR, IDS_DOWNLOAD_VERIFY_DROP,
00573 (LPCTSTR)CString( inet_ntoa( pSource->m_pAddress ) ),
00574 (LPCTSTR)pSource->m_sServer, (LPCTSTR)m_sRemoteName,
00575 nOffset, nOffset + nLength - 1 );
00576 pSource->Remove( TRUE, TRUE );
00577 }
00578
00579 pSource = pNext;
00580 }
00581 }
00582
00584
00585
00586 void CDownloadWithSources::RemoveSource(CDownloadSource* pSource, BOOL bBan)
00587 {
00588 if ( bBan && pSource->m_sURL.GetLength() )
00589 {
00590 m_pFailedSources.AddTail( pSource->m_sURL );
00591 }
00592
00593 ASSERT( m_nSourceCount > 0 );
00594 m_nSourceCount --;
00595
00596 if ( pSource->m_pPrev != NULL )
00597 pSource->m_pPrev->m_pNext = pSource->m_pNext;
00598 else
00599 m_pSourceFirst = pSource->m_pNext;
00600
00601 if ( pSource->m_pNext != NULL )
00602 pSource->m_pNext->m_pPrev = pSource->m_pPrev;
00603 else
00604 m_pSourceLast = pSource->m_pPrev;
00605
00606 delete pSource;
00607 SetModified();
00608 }
00609
00611
00612
00613 void CDownloadWithSources::SortSource(CDownloadSource* pSource, BOOL bTop)
00614 {
00615 ASSERT( m_nSourceCount > 0 );
00616
00617 if ( pSource->m_pPrev != NULL )
00618 pSource->m_pPrev->m_pNext = pSource->m_pNext;
00619 else
00620 m_pSourceFirst = pSource->m_pNext;
00621
00622 if ( pSource->m_pNext != NULL )
00623 pSource->m_pNext->m_pPrev = pSource->m_pPrev;
00624 else
00625 m_pSourceLast = pSource->m_pPrev;
00626
00627 if ( ! bTop )
00628 {
00629 pSource->m_pPrev = m_pSourceLast;
00630 pSource->m_pNext = NULL;
00631
00632 if ( m_pSourceLast != NULL )
00633 {
00634 m_pSourceLast->m_pNext = pSource;
00635 m_pSourceLast = pSource;
00636 }
00637 else
00638 {
00639 m_pSourceFirst = m_pSourceLast = pSource;
00640 }
00641 }
00642 else
00643 {
00644 pSource->m_pPrev = NULL;
00645 pSource->m_pNext = m_pSourceFirst;
00646
00647 if ( m_pSourceFirst != NULL )
00648 {
00649 m_pSourceFirst->m_pPrev = pSource;
00650 m_pSourceFirst = pSource;
00651 }
00652 else
00653 {
00654 m_pSourceFirst = m_pSourceLast = pSource;
00655 }
00656 }
00657 }
00658
00659
00661
00662
00663 void CDownloadWithSources::SortSource(CDownloadSource* pSource)
00664 {
00665 ASSERT( m_nSourceCount > 0 );
00666
00667
00668 if ( pSource->m_pPrev != NULL )
00669 pSource->m_pPrev->m_pNext = pSource->m_pNext;
00670 else
00671 m_pSourceFirst = pSource->m_pNext;
00672
00673 if ( pSource->m_pNext != NULL )
00674 pSource->m_pNext->m_pPrev = pSource->m_pPrev;
00675 else
00676 m_pSourceLast = pSource->m_pPrev;
00677
00678
00679
00680 if ( ( m_pSourceFirst == NULL ) || ( m_pSourceLast == NULL ) )
00681 {
00682 m_pSourceFirst = m_pSourceLast = pSource;
00683 pSource->m_pNext = pSource->m_pPrev = NULL;
00684 }
00685 else
00686 {
00687 CDownloadSource* pCompare = m_pSourceFirst;
00688
00689 while ( ( pCompare != NULL ) && (pCompare->m_nSortOrder < pSource->m_nSortOrder) )
00690 pCompare = pCompare->m_pNext;
00691
00692
00693
00694 if ( pCompare == NULL )
00695 {
00696 m_pSourceLast->m_pNext = pSource;
00697 pSource->m_pPrev = m_pSourceLast;
00698 pSource->m_pNext = NULL;
00699 m_pSourceLast = pSource;
00700 }
00701 else
00702 {
00703 if ( pCompare->m_pPrev == NULL )
00704 m_pSourceFirst = pSource;
00705 else
00706 pCompare->m_pPrev->m_pNext = pSource;
00707
00708 pSource->m_pNext = pCompare;
00709 pSource->m_pPrev = pCompare->m_pPrev;
00710 pCompare->m_pPrev= pSource;
00711 }
00712
00713 }
00714 }
00715
00717
00718
00719 #define SRC_COLOURS 6
00720
00721 int CDownloadWithSources::GetSourceColour()
00722 {
00723 BOOL bTaken[SRC_COLOURS];
00724 ZeroMemory( bTaken, sizeof(BOOL) * SRC_COLOURS );
00725 int nFree = SRC_COLOURS;
00726
00727 for ( CDownloadSource* pSource = GetFirstSource() ; pSource ; pSource = pSource->m_pNext )
00728 {
00729 if ( pSource->m_nColour >= 0 )
00730 {
00731 if ( bTaken[ pSource->m_nColour ] == FALSE )
00732 {
00733 bTaken[ pSource->m_nColour ] = TRUE;
00734 nFree--;
00735 }
00736 }
00737 }
00738
00739 srand( GetTickCount() + (DWORD)this );
00740
00741 if ( nFree == 0 ) return rand() % SRC_COLOURS;
00742
00743 nFree = rand() % nFree;
00744
00745 for ( int nColour = 0 ; nColour < SRC_COLOURS ; nColour++ )
00746 {
00747 if ( bTaken[ nColour ] == FALSE )
00748 {
00749 if ( nFree-- == 0 ) return nColour;
00750 }
00751 }
00752
00753 return rand() % SRC_COLOURS;
00754 }
00755
00757
00758
00759 void CDownloadWithSources::Serialize(CArchive& ar, int nVersion)
00760 {
00761 CDownloadBase::Serialize( ar, nVersion );
00762
00763 if ( ar.IsStoring() )
00764 {
00765 ar.WriteCount( GetSourceCount() );
00766
00767 for ( CDownloadSource* pSource = GetFirstSource() ; pSource ; pSource = pSource->m_pNext )
00768 {
00769 pSource->Serialize( ar, nVersion );
00770 }
00771
00772 ar.WriteCount( m_pXML != NULL ? 1 : 0 );
00773 if ( m_pXML ) m_pXML->Serialize( ar );
00774 }
00775 else
00776 {
00777 for ( int nSources = ar.ReadCount() ; nSources ; nSources-- )
00778 {
00779
00780 CDownloadSource* pSource = new CDownloadSource( (CDownload*)this );
00781
00782
00783 m_nSourceCount ++;
00784 pSource->m_pPrev = m_pSourceLast;
00785 pSource->m_pNext = NULL;
00786
00787 if ( m_pSourceLast != NULL )
00788 {
00789 m_pSourceLast->m_pNext = pSource;
00790 m_pSourceLast = pSource;
00791 }
00792 else
00793 {
00794 m_pSourceFirst = m_pSourceLast = pSource;
00795 }
00796
00797
00798 pSource->Serialize( ar, nVersion );
00799
00800
00801 if ( ( !pSource->m_nPort ) && ( _tcsnicmp( pSource->m_sURL, _T("ed2kftp://"), 10 ) == 0 ) )
00802 {
00803 CString strURL = pSource->m_sURL.Mid(10);
00804 if ( strURL.GetLength())
00805 _stscanf( strURL, _T("%lu"), &pSource->m_pAddress.S_un.S_addr );
00806 }
00807 }
00808
00809 if ( ar.ReadCount() )
00810 {
00811 m_pXML = new CXMLElement();
00812 m_pXML->Serialize( ar );
00813 }
00814 }
00815 }