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

DownloadTransferFTP.cpp

Go to the documentation of this file.
00001 //
00002 // DownloadTransferFTP.cpp
00003 //
00004 //      Date:                   "$Date: 2005/06/27 18:15:53 $"
00005 //      Revision:               "$Revision: 1.8 $"
00006 //  Last change by:     "$Author: spooky23 $"
00007 //
00008 // Copyright (c) Nikolay Raspopov, 2004-2005.
00009 // This file is part of SHAREAZA (www.shareaza.com)
00010 //
00011 // Shareaza is free software; you can redistribute it
00012 // and/or modify it under the terms of the GNU General Public License
00013 // as published by the Free Software Foundation; either version 2 of
00014 // the License, or (at your option) any later version.
00015 //
00016 // Shareaza is distributed in the hope that it will be useful,
00017 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00018 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019 // GNU General Public License for more details.
00020 //
00021 // You should have received a copy of the GNU General Public License
00022 // along with Shareaza; if not, write to the Free Software
00023 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00024 //
00025 
00026 #include "StdAfx.h"
00027 #include "Shareaza.h"
00028 #include "Settings.h"
00029 #include "Download.h"
00030 #include "Downloads.h"
00031 #include "DownloadSource.h"
00032 #include "DownloadTransfer.h"
00033 #include "DownloadTransferFTP.h"
00034 #include "FragmentedFile.h"
00035 #include "Network.h"
00036 #include "SourceURL.h"
00037 #include "GProfile.h"
00038 
00039 #ifdef _DEBUG
00040 #undef THIS_FILE
00041 static char THIS_FILE[]=__FILE__;
00042 #define new DEBUG_NEW
00043 #endif
00044 
00046 // Service functions
00047 
00048 inline void MakePORTArgs (const SOCKADDR_IN& host, CString& strValue)
00049 {
00050         strValue.Format( _T("%u,%u,%u,%u,%hu,%hu"),
00051                 unsigned( host.sin_addr.S_un.S_un_b.s_b1 ),
00052                 unsigned( host.sin_addr.S_un.S_un_b.s_b2 ),
00053                 unsigned( host.sin_addr.S_un.S_un_b.s_b3 ),
00054                 unsigned( host.sin_addr.S_un.S_un_b.s_b4 ),
00055                 host.sin_port & 0xff,
00056                 (host.sin_port >> 8) & 0xff );
00057 }
00058 
00059 inline bool ParsePASVArgs (const CString& args, SOCKADDR_IN& host)
00060 {
00061         CString strValue (args);
00062         int begin = strValue.Find (_T('('));
00063         int end = strValue.Find (_T(')'));
00064         if (begin == -1 || end == -1 || end - begin < 12)
00065                 return false;
00066         strValue = strValue.Mid (begin + 1, end - begin - 1);
00067         ZeroMemory (&host, sizeof (host));
00068         host.sin_family = AF_INET;
00069         int d;
00070         // h1
00071         d = strValue.Find (_T(','));
00072         if (d == -1)
00073                 return false;
00074         host.sin_addr.S_un.S_un_b.s_b1 = (unsigned char) (_tstoi (strValue.Mid (0, d)) & 0xff);
00075         strValue = strValue.Mid (d + 1);
00076         // h2
00077         d = strValue.Find (_T(','));
00078         if (d == -1)
00079                 return false;
00080         host.sin_addr.S_un.S_un_b.s_b2 = (unsigned char) (_tstoi (strValue.Mid (0, d)) & 0xff);
00081         strValue = strValue.Mid (d + 1);
00082         // h3
00083         d = strValue.Find (_T(','));
00084         if (d == -1)
00085                 return false;
00086         host.sin_addr.S_un.S_un_b.s_b3 = (unsigned char) (_tstoi (strValue.Mid (0, d)) & 0xff);
00087         strValue = strValue.Mid (d + 1);
00088         // h4
00089         d = strValue.Find (_T(','));
00090         if (d == -1)
00091                 return false;
00092         host.sin_addr.S_un.S_un_b.s_b4 = (unsigned char) (_tstoi (strValue.Mid (0, d)) & 0xff);
00093         strValue = strValue.Mid (d + 1);
00094         // p1
00095         d = strValue.Find (_T(','));
00096         if (d == -1)
00097                 return false;
00098         host.sin_port = (unsigned char) (_tstoi (strValue.Mid (0, d)) & 0xff);
00099         strValue = strValue.Mid (d + 1);
00100         // p2
00101         host.sin_port += (unsigned char) (_tstoi (strValue) & 0xff) * 256;
00102         return true;
00103 }
00104 
00105 inline bool FTPisOK( const CString& str )
00106 {
00107         return ( str.GetLength () == 3 && str [0] == _T('2') );
00108 }
00109 
00111 // CDownloadTransferFTP construction
00112 
00113 CDownloadTransferFTP::CDownloadTransferFTP (CDownloadSource* pSource) :
00114         CDownloadTransfer ( pSource, PROTOCOL_FTP ),
00115         m_FtpState (ftpConnecting),
00116         m_tRequest (0),
00117         m_bPassive (TRUE /* FALSE */),
00118         m_bSizeChecked (FALSE)
00119 {
00120         m_RETR.SetOwner (this);
00121 }
00122 
00124 // CDownloadTransferFTP initiate connection
00125 
00126 BOOL CDownloadTransferFTP::Initiate()
00127 {
00128         theApp.Message( MSG_DEFAULT, IDS_DOWNLOAD_CONNECTING,
00129                 (LPCTSTR)CString( inet_ntoa( m_pSource->m_pAddress ) ), m_pSource->m_nPort,
00130                 (LPCTSTR)m_pDownload->GetDisplayName() );
00131 
00132         m_tConnected    = GetTickCount();
00133         m_FtpState              = ftpConnecting;
00134 
00135         if ( ConnectTo( &m_pSource->m_pAddress, m_pSource->m_nPort ) )
00136         {
00137                 SetState( dtsConnecting );
00138                 
00139                 if ( !m_pDownload->IsBoosted() )
00140                         m_mInput.pLimit = m_mOutput.pLimit = &Downloads.m_nLimitGeneric;
00141                 
00142                 return TRUE;
00143         }
00144         else
00145         {
00146                 theApp.Message( MSG_ERROR, IDS_DOWNLOAD_CONNECT_ERROR, (LPCTSTR)m_sAddress );
00147                 Close( TS_UNKNOWN );
00148                 return FALSE;
00149         }
00150 }
00151 
00153 // CDownloadTransferFTP close
00154 
00155 void CDownloadTransferFTP::Close (TRISTATE bKeepSource)
00156 {
00157         m_LIST.Close ();
00158         m_RETR.Close ();
00159 
00160         if ( m_pSource != NULL && m_nState == dtsDownloading && m_FtpState == ftpRETR)
00161                 m_pSource->AddFragment( m_nOffset, m_nPosition );
00162 
00163         m_FtpState = ftpConnecting;
00164         m_bSizeChecked = FALSE;
00165         
00166         CDownloadTransfer::Close( bKeepSource );
00167 }
00168 
00170 // CDownloadTransferFTP bandwidth control
00171 
00172 void CDownloadTransferFTP::Boost()
00173 {
00174         m_mInput.pLimit = m_mOutput.pLimit =
00175                 m_LIST.m_mInput.pLimit = m_LIST.m_mOutput.pLimit =
00176                 m_RETR.m_mInput.pLimit = m_RETR.m_mOutput.pLimit = NULL;
00177 }
00178 
00179 DWORD CDownloadTransferFTP::GetAverageSpeed()
00180 {
00181         return m_pSource->m_nSpeed = GetMeasuredSpeed();
00182 }
00183 
00184 DWORD CDownloadTransferFTP::GetMeasuredSpeed()
00185 {
00186         Measure();
00187         m_LIST.Measure();
00188         m_RETR.Measure();
00189         return m_mInput.nMeasure + m_LIST.m_mInput.nMeasure + m_RETR.m_mInput.nMeasure;
00190 }
00191 
00193 // CDownloadTransferFTP connection handler
00194 
00195 BOOL CDownloadTransferFTP::OnConnected()
00196 {
00197         theApp.Message( MSG_DEFAULT, IDS_DOWNLOAD_CONNECTED, (LPCTSTR)m_sAddress );
00198         
00199         m_tConnected = GetTickCount();
00200         SetState( dtsRequesting );
00201 
00202         return StartNextFragment();
00203 }
00204 
00206 // CDownloadTransferFTP fragment allocation
00207 
00208 BOOL CDownloadTransferFTP::StartNextFragment()
00209 {
00210         ASSERT( this != NULL );
00211         if ( this == NULL ) return FALSE;
00212 
00213         m_nOffset                       = SIZE_UNKNOWN;
00214         m_nPosition                     = 0;
00215         m_bWantBackwards        = FALSE;
00216         m_bRecvBackwards        = FALSE;
00217         
00218         if ( m_pInput == NULL || m_pOutput == NULL )
00219         {
00220                 theApp.Message( MSG_DEFAULT, IDS_DOWNLOAD_CLOSING_EXTRA, (LPCTSTR)m_sAddress );
00221                 Close( TS_TRUE );
00222                 return FALSE;
00223         } else if ( m_FtpState == ftpConnecting )
00224         {
00225                 // Handshaking
00226                 m_tRequest = GetTickCount();
00227                 return TRUE;
00228         }
00229         else if ( m_pDownload->m_nSize == SIZE_UNKNOWN || !m_bSizeChecked )
00230         {
00231                 // Getting file size
00232                 m_FtpState = ftpSIZE_TYPE; // ftpLIST_TYPE;
00233                 SetState( dtsRequesting );
00234                 return SendCommand ();
00235         }
00236         else if ( m_pDownload->GetFragment( this ) )
00237         {
00238                 // Downloading
00239                 // ChunkifyRequest( &m_nOffset, &m_nLength, Settings.Downloads.ChunkSize, TRUE );
00240                 theApp.Message( MSG_DEFAULT, IDS_DOWNLOAD_FRAGMENT_REQUEST,
00241                         m_nOffset, m_nOffset + m_nLength - 1,
00242                         (LPCTSTR)m_pDownload->GetDisplayName(), (LPCTSTR)m_sAddress );
00243                 // Sending request
00244                 m_FtpState = ftpRETR_TYPE;
00245                 SetState( dtsDownloading );
00246                 return SendCommand ();
00247         }
00248         else
00249         {
00250                 if ( m_pSource != NULL ) m_pSource->SetAvailableRanges( NULL );         
00251                 theApp.Message( MSG_DEFAULT, IDS_DOWNLOAD_FRAGMENT_END, (LPCTSTR)m_sAddress );
00252                 Close( TS_TRUE );
00253                 return FALSE;
00254         }
00255 }
00256 
00258 // CDownloadTransferFTP subtract pending requests
00259 
00260 BOOL CDownloadTransferFTP::SubtractRequested(FF::SimpleFragmentList& ppFragments)
00261 {
00262         if ( m_nOffset < SIZE_UNKNOWN && m_nLength < SIZE_UNKNOWN )
00263         {
00264                 if ( m_nState == dtsRequesting || m_nState == dtsDownloading )
00265                 {
00266             ppFragments.erase( FF::SimpleFragment( m_nOffset, m_nOffset + m_nLength ) );
00267                         return TRUE;
00268                 }
00269         }
00270         
00271         return FALSE;
00272 }
00273 
00275 // CDownloadTransferFTP run handler
00276 
00277 BOOL CDownloadTransferFTP::OnRun()
00278 {
00279         CDownloadTransfer::OnRun();
00280         
00281         DWORD tNow = GetTickCount();
00282         
00283         switch ( m_nState )
00284         {
00285         case dtsConnecting:
00286                 if ( tNow - m_tConnected > Settings.Connection.TimeoutConnect )
00287                 {
00288                         theApp.Message( MSG_ERROR, IDS_CONNECTION_TIMEOUT_CONNECT, (LPCTSTR)m_sAddress );
00289                         if ( m_pSource != NULL ) m_pSource->PushRequest();
00290                         Close( TS_UNKNOWN );
00291                         return FALSE;
00292                 }
00293                 break;
00294 
00295         case dtsRequesting:
00296         case dtsHeaders:
00297                 if ( tNow - m_tRequest > Settings.Connection.TimeoutHandshake )
00298                 {
00299                         theApp.Message( MSG_ERROR, IDS_DOWNLOAD_REQUEST_TIMEOUT, (LPCTSTR)m_sAddress );
00300                         Close( TS_UNKNOWN );
00301                         return FALSE;
00302                 }
00303                 break;
00304 
00305         case dtsDownloading:
00306         case dtsFlushing:
00307         case dtsTiger:
00308         case dtsMetadata:
00309                 if ( tNow - m_mInput.tLast > Settings.Connection.TimeoutTraffic * 2 )
00310                 {
00311                         theApp.Message( MSG_ERROR, IDS_DOWNLOAD_TRAFFIC_TIMEOUT, (LPCTSTR)m_sAddress );
00312                         Close( TS_TRUE );
00313                         return FALSE;
00314                 }
00315                 break;
00316 
00317         case dtsBusy:
00318                 if ( tNow - m_tRequest > 1000 )
00319                 {
00320                         theApp.Message( MSG_ERROR, IDS_DOWNLOAD_BUSY, (LPCTSTR)m_sAddress, Settings.Downloads.RetryDelay / 1000 );
00321                         Close( TS_TRUE );
00322                         return FALSE;
00323                 }
00324                 break;
00325 
00326         case dtsQueued:
00327                 if ( tNow >= m_tRequest )
00328                 {
00329                         return StartNextFragment();
00330                 }
00331                 break;
00332         }
00333 
00334         return TRUE;
00335 }
00336 
00338 // CDownloadTransferFTP read handler
00339 
00340 BOOL CDownloadTransferFTP::OnRead()
00341 {
00342         CDownloadTransfer::OnRead();
00343         
00344         CString strLine;
00345         while( m_pInput->ReadLine( strLine ) )
00346         {
00347                 strLine.Trim( _T(" \t\r\n") );
00348                 if ( strLine.GetLength() > 256 )
00349                         strLine = _T("#LINE_TOO_LONG#");
00350                 if ( strLine.GetLength() > 3 )
00351                 {
00352                         m_sLastHeader = strLine.Left( 3 ).TrimRight( _T(" \t\r\n") );
00353                         if ( !OnHeaderLine( m_sLastHeader,
00354                                 strLine.Mid( 4 ).TrimLeft( _T(" \t\r\n") ) ) )
00355                 return FALSE;
00356         }
00357         }
00358         return TRUE;
00359 }
00360 
00362 // CDownloadTransferFTP read header lines
00363 
00364 BOOL CDownloadTransferFTP::OnHeaderLine( CString& strHeader, CString& strValue )
00365 {
00366         theApp.Message( MSG_DEBUG, _T("%s >> %s: %s"),
00367                 (LPCTSTR) m_sAddress, (LPCTSTR) strHeader, (LPCTSTR) strValue );
00368         TRACE( _T("%s >> %s: %s\n"),
00369                 (LPCTSTR) m_sAddress, (LPCTSTR) strHeader, (LPCTSTR) strValue );
00370 
00371         m_pSource->SetLastSeen();
00372 
00373         switch( m_FtpState )
00374         {
00375                 case ftpConnecting:
00376                         if ( strHeader == _T("220") ) // Connected
00377                         {
00378                         m_LIST.m_sUserAgent = m_RETR.m_sUserAgent = m_sUserAgent = strValue;
00379                                 if ( IsAgentBlocked() )
00380                                 {
00381                                         Close( TS_FALSE );
00382                                         return FALSE;
00383                                 }
00384                         // Sending login
00385                                 m_FtpState = ftpUSER;
00386                         SetState( dtsRequesting );
00387                         return SendCommand();
00388                         }
00389                 break;
00390 
00391                 case ftpUSER:
00392                 if ( strHeader == _T("331") )   // Access allowed
00393                         {               
00394                         // Sending password
00395                                 m_FtpState = ftpPASS;
00396                         SetState( dtsRequesting );
00397                         return SendCommand ();
00398                         } else 
00399                 if ( FTPisOK( strHeader ) )             // Extra headers, may be some 220
00400                         // Bypass
00401                                 return TRUE;
00402                         // Wrong login or other errors
00403                 // 530: This FTP server is anonymous only.
00404                 break;
00405 
00406                 case ftpPASS:
00407                 if ( strHeader == _T("230") )   // Logged in
00408                         {
00409                         // Downloading
00410                         m_FtpState = ftpDownloading;
00411                         SetState( dtsRequesting );
00412                                 return StartNextFragment();
00413                 } else 
00414                 if ( FTPisOK( strHeader ) )             // Extra headers
00415                         // Bypass
00416                         return TRUE;
00417                         // Wrong password or other errors
00418                 // 530: Login incorrect.
00419                 break;
00420 
00421         case ftpSIZE_TYPE:
00422                 if ( strHeader == _T("200") )   // Type I setted
00423                         {
00424                         // Getting file size
00425                         m_FtpState = ftpSIZE;
00426                         SetState( dtsRequesting );
00427                         return SendCommand ();
00428                         } else
00429                 if ( FTPisOK( strHeader ) )             // Extra headers, may be some 230
00430                         // Bypass
00431                                 return TRUE;
00432                 break;
00433 
00434         case ftpSIZE:
00435                 if ( strHeader == _T("213") )   // SIZE reply
00436                         {
00437                         QWORD size = _tstoi64( strValue );
00438                         if ( size <= 0 )
00439                         {
00440                                 // Wrong SIZE reply format
00441                                 ASSERT( FALSE );
00442                                 Close( TS_TRUE );
00443                                 return FALSE;
00444                         }
00445                         if ( m_pDownload->m_nSize == SIZE_UNKNOWN )
00446                         m_pDownload->m_nSize = size;
00447                         else
00448                         {
00449                                 if ( m_pDownload->m_nSize != size )
00450                                 {
00451                                         // File size changed!
00452                                         theApp.Message( MSG_ERROR, IDS_DOWNLOAD_WRONG_SIZE,
00453                                                 (LPCTSTR)m_sAddress, (LPCTSTR)m_pDownload->GetDisplayName() );
00454                                         Close( TS_FALSE );
00455                                         return FALSE;
00456                                 }
00457                         }
00458                         m_bSizeChecked = TRUE;
00459                         // Downloading
00460                         m_FtpState = ftpDownloading;
00461                         SetState( dtsRequesting );
00462                         return StartNextFragment();
00463                 } else 
00464                 if ( FTPisOK( strHeader ) )             // Extra headers, may be some 230
00465                         // Bypass
00466                         return TRUE;
00467                 else
00468                 if ( strHeader == _T("550") )   // File unavailable
00469                 {
00470                         theApp.Message( MSG_ERROR, IDS_DOWNLOAD_FILENOTFOUND,
00471                                 (LPCTSTR)m_sAddress, (LPCTSTR)m_pDownload->GetDisplayName() );
00472                         Close( TS_FALSE );
00473                         return FALSE;
00474                 }
00475                 break;
00476 
00477         case ftpLIST_TYPE:
00478                 if ( strHeader == _T("200") )   // Type A setted
00479                 {
00480                         // Mode choosing
00481                         m_FtpState = ftpLIST_PASVPORT;
00482                         SetState( dtsRequesting );
00483                         return SendCommand ();
00484                 } else
00485                 if ( FTPisOK( strHeader ) )             // Extra headers, may be some 230
00486                         // Bypass
00487                         return TRUE;
00488                 break;
00489 
00490         case ftpLIST_PASVPORT:
00491                 if ( strHeader == _T("227") ||
00492                          strHeader == _T("200") )       // Entered passive or active mode
00493                 {
00494                         // Getting file size
00495                         if ( m_bPassive )
00496                         {
00497                                 // Passive mode
00498                                 SOCKADDR_IN host;
00499                                 if ( !ParsePASVArgs( strValue, host ) )
00500                                 {
00501                                         // Wrong PASV reply format
00502                                         ASSERT( FALSE );
00503                                         Close( TS_TRUE );
00504                                         return FALSE;
00505                                 }
00506                                 if ( !m_LIST.ConnectTo( &host ) )
00507                                 {
00508                                         // Cannot connect
00509                                         theApp.Message( MSG_ERROR, IDS_DOWNLOAD_CONNECT_ERROR,
00510                                                 (LPCTSTR)m_sAddress );
00511                                         Close( TS_TRUE );
00512                                         return FALSE;
00513                                 }
00514                         }
00515                         m_FtpState = ftpLIST;
00516                         SetState( dtsRequesting );
00517                         return SendCommand ();
00518                 } else
00519                 if ( FTPisOK( strHeader ) )             // Extra headers
00520                         // Bypass
00521                         return TRUE;
00522                 break;
00523 
00524         case ftpLIST:
00525                 if ( strHeader == _T("125") ||
00526                          strHeader == _T("150") )               // Transfer started
00527                         {
00528                         // Downloading
00529                         return TRUE;
00530                         } else
00531                 if ( strHeader == _T("226") )           // Transfer completed
00532                         {
00533                                 // Extract file size
00534                         QWORD size = m_LIST.ExtractFileSize();
00535                         if ( size == SIZE_UNKNOWN )
00536                         {
00537                                 // Wrong LIST reply format
00538                                 Close( TS_TRUE );
00539                                 return FALSE;
00540                         }
00541                         if ( m_pDownload->m_nSize == SIZE_UNKNOWN )
00542                         m_pDownload->m_nSize = size;
00543                         else
00544                         {
00545                                 if ( m_pDownload->m_nSize != size )
00546                                 {
00547                                         // File size changed!
00548                                         theApp.Message( MSG_ERROR, IDS_DOWNLOAD_WRONG_SIZE,
00549                                                 (LPCTSTR)m_sAddress, (LPCTSTR)m_pDownload->GetDisplayName() );
00550                                         Close( TS_FALSE );
00551                                         return FALSE;
00552                                 }
00553                         }
00554                         m_bSizeChecked = TRUE;
00555                         // Aborting
00556                         m_LIST.Close();
00557                         m_FtpState = ftpABOR;
00558                         SetState( dtsRequesting );
00559                         return SendCommand();
00560                 } else
00561                 if ( strHeader == _T("550") )   // File unavailable
00562                 {
00563                         theApp.Message( MSG_ERROR, IDS_DOWNLOAD_FILENOTFOUND,
00564                                 (LPCTSTR)m_sAddress, (LPCTSTR)m_pDownload->GetDisplayName() );
00565                         Close( TS_FALSE );
00566                         return FALSE;
00567                         }
00568                 break;
00569 
00570         case ftpRETR_TYPE:
00571                         if ( strHeader == _T("200") ) // Type I setted
00572                         {
00573                         // Mode choosing
00574                         m_FtpState = ftpRETR_PASVPORT;
00575                         SetState( dtsDownloading );
00576                         return SendCommand();
00577                 } else
00578                 if ( FTPisOK( strHeader ) )             // Extra headers, may be some 230
00579                         // Bypass
00580                         return TRUE;
00581                 break;
00582 
00583         case ftpRETR_PASVPORT:
00584                 if ( strHeader == _T("227") ||
00585                          strHeader == _T("200") )       // Entered passive or active mode
00586                 {
00587                         // File fragment choosing
00588                         if ( m_bPassive )
00589                         {
00590                                 SOCKADDR_IN host;
00591                                 if ( !ParsePASVArgs( strValue, host ) )
00592                                 {
00593                                         // Wrong PASV reply format
00594                                         ASSERT( FALSE );
00595                                         Close( TS_TRUE );
00596                                         return FALSE;
00597                                 }
00598                                 if ( !m_RETR.ConnectTo( &host ) )
00599                                 {
00600                                         // Cannot connect
00601                                         theApp.Message( MSG_ERROR, IDS_DOWNLOAD_CONNECT_ERROR,
00602                                                 (LPCTSTR)m_sAddress );
00603                                         Close( TS_TRUE );
00604                                         return FALSE;
00605                                 }
00606                                 }
00607                         m_FtpState = ftpRETR_REST;
00608                         SetState (dtsDownloading);
00609                         return SendCommand ();
00610                 } else
00611                 if ( FTPisOK( strHeader ) )             // Extra headers
00612                         // Bypass
00613                         return TRUE;
00614                 break;
00615 
00616         case ftpRETR_REST:
00617                 if ( strHeader == _T("350") )   // Offset setted
00618                         {
00619                         // Downloading
00620                         m_FtpState = ftpRETR;
00621                         SetState( dtsDownloading );
00622                         return SendCommand ();
00623                 }
00624                 break;
00625 
00626         case ftpRETR:
00627                 if ( strHeader == _T("125") ||
00628                          strHeader == _T("150") )       // Transfer started
00629                         {
00630                         // Downloading
00631                         return TRUE;
00632                 } else
00633                 if ( strHeader == _T("226") ||
00634                          strHeader == _T("426") )       // Transfer completed
00635                 {
00636                         // Aborting
00637                         m_RETR.Close();
00638                         m_FtpState = ftpABOR;
00639                         SetState( dtsDownloading );
00640                         return SendCommand ();
00641                         } else
00642                 if ( strHeader == _T("550") )   // File unavailable
00643                         {
00644                         theApp.Message( MSG_ERROR, IDS_DOWNLOAD_FILENOTFOUND,
00645                                 (LPCTSTR)m_sAddress, (LPCTSTR)m_pDownload->GetDisplayName() );
00646                         Close( TS_FALSE );
00647                         return FALSE;
00648                 }
00649                 break;
00650 
00651         case ftpABOR:
00652                 // Downloading
00653                 m_FtpState = ftpDownloading;
00654                 SetState( dtsDownloading );
00655                                 return StartNextFragment();
00656 
00657         default:
00658                 // Really unexpected errors
00659                 ASSERT( FALSE );
00660         }
00661 
00662         theApp.Message( MSG_ERROR, IDS_DOWNLOAD_HTTPCODE,
00663                 (LPCTSTR)m_sAddress, (LPCTSTR)strHeader, (LPCTSTR)strValue);
00664                 Close( TS_TRUE );
00665                 return FALSE;
00666 }
00667 
00668 BOOL CDownloadTransferFTP::SendCommand (LPCTSTR args)
00669 {
00670         CSourceURL pURL;
00671         if ( !pURL.ParseFTP( m_pSource->m_sURL, TRUE ) )
00672                 return FALSE;
00673 
00674         CString strLine;
00675         switch( m_FtpState )
00676         {
00677         case ftpUSER:
00678                 // Sending login
00679                 strLine = _T("USER ");
00680                 strLine += pURL.m_sLogin;
00681                 break;
00682 
00683         case ftpPASS:
00684                 // Sending password
00685                 strLine = _T("PASS ");
00686                 strLine += pURL.m_sPassword;
00687                 break;
00688 
00689         case ftpLIST_PASVPORT:
00690                 // Selecting passive or active mode
00691                 if ( m_bPassive )
00692                         strLine = _T("PASV");
00693 /*              else
00694                 {
00695                         SOCKADDR_IN host;
00696                         if ( !Handshakes.Add( &m_LIST, host ) )
00697                         {
00698                                 // Unexpected errors
00699                                 Close( TS_TRUE );
00700                                 return FALSE;
00701                         }
00702                         CString args;
00703                         MakePORTArgs( host, args );
00704                         strLine = _T("PORT ");
00705                         strLine += args;
00706                 }*/
00707                 break;
00708 
00709         case ftpSIZE:
00710                 // Listing file size
00711                 strLine = _T("SIZE ");
00712                 strLine += pURL.m_sPath;
00713                 break;
00714 
00715         case ftpLIST_TYPE:
00716                 // Selecting ASCII type for transfer
00717                 strLine = _T("TYPE A");
00718                 break;
00719 
00720         case ftpLIST:
00721                 // Listing file attributes
00722                 strLine = _T("LIST ");
00723                 strLine += pURL.m_sPath;
00724                 break;
00725 
00726         case ftpSIZE_TYPE:
00727         case ftpRETR_TYPE:
00728                 // Selecting BINARY type for transfer
00729                 strLine = _T("TYPE I");
00730                 break;
00731 
00732         case ftpRETR_PASVPORT:
00733                 // Selecting passive or active mode
00734                 if ( m_bPassive )
00735                         strLine = _T("PASV");
00736 /*              else
00737                 {
00738                         SOCKADDR_IN host;
00739                         if ( !Handshakes.Add( &m_RETR, host ) )
00740                         {
00741                                 // Unexpected errors
00742                                 Close( TS_TRUE );
00743                                 return FALSE;
00744                         }
00745                         CString args;
00746                         MakePORTArgs( host, args );
00747                         strLine = _T("PORT ");
00748                         strLine += args;
00749                 }*/
00750                 break;
00751 
00752         case ftpRETR_REST:
00753                 // Restarting from offset position
00754                 strLine.Format( _T("REST %d"), m_nOffset );
00755                 break;
00756 
00757         case ftpRETR:
00758                 // Retriving file
00759                 strLine = _T("RETR ");
00760                 strLine += pURL.m_sPath;
00761                 break;
00762 
00763         case ftpABOR:
00764                 // Transfer aborting
00765                 strLine = _T("ABOR");
00766                 break;
00767 
00768                 default:
00769                 return TRUE;
00770         }
00771         
00772         theApp.Message( MSG_DEBUG, _T("%s << %s"), (LPCTSTR) m_sAddress, (LPCTSTR) strLine );
00773         TRACE( _T("%s << %s\n"), (LPCTSTR) m_sAddress, (LPCTSTR) strLine );
00774 
00775         m_tRequest = GetTickCount();
00776         m_pOutput->Clear ();
00777         m_pOutput->Print( strLine  + _T("\r\n") );
00778 
00779         return TRUE;
00780 }
00781 
00783 // CDownloadTransferFTP dropped connection handler
00784 
00785 void CDownloadTransferFTP::OnDropped(BOOL bError)
00786 {
00787         if ( m_nState == dtsConnecting )
00788         {
00789                 theApp.Message( MSG_ERROR, IDS_DOWNLOAD_CONNECT_ERROR, (LPCTSTR)m_sAddress );
00790                 if ( m_pSource != NULL ) m_pSource->PushRequest();
00791                 Close( TS_UNKNOWN );
00792         } else
00793                 {
00794                         theApp.Message( MSG_ERROR, IDS_DOWNLOAD_DROPPED, (LPCTSTR)m_sAddress );
00795                         Close( m_nState >= dtsDownloading ? TS_TRUE : TS_UNKNOWN );
00796                 }
00797 }

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