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 "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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 }