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

📄 ieprotocol.cpp

📁 著名的下载软件核心Shareaza
💻 CPP
字号:
//
// IEProtocol.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 "IEProtocol.h"
#include "Buffer.h"

#include "SHA.h"
#include "ZIPFile.h"
#include "ShellIcons.h"
#include "Connection.h"


/////////////////////////////////////////////////////////////////////////////
// System

IMPLEMENT_DYNAMIC(CIEProtocol, CCmdTarget)
IMPLEMENT_DYNAMIC(CIEProtocolRequest, CCmdTarget)

BEGIN_INTERFACE_MAP(CIEProtocol, CCmdTarget)
	INTERFACE_PART(CIEProtocol, IID_IClassFactory, ClassFactory)
END_INTERFACE_MAP()

BEGIN_INTERFACE_MAP(CIEProtocolRequest, CCmdTarget)
	INTERFACE_PART(CIEProtocolRequest, IID_IInternetProtocol, InternetProtocol)
	INTERFACE_PART(CIEProtocolRequest, IID_IInternetProtocolRoot, InternetProtocol)
	INTERFACE_PART(CIEProtocolRequest, IID_IInternetProtocolInfo, InternetProtocolInfo)
END_INTERFACE_MAP()

/////////////////////////////////////////////////////////////////////////////
// Global Instance

CLSID	CIEProtocol::clsidProtocol	= { 0x18d11ed9, 0x1264, 0x48a1, { 0x9e, 0x14, 0x20, 0xf2, 0xc6, 0x33, 0x24, 0x2b } };
LPCWSTR	CIEProtocol::pszProtocols[]	= { L"p2p-col", L"telnet", NULL };

CIEProtocol IEProtocol;


/////////////////////////////////////////////////////////////////////////////
// CIEProtocol construction

CIEProtocol::CIEProtocol()
{
	m_pShutdown = NULL;
	m_nRequests = 0;
	
	m_pCollZIP	= NULL;
}

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

/////////////////////////////////////////////////////////////////////////////
// CIEProtocol session control

BOOL CIEProtocol::Create()
{
	CSingleLock pLock( &m_pSection, TRUE );
	
	if ( m_pSession != NULL ) return TRUE;
	
	CComPtr<IInternetSession> pSession;
	
	if ( FAILED( CoInternetGetSession( 0, &pSession, 0 ) ) ) return FALSE;
	
	for ( int nProtocol = 0 ; pszProtocols[ nProtocol ] != NULL ; nProtocol++ )
	{
		if ( FAILED( pSession->RegisterNameSpace( &m_xClassFactory, clsidProtocol,
			 pszProtocols[ nProtocol ], 0, NULL, 0 ) ) ) return FALSE;
	}
	
	m_pSession = pSession;
	
	return TRUE;
}

void CIEProtocol::Close()
{
	CSingleLock pLock( &m_pSection, TRUE );
	
	if ( m_nRequests > 0 )
	{
		m_pShutdown = new CEvent();
		
		pLock.Unlock();
		WaitForSingleObject( *m_pShutdown, 5000 );
		pLock.Lock();
		
		delete m_pShutdown;
		m_pShutdown = NULL;
		
		ASSERT( m_nRequests == 0 );
		m_nRequests = 0;
	}
	
	if ( m_pSession != NULL )
	{
		for ( int nProtocol = 0 ; pszProtocols[ nProtocol ] != NULL ; nProtocol++ )
		{
			m_pSession->UnregisterNameSpace( &m_xClassFactory, pszProtocols[ nProtocol ] );
		}
		
		m_pSession = NULL;
	}
	
	SetCollection( NULL, NULL );
}

/////////////////////////////////////////////////////////////////////////////
// CIEProtocol request management

CIEProtocolRequest* CIEProtocol::CreateRequest()
{
	CSingleLock pLock( &m_pSection, TRUE );
	return new CIEProtocolRequest( this );
}

void CIEProtocol::OnRequestConstruct(CIEProtocolRequest* pRequest)
{
	CSingleLock pLock( &m_pSection, TRUE );
	m_nRequests ++;
}

void CIEProtocol::OnRequestDestruct(CIEProtocolRequest* pRequest)
{
	CSingleLock pLock( &m_pSection, TRUE );
	
	ASSERT( m_nRequests > 0 );
	
	if ( --m_nRequests == 0 )
	{
		if ( m_pShutdown != NULL ) m_pShutdown->SetEvent();
	}
}

