⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 collectionfile.cpp

📁 著名的下载软件核心Shareaza
💻 CPP
字号:
//
// ColletionFile.cpp
//
// Copyright (c) Shareaza Development Team, 2002-2004.
// This file is part of SHAREAZA (www.shareaza.com)
//
// Shareaza is free software; you can redistribute it
// and/or modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// Shareaza is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Shareaza; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//

#include "StdAfx.h"
#include "Shareaza.h"
#include "CollectionFile.h"

#include "ZIPFile.h"
#include "Buffer.h"
#include "XML.h"
#include "Schema.h"
#include "SchemaCache.h"

#include "Library.h"
#include "Downloads.h"
#include "ShareazaURL.h"
#include "SharedFile.h"

#include "SHA.h"
#include "MD5.h"
#include "ED2K.h"
#include "TigerTree.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

IMPLEMENT_DYNAMIC(CCollectionFile, CComObject)


/////////////////////////////////////////////////////////////////////////////
// CCollectionFile construction

CCollectionFile::CCollectionFile()
{
	m_pMetadata = NULL;
}

CCollectionFile::~CCollectionFile()
{
	Close();
}

/////////////////////////////////////////////////////////////////////////////
// CCollectionFile open a collection file

BOOL CCollectionFile::Open(LPCTSTR pszFile)
{
	Close();
	CZIPFile pZIP;
	return pZIP.Open( pszFile ) && LoadManifest( pZIP );
}

BOOL CCollectionFile::Attach(HANDLE hFile)
{
	Close();
	CZIPFile pZIP;
	return pZIP.Attach( hFile ) && LoadManifest( pZIP );
}

/////////////////////////////////////////////////////////////////////////////
// CCollectionFile close a collection file

void CCollectionFile::Close()
{
	for ( POSITION pos = GetFileIterator() ; pos ; ) delete GetNextFile( pos );
	m_pFiles.RemoveAll();
	
	if ( m_pMetadata != NULL ) delete m_pMetadata;
	m_pMetadata = NULL;
	
	m_sTitle.Empty();
	m_sThisURI.Empty();
	m_sParentURI.Empty();
}

/////////////////////////////////////////////////////////////////////////////
// CCollectionFile find a file by URN

CCollectionFile::File* CCollectionFile::FindByURN(LPCTSTR pszURN)
{
	SHA1 pSHA1; MD5 pMD5; TIGEROOT pTiger; MD4 pED2K;
	
	BOOL bSHA1	= CSHA::HashFromURN( pszURN, &pSHA1 );
	BOOL bMD5	= CMD5::HashFromURN( pszURN, &pMD5 );
	BOOL bTiger	= CTigerNode::HashFromURN( pszURN, &pTiger );
	BOOL bED2K	= CED2K::HashFromURN( pszURN, &pED2K );
	
	for ( POSITION pos = GetFileIterator() ; pos ; )
	{
		File* pFile = GetNextFile( pos );
		
		if ( bSHA1 && pFile->m_bSHA1 && pSHA1 == pFile->m_pSHA1 ) return pFile;
		if ( bMD5 && pFile->m_bMD5 && pMD5 == pFile->m_pMD5 ) return pFile;
		if ( bTiger && pFile->m_bTiger && pTiger == pFile->m_pTiger ) return pFile;
		if ( bED2K && pFile->m_bED2K && pED2K == pFile->m_pED2K ) return pFile;
	}
	
	return NULL;
}

/////////////////////////////////////////////////////////////////////////////
// CCollectionFile find a shared file

CCollectionFile::File* CCollectionFile::FindFile(CLibraryFile* pShared, BOOL bApply)
{
	File* pFile = NULL;
	
	for ( POSITION pos = GetFileIterator() ; pos ; )
	{
		pFile = GetNextFile( pos );
		if ( pShared->m_bSHA1 && pFile->m_bSHA1 && pShared->m_pSHA1 == pFile->m_pSHA1 ) break;
		if ( pShared->m_bMD5 && pFile->m_bMD5 && pShared->m_pMD5 == pFile->m_pMD5 ) break;
		if ( pShared->m_bTiger && pFile->m_bTiger && pShared->m_pTiger == pFile->m_pTiger ) break;
		if ( pShared->m_bED2K && pFile->m_bED2K && pShared->m_pED2K == pFile->m_pED2K ) break;
		pFile = NULL;
	}
	
	if ( bApply && pFile != NULL ) pFile->ApplyMetadata( pShared );
	
	return pFile;
}

/////////////////////////////////////////////////////////////////////////////
// CCollectionFile get count

int CCollectionFile::GetMissingCount()
{
	int nCount =0;
	
	for ( POSITION pos = GetFileIterator() ; pos ; )
	{
		File* pFile = GetNextFile( pos );
		if ( ! pFile->IsComplete() && ! pFile->IsDownloading() ) nCount++;
	}
	
	return nCount;
}

