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 "BTInfo.h"
00026 #include "BENode.h"
00027 #include "Buffer.h"
00028
00029 #include "DownloadTask.h"
00030
00031 #ifdef _DEBUG
00032 #undef THIS_FILE
00033 static char THIS_FILE[]=__FILE__;
00034 #define new DEBUG_NEW
00035 #endif
00036
00037
00039
00040
00041 CBTInfo::CBTInfo()
00042 {
00043 m_bValid = FALSE;
00044 m_bEncodingError = FALSE;
00045 m_bDataSHA1 = FALSE;
00046 m_bDataED2K = FALSE;
00047 m_bDataTiger = FALSE;
00048 m_nTotalSize = 0;
00049 m_nBlockSize = 0;
00050 m_nBlockCount = 0;
00051 m_pBlockSHA1 = NULL;
00052 m_nFiles = 0;
00053 m_pFiles = NULL;
00054
00055 m_nEncoding = Settings.BitTorrent.TorrentCodePage;
00056 m_tCreationDate = 0;
00057
00058 m_pAnnounceTracker = NULL;
00059 m_nTrackerIndex = -1;
00060 }
00061
00062 CBTInfo::~CBTInfo()
00063 {
00064 Clear();
00065 }
00066
00067 CBTInfo::CBTFile::CBTFile()
00068 {
00069 m_nSize = 0;
00070 m_bSHA1 = FALSE;
00071 m_bED2K = FALSE;
00072 m_bTiger = FALSE;
00073 }
00074
00076
00077
00078 void CBTInfo::Clear()
00079 {
00080
00081 if ( m_pBlockSHA1 != NULL ) delete [] m_pBlockSHA1;
00082
00083 if ( m_pFiles != NULL ) delete [] m_pFiles;
00084
00085 m_bValid = FALSE;
00086 m_nTotalSize = 0;
00087 m_nBlockSize = 0;
00088 m_nBlockCount = 0;
00089 m_pBlockSHA1 = NULL;
00090 m_nFiles = 0;
00091 m_pFiles = NULL;
00092
00093
00094 if ( m_pAnnounceTracker != NULL )
00095 {
00096 delete m_pAnnounceTracker;
00097 m_pAnnounceTracker = NULL;
00098 }
00099
00100 while ( ! m_pTrackerList.IsEmpty() )
00101 {
00102 delete (CBTTracker *)m_pTrackerList.GetAt( 0 );
00103 m_pTrackerList.RemoveAt( 0 );
00104 }
00105 }
00106
00108
00109
00110 void CBTInfo::Copy(CBTInfo* pSource)
00111 {
00112 ASSERT( pSource != NULL );
00113 Clear();
00114
00115 m_bValid = pSource->m_bValid;
00116 m_bEncodingError= pSource->m_bEncodingError;
00117 m_pInfoSHA1 = pSource->m_pInfoSHA1;
00118 m_bDataSHA1 = pSource->m_bDataSHA1;
00119 m_pDataSHA1 = pSource->m_pDataSHA1;
00120 m_bDataED2K = pSource->m_bDataED2K;
00121 m_pDataED2K = pSource->m_pDataED2K;
00122 m_bDataTiger = pSource->m_bDataTiger;
00123 m_pDataTiger = pSource->m_pDataTiger;
00124
00125 m_nTotalSize = pSource->m_nTotalSize;
00126 m_nBlockSize = pSource->m_nBlockSize;
00127 m_nBlockCount = pSource->m_nBlockCount;
00128
00129 m_sName = pSource->m_sName;
00130 m_sTracker = pSource->m_sTracker;
00131 m_nFiles = pSource->m_nFiles;
00132
00133 m_nEncoding = pSource->m_nEncoding;
00134 m_sComment = pSource->m_sComment;
00135 m_tCreationDate = pSource->m_tCreationDate;
00136 m_sCreatedBy = pSource->m_sCreatedBy;
00137
00138 if ( pSource->m_pBlockSHA1 != NULL )
00139 {
00140 m_pBlockSHA1 = new SHA1[ m_nBlockCount ];
00141 CopyMemory( m_pBlockSHA1, pSource->m_pBlockSHA1,
00142 sizeof(SHA1) * (DWORD)m_nBlockCount );
00143 }
00144
00145 if ( pSource->m_pFiles != NULL )
00146 {
00147 m_pFiles = new CBTFile[ m_nFiles ];
00148 for ( int nFile = 0 ; nFile < m_nFiles ; nFile++ )
00149 m_pFiles[ nFile ].Copy( &pSource->m_pFiles[ nFile ] );
00150 }
00151
00152
00153 if ( pSource->m_pAnnounceTracker != NULL )
00154 {
00155 m_pAnnounceTracker = new CBTTracker;
00156 m_pAnnounceTracker->Copy( pSource->m_pAnnounceTracker );
00157 }
00158
00159 for ( int nCount = 0 ; nCount < pSource->m_pTrackerList.GetCount() ; nCount++ )
00160 {
00161 CBTTracker* pTracker = new CBTTracker;
00162 pTracker->Copy( (CBTTracker *)pSource->m_pTrackerList.GetAt( nCount ) );
00163 m_pTrackerList.Add( pTracker );
00164 }
00165 }
00166
00168
00169
00170 void CBTInfo::Serialize(CArchive& ar)
00171 {
00172 int nVersion = 3;
00173
00174 if ( ar.IsStoring() )
00175 {
00176 ar << nVersion;
00177
00178 ar << m_bValid;
00179 if ( ! m_bValid ) return;
00180
00181 ar.Write( &m_pInfoSHA1, sizeof(SHA1) );
00182
00183 ar << m_nTotalSize;
00184 ar << m_nBlockSize;
00185 ar << m_nBlockCount;
00186 ar.Write( m_pBlockSHA1, m_nBlockCount * sizeof(SHA1) );
00187
00188 ar << m_sName;
00189
00190 ar << m_nEncoding;
00191 ar << m_sComment;
00192 ar << m_tCreationDate;
00193 ar << m_sCreatedBy;
00194
00195 ar.WriteCount( m_nFiles );
00196 for ( int nFile = 0 ; nFile < m_nFiles ; nFile++ )
00197 m_pFiles[ nFile ].Serialize( ar, nVersion );
00198
00199 ar << m_sTracker;
00200 }
00201 else
00202 {
00203 ar >> nVersion;
00204 if ( nVersion < 1 ) AfxThrowUserException();
00205
00206 ar >> m_bValid;
00207 if ( ! m_bValid ) return;
00208
00209 ar.Read( &m_pInfoSHA1, sizeof(SHA1) );
00210
00211 if ( nVersion >= 2 )
00212 {
00213 ar >> m_nTotalSize;
00214 }
00215 else
00216 {
00217 DWORD nTotalSize;
00218 ar >> nTotalSize;
00219 m_nTotalSize = nTotalSize;
00220 }
00221
00222 ar >> m_nBlockSize;
00223 ar >> m_nBlockCount;
00224
00225 m_pBlockSHA1 = new SHA1[ (DWORD)m_nBlockCount ];
00226 ar.Read( m_pBlockSHA1, (DWORD)m_nBlockCount * sizeof(SHA1) );
00227
00228 ar >> m_sName;
00229
00230 if ( nVersion >= 3 )
00231 {
00232 ar >> m_nEncoding;
00233 ar >> m_sComment;
00234 ar >> m_tCreationDate;
00235 ar >> m_sCreatedBy;
00236 }
00237
00238 m_nFiles = ar.ReadCount();
00239 m_pFiles = new CBTFile[ m_nFiles ];
00240 for ( int nFile = 0 ; nFile < m_nFiles ; nFile++ )
00241 m_pFiles[ nFile ].Serialize( ar, nVersion );
00242
00243 ar >> m_sTracker;
00244 }
00245 }
00246
00248
00249
00250 BOOL CBTInfo::LoadTorrentFile(LPCTSTR pszFile)
00251 {
00252 CFile pFile;
00253
00254 if ( pFile.Open( pszFile, CFile::modeRead|CFile::shareDenyNone ) )
00255 {
00256 DWORD nLength = (DWORD)pFile.GetLength();
00257
00258 if ( nLength < 20 * 1024 * 1024 )
00259 {
00260 m_pSource.Clear();
00261 m_pSource.EnsureBuffer( nLength );
00262 pFile.Read( m_pSource.m_pBuffer, nLength );
00263 m_pSource.m_nLength = nLength;
00264
00265 return LoadTorrentBuffer( &m_pSource );
00266 }
00267 }
00268 else
00269 {
00270 DWORD nError = GetLastError();
00271 }
00272
00273 return FALSE;
00274 }
00275
00277
00278
00279 BOOL CBTInfo::SaveTorrentFile(LPCTSTR pszPath)
00280 {
00281 ASSERT( pszPath != NULL );
00282 if ( ! IsAvailable() ) return FALSE;
00283 if ( m_pSource.m_nLength == 0 ) return FALSE;
00284
00285 CString strPath;
00286 strPath.Format( _T("%s\\%s.torrent"), pszPath, (LPCTSTR)CDownloadTask::SafeFilename( m_sName ) );
00287
00288 CFile pFile;
00289 if ( ! pFile.Open( strPath, CFile::modeWrite | CFile::modeCreate ) ) return FALSE;
00290
00291 pFile.Write( m_pSource.m_pBuffer, m_pSource.m_nLength );
00292 pFile.Close();
00293
00294 return TRUE;
00295 }
00296
00298
00299
00300 BOOL CBTInfo::LoadTorrentBuffer(CBuffer* pBuffer)
00301 {
00302 CBENode* pNode = CBENode::Decode( pBuffer );
00303 if ( pNode == NULL ) return FALSE;
00304 BOOL bSuccess = LoadTorrentTree( pNode );
00305 delete pNode;
00306 return bSuccess;
00307 }
00308
00310
00311
00312 BOOL CBTInfo::LoadTorrentTree(CBENode* pRoot)
00313 {
00314 Clear();
00315
00316 if ( ! pRoot->IsType( CBENode::beDict ) ) return FALSE;
00317
00318
00319 m_nEncoding = 0;
00320 CBENode* pEncoding = pRoot->GetNode( "codepage" );
00321 if ( ( pEncoding ) && ( pEncoding->IsType( CBENode::beInt ) ) )
00322 {
00323
00324 m_nEncoding = (UINT)pEncoding->GetInt();
00325 }
00326 else
00327 {
00328
00329 pEncoding = pRoot->GetNode( "encoding" );
00330 if ( ( pEncoding ) && ( pEncoding->IsType( CBENode::beString ) ) )
00331 {
00332 CString strEncoding = pEncoding->GetString();
00333
00334 if ( strEncoding.GetLength() < 3 )
00335 theApp.Message( MSG_ERROR, _T("Torrent 'encoding' node too short") );
00336 else if ( _tcsistr( strEncoding.GetString() , _T("UTF-8") ) != NULL ||
00337 _tcsistr( strEncoding.GetString() , _T("UTF8") ) != NULL )
00338 m_nEncoding = CP_UTF8;
00339 else if ( _tcsistr( strEncoding.GetString() , _T("ANSI") ) != NULL )
00340 m_nEncoding = CP_ACP;
00341 else if ( _tcsistr( strEncoding.GetString() , _T("BIG5") ) != NULL )
00342 m_nEncoding = 950;
00343 else if ( _tcsistr( strEncoding.GetString() , _T("Korean") ) != NULL )
00344 m_nEncoding = 949;
00345 else if ( _tcsistr( strEncoding.GetString() , _T("UHC") ) != NULL )
00346 m_nEncoding = 949;
00347 else if ( _tcsistr( strEncoding.GetString() , _T("Chinese") ) != NULL )
00348 m_nEncoding = 936;
00349 else if ( _tcsistr( strEncoding.GetString() , _T("GB2312") ) != NULL )
00350 m_nEncoding = 936;
00351 else if ( _tcsistr( strEncoding.GetString() , _T("GBK") ) != NULL )
00352 m_nEncoding = 936;
00353 else if ( _tcsistr( strEncoding.GetString() , _T("Japanese") ) != NULL )
00354 m_nEncoding = 932;
00355 else if ( _tcsistr( strEncoding.GetString() , _T("Shift-JIS") ) != NULL )
00356 m_nEncoding = 932;
00357 else if ( _tcsnicmp( strEncoding.GetString() , _T("Windows-"), 8 ) == 0 )
00358 {
00359 UINT nEncoding = 0;
00360 strEncoding = strEncoding.Mid( 8 );
00361 if ( ( _stscanf( strEncoding, _T("%u"), &nEncoding ) == 1 ) && ( nEncoding > 0 ) )
00362 {
00363 m_nEncoding = nEncoding;
00364 }
00365 }
00366 else if ( _tcsnicmp( strEncoding.GetString() , _T("CP"), 2 ) == 0 )
00367 {
00368 UINT nEncoding = 0;
00369 strEncoding = strEncoding.Mid( 2 );
00370 if ( ( _stscanf( strEncoding, _T("%u"), &nEncoding ) == 1 ) && ( nEncoding > 0 ) )
00371 {
00372 m_nEncoding = nEncoding;
00373 }
00374 }
00375 }
00376 }
00377
00378
00379 m_sComment = pRoot->GetStringFromSubNode( "comment", m_nEncoding, &m_bEncodingError );
00380
00381
00382 CBENode* pDate = pRoot->GetNode( "creation date" );
00383 if ( ( pDate ) && ( pDate->IsType( CBENode::beInt ) ) )
00384 {
00385 m_tCreationDate = (DWORD)pDate->GetInt();
00386
00387
00388 }
00389
00390
00391 m_sCreatedBy = pRoot->GetStringFromSubNode( "created by", m_nEncoding, &m_bEncodingError );
00392
00393
00394
00395
00396 CBENode* pAnnounceList = pRoot->GetNode( "announce-list" );
00397 if ( ( pAnnounceList ) && ( pAnnounceList->IsType( CBENode::beList ) ) )
00398 {
00399
00400 srand( GetTickCount() );
00401
00402 for ( int nTier = 0 ; nTier < pAnnounceList->GetCount() ; nTier++ )
00403 {
00404 CBENode* pSubList = pAnnounceList->GetNode( nTier );
00405 if ( ( pSubList ) && ( pSubList->IsType( CBENode::beList ) ) )
00406 {
00407 CStringList pTrackers;
00408
00409 for ( int nTracker = 0 ; nTracker < pSubList->GetCount() ; nTracker++ )
00410 {
00411 CBENode* pTracker = pSubList->GetNode( nTracker );
00412 if ( ( pTracker ) && ( pTracker->IsType( CBENode::beString ) ) )
00413 {
00414 CString strTracker = pTracker->GetString();
00415
00416 if ( strTracker.Find( _T("http") ) == 0 )
00417 {
00418
00419 pTrackers.AddTail( strTracker );
00420 }
00421 }
00422 }
00423
00424 if ( ! pTrackers.IsEmpty() )
00425 {
00426
00427 if ( pTrackers.GetCount() > 1 )
00428 {
00429 for ( POSITION pos = pTrackers.GetHeadPosition() ; pos ; )
00430 {
00431 if ( rand() % 2 )
00432 {
00433 CString strTemp;
00434 strTemp = pTrackers.GetAt( pos );
00435 pTrackers.RemoveAt( pos );
00436
00437 if ( rand() % 2 )
00438 pTrackers.AddHead( strTemp );
00439 else
00440 pTrackers.AddTail( strTemp );
00441 }
00442 pTrackers.GetNext( pos );
00443 }
00444 }
00445
00446
00447 for ( POSITION pos = pTrackers.GetHeadPosition() ; pos ; )
00448 {
00449 CBTTracker* pTracker = new CBTTracker;
00450 pTracker->m_sAddress = pTrackers.GetNext( pos );
00451 pTracker->m_nTier = nTier;
00452
00453 m_pTrackerList.Add( pTracker );
00454
00455 m_sTracker = pTracker->m_sAddress;
00456 }
00457
00458 pTrackers.RemoveAll();
00459 }
00460 }
00461 }
00462 }
00463
00464
00465
00466 CBENode* pAnnounce = pRoot->GetNode( "announce" );
00467 if ( pAnnounce->IsType( CBENode::beString ) )
00468 {
00469
00470 CString strTracker = pAnnounce->GetString();
00471
00472
00473 if ( strTracker.Find( _T("http") ) == 0 )
00474 {
00475 m_sTracker = strTracker;
00476
00477 m_pAnnounceTracker = new CBTTracker;
00478 m_pAnnounceTracker->m_sAddress = strTracker;
00479 }
00480 else
00481 {
00482 m_bEncodingError = TRUE;
00483 }
00484 }
00485
00486
00487 CBENode* pInfo = pRoot->GetNode( "info" );
00488 if ( ! pInfo->IsType( CBENode::beDict ) ) return FALSE;
00489
00490
00491 m_sName = pInfo->GetStringFromSubNode( "name", m_nEncoding, &m_bEncodingError );
00492
00493 if ( m_sName.IsEmpty() ) m_sName.Format( _T("Unnamed_Torrent_%i"), (int)rand() );
00494
00495
00496 CBENode* pPL = pInfo->GetNode( "piece length" );
00497 if ( ! pPL->IsType( CBENode::beInt ) ) return FALSE;
00498 m_nBlockSize = (DWORD)pPL->GetInt();
00499 if ( ! m_nBlockSize ) return FALSE;
00500
00501 CBENode* pHash = pInfo->GetNode( "pieces" );
00502 if ( ! pHash->IsType( CBENode::beString ) ) return FALSE;
00503 if ( pHash->m_nValue % sizeof(SHA1) ) return FALSE;
00504 m_nBlockCount = (DWORD)( pHash->m_nValue / sizeof(SHA1) );
00505 if ( ! m_nBlockCount || m_nBlockCount > 209716 ) return FALSE;
00506
00507 m_pBlockSHA1 = new SHA1[ m_nBlockCount ];
00508
00509 for ( DWORD nBlock = 0 ; nBlock < m_nBlockCount ; nBlock++ )
00510 {
00511 SHA1* pSource = (SHA1*)pHash->m_pValue;
00512 CopyMemory( m_pBlockSHA1 + nBlock, pSource + nBlock, sizeof(SHA1) );
00513 }
00514
00515
00516 if ( CBENode* pSHA1 = pInfo->GetNode( "sha1" ) )
00517 {
00518 if ( ! pSHA1->IsType( CBENode::beString ) || pSHA1->m_nValue != sizeof(SHA1) ) return FALSE;
00519 m_bDataSHA1 = TRUE;
00520 CopyMemory( &m_pDataSHA1, pSHA1->m_pValue, sizeof(SHA1) );
00521 }
00522
00523 if ( CBENode* pED2K = pInfo->GetNode( "ed2k" ) )
00524 {
00525 if ( ! pED2K->IsType( CBENode::beString ) || pED2K->m_nValue != sizeof(MD4) ) return FALSE;
00526 m_bDataED2K = TRUE;
00527 CopyMemory( &m_pDataED2K, pED2K->m_pValue, sizeof(MD4) );
00528 }
00529
00530 if ( CBENode* pTiger = pInfo->GetNode( "tiger" ) )
00531 {
00532 if ( ! pTiger->IsType( CBENode::beString ) || pTiger->m_nValue != sizeof(TIGEROOT) ) return FALSE;
00533 m_bDataTiger = TRUE;
00534 CopyMemory( &m_pDataTiger, pTiger->m_pValue, sizeof(TIGEROOT) );
00535 }
00536
00537
00538 if ( CBENode* pLength = pInfo->GetNode( "length" ) )
00539 {
00540 if ( ! pLength->IsType( CBENode::beInt ) ) return FALSE;
00541 m_nTotalSize = pLength->GetInt();
00542 if ( ! m_nTotalSize ) return FALSE;
00543
00544 m_nFiles = 1;
00545 m_pFiles = new CBTFile[ m_nFiles ];
00546 m_pFiles[0].m_sPath = m_sName;
00547 m_pFiles[0].m_nSize = m_nTotalSize;
00548 m_pFiles[0].m_bSHA1 = m_bDataSHA1;
00549 m_pFiles[0].m_pSHA1 = m_pDataSHA1;
00550 }
00551 else if ( CBENode* pFiles = pInfo->GetNode( "files" ) )
00552 {
00553 CString strPath;
00554
00555 if ( ! pFiles->IsType( CBENode::beList ) ) return FALSE;
00556 m_nFiles = pFiles->GetCount();
00557 if ( ! m_nFiles || m_nFiles > 8192 ) return FALSE;
00558 m_pFiles = new CBTFile[ m_nFiles ];
00559
00560 m_nTotalSize = 0;
00561
00562 for ( int nFile = 0 ; nFile < m_nFiles ; nFile++ )
00563 {
00564 CBENode* pFile = pFiles->GetNode( nFile );
00565 if ( ! pFile->IsType( CBENode::beDict ) ) return FALSE;
00566
00567 CBENode* pLength = pFile->GetNode( "length" );
00568 if ( ! pLength->IsType( CBENode::beInt ) ) return FALSE;
00569 m_pFiles[ nFile ].m_nSize = pLength->GetInt();
00570
00571
00572 strPath.Empty();
00573 CBENode* pPath;
00574
00575 if ( Settings.BitTorrent.TorrentExtraKeys )
00576 {
00577 pPath = pFile->GetNode( "path.utf-8" );
00578 if ( pPath )
00579 {
00580 if ( ! pPath->IsType( CBENode::beList ) ) return FALSE;
00581 if ( pPath->GetCount() > 32 ) return FALSE;
00582 CBENode* pPart = pPath->GetNode( 0 );
00583 if ( pPart->IsType( CBENode::beString ) ) strPath = pPart->GetString();
00584 }
00585 }
00586
00587
00588
00589 pPath = pFile->GetNode( "path" );
00590
00591 if ( ! pPath ) return FALSE;
00592 if ( ! pPath->IsType( CBENode::beList ) ) return FALSE;
00593
00594 CBENode* pPart = pPath->GetNode( 0 );
00595 if ( pPart->IsType( CBENode::beString ) )
00596 {
00597 if ( ! IsValid( strPath ) )
00598 {
00599
00600 strPath = pPart->GetString();
00601 }
00602 else
00603 {
00604
00605 CString strCheck = pPart->GetString();
00606 if ( strPath != strCheck ) m_bEncodingError = TRUE;
00607
00608 pPath = pFile->GetNode( "path.utf-8" );
00609 }
00610 }
00611
00612
00613 if ( ( ! IsValid( strPath ) ) )
00614 {
00615
00616 m_bEncodingError = TRUE;
00617
00618 pPath = pFile->GetNode( "path" );
00619 if ( pPath )
00620 {
00621 CBENode* pPart = pPath->GetNode( 0 );
00622 if ( pPart->IsType( CBENode::beString ) ) strPath = pPart->DecodeString(m_nEncoding);
00623 }
00624 }
00625
00626 if ( ! pPath ) return FALSE;
00627 if ( ! pPath->IsType( CBENode::beList ) ) return FALSE;
00628 if ( pPath->GetCount() > 32 ) return FALSE;
00629 if ( _tcsicmp( strPath.GetString() , _T("#ERROR#") ) == 0 ) return FALSE;
00630
00631
00632
00633
00634 m_pFiles[ nFile ].m_sPath = CDownloadTask::SafeFilename( m_sName );
00635
00636 for ( int nPath = 0 ; nPath < pPath->GetCount() ; nPath++ )
00637 {
00638 CBENode* pPart = pPath->GetNode( nPath );
00639 if ( ! pPart->IsType( CBENode::beString ) ) return FALSE;
00640
00641 if ( m_pFiles[ nFile ].m_sPath.GetLength() )
00642 m_pFiles[ nFile ].m_sPath += '\\';
00643
00644
00645 strPath = pPart->GetString();
00646 strPath = CDownloadTask::SafeFilename( pPart->GetString() );
00647
00648 if ( _tcsicmp( strPath.GetString() , _T("#ERROR#") ) == 0 )
00649 strPath = CDownloadTask::SafeFilename( pPart->DecodeString( m_nEncoding ) );
00650
00651 m_pFiles[ nFile ].m_sPath += strPath;
00652 }
00653
00654 if ( CBENode* pSHA1 = pFile->GetNode( "sha1" ) )
00655 {
00656 if ( ! pSHA1->IsType( CBENode::beString ) || pSHA1->m_nValue != sizeof(SHA1) ) return FALSE;
00657 m_pFiles[ nFile ].m_bSHA1 = TRUE;
00658 CopyMemory( &m_pFiles[ nFile ].m_pSHA1, pSHA1->m_pValue, sizeof(SHA1) );
00659 }
00660
00661 if ( CBENode* pED2K = pInfo->GetNode( "ed2k" ) )
00662 {
00663 if ( ! pED2K->IsType( CBENode::beString ) || pED2K->m_nValue != sizeof(MD4) ) return FALSE;
00664 m_pFiles[ nFile ].m_bED2K = TRUE;
00665 CopyMemory( &m_pFiles[ nFile].m_pED2K, pED2K->m_pValue, sizeof(MD4) );
00666 }
00667
00668 if ( CBENode* pTiger = pInfo->GetNode( "tiger" ) )
00669 {
00670 if ( ! pTiger->IsType( CBENode::beString ) || pTiger->m_nValue != sizeof(TIGEROOT) ) return FALSE;
00671 m_pFiles[ nFile ].m_bTiger = TRUE;
00672 CopyMemory( &m_pFiles[ nFile ].m_pTiger, pTiger->m_pValue, sizeof(TIGEROOT) );
00673 }
00674
00675 m_nTotalSize += m_pFiles[ nFile ].m_nSize;
00676 }
00677
00678 if ( m_nFiles == 1 )
00679 {
00680
00681
00682
00683 m_sName = strPath;
00684
00685
00686 if ( m_pFiles[0].m_bSHA1 )
00687 {
00688 m_bDataSHA1 = m_pFiles[0].m_bSHA1;
00689 m_pDataSHA1 = m_pFiles[0].m_pSHA1;
00690 }
00691 else if ( m_bDataSHA1 )
00692 {
00693 m_pFiles[0].m_bSHA1 = m_bDataSHA1;
00694 m_pFiles[0].m_pSHA1 = m_pDataSHA1;
00695
00696 }
00697 if ( m_pFiles[0].m_bED2K )
00698 {
00699 m_bDataED2K = m_pFiles[0].m_bED2K;
00700 m_pDataED2K = m_pFiles[0].m_pED2K;
00701 }
00702 else if ( m_bDataED2K )
00703 {
00704 m_pFiles[0].m_bED2K = m_bDataED2K;
00705 m_pFiles[0].m_pED2K = m_pDataED2K;
00706 }
00707 if ( m_pFiles[0].m_bTiger )
00708 {
00709 m_bDataTiger = m_pFiles[0].m_bTiger;
00710 m_pDataTiger = m_pFiles[0].m_pTiger;
00711 }
00712 else if ( m_bDataTiger )
00713 {
00714 m_pFiles[0].m_bTiger = m_bDataTiger;
00715 m_pFiles[0].m_pTiger = m_pDataTiger;
00716 }
00717 }
00718 }
00719 else
00720 {
00721 return FALSE;
00722 }
00723
00724 if ( ( m_nTotalSize + m_nBlockSize - 1 ) / m_nBlockSize != m_nBlockCount )
00725 return FALSE;
00726
00727 if ( ! CheckFiles() ) return FALSE;
00728
00729 pInfo->GetSHA1( &m_pInfoSHA1 );
00730 m_bValid = TRUE;
00731
00732 return TRUE;
00733 }
00734
00736
00737
00738 BOOL CBTInfo::CheckFiles()
00739 {
00740 for ( int nFile = 0 ; nFile < m_nFiles ; nFile++ )
00741 {
00742 m_pFiles[ nFile ].m_sPath.TrimLeft();
00743 m_pFiles[ nFile ].m_sPath.TrimRight();
00744
00745 LPCTSTR pszPath = m_pFiles[ nFile ].m_sPath;
00746
00747 if ( pszPath == NULL || *pszPath == 0 ) return FALSE;
00748 if ( pszPath[1] == ':' ) return FALSE;
00749 if ( *pszPath == '\\' || *pszPath == '/' ) return FALSE;
00750 if ( _tcsstr( pszPath, _T("..\\") ) != NULL ) return FALSE;
00751 if ( _tcsstr( pszPath, _T("../") ) != NULL ) return FALSE;
00752 }
00753
00754 return ( m_nFiles > 0 );
00755 }
00756
00758
00759
00760 void CBTInfo::BeginBlockTest()
00761 {
00762 ASSERT( IsAvailable() );
00763 ASSERT( m_pBlockSHA1 != NULL );
00764
00765 m_pTestSHA1.Reset();
00766 m_nTestByte = 0;
00767 }
00768
00769 void CBTInfo::AddToTest(LPCVOID pInput, DWORD nLength)
00770 {
00771 if ( nLength == 0 ) return;
00772
00773 ASSERT( IsAvailable() );
00774 ASSERT( m_pBlockSHA1 != NULL );
00775 ASSERT( m_nTestByte + nLength <= m_nBlockSize );
00776
00777 m_pTestSHA1.Add( pInput, nLength );
00778 m_nTestByte += nLength;
00779 }
00780
00781 BOOL CBTInfo::FinishBlockTest(DWORD nBlock)
00782 {
00783 ASSERT( IsAvailable() );
00784 ASSERT( m_pBlockSHA1 != NULL );
00785
00786 if ( nBlock >= m_nBlockCount ) return FALSE;
00787
00788 SHA1 pSHA1;
00789 m_pTestSHA1.Finish();
00790 m_pTestSHA1.GetHash( &pSHA1 );
00791
00792 return pSHA1 == m_pBlockSHA1[ nBlock ];
00793 }
00794
00795
00797
00798
00799 void CBTInfo::CBTFile::Copy(CBTFile* pSource)
00800 {
00801 m_sPath = pSource->m_sPath;
00802 m_nSize = pSource->m_nSize;
00803 m_bSHA1 = pSource->m_bSHA1;
00804 m_pSHA1 = pSource->m_pSHA1;
00805 m_bED2K = pSource->m_bED2K;
00806 m_pED2K = pSource->m_pED2K;
00807 m_bTiger = pSource->m_bTiger;
00808 m_pTiger = pSource->m_pTiger;
00809 }
00810
00812
00813
00814 void CBTInfo::CBTFile::Serialize(CArchive& ar, int nVersion)
00815 {
00816 if ( ar.IsStoring() )
00817 {
00818 ar << m_nSize;
00819 ar << m_sPath;
00820 ar << m_bSHA1;
00821 if ( m_bSHA1 ) ar.Write( &m_pSHA1, sizeof(SHA1) );
00822 }
00823 else
00824 {
00825 if ( nVersion >= 2 )
00826 {
00827 ar >> m_nSize;
00828 }
00829 else
00830 {
00831 DWORD nSize;
00832 ar >> nSize;
00833 m_nSize = nSize;
00834 }
00835
00836 ar >> m_sPath;
00837 ar >> m_bSHA1;
00838 if ( m_bSHA1 ) ar.Read( &m_pSHA1, sizeof(SHA1) );
00839 }
00840 }
00841
00843
00844
00845 CBTInfo::CBTTracker::CBTTracker()
00846 {
00847 m_sAddress.Empty();
00848 m_tLastAccess = 0;
00849 m_tLastSuccess = 0;
00850 m_tLastFail = 0;
00851 m_nFailures = 0;
00852 m_nTier = 0;
00853 m_nTier = 0;
00854 m_nType = 0;
00855 }
00856
00857 CBTInfo::CBTTracker::~CBTTracker()
00858 {
00859 }
00860
00861
00863
00864
00865 void CBTInfo::CBTTracker::Copy(CBTTracker* pSource)
00866 {
00867 m_sAddress = pSource->m_sAddress;
00868 m_tLastAccess = pSource->m_tLastAccess;
00869 m_tLastSuccess = pSource->m_tLastSuccess;
00870 m_tLastFail = pSource->m_tLastFail;
00871 m_nFailures = pSource->m_nFailures;
00872 m_nTier = pSource->m_nTier;
00873 m_nType = pSource->m_nType;
00874 }
00875
00877
00878
00879 void CBTInfo::CBTTracker::Serialize(CArchive& ar, int nVersion)
00880 {
00881 if ( ar.IsStoring() )
00882 {
00883 ar << m_sAddress;
00884 ar << m_tLastAccess;
00885 ar << m_tLastSuccess;
00886 ar << m_tLastFail;
00887 ar << m_nFailures;
00888 ar << m_nTier;
00889 ar << m_nType;
00890 }
00891 else
00892 {
00893 ar >> m_sAddress;
00894 ar >> m_tLastAccess;
00895 ar >> m_tLastSuccess;
00896 ar >> m_tLastFail;
00897 ar >> m_nFailures;
00898 ar << m_nTier;
00899 ar >> m_nType;
00900
00901 }
00902 }
00903