/////////////////////////////////////////////////////////////////////////////
// CIEProtocol IClassFactory implementation

IMPLEMENT_UNKNOWN(CIEProtocol, ClassFactory)

STDMETHODIMP CIEProtocol::XClassFactory::CreateInstance(IUnknown* pUnkOuter, REFIID riid, void** ppvObject)
{
	METHOD_PROLOGUE(CIEProtocol, ClassFactory)
	
	if ( pUnkOuter != NULL ) return CLASS_E_NOAGGREGATION;
	
	CIEProtocolRequest* pRequest = pThis->CreateRequest();
	HRESULT hr = pRequest->ExternalQueryInterface( &riid, ppvObject );
	pRequest->ExternalRelease();
	
	return hr;
}

STDMETHODIMP CIEProtocol::XClassFactory::LockServer(BOOL fLock)
{
	METHOD_PROLOGUE(CIEProtocol, ClassFactory)
	
	if ( fLock )
		AfxOleLockApp();
	else
		AfxOleUnlockApp();
	
	return S_OK;
}


/////////////////////////////////////////////////////////////////////////////
// CIEProtocolRequest construction

CIEProtocolRequest::CIEProtocolRequest(CIEProtocol* pProtocol)
{
	ASSERT( pProtocol != NULL );
	
	m_pProtocol	= pProtocol;
	m_pBuffer	= new CBuffer();
	
	m_pProtocol->OnRequestConstruct( this );
}

CIEProtocolRequest::~CIEProtocolRequest()
{
	ASSERT( m_pSink == NULL );
	
	m_pProtocol->OnRequestDestruct( this );
	
	delete m_pBuffer;
}

/////////////////////////////////////////////////////////////////////////////
// CIEProtocolRequest transfer handler

HRESULT CIEProtocolRequest::OnStart(LPCTSTR pszURL, IInternetProtocolSink* pSink, IInternetBindInfo* pBindInfo, DWORD dwFlags)
{
	CSingleLock pLock( &m_pSection, TRUE );
	CString strMimeType;
	
	if ( m_pSink != NULL ) return E_UNEXPECTED;
	
	HRESULT hr = m_pProtocol->OnRequest( pszURL, m_pBuffer, &strMimeType,
					( dwFlags & PI_PARSE_URL ) != 0 );
	
	if ( ( dwFlags & PI_PARSE_URL ) || ( hr == INET_E_INVALID_URL ) ) return hr;
	
	m_pSink = pSink;
	
	if ( SUCCEEDED(hr) )
	{
		if ( strMimeType.GetLength() > 0 )
		{
			BSTR bsMimeType = strMimeType.AllocSysString();
			m_pSink->ReportProgress( BINDSTATUS_MIMETYPEAVAILABLE, bsMimeType );
			SysFreeString( bsMimeType );
		}
		
		m_pSink->ReportData( BSCF_LASTDATANOTIFICATION, m_pBuffer->m_nLength, m_pBuffer->m_nLength );
		m_pSink->ReportResult( S_OK, 200, L"OK" );
	}
	else
	{
		m_pSink->ReportResult( INET_E_OBJECT_NOT_FOUND, 404, L"OK" );
	}
	
	return hr;
}

HRESULT CIEProtocolRequest::OnRead(void* pv, ULONG cb, ULONG* pcbRead)
{
	CSingleLock pLock( &m_pSection, TRUE );
	
	if ( m_pSink == NULL ) return E_UNEXPECTED;
	
	cb = min( cb, m_pBuffer->m_nLength );
	if ( pcbRead != NULL ) *pcbRead = cb;
	
	if ( cb > 0 )
	{
		CopyMemory( pv, m_pBuffer->m_pBuffer, cb );
		m_pBuffer->Remove( cb );
	}
	
	return ( cb > 0 || m_pBuffer->m_nLength > 0 ) ? S_OK : S_FALSE;
}

HRESULT CIEProtocolRequest::OnTerminate()
{
	CSingleLock pLock( &m_pSection, TRUE );
	
	if ( m_pSink == NULL ) return E_UNEXPECTED;
	
	m_pSink = NULL;
	m_pBuffer->Clear();
	
	return S_OK;
}

/////////////////////////////////////////////////////////////////////////////
// CIEProtocolRequest IInternetProtocol implementation

