Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members

IEProtocol.cpp

Go to the documentation of this file.
00001 //
00002 // IEProtocol.cpp
00003 //
00004 // Copyright (c) Shareaza Development Team, 2002-2005.
00005 // This file is part of SHAREAZA (www.shareaza.com)
00006 //
00007 // Shareaza is free software; you can redistribute it
00008 // and/or modify it under the terms of the GNU General Public License
00009 // as published by the Free Software Foundation; either version 2 of
00010 // the License, or (at your option) any later version.
00011 //
00012 // Shareaza is distributed in the hope that it will be useful,
00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 // GNU General Public License for more details.
00016 //
00017 // You should have received a copy of the GNU General Public License
00018 // along with Shareaza; if not, write to the Free Software
00019 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020 //
00021 
00022 #include "StdAfx.h"
00023 #include "Shareaza.h"
00024 #include "IEProtocol.h"
00025 #include "Buffer.h"
00026 
00027 #include "SHA.h"
00028 #include "ZIPFile.h"
00029 #include "ShellIcons.h"
00030 #include "Connection.h"
00031 
00032 
00034 // System
00035 
00036 IMPLEMENT_DYNAMIC(CIEProtocol, CCmdTarget)
00037 IMPLEMENT_DYNAMIC(CIEProtocolRequest, CCmdTarget)
00038 
00039 BEGIN_INTERFACE_MAP(CIEProtocol, CCmdTarget)
00040         INTERFACE_PART(CIEProtocol, IID_IClassFactory, ClassFactory)
00041 END_INTERFACE_MAP()
00042 
00043 BEGIN_INTERFACE_MAP(CIEProtocolRequest, CCmdTarget)
00044         INTERFACE_PART(CIEProtocolRequest, IID_IInternetProtocol, InternetProtocol)
00045         INTERFACE_PART(CIEProtocolRequest, IID_IInternetProtocolRoot, InternetProtocol)
00046         INTERFACE_PART(CIEProtocolRequest, IID_IInternetProtocolInfo, InternetProtocolInfo)
00047 END_INTERFACE_MAP()
00048 
00050 // Global Instance
00051 
00052 CLSID   CIEProtocol::clsidProtocol      = { 0x18d11ed9, 0x1264, 0x48a1, { 0x9e, 0x14, 0x20, 0xf2, 0xc6, 0x33, 0x24, 0x2b } };
00053 LPCWSTR CIEProtocol::pszProtocols[]     = { L"p2p-col", L"telnet", NULL };
00054 
00055 CIEProtocol IEProtocol;
00056 
00057 
00059 // CIEProtocol construction
00060 
00061 CIEProtocol::CIEProtocol()
00062 {
00063         m_pShutdown = NULL;
00064         m_nRequests = 0;
00065 
00066         m_pCollZIP      = NULL;
00067 }
00068 
00069 CIEProtocol::~CIEProtocol()
00070 {
00071         Close();
00072 }
00073 
00075 // CIEProtocol session control
00076 
00077 BOOL CIEProtocol::Create()
00078 {
00079         CSingleLock pLock( &m_pSection, TRUE );
00080 
00081         if ( m_pSession ) return TRUE;
00082 
00083         CComPtr<IInternetSession> pSession;
00084 
00085         if ( FAILED( CoInternetGetSession( 0, &pSession, 0 ) ) ) return FALSE;
00086 
00087         for ( int nProtocol = 0 ; pszProtocols[ nProtocol ] != NULL ; nProtocol++ )
00088         {
00089                 if ( FAILED( pSession->RegisterNameSpace( &m_xClassFactory, clsidProtocol,
00090                          pszProtocols[ nProtocol ], 0, NULL, 0 ) ) ) return FALSE;
00091         }
00092 
00093         m_pSession = pSession;
00094 
00095         return TRUE;
00096 }
00097 
00098 void CIEProtocol::Close()
00099 {
00100         CSingleLock pLock( &m_pSection, TRUE );
00101 
00102         if ( m_nRequests > 0 )
00103         {
00104                 m_pShutdown = new CEvent();
00105 
00106                 pLock.Unlock();
00107                 WaitForSingleObject( *m_pShutdown, 5000 );
00108                 pLock.Lock();
00109 
00110                 delete m_pShutdown;
00111                 m_pShutdown = NULL;
00112 
00113                 ASSERT( m_nRequests == 0 );
00114                 m_nRequests = 0;
00115         }
00116 
00117         if ( m_pSession )
00118         {
00119                 for ( int nProtocol = 0 ; pszProtocols[ nProtocol ] != NULL ; nProtocol++ )
00120                 {
00121                         m_pSession->UnregisterNameSpace( &m_xClassFactory, pszProtocols[ nProtocol ] );
00122                 }
00123 
00124                 m_pSession = NULL;
00125         }
00126 
00127         SetCollection( NULL, NULL );
00128 }
00129 
00131 // CIEProtocol request management
00132 
00133 CIEProtocolRequest* CIEProtocol::CreateRequest()
00134 {
00135         CSingleLock pLock( &m_pSection, TRUE );
00136         return new CIEProtocolRequest( this );
00137 }
00138 
00139 void CIEProtocol::OnRequestConstruct(CIEProtocolRequest* pRequest)
00140 {
00141         CSingleLock pLock( &m_pSection, TRUE );
00142         m_nRequests ++;
00143 }
00144 
00145 void CIEProtocol::OnRequestDestruct(CIEProtocolRequest* pRequest)
00146 {
00147         CSingleLock pLock( &m_pSection, TRUE );
00148 
00149         ASSERT( m_nRequests > 0 );
00150 
00151         if ( --m_nRequests == 0 )
00152         {
00153                 if ( m_pShutdown != NULL ) m_pShutdown->SetEvent();
00154         }
00155 }
00156 
00158 // CIEProtocol IClassFactory implementation
00159 
00160 IMPLEMENT_UNKNOWN(CIEProtocol, ClassFactory)
00161 
00162 STDMETHODIMP CIEProtocol::XClassFactory::CreateInstance(IUnknown* pUnkOuter, REFIID riid, void** ppvObject)
00163 {
00164         METHOD_PROLOGUE(CIEProtocol, ClassFactory)
00165 
00166         if ( pUnkOuter != NULL ) return CLASS_E_NOAGGREGATION;
00167 
00168         CIEProtocolRequest* pRequest = pThis->CreateRequest();
00169         HRESULT hr = pRequest->ExternalQueryInterface( &riid, ppvObject );
00170         pRequest->ExternalRelease();
00171 
00172         return hr;
00173 }
00174 
00175 STDMETHODIMP CIEProtocol::XClassFactory::LockServer(BOOL fLock)
00176 {
00177         METHOD_PROLOGUE(CIEProtocol, ClassFactory)
00178 
00179         if ( fLock )
00180                 AfxOleLockApp();
00181         else
00182                 AfxOleUnlockApp();
00183 
00184         return S_OK;
00185 }
00186 
00187 
00189 // CIEProtocolRequest construction
00190 
00191 CIEProtocolRequest::CIEProtocolRequest(CIEProtocol* pProtocol)
00192 {
00193         ASSERT( pProtocol != NULL );
00194 
00195         m_pProtocol     = pProtocol;
00196         m_pBuffer       = new CBuffer();
00197 
00198         m_pProtocol->OnRequestConstruct( this );
00199 }
00200 
00201 CIEProtocolRequest::~CIEProtocolRequest()
00202 {
00203         ASSERT( m_pSink == NULL );
00204 
00205         m_pProtocol->OnRequestDestruct( this );
00206 
00207         delete m_pBuffer;
00208 }
00209 
00211 // CIEProtocolRequest transfer handler
00212 
00213 HRESULT CIEProtocolRequest::OnStart(LPCTSTR pszURL, IInternetProtocolSink* pSink, IInternetBindInfo* pBindInfo, DWORD dwFlags)
00214 {
00215         CSingleLock pLock( &m_pSection, TRUE );
00216         CString strMimeType;
00217 
00218         if ( m_pSink ) return E_UNEXPECTED;
00219 
00220         HRESULT hr = m_pProtocol->OnRequest( pszURL, m_pBuffer, &strMimeType,
00221                                         ( dwFlags & PI_PARSE_URL ) != 0 );
00222 
00223         if ( ( dwFlags & PI_PARSE_URL ) || ( hr == INET_E_INVALID_URL ) ) return hr;
00224 
00225         m_pSink = pSink;
00226 
00227         if ( SUCCEEDED(hr) )
00228         {
00229                 if ( strMimeType.GetLength() > 0 )
00230                 {
00231                         BSTR bsMimeType = strMimeType.AllocSysString();
00232                         m_pSink->ReportProgress( BINDSTATUS_MIMETYPEAVAILABLE, bsMimeType );
00233                         SysFreeString( bsMimeType );
00234                 }
00235 
00236                 m_pSink->ReportData( BSCF_LASTDATANOTIFICATION, m_pBuffer->m_nLength, m_pBuffer->m_nLength );
00237                 m_pSink->ReportResult( S_OK, 200, L"OK" );
00238         }
00239         else
00240         {
00241                 m_pSink->ReportResult( INET_E_OBJECT_NOT_FOUND, 404, L"OK" );
00242         }
00243 
00244         return hr;
00245 }
00246 
00247 HRESULT CIEProtocolRequest::OnRead(void* pv, ULONG cb, ULONG* pcbRead)
00248 {
00249         CSingleLock pLock( &m_pSection, TRUE );
00250 
00251         if ( m_pSink == NULL ) return E_UNEXPECTED;
00252 
00253         cb = min( cb, m_pBuffer->m_nLength );
00254         if ( pcbRead != NULL ) *pcbRead = cb;
00255 
00256         if ( cb > 0 )
00257         {
00258                 CopyMemory( pv, m_pBuffer->m_pBuffer, cb );
00259                 m_pBuffer->Remove( cb );
00260         }
00261 
00262         return ( cb > 0 || m_pBuffer->m_nLength > 0 ) ? S_OK : S_FALSE;
00263 }
00264 
00265 HRESULT CIEProtocolRequest::OnTerminate()
00266 {
00267         CSingleLock pLock( &m_pSection, TRUE );
00268 
00269         if ( m_pSink == NULL ) return E_UNEXPECTED;
00270 
00271         m_pSink = NULL;
00272         m_pBuffer->Clear();
00273 
00274         return S_OK;
00275 }
00276 
00278 // CIEProtocolRequest IInternetProtocol implementation
00279 
00280 IMPLEMENT_UNKNOWN(CIEProtocolRequest, InternetProtocol)
00281 
00282 STDMETHODIMP CIEProtocolRequest::XInternetProtocol::Abort(HRESULT hrReason, DWORD dwOptions)
00283 {
00284         METHOD_PROLOGUE(CIEProtocolRequest, InternetProtocol)
00285         return S_OK;
00286 }
00287 
00288 STDMETHODIMP CIEProtocolRequest::XInternetProtocol::Continue(PROTOCOLDATA *pProtocolData)
00289 {
00290         METHOD_PROLOGUE(CIEProtocolRequest, InternetProtocol)
00291         return S_OK;
00292 }
00293 
00294 STDMETHODIMP CIEProtocolRequest::XInternetProtocol::Resume()
00295 {
00296         METHOD_PROLOGUE(CIEProtocolRequest, InternetProtocol)
00297         return E_NOTIMPL;
00298 }
00299 
00300 STDMETHODIMP CIEProtocolRequest::XInternetProtocol::Start(LPCWSTR szUrl, IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo, DWORD grfPI, HANDLE_PTR dwReserved)
00301 {
00302         METHOD_PROLOGUE(CIEProtocolRequest, InternetProtocol)
00303         return pThis->OnStart( CString( szUrl ), pOIProtSink, pOIBindInfo, grfPI );
00304 }
00305 
00306 STDMETHODIMP CIEProtocolRequest::XInternetProtocol::Suspend()
00307 {
00308         METHOD_PROLOGUE(CIEProtocolRequest, InternetProtocol)
00309         return E_NOTIMPL;
00310 }
00311 
00312 STDMETHODIMP CIEProtocolRequest::XInternetProtocol::Terminate(DWORD dwOptions)
00313 {
00314         METHOD_PROLOGUE(CIEProtocolRequest, InternetProtocol)
00315         return pThis->OnTerminate();
00316 }
00317 
00318 STDMETHODIMP CIEProtocolRequest::XInternetProtocol::LockRequest(DWORD dwOptions)
00319 {
00320         METHOD_PROLOGUE(CIEProtocolRequest, InternetProtocol)
00321         return S_OK;
00322 }
00323 
00324 STDMETHODIMP CIEProtocolRequest::XInternetProtocol::Read(void *pv, ULONG cb, ULONG *pcbRead)
00325 {
00326         METHOD_PROLOGUE(CIEProtocolRequest, InternetProtocol)
00327         return pThis->OnRead( pv, cb, pcbRead );
00328 }
00329 
00330 STDMETHODIMP CIEProtocolRequest::XInternetProtocol::Seek(LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
00331 {
00332         METHOD_PROLOGUE(CIEProtocolRequest, InternetProtocol)
00333         return E_FAIL;
00334 }
00335 
00336 STDMETHODIMP CIEProtocolRequest::XInternetProtocol::UnlockRequest()
00337 {
00338         METHOD_PROLOGUE(CIEProtocolRequest, InternetProtocol)
00339         return S_OK;
00340 }
00341 
00343 // CIEProtocolRequest IInternetProtocolInfo implementation
00344 
00345 IMPLEMENT_UNKNOWN(CIEProtocolRequest, InternetProtocolInfo)
00346 
00347 STDMETHODIMP CIEProtocolRequest::XInternetProtocolInfo::CombineUrl(LPCWSTR pwzBaseUrl, LPCWSTR pwzRelativeUrl, DWORD dwCombineFlags, LPWSTR pwzResult, DWORD cchResult, DWORD *pcchResult, DWORD dwReserved)
00348 {
00349         METHOD_PROLOGUE(CIEProtocolRequest, InternetProtocolInfo)
00350         return INET_E_DEFAULT_ACTION;
00351 }
00352 
00353 STDMETHODIMP CIEProtocolRequest::XInternetProtocolInfo::CompareUrl(LPCWSTR pwzUrl1, LPCWSTR pwzUrl2, DWORD dwCompareFlags)
00354 {
00355         METHOD_PROLOGUE(CIEProtocolRequest, InternetProtocolInfo)
00356         return INET_E_DEFAULT_ACTION;
00357 }
00358 
00359 STDMETHODIMP CIEProtocolRequest::XInternetProtocolInfo::ParseUrl(LPCWSTR pwzUrl, PARSEACTION ParseAction, DWORD dwParseFlags, LPWSTR pwzResult, DWORD cchResult, DWORD *pcchResult, DWORD dwReserved)
00360 {
00361         METHOD_PROLOGUE(CIEProtocolRequest, InternetProtocolInfo)
00362         switch ( ParseAction )
00363         {
00364         case PARSE_SECURITY_URL:
00365                 // Substitute a known remote URL, to class this as an offsite/high-security zone
00366                 *pcchResult = _tcslen( _T("http://p2p-col.shareaza.com/") ) + 1;
00367                 if ( cchResult < *pcchResult ) return S_FALSE;
00368                 wcscpy( pwzResult, L"http://p2p-col.shareaza.com/" );
00369                 return S_OK;
00370         default:
00371                 return INET_E_DEFAULT_ACTION;
00372         }
00373 }
00374 
00375 STDMETHODIMP CIEProtocolRequest::XInternetProtocolInfo::QueryInfo(LPCWSTR pwzUrl, QUERYOPTION OueryOption, DWORD dwQueryFlags, LPVOID pBuffer, DWORD cbBuffer, DWORD *pcbBuf, DWORD dwReserved)
00376 {
00377         METHOD_PROLOGUE(CIEProtocolRequest, InternetProtocolInfo)
00378         switch ( OueryOption )
00379         {
00380         case QUERY_USES_NETWORK:
00381         case QUERY_IS_SECURE:
00382         case QUERY_IS_SAFE:
00383                 *pcbBuf = 4;
00384                 if ( cbBuffer < 4 ) return S_FALSE;
00385                 *(DWORD*)pBuffer = 0;
00386                 return S_OK;
00387         default:
00388                 return INET_E_DEFAULT_ACTION;
00389         }
00390 }
00391 
00392 
00394 // CIEProtocol request handler
00395 
00396 HRESULT CIEProtocol::OnRequest(LPCTSTR pszURL, CBuffer* pBuffer, CString* psMimeType, BOOL bParseOnly)
00397 {
00398         CSingleLock pLock( &m_pSection, TRUE );
00399 
00400         if ( _tcsnicmp( pszURL, _T("p2p-col://"), 10 ) == 0 )
00401         {
00402                 return OnRequestRAZACOL( pszURL + 10, pBuffer, psMimeType, bParseOnly );
00403         }
00404         else
00405         {
00406                 return INET_E_INVALID_URL;
00407         }
00408 }
00409 
00411 // CIEProtocol request handler - "p2p-col"
00412 
00413 HRESULT CIEProtocol::OnRequestRAZACOL(LPCTSTR pszURL, CBuffer* pBuffer, CString* psMimeType, BOOL bParseOnly)
00414 {
00415         if ( _tcslen( pszURL ) < 32 + 1 ) return INET_E_INVALID_URL;
00416         if ( pszURL[32] != '/' ) return INET_E_INVALID_URL;
00417 
00418         SHA1 pSHA1;
00419         if ( ! CSHA::HashFromString( pszURL, &pSHA1 ) ) return INET_E_INVALID_URL;
00420 
00421         if ( m_pCollZIP == NULL || ! m_pCollZIP->IsOpen() ) return INET_E_OBJECT_NOT_FOUND;
00422         if ( m_pCollSHA1 != pSHA1 ) return INET_E_OBJECT_NOT_FOUND;
00423 
00424         CString strPath( pszURL + 32 );
00425         strPath = CConnection::URLDecode( strPath );
00426         if ( strPath.Right( 1 ) == _T("/") ) strPath += _T("index.htm");
00427 
00428         CZIPFile::File* pFile = m_pCollZIP->GetFile( strPath.Mid( 1 ) );
00429         if ( pFile == NULL ) return INET_E_OBJECT_NOT_FOUND;
00430 
00431         CBuffer* pSource = pFile->Decompress();
00432         if ( pSource == NULL ) return INET_E_OBJECT_NOT_FOUND;
00433 
00434         pBuffer->AddBuffer( pSource );
00435         delete pSource;
00436 
00437         ShellIcons.Lookup( strPath, NULL, NULL, NULL, psMimeType );
00438 
00439         return S_OK;
00440 }
00441 
00443 // CIEProtocol collection
00444 
00445 BOOL CIEProtocol::SetCollection(SHA1* pSHA1, LPCTSTR pszPath, CString* psIndex)
00446 {
00447         CSingleLock pLock( &m_pSection, TRUE );
00448 
00449         if ( m_pCollZIP != NULL )
00450         {
00451                 delete m_pCollZIP;
00452                 m_pCollZIP = NULL;
00453         }
00454 
00455         if ( pSHA1 == NULL || pszPath == NULL ) return TRUE;
00456 
00457         m_pCollZIP      = new CZIPFile();
00458         m_pCollSHA1     = *pSHA1;
00459 
00460         if ( m_pCollZIP->Open( pszPath ) )
00461         {
00462                 if ( CZIPFile::File* pFile = m_pCollZIP->GetFile( _T("index.htm"), TRUE ) )
00463                 {
00464                         if ( psIndex != NULL ) *psIndex = pFile->m_sName;
00465                 }
00466 
00467                 return TRUE;
00468         }
00469         else
00470         {
00471                 delete m_pCollZIP;
00472                 m_pCollZIP = NULL;
00473                 return FALSE;
00474         }
00475 }

Generated on Thu Dec 15 10:39:43 2005 for Shareaza 2.2.1.0 by  doxygen 1.4.2