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

BTInfo.cpp

Go to the documentation of this file.
00001 //
00002 // BTInfo.cpp
00003 //
00004 // Copyright (c) Shareaza Development Team, 2002-2005.
00005 // This file is part of SHAREAZA (www.shareaza.com)
00006 //
00007 // Shareaza is free software; you can redistribute it
00008 // and/or modify it under the terms of the GNU General Public License
00009 // as published by the Free Software Foundation; either version 2 of
00010 // the License, or (at your option) any later version.
00011 //
00012 // Shareaza is distributed in the hope that it will be useful,
00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 // GNU General Public License for more details.
00016 //
00017 // You should have received a copy of the GNU General Public License
00018 // along with Shareaza; if not, write to the Free Software
00019 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
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 // CBTInfo construction
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 // CBTInfo clear
00077 
00078 void CBTInfo::Clear()
00079 {
00080         // Delete SHA1
00081         if ( m_pBlockSHA1 != NULL ) delete [] m_pBlockSHA1;
00082         // Delete files
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         // Delete trackers
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 // CBTInfo copy
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         // Copy trackers
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 // CBTInfo serialize
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 // CBTInfo load .torrent file
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 // CBTInfo save .torrent file
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 // CBTInfo load torrent info from buffer
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 // CBTInfo load torrent info from tree
00311 
00312 BOOL CBTInfo::LoadTorrentTree(CBENode* pRoot)
00313 {
00314         Clear();
00315         
00316         if ( ! pRoot->IsType( CBENode::beDict ) ) return FALSE;
00317 
00318         // Get the encoding (from torrents that have it)
00319         m_nEncoding = 0;
00320         CBENode* pEncoding = pRoot->GetNode( "codepage" );
00321         if ( ( pEncoding ) &&  ( pEncoding->IsType( CBENode::beInt )  ) )
00322         {
00323                 // "codepage" style (UNIT giving the exact Windows code page)
00324                 m_nEncoding = (UINT)pEncoding->GetInt();
00325         }
00326         else
00327         {
00328                 // "encoding" style (String representing the encoding to use)
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         // Get the comments (if present)
00379         m_sComment = pRoot->GetStringFromSubNode( "comment", m_nEncoding, &m_bEncodingError );
00380 
00381         // Get the creation date (if present)
00382         CBENode* pDate = pRoot->GetNode( "creation date" );
00383         if ( ( pDate ) &&  ( pDate->IsType( CBENode::beInt )  ) )
00384         {
00385                 m_tCreationDate = (DWORD)pDate->GetInt();
00386                 // CTime pTime( (time_t)m_tCreationDate );
00387                 // theApp.Message( MSG_SYSTEM, pTime.Format( _T("%Y-%m-%d %H:%M:%S") ) );
00388         }
00389 
00390         // Get the creator (if present)
00391         m_sCreatedBy = pRoot->GetStringFromSubNode( "created by", m_nEncoding, &m_bEncodingError );
00392 
00393         // Get announce-list (if present)       
00394         // ******************************************************************
00395         // Note: This isn't supported yet! (This section does nothing but read data.)
00396         CBENode* pAnnounceList = pRoot->GetNode( "announce-list" );
00397         if ( ( pAnnounceList ) && ( pAnnounceList->IsType( CBENode::beList ) ) )
00398         {
00399                 // Initialise random number generator
00400                 srand( GetTickCount() );
00401                 // Loop through all the tiers
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                                 // Read in the trackers
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                                                 // Check tracker is valid
00416                                                 if ( strTracker.Find( _T("http") ) == 0 ) 
00417                                                 {
00418                                                         // Store tracker
00419                                                         pTrackers.AddTail( strTracker );
00420                                                 }
00421                                         }
00422                                 }
00423 
00424                                 if ( ! pTrackers.IsEmpty() )
00425                                 {
00426                                         // Randomise the tracker order in this tier
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                                         // Store the trackers
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; // **** Debug check
00456                                         }
00457                                         // Delete temporary storage
00458                                         pTrackers.RemoveAll();
00459                                 }
00460                         }
00461                 }
00462         }
00463         //******************************************************************
00464 
00465         // Get announce
00466         CBENode* pAnnounce = pRoot->GetNode( "announce" );
00467         if ( pAnnounce->IsType( CBENode::beString ) )
00468         {
00469                 // Get the tracker
00470                 CString strTracker = pAnnounce->GetString();
00471 
00472                 // Store it if it's valid. (Some torrents have invalid trackers)
00473                 if ( strTracker.Find( _T("http") ) == 0 ) 
00474                 {
00475                         m_sTracker = strTracker;
00476                         // Create the announce tracker object
00477                         m_pAnnounceTracker = new CBTTracker;
00478                         m_pAnnounceTracker->m_sAddress = strTracker;
00479                 }
00480                 else 
00481                 {
00482                         m_bEncodingError = TRUE;
00483                 }
00484         }
00485 
00486         // Get the info node
00487         CBENode* pInfo = pRoot->GetNode( "info" );
00488         if ( ! pInfo->IsType( CBENode::beDict ) ) return FALSE;
00489         
00490         // Get the name
00491         m_sName = pInfo->GetStringFromSubNode( "name", m_nEncoding, &m_bEncodingError );
00492         // If we still don't have a name, generate one
00493         if ( m_sName.IsEmpty() ) m_sName.Format( _T("Unnamed_Torrent_%i"), (int)rand() );
00494         
00495         // Get the piece stuff
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         // Hash info
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         // Details on file (or files).
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                         // Try path.utf8 if it's set
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                         // Get the regular path
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                                         // Get the path
00600                                         strPath = pPart->GetString();
00601                                 }
00602                                 else
00603                                 {
00604                                         // Check the path matches the .utf path
00605                                         CString strCheck =  pPart->GetString();
00606                                         if ( strPath != strCheck ) m_bEncodingError = TRUE;
00607                                         // Switch back to the UTF-8 path
00608                                         pPath = pFile->GetNode( "path.utf-8" );
00609                                 }
00610                         }
00611 
00612                         // If that didn't work, try decoding the path
00613                         if ( ( ! IsValid( strPath ) )  )
00614                         {
00615                                 // There was an error reading the path
00616                                 m_bEncodingError = TRUE;
00617                                 // Open path node
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                         // Hack to prefix all
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                                 // Get the path
00645                                 strPath = pPart->GetString();
00646                                 strPath = CDownloadTask::SafeFilename( pPart->GetString() );
00647                                 // Check for encoding error
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                         // Single file in a multi-file torrent
00681 
00682                         // Reset the name
00683                         m_sName = strPath;
00684 
00685                         // Set data/file hashes (if they aren't)
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 // CBTInfo load torrent info from tree
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 // CBTInfo block testing
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 // CBTInfo::CBTFile copy
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 // CBTInfo::CBTFile serialize
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 // CBTInfo::CBTTracker construction and destruction
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 // CBTInfo::CBTTracker copy
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 // CBTInfo::CBTTracker serialize
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 

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