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

GGEP.cpp

Go to the documentation of this file.
00001 //
00002 // GGEP.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 "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 // CGGEPBlock construction
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 // CGGEPBlock clear
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 // CGGEPBlock add
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 // CGGEPBlock find
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 // CGGEPBlock from packet
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 // CGGEPBlock read helpers
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 // CGGEPBlock read internal
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 // CGGEPBlock write helpers
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 // CGGEPItem construction
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 // CGGEPItem ID check
00231 
00232 BOOL CGGEPItem::IsNamed(LPCTSTR pszID)
00233 {
00234         return m_sID == pszID;
00235 }
00236 
00238 // CGGEPItem reading and writing
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 // CGGEPItem string conversion
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 // CGGEPItem read
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 // CGGEPItem write to packet
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 // CGGEPItem write to string
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 // CGGEPItem COBS encoding
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 // CGGEPItem compression
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 }

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