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 "ThumbCache.h"
00026 #include "ImageFile.h"
00027 #include "Library.h"
00028
00029 #ifdef _DEBUG
00030 #undef THIS_FILE
00031 static char THIS_FILE[]=__FILE__;
00032 #define new DEBUG_NEW
00033 #endif
00034
00035 #define THUMB_SIGNATURE "RAZATDB1"
00036
00037
00039
00040
00041 CThumbCache::CThumbCache()
00042 {
00043 m_bOpen = FALSE;
00044 m_nOffset = 0;
00045 m_pIndex = NULL;
00046 m_nIndex = 0;
00047 m_nBuffer = 0;
00048 }
00049
00050 CThumbCache::~CThumbCache()
00051 {
00052 Close();
00053 }
00054
00056
00057
00058 BOOL CThumbCache::Prepare(LPCTSTR pszPath, CSize* pszThumb, BOOL bCreate)
00059 {
00060 CString strPath( pszPath );
00061
00062 int nSlash = strPath.ReverseFind( '\\' );
00063 if ( nSlash >= 0 ) strPath = strPath.Left( nSlash );
00064 strPath += _T("\\SThumbs.dat");
00065
00066 if ( m_bOpen && strPath.CompareNoCase( m_sPath ) == 0 )
00067 {
00068 if ( m_szThumb != *pszThumb )
00069 {
00070 Close();
00071 DeleteFile( strPath );
00072 }
00073
00074 return TRUE;
00075 }
00076 else if ( m_bOpen )
00077 {
00078 Close();
00079 }
00080
00081 if ( m_pFile.Open( strPath, CFile::modeReadWrite ) )
00082 {
00083 CHAR szID[8];
00084 m_pFile.Read( szID, 8 );
00085
00086 if ( memcmp( szID, THUMB_SIGNATURE, 8 ) != 0 )
00087 {
00088 m_pFile.Close();
00089 return DeleteFile( strPath ) && Prepare( pszPath, pszThumb, bCreate );
00090 }
00091
00092 m_pFile.Read( &m_szThumb.cx, 4 );
00093 m_pFile.Read( &m_szThumb.cy, 4 );
00094
00095 if ( pszThumb->cx == 0 && pszThumb->cy == 0 ) *pszThumb = m_szThumb;
00096
00097 if ( m_szThumb == *pszThumb )
00098 {
00099 m_pFile.Read( &m_nOffset, 4 );
00100 m_pFile.Read( &m_nIndex, 4 );
00101
00102 for ( m_nBuffer = m_nIndex ; m_nBuffer & 63 ; m_nBuffer++ );
00103 m_pIndex = new THUMB_INDEX[ m_nBuffer ];
00104
00105 m_pFile.Seek( m_nOffset, 0 );
00106 m_pFile.Read( m_pIndex, sizeof(THUMB_INDEX) * m_nIndex );
00107
00108 m_sPath = strPath;
00109 m_bOpen = TRUE;
00110 }
00111 else
00112 {
00113 m_pFile.Close();
00114 DeleteFile( strPath );
00115 }
00116 }
00117
00118 if ( ! m_bOpen )
00119 {
00120 if ( ! bCreate ) return FALSE;
00121
00122 if ( ! m_pFile.Open( strPath, CFile::modeReadWrite|CFile::modeCreate ) ) return FALSE;
00123
00124 SetFileAttributes( strPath, FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM );
00125
00126 if ( pszThumb->cx == 0 && pszThumb->cy == 0 ) *pszThumb = CSize( Settings.Library.ThumbSize, Settings.Library.ThumbSize );
00127
00128 m_szThumb = *pszThumb;
00129
00130 m_pFile.Write( THUMB_SIGNATURE, 8 );
00131 m_pFile.Write( &m_szThumb.cx, 4 );
00132 m_pFile.Write( &m_szThumb.cy, 4 );
00133 m_pFile.Write( &m_nOffset, 4 );
00134 m_pFile.Write( &m_nIndex, 4 );
00135 m_nOffset = 24;
00136
00137 m_sPath = strPath;
00138 m_bOpen = TRUE;
00139 }
00140
00141 return TRUE;
00142 }
00143
00145
00146
00147 void CThumbCache::Close()
00148 {
00149 CSingleLock pLock( &m_pSection, TRUE );
00150
00151 if ( m_bOpen == FALSE ) return;
00152
00153 m_sPath.Empty();
00154 m_pFile.Close();
00155 m_bOpen = FALSE;
00156
00157 if ( m_pIndex != NULL ) delete [] m_pIndex;
00158
00159 m_pIndex = NULL;
00160 m_nIndex = 0;
00161 m_nBuffer = 0;
00162 }
00163
00165
00166
00167 BOOL CThumbCache::Load(LPCTSTR pszPath, CSize* pszThumb, DWORD nIndex, CImageFile* pImage)
00168 {
00169 CSingleLock pLock( &m_pSection, TRUE );
00170
00171 if ( ! Prepare( pszPath, pszThumb, FALSE ) ) return FALSE;
00172
00173 THUMB_INDEX* pIndex = m_pIndex;
00174
00175 DWORD nCount = m_nIndex;
00176 for ( ; nCount ; nCount--, pIndex++ )
00177 {
00178 if ( pIndex->nIndex == nIndex ) break;
00179 }
00180
00181 if ( nCount == 0 ) return FALSE;
00182
00183 FILETIME pTime;
00184 GetFileTime( pszPath, &pTime );
00185 if ( CompareFileTime( &pIndex->pTime, &pTime ) != 0 ) return FALSE;
00186
00187 m_pFile.Seek( pIndex->nOffset, 0 );
00188
00189 try
00190 {
00191 CArchive ar( &m_pFile, CArchive::load );
00192 pImage->Serialize( ar );
00193 }
00194 catch ( CException* pException )
00195 {
00196 pException->Delete();
00197 return FALSE;
00198 }
00199
00200 return TRUE;
00201 }
00202
00204
00205
00206 BOOL CThumbCache::Store(LPCTSTR pszPath, CSize* pszThumb, DWORD nIndex, CImageFile* pImage)
00207 {
00208 CSingleLock pLock( &m_pSection, TRUE );
00209
00210 if ( ! Prepare( pszPath, pszThumb, TRUE ) ) return FALSE;
00211
00212 DWORD nBlock = pImage->GetSerialSize();
00213
00214 THUMB_INDEX* pIndex = m_pIndex;
00215
00216 DWORD nCount = m_nIndex;
00217 for ( ; nCount ; nCount--, pIndex++ )
00218 {
00219 if ( pIndex->nIndex == nIndex ) break;
00220 }
00221
00222 if ( nCount != 0 && pIndex->nLength != nBlock )
00223 {
00224 pIndex->nIndex = 0;
00225 nCount = 0;
00226 }
00227
00228 if ( nCount == 0 )
00229 {
00230 THUMB_INDEX* pBestIndex = NULL;
00231 DWORD nBestOverhead = 0xFFFFFFFF;
00232
00233 for ( pIndex = m_pIndex, nCount = m_nIndex ; nCount ; nCount--, pIndex++ )
00234 {
00235 if ( pIndex->nLength >= nBlock &&
00236 ( pIndex->nIndex == 0 || Library.LookupFile( pIndex->nIndex ) == NULL ) )
00237 {
00238 DWORD nOverhead = pIndex->nLength - nBlock;
00239
00240 if ( nOverhead < nBestOverhead )
00241 {
00242 pBestIndex = pIndex;
00243 nBestOverhead = nOverhead;
00244 if ( nOverhead == 0 ) break;
00245 }
00246 }
00247 }
00248
00249 if ( pBestIndex != NULL )
00250 {
00251 pIndex = pBestIndex;
00252 }
00253 else
00254 {
00255 if ( m_nIndex >= m_nBuffer )
00256 {
00257 m_nBuffer += 64;
00258 THUMB_INDEX* pNew = new THUMB_INDEX[ m_nBuffer ];
00259 if ( m_nIndex ) CopyMemory( pNew, m_pIndex, sizeof(THUMB_INDEX) * m_nIndex );
00260 if ( m_pIndex ) delete [] m_pIndex;
00261 m_pIndex = pNew;
00262 }
00263
00264 pIndex = m_pIndex + m_nIndex++;
00265 pIndex->nOffset = m_nOffset;
00266 pIndex->nLength = nBlock;
00267
00268 m_nOffset += nBlock;
00269 }
00270
00271 pIndex->nIndex = nIndex;
00272 }
00273
00274 GetFileTime( pszPath, &pIndex->pTime );
00275
00276 m_pFile.Seek( pIndex->nOffset, 0 );
00277
00278 try
00279 {
00280 CArchive ar( &m_pFile, CArchive::store );
00281 pImage->Serialize( ar );
00282 ar.Flush();
00283 }
00284 catch ( CException* pException )
00285 {
00286 pException->Delete();
00287 }
00288
00289 m_pFile.SetLength( m_nOffset + sizeof(THUMB_INDEX) * m_nIndex );
00290 m_pFile.Seek( 16, 0 );
00291 m_pFile.Write( &m_nOffset, 4 );
00292 m_pFile.Write( &m_nIndex, 4 );
00293 m_pFile.Seek( m_nOffset, 0 );
00294 m_pFile.Write( m_pIndex, sizeof(THUMB_INDEX) * m_nIndex );
00295
00296 m_pFile.Flush();
00297
00298 return TRUE;
00299 }
00300
00302
00303
00304 BOOL CThumbCache::Purge(LPCTSTR pszPath)
00305 {
00306 CString strPath( pszPath );
00307
00308 int nSlash = strPath.ReverseFind( '\\' );
00309 if ( nSlash >= 0 ) strPath = strPath.Left( nSlash );
00310 strPath += _T("\\SThumbs.dat");
00311
00312 if ( GetFileAttributes( strPath ) == 0xFFFFFFFF ) return FALSE;
00313
00314 DeleteFile( strPath );
00315
00316 return TRUE;
00317 }
00318
00320
00321
00322 BOOL CThumbCache::GetFileTime(LPCTSTR pszPath, FILETIME* pTime)
00323 {
00324 BOOL bSuccess = FALSE;
00325
00326 if ( Library.m_pfnGFAEW != NULL )
00327 {
00328 USES_CONVERSION;
00329 WIN32_FILE_ATTRIBUTE_DATA pInfo;
00330 bSuccess = (*Library.m_pfnGFAEW)( T2CW(pszPath), GetFileExInfoStandard, &pInfo );
00331 *pTime = pInfo.ftLastWriteTime;
00332 }
00333 else if ( Library.m_pfnGFAEA != NULL )
00334 {
00335 USES_CONVERSION;
00336 WIN32_FILE_ATTRIBUTE_DATA pInfo;
00337 bSuccess = (*Library.m_pfnGFAEA)( T2CA(pszPath), GetFileExInfoStandard, &pInfo );
00338 *pTime = pInfo.ftLastWriteTime;
00339 }
00340 else
00341 {
00342 HANDLE hFile = CreateFile( pszPath, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
00343 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
00344
00345 if ( hFile != INVALID_HANDLE_VALUE )
00346 {
00347 ::GetFileTime( hFile, NULL, NULL, pTime );
00348 CloseHandle( hFile );
00349 }
00350 }
00351
00352 return bSuccess;
00353 }