IMPLEMENT_UNKNOWN(CIEProtocolRequest, InternetProtocol)

STDMETHODIMP CIEProtocolRequest::XInternetProtocol::Abort(HRESULT hrReason, DWORD dwOptions)
{
	METHOD_PROLOGUE(CIEProtocolRequest, InternetProtocol)
	return S_OK;
}

STDMETHODIMP CIEProtocolRequest::XInternetProtocol::Continue(PROTOCOLDATA *pProtocolData)
{
	METHOD_PROLOGUE(CIEProtocolRequest, InternetProtocol)
	return S_OK;
}

STDMETHODIMP CIEProtocolRequest::XInternetProtocol::Resume()
{
	METHOD_PROLOGUE(CIEProtocolRequest, InternetProtocol)
	return E_NOTIMPL;
}

STDMETHODIMP CIEProtocolRequest::XInternetProtocol::Start(LPCWSTR szUrl, IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo, DWORD grfPI, HANDLE_PTR dwReserved)
{
	METHOD_PROLOGUE(CIEProtocolRequest, InternetProtocol)
	return pThis->OnStart( CString( szUrl ), pOIProtSink, pOIBindInfo, grfPI );
}

STDMETHODIMP CIEProtocolRequest::XInternetProtocol::Suspend()
{
	METHOD_PROLOGUE(CIEProtocolRequest, InternetProtocol)
	return E_NOTIMPL;
}

STDMETHODIMP CIEProtocolRequest::XInternetProtocol::Terminate(DWORD dwOptions)
{
	METHOD_PROLOGUE(CIEProtocolRequest, InternetProtocol)
	return pThis->OnTerminate();
}

STDMETHODIMP CIEProtocolRequest::XInternetProtocol::LockRequest(DWORD dwOptions)
{
	METHOD_PROLOGUE(CIEProtocolRequest, InternetProtocol)
	return S_OK;
}

STDMETHODIMP CIEProtocolRequest::XInternetProtocol::Read(void *pv, ULONG cb, ULONG *pcbRead)
{
	METHOD_PROLOGUE(CIEProtocolRequest, InternetProtocol)
	return pThis->OnRead( pv, cb, pcbRead );
}

