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 "Library.h"
00026 #include "LibraryMaps.h"
00027 #include "LibraryFolders.h"
00028 #include "SharedFile.h"
00029 #include "SharedFolder.h"
00030 #include "AlbumFolder.h"
00031 #include "Application.h"
00032 #include "CollectionFile.h"
00033
00034 #include "XML.h"
00035 #include "Schema.h"
00036 #include "SchemaCache.h"
00037 #include <shlobj.h>
00038
00039 IMPLEMENT_DYNAMIC(CLibraryFolders, CComObject)
00040
00041 BEGIN_INTERFACE_MAP(CLibraryFolders, CComObject)
00042 INTERFACE_PART(CLibraryFolders, IID_ILibraryFolders, LibraryFolders)
00043 END_INTERFACE_MAP()
00044
00045 CLibraryFolders LibraryFolders;
00046
00047
00049
00050
00051 CLibraryFolders::CLibraryFolders()
00052 {
00053 EnableDispatch( IID_ILibraryFolders );
00054
00055 m_pAlbumRoot = NULL;
00056 m_bRemoveMask = FALSE;
00057 }
00058
00059 CLibraryFolders::~CLibraryFolders()
00060 {
00061 if ( m_pAlbumRoot != NULL ) delete m_pAlbumRoot;
00062 }
00063
00065
00066
00067 POSITION CLibraryFolders::GetFolderIterator() const
00068 {
00069 return m_pFolders.GetHeadPosition();
00070 }
00071
00072 CLibraryFolder* CLibraryFolders::GetNextFolder(POSITION& pos) const
00073 {
00074 return (CLibraryFolder*)m_pFolders.GetNext( pos );
00075 }
00076
00077 int CLibraryFolders::GetFolderCount() const
00078 {
00079 return m_pFolders.GetCount();
00080 }
00081
00083
00084
00085 CLibraryFolder* CLibraryFolders::GetFolder(LPCTSTR pszPath) const
00086 {
00087 for ( POSITION pos = GetFolderIterator() ; pos ; )
00088 {
00089 CLibraryFolder* pFolder = GetNextFolder( pos )->GetFolderByPath( pszPath );
00090 if ( pFolder != NULL ) return pFolder;
00091 }
00092
00093 return NULL;
00094 }
00095
00096 BOOL CLibraryFolders::CheckFolder(CLibraryFolder* pFolder, BOOL bRecursive) const
00097 {
00098 if ( m_pFolders.Find( pFolder ) != NULL ) return TRUE;
00099 if ( ! bRecursive ) return FALSE;
00100
00101 for ( POSITION pos = GetFolderIterator() ; pos ; )
00102 {
00103 if ( GetNextFolder( pos )->CheckFolder( pFolder, TRUE ) ) return TRUE;
00104 }
00105
00106 return FALSE;
00107 }
00108
00110
00111
00112 CLibraryFolder* CLibraryFolders::AddFolder(LPCTSTR pszPath)
00113 {
00114 CString strPath = pszPath;
00115
00116 if ( strPath.GetLength() == 3 && strPath.GetAt( 2 ) == '\\' )
00117 strPath = strPath.Left( 2 );
00118
00119 if ( IsFolderShared( strPath ) ) return NULL;
00120 if ( IsSubFolderShared( strPath ) ) return NULL;
00121
00122 CLibraryFolder* pFolder;
00123 {
00124 CQuickLock oLock( Library.m_pSection );
00125
00126 pFolder = new CLibraryFolder( NULL, strPath );
00127 BOOL bAdded = FALSE;
00128
00129 for ( POSITION pos = GetFolderIterator() ; pos ; )
00130 {
00131 POSITION posAdd = pos;
00132
00133 if ( GetNextFolder( pos )->m_sName.CompareNoCase( pFolder->m_sName ) >= 0 )
00134 {
00135 m_pFolders.InsertBefore( posAdd, pFolder );
00136 bAdded = TRUE;
00137 break;
00138 }
00139 }
00140
00141 if ( ! bAdded ) m_pFolders.AddTail( pFolder );
00142
00143 Library.Update();
00144 }
00145 Library.StartThread();
00146
00147 return pFolder;
00148 }
00149
00150 CLibraryFolder* CLibraryFolders::AddFolder(LPCTSTR pszPath, BOOL bShared)
00151 {
00152 CLibraryFolder* pFolder = AddFolder( pszPath );
00153
00154 if( pFolder )
00155 {
00156 if( bShared )
00157 pFolder->m_bShared = TS_TRUE;
00158 else
00159 pFolder->m_bShared = TS_FALSE;
00160 }
00161
00162 return pFolder;
00163 }
00164
00166
00167
00168 BOOL CLibraryFolders::RemoveFolder(CLibraryFolder* pFolder)
00169 {
00170 CQuickLock pLock( Library.m_pSection );
00171 CWaitCursor pCursor;
00172
00173 if ( m_bRemoveMask ) return FALSE;
00174
00175 POSITION pos = m_pFolders.Find( pFolder );
00176 if ( pos == NULL ) return FALSE;
00177
00178 pFolder->OnDelete();
00179 m_pFolders.RemoveAt( pos );
00180
00181 Library.Update();
00182
00183 return TRUE;
00184 }
00185
00187
00188
00189 CLibraryFolder* CLibraryFolders::IsFolderShared(LPCTSTR pszPath)
00190 {
00191 CString strPathLC( pszPath );
00192 CharLower( strPathLC.GetBuffer() );
00193 strPathLC.ReleaseBuffer();
00194
00195 for ( POSITION pos = GetFolderIterator() ; pos ; )
00196 {
00197 CLibraryFolder* pFolder = GetNextFolder( pos );
00198
00199 CString strOldLC( pFolder->m_sPath );
00200 CharLower( strOldLC.GetBuffer() );
00201 strOldLC.ReleaseBuffer();
00202
00203 if ( strPathLC.GetLength() > strOldLC.GetLength() )
00204 {
00205 int nLength = strOldLC.GetLength();
00206 if ( strPathLC.Left( nLength ) == strOldLC &&
00207 strPathLC.GetAt( nLength ) == _T('\\') )
00208 return pFolder;
00209 }
00210 else
00211 {
00212 if ( strPathLC == strOldLC ) return pFolder;
00213 }
00214 }
00215
00216 return NULL;
00217 }
00218
00220
00221
00222 CLibraryFolder* CLibraryFolders::IsSubFolderShared(LPCTSTR pszPath)
00223 {
00224 CString strPathLC( pszPath );
00225 CharLower( strPathLC.GetBuffer() );
00226 strPathLC.ReleaseBuffer();
00227
00228 for ( POSITION pos = GetFolderIterator() ; pos ; )
00229 {
00230 CLibraryFolder* pFolder = GetNextFolder( pos );
00231
00232 CString strOldLC( pFolder->m_sPath );
00233 CharLower( strOldLC.GetBuffer() );
00234 strOldLC.ReleaseBuffer();
00235
00236 if ( strPathLC.GetLength() < strOldLC.GetLength() )
00237 {
00238 int nLength = strPathLC.GetLength();
00239 if ( strOldLC.Left( nLength ) == strPathLC &&
00240 strOldLC.GetAt( nLength ) == _T('\\') )
00241 return pFolder;
00242 }
00243 }
00244
00245 return NULL;
00246 }
00247
00249
00250
00251 BOOL CLibraryFolders::IsShareable(LPCTSTR pszPath)
00252 {
00253 CString strPathLC( pszPath );
00254 CharLower( strPathLC.GetBuffer() );
00255 strPathLC.ReleaseBuffer();
00256
00257
00258 CString strWindowsLC, strProgramsLC;
00259 PTSTR pszWindowsPath, pszProgramsPath;
00260
00261 pszWindowsPath = strWindowsLC.GetBuffer( MAX_PATH + 1 );
00262 pszProgramsPath = strProgramsLC.GetBuffer( MAX_PATH + 1 );
00263
00264 if ( HINSTANCE hShell = LoadLibrary( _T("shfolder.dll") ) )
00265 {
00266 HRESULT (WINAPI *pfnSHGetFolderPath)(HWND, int, HANDLE, DWORD, LPWSTR);
00267 (FARPROC&)pfnSHGetFolderPath = GetProcAddress( hShell, "SHGetFolderPathW" );
00268 if ( pfnSHGetFolderPath != NULL )
00269 {
00270 (*pfnSHGetFolderPath)(NULL, CSIDL_WINDOWS, NULL, NULL, pszWindowsPath);
00271 (*pfnSHGetFolderPath)(NULL, CSIDL_PROGRAM_FILES, NULL, NULL, pszProgramsPath);
00272 }
00273 FreeLibrary( hShell );
00274 }
00275 CharLower( pszWindowsPath );
00276 CharLower( pszProgramsPath );
00277
00278 strWindowsLC.ReleaseBuffer();
00279 strProgramsLC.ReleaseBuffer();
00280
00281 if ( strWindowsLC.IsEmpty() ) strWindowsLC = _T("c:\\windows");
00282 if ( strProgramsLC.IsEmpty() ) strProgramsLC = _T("c:\\program files");
00283
00284
00285
00286 CString strIncompletePathLC = Settings.Downloads.IncompletePath;
00287 CharLower( strIncompletePathLC.GetBuffer() );
00288 strIncompletePathLC.ReleaseBuffer();
00289
00290 CString strGeneralPathLC = Settings.General.Path;
00291 CharLower( strGeneralPathLC.GetBuffer() );
00292 strGeneralPathLC.ReleaseBuffer();
00293
00294 CString strUserPathLC = Settings.General.UserPath;
00295 CharLower( strUserPathLC.GetBuffer() );
00296 strUserPathLC.ReleaseBuffer();
00297
00298 BOOL bTest = pszPath == strWindowsLC;
00299
00300 return !( strPathLC == _T( "" ) ||
00301 strPathLC == strWindowsLC.Left( 3 ) ||
00302 strPathLC == strProgramsLC ||
00303 strPathLC == strWindowsLC ||
00304 strPathLC == strGeneralPathLC ||
00305 strPathLC == strGeneralPathLC + _T("\\data") ||
00306 strPathLC == strUserPathLC ||
00307 strPathLC == strUserPathLC + _T("\\data") ||
00308 strPathLC == strIncompletePathLC );
00309 }
00310
00312
00313
00314 CAlbumFolder* CLibraryFolders::GetAlbumRoot()
00315 {
00316 if ( m_pAlbumRoot == NULL )
00317 {
00318 m_pAlbumRoot = new CAlbumFolder( NULL, CSchema::uriLibrary );
00319 }
00320
00321 return m_pAlbumRoot;
00322 }
00323
00324 BOOL CLibraryFolders::CheckAlbum(CAlbumFolder* pFolder) const
00325 {
00326 if ( m_pAlbumRoot == NULL ) return FALSE;
00327 return m_pAlbumRoot->CheckFolder( pFolder, TRUE );
00328 }
00329
00331
00332
00333 CAlbumFolder* CLibraryFolders::GetAlbumTarget(LPCTSTR pszSchemaURI, LPCTSTR pszMember, LPCTSTR pszValue) const
00334 {
00335 if ( m_pAlbumRoot == NULL ) return NULL;
00336
00337 CSchema* pSchema = SchemaCache.Get( pszSchemaURI );
00338 if ( pSchema == NULL ) return NULL;
00339
00340 CSchemaMember* pMember = pSchema->GetMember( pszMember );
00341
00342 if ( pMember == NULL )
00343 {
00344 if ( pSchema->GetMemberCount() == 0 ) return NULL;
00345 POSITION pos = pSchema->GetMemberIterator();
00346 pMember = pSchema->GetNextMember( pos );
00347 }
00348
00349 if ( pszValue != NULL )
00350 {
00351 CString strValue( pszValue );
00352 CXMLNode::UniformString( strValue );
00353 return m_pAlbumRoot->GetTarget( pMember, strValue );
00354 }
00355 else
00356 {
00357 return m_pAlbumRoot->GetTarget( pMember, NULL );
00358 }
00359 }
00360
00362
00363
00364 CAlbumFolder* CLibraryFolders::GetCollection(SHA1* pSHA1)
00365 {
00366 return GetAlbumRoot()->FindCollection( pSHA1 );
00367 }
00368
00370
00371
00372 BOOL CLibraryFolders::MountCollection(SHA1* pSHA1, CCollectionFile* pCollection)
00373 {
00374 CSingleLock pLock( &Library.m_pSection );
00375 BOOL bSuccess = FALSE;
00376
00377 if ( ! pLock.Lock( 500 ) ) return FALSE;
00378
00379 if ( pCollection->GetThisURI().GetLength() )
00380 {
00381 bSuccess |= GetAlbumRoot()->MountCollection( pSHA1, pCollection );
00382 }
00383
00384 if ( pCollection->GetParentURI().GetLength() )
00385 {
00386 if ( CAlbumFolder* pFolder = GetAlbumTarget( pCollection->GetParentURI(), NULL, NULL ) )
00387 {
00388 bSuccess |= pFolder->MountCollection( pSHA1, pCollection, TRUE );
00389 }
00390 }
00391
00392 return bSuccess;
00393 }
00394
00396
00397
00398 void CLibraryFolders::CreateAlbumTree()
00399 {
00400 int nCount = GetAlbumRoot()->GetFolderCount();
00401
00402 if ( m_pAlbumRoot->GetFolderByURI( CSchema::uriAllFiles ) == NULL )
00403 {
00404 CAlbumFolder* pAllFiles = m_pAlbumRoot->AddFolder( CSchema::uriAllFiles );
00405 }
00406
00407 if ( m_pAlbumRoot->GetFolderByURI( CSchema::uriApplicationRoot ) == NULL )
00408 {
00409 CAlbumFolder* pAppRoot = m_pAlbumRoot->AddFolder( CSchema::uriApplicationRoot );
00410 CAlbumFolder* pAppAll = pAppRoot->AddFolder( CSchema::uriApplicationAll );
00411 }
00412
00413 if ( m_pAlbumRoot->GetFolderByURI( CSchema::uriBookRoot ) == NULL )
00414 {
00415 CAlbumFolder* pBookRoot = m_pAlbumRoot->AddFolder( CSchema::uriBookRoot );
00416 CAlbumFolder* pBookAll = pBookRoot->AddFolder( CSchema::uriBookAll );
00417 }
00418
00419 if ( m_pAlbumRoot->GetFolderByURI( CSchema::uriImageRoot ) == NULL )
00420 {
00421 CAlbumFolder* pImageRoot = m_pAlbumRoot->AddFolder( CSchema::uriImageRoot );
00422 CAlbumFolder* pImageAll = pImageRoot->AddFolder( CSchema::uriImageAll );
00423 }
00424
00425 if ( m_pAlbumRoot->GetFolderByURI( CSchema::uriMusicRoot ) == NULL )
00426 {
00427 CAlbumFolder* pMusicRoot = m_pAlbumRoot->AddFolder( CSchema::uriMusicRoot );
00428 CAlbumFolder* pMusicAll = pMusicRoot->AddFolder( CSchema::uriMusicAll );
00429 CAlbumFolder* pMusicAlbum = pMusicRoot->AddFolder( CSchema::uriMusicAlbumCollection );
00430 CAlbumFolder* pMusicArtist = pMusicRoot->AddFolder( CSchema::uriMusicArtistCollection );
00431 CAlbumFolder* pMusicGenre = pMusicRoot->AddFolder( CSchema::uriMusicGenreCollection );
00432 }
00433
00434 if ( m_pAlbumRoot->GetFolderByURI( CSchema::uriVideoRoot ) == NULL )
00435 {
00436 CAlbumFolder* pVideoRoot = m_pAlbumRoot->AddFolder( CSchema::uriVideoRoot );
00437 CAlbumFolder* pVideoAll = pVideoRoot->AddFolder( CSchema::uriVideoAll );
00438 CAlbumFolder* pVideoSeries = pVideoRoot->AddFolder( CSchema::uriVideoSeriesCollection );
00439 CAlbumFolder* pVideoFilm = pVideoRoot->AddFolder( CSchema::uriVideoFilmCollection );
00440 CAlbumFolder* pVideoMusic = pVideoRoot->AddFolder( CSchema::uriVideoMusicCollection );
00441 }
00442
00443 if ( m_pAlbumRoot->GetFolderByURI( CSchema::uriFavouritesFolder ) == NULL )
00444 {
00445 CAlbumFolder* pFavourites = m_pAlbumRoot->AddFolder( CSchema::uriFavouritesFolder );
00446 }
00447
00448 if ( m_pAlbumRoot->GetFolderByURI( CSchema::uriCollectionsFolder ) == NULL )
00449 {
00450 CAlbumFolder* pCollections = m_pAlbumRoot->AddFolder( CSchema::uriCollectionsFolder );
00451 }
00452
00453 if ( m_pAlbumRoot->GetFolderByURI( CSchema::uriDocumentRoot ) == NULL )
00454 {
00455 CAlbumFolder* pDocumentRoot = m_pAlbumRoot->AddFolder( CSchema::uriDocumentRoot );
00456 CAlbumFolder* pDocumentAll = pDocumentRoot->AddFolder( CSchema::uriDocumentAll );
00457 }
00458
00459 if ( m_pAlbumRoot->GetFolderCount() != nCount )
00460 {
00461 for ( POSITION pos = LibraryMaps.GetFileIterator() ; pos ; )
00462 {
00463 CLibraryFile* pFile = LibraryMaps.GetNextFile( pos );
00464 if ( pFile->IsAvailable() ) m_pAlbumRoot->OrganiseFile( pFile );
00465 }
00466 }
00467 }
00468
00470
00471
00472 void CLibraryFolders::OnFileDelete(CLibraryFile* pFile)
00473 {
00474 if ( m_pAlbumRoot != NULL ) m_pAlbumRoot->OnFileDelete( pFile );
00475 }
00476
00478
00479
00480 void CLibraryFolders::Clear()
00481 {
00482 for ( POSITION pos = GetFolderIterator() ; pos ; )
00483 {
00484 delete GetNextFolder( pos );
00485 }
00486
00487 m_pFolders.RemoveAll();
00488
00489 if ( m_pAlbumRoot != NULL ) delete m_pAlbumRoot;
00490 m_pAlbumRoot = NULL;
00491 }
00492
00494
00495
00496 BOOL CLibraryFolders::ThreadScan(BOOL* pbContinue, BOOL bForce)
00497 {
00498 BOOL bChanged = FALSE;
00499
00500 {
00501 CQuickLock oLock( Library.m_pSection );
00502 m_bRemoveMask = TRUE;
00503 }
00504
00505 for ( POSITION pos = GetFolderIterator() ; pos && *pbContinue ; )
00506 {
00507 CLibraryFolder* pFolder = GetNextFolder( pos );
00508
00509 if ( GetFileAttributes( pFolder->m_sPath ) != 0xFFFFFFFF )
00510 {
00511 if ( bForce || pFolder->CheckMonitor() )
00512 {
00513 if ( pFolder->ThreadScan() ) bChanged = TRUE;
00514 }
00515
00516 pFolder->SetMonitor();
00517 }
00518 }
00519
00520 {
00521 CQuickLock oLock( Library.m_pSection );
00522 m_bRemoveMask = FALSE;
00523 }
00524
00525 return bChanged;
00526 }
00527
00529
00530
00531 void CLibraryFolders::Serialize(CArchive& ar, int nVersion)
00532 {
00533 if ( ar.IsStoring() )
00534 {
00535 ar.WriteCount( GetFolderCount() );
00536
00537 for ( POSITION pos = GetFolderIterator() ; pos ; )
00538 {
00539 GetNextFolder( pos )->Serialize( ar, nVersion );
00540 }
00541 }
00542 else
00543 {
00544 for ( int nCount = ar.ReadCount() ; nCount > 0 ; nCount-- )
00545 {
00546 CLibraryFolder* pFolder = new CLibraryFolder( NULL );
00547 pFolder->Serialize( ar, nVersion );
00548 m_pFolders.AddTail( pFolder );
00549 }
00550 }
00551
00552 if ( nVersion >= 6 ) GetAlbumRoot()->Serialize( ar, nVersion );
00553 }
00554
00556
00557
00558 IMPLEMENT_DISPATCH(CLibraryFolders, LibraryFolders)
00559
00560 STDMETHODIMP CLibraryFolders::XLibraryFolders::get_Application(IApplication FAR* FAR* ppApplication)
00561 {
00562 METHOD_PROLOGUE( CLibraryFolders, LibraryFolders )
00563 *ppApplication = Application.GetApp();
00564 return S_OK;
00565 }
00566
00567 STDMETHODIMP CLibraryFolders::XLibraryFolders::get_Library(ILibrary FAR* FAR* ppLibrary)
00568 {
00569 METHOD_PROLOGUE( CLibraryFolders, LibraryFolders )
00570 *ppLibrary = (ILibrary*)Library.GetInterface( IID_ILibrary, TRUE );
00571 return S_OK;
00572 }
00573
00574 STDMETHODIMP CLibraryFolders::XLibraryFolders::get__NewEnum(IUnknown FAR* FAR* ppEnum)
00575 {
00576 METHOD_PROLOGUE( CLibraryFolders, LibraryFolders )
00577 return E_NOTIMPL;
00578 }
00579
00580 STDMETHODIMP CLibraryFolders::XLibraryFolders::get_Item(VARIANT vIndex, ILibraryFolder FAR* FAR* ppFolder)
00581 {
00582 METHOD_PROLOGUE( CLibraryFolders, LibraryFolders )
00583
00584 CLibraryFolder* pFolder = NULL;
00585 *ppFolder = NULL;
00586
00587 if ( vIndex.vt == VT_BSTR )
00588 {
00589 CString strName( vIndex.bstrVal );
00590 pFolder = pThis->GetFolder( strName );
00591 }
00592 else
00593 {
00594 VARIANT va;
00595 VariantInit( &va );
00596
00597 if ( FAILED( VariantChangeType( &va, (VARIANT FAR*)&vIndex, 0, VT_I4 ) ) )
00598 return E_INVALIDARG;
00599 if ( va.lVal < 0 || va.lVal >= pThis->GetFolderCount() )
00600 return E_INVALIDARG;
00601
00602 for ( POSITION pos = pThis->GetFolderIterator() ; pos ; )
00603 {
00604 pFolder = pThis->GetNextFolder( pos );
00605 if ( va.lVal-- == 0 ) break;
00606 pFolder = NULL;
00607 }
00608 }
00609
00610 *ppFolder = pFolder ? (ILibraryFolder*)pFolder->GetInterface( IID_ILibraryFolder, TRUE ) : NULL;
00611
00612 return S_OK;
00613 }
00614
00615 STDMETHODIMP CLibraryFolders::XLibraryFolders::get_Count(LONG FAR* pnCount)
00616 {
00617 METHOD_PROLOGUE( CLibraryFolders, LibraryFolders )
00618 *pnCount = pThis->GetFolderCount();
00619 return S_OK;
00620 }