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 "CollectionFile.h"
00025
00026 #include "ZIPFile.h"
00027 #include "Buffer.h"
00028 #include "XML.h"
00029 #include "Schema.h"
00030 #include "SchemaCache.h"
00031
00032 #include "Library.h"
00033 #include "Downloads.h"
00034 #include "ShareazaURL.h"
00035 #include "SharedFile.h"
00036
00037 #include "SHA.h"
00038 #include "MD5.h"
00039 #include "ED2K.h"
00040 #include "TigerTree.h"
00041
00042 #ifdef _DEBUG
00043 #undef THIS_FILE
00044 static char THIS_FILE[]=__FILE__;
00045 #define new DEBUG_NEW
00046 #endif
00047
00048 IMPLEMENT_DYNAMIC(CCollectionFile, CComObject)
00049
00050
00051
00052
00053
00054 CCollectionFile::CCollectionFile()
00055 {
00056 m_pMetadata = NULL;
00057 }
00058
00059 CCollectionFile::~CCollectionFile()
00060 {
00061 Close();
00062 }
00063
00065
00066
00067 BOOL CCollectionFile::Open(LPCTSTR pszFile)
00068 {
00069 Close();
00070 CZIPFile pZIP;
00071 return pZIP.Open( pszFile ) && LoadManifest( pZIP );
00072 }
00073
00074 BOOL CCollectionFile::Attach(HANDLE hFile)
00075 {
00076 Close();
00077 CZIPFile pZIP;
00078 return pZIP.Attach( hFile ) && LoadManifest( pZIP );
00079 }
00080
00082
00083
00084 void CCollectionFile::Close()
00085 {
00086 for ( POSITION pos = GetFileIterator() ; pos ; ) delete GetNextFile( pos );
00087 m_pFiles.RemoveAll();
00088
00089 if ( m_pMetadata != NULL ) delete m_pMetadata;
00090 m_pMetadata = NULL;
00091
00092 m_sTitle.Empty();
00093 m_sThisURI.Empty();
00094 m_sParentURI.Empty();
00095 }
00096
00098
00099
00100 CCollectionFile::File* CCollectionFile::FindByURN(LPCTSTR pszURN)
00101 {
00102 SHA1 pSHA1; MD5 pMD5; TIGEROOT pTiger; MD4 pED2K;
00103
00104 BOOL bSHA1 = CSHA::HashFromURN( pszURN, &pSHA1 );
00105 BOOL bMD5 = CMD5::HashFromURN( pszURN, &pMD5 );
00106 BOOL bTiger = CTigerNode::HashFromURN( pszURN, &pTiger );
00107 BOOL bED2K = CED2K::HashFromURN( pszURN, &pED2K );
00108
00109 for ( POSITION pos = GetFileIterator() ; pos ; )
00110 {
00111 File* pFile = GetNextFile( pos );
00112
00113 if ( bSHA1 && pFile->m_bSHA1 && pSHA1 == pFile->m_pSHA1 ) return pFile;
00114 if ( bMD5 && pFile->m_bMD5 && pMD5 == pFile->m_pMD5 ) return pFile;
00115 if ( bTiger && pFile->m_bTiger && pTiger == pFile->m_pTiger ) return pFile;
00116 if ( bED2K && pFile->m_bED2K && pED2K == pFile->m_pED2K ) return pFile;
00117 }
00118
00119 return NULL;
00120 }
00121
00123
00124
00125 CCollectionFile::File* CCollectionFile::FindFile(CLibraryFile* pShared, BOOL bApply)
00126 {
00127 File* pFile = NULL;
00128
00129 for ( POSITION pos = GetFileIterator() ; pos ; )
00130 {
00131 pFile = GetNextFile( pos );
00132 if ( pShared->m_bSHA1 && pFile->m_bSHA1 && pShared->m_pSHA1 == pFile->m_pSHA1 ) break;
00133 if ( pShared->m_bMD5 && pFile->m_bMD5 && pShared->m_pMD5 == pFile->m_pMD5 ) break;
00134 if ( pShared->m_bTiger && pFile->m_bTiger && pShared->m_pTiger == pFile->m_pTiger ) break;
00135 if ( pShared->m_bED2K && pFile->m_bED2K && pShared->m_pED2K == pFile->m_pED2K ) break;
00136 pFile = NULL;
00137 }
00138
00139 if ( bApply && pFile != NULL ) pFile->ApplyMetadata( pShared );
00140
00141 return pFile;
00142 }
00143
00145
00146
00147 int CCollectionFile::GetMissingCount()
00148 {
00149 int nCount =0;
00150
00151 for ( POSITION pos = GetFileIterator() ; pos ; )
00152 {
00153 File* pFile = GetNextFile( pos );
00154 if ( ! pFile->IsComplete() && ! pFile->IsDownloading() ) nCount++;
00155 }
00156
00157 return nCount;
00158 }
00159
00161
00162
00163 BOOL CCollectionFile::LoadManifest(CZIPFile& pZIP)
00164 {
00165 CZIPFile::File* pFile = pZIP.GetFile( _T("Collection.xml"), TRUE );
00166 if ( pFile == NULL ) return FALSE;
00167
00168 CBuffer* pBuffer = pFile->Decompress();
00169 if ( pBuffer == NULL ) return FALSE;
00170
00171 CXMLElement* pXML = CXMLElement::FromString( pBuffer->ReadString( pBuffer->m_nLength, CP_UTF8 ), TRUE );
00172 delete pBuffer;
00173
00174 if ( pXML == NULL ) return FALSE;
00175 if ( ! pXML->IsNamed( _T("collection") ) ) return FALSE;
00176
00177 CXMLElement* pProperties = pXML->GetElementByName( _T("properties") );
00178 if ( pProperties == NULL ) return FALSE;
00179 CXMLElement* pContents = pXML->GetElementByName( _T("contents") );
00180 if ( pContents == NULL ) return FALSE;
00181
00182 for ( POSITION pos = pContents->GetElementIterator() ; pos ; )
00183 {
00184 File* pFile = new File( this );
00185
00186 if ( pFile->Parse( pContents->GetNextElement( pos ) ) )
00187 {
00188 m_pFiles.AddTail( pFile );
00189 }
00190 else
00191 {
00192 delete pFile;
00193 Close();
00194 return FALSE;
00195 }
00196 }
00197
00198 if ( CXMLElement* pMetadata = pProperties->GetElementByName( _T("metadata") ) )
00199 {
00200 m_pMetadata = CloneMetadata( pMetadata );
00201 if ( m_pMetadata != NULL ) m_sThisURI = m_pMetadata->GetAttributeValue( CXMLAttribute::schemaName );
00202 }
00203
00204 if ( CXMLElement* pTitle = pProperties->GetElementByName( _T("title") ) )
00205 {
00206 m_sTitle = pTitle->GetValue();
00207 }
00208
00209 if ( CXMLElement* pMounting = pProperties->GetElementByName( _T("mounting") ) )
00210 {
00211 if ( CXMLElement* pParent = pMounting->GetElementByName( _T("parent") ) )
00212 {
00213 m_sParentURI = pParent->GetAttributeValue( _T("uri") );
00214 }
00215 if ( CXMLElement* pThis = pMounting->GetElementByName( _T("this") ) )
00216 {
00217 m_sThisURI = pThis->GetAttributeValue( _T("uri") );
00218 }
00219 }
00220
00221 delete pXML;
00222 return TRUE;
00223 }
00224
00226
00227
00228 CXMLElement* CCollectionFile::CloneMetadata(CXMLElement* pMetadata)
00229 {
00230 CString strURI = pMetadata->GetAttributeValue( _T("xmlns:s") );
00231 if ( strURI.IsEmpty() ) return NULL;
00232
00233 CXMLElement* pCore = pMetadata->GetFirstElement();
00234 if ( pCore == NULL ) return NULL;
00235
00236 if ( CSchema* pSchema = SchemaCache.Get( strURI ) )
00237 {
00238 pMetadata = pSchema->Instantiate();
00239 }
00240 else
00241 {
00242 pMetadata = new CXMLElement( NULL, pCore->GetName() + 's' );
00243 pMetadata->AddAttribute( CXMLAttribute::schemaName, strURI );
00244 }
00245
00246 pCore = pCore->Clone();
00247 pMetadata->AddElement( pCore );
00248
00249 CString strName = pMetadata->GetName();
00250 if ( _tcsnicmp( strName, _T("s:"), 2 ) == 0 ) pMetadata->SetName( strName.Mid( 2 ) );
00251
00252 strName = pCore->GetName();
00253 if ( _tcsnicmp( strName, _T("s:"), 2 ) == 0 ) pCore->SetName( strName.Mid( 2 ) );
00254
00255 for ( POSITION pos = pCore->GetElementIterator() ; pos ; )
00256 {
00257 CXMLNode* pNode = pCore->GetNextElement( pos );
00258 CString strName = pNode->GetName();
00259 if ( _tcsnicmp( strName, _T("s:"), 2 ) == 0 ) pNode->SetName( strName.Mid( 2 ) );
00260 }
00261
00262 for ( POSITION pos = pCore->GetAttributeIterator() ; pos ; )
00263 {
00264 CXMLNode* pNode = pCore->GetNextAttribute( pos );
00265 CString strName = pNode->GetName();
00266 if ( _tcsnicmp( strName, _T("s:"), 2 ) == 0 ) pNode->SetName( strName.Mid( 2 ) );
00267 }
00268
00269 return pMetadata;
00270 }
00271
00272
00274
00275
00276 CCollectionFile::File::File(CCollectionFile* pParent)
00277 {
00278 m_pParent = pParent;
00279 m_bSHA1 = FALSE;
00280 m_bMD5 = FALSE;
00281 m_bTiger = FALSE;
00282 m_bED2K = FALSE;
00283 m_nSize = SIZE_UNKNOWN;
00284 m_pMetadata = NULL;
00285 }
00286
00287 CCollectionFile::File::~File()
00288 {
00289 if ( m_pMetadata != NULL ) delete m_pMetadata;
00290 }
00291
00293
00294
00295 BOOL CCollectionFile::File::Parse(CXMLElement* pRoot)
00296 {
00297 if ( ! pRoot->IsNamed( _T("file") ) ) return FALSE;
00298
00299 for ( POSITION pos = pRoot->GetElementIterator() ; pos ; )
00300 {
00301 CXMLElement* pXML = pRoot->GetNextElement( pos );
00302
00303 if ( pXML->IsNamed( _T("id") ) )
00304 {
00305 m_bSHA1 |= CSHA::HashFromURN( pXML->GetValue(), &m_pSHA1 );
00306 m_bMD5 |= CMD5::HashFromURN( pXML->GetValue(), &m_pMD5 );
00307 m_bTiger |= CTigerNode::HashFromURN( pXML->GetValue(), &m_pTiger );
00308 m_bED2K |= CED2K::HashFromURN( pXML->GetValue(), &m_pED2K );
00309 }
00310 else if ( pXML->IsNamed( _T("description") ) )
00311 {
00312 if ( CXMLElement* pName = pXML->GetElementByName( _T("name") ) )
00313 {
00314 m_sName = pName->GetValue();
00315 }
00316 if ( CXMLElement* pSize = pXML->GetElementByName( _T("size") ) )
00317 {
00318 _stscanf( pSize->GetValue(), _T("%I64i"), &m_nSize );
00319 }
00320 }
00321 else if ( pXML->IsNamed( _T("metadata") ) )
00322 {
00323 if ( m_pMetadata != NULL ) delete m_pMetadata;
00324 m_pMetadata = CCollectionFile::CloneMetadata( pXML );
00325 }
00326 else if ( pXML->IsNamed( _T("packaged") ) )
00327 {
00328 if ( CXMLElement* pSource = pXML->GetElementByName( _T("source") ) )
00329 {
00330 m_sSource = pSource->GetValue();
00331 }
00332 }
00333 }
00334
00335 return m_bSHA1 || m_bMD5 || m_bTiger || m_bED2K;
00336 }
00337
00339
00340
00341 BOOL CCollectionFile::File::IsComplete() const
00342 {
00343 if ( m_bSHA1 && LibraryMaps.LookupFileBySHA1( &m_pSHA1, FALSE, TRUE ) )
00344 return TRUE;
00345 if ( m_bTiger && LibraryMaps.LookupFileByTiger( &m_pTiger, FALSE, TRUE ) )
00346 return TRUE;
00347 if ( m_bED2K && LibraryMaps.LookupFileByED2K( &m_pED2K, FALSE, TRUE ) )
00348 return TRUE;
00349 return FALSE;
00350 }
00351
00352 BOOL CCollectionFile::File::IsDownloading() const
00353 {
00354 if ( m_bSHA1 && Downloads.FindBySHA1( &m_pSHA1 ) )
00355 return TRUE;
00356 if ( m_bTiger && Downloads.FindByTiger( &m_pTiger ) )
00357 return TRUE;
00358 if ( m_bED2K && Downloads.FindByED2K( &m_pED2K ) )
00359 return TRUE;
00360 return FALSE;
00361 }
00362
00364
00365
00366 BOOL CCollectionFile::File::Download()
00367 {
00368 CShareazaURL pURL;
00369
00370 if ( IsComplete() || IsDownloading() ) return FALSE;
00371
00372 pURL.m_nAction = CShareazaURL::uriDownload;
00373 pURL.m_bSHA1 = m_bSHA1;
00374 pURL.m_pSHA1 = m_pSHA1;
00375 pURL.m_bMD5 = m_bMD5;
00376 pURL.m_pMD5 = m_pMD5;
00377 pURL.m_bTiger = m_bTiger;
00378 pURL.m_pTiger = m_pTiger;
00379 pURL.m_bED2K = m_bED2K;
00380 pURL.m_pED2K = m_pED2K;
00381 pURL.m_sName = m_sName;
00382 pURL.m_bSize = ( m_nSize != SIZE_UNKNOWN );
00383 pURL.m_nSize = m_nSize;
00384
00385 return Downloads.Add( &pURL ) != NULL;
00386 }
00387
00389
00390
00391 BOOL CCollectionFile::File::ApplyMetadata(CLibraryFile* pShared)
00392 {
00393 ASSERT( pShared != NULL );
00394 if ( m_pMetadata == NULL ) return FALSE;
00395
00396 CXMLElement* pXML = m_pMetadata->Clone();
00397 BOOL bResult = pShared->SetMetadata( pXML );
00398 delete pXML;
00399
00400 return bResult;
00401 }