STDMETHODIMP CIEProtocolRequest::XInternetProtocol::Seek(LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
{
	METHOD_PROLOGUE(CIEProtocolRequest, InternetProtocol)
	return E_FAIL;
}

STDMETHODIMP CIEProtocolRequest::XInternetProtocol::UnlockRequest()
{
	METHOD_PROLOGUE(CIEProtocolRequest, InternetProtocol)
	return S_OK;
}

/////////////////////////////////////////////////////////////////////////////
// CIEProtocolRequest IInternetProtocolInfo implementation

IMPLEMENT_UNKNOWN(CIEProtocolRequest, InternetProtocolInfo)

STDMETHODIMP CIEProtocolRequest::XInternetProtocolInfo::CombineUrl(LPCWSTR pwzBaseUrl, LPCWSTR pwzRelativeUrl, DWORD dwCombineFlags, LPWSTR pwzResult, DWORD cchResult, DWORD *pcchResult, DWORD dwReserved)
{
	METHOD_PROLOGUE(CIEProtocolRequest, InternetProtocolInfo)
	return INET_E_DEFAULT_ACTION;
}

STDMETHODIMP CIEProtocolRequest::XInternetProtocolInfo::CompareUrl(LPCWSTR pwzUrl1, LPCWSTR pwzUrl2, DWORD dwCompareFlags)
{
	METHOD_PROLOGUE(CIEProtocolRequest, InternetProtocolInfo)
	return INET_E_DEFAULT_ACTION;
}

STDMETHODIMP CIEProtocolRequest::XInternetProtocolInfo::ParseUrl(LPCWSTR pwzUrl, PARSEACTION ParseAction, DWORD dwParseFlags, LPWSTR pwzResult, DWORD cchResult, DWORD *pcchResult, DWORD dwReserved)
{
	METHOD_PROLOGUE(CIEProtocolRequest, InternetProtocolInfo)
	switch ( ParseAction )
	{
	case PARSE_SECURITY_URL:
		// Substitute a known remote URL, to class this as an offsite/high-security zone
		*pcchResult = _tcslen( _T("http://p2p-col.shareaza.com/") ) + 1;
		if ( cchResult < *pcchResult ) return S_FALSE;
		wcscpy( pwzResult, L"http://p2p-col.shareaza.com/" );
		return S_OK;
	default:
		return INET_E_DEFAULT_ACTION;
	}
}

STDMETHODIMP CIEProtocolRequest::XInternetProtocolInfo::QueryInfo(LPCWSTR pwzUrl, QUERYOPTION OueryOption, DWORD dwQueryFlags, LPVOID pBuffer, DWORD cbBuffer, DWORD *pcbBuf, DWORD dwReserved)
{
	METHOD_PROLOGUE(CIEProtocolRequest, InternetProtocolInfo)
	switch ( OueryOption )
	{
	case QUERY_USES_NETWORK:
	case QUERY_IS_SECURE:
	case QUERY_IS_SAFE:
		*pcbBuf = 4;
		if ( cbBuffer < 4 ) return S_FALSE;
		*(DWORD*)pBuffer = 0;
		return S_OK;
	default:
		return INET_E_DEFAULT_ACTION;
	}
}


/////////////////////////////////////////////////////////////////////////////
// CIEProtocol request handler

HRESULT CIEProtocol::OnRequest(LPCTSTR pszURL, CBuffer* pBuffer, CString* psMimeType, BOOL bParseOnly)
{
	CSingleLock pLock( &m_pSection, TRUE );
	
	if ( _tcsnicmp( pszURL, _T("p2p-col://"), 10 ) == 0 )
	{
		return OnRequestRAZACOL( pszURL + 10, pBuffer, psMimeType, bParseOnly );
	}
	else
	{
		return INET_E_INVALID_URL;
	}
}

/////////////////////////////////////////////////////////////////////////////
// CIEProtocol request handler - "p2p-col"

HRESULT CIEProtocol::OnRequestRAZACOL(LPCTSTR pszURL, CBuffer* pBuffer, CString* psMimeType, BOOL bParseOnly)
{
	if ( _tcslen( pszURL ) < 32 + 1 ) return INET_E_INVALID_URL;
	if ( pszURL[32] != '/' ) return INET_E_INVALID_URL;
	
	SHA1 pSHA1;
	if ( ! CSHA::HashFromString( pszURL, &pSHA1 ) ) return INET_E_INVALID_URL;
	
	if ( m_pCollZIP == NULL || ! m_pCollZIP->IsOpen() ) return INET_E_OBJECT_NOT_FOUND;
	if ( m_pCollSHA1 != pSHA1 ) return INET_E_OBJECT_NOT_FOUND;
	
	CString strPath( pszURL + 32 );
	strPath = CConnection::URLDecode( strPath );
	if ( strPath.Right( 1 ) == _T("/") ) strPath += _T("index.htm");
	
	CZIPFile::File* pFile = m_pCollZIP->GetFile( strPath.Mid( 1 ) );
	if ( pFile == NULL ) return INET_E_OBJECT_NOT_FOUND;
	
	CBuffer* pSource = pFile->Decompress();
	if ( pSource == NULL ) return INET_E_OBJECT_NOT_FOUND;
	
	pBuffer->AddBuffer( pSource );
	delete pSource;
	
	ShellIcons.Lookup( strPath, NULL, NULL, NULL, psMimeType );
	
	return S_OK;
}

/////////////////////////////////////////////////////////////////////////////
// CIEProtocol collection

BOOL CIEProtocol::SetCollection(SHA1* pSHA1, LPCTSTR pszPath, CString* psIndex)
{
	CSingleLock pLock( &m_pSection, TRUE );
	
	if ( m_pCollZIP != NULL )
	{
		delete m_pCollZIP;
		m_pCollZIP = NULL;
	}
	
	if ( pSHA1 == NULL || pszPath == NULL ) return TRUE;
	
	m_pCollZIP	= new CZIPFile();
	m_pCollSHA1	= *pSHA1;
	
	if ( m_pCollZIP->Open( pszPath ) )
	{
		if ( CZIPFile::File* pFile = m_pCollZIP->GetFile( _T("index.htm"), TRUE ) )
		{
			if ( psIndex != NULL ) *psIndex = pFile->m_sName;
		}
		
		return TRUE;
	}
	else
	{
		delete m_pCollZIP;
		m_pCollZIP = NULL;
		return FALSE;
	}
}

⌨️ 快捷键说明

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