/////////////////////////////////////////////////////////////////////////////
// CCollectionFile load the manifest

BOOL CCollectionFile::LoadManifest(CZIPFile& pZIP)
{
	CZIPFile::File* pFile = pZIP.GetFile( _T("Collection.xml"), TRUE );
	if ( pFile == NULL ) return FALSE;
	
	CBuffer* pBuffer = pFile->Decompress();
	if ( pBuffer == NULL ) return FALSE;
	
	CXMLElement* pXML = CXMLElement::FromString( pBuffer->ReadString( pBuffer->m_nLength, CP_UTF8 ), TRUE );
	delete pBuffer;
	
	if ( pXML == NULL ) return FALSE;
	if ( ! pXML->IsNamed( _T("collection") ) ) return FALSE;
	
	CXMLElement* pProperties = pXML->GetElementByName( _T("properties") );
	if ( pProperties == NULL ) return FALSE;
	CXMLElement* pContents = pXML->GetElementByName( _T("contents") );
	if ( pContents == NULL ) return FALSE;
	
	for ( POSITION pos = pContents->GetElementIterator() ; pos ; )
	{
		File* pFile = new File( this );
		
		if ( pFile->Parse( pContents->GetNextElement( pos ) ) )
		{
			m_pFiles.AddTail( pFile );
		}
		else
		{
			delete pFile;
			Close();
			return FALSE;
		}
	}
	
	if ( CXMLElement* pMetadata = pProperties->GetElementByName( _T("metadata") ) )
	{
		m_pMetadata = CloneMetadata( pMetadata );
		if ( m_pMetadata != NULL ) m_sThisURI = m_pMetadata->GetAttributeValue( CXMLAttribute::schemaName );
	}
	
	if ( CXMLElement* pTitle = pProperties->GetElementByName( _T("title") ) )
	{
		m_sTitle = pTitle->GetValue();
	}
	
	if ( CXMLElement* pMounting = pProperties->GetElementByName( _T("mounting") ) )
	{
		if ( CXMLElement* pParent = pMounting->GetElementByName( _T("parent") ) )
		{
			m_sParentURI = pParent->GetAttributeValue( _T("uri") );
		}
		if ( CXMLElement* pThis = pMounting->GetElementByName( _T("this") ) )
		{
			m_sThisURI = pThis->GetAttributeValue( _T("uri") );
		}
	}
	
	delete pXML;
	return TRUE;
}

/////////////////////////////////////////////////////////////////////////////
// CCollectionFile clone metadata

CXMLElement* CCollectionFile::CloneMetadata(CXMLElement* pMetadata)
{
	CString strURI = pMetadata->GetAttributeValue( _T("xmlns:s") );
	if ( strURI.IsEmpty() ) return NULL;
	
	CXMLElement* pCore = pMetadata->GetFirstElement();
	if ( pCore == NULL ) return NULL;
	
	if ( CSchema* pSchema = SchemaCache.Get( strURI ) )
	{
		pMetadata = pSchema->Instantiate();
	}
	else
	{
		pMetadata = new CXMLElement( NULL, pCore->GetName() + 's' );
		pMetadata->AddAttribute( CXMLAttribute::schemaName, strURI );
	}
	
	pCore = pCore->Clone();
	pMetadata->AddElement( pCore );
	
	CString strName = pMetadata->GetName();
	if ( _tcsnicmp( strName, _T("s:"), 2 ) == 0 ) pMetadata->SetName( strName.Mid( 2 ) );
	
	strName = pCore->GetName();
	if ( _tcsnicmp( strName, _T("s:"), 2 ) == 0 ) pCore->SetName( strName.Mid( 2 ) );
	
	for ( POSITION pos = pCore->GetElementIterator() ; pos ; )
	{
		CXMLNode* pNode = pCore->GetNextElement( pos );
		CString strName = pNode->GetName();
		if ( _tcsnicmp( strName, _T("s:"), 2 ) == 0 ) pNode->SetName( strName.Mid( 2 ) );
	}
	
	for ( pos = pCore->GetAttributeIterator() ; pos ; )
	{
		CXMLNode* pNode = pCore->GetNextAttribute( pos );
		CString strName = pNode->GetName();
		if ( _tcsnicmp( strName, _T("s:"), 2 ) == 0 ) pNode->SetName( strName.Mid( 2 ) );
	}
	
	return pMetadata;
}


/////////////////////////////////////////////////////////////////////////////
// CCollectionFile::File construction

