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 "GGEP.h"
00026 #include "G1Packet.h"
00027 #include "ZLib.h"
00028
00029 #ifdef _DEBUG
00030 #undef THIS_FILE
00031 static char THIS_FILE[]=__FILE__;
00032 #define new DEBUG_NEW
00033 #endif
00034
00035
00037
00038
00039 CGGEPBlock::CGGEPBlock()
00040 {
00041 m_pFirst = m_pLast = NULL;
00042
00043 m_pInput = NULL;
00044 m_nInput = 0;
00045 }
00046
00047 CGGEPBlock::~CGGEPBlock()
00048 {
00049 Clear();
00050 }
00051
00053
00054
00055 void CGGEPBlock::Clear()
00056 {
00057 while ( m_pFirst )
00058 {
00059 CGGEPItem* pNext = m_pFirst->m_pNext;
00060 delete m_pFirst;
00061 m_pFirst = pNext;
00062 }
00063
00064 m_pLast = NULL;
00065 }
00066
00068
00069
00070 CGGEPItem* CGGEPBlock::Add(LPCTSTR pszID)
00071 {
00072 if ( ! pszID || ! *pszID ) return NULL;
00073
00074 CGGEPItem* pItem = new CGGEPItem( pszID );
00075
00076 if ( ! m_pFirst ) m_pFirst = pItem;
00077 if ( m_pLast ) m_pLast->m_pNext = pItem;
00078 m_pLast = pItem;
00079
00080 return pItem;
00081 }
00082
00084
00085
00086 CGGEPItem* CGGEPBlock::Find(LPCTSTR pszID, DWORD nMinLength)
00087 {
00088 if ( ! pszID || ! *pszID ) return NULL;
00089
00090 for ( CGGEPItem* pItem = m_pFirst ; pItem ; pItem = pItem->m_pNext )
00091 {
00092 if ( pItem->m_sID.CompareNoCase( pszID ) == 0 && pItem->m_nLength >= nMinLength )
00093 return pItem;
00094 }
00095
00096 return NULL;
00097 }
00098
00100
00101
00102 CGGEPBlock* CGGEPBlock::FromPacket(CPacket* pPacket)
00103 {
00104 CGGEPBlock* pBlock = new CGGEPBlock();
00105 if ( pBlock->ReadFromPacket( pPacket ) ) return pBlock;
00106 delete pBlock;
00107 return NULL;
00108 }
00109
00111
00112
00113 BOOL CGGEPBlock::ReadFromPacket(CPacket* pPacket)
00114 {
00115 m_pInput = pPacket->m_pBuffer + pPacket->m_nPosition;
00116 m_nInput = pPacket->m_nLength - pPacket->m_nPosition;
00117
00118 BOOL bSuccess = ReadInternal();
00119
00120 pPacket->m_nPosition = pPacket->m_nLength - m_nInput;
00121
00122 return bSuccess;
00123 }
00124
00125 BOOL CGGEPBlock::ReadFromString(LPCTSTR pszData)
00126 {
00127 m_pInput = (BYTE*)pszData;
00128 m_nInput = _tcslen( pszData );
00129
00130 return ReadInternal();
00131 }
00132
00134
00135
00136 BOOL CGGEPBlock::ReadInternal()
00137 {
00138 while ( m_nInput )
00139 {
00140 if ( ReadByte() == GGEP_MAGIC ) break;
00141 }
00142
00143 if ( ! m_nInput ) return FALSE;
00144
00145 while ( m_nInput >= 3 )
00146 {
00147 BYTE nFlags = ReadByte();
00148 if ( ! ( nFlags & GGEP_HDR_IDLEN ) ) return FALSE;
00149
00150 CGGEPItem* pItem = new CGGEPItem();
00151
00152 if ( pItem->ReadFrom( this, nFlags ) )
00153 {
00154 if ( ! m_pFirst ) m_pFirst = pItem;
00155 if ( m_pLast ) m_pLast->m_pNext = pItem;
00156 m_pLast = pItem;
00157 }
00158 else
00159 {
00160 delete pItem;
00161 return FALSE;
00162 }
00163
00164 if ( nFlags & GGEP_HDR_LAST ) return TRUE;
00165 }
00166
00167 return FALSE;
00168 }
00169
00170 BYTE CGGEPBlock::ReadByte()
00171 {
00172 if ( m_nInput < 1 ) AfxThrowUserException();
00173 m_nInput--;
00174 BYTE result = *m_pInput;
00175 m_pInput+= 2;
00176 return result;
00177 }
00178
00180
00181
00182 void CGGEPBlock::Write(CPacket* pPacket)
00183 {
00184 if ( ! m_pFirst ) return;
00185
00186 pPacket->WriteByte( GGEP_MAGIC );
00187
00188 for ( CGGEPItem* pItem = m_pFirst ; pItem ; pItem = pItem->m_pNext )
00189 {
00190 pItem->WriteTo( pPacket );
00191 }
00192
00193 Clear();
00194 }
00195
00196 void CGGEPBlock::Write(CString& str)
00197 {
00198 if ( ! m_pFirst ) return;
00199
00200 str += (TCHAR)GGEP_MAGIC;
00201
00202 for ( CGGEPItem* pItem = m_pFirst ; pItem ; pItem = pItem->m_pNext )
00203 {
00204 pItem->WriteTo( str );
00205 }
00206
00207 Clear();
00208 }
00209
00210
00212
00213
00214 CGGEPItem::CGGEPItem(LPCTSTR pszID)
00215 {
00216 m_pNext = NULL;
00217 m_pBuffer = NULL;
00218 m_nLength = 0;
00219 m_nPosition = 0;
00220
00221 if ( pszID ) m_sID = pszID;
00222 }
00223
00224 CGGEPItem::~CGGEPItem()
00225 {
00226 if ( m_pBuffer ) delete [] m_pBuffer;
00227 }
00228
00230
00231
00232 BOOL CGGEPItem::IsNamed(LPCTSTR pszID)
00233 {
00234 return m_sID == pszID;
00235 }
00236
00238
00239
00240 void CGGEPItem::Read(LPVOID pData, int nLength)
00241 {
00242 if ( m_nPosition + (DWORD)nLength >= m_nLength ) AfxThrowUserException();
00243 CopyMemory( pData, m_pBuffer + m_nPosition, nLength );
00244 m_nPosition += nLength;
00245 }
00246
00247 BYTE CGGEPItem::ReadByte()
00248 {
00249 BYTE nByte;
00250 Read( &nByte, 1 );
00251 return nByte;
00252 }
00253
00254 void CGGEPItem::Write(LPCVOID pData, int nLength)
00255 {
00256 BYTE* pNew = new BYTE[ m_nLength + (DWORD)nLength ];
00257
00258 if ( m_pBuffer )
00259 {
00260 CopyMemory( pNew, m_pBuffer, m_nLength );
00261 delete [] m_pBuffer;
00262 }
00263
00264 m_pBuffer = pNew;
00265 CopyMemory( m_pBuffer + m_nLength, pData, nLength );
00266 m_nLength += nLength;
00267 }
00268
00269 void CGGEPItem::WriteByte(BYTE nValue)
00270 {
00271 Write( &nValue, 1 );
00272 }
00273
00275
00276
00277 CString CGGEPItem::ToString()
00278 {
00279 CString strValue;
00280
00281 LPTSTR pszOut = strValue.GetBuffer( m_nLength );
00282 LPCSTR pszIn = (LPCSTR)m_pBuffer;
00283
00284 for ( DWORD nChar = 0 ; nChar < m_nLength ; nChar++ )
00285 *pszOut++ = (TCHAR)*pszIn++;
00286
00287 strValue.ReleaseBuffer( m_nLength );
00288 return strValue;
00289 }
00290
00292
00293
00294 BOOL CGGEPItem::ReadFrom(CGGEPBlock* pBlock, BYTE nFlags)
00295 {
00296 BYTE nLen = ( nFlags & GGEP_HDR_IDLEN );
00297
00298 if ( pBlock->m_nInput <= nLen ) return FALSE;
00299
00300 LPTSTR pszID = m_sID.GetBuffer( nLen );
00301 for ( BYTE i = nLen ; i && pBlock->m_nInput ; i-- ) *pszID++ = pBlock->ReadByte();
00302 m_sID.ReleaseBuffer( nLen );
00303
00304 m_nLength = 0;
00305
00306 for ( BYTE i = 0 ; i < 3 ; i++ )
00307 {
00308 if ( ! pBlock->m_nInput ) return FALSE;
00309 nLen = pBlock->ReadByte();
00310
00311 m_nLength = ( m_nLength << 6 ) | ( nLen & GGEP_LEN_MASK );
00312
00313 if ( nLen & GGEP_LEN_LAST ) break;
00314 if ( ! pBlock->m_nInput || ! ( nLen & GGEP_LEN_MORE ) ) return FALSE;
00315 }
00316
00317 if ( nLen & GGEP_LEN_MORE ) return FALSE;
00318 if ( ! ( nLen & GGEP_LEN_LAST ) ) return FALSE;
00319
00320 if ( ! m_nLength ) return TRUE;
00321
00322 if ( pBlock->m_nInput < m_nLength ) return FALSE;
00323
00324 m_pBuffer = new BYTE[ m_nLength ];
00325
00326 CopyMemory( m_pBuffer, pBlock->m_pInput, m_nLength );
00327 pBlock->m_pInput += m_nLength;
00328 pBlock->m_nInput -= m_nLength;
00329
00330 if ( ( nFlags & GGEP_HDR_COBS ) && ! Decode() )
00331 {
00332 delete [] m_pBuffer;
00333 m_pBuffer = NULL;
00334 return FALSE;
00335 }
00336
00337 if ( ( nFlags & GGEP_HDR_DEFLATE ) && ! Inflate() )
00338 {
00339 delete [] m_pBuffer;
00340 m_pBuffer = NULL;
00341 return FALSE;
00342 }
00343
00344 return TRUE;
00345 }
00346
00348
00349
00350 void CGGEPItem::WriteTo(CPacket* pPacket)
00351 {
00352 BYTE nFlags = ( m_sID.GetLength() & GGEP_HDR_IDLEN );
00353
00354 if ( Deflate( TRUE ) ) nFlags |= GGEP_HDR_DEFLATE;
00355 if ( Encode( TRUE ) ) nFlags |= GGEP_HDR_COBS;
00356
00357 if ( m_pNext == NULL ) nFlags |= GGEP_HDR_LAST;
00358
00359 pPacket->WriteByte( nFlags );
00360
00361 for ( BYTE i = 0 ; i < m_sID.GetLength() ; i++ )
00362 pPacket->WriteByte( (BYTE)m_sID.GetAt( i ) );
00363
00364 if ( m_nLength & 0x3F000 )
00365 pPacket->WriteByte( (BYTE)( ( ( m_nLength >> 12 ) & GGEP_LEN_MASK ) | GGEP_LEN_MORE ) );
00366
00367 if ( m_nLength & 0xFC0 )
00368 pPacket->WriteByte( (BYTE)( ( ( m_nLength >> 6 ) & GGEP_LEN_MASK ) | GGEP_LEN_MORE ) );
00369
00370 if ( m_nLength & 0x3F )
00371 pPacket->WriteByte( (BYTE)( ( m_nLength & GGEP_LEN_MASK ) | GGEP_LEN_LAST ) );
00372
00373 if ( m_pBuffer && m_nLength )
00374 pPacket->Write( m_pBuffer, m_nLength );
00375 }
00376
00378
00379
00380 void CGGEPItem::WriteTo(CString& str)
00381 {
00382 BYTE nFlags = ( m_sID.GetLength() & GGEP_HDR_IDLEN );
00383
00384 if ( Deflate( TRUE ) ) nFlags |= GGEP_HDR_DEFLATE;
00385 if ( Encode() ) nFlags |= GGEP_HDR_COBS;
00386
00387 if ( m_pNext == NULL ) nFlags |= GGEP_HDR_LAST;
00388
00389 str += (TCHAR)nFlags;
00390 str += m_sID;
00391
00392 if ( m_nLength & 0x3F000 )
00393 str += (TCHAR)( ( ( m_nLength >> 12 ) & GGEP_LEN_MASK ) | GGEP_LEN_MORE );
00394
00395 if ( m_nLength & 0xFC0 )
00396 str += (TCHAR)( ( ( m_nLength >> 6 ) & GGEP_LEN_MASK ) | GGEP_LEN_MORE );
00397
00398 if ( m_nLength & 0x3F )
00399 str += (TCHAR)( ( m_nLength & GGEP_LEN_MASK ) | GGEP_LEN_LAST );
00400
00401 if ( m_pBuffer && m_nLength )
00402 {
00403 for ( DWORD nLen = 0 ; nLen < m_nLength ; nLen++ )
00404 str += (TCHAR)m_pBuffer[ nLen ];
00405 }
00406 }
00407
00409
00410
00411 BOOL CGGEPItem::Encode(BOOL bIfZeros)
00412 {
00413 if ( ! m_pBuffer ) return FALSE;
00414
00415 DWORD nLength;
00416 BYTE* pIn;
00417
00418 if ( bIfZeros )
00419 {
00420 for ( pIn = m_pBuffer, nLength = m_nLength ; nLength > 0 ; nLength--, pIn++ )
00421 {
00422 if ( *pIn == 0 ) break;
00423 }
00424 if ( ! nLength ) return FALSE;
00425 }
00426
00427 BYTE* pOutput = new BYTE[ m_nLength * 2 ];
00428 BYTE* pOut = pOutput;
00429 BYTE* pRange = NULL;
00430 DWORD nRange = 0;
00431
00432 for ( pIn = m_pBuffer, nLength = m_nLength ; nLength > 0 ; nLength--, pIn++ )
00433 {
00434 if ( *pIn == 0 )
00435 {
00436 if ( pRange )
00437 {
00438 ASSERT( nRange > 0 && nRange < 254 );
00439 *pOut++ = (BYTE)( nRange + 1 );
00440 CopyMemory( pOut, pRange, nRange );
00441 pOut += nRange;
00442 pRange = NULL;
00443 nRange = 0;
00444 }
00445 else
00446 {
00447 *pOut++ = 1;
00448 }
00449 }
00450 else if ( pRange )
00451 {
00452 if ( ++nRange == 254 )
00453 {
00454 *pOut++ = 255;
00455 CopyMemory( pOut, pRange, 254 );
00456 pOut += 254;
00457 pRange = NULL;
00458 nRange = 0;
00459 }
00460 }
00461 else
00462 {
00463 pRange = pIn;
00464 nRange = 1;
00465 }
00466 }
00467
00468 if ( pRange )
00469 {
00470 ASSERT( nRange > 0 && nRange < 254 );
00471 *pOut++ = (BYTE)( nRange + 1 );
00472 CopyMemory( pOut, pRange, nRange );
00473 pOut += nRange;
00474 pRange = NULL;
00475 nRange = 0;
00476 }
00477
00478 delete [] m_pBuffer;
00479
00480 m_pBuffer = pOutput;
00481 m_nLength = pOut - pOutput;
00482
00483 return TRUE;
00484 }
00485
00486 BOOL CGGEPItem::Decode()
00487 {
00488 if ( ! m_pBuffer ) return FALSE;
00489
00490 BYTE* pOutput = new BYTE[ m_nLength * 2 ];
00491 BYTE* pOut = pOutput;
00492 BYTE* pIn = m_pBuffer;
00493
00494 for ( DWORD nLength = m_nLength ; nLength > 0 ; nLength--, pIn++ )
00495 {
00496 if ( *pIn == 0 )
00497 {
00498 break;
00499 }
00500 else if ( *pIn == 1 )
00501 {
00502 *pOut++ = 0;
00503 continue;
00504 }
00505
00506 BOOL bZero = ( *pIn != 255 );
00507 BYTE nSize = *pIn++ - 1;
00508 nLength--;
00509
00510 nSize = (BYTE)min( (DWORD)nSize, nLength );
00511
00512 while ( nSize-- )
00513 {
00514 *pOut++ = *pIn++;
00515 nLength--;
00516 }
00517
00518 if ( bZero && nLength ) *pOut++ = 0;
00519
00520 pIn--;
00521 nLength++;
00522 }
00523
00524 delete [] m_pBuffer;
00525
00526 m_pBuffer = pOutput;
00527 m_nLength = pOut - pOutput;
00528
00529 return TRUE;
00530 }
00531
00533
00534
00535 BOOL CGGEPItem::Deflate(BOOL bIfSmaller)
00536 {
00537 if ( ! m_pBuffer ) return FALSE;
00538 if ( bIfSmaller && m_nLength < 45 ) return FALSE;
00539
00540 DWORD nCompressed = 0;
00541 BYTE* pCompressed = CZLib::Compress( m_pBuffer, m_nLength, &nCompressed );
00542
00543 if ( ! pCompressed ) return FALSE;
00544
00545 if ( bIfSmaller && nCompressed >= m_nLength )
00546 {
00547 delete [] pCompressed;
00548 return FALSE;
00549 }
00550
00551 delete [] m_pBuffer;
00552 m_pBuffer = pCompressed;
00553 m_nLength = nCompressed;
00554
00555 return TRUE;
00556 }
00557
00558 BOOL CGGEPItem::Inflate()
00559 {
00560 if ( ! m_pBuffer ) return FALSE;
00561
00562 DWORD nCompressed = 0;
00563 BYTE* pCompressed = CZLib::Decompress( m_pBuffer, m_nLength, &nCompressed );
00564
00565 if ( ! pCompressed ) return FALSE;
00566
00567 delete [] m_pBuffer;
00568 m_pBuffer = pCompressed;
00569 m_nLength = nCompressed;
00570
00571 return TRUE;
00572 }