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

BENode.cpp

Go to the documentation of this file.
00001 //
00002 // BENode.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 "BENode.h"
00026 #include "Buffer.h"
00027 #include "SHA.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 // CBENode construction/destruction
00038 
00039 CBENode::CBENode()
00040 {
00041         m_nType         = beNull;
00042         m_pValue        = NULL;
00043         m_nValue        = 0;
00044 }
00045 
00046 CBENode::~CBENode()
00047 {
00048         if ( m_pValue != NULL ) Clear();
00049 }
00050 
00052 // CBENode clear
00053 
00054 void CBENode::Clear()
00055 {
00056         if ( m_pValue != NULL )
00057         {
00058                 if ( m_nType == beString )
00059                 {
00060                         delete [] (LPSTR)m_pValue;
00061                 }
00062                 else if ( m_nType == beList )
00063                 {
00064                         CBENode** pNode = (CBENode**)m_pValue;
00065                         for ( ; m_nValue-- ; pNode++ ) delete *pNode;
00066                         delete [] (CBENode**)m_pValue;
00067                 }
00068                 else if ( m_nType == beDict )
00069                 {
00070                         CBENode** pNode = (CBENode**)m_pValue;
00071                         for ( ; m_nValue-- ; pNode++ )
00072                         {
00073                                 delete *pNode++;
00074                                 delete [] (LPBYTE)*pNode;
00075                         }
00076                         delete [] (CBENode**)m_pValue;
00077                 }
00078         }
00079         
00080         m_nType         = beNull;
00081         m_pValue        = NULL;
00082         m_nValue        = 0;
00083 }
00084 
00086 // CBENode add a child node
00087 
00088 CBENode* CBENode::Add(const LPBYTE pKey, int nKey)
00089 {
00090         switch ( m_nType )
00091         {
00092         case beNull:
00093                 m_nType         = ( pKey != NULL && nKey > 0 ) ? beDict : beList;
00094                 m_pValue        = NULL;
00095                 m_nValue        = 0;
00096                 break;
00097         case beList:
00098                 ASSERT( pKey == NULL && nKey == 0 );
00099                 break;
00100         case beDict:
00101                 ASSERT( pKey != NULL && nKey > 0 );
00102                 break;
00103         default:
00104                 ASSERT( FALSE );
00105                 break;
00106         }
00107         
00108         CBENode* pNew = new CBENode();                                  // Possible memory leak while running
00109         
00110         if ( m_nType == beList )
00111         {
00112                 CBENode** pList = new CBENode*[ (DWORD)m_nValue + 1 ];
00113                 
00114                 if ( m_pValue != NULL )
00115                 {
00116                         CopyMemory( pList, m_pValue, 4 * (DWORD)m_nValue );
00117                         delete [] (CBENode**)m_pValue;
00118                 }
00119                 
00120                 pList[ m_nValue++ ] = pNew;
00121                 m_pValue = pList;
00122         }
00123         else
00124         {
00125                 CBENode** pList = new CBENode*[ (DWORD)m_nValue * 2 + 2 ];
00126                 
00127                 if ( m_pValue != NULL )
00128                 {
00129                         CopyMemory( pList, m_pValue, 8 * (DWORD)m_nValue );
00130                         delete [] (CBENode**)m_pValue;
00131                 }
00132                 
00133                 BYTE* pxKey = new BYTE[ nKey + 1 ];                                     // Possible memory leak while running
00134                 CopyMemory( pxKey, pKey, nKey );
00135                 pxKey[ nKey ] = 0;
00136                 
00137                 pList[ m_nValue * 2 ]           = pNew;
00138                 pList[ m_nValue * 2 + 1 ]       = (CBENode*)pxKey;
00139                 
00140                 m_pValue = pList;
00141                 m_nValue ++;
00142         }
00143         
00144         return pNew;
00145 }
00146 
00148 // CBENode find a child node
00149 
00150 CBENode* CBENode::GetNode(LPCSTR pszKey) const
00151 {
00152         if ( m_nType != beDict ) return NULL;
00153         
00154         CBENode** pNode = (CBENode**)m_pValue;
00155         
00156         for ( DWORD nNode = (DWORD)m_nValue ; nNode ; nNode--, pNode += 2 )
00157         {
00158                 if ( strcmp( pszKey, (LPCSTR)pNode[1] ) == 0 ) return *pNode;
00159         }
00160         
00161         return NULL;
00162 }
00163 
00164 CBENode* CBENode::GetNode(const LPBYTE pKey, int nKey) const
00165 {
00166         if ( m_nType != beDict ) return NULL;
00167         
00168         CBENode** pNode = (CBENode**)m_pValue;
00169         
00170         for ( DWORD nNode = (DWORD)m_nValue ; nNode ; nNode--, pNode += 2 )
00171         {
00172                 if ( memcmp( pKey, (LPBYTE)pNode[1], nKey ) == 0 ) return *pNode;
00173         }
00174         
00175         return NULL;
00176 }
00177 
00178 
00180 // CBENode Extract a string from a node under this one. (Checks both normal and .utf-8)
00181 
00182 CString CBENode::GetStringFromSubNode(LPCSTR pszKey, UINT nEncoding, BOOL* pEncodingError)
00183 {
00184         CBENode*        pSubNode;
00185         CString         strValue;
00186 
00187         if ( Settings.BitTorrent.TorrentExtraKeys )
00188         {
00189                 // check for undocumented nodes
00190                 char*   pszUTF8Key;
00191                 UINT    nUTF8Len = strlen( pszKey ) + 8;
00192 
00193                 pszUTF8Key = new char[ nUTF8Len ];
00194                 strncpy( pszUTF8Key, pszKey, nUTF8Len );
00195                 strncat( pszUTF8Key, ".utf-8", nUTF8Len );
00196 
00197                 // Open the supplied node + .utf-8
00198                 pSubNode = GetNode( pszUTF8Key );
00199                 // We found a back-up node
00200                 // If it exists and is a string, try reading it
00201                 if ( ( pSubNode ) && ( pSubNode->m_nType == CBENode::beString ) )
00202                 {
00203                         // Assumed to be UTF-8
00204                         strValue = pSubNode->GetString();
00205                 }
00206                 delete [] pszUTF8Key;
00207         }
00208 
00209         // Open the supplied sub-node
00210         pSubNode = GetNode( pszKey );
00211         // If it exists and is a string, try reading it
00212         if ( ( pSubNode ) && ( pSubNode->m_nType == CBENode::beString ) )
00213         {
00214                 if ( ! IsValid( strValue ) )
00215                 {
00216                         // Read the string using the correct encoding. (UTF-8)
00217                         strValue = pSubNode->GetString();
00218                 }
00219                 else
00220                 {
00221                         // We already have a value - check it's valid
00222                         CString strCheck = pSubNode->GetString();
00223                         if ( strCheck != strValue ) *pEncodingError = TRUE;
00224                 }
00225         }
00226 
00227         if ( ! IsValid( strValue ) )
00228         {
00229                 // If we still don't have a valid name, try a decode by forcing the code page.
00230                 pSubNode = GetNode( pszKey );
00231                 if ( ( pSubNode ) && ( pSubNode->m_nType == CBENode::beString ) )
00232                 {
00233                         strValue = pSubNode->DecodeString( nEncoding );
00234 
00235                         if ( IsValid( strValue ) ) *pEncodingError = TRUE;
00236                 }
00237         }
00238 
00239         if ( _tcsicmp( strValue , _T("#ERROR#") ) == 0 ) strValue.Empty();
00240 
00241         return strValue;
00242 }
00243 
00244 // CBENode Extract a string from a list/dictionary
00245 
00246 CString CBENode::GetStringFromSubNode(int nItem, UINT nEncoding, BOOL* pEncodingError)
00247 {
00248         CBENode*        pSubNode;
00249         CString         strValue;
00250 
00251         // Check we are a list / dictionary type
00252         if ( m_nType != beList && m_nType != beDict ) return strValue;
00253         // Open the supplied list/dictionary item
00254         pSubNode = GetNode( nItem );
00255         // If it exists and is a string, try reading it
00256         if ( ( pSubNode ) && ( pSubNode->m_nType == CBENode::beString ) )
00257         {
00258                 // Read the string using the correct encoding. (UTF-8)
00259                 strValue = pSubNode->GetString();
00260         }
00261         // If it wasn't valid, try a decode by forcing the code page.
00262         if ( ! IsValid( strValue ) )
00263         {
00264                 // If we still don't have a valid name, try a decode by forcing the code page.
00265                 if ( ( pSubNode ) && ( pSubNode->m_nType == CBENode::beString ) )
00266                 {
00267                         *pEncodingError = TRUE;
00268                         strValue = pSubNode->DecodeString( nEncoding );
00269                 }
00270         }
00271 
00272         return strValue;
00273 }
00274 
00276 // CBENode SHA1 computation
00277 
00278 void CBENode::GetSHA1(SHA1* pSHA1) const
00279 {
00280         ASSERT( this != NULL );
00281         
00282         CBuffer pBuffer;
00283         Encode( &pBuffer );
00284         
00285         CSHA pSHA;
00286         pSHA.Add( pBuffer.m_pBuffer, pBuffer.m_nLength );
00287         pSHA.Finish();
00288         pSHA.GetHash( pSHA1 );
00289 }
00290 
00292 // CBENode encoding
00293 
00294 void CBENode::Encode(CBuffer* pBuffer) const
00295 {
00296         CHAR szBuffer[64];
00297         
00298         ASSERT( this != NULL );
00299         ASSERT( pBuffer != NULL );
00300         CString str;
00301         
00302         if ( m_nType == beString )
00303         {
00304                 sprintf( szBuffer, "%u:", (DWORD)m_nValue );
00305                 pBuffer->Print( szBuffer );
00306                 pBuffer->Add( m_pValue, (DWORD)m_nValue );
00307         }
00308         else if ( m_nType == beInt )
00309         {
00310                 sprintf( szBuffer, "i%I64ie", m_nValue );
00311                 pBuffer->Print( szBuffer );
00312         }
00313         else if ( m_nType == beList )
00314         {
00315                 CBENode** pNode = (CBENode**)m_pValue;
00316                 
00317                 pBuffer->Print( "l" );
00318                 
00319                 for ( DWORD nItem = 0 ; nItem < (DWORD)m_nValue ; nItem++, pNode++ )
00320                 {
00321                         (*pNode)->Encode( pBuffer );
00322                 }
00323                 
00324                 pBuffer->Print( "e" );
00325         }
00326         else if ( m_nType == beDict )
00327         {
00328                 CBENode** pNode = (CBENode**)m_pValue;
00329                 
00330                 pBuffer->Print( "d" );
00331                 
00332                 for ( DWORD nItem = 0 ; nItem < m_nValue ; nItem++, pNode += 2 )
00333                 {
00334                         LPCSTR pszKey = (LPCSTR)pNode[1];
00335                         sprintf( szBuffer, "%i:", strlen( pszKey ) );
00336                         pBuffer->Print( szBuffer );
00337                         pBuffer->Print( pszKey );
00338                         (*pNode)->Encode( pBuffer );
00339                 }
00340                 
00341                 pBuffer->Print( "e" );
00342         }
00343         else
00344         {
00345                 ASSERT( FALSE );
00346         }
00347 }
00348 
00350 // CBENode decoding
00351 
00352 CBENode* CBENode::Decode(CBuffer* pBuffer)
00353 {
00354         ASSERT( pBuffer != NULL );
00355         
00356         CBENode* pNode  = new CBENode();
00357         LPBYTE pInput   = pBuffer->m_pBuffer;
00358         DWORD nInput    = pBuffer->m_nLength;
00359         
00360         try
00361         {
00362                 pNode->Decode( pInput, nInput );
00363         }
00364         catch ( CException* pException )
00365         {
00366                 pException->Delete();
00367                 delete pNode;
00368                 pNode = NULL;
00369         }
00370         
00371         return pNode;
00372 }
00373 
00374 #define INC(x) { pInput += (x); nInput -= (x); }
00375 
00376 void CBENode::Decode(LPBYTE& pInput, DWORD& nInput)
00377 {
00378         ASSERT( m_nType == beNull );
00379         ASSERT( pInput != NULL );
00380         
00381         if ( nInput < 1 ) AfxThrowUserException();
00382         
00383         if ( *pInput == 'i' )
00384         {
00385                 INC( 1 );
00386                 
00387         DWORD nSeek = 1;
00388                 for ( ; nSeek < 40 ; nSeek++ )
00389                 {
00390                         if ( nSeek >= nInput ) AfxThrowUserException();
00391                         if ( pInput[nSeek] == 'e' ) break;
00392                 }
00393                 
00394                 if ( nSeek >= 40 ) AfxThrowUserException();
00395                 
00396                 pInput[nSeek] = 0;
00397                 if ( sscanf( (LPCSTR)pInput, "%I64i", &m_nValue ) != 1 ) AfxThrowUserException();
00398                 pInput[nSeek] = 'e';
00399                 
00400                 INC( nSeek + 1 );
00401                 m_nType = beInt;
00402         }
00403         else if ( *pInput == 'l' )
00404         {
00405                 m_nType = beList;
00406                 INC( 1 );
00407                 
00408                 while ( TRUE )
00409                 {
00410                         if ( nInput < 1 ) AfxThrowUserException();
00411                         if ( *pInput == 'e' ) break;
00412                         Add()->Decode( pInput, nInput );
00413                 }
00414                 
00415                 INC( 1 );
00416         }
00417         else if ( *pInput == 'd' )
00418         {
00419                 m_nType = beDict;
00420                 INC( 1 );
00421                 
00422                 while ( TRUE )
00423                 {
00424                         if ( nInput < 1 ) AfxThrowUserException();
00425                         if ( *pInput == 'e' ) break;
00426                         
00427                         int nLen = DecodeLen( pInput, nInput );
00428                         LPBYTE pKey = pInput;
00429                         INC( nLen );
00430                         
00431                         Add( pKey, nLen )->Decode( pInput, nInput );
00432                 }
00433                 
00434                 INC( 1 );
00435         }
00436         else if ( *pInput >= '0' && *pInput <= '9' )
00437         {
00438                 m_nType         = beString;
00439                 m_nValue        = DecodeLen( pInput, nInput );
00440                 m_pValue        = new CHAR[ (DWORD)m_nValue + 1 ];
00441                 CopyMemory( m_pValue, pInput, (DWORD)m_nValue );
00442                 ((LPBYTE)m_pValue)[ m_nValue ] = 0;
00443                 
00444                 INC( (DWORD)m_nValue );
00445         }
00446         else
00447         {
00448                 AfxThrowUserException();
00449         }
00450 }
00451 
00452 int CBENode::DecodeLen(LPBYTE& pInput, DWORD& nInput)
00453 {
00454     DWORD nSeek = 1;
00455     for ( ; nSeek < 32 ; nSeek++ )
00456         {
00457                 if ( nSeek >= nInput ) AfxThrowUserException();
00458                 if ( pInput[ nSeek ] == ':' ) break;
00459         }
00460         
00461         if ( nSeek >= 32 ) AfxThrowUserException();
00462         int nLen = 0;
00463         
00464         pInput[ nSeek ] = 0;
00465         if ( sscanf( (LPCSTR)pInput, "%i", &nLen ) != 1 ) AfxThrowUserException();
00466         pInput[ nSeek ] = ':';
00467         INC( nSeek + 1 );
00468         
00469         if ( nInput < (DWORD)nLen ) AfxThrowUserException();
00470         
00471         return nLen;
00472 }

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