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 "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
00035
00036 CED2K::CED2K()
00037 {
00038 m_pList = NULL;
00039 m_nList = 0;
00040 }
00041
00042 CED2K::~CED2K()
00043 {
00044 Clear();
00045 }
00046
00048
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
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
00103
00104 BOOL CED2K::GetRoot(MD4* pHash) const
00105 {
00106
00107 *pHash = m_pRoot;
00108 return TRUE;
00109 }
00110
00112
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
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
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
00202
00203 void CED2K::BeginBlockTest()
00204 {
00205 ASSERT( IsAvailable() );
00206
00207 m_pSegment.Reset();
00208 m_nCurByte = 0;
00209 }
00210
00212
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
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
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
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
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
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
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