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 "Settings.h"
00025 #include "Download.h"
00026 #include "Downloads.h"
00027 #include "DownloadSource.h"
00028 #include "DownloadTransfer.h"
00029 #include "DownloadTransferHTTP.h"
00030 #include "FragmentedFile.h"
00031 #include "Network.h"
00032 #include "Buffer.h"
00033 #include "SourceURL.h"
00034 #include "GProfile.h"
00035 #include "SHA.h"
00036 #include "ED2K.h"
00037 #include "TigerTree.h"
00038 #include "XML.h"
00039
00040 #ifdef _DEBUG
00041 #undef THIS_FILE
00042 static char THIS_FILE[]=__FILE__;
00043 #define new DEBUG_NEW
00044 #endif
00045
00046
00048
00049
00050 CDownloadTransferHTTP::CDownloadTransferHTTP(CDownloadSource* pSource) : CDownloadTransfer( pSource, PROTOCOL_HTTP )
00051 {
00052 m_nRequests = 0;
00053 m_tContent = 0;
00054
00055 m_bBadResponse = FALSE;
00056 m_bBusyFault = FALSE;
00057 m_bRangeFault = FALSE;
00058 m_bHashMatch = FALSE;
00059 m_bTigerFetch = FALSE;
00060 m_bTigerIgnore = FALSE;
00061 m_bMetaFetch = FALSE;
00062 m_bMetaIgnore = FALSE;
00063
00064 m_nRetryDelay = Settings.Downloads.RetryDelay;
00065 }
00066
00067 CDownloadTransferHTTP::~CDownloadTransferHTTP()
00068 {
00069 }
00070
00072
00073
00074 BOOL CDownloadTransferHTTP::Initiate()
00075 {
00076 theApp.Message( MSG_DEFAULT, IDS_DOWNLOAD_CONNECTING,
00077 (LPCTSTR)CString( inet_ntoa( m_pSource->m_pAddress ) ), m_pSource->m_nPort,
00078 (LPCTSTR)m_pDownload->GetDisplayName() );
00079
00080 if ( ConnectTo( &m_pSource->m_pAddress, m_pSource->m_nPort ) )
00081 {
00082 SetState( dtsConnecting );
00083
00084 if ( ! m_pDownload->IsBoosted() )
00085 m_mInput.pLimit = m_mOutput.pLimit = &Downloads.m_nLimitGeneric;
00086
00087 return TRUE;
00088 }
00089 else
00090 {
00091 theApp.Message( MSG_ERROR, IDS_DOWNLOAD_CONNECT_ERROR, (LPCTSTR)m_sAddress );
00092 Close( TS_UNKNOWN );
00093 return FALSE;
00094 }
00095 }
00096
00098
00099
00100 BOOL CDownloadTransferHTTP::AcceptPush(CConnection* pConnection)
00101 {
00102 AttachTo( pConnection );
00103
00104 theApp.Message( MSG_DEFAULT, IDS_DOWNLOAD_PUSHED, (LPCTSTR)m_sAddress,
00105 (LPCTSTR)m_pDownload->GetDisplayName() );
00106
00107 if ( ! m_pDownload->IsBoosted() )
00108 m_mInput.pLimit = m_mOutput.pLimit = &Downloads.m_nLimitGeneric;
00109
00110 if ( StartNextFragment() ) return TRUE;
00111
00112 return FALSE;
00113 }
00114
00116
00117
00118 void CDownloadTransferHTTP::Close(TRISTATE bKeepSource)
00119 {
00120 if ( m_pSource != NULL && m_nState == dtsDownloading && m_nPosition )
00121 {
00122 if ( m_bRecvBackwards )
00123 {
00124 m_pSource->AddFragment( m_nOffset + m_nLength - m_nPosition, m_nPosition );
00125 }
00126 else
00127 {
00128 m_pSource->AddFragment( m_nOffset, m_nPosition );
00129 }
00130 }
00131
00132 CDownloadTransfer::Close( bKeepSource );
00133 }
00134
00136
00137
00138 void CDownloadTransferHTTP::Boost()
00139 {
00140 m_mInput.pLimit = m_mOutput.pLimit = NULL;
00141 }
00142
00143 DWORD CDownloadTransferHTTP::GetAverageSpeed()
00144 {
00145 if ( m_nState == dtsDownloading )
00146 {
00147 DWORD nTime = ( GetTickCount() - m_tContent ) / 1000;
00148 if ( nTime > 0 ) m_pSource->m_nSpeed = (DWORD)( m_nPosition / nTime );
00149 }
00150
00151 return m_pSource->m_nSpeed;
00152 }
00153
00155
00156
00157 BOOL CDownloadTransferHTTP::OnConnected()
00158 {
00159 theApp.Message( MSG_DEFAULT, IDS_DOWNLOAD_CONNECTED, (LPCTSTR)m_sAddress );
00160
00161 m_tConnected = GetTickCount();
00162
00163 return StartNextFragment();
00164 }
00165
00167
00168
00169 bool VerifySelection(CDownloadTransferHTTP* pTransfer)
00170 {
00171 FF::SimpleFragment oFragment( pTransfer->m_nOffset, pTransfer->m_nOffset + pTransfer->m_nLength );
00172 FF::SimpleFragmentList::IteratorPair p = pTransfer->m_pSource->m_oAvailable.overlappingRange( oFragment );
00173 return pTransfer->m_pSource->m_oAvailable.empty()
00174 || p.first != p.second && p.first->begin() <= pTransfer->m_nOffset
00175 && p.first->end() >= pTransfer->m_nOffset + pTransfer->m_nLength;
00176 }
00177
00178 BOOL CDownloadTransferHTTP::StartNextFragment()
00179 {
00180 ASSERT( this != NULL );
00181 if ( this == NULL ) return FALSE;
00182
00183 m_nOffset = SIZE_UNKNOWN;
00184 m_nPosition = 0;
00185 m_bWantBackwards = FALSE;
00186 m_bRecvBackwards = FALSE;
00187 m_bTigerFetch = FALSE;
00188 m_bMetaFetch = FALSE;
00189
00190 if ( m_pInput == NULL || m_pOutput == NULL
00191 )
00192 {
00193 theApp.Message( MSG_DEFAULT, IDS_DOWNLOAD_CLOSING_EXTRA, (LPCTSTR)m_sAddress );
00194 Close( TS_TRUE );
00195 return FALSE;
00196 }
00197
00198
00199
00200 if ( m_pInput->m_nLength > 0 && m_nRequests > 0 )
00201 {
00202 theApp.Message( MSG_ERROR, IDS_DOWNLOAD_CLOSING_OVERFLOW, (LPCTSTR)m_sAddress );
00203 Close( TS_TRUE );
00204 return FALSE;
00205 }
00206
00207 if ( m_pDownload->m_nSize == SIZE_UNKNOWN )
00208 {
00209 return SendRequest();
00210 }
00211 else if ( m_pDownload->NeedTigerTree() && m_sTigerTree.GetLength() )
00212 {
00213 theApp.Message( MSG_DEFAULT, IDS_DOWNLOAD_TIGER_REQUEST,
00214 (LPCTSTR)m_pDownload->GetDisplayName(), (LPCTSTR)m_sAddress );
00215
00216 m_bTigerFetch = TRUE;
00217 m_bTigerIgnore = TRUE;
00218
00219 return SendRequest();
00220 }
00221 else if ( m_pDownload->m_pXML == NULL && m_sMetadata.GetLength() )
00222 {
00223 theApp.Message( MSG_DEFAULT, IDS_DOWNLOAD_METADATA_REQUEST,
00224 (LPCTSTR)m_pDownload->GetDisplayName(), (LPCTSTR)m_sAddress );
00225
00226 m_bMetaFetch = TRUE;
00227 m_bMetaIgnore = TRUE;
00228
00229 return SendRequest();
00230 }
00231 else if ( m_pDownload->GetFragment( this ) )
00232 {
00233 ASSERT( VerifySelection( this ) );
00234 ChunkifyRequest( &m_nOffset, &m_nLength, Settings.Downloads.ChunkSize, TRUE );
00235 ASSERT( VerifySelection( this ) );
00236
00237 theApp.Message( MSG_DEFAULT, IDS_DOWNLOAD_FRAGMENT_REQUEST,
00238 m_nOffset, m_nOffset + m_nLength - 1,
00239 (LPCTSTR)m_pDownload->GetDisplayName(), (LPCTSTR)m_sAddress );
00240
00241 return SendRequest();
00242 }
00243 else
00244 {
00245 if ( m_pSource != NULL ) m_pSource->SetAvailableRanges( NULL );
00246
00247 theApp.Message( MSG_DEFAULT, IDS_DOWNLOAD_FRAGMENT_END, (LPCTSTR)m_sAddress );
00248 Close( TS_TRUE );
00249
00250 return FALSE;
00251 }
00252 }
00253
00255
00256
00257 BOOL CDownloadTransferHTTP::SubtractRequested(FF::SimpleFragmentList& ppFragments)
00258 {
00259 if ( m_nOffset < SIZE_UNKNOWN && m_nLength < SIZE_UNKNOWN )
00260 {
00261 if ( m_nState == dtsRequesting || m_nState == dtsDownloading )
00262 {
00263 ppFragments.erase( FF::SimpleFragment( m_nOffset, m_nOffset + m_nLength ) );
00264 return TRUE;
00265 }
00266 }
00267
00268 return FALSE;
00269 }
00270
00272
00273
00274 BOOL CDownloadTransferHTTP::SendRequest()
00275 {
00276 CString strLine;
00277
00278 CSourceURL pURL;
00279 if ( ! pURL.ParseHTTP( m_pSource->m_sURL, FALSE ) ) return FALSE;
00280
00281 if ( m_bTigerFetch )
00282 {
00283 pURL.m_sPath = m_sTigerTree;
00284 m_sTigerTree.Empty();
00285 }
00286 else if ( m_bMetaFetch )
00287 {
00288 pURL.m_sPath = m_sMetadata;
00289 m_sMetadata.Empty();
00290 }
00291
00292 if ( Settings.Downloads.RequestHTTP11 )
00293 {
00294 strLine.Format( _T("GET %s HTTP/1.1\r\n"), (LPCTSTR)pURL.m_sPath );
00295 m_pOutput->Print( strLine );
00296
00297 strLine.Format( _T("Host: %s\r\n"), (LPCTSTR)pURL.m_sAddress );
00298 m_pOutput->Print( strLine );
00299 }
00300 else
00301 {
00302 strLine.Format( _T("GET %s HTTP/1.0\r\n"), (LPCTSTR)pURL.m_sPath );
00303 }
00304
00305 theApp.Message( MSG_DEBUG, _T("%s: DOWNLOAD REQUEST: %s"),
00306 (LPCTSTR)m_sAddress, (LPCTSTR)pURL.m_sPath );
00307
00308 m_pOutput->Print( "Connection: Keep-Alive\r\n" );
00309
00310 if ( Settings.Gnutella2.EnableToday ) m_pOutput->Print( "X-Features: g2/1.0\r\n" );
00311
00312 if ( m_bTigerFetch )
00313 {
00314 m_pOutput->Print( "Accept: application/dime, application/tigertree-breadthfirst\r\n" );
00315 }
00316 else if ( m_bMetaFetch )
00317 {
00318 m_pOutput->Print( "Accept: text/xml\r\n" );
00319 }
00320
00321 if ( m_nOffset != SIZE_UNKNOWN && ! m_bTigerFetch && ! m_bMetaFetch )
00322 {
00323 if ( m_nOffset + m_nLength == m_pDownload->m_nSize )
00324 {
00325 strLine.Format( _T("Range: bytes=%I64i-\r\n"), m_nOffset );
00326 }
00327 else
00328 {
00329 strLine.Format( _T("Range: bytes=%I64i-%I64i\r\n"), m_nOffset, m_nOffset + m_nLength - 1 );
00330 }
00331 m_pOutput->Print( strLine );
00332 }
00333 else
00334 {
00335 m_pOutput->Print( "Range: bytes=0-\r\n" );
00336 }
00337
00338 if ( m_bWantBackwards && Settings.Downloads.AllowBackwards )
00339 {
00340 m_pOutput->Print( "Accept-Encoding: backwards\r\n" );
00341 }
00342
00343 strLine = Settings.SmartAgent();
00344
00345 if ( strLine.GetLength() )
00346 {
00347 strLine = _T("User-Agent: ") + strLine + _T("\r\n");
00348 m_pOutput->Print( strLine );
00349 }
00350
00351 if ( m_nRequests == 0 )
00352 {
00353 if ( m_bInitiated ) SendMyAddress();
00354
00355 strLine = MyProfile.GetNick().Left( 255 );
00356
00357 if ( strLine.GetLength() > 0 )
00358 {
00359 strLine = _T("X-Nick: ") + URLEncode( strLine ) + _T("\r\n");
00360 m_pOutput->Print( strLine );
00361 }
00362 }
00363
00364 if ( m_pSource->m_nPort == INTERNET_DEFAULT_HTTP_PORT )
00365 {
00366 int nSlash = m_pSource->m_sURL.ReverseFind( '/' );
00367 if ( nSlash > 0 )
00368 {
00369 strLine = _T("Referrer: ") + m_pSource->m_sURL.Left( nSlash + 1 ) + _T("\r\n");
00370 m_pOutput->Print( strLine );
00371 }
00372 }
00373
00374 m_pOutput->Print( "X-Queue: 0.1\r\n" );
00375
00376 if ( m_pSource->m_bSHA1 && Settings.Library.SourceMesh && ! m_bTigerFetch && ! m_bMetaFetch )
00377 {
00378 CString strURN = CSHA::HashToString( &m_pDownload->m_pSHA1, TRUE );
00379
00380 m_pOutput->Print( "X-Content-URN: " );
00381 m_pOutput->Print( strURN + _T("\r\n") );
00382
00383 if ( m_pSource->m_nGnutella == 1 )
00384 strLine = m_pDownload->GetSourceURLs( &m_pSourcesSent, 15, PROTOCOL_G1, m_pSource );
00385 else
00386 strLine = m_pDownload->GetSourceURLs( &m_pSourcesSent, 15, PROTOCOL_HTTP, m_pSource );
00387
00388 if ( strLine.GetLength() )
00389 {
00390 m_pOutput->Print( "Alt-Location: " );
00391 m_pOutput->Print( strLine + _T("\r\n") );
00392 }
00393
00394 if ( m_pDownload->IsShared() && m_pDownload->IsStarted() && Network.IsStable() )
00395 {
00396 strLine.Format( _T("http://%s:%i/uri-res/N2R?%s "),
00397 (LPCTSTR)CString( inet_ntoa( Network.m_pHost.sin_addr ) ),
00398 htons( Network.m_pHost.sin_port ),
00399 (LPCTSTR)strURN );
00400 strLine += TimeToString( time( NULL ) - 180 );
00401 m_pOutput->Print( "Alt-Location: " );
00402 m_pOutput->Print( strLine + _T("\r\n") );
00403 }
00404 }
00405
00406 m_pOutput->Print( "\r\n" );
00407
00408 SetState( dtsRequesting );
00409 m_tRequest = GetTickCount();
00410 m_bBusyFault = FALSE;
00411 m_bRangeFault = FALSE;
00412 m_bKeepAlive = FALSE;
00413 m_bHashMatch = FALSE;
00414 m_bGotRange = FALSE;
00415 m_bGotRanges = FALSE;
00416 m_bQueueFlag = FALSE;
00417 m_nContentLength = SIZE_UNKNOWN;
00418 m_sContentType.Empty();
00419
00420 m_sTigerTree.Empty();
00421 m_nRequests++;
00422
00423 m_pSource->SetLastSeen();
00424
00425 CDownloadTransfer::OnWrite();
00426
00427 return TRUE;
00428 }
00429
00431
00432
00433 BOOL CDownloadTransferHTTP::OnRun()
00434 {
00435 CDownloadTransfer::OnRun();
00436
00437 DWORD tNow = GetTickCount();
00438
00439 switch ( m_nState )
00440 {
00441 case dtsConnecting:
00442 if ( tNow - m_tConnected > Settings.Connection.TimeoutConnect )
00443 {
00444 theApp.Message( MSG_ERROR, IDS_CONNECTION_TIMEOUT_CONNECT, (LPCTSTR)m_sAddress );
00445 if ( m_pSource != NULL ) m_pSource->PushRequest();
00446 Close( TS_UNKNOWN );
00447 return FALSE;
00448 }
00449 break;
00450
00451 case dtsRequesting:
00452 case dtsHeaders:
00453 if ( tNow - m_tRequest > Settings.Connection.TimeoutHandshake )
00454 {
00455 theApp.Message( MSG_ERROR, IDS_DOWNLOAD_REQUEST_TIMEOUT, (LPCTSTR)m_sAddress );
00456 Close( m_bBusyFault || m_bQueueFlag ? TS_TRUE : TS_UNKNOWN );
00457 return FALSE;
00458 }
00459 break;
00460
00461 case dtsDownloading:
00462 case dtsFlushing:
00463 case dtsTiger:
00464 case dtsMetadata:
00465 if ( tNow - m_mInput.tLast > Settings.Connection.TimeoutTraffic * 2 )
00466 {
00467 theApp.Message( MSG_ERROR, IDS_DOWNLOAD_TRAFFIC_TIMEOUT, (LPCTSTR)m_sAddress );
00468 Close( TS_TRUE );
00469 return FALSE;
00470 }
00471 break;
00472
00473 case dtsBusy:
00474 if ( tNow - m_tRequest > 1000 )
00475 {
00476 theApp.Message( MSG_ERROR, IDS_DOWNLOAD_BUSY, (LPCTSTR)m_sAddress, Settings.Downloads.RetryDelay / 1000 );
00477 Close( TS_TRUE );
00478 return FALSE;
00479 }
00480 break;
00481
00482 case dtsQueued:
00483 if ( tNow >= m_tRequest )
00484 {
00485 return StartNextFragment();
00486 }
00487 break;
00488
00489 }
00490
00491 return TRUE;
00492 }
00493
00495
00496
00497 BOOL CDownloadTransferHTTP::OnRead()
00498 {
00499 CDownloadTransfer::OnRead();
00500
00501 switch ( m_nState )
00502 {
00503 case dtsRequesting:
00504 if ( ! ReadResponseLine() ) return FALSE;
00505 if ( m_nState != dtsHeaders ) break;
00506
00507 case dtsHeaders:
00508 if ( ! ReadHeaders() ) return FALSE;
00509 if ( m_nState != dtsDownloading ) break;
00510
00511 case dtsDownloading:
00512 return ReadContent();
00513
00514 case dtsTiger:
00515 return ReadTiger();
00516
00517 case dtsMetadata:
00518 return ReadMetadata();
00519
00520 case dtsFlushing:
00521 return ReadFlush();
00522
00523 }
00524
00525 return TRUE;
00526 }
00527
00529
00530
00531 BOOL CDownloadTransferHTTP::ReadResponseLine()
00532 {
00533 CString strLine, strCode, strMessage;
00534
00535 if ( ! m_pInput->ReadLine( strLine ) ) return TRUE;
00536 if ( strLine.IsEmpty() ) return TRUE;
00537
00538 if ( strLine.GetLength() > 512 ) strLine = _T("#LINE_TOO_LONG#");
00539
00540 theApp.Message( MSG_DEBUG, _T("%s: DOWNLOAD RESPONSE: %s"), (LPCTSTR)m_sAddress, (LPCTSTR)strLine );
00541
00542 if ( strLine.GetLength() >= 12 && strLine.Left( 9 ) == _T("HTTP/1.1 ") )
00543 {
00544 strCode = strLine.Mid( 9, 3 );
00545 strMessage = strLine.Mid( 12 );
00546 }
00547 else if ( strLine.GetLength() >= 12 && strLine.Left( 9 ) == _T("HTTP/1.0 ") )
00548 {
00549 strCode = strLine.Mid( 9, 3 );
00550 strMessage = strLine.Mid( 12 );
00551 }
00552 else if ( strLine.GetLength() >= 8 && strLine.Left( 4 ) == _T("HTTP") )
00553 {
00554 strCode = strLine.Mid( 5, 3 );
00555 strMessage = strLine.Mid( 8 );
00556 }
00557 else
00558 {
00559 theApp.Message( MSG_ERROR, IDS_DOWNLOAD_NOHTTP, (LPCTSTR)m_sAddress );
00560 Close( TS_FALSE );
00561 return FALSE;
00562 }
00563
00564 if ( strCode == _T("200") || strCode == _T("206") )
00565 {
00566 SetState( dtsHeaders );
00567 }
00568 else if ( strCode == _T("503") )
00569 {
00570 if ( _tcsistr( strMessage, _T("range") ) != NULL )
00571 {
00572 m_bRangeFault = TRUE;
00573 }
00574 else
00575 {
00576 m_bBusyFault = TRUE;
00577 }
00578
00579 SetState( dtsHeaders );
00580 }
00581 else if ( strCode == _T("416") )
00582 {
00583 m_bRangeFault = TRUE;
00584 SetState( dtsHeaders );
00585 }
00586 else if ( FALSE && ( strCode == _T("301") || strCode == _T("302") ) )
00587 {
00588
00589 }
00590 else
00591 {
00592 strMessage.TrimLeft();
00593 if ( strMessage.GetLength() > 128 ) strMessage = _T("No Message");
00594 theApp.Message( MSG_ERROR, IDS_DOWNLOAD_HTTPCODE, (LPCTSTR)m_sAddress,
00595 (LPCTSTR)strCode, (LPCTSTR)strMessage );
00596 SetState( dtsHeaders );
00597 m_bBadResponse = TRUE;
00598 }
00599
00600 m_pHeaderName.RemoveAll();
00601 m_pHeaderValue.RemoveAll();
00602
00603 return TRUE;
00604 }
00605
00607
00608
00609 BOOL CDownloadTransferHTTP::OnHeaderLine(CString& strHeader, CString& strValue)
00610 {
00611 theApp.Message( MSG_DEBUG, _T("%s: DOWNLOAD HEADER: %s: %s"), (LPCTSTR)m_sAddress, (LPCTSTR)strHeader, (LPCTSTR)strValue );
00612
00613 if ( strHeader.CompareNoCase( _T("Server") ) == 0 )
00614 {
00615 m_sUserAgent = strValue;
00616
00617 if ( IsAgentBlocked() )
00618 {
00619 Close( TS_FALSE );
00620 return FALSE;
00621 }
00622
00623 m_pSource->m_sServer = strValue;
00624 if ( strValue.GetLength() > 64 ) strValue = strValue.Left( 64 );
00625
00626 if ( _tcsistr( m_sUserAgent, _T("shareaza") ) != NULL ) m_pSource->SetGnutella( 3 );
00627 if ( _tcsistr( m_sUserAgent, _T("trustyfiles") ) != NULL ) m_pSource->SetGnutella( 3 );
00628 if ( _tcsistr( m_sUserAgent, _T("gnucdna") ) != NULL ) m_pSource->SetGnutella( 3 );
00629 if ( _tcsistr( m_sUserAgent, _T("vagaa") ) != NULL ) m_pSource->SetGnutella( 3 );
00630 if ( _tcsistr( m_sUserAgent, _T("mxie") ) != NULL ) m_pSource->SetGnutella( 3 );
00631 if ( _tcsistr( m_sUserAgent, _T("adagio") ) != NULL ) m_pSource->SetGnutella( 2 );
00632 }
00633 else if ( strHeader.CompareNoCase( _T("Connection") ) == 0 )
00634 {
00635 if ( strValue.CompareNoCase( _T("Keep-Alive") ) == 0 ) m_bKeepAlive = TRUE;
00636 }
00637 else if ( strHeader.CompareNoCase( _T("Content-Length") ) == 0 )
00638 {
00639 _stscanf( strValue, _T("%I64i"), &m_nContentLength );
00640 }
00641 else if ( strHeader.CompareNoCase( _T("Content-Range") ) == 0 )
00642 {
00643 QWORD nFirst = 0, nLast = 0, nTotal = 0;
00644
00645 if ( _stscanf( strValue, _T("bytes %I64i-%I64i/%I64i"), &nFirst, &nLast, &nTotal ) != 3 )
00646 _stscanf( strValue, _T("bytes=%I64i-%I64i/%I64i"), &nFirst, &nLast, &nTotal );
00647
00648 if ( m_pDownload->m_nSize == SIZE_UNKNOWN )
00649 {
00650 m_pDownload->m_nSize = nTotal;
00651 }
00652 else if ( m_bTigerFetch || m_bMetaFetch )
00653 {
00654 m_nOffset = nFirst;
00655 m_nLength = nLast + 1 - nFirst;
00656 if ( m_nContentLength == SIZE_UNKNOWN ) m_nContentLength = m_nLength;
00657 return TRUE;
00658 }
00659 else if ( m_pDownload->m_nSize != nTotal )
00660 {
00661 theApp.Message( MSG_ERROR, IDS_DOWNLOAD_WRONG_SIZE, (LPCTSTR)m_sAddress,
00662 (LPCTSTR)m_pDownload->GetDisplayName() );
00663 Close( TS_FALSE );
00664 return FALSE;
00665 }
00666
00667 if ( m_nOffset == SIZE_UNKNOWN && ! m_pDownload->GetFragment( this ) )
00668 {
00669 Close( TS_TRUE );
00670 return FALSE;
00671 }
00672
00673 BOOL bUseful = m_pDownload->IsPositionEmpty( nFirst );
00674
00675
00676 if ( nFirst == m_nOffset && nLast == m_nOffset + m_nLength - 1 && bUseful )
00677 {
00678
00679 }
00680 else if ( nFirst >= m_nOffset && nFirst < m_nOffset + m_nLength && bUseful )
00681 {
00682 m_nOffset = nFirst;
00683 m_nLength = nLast - nFirst + 1;
00684
00685 theApp.Message( MSG_DEFAULT, IDS_DOWNLOAD_USEFUL_RANGE, (LPCTSTR)m_sAddress,
00686 m_nOffset, m_nOffset + m_nLength - 1, (LPCTSTR)m_pDownload->GetDisplayName() );
00687 }
00688 else
00689 {
00690 theApp.Message( MSG_ERROR, IDS_DOWNLOAD_WRONG_RANGE, (LPCTSTR)m_sAddress,
00691 (LPCTSTR)m_pDownload->GetDisplayName() );
00692 Close( TS_TRUE );
00693
00694 return FALSE;
00695 }
00696
00697 if ( m_nContentLength == SIZE_UNKNOWN ) m_nContentLength = m_nLength;
00698 m_bGotRange = TRUE;
00699 }
00700 else if ( strHeader.CompareNoCase( _T("Content-Type") ) == 0 )
00701 {
00702 m_sContentType = strValue;
00703 }
00704 else if ( strHeader.CompareNoCase( _T("Content-Encoding") ) == 0 )
00705 {
00706 if ( Settings.Downloads.AllowBackwards && _tcsistr( strValue, _T("backwards") ) ) m_bRecvBackwards = TRUE;
00707 }
00708 else if ( strHeader.CompareNoCase( _T("X-Gnutella-Content-URN") ) == 0 ||
00709 strHeader.CompareNoCase( _T("X-Content-URN") ) == 0 ||
00710 strHeader.CompareNoCase( _T("Content-URN") ) == 0 )
00711 {
00712 for ( CString strURNs = strValue + ',' ; ; )
00713 {
00714 int nPos = strURNs.Find( ',' );
00715 if ( nPos < 0 ) break;
00716
00717 strValue = strURNs.Left( nPos );
00718 strURNs = strURNs.Mid( nPos + 1 );
00719 strValue.TrimLeft();
00720
00721 SHA1 pSHA1;
00722 if ( CSHA::HashFromURN( strValue, &pSHA1 ) )
00723 {
00724 if ( m_pSource->CheckHash( &pSHA1 ) )
00725 {
00726 m_bHashMatch = TRUE;
00727 }
00728 else
00729 {
00730 theApp.Message( MSG_ERROR, IDS_DOWNLOAD_WRONG_HASH, (LPCTSTR)m_sAddress,
00731 (LPCTSTR)m_pDownload->GetDisplayName() );
00732 Close( TS_FALSE );
00733 return FALSE;
00734 }
00735 }
00736
00737
00738
00739 TIGEROOT pTiger;
00740 if ( ! m_bHashMatch && CTigerNode::HashFromURN( strValue, &pTiger ) )
00741 {
00742 if ( m_pSource->CheckHash( &pTiger ) )
00743 {
00744 m_bHashMatch = TRUE;
00745 }
00746 else
00747 {
00748 theApp.Message( MSG_ERROR, IDS_DOWNLOAD_WRONG_HASH, (LPCTSTR)m_sAddress,
00749 (LPCTSTR)m_pDownload->GetDisplayName() );
00750 Close( TS_FALSE );
00751 return FALSE;
00752 }
00753 }
00754
00755 MD4 pED2K;
00756 if ( CED2K::HashFromURN( strValue, &pED2K ) )
00757 {
00758 if ( m_pSource->CheckHash( &pED2K ) )
00759 {
00760 m_bHashMatch = TRUE;
00761 }
00762 else
00763 {
00764 theApp.Message( MSG_ERROR, IDS_DOWNLOAD_WRONG_HASH, (LPCTSTR)m_sAddress,
00765 (LPCTSTR)m_pDownload->GetDisplayName() );
00766 Close( TS_FALSE );
00767 return FALSE;
00768 }
00769 }
00770 }
00771 m_pSource->SetGnutella( 1 );
00772 }
00773 else if ( strHeader.CompareNoCase( _T("X-Metadata-Path") ) == 0 )
00774 {
00775 if ( ! m_bMetaIgnore && Settings.Downloads.Metadata ) m_sMetadata = strValue;
00776 }
00777 else if ( strHeader.CompareNoCase( _T("X-TigerTree-Path") ) == 0 )
00778 {
00779 if ( Settings.Downloads.VerifyTiger && ! m_bTigerIgnore && m_sTigerTree.IsEmpty() )
00780 {
00781 if ( strValue.Find( _T("tigertree/v1") ) < 0 &&
00782 strValue.Find( _T("tigertree/v2") ) < 0 )
00783 {
00784 m_sTigerTree = strValue;
00785 }
00786 }
00787 }
00788 else if ( strHeader.CompareNoCase( _T("X-Thex-URI") ) == 0 )
00789 {
00790 if ( Settings.Downloads.VerifyTiger && ! m_bTigerIgnore )
00791 {
00792 if ( StartsWith( strValue, _T("/") ) )
00793 {
00794 m_sTigerTree = strValue.SpanExcluding( _T("; ") );
00795 Replace( m_sTigerTree, _T("ed2k=0"), _T("ed2k=1") );
00796 }
00797 }
00798 m_pSource->SetGnutella( 1 );
00799 }
00800 else if ( strHeader.CompareNoCase( _T("X-Gnutella-Alternate-Location") ) == 0 ||
00801 strHeader.CompareNoCase( _T("Alt-Location") ) == 0 ||
00802 strHeader.CompareNoCase( _T("X-Alt") ) == 0 )
00803 {
00804 if ( Settings.Library.SourceMesh )
00805 {
00806 if ( strValue.Find( _T("Zhttp://") ) < 0 )
00807 {
00808 m_pDownload->AddSourceURLs( strValue, m_bHashMatch );
00809 }
00810 }
00811 m_pSource->SetGnutella( 1 );
00812 }
00813 else if ( strHeader.CompareNoCase( _T("X-Available-Ranges") ) == 0 )
00814 {
00815 m_bGotRanges = TRUE;
00816 m_pSource->SetAvailableRanges( strValue );
00817 m_pSource->SetGnutella( 1 );
00818 if ( m_pSource->m_oAvailable.empty() )
00819 {
00820 theApp.Message( MSG_DEBUG, _T( "header did not include valid ranges, dropping source..." ) );
00821 Close( TS_FALSE );
00822 return FALSE;
00823 }
00824 }
00825 else if ( strHeader.CompareNoCase( _T("X-Queue") ) == 0 )
00826 {
00827 m_pSource->SetGnutella( 1 );
00828
00829 m_bQueueFlag = TRUE;
00830 CharLower( strValue.GetBuffer() );
00831 strValue.ReleaseBuffer();
00832
00833 int nPos = strValue.Find( _T("position=") );
00834 if ( nPos >= 0 ) _stscanf( strValue.Mid( nPos + 9 ), _T("%i"), &m_nQueuePos );
00835
00836 nPos = strValue.Find( _T("length=") );
00837 if ( nPos >= 0 ) _stscanf( strValue.Mid( nPos + 7 ), _T("%i"), &m_nQueueLen );
00838
00839 DWORD nLimit;
00840
00841 nPos = strValue.Find( _T("pollmin=") );
00842 if ( nPos >= 0 && _stscanf( strValue.Mid( nPos + 8 ), _T("%u"), &nLimit ) == 1 )
00843 {
00844 m_nRetryDelay = max( m_nRetryDelay, nLimit * 1000 + 3000 );
00845 }
00846
00847 nPos = strValue.Find( _T("pollmax=") );
00848 if ( nPos >= 0 && _stscanf( strValue.Mid( nPos + 8 ), _T("%u"), &nLimit ) == 1 )
00849 {
00850 m_nRetryDelay = min( m_nRetryDelay, nLimit * 1000 - 8000 );
00851 }
00852
00853 nPos = strValue.Find( _T("id=") );
00854 if ( nPos >= 0 )
00855 {
00856 m_sQueueName = strValue.Mid( nPos + 3 );
00857 m_sQueueName.TrimLeft();
00858 if ( m_sQueueName.Find( '\"' ) == 0 )
00859 {
00860 m_sQueueName = m_sQueueName.Mid( 1 ).SpanExcluding( _T("\"") );
00861 }
00862 else
00863 {
00864 m_sQueueName = m_sQueueName.SpanExcluding( _T("\" ") );
00865 }
00866 if ( m_sQueueName == _T("s") ) m_sQueueName = _T("Small Queue");
00867 else if ( m_sQueueName == _T("l") ) m_sQueueName = _T("Large Queue");
00868 }
00869 }
00870 else if ( strHeader.CompareNoCase( _T("X-PerHost") ) == 0 ||
00871 strHeader.CompareNoCase( _T("X-Gnutella-maxSlotsPerHost") ) == 0 )
00872 {
00873 int nLimit = 0;
00874
00875 if ( _stscanf( strValue, _T("%i"), &nLimit ) != 1 )
00876 {
00877 Downloads.SetPerHostLimit( &m_pHost.sin_addr, nLimit );
00878 }
00879 }
00880 else if ( strHeader.CompareNoCase( _T("X-Delete-Source") ) == 0 )
00881 {
00882 m_bBadResponse = TRUE;
00883 }
00884 else if ( strHeader.CompareNoCase( _T("X-Nick") ) == 0 ||
00885 strHeader.CompareNoCase( _T("X-Name") ) == 0 ||
00886 strHeader.CompareNoCase( _T("X-UserName") ) == 0 )
00887 {
00888 m_pSource->m_sNick = URLDecode( strValue );
00889 }
00890 else if ( strHeader.CompareNoCase( _T("X-Features") ) == 0 )
00891 {
00892 if ( _tcsistr( strValue, _T("g2/") ) != NULL ) m_pSource->SetGnutella( 2 );
00893 if ( _tcsistr( strValue, _T("gnet2/") ) != NULL ) m_pSource->SetGnutella( 2 );
00894 if ( _tcsistr( strValue, _T("gnutella2/") ) != NULL ) m_pSource->SetGnutella( 2 );
00895 m_pSource->SetGnutella( 1 );
00896 }
00897
00898 return CTransfer::OnHeaderLine( strHeader, strValue );
00899 }
00900
00902
00903
00904 BOOL CDownloadTransferHTTP::OnHeadersComplete()
00905 {
00906 if ( m_bBadResponse )
00907 {
00908 Close( TS_FALSE );
00909 return FALSE;
00910 }
00911 else if ( ! m_pSource->CanInitiate( TRUE, TRUE ) )
00912 {
00913 theApp.Message( MSG_ERROR, IDS_DOWNLOAD_DISABLED,
00914 (LPCTSTR)m_pDownload->GetDisplayName(), (LPCTSTR)m_sAddress, (LPCTSTR)m_sUserAgent );
00915 Close( TS_FALSE );
00916 return FALSE;
00917 }
00918 else if ( m_bBusyFault )
00919 {
00920 m_nOffset = SIZE_UNKNOWN;
00921
00922 if ( Settings.Downloads.QueueLimit > 0 && m_nQueuePos > Settings.Downloads.QueueLimit )
00923 {
00924 theApp.Message( MSG_ERROR, IDS_DOWNLOAD_QUEUE_HUGE,
00925 (LPCTSTR)m_sAddress, (LPCTSTR)m_pDownload->GetDisplayName(), m_nQueuePos );
00926 Close( TS_FALSE );
00927 return FALSE;
00928 }
00929 else if ( m_bQueueFlag && m_nRetryDelay >= 600000 )
00930 {
00931 m_pSource->m_tAttempt = GetTickCount() + m_nRetryDelay;
00932 m_bQueueFlag = FALSE;
00933 }
00934
00935 if ( m_bQueueFlag )
00936 {
00937 SetState( dtsFlushing );
00938 m_tContent = m_mInput.tLast = GetTickCount();
00939 return ReadFlush();
00940 }
00941 else
00942 {
00943 SetState( dtsBusy );
00944 m_tRequest = GetTickCount();
00945 return TRUE;
00946 }
00947 }
00948 else if ( ! m_bGotRanges && ! m_bTigerFetch && ! m_bMetaFetch )
00949 {
00950 m_pSource->SetAvailableRanges( NULL );
00951 }
00952
00953 if ( m_bRangeFault )
00954 {
00955 if ( m_pHost.sin_addr.S_un.S_addr == Network.m_pHost.sin_addr.S_un.S_addr )
00956 {
00957 Close( TS_FALSE );
00958 return FALSE;
00959 }
00960
00961 m_nOffset = SIZE_UNKNOWN;
00962 SetState( dtsFlushing );
00963 m_tContent = m_mInput.tLast = GetTickCount();
00964
00965 return ReadFlush();
00966 }
00967 else if ( m_nContentLength == SIZE_UNKNOWN )
00968 {
00969 theApp.Message( MSG_ERROR, IDS_DOWNLOAD_WRONG_SIZE, (LPCTSTR)m_sAddress,
00970 (LPCTSTR)m_pDownload->GetDisplayName() );
00971 Close( TS_FALSE );
00972 return FALSE;
00973 }
00974 else if ( m_bTigerFetch )
00975 {
00976 if ( ! m_bGotRange )
00977 {
00978 m_nOffset = 0;
00979 m_nLength = m_nContentLength;
00980 }
00981 else if ( m_nOffset > 0 )
00982 {
00983 theApp.Message( MSG_DEFAULT, IDS_DOWNLOAD_TIGER_RANGE, (LPCTSTR)m_sAddress );
00984 Close( TS_FALSE );
00985 return FALSE;
00986 }
00987
00988 if ( m_sContentType.CompareNoCase( _T("application/tigertree-breadthfirst") ) &&
00989 m_sContentType.CompareNoCase( _T("application/dime") ) )
00990 {
00991 theApp.Message( MSG_DEFAULT, IDS_DOWNLOAD_TIGER_RANGE, (LPCTSTR)m_sAddress );
00992 Close( TS_FALSE );
00993 return FALSE;
00994 }
00995
00996 SetState( dtsTiger );
00997 m_tContent = m_mInput.tLast = GetTickCount();
00998
00999 theApp.Message( MSG_DEFAULT, IDS_DOWNLOAD_TIGER_RECV, (LPCTSTR)m_sAddress,
01000 (LPCTSTR)m_pSource->m_sServer );
01001
01002 return ReadTiger();
01003 }
01004 else if ( m_bMetaFetch )
01005 {
01006 if ( ! m_bGotRange )
01007 {
01008 m_nOffset = 0;
01009 m_nLength = m_nContentLength;
01010 }
01011
01012 SetState( dtsMetadata );
01013 m_tContent = m_mInput.tLast = GetTickCount();
01014
01015 theApp.Message( MSG_DEFAULT, IDS_DOWNLOAD_METADATA_RECV,
01016 (LPCTSTR)m_sAddress, (LPCTSTR)m_pSource->m_sServer );
01017
01018 return ReadMetadata();
01019 }
01020 else if ( ! m_bGotRange )
01021 {
01022 if ( m_pDownload->m_nSize == SIZE_UNKNOWN )
01023 {
01024 m_pDownload->m_nSize = m_nContentLength;
01025 }
01026 else if ( m_pDownload->m_nSize != m_nContentLength )
01027 {
01028 theApp.Message( MSG_ERROR, IDS_DOWNLOAD_WRONG_SIZE, (LPCTSTR)m_sAddress,
01029 (LPCTSTR)m_pDownload->GetDisplayName() );
01030 Close( TS_FALSE );
01031 return FALSE;
01032 }
01033
01034 if ( m_nOffset == SIZE_UNKNOWN && ! m_pDownload->GetFragment( this ) )
01035 {
01036 Close( TS_TRUE );
01037 return FALSE;
01038 }
01039
01040 if ( ! m_pDownload->IsPositionEmpty( 0 ) )
01041 {
01042 theApp.Message( MSG_ERROR, IDS_DOWNLOAD_WRONG_RANGE, (LPCTSTR)m_sAddress,
01043 (LPCTSTR)m_pDownload->GetDisplayName() );
01044 Close( TS_TRUE );
01045 return FALSE;
01046 }
01047
01048 m_nOffset = 0;
01049 m_nLength = m_nContentLength;
01050 }
01051
01052 if ( m_nContentLength != m_nLength )
01053 {
01054 theApp.Message( MSG_ERROR, IDS_DOWNLOAD_WRONG_RANGE, (LPCTSTR)m_sAddress,
01055 (LPCTSTR)m_pDownload->GetDisplayName() );
01056 Close( TS_FALSE );
01057 return FALSE;
01058 }
01059
01060 if ( ! m_bKeepAlive ) m_pSource->m_bCloseConn = TRUE;
01061
01062 theApp.Message( MSG_DEFAULT, IDS_DOWNLOAD_CONTENT, (LPCTSTR)m_sAddress,
01063 (LPCTSTR)m_pSource->m_sServer );
01064
01065 SetState( dtsDownloading );
01066 m_nPosition = 0;
01067 m_tContent = m_mInput.tLast = GetTickCount();
01068
01069 return TRUE;
01070 }
01071
01073
01074
01075 BOOL CDownloadTransferHTTP::ReadContent()
01076 {
01077 if ( m_pInput->m_nLength > 0 )
01078 {
01079 m_pSource->SetValid();
01080
01081 DWORD nLength = (DWORD)min( (QWORD)m_pInput->m_nLength, m_nLength - m_nPosition );
01082 BOOL bSubmit = FALSE;
01083
01084 if ( m_bRecvBackwards )
01085 {
01086 BYTE* pBuffer = new BYTE[ nLength ];
01087 CBuffer::ReverseBuffer( m_pInput->m_pBuffer, pBuffer, nLength );
01088 bSubmit = m_pDownload->SubmitData(
01089 m_nOffset + m_nLength - m_nPosition - nLength, pBuffer, nLength );
01090 delete [] pBuffer;
01091 }
01092 else
01093 {
01094 bSubmit = m_pDownload->SubmitData(
01095 m_nOffset + m_nPosition, m_pInput->m_pBuffer, nLength );
01096 }
01097
01098 m_pInput->Clear();
01099 m_nPosition += nLength;
01100 m_nDownloaded += nLength;
01101
01102 if ( ! bSubmit )
01103 {
01104 BOOL bUseful = m_pDownload->IsRangeUsefulEnough( this,
01105 m_bRecvBackwards ? m_nOffset : m_nOffset + m_nPosition,
01106 m_nLength - m_nPosition );
01107
01108 if ( ! bUseful )
01109 {
01110 theApp.Message( MSG_DEFAULT, IDS_DOWNLOAD_FRAGMENT_OVERLAP, (LPCTSTR)m_sAddress );
01111 Close( TS_TRUE );
01112 return FALSE;
01113 }
01114 }
01115 }
01116
01117 if ( m_nPosition >= m_nLength )
01118 {
01119 m_pSource->AddFragment( m_nOffset, m_nLength );
01120 return StartNextFragment();
01121 }
01122
01123 return TRUE;
01124 }
01125
01127
01128
01129 BOOL CDownloadTransferHTTP::ReadMetadata()
01130 {
01131 if ( m_pInput->m_nLength < m_nLength ) return TRUE;
01132
01133 CString strXML = m_pInput->ReadString( (DWORD)m_nLength, CP_UTF8 );
01134
01135 if ( CXMLElement* pXML = CXMLElement::FromString( strXML, TRUE ) )
01136 {
01137 if ( m_pDownload->m_pXML == NULL )
01138 {
01139 m_pDownload->m_pXML = pXML;
01140 }
01141 else
01142 {
01143 delete pXML;
01144 }
01145 }
01146
01147 m_pInput->Remove( (DWORD)m_nLength );
01148
01149 return StartNextFragment();
01150 }
01151
01153
01154
01155 BOOL CDownloadTransferHTTP::ReadTiger()
01156 {
01157 if ( m_pInput->m_nLength < m_nLength ) return TRUE;
01158
01159 if ( m_sContentType.CompareNoCase( _T("application/tigertree-breadthfirst") ) == 0 )
01160 {
01161 m_pDownload->SetTigerTree( m_pInput->m_pBuffer, (DWORD)m_nLength );
01162 m_pInput->Remove( (DWORD)m_nLength );
01163 }
01164 else if ( m_sContentType.CompareNoCase( _T("application/dime") ) == 0 )
01165 {
01166 CString strID, strType, strUUID = _T("x");
01167 DWORD nFlags, nBody;
01168
01169 while ( m_pInput->ReadDIME( &nFlags, &strID, &strType, &nBody ) )
01170 {
01171 theApp.Message( MSG_DEBUG, _T("THEX DIME: %i, '%s', '%s', %i"),
01172 nFlags, (LPCTSTR)strID, (LPCTSTR)strType, nBody );
01173
01174 if ( ( nFlags & 1 ) && strType.CompareNoCase( _T("text/xml") ) == 0 && nBody < 1024*1024 )
01175 {
01176 BOOL bSize = FALSE, bDigest = FALSE, bEncoding = FALSE;
01177 CString strXML;
01178
01179 strXML = m_pInput->ReadString( nBody, CP_UTF8 );
01180
01181 if ( CXMLElement* pXML = CXMLElement::FromString( strXML ) )
01182 {
01183 if ( pXML->IsNamed( _T("hashtree") ) )
01184 {
01185 if ( CXMLElement* pxFile = pXML->GetElementByName( _T("file") ) )
01186 {
01187 QWORD nSize = 0;
01188 _stscanf( pxFile->GetAttributeValue( _T("size") ), _T("%I64i"), &nSize );
01189 bSize = ( nSize == m_pDownload->m_nSize );
01190 }
01191 if ( CXMLElement* pxDigest = pXML->GetElementByName( _T("digest") ) )
01192 {
01193 if ( pxDigest->GetAttributeValue( _T("algorithm") ).CompareNoCase( _T("http://open-content.net/spec/digest/tiger") ) == 0 )
01194 {
01195 bDigest = ( pxDigest->GetAttributeValue( _T("outputsize") ) == _T("24") );
01196 }
01197 }
01198 if ( CXMLElement* pxTree = pXML->GetElementByName( _T("serializedtree") ) )
01199 {
01200 bEncoding = ( pxTree->GetAttributeValue( _T("type") ).CompareNoCase( _T("http://open-content.net/spec/thex/breadthfirst") ) == 0 );
01201 strUUID = pxTree->GetAttributeValue( _T("uri") );
01202 }
01203 }
01204 delete pXML;
01205 }
01206
01207 theApp.Message( MSG_DEBUG, _T("THEX XML: size=%i, digest=%i, encoding=%i"),
01208 bSize, bDigest, bEncoding );
01209
01210 if ( ! bSize || ! bDigest || ! bEncoding ) break;
01211 }
01212 else if ( strID == strUUID && strType.CompareNoCase( _T("http://open-content.net/spec/thex/breadthfirst") ) == 0 )
01213 {
01214 m_pDownload->SetTigerTree( m_pInput->m_pBuffer, nBody );
01215 }
01216 else if ( strType.CompareNoCase( _T("http://edonkey2000.com/spec/md4-hashset") ) == 0 )
01217 {
01218 m_pDownload->SetHashset( m_pInput->m_pBuffer, nBody );
01219 }
01220
01221 m_pInput->Remove( ( nBody + 3 ) & ~3 );
01222 if ( nFlags & 2 ) break;
01223 }
01224
01225 m_pInput->Clear();
01226 }
01227
01228 return StartNextFragment();
01229 }
01230
01232
01233
01234 BOOL CDownloadTransferHTTP::ReadFlush()
01235 {
01236 if ( m_nContentLength == SIZE_UNKNOWN ) m_nContentLength = 0;
01237
01238 DWORD nRemove = min( m_pInput->m_nLength, (DWORD)m_nContentLength );
01239 m_nContentLength -= nRemove;
01240
01241 m_pInput->Remove( nRemove );
01242
01243 if ( m_nContentLength == 0 )
01244 {
01245 if ( m_bQueueFlag )
01246 {
01247 SetState( dtsQueued );
01248 m_tRequest = GetTickCount() + m_nRetryDelay;
01249
01250 theApp.Message( MSG_ERROR, IDS_DOWNLOAD_QUEUED,
01251 (LPCTSTR)m_sAddress, m_nQueuePos, m_nQueueLen,
01252 (LPCTSTR)m_sQueueName );
01253 }
01254 else if ( m_bRangeFault && !m_bGotRanges )
01255 {
01256
01257
01258 theApp.Message( MSG_DEFAULT, IDS_DOWNLOAD_416_WITHOUT_RANGE, (LPCTSTR)m_sAddress );
01259 Close( TS_TRUE );
01260 return FALSE;
01261 }
01262 else if ( m_bRangeFault && m_bGotRanges && m_nRequests >= 2 )
01263 {
01264
01265
01266
01267 theApp.Message( MSG_ERROR, _T("BUG: Shareaza requested a fragment from host %s, although it knew that the host doesn't have that fragment") , (LPCTSTR)m_sAddress );
01268 Close( TS_TRUE );
01269 return FALSE;
01270 }
01271 else
01272 {
01273 return StartNextFragment();
01274 }
01275 }
01276
01277 return TRUE;
01278 }
01279
01281
01282
01283 void CDownloadTransferHTTP::OnDropped(BOOL bError)
01284 {
01285 if ( m_nState == dtsConnecting )
01286 {
01287 theApp.Message( MSG_ERROR, IDS_DOWNLOAD_CONNECT_ERROR, (LPCTSTR)m_sAddress );
01288 if ( m_pSource != NULL ) m_pSource->PushRequest();
01289 Close( TS_UNKNOWN );
01290 }
01291 else if ( m_nState == dtsBusy )
01292 {
01293 theApp.Message( MSG_ERROR, IDS_DOWNLOAD_BUSY, (LPCTSTR)m_sAddress, Settings.Downloads.RetryDelay / 1000 );
01294 Close( TS_TRUE );
01295 }
01296 else
01297 {
01298
01299
01300
01301 if ( m_bBusyFault || m_bQueueFlag )
01302 {
01303 theApp.Message( MSG_ERROR, IDS_DOWNLOAD_BUSY, (LPCTSTR)m_sAddress, Settings.Downloads.RetryDelay / 1000 );
01304 Close( TS_TRUE );
01305 }
01306 else
01307 {
01308 theApp.Message( MSG_ERROR, IDS_DOWNLOAD_DROPPED, (LPCTSTR)m_sAddress );
01309 Close( m_nState >= dtsDownloading ? TS_TRUE : TS_UNKNOWN );
01310 }
01311 }
01312 }
01313