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 "DownloadWithTiger.h"
00027 #include "FragmentedFile.h"
00028
00029 #include "Neighbours.h"
00030 #include "Transfers.h"
00031 #include "Library.h"
00032 #include "SharedFile.h"
00033 #include "BTInfo.h"
00034
00035 #ifdef _DEBUG
00036 #undef THIS_FILE
00037 static char THIS_FILE[]=__FILE__;
00038 #define new DEBUG_NEW
00039 #endif
00040
00041
00043
00044
00045 CDownloadWithTiger::CDownloadWithTiger()
00046 {
00047 m_pTigerBlock = NULL;
00048 m_nTigerBlock = 0;
00049 m_nTigerSuccess = 0;
00050
00051 m_pHashsetBlock = NULL;
00052 m_nHashsetBlock = 0;
00053 m_nHashsetSuccess = 0;
00054
00055 m_nVerifyCookie = 0;
00056 m_nVerifyHash = HASH_NULL;
00057 m_nVerifyBlock = 0xFFFFFFFF;
00058 }
00059
00060 CDownloadWithTiger::~CDownloadWithTiger()
00061 {
00062 if ( m_pHashsetBlock != NULL ) delete [] m_pHashsetBlock;
00063 if ( m_pTigerBlock != NULL ) delete [] m_pTigerBlock;
00064 }
00065
00067
00068
00069 DWORD CDownloadWithTiger::GetValidationCookie() const
00070 {
00071 return m_nVerifyCookie;
00072 }
00073
00074 QWORD CDownloadWithTiger::GetVerifyLength(int nHash) const
00075 {
00076 if ( nHash == HASH_NULL )
00077 {
00078 if ( m_pTorrentBlock != NULL ) return m_nTorrentSize;
00079 else if ( m_pTigerBlock != NULL ) return m_nTigerSize;
00080 else if ( m_pHashsetBlock != NULL ) return ED2K_PART_SIZE;
00081 }
00082 else if ( nHash == HASH_TIGERTREE && m_pTigerBlock != NULL )
00083 {
00084 return m_nTigerSize;
00085 }
00086 else if ( nHash == HASH_ED2K && m_pHashsetBlock != NULL )
00087 {
00088 return ED2K_PART_SIZE;
00089 }
00090 else if ( nHash == HASH_TORRENT && m_pTorrentBlock != NULL )
00091 {
00092 return m_nTorrentSize;
00093 }
00094
00095 return 0;
00096 }
00097
00098 BOOL CDownloadWithTiger::GetNextVerifyRange(QWORD& nOffset, QWORD& nLength, BOOL& bSuccess, int nHash) const
00099 {
00100 if ( nOffset >= m_nSize ) return FALSE;
00101 if ( m_pTigerBlock == NULL && m_pHashsetBlock == NULL && m_pTorrentBlock == NULL ) return FALSE;
00102
00103 if ( nHash == HASH_NULL )
00104 {
00105 if ( m_pTorrentBlock != NULL ) nHash = HASH_TORRENT;
00106 else if ( m_pTigerBlock != NULL ) nHash = HASH_TIGERTREE;
00107 else if ( m_pHashsetBlock != NULL ) nHash = HASH_ED2K;
00108 }
00109
00110 QWORD nBlockCount, nBlockSize;
00111 BYTE* pBlockPtr;
00112
00113 switch ( nHash )
00114 {
00115 case HASH_TIGERTREE:
00116 if ( m_pTigerBlock == NULL ) return FALSE;
00117 pBlockPtr = m_pTigerBlock;
00118 nBlockCount = m_nTigerBlock;
00119 nBlockSize = m_nTigerSize;
00120 break;
00121 case HASH_ED2K:
00122 if ( m_pHashsetBlock == NULL ) return FALSE;
00123 pBlockPtr = m_pHashsetBlock;
00124 nBlockCount = m_nHashsetBlock;
00125 nBlockSize = ED2K_PART_SIZE;
00126 break;
00127 case HASH_TORRENT:
00128 if ( m_pTorrentBlock == NULL ) return FALSE;
00129 pBlockPtr = m_pTorrentBlock;
00130 nBlockCount = m_nTorrentBlock;
00131 nBlockSize = m_nTorrentSize;
00132 break;
00133 default:
00134 return FALSE;
00135 }
00136
00137 if ( nBlockSize == 0 ) return FALSE;
00138
00139 for ( QWORD nBlock = nOffset / nBlockSize ; nBlock < nBlockCount ; nBlock++ )
00140 {
00141 QWORD nThis = nBlock * nBlockSize;
00142
00143 if ( nThis >= nOffset && pBlockPtr[ nBlock ] )
00144 {
00145 TRISTATE nBase = pBlockPtr[ nBlock ];
00146 bSuccess = nBase == TS_TRUE;
00147 nOffset = nThis;
00148 nLength = 0;
00149
00150 for ( ; nBlock < nBlockCount ; nBlock++ )
00151 {
00152 if ( nBase != pBlockPtr[ nBlock ] ) break;
00153 nLength += nBlockSize;
00154 }
00155
00156 return TRUE;
00157 }
00158 }
00159
00160 return FALSE;
00161 }
00162
00163 BOOL CDownloadWithTiger::IsFullyVerified()
00164 {
00165 if ( m_nTorrentBlock > 0 && m_nTorrentSuccess >= m_nTorrentBlock ) return TRUE;
00166 if ( m_nTigerBlock > 0 && m_nTigerSuccess >= m_nTigerBlock ) return TRUE;
00167 if ( m_nHashsetBlock > 0 && m_nHashsetSuccess >= m_nHashsetBlock ) return TRUE;
00168 return FALSE;
00169 }
00170
00172
00173
00174 BOOL CDownloadWithTiger::NeedTigerTree() const
00175 {
00176 return ( m_nSize < SIZE_UNKNOWN && m_pTigerTree.IsAvailable() == FALSE );
00177 }
00178
00179 BOOL CDownloadWithTiger::SetTigerTree(BYTE* pTiger, DWORD nTiger)
00180 {
00181 if ( m_nSize == SIZE_UNKNOWN ) return FALSE;
00182 if ( m_pTigerTree.IsAvailable() ) return TRUE;
00183
00184 if ( ! m_pTigerTree.FromBytes( pTiger, nTiger,
00185 Settings.Library.TigerHeight, m_nSize ) )
00186 {
00187 theApp.Message( MSG_ERROR, IDS_DOWNLOAD_TIGER_CORRUPT,
00188 (LPCTSTR)GetDisplayName() );
00189 return FALSE;
00190 }
00191
00192 TIGEROOT pRoot;
00193 m_pTigerTree.GetRoot( &pRoot );
00194
00195 if ( m_bTiger && m_pTiger != pRoot )
00196 {
00197 m_pTigerTree.Clear();
00198 theApp.Message( MSG_ERROR, IDS_DOWNLOAD_TIGER_MISMATCH,
00199 (LPCTSTR)GetDisplayName() );
00200 return FALSE;
00201 }
00202 else if ( ! m_bTiger )
00203 {
00204 m_bTiger = TRUE;
00205 m_pTiger = pRoot;
00206 }
00207
00208 m_nTigerSize = m_pTigerTree.GetBlockLength();
00209 m_nTigerBlock = m_pTigerTree.GetBlockCount();
00210 m_pTigerBlock = new BYTE[ m_nTigerBlock ];
00211
00212 ZeroMemory( m_pTigerBlock, sizeof(BYTE) * m_nTigerBlock );
00213
00214 SetModified();
00215
00216 theApp.Message( MSG_DEFAULT, IDS_DOWNLOAD_TIGER_READY,
00217 (LPCTSTR)GetDisplayName(), m_pTigerTree.GetHeight(),
00218 (LPCTSTR)Settings.SmartVolume( m_nTigerSize, FALSE ) );
00219
00220 return TRUE;
00221 }
00222
00223 CTigerTree* CDownloadWithTiger::GetTigerTree()
00224 {
00225 return m_pTigerTree.IsAvailable() ? &m_pTigerTree : NULL;
00226 }
00227
00229
00230
00231 BOOL CDownloadWithTiger::NeedHashset() const
00232 {
00233 return ( m_nSize < SIZE_UNKNOWN && m_pHashset.IsAvailable() == FALSE );
00234 }
00235
00236 BOOL CDownloadWithTiger::SetHashset(BYTE* pSource, DWORD nSource)
00237 {
00238 if ( m_nSize == SIZE_UNKNOWN ) return FALSE;
00239 if ( m_pHashset.IsAvailable() ) return TRUE;
00240
00241 if ( nSource == 0 && m_bED2K )
00242 {
00243 m_pHashset.FromRoot( &m_pED2K );
00244 }
00245 else if ( m_pHashset.FromBytes( pSource, nSource, m_nSize ) )
00246 {
00247 MD4 pRoot;
00248 m_pHashset.GetRoot( &pRoot );
00249
00250 if ( m_bED2K && m_pED2K != pRoot )
00251 {
00252 m_pHashset.Clear();
00253 theApp.Message( MSG_ERROR, IDS_DOWNLOAD_HASHSET_CORRUPT,
00254 (LPCTSTR)GetDisplayName() );
00255 return FALSE;
00256 }
00257 else if ( ! m_bED2K )
00258 {
00259 m_bED2K = TRUE;
00260 m_pED2K = pRoot;
00261 }
00262 }
00263 else
00264 {
00265 theApp.Message( MSG_ERROR, IDS_DOWNLOAD_HASHSET_CORRUPT,
00266 (LPCTSTR)GetDisplayName() );
00267 return FALSE;
00268 }
00269
00270 m_nHashsetBlock = m_pHashset.GetBlockCount();
00271 m_pHashsetBlock = new BYTE[ m_nHashsetBlock ];
00272
00273 ZeroMemory( m_pHashsetBlock, sizeof(BYTE) * m_nHashsetBlock );
00274
00275 SetModified();
00276
00277 theApp.Message( MSG_DEFAULT, IDS_DOWNLOAD_HASHSET_READY,
00278 (LPCTSTR)GetDisplayName(),
00279 (LPCTSTR)Settings.SmartVolume( ED2K_PART_SIZE, FALSE ) );
00280
00281 Neighbours.SendDonkeyDownload( reinterpret_cast<CDownload*>( this ) );
00282
00283 return TRUE;
00284 }
00285
00286 CED2K* CDownloadWithTiger::GetHashset()
00287 {
00288 return m_pHashset.IsAvailable() ? &m_pHashset : NULL;
00289 }
00290
00292
00293
00294 BOOL CDownloadWithTiger::ValidationCanFinish() const
00295 {
00296 BOOL bAvailable = FALSE;
00297
00298 if ( m_pTorrentBlock != NULL )
00299 {
00300 if ( m_nTorrentSuccess >= m_nTorrentBlock ) return TRUE;
00301 bAvailable = TRUE;
00302 }
00303
00304 if ( m_pTigerBlock != NULL && Settings.Downloads.VerifyTiger )
00305 {
00306 if ( m_nTigerSuccess >= m_nTigerBlock ) return TRUE;
00307 bAvailable = TRUE;
00308 }
00309
00310 if ( m_pHashsetBlock != NULL && Settings.Downloads.VerifyED2K )
00311 {
00312 if ( m_nHashsetSuccess >= m_nHashsetBlock ) return TRUE;
00313 bAvailable = TRUE;
00314 }
00315
00316 return ! bAvailable;
00317 }
00318
00320
00321
00322 void CDownloadWithTiger::RunValidation(BOOL bSeeding)
00323 {
00324 if ( m_pTigerBlock == NULL && m_pHashsetBlock == NULL && m_pTorrentBlock == NULL ) return;
00325 if ( m_sLocalName.IsEmpty() ) return;
00326
00327 if ( ! bSeeding )
00328 {
00329 if ( m_pFile == NULL || ! OpenFile() ) return;
00330 }
00331
00332 if ( m_nVerifyHash > HASH_NULL && m_nVerifyBlock < 0xFFFFFFFF )
00333 {
00334 Downloads.m_nValidation ++;
00335 ContinueValidation();
00336 }
00337 else
00338 {
00339 if ( FindNewValidationBlock( HASH_TORRENT ) ||
00340 FindNewValidationBlock( HASH_TIGERTREE ) ||
00341 FindNewValidationBlock( HASH_ED2K ) )
00342 {
00343 Downloads.m_nValidation ++;
00344 ContinueValidation();
00345 }
00346 }
00347 }
00348
00350
00351
00352 BOOL CDownloadWithTiger::FindNewValidationBlock(int nHash)
00353 {
00354 if ( nHash == HASH_TIGERTREE && ! Settings.Downloads.VerifyTiger ) return FALSE;
00355 if ( nHash == HASH_ED2K && ! Settings.Downloads.VerifyED2K ) return FALSE;
00356
00357 DWORD nBlockCount;
00358 QWORD nBlockSize;
00359 BYTE* pBlockPtr;
00360
00361 switch ( nHash )
00362 {
00363 case HASH_TIGERTREE:
00364 if ( m_pTigerBlock == NULL ) return FALSE;
00365 pBlockPtr = m_pTigerBlock;
00366 nBlockCount = m_nTigerBlock;
00367 nBlockSize = m_nTigerSize;
00368 break;
00369 case HASH_ED2K:
00370 if ( m_pHashsetBlock == NULL ) return FALSE;
00371 pBlockPtr = m_pHashsetBlock;
00372 nBlockCount = m_nHashsetBlock;
00373 nBlockSize = ED2K_PART_SIZE;
00374 break;
00375 case HASH_TORRENT:
00376 if ( m_pTorrentBlock == NULL ) return FALSE;
00377 pBlockPtr = m_pTorrentBlock;
00378 nBlockCount = m_nTorrentBlock;
00379 nBlockSize = m_nTorrentSize;
00380 break;
00381 default:
00382 return FALSE;
00383 }
00384
00385 DWORD nTarget = 0xFFFFFFFF;
00386
00387 if ( m_pFile == NULL )
00388 {
00389 for ( TRISTATE nState = TS_UNKNOWN ; nState < TS_TRUE ; nState++ )
00390 {
00391 for ( DWORD nBlock = 0 ; nBlock < nBlockCount ; nBlock ++ )
00392 {
00393 if ( pBlockPtr[ nBlock ] == nState )
00394 {
00395 nTarget = nBlock;
00396 break;
00397 }
00398 }
00399
00400 if ( nTarget != 0xFFFFFFFF ) break;
00401 }
00402 }
00403 else
00404 {
00405 DWORD nRetry = 0xFFFFFFFF;
00406 QWORD nPrevious = 0;
00407
00408 for ( FF::SimpleFragmentList::ConstIterator pFragment
00409 = m_pFile->GetEmptyFragmentList().begin();
00410 pFragment != m_pFile->GetEmptyFragmentList().end();
00411 ++pFragment )
00412 {
00413 if ( pFragment->begin() - nPrevious >= nBlockSize )
00414 {
00415 DWORD nBlock = (DWORD)( ( nPrevious + nBlockSize - 1 ) / nBlockSize );
00416 nPrevious = nBlockSize * (QWORD)nBlock + nBlockSize;
00417
00418 for ( ; nPrevious <= pFragment->begin() ; nBlock ++, nPrevious += nBlockSize )
00419 {
00420 if ( pBlockPtr[ nBlock ] == TS_UNKNOWN )
00421 {
00422 nTarget = nBlock;
00423 break;
00424 }
00425 else if ( pBlockPtr[ nBlock ] == TS_FALSE && nRetry == 0xFFFFFFFF )
00426 {
00427 nRetry = nBlock;
00428 }
00429 }
00430
00431 if ( nTarget != 0xFFFFFFFF ) break;
00432 }
00433
00434 nPrevious = pFragment->end();
00435 }
00436
00437 if ( m_nSize > nPrevious && nTarget == 0xFFFFFFFF )
00438 {
00439 DWORD nBlock = (DWORD)( ( nPrevious + nBlockSize - 1 ) / nBlockSize );
00440 nPrevious = nBlockSize * (QWORD)nBlock;
00441
00442 for ( ; nPrevious < m_nSize ; nBlock ++, nPrevious += nBlockSize )
00443 {
00444 if ( pBlockPtr[ nBlock ] == TS_UNKNOWN )
00445 {
00446 nTarget = nBlock;
00447 break;
00448 }
00449 else if ( pBlockPtr[ nBlock ] == TS_FALSE && nRetry == 0xFFFFFFFF )
00450 {
00451 nRetry = nBlock;
00452 }
00453 }
00454 }
00455
00456 if ( nTarget == 0xFFFFFFFF ) nTarget = nRetry;
00457 }
00458
00459 if ( nTarget != 0xFFFFFFFF )
00460 {
00461 m_nVerifyHash = nHash;
00462 m_nVerifyBlock = nTarget;
00463 m_nVerifyOffset = nTarget * nBlockSize;
00464 m_nVerifyLength = min( nBlockSize, m_nSize - m_nVerifyOffset );
00465 m_tVerifyLast = GetTickCount();
00466
00467 if ( m_nVerifyHash == HASH_TIGERTREE )
00468 m_pTigerTree.BeginBlockTest();
00469 else if ( m_nVerifyHash == HASH_ED2K )
00470 m_pHashset.BeginBlockTest();
00471 else if ( m_nVerifyHash == HASH_TORRENT )
00472 m_pTorrent.BeginBlockTest();
00473
00474 return TRUE;
00475 }
00476
00477 return FALSE;
00478 }
00479
00481
00482
00483 void CDownloadWithTiger::ContinueValidation()
00484 {
00485 ASSERT( m_nVerifyHash > HASH_NULL );
00486 ASSERT( m_nVerifyBlock < 0xFFFFFFFF );
00487
00488 BOOL bDone = ( m_pFile == NULL ) || ( m_pFile->GetRemaining() == 0 );
00489 HANDLE hComplete = INVALID_HANDLE_VALUE;
00490
00491 if ( m_pFile == NULL )
00492 {
00493 hComplete = CreateFile( m_sLocalName, GENERIC_READ,
00494 FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
00495 FILE_ATTRIBUTE_NORMAL, NULL );
00496 if ( hComplete == INVALID_HANDLE_VALUE ) return;
00497 }
00498
00499 for ( int nRound = bDone ? 10 : 2 ; nRound > 0 && m_nVerifyLength > 0 ; nRound-- )
00500 {
00501 DWORD nChunk = (DWORD)min( DWORD(m_nVerifyLength), Transfers.m_nBuffer );
00502 LPBYTE pChunk = Transfers.m_pBuffer;
00503
00504 if ( m_pFile != NULL )
00505 {
00506 m_pFile->ReadRange( m_nVerifyOffset, pChunk, nChunk );
00507 }
00508 else
00509 {
00510 LONG nOffsetHigh = (LONG)( m_nVerifyOffset >> 32 );
00511 SetFilePointer( hComplete, (DWORD)( m_nVerifyOffset & 0xFFFFFFFF ), &nOffsetHigh, FILE_BEGIN );
00512 ReadFile( hComplete, pChunk, nChunk, &nChunk, NULL );
00513 }
00514
00515 if ( m_nVerifyHash == HASH_TIGERTREE )
00516 m_pTigerTree.AddToTest( pChunk, (DWORD)nChunk );
00517 else if ( m_nVerifyHash == HASH_ED2K )
00518 m_pHashset.AddToTest( pChunk, (DWORD)nChunk );
00519 else if ( m_nVerifyHash == HASH_TORRENT )
00520 m_pTorrent.AddToTest( pChunk, (DWORD)nChunk );
00521 else
00522 ASSERT( FALSE );
00523
00524 m_nVerifyOffset += nChunk;
00525 m_nVerifyLength -= nChunk;
00526 }
00527
00528 if ( hComplete != INVALID_HANDLE_VALUE ) CloseHandle( hComplete );
00529 if ( m_nVerifyLength == 0 ) FinishValidation();
00530 }
00531
00532 void CDownloadWithTiger::FinishValidation()
00533 {
00534 FF::SimpleFragmentList oCorrupted( m_nSize );
00535
00536 if ( m_nVerifyHash == HASH_TIGERTREE )
00537 {
00538 if ( m_pTigerTree.FinishBlockTest( m_nVerifyBlock ) )
00539 {
00540 m_pTigerBlock[ m_nVerifyBlock ] = TS_TRUE;
00541 m_nTigerSuccess ++;
00542 }
00543 else
00544 {
00545 m_pTigerBlock[ m_nVerifyBlock ] = TS_FALSE;
00546
00547 QWORD nOffset = QWORD(m_nVerifyBlock) * QWORD(m_nTigerSize);
00548 oCorrupted.insert( oCorrupted.end(), FF::SimpleFragment( nOffset,
00549 ::std::min( nOffset + m_nTigerSize, m_nSize ) ) );
00550 }
00551 }
00552 else if ( m_nVerifyHash == HASH_ED2K )
00553 {
00554 if ( m_pHashset.FinishBlockTest( m_nVerifyBlock ) )
00555 {
00556 m_pHashsetBlock[ m_nVerifyBlock ] = TS_TRUE;
00557 m_nHashsetSuccess ++;
00558 }
00559 else
00560 {
00561 m_pHashsetBlock[ m_nVerifyBlock ] = TS_FALSE;
00562
00563 QWORD nOffset = QWORD(m_nVerifyBlock) * QWORD(ED2K_PART_SIZE);
00564 oCorrupted.insert( oCorrupted.end(), FF::SimpleFragment( nOffset,
00565 ::std::min( nOffset + ED2K_PART_SIZE, m_nSize ) ) );
00566 }
00567 }
00568 else if ( m_nVerifyHash == HASH_TORRENT )
00569 {
00570 if ( m_pTorrent.FinishBlockTest( m_nVerifyBlock ) )
00571 {
00572 m_pTorrentBlock[ m_nVerifyBlock ] = TS_TRUE;
00573 m_nTorrentSuccess ++;
00574
00575 OnFinishedTorrentBlock( m_nVerifyBlock );
00576 }
00577 else
00578 {
00579 m_pTorrentBlock[ m_nVerifyBlock ] = TS_FALSE;
00580
00581 QWORD nOffset = QWORD(m_nVerifyBlock) * QWORD(m_nTorrentSize);
00582 oCorrupted.insert( oCorrupted.end(), FF::SimpleFragment( nOffset,
00583 ::std::min( nOffset + m_nTorrentSize, m_nSize ) ) );
00584 }
00585 }
00586
00587 if ( !oCorrupted.empty() && m_pFile != NULL )
00588 {
00589 if ( m_pTigerBlock != NULL )
00590 SubtractHelper( oCorrupted, m_pTigerBlock, m_nTigerBlock, m_nTigerSize );
00591 if ( m_pHashsetBlock != NULL )
00592 SubtractHelper( oCorrupted, m_pHashsetBlock, m_nHashsetBlock, ED2K_PART_SIZE );
00593 if ( m_pTorrentBlock != NULL )
00594 SubtractHelper( oCorrupted, m_pTorrentBlock, m_nTorrentBlock, m_nTorrentSize );
00595
00596 for ( FF::SimpleFragmentList::ConstIterator pRange = oCorrupted.begin();
00597 pRange != oCorrupted.end(); ++pRange )
00598 {
00599 m_pFile->InvalidateRange( pRange->begin(), pRange->length() );
00600 RemoveOverlappingSources( pRange->begin(), pRange->length() );
00601 }
00602
00603 }
00604 m_nVerifyHash = HASH_NULL;
00605 m_nVerifyBlock = 0xFFFFFFFF;
00606 m_nVerifyCookie++;
00607
00608 SetModified();
00609 }
00610
00611 void CDownloadWithTiger::SubtractHelper(FF::SimpleFragmentList& ppCorrupted, BYTE* pBlock, QWORD nBlock, QWORD nSize)
00612 {
00613 QWORD nOffset = 0;
00614
00615 while ( nBlock-- && !ppCorrupted.empty() )
00616 {
00617 if ( *pBlock++ == TS_TRUE )
00618 {
00619 ppCorrupted.erase( FF::SimpleFragment( nOffset, ::std::min( nOffset + nSize, m_nSize ) ) );
00620 }
00621
00622 nOffset += nSize;
00623 }
00624 }
00625
00627
00628
00629 CString CDownloadWithTiger::GetAvailableRanges() const
00630 {
00631 CString strRanges, strRange;
00632 QWORD nOffset, nLength;
00633 BOOL bSuccess;
00634
00635 for ( nOffset = 0 ; GetNextVerifyRange( nOffset, nLength, bSuccess ) ; )
00636 {
00637 if ( bSuccess )
00638 {
00639 if ( strRanges.IsEmpty() )
00640 strRanges = _T("bytes ");
00641 else
00642 strRanges += ',';
00643
00644 strRange.Format( _T("%I64i-%I64i"), nOffset, nOffset + nLength - 1 );
00645 strRanges += strRange;
00646 }
00647
00648 nOffset += nLength;
00649 }
00650
00651 if ( strRanges.IsEmpty() ) strRanges = CDownloadWithTorrent::GetAvailableRanges();
00652
00653 return strRanges;
00654 }
00655
00657
00658
00659 void CDownloadWithTiger::ResetVerification()
00660 {
00661 if ( m_nVerifyHash == HASH_TIGERTREE )
00662 {
00663 m_pTigerTree.FinishBlockTest( m_nVerifyBlock );
00664 }
00665 else if ( m_nVerifyHash == HASH_ED2K )
00666 {
00667 m_pHashset.FinishBlockTest( m_nVerifyBlock );
00668 }
00669 else if ( m_nVerifyHash == HASH_TORRENT )
00670 {
00671 m_pTorrent.FinishBlockTest( m_nVerifyBlock );
00672 }
00673
00674 if ( m_pTigerBlock != NULL ) ZeroMemory( m_pTigerBlock, m_nTigerBlock );
00675 if ( m_pHashsetBlock != NULL ) ZeroMemory( m_pHashsetBlock, m_nHashsetBlock );
00676 if ( m_pTorrentBlock != NULL ) ZeroMemory( m_pTorrentBlock, m_nTorrentBlock );
00677
00678 m_nTigerSuccess = 0;
00679 m_nHashsetSuccess = 0;
00680 m_nTorrentSuccess = 0;
00681
00682 m_nVerifyHash = HASH_NULL;
00683 m_nVerifyBlock = 0xFFFFFFFF;
00684
00685 m_nVerifyCookie++;
00686 SetModified();
00687 }
00688
00689 void CDownloadWithTiger::ClearVerification()
00690 {
00691 ResetVerification();
00692
00693 if ( m_pTigerBlock != NULL ) delete [] m_pTigerBlock;
00694 if ( m_pHashsetBlock != NULL ) delete [] m_pHashsetBlock;
00695
00696 m_pTigerBlock = NULL;
00697 m_nTigerBlock = 0;
00698 m_pHashsetBlock = NULL;
00699 m_nHashsetBlock = 0;
00700
00701 m_pTigerTree.Clear();
00702 m_pHashset.Clear();
00703
00704 m_nVerifyCookie++;
00705 SetModified();
00706 }
00707
00709
00710
00711 void CDownloadWithTiger::Serialize(CArchive& ar, int nVersion)
00712 {
00713 CDownloadWithTorrent::Serialize( ar, nVersion );
00714
00715 m_pTigerTree.Serialize( ar );
00716
00717 if ( m_pTigerTree.IsAvailable() )
00718 {
00719 if ( ar.IsStoring() )
00720 {
00721 ar << m_nTigerBlock;
00722 ar << m_nTigerSize;
00723 ar << m_nTigerSuccess;
00724 ar.Write( m_pTigerBlock, sizeof(BYTE) * m_nTigerBlock );
00725 }
00726 else
00727 {
00728 m_pTigerTree.SetupParameters( m_nSize );
00729
00730 ar >> m_nTigerBlock;
00731 ar >> m_nTigerSize;
00732 ar >> m_nTigerSuccess;
00733
00734 m_pTigerBlock = new BYTE[ m_nTigerBlock ];
00735 ar.Read( m_pTigerBlock, sizeof(BYTE) * m_nTigerBlock );
00736 }
00737 }
00738
00739 if ( nVersion >= 19 )
00740 {
00741 m_pHashset.Serialize( ar );
00742
00743 if ( m_pHashset.IsAvailable() )
00744 {
00745 if ( ar.IsStoring() )
00746 {
00747 ar << m_nHashsetBlock;
00748 ar << m_nHashsetSuccess;
00749 ar.Write( m_pHashsetBlock, sizeof(BYTE) * m_nHashsetBlock );
00750 }
00751 else
00752 {
00753 ar >> m_nHashsetBlock;
00754 ar >> m_nHashsetSuccess;
00755
00756 m_pHashsetBlock = new BYTE[ m_nHashsetBlock ];
00757 ar.Read( m_pHashsetBlock, sizeof(BYTE) * m_nHashsetBlock );
00758 }
00759 }
00760 }
00761
00762 if ( nVersion < 30 && m_bBTH )
00763 {
00764 ClearVerification();
00765 m_bSHA1 = m_bTiger = m_bED2K = FALSE;
00766 }
00767 }