CCollectionFile::File::File(CCollectionFile* pParent)
{
	m_pParent	= pParent;
	m_bSHA1		= FALSE;
	m_bMD5		= FALSE;
	m_bTiger	= FALSE;
	m_bED2K		= FALSE;
	m_nSize		= SIZE_UNKNOWN;
	m_pMetadata	= NULL;
}

CCollectionFile::File::~File()
{
	if ( m_pMetadata != NULL ) delete m_pMetadata;
}

/////////////////////////////////////////////////////////////////////////////
// CCollectionFile::File parse

BOOL CCollectionFile::File::Parse(CXMLElement* pRoot)
{
	if ( ! pRoot->IsNamed( _T("file") ) ) return FALSE;
	
	for ( POSITION pos = pRoot->GetElementIterator() ; pos ; )
	{
		CXMLElement* pXML = pRoot->GetNextElement( pos );
		
		if ( pXML->IsNamed( _T("id") ) )
		{
			m_bSHA1		|= CSHA::HashFromURN( pXML->GetValue(), &m_pSHA1 );
			m_bMD5		|= CMD5::HashFromURN( pXML->GetValue(), &m_pMD5 );
			m_bTiger	|= CTigerNode::HashFromURN( pXML->GetValue(), &m_pTiger );
			m_bED2K		|= CED2K::HashFromURN( pXML->GetValue(), &m_pED2K );
		}
		else if ( pXML->IsNamed( _T("description") ) )
		{
			if ( CXMLElement* pName = pXML->GetElementByName( _T("name") ) )
			{
				m_sName = pName->GetValue();
			}
			if ( CXMLElement* pSize = pXML->GetElementByName( _T("size") ) )
			{
				_stscanf( pSize->GetValue(), _T("%I64i"), &m_nSize );
			}
		}
		else if ( pXML->IsNamed( _T("metadata") ) )
		{
			if ( m_pMetadata != NULL ) delete m_pMetadata;
			m_pMetadata = CCollectionFile::CloneMetadata( pXML );
		}
		else if ( pXML->IsNamed( _T("packaged") ) )
		{
			if ( CXMLElement* pSource = pXML->GetElementByName( _T("source") ) )
			{
				m_sSource = pSource->GetValue();
			}
		}
	}
	
	return m_bSHA1 || m_bMD5 || m_bTiger || m_bED2K;
}

/////////////////////////////////////////////////////////////////////////////
// CCollectionFile::File state

BOOL CCollectionFile::File::IsComplete() const
{
	if ( m_bSHA1 && LibraryMaps.LookupFileBySHA1( &m_pSHA1, FALSE, FALSE, TRUE ) )
		return TRUE;
	if ( m_bTiger && LibraryMaps.LookupFileByTiger( &m_pTiger, FALSE, FALSE, TRUE ) )
		return TRUE;
	if ( m_bED2K && LibraryMaps.LookupFileByED2K( &m_pED2K, FALSE, FALSE, TRUE ) )
		return TRUE;
	return FALSE;
}

BOOL CCollectionFile::File::IsDownloading() const
{
	if ( m_bSHA1 && Downloads.FindBySHA1( &m_pSHA1 ) )
		return TRUE;
	if ( m_bTiger && Downloads.FindByTiger( &m_pTiger ) )
		return TRUE;
	if ( m_bED2K && Downloads.FindByED2K( &m_pED2K ) )
		return TRUE;
	return FALSE;
}

/////////////////////////////////////////////////////////////////////////////
// CCollectionFile::File download

BOOL CCollectionFile::File::Download()
{
	CShareazaURL pURL;
	
	if ( IsComplete() || IsDownloading() ) return FALSE;
	
	pURL.m_nAction	= CShareazaURL::uriDownload;
	pURL.m_bSHA1	= m_bSHA1;
	pURL.m_pSHA1	= m_pSHA1;
	pURL.m_bMD5		= m_bMD5;
	pURL.m_pMD5		= m_pMD5;
	pURL.m_bTiger	= m_bTiger;
	pURL.m_pTiger	= m_pTiger;
	pURL.m_bED2K	= m_bED2K;
	pURL.m_pED2K	= m_pED2K;
	pURL.m_sName	= m_sName;
	pURL.m_bSize	= ( m_nSize != SIZE_UNKNOWN );
	pURL.m_nSize	= m_nSize;
	
	return Downloads.Add( &pURL ) != NULL;
}

/////////////////////////////////////////////////////////////////////////////
// CCollectionFile::File apply metadata to a shared file

BOOL CCollectionFile::File::ApplyMetadata(CLibraryFile* pShared)
{
	ASSERT( pShared != NULL );
	if ( m_pMetadata == NULL ) return FALSE;
	
	CXMLElement* pXML = m_pMetadata->Clone();
	BOOL bResult = pShared->SetMetadata( pXML );
	delete pXML;
	
	return bResult;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -