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

ED2K.cpp

Go to the documentation of this file.
00001 //
00002 // ED2K.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 "ED2K.h"
00025 
00026 #ifdef _DEBUG
00027 #undef THIS_FILE
00028 static char THIS_FILE[]=__FILE__;
00029 #define new DEBUG_NEW
00030 #endif
00031 
00032 
00034 // CED2K construction
00035 
00036 CED2K::CED2K()
00037 {
00038         m_pList = NULL;
00039         m_nList = 0;
00040 }
00041 
00042 CED2K::~CED2K()
00043 {
00044         Clear();
00045 }
00046 
00048 // CED2K clear
00049 
00050 void CED2K::Clear()
00051 {
00052         ZeroMemory( &m_pRoot, sizeof(MD4) );
00053         if ( m_pList != NULL ) delete [] m_pList;
00054         m_pList = NULL;
00055         m_nList = 0;
00056 }
00057 
00059 // CED2K serialization
00060 
00061 void CED2K::Serialize(CArchive& ar)
00062 {
00063         if ( ar.IsStoring() )
00064         {
00065                 ar << m_nList;
00066                 if ( m_nList == 0 ) return;
00067 
00068                 ar.Write( &m_pRoot, sizeof(MD4) );
00069                 if ( m_nList > 1 ) ar.Write( m_pList, sizeof(MD4) * m_nList );
00070         }
00071         else
00072         {
00073                 Clear();
00074 
00075                 ar >> m_nList;
00076                 if ( m_nList == 0 ) return;
00077 
00078                 ar.Read( &m_pRoot, sizeof(MD4) );
00079 
00080                 m_pList = new MD4[ m_nList ];
00081 
00082                 if ( m_nList > 1 )
00083                 {
00084                         ar.Read( m_pList, sizeof(MD4) * m_nList );
00085                 }
00086                 else if ( m_nList == 1 )
00087                 {
00088                         *m_pList = m_pRoot;
00089                 }
00090         }
00091 }
00092 
00093 DWORD CED2K::GetSerialSize() const
00094 {
00095         DWORD nSize = 4;
00096         if ( m_nList > 0 ) nSize += sizeof(MD4);
00097         if ( m_nList > 1 ) nSize += sizeof(MD4) * m_nList;
00098         return nSize;
00099 }
00100 
00102 // CED2K root value
00103 
00104 BOOL CED2K::GetRoot(MD4* pHash) const
00105 {
00106         // if ( m_nList == 0 ) return FALSE;
00107         *pHash = m_pRoot;
00108         return TRUE;
00109 }
00110 
00112 // CED2K file hashing - begin
00113 
00114 void CED2K::BeginFile(QWORD nLength)
00115 {
00116         ASSERT( ! IsAvailable() );
00117 
00118         m_nList = (DWORD)( ( nLength + ED2K_PART_SIZE - 1 ) / ED2K_PART_SIZE );
00119         m_pList = new MD4[ m_nList ];
00120 
00121         m_pSegment.Reset();
00122         m_nCurHash = 0;
00123         m_nCurByte = 0;
00124 }
00125 
00127 // CED2K file hashing - add data
00128 
00129 void CED2K::AddToFile(LPCVOID pInput, DWORD nLength)
00130 {
00131         if ( nLength == 0 ) return;
00132 
00133         ASSERT( IsAvailable() );
00134         ASSERT( m_nCurHash < m_nList );
00135         ASSERT( m_nCurByte < ED2K_PART_SIZE );
00136 
00137         const BYTE* pBytes = (const BYTE*)pInput;
00138 
00139         while ( nLength > 0 )
00140         {
00141                 DWORD nInThisHash       = ( ED2K_PART_SIZE - m_nCurByte );
00142                 DWORD nToProcess        = min( nInThisHash, nLength );
00143 
00144                 m_pSegment.Add( pBytes, nToProcess );
00145 
00146                 m_nCurByte += nToProcess;
00147                 nLength -= nToProcess;
00148                 pBytes += nToProcess;
00149 
00150                 if ( m_nCurByte >= ED2K_PART_SIZE )
00151                 {
00152                         ASSERT( m_nCurHash < m_nList );
00153                         m_pSegment.Finish();
00154                         m_pSegment.GetHash( &m_pList[ m_nCurHash ] );
00155                         m_pSegment.Reset();
00156                         m_nCurHash++;
00157                         m_nCurByte = 0;
00158                 }
00159         }
00160 }
00161 
00163 // CED2K file hashing - finish
00164 
00165 BOOL CED2K::FinishFile()
00166 {
00167         ASSERT( IsAvailable() );
00168         ASSERT( m_nCurHash <= m_nList );
00169         ASSERT( m_nCurByte < ED2K_PART_SIZE );
00170 
00171         if ( m_nCurHash < m_nList )
00172         {
00173                 m_pSegment.Finish();
00174                 m_pSegment.GetHash( &m_pList[ m_nCurHash++ ] );
00175                 m_pSegment.Reset();
00176         }
00177 
00178         ASSERT( m_nCurHash == m_nList );
00179 
00180         if ( m_nList == 1 )
00181         {
00182                 m_pRoot = *m_pList;
00183         }
00184         else if ( m_nList == 0)
00185         {
00186                 m_pSegment.Finish();
00187                 m_pSegment.GetHash( &m_pRoot );
00188         }
00189         else
00190         {
00191                 CMD4 pOverall;
00192                 pOverall.Add( m_pList, sizeof(MD4) * m_nList );
00193                 pOverall.Finish();
00194                 pOverall.GetHash( &m_pRoot );
00195         }
00196 
00197         return TRUE;
00198 }
00199 
00201 // CED2K block testing - begin
00202 
00203 void CED2K::BeginBlockTest()
00204 {
00205         ASSERT( IsAvailable() );
00206 
00207         m_pSegment.Reset();
00208         m_nCurByte = 0;
00209 }
00210 
00212 // CED2K block testing - add data
00213 
00214 void CED2K::AddToTest(LPCVOID pInput, DWORD nLength)
00215 {
00216         if ( nLength == 0 ) return;
00217 
00218         ASSERT( IsAvailable() );
00219         ASSERT( m_nCurByte + nLength <= ED2K_PART_SIZE );
00220 
00221         m_pSegment.Add( pInput, nLength );
00222         m_nCurByte += nLength;
00223 }
00224 
00226 // CED2K block testing - finish
00227 
00228 BOOL CED2K::FinishBlockTest(DWORD nBlock)
00229 {
00230         ASSERT( IsAvailable() );
00231 
00232         if ( nBlock >= m_nList ) return FALSE;
00233 
00234         MD4 pMD4;
00235         m_pSegment.Finish();
00236         m_pSegment.GetHash( &pMD4 );
00237 
00238         return pMD4 == m_pList[ nBlock ];
00239 }
00240 
00242 // CED2K encode to bytes
00243 
00244 BOOL CED2K::ToBytes(BYTE** ppOutput, DWORD* pnOutput)
00245 {
00246         if ( m_nList == 0 ) return FALSE;
00247 
00248         *pnOutput = sizeof(MD4) * m_nList;
00249         *ppOutput = new BYTE[ *pnOutput ];
00250         CopyMemory( *ppOutput, m_pList, *pnOutput );
00251 
00252         return TRUE;
00253 }
00254 
00255 LPCVOID CED2K::GetRawPtr() const
00256 {
00257         return (LPCVOID)m_pList;
00258 }
00259 
00261 // CED2K decode from bytes
00262 
00263 BOOL CED2K::FromBytes(BYTE* pOutput, DWORD nOutput, QWORD nSize)
00264 {
00265         Clear();
00266 
00267         if ( pOutput == NULL || nOutput == 0 || ( nOutput % sizeof(MD4) ) != 0 ) return FALSE;
00268 
00269         if ( nSize > 0 )
00270         {
00271                 if ( nOutput / sizeof(MD4) != ( nSize + ED2K_PART_SIZE - 1 ) / ED2K_PART_SIZE )
00272                         return FALSE;
00273         }
00274 
00275         m_nList = nOutput / sizeof(MD4);
00276         m_pList = new MD4[ m_nList ];
00277 
00278         CopyMemory( m_pList, pOutput, nOutput );
00279 
00280         if ( m_nList == 1 )
00281         {
00282                 m_pRoot = *m_pList;
00283         }
00284         else
00285         {
00286                 CMD4 pOverall;
00287                 pOverall.Add( m_pList, sizeof(MD4) * m_nList );
00288                 pOverall.Finish();
00289                 pOverall.GetHash( &m_pRoot );
00290         }
00291 
00292         return TRUE;
00293 }
00294 
00295 BOOL CED2K::FromRoot(MD4* pHash)
00296 {
00297         Clear();
00298 
00299         m_nList = 1;
00300         m_pList = new MD4[ m_nList ];
00301 
00302         m_pRoot = *m_pList = *pHash;
00303 
00304         return TRUE;
00305 }
00306 
00308 // CED2K integrity checking
00309 
00310 BOOL CED2K::CheckIntegrity()
00311 {
00312         ASSERT( IsAvailable() );
00313 
00314         if ( m_nList == 1 )
00315         {
00316                 return *m_pList == m_pRoot;
00317         }
00318         else
00319         {
00320                 CMD4 pOverall;
00321                 MD4 pRoot;
00322 
00323                 pOverall.Add( m_pList, sizeof(MD4) * m_nList );
00324                 pOverall.Finish();
00325                 pOverall.GetHash( &pRoot );
00326 
00327                 return pRoot == m_pRoot;
00328         }
00329 }
00330 
00331 
00333 // CED2K convert to string
00334 
00335 CString CED2K::HashToString(const MD4* pHash, BOOL bURN)
00336 {
00337         CString str;
00338 
00339         str.Format( bURN ?
00340                 _T("urn:ed2khash:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x") :
00341                 _T("%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"),
00342                 pHash->n[0], pHash->n[1], pHash->n[2], pHash->n[3],
00343                 pHash->n[4], pHash->n[5], pHash->n[6], pHash->n[7],
00344                 pHash->n[8], pHash->n[9], pHash->n[10], pHash->n[11],
00345                 pHash->n[12], pHash->n[13], pHash->n[14], pHash->n[15] );
00346 
00347         return str;
00348 }
00349 
00351 // CED2K parse from a string
00352 
00353 BOOL CED2K::HashFromString(LPCTSTR pszHash, MD4* pHash)
00354 {
00355         if ( _tcslen( pszHash ) < 32 ) return FALSE;
00356 
00357         BYTE* pOut = (BYTE*)pHash;
00358 
00359         for ( int nPos = 16 ; nPos ; nPos--, pOut++ )
00360         {
00361                 if ( *pszHash >= '0' && *pszHash <= '9' )
00362                         *pOut = ( *pszHash - '0' ) << 4;
00363                 else if ( *pszHash >= 'A' && *pszHash <= 'F' )
00364                         *pOut = ( *pszHash - 'A' + 10 ) << 4;
00365                 else if ( *pszHash >= 'a' && *pszHash <= 'f' )
00366                         *pOut = ( *pszHash - 'a' + 10 ) << 4;
00367                 pszHash++;
00368                 if ( *pszHash >= '0' && *pszHash <= '9' )
00369                         *pOut |= ( *pszHash - '0' );
00370                 else if ( *pszHash >= 'A' && *pszHash <= 'F' )
00371                         *pOut |= ( *pszHash - 'A' + 10 );
00372                 else if ( *pszHash >= 'a' && *pszHash <= 'f' )
00373                         *pOut |= ( *pszHash - 'a' + 10 );
00374                 pszHash++;
00375         }
00376 
00377         return TRUE;
00378 }
00379 
00380 BOOL CED2K::HashFromURN(LPCTSTR pszHash, MD4* pHash)
00381 {
00382         if ( pszHash == NULL ) return FALSE;
00383 
00384         int nLen = _tcslen( pszHash );
00385 
00386         if ( nLen >= 9 + 32 && _tcsnicmp( pszHash, _T("urn:ed2k:"), 9 ) == 0 )
00387         {
00388                 return HashFromString( pszHash + 9, pHash );
00389         }
00390         else if ( nLen >= 5 + 32 && _tcsnicmp( pszHash, _T("ed2k:"), 5 ) == 0 )
00391         {
00392                 return HashFromString( pszHash + 5, pHash );
00393         }
00394         else if ( nLen >= 13 + 32 && _tcsnicmp( pszHash, _T("urn:ed2khash:"), 13 ) == 0 )
00395         {
00396                 return HashFromString( pszHash + 13, pHash );
00397         }
00398         else if ( nLen >= 9 + 32 && _tcsnicmp( pszHash, _T("ed2khash:"), 9 ) == 0 )
00399         {
00400                 return HashFromString( pszHash + 9, pHash );
00401         }
00402 
00403         return FALSE;
00404 }
00405 

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