active mode support for wxFTP (extremely heavily modified patch 1006252)

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@29204 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2004-09-18 14:24:49 +00:00
parent 6adbb0bf6e
commit e245458872
4 changed files with 246 additions and 60 deletions

View File

@@ -208,6 +208,8 @@ All:
- basic UDP sockets support (Lenny Maiorani) - basic UDP sockets support (Lenny Maiorani)
- fixed wxDateTime::GetWeekDayName() for some dates (Daniel Kaps) - fixed wxDateTime::GetWeekDayName() for some dates (Daniel Kaps)
- deprecated wxDateTime::SetToTheWeek() in favour of SetToWeekOfYear() - deprecated wxDateTime::SetToTheWeek() in favour of SetToWeekOfYear()
- active mode support in wxFTP (Randall Fox)
- sped up wxHTTP and wxFTP
All (GUI): All (GUI):

View File

@@ -103,18 +103,21 @@ enum TransferMode
\latexignore{\rtfignore{\wxheading{Members}}} \latexignore{\rtfignore{\wxheading{Members}}}
\membersection{wxFTP::wxFTP} \membersection{wxFTP::wxFTP}
\func{}{wxFTP}{\void} \func{}{wxFTP}{\void}
Default constructor. Default constructor.
\membersection{wxFTP::\destruct{wxFTP}} \membersection{wxFTP::\destruct{wxFTP}}
\func{}{\destruct{wxFTP}}{\void} \func{}{\destruct{wxFTP}}{\void}
Destructor will close the connection if connected. Destructor will close the connection if connected.
\membersection{wxFTP::Abort}\label{wxftpabort} \membersection{wxFTP::Abort}\label{wxftpabort}
\func{bool}{Abort}{\void} \func{bool}{Abort}{\void}
@@ -122,6 +125,7 @@ Destructor will close the connection if connected.
Aborts the download currently in process, returns {\tt true} if ok, {\tt false} Aborts the download currently in process, returns {\tt true} if ok, {\tt false}
if an error occured. if an error occured.
\membersection{wxFTP::CheckCommand} \membersection{wxFTP::CheckCommand}
\func{bool}{CheckCommand}{\param{const wxString\&}{ command}, \param{char }{ret}} \func{bool}{CheckCommand}{\param{const wxString\&}{ command}, \param{char }{ret}}
@@ -133,6 +137,7 @@ the expected result.
true if the command has been sent successfully, else false. true if the command has been sent successfully, else false.
\membersection{wxFTP::SendCommand}\label{wxftpsendcommand} \membersection{wxFTP::SendCommand}\label{wxftpsendcommand}
\func{char}{SendCommand}{\param{const wxString\&}{ command}} \func{char}{SendCommand}{\param{const wxString\&}{ command}}
@@ -140,6 +145,7 @@ true if the command has been sent successfully, else false.
Send the specified {\it command} to the FTP server and return the first Send the specified {\it command} to the FTP server and return the first
character of the return code. character of the return code.
\membersection{wxFTP::GetLastResult} \membersection{wxFTP::GetLastResult}
\func{const wxString\&}{GetLastResult}{\void} \func{const wxString\&}{GetLastResult}{\void}
@@ -149,6 +155,7 @@ command.
% ---------------------------------------------------------------------------- % ----------------------------------------------------------------------------
\membersection{wxFTP::ChDir} \membersection{wxFTP::ChDir}
\func{bool}{ChDir}{\param{const wxString\&}{ dir}} \func{bool}{ChDir}{\param{const wxString\&}{ dir}}
@@ -156,6 +163,7 @@ command.
Change the current FTP working directory. Change the current FTP working directory.
Returns true if successful. Returns true if successful.
\membersection{wxFTP::MkDir} \membersection{wxFTP::MkDir}
\func{bool}{MkDir}{\param{const wxString\&}{ dir}} \func{bool}{MkDir}{\param{const wxString\&}{ dir}}
@@ -163,6 +171,7 @@ Returns true if successful.
Create the specified directory in the current FTP working directory. Create the specified directory in the current FTP working directory.
Returns true if successful. Returns true if successful.
\membersection{wxFTP::RmDir} \membersection{wxFTP::RmDir}
\func{bool}{RmDir}{\param{const wxString\&}{ dir}} \func{bool}{RmDir}{\param{const wxString\&}{ dir}}
@@ -170,6 +179,7 @@ Returns true if successful.
Remove the specified directory from the current FTP working directory. Remove the specified directory from the current FTP working directory.
Returns true if successful. Returns true if successful.
\membersection{wxFTP::Pwd} \membersection{wxFTP::Pwd}
\func{wxString}{Pwd}{\void} \func{wxString}{Pwd}{\void}
@@ -178,6 +188,7 @@ Returns the current FTP working directory.
% ---------------------------------------------------------------------------- % ----------------------------------------------------------------------------
\membersection{wxFTP::Rename} \membersection{wxFTP::Rename}
\func{bool}{Rename}{\param{const wxString\&}{ src}, \param{const wxString\&}{ dst}} \func{bool}{Rename}{\param{const wxString\&}{ src}, \param{const wxString\&}{ dst}}
@@ -186,6 +197,7 @@ Rename the specified {\it src} element to {\it dst}. Returns true if successful.
% ---------------------------------------------------------------------------- % ----------------------------------------------------------------------------
\membersection{wxFTP::RmFile} \membersection{wxFTP::RmFile}
\func{bool}{RmFile}{\param{const wxString\&}{ path}} \func{bool}{RmFile}{\param{const wxString\&}{ path}}
@@ -194,18 +206,31 @@ Delete the file specified by {\it path}. Returns true if successful.
% ---------------------------------------------------------------------------- % ----------------------------------------------------------------------------
\membersection{wxFTP::SetAscii} \membersection{wxFTP::SetAscii}
\func{bool}{SetAscii}{\void} \func{bool}{SetAscii}{\void}
Sets the transfer mode to ASCII. It will be used for the next transfer. Sets the transfer mode to ASCII. It will be used for the next transfer.
\membersection{wxFTP::SetBinary} \membersection{wxFTP::SetBinary}
\func{bool}{SetBinary}{\void} \func{bool}{SetBinary}{\void}
Sets the transfer mode to binary (IMAGE). It will be used for the next transfer. Sets the transfer mode to binary (IMAGE). It will be used for the next transfer.
\membersection{wxFTP::SetPassive}
\func{void}{SetPassive}{\param{bool }{pasv}}
If \arg{pasv} is \true, passive connection to the FTP server is used. This is
the default as it works with practically all firewalls. If the server doesn't
support passive move, you may call this function with \false argument to use
active connection.
\membersection{wxFTP::SetTransferMode} \membersection{wxFTP::SetTransferMode}
\func{bool}{SetTransferMode}{\param{TransferMode }{mode}} \func{bool}{SetTransferMode}{\param{TransferMode }{mode}}
@@ -217,6 +242,7 @@ If this function is never called, binary transfer mode is used by default.
% ---------------------------------------------------------------------------- % ----------------------------------------------------------------------------
\membersection{wxFTP::SetUser} \membersection{wxFTP::SetUser}
\func{void}{SetUser}{\param{const wxString\&}{ user}} \func{void}{SetUser}{\param{const wxString\&}{ user}}
@@ -233,6 +259,7 @@ This parameter can be included in a URL if you want to use the URL manager.
For example, you can use: "ftp://a\_user:a\_password@a.host:service/a\_directory/a\_file" For example, you can use: "ftp://a\_user:a\_password@a.host:service/a\_directory/a\_file"
to specify a user and a password. to specify a user and a password.
\membersection{wxFTP::SetPassword} \membersection{wxFTP::SetPassword}
\func{void}{SetPassword}{\param{const wxString\&}{ passwd}} \func{void}{SetPassword}{\param{const wxString\&}{ passwd}}
@@ -253,12 +280,14 @@ to specify a user and a password.
% ---------------------------------------------------------------------------- % ----------------------------------------------------------------------------
\membersection{wxFTP::FileExists}\label{wxftpfileexists} \membersection{wxFTP::FileExists}\label{wxftpfileexists}
\func{bool}{FileExists}{\param{const wxString\&}{ filename}} \func{bool}{FileExists}{\param{const wxString\&}{ filename}}
Returns {\tt true} if the given remote file exists, {\tt false} otherwise. Returns {\tt true} if the given remote file exists, {\tt false} otherwise.
\membersection{wxFTP::GetFileSize}\label{wxftpgetfilesize} \membersection{wxFTP::GetFileSize}\label{wxftpgetfilesize}
\func{int}{GetFileSize}{\param{const wxString\&}{ filename}} \func{int}{GetFileSize}{\param{const wxString\&}{ filename}}
@@ -268,6 +297,7 @@ couldn't be determined. Notice that this size can be approximative size only
and shouldn't be used for allocating the buffer in which the remote file is and shouldn't be used for allocating the buffer in which the remote file is
copied, for example. copied, for example.
\membersection{wxFTP::GetDirList}\label{wxftpgetdirlist} \membersection{wxFTP::GetDirList}\label{wxftpgetdirlist}
\func{bool}{GetDirList}{\param{wxArrayString\& }{files}, \param{const wxString\&}{ wildcard = ""}} \func{bool}{GetDirList}{\param{wxArrayString\& }{files}, \param{const wxString\&}{ wildcard = ""}}
@@ -302,6 +332,7 @@ otherwise.
\helpref{GetFilesList}{wxftpgetfileslist} \helpref{GetFilesList}{wxftpgetfileslist}
\membersection{wxFTP::GetFilesList}\label{wxftpgetfileslist} \membersection{wxFTP::GetFilesList}\label{wxftpgetfileslist}
\func{bool}{GetFilesList}{\param{wxArrayString\& }{files}, \param{const wxString\&}{ wildcard = ""}} \func{bool}{GetFilesList}{\param{wxArrayString\& }{files}, \param{const wxString\&}{ wildcard = ""}}
@@ -316,6 +347,7 @@ otherwise.
% ---------------------------------------------------------------------------- % ----------------------------------------------------------------------------
\membersection{wxFTP::GetOutputStream} \membersection{wxFTP::GetOutputStream}
\func{wxOutputStream *}{GetOutputStream}{\param{const wxString\&}{ file}} \func{wxOutputStream *}{GetOutputStream}{\param{const wxString\&}{ file}}
@@ -334,6 +366,7 @@ An initialized write-only stream.
% ---------------------------------------------------------------------------- % ----------------------------------------------------------------------------
\membersection{wxFTP::GetInputStream}\label{wxftpgetinput} \membersection{wxFTP::GetInputStream}\label{wxftpgetinput}
\func{wxInputStream *}{GetInputStream}{\param{const wxString\&}{ path}} \func{wxInputStream *}{GetInputStream}{\param{const wxString\&}{ path}}

View File

@@ -42,7 +42,7 @@ public:
void SetUser(const wxString& user) { m_user = user; } void SetUser(const wxString& user) { m_user = user; }
void SetPassword(const wxString& passwd) { m_passwd = passwd; } void SetPassword(const wxString& passwd) { m_passwd = passwd; }
bool Connect(wxSockAddress& addr, bool wait = TRUE); bool Connect(wxSockAddress& addr, bool wait = true);
bool Connect(const wxString& host); bool Connect(const wxString& host);
// disconnect // disconnect
@@ -51,6 +51,8 @@ public:
// Parameters set up // Parameters set up
// set transfer mode now // set transfer mode now
void SetPassive(bool pasv) { m_bPassive = pasv; };
void SetDefaultTimeout(wxUint32 Value);
bool SetBinary() { return SetTransferMode(BINARY); } bool SetBinary() { return SetTransferMode(BINARY); }
bool SetAscii() { return SetTransferMode(ASCII); } bool SetAscii() { return SetTransferMode(ASCII); }
bool SetTransferMode(TransferMode mode); bool SetTransferMode(TransferMode mode);
@@ -104,7 +106,7 @@ public:
bool GetFilesList(wxArrayString& files, bool GetFilesList(wxArrayString& files,
const wxString& wildcard = wxEmptyString) const wxString& wildcard = wxEmptyString)
{ {
return GetList(files, wildcard, FALSE); return GetList(files, wildcard, false);
} }
// get a directory list in server dependent format - this can be shown // get a directory list in server dependent format - this can be shown
@@ -112,17 +114,17 @@ public:
bool GetDirList(wxArrayString& files, bool GetDirList(wxArrayString& files,
const wxString& wildcard = wxEmptyString) const wxString& wildcard = wxEmptyString)
{ {
return GetList(files, wildcard, TRUE); return GetList(files, wildcard, true);
} }
// equivalent to either GetFilesList() (default) or GetDirList() // equivalent to either GetFilesList() (default) or GetDirList()
bool GetList(wxArrayString& files, bool GetList(wxArrayString& files,
const wxString& wildcard = wxEmptyString, const wxString& wildcard = wxEmptyString,
bool details = FALSE); bool details = false);
protected: protected:
// this executes a simple ftp command with the given argument and returns // this executes a simple ftp command with the given argument and returns
// TRUE if it its return code starts with '2' // true if it its return code starts with '2'
bool DoSimpleCommand(const wxChar *command, bool DoSimpleCommand(const wxChar *command,
const wxString& arg = wxEmptyString); const wxString& arg = wxEmptyString);
@@ -133,7 +135,19 @@ protected:
// check that the result is equal to expected value // check that the result is equal to expected value
bool CheckResult(char ch) { return GetResult() == ch; } bool CheckResult(char ch) { return GetResult() == ch; }
wxSocketClient *GetPort(); // return the socket to be used, Passive/Active versions are used only by
// GetPort()
wxSocketBase *GetPort();
wxSocketBase *GetPassivePort();
wxSocketBase *GetActivePort();
// helper for GetPort()
wxString GetPortCmdArgument(wxIPV4address Local, wxIPV4address New);
// accept connection from server in active mode, returns the same socket as
// passed in in passive mode
wxSocketBase *AcceptIfActive(wxSocketBase *sock);
wxString m_user, wxString m_user,
m_passwd; m_passwd;
@@ -151,6 +165,14 @@ protected:
friend class wxInputFTPStream; friend class wxInputFTPStream;
friend class wxOutputFTPStream; friend class wxOutputFTPStream;
bool m_bPassive;
wxUint32 m_uiDefaultTimeout;
// following is true when a read or write times out, we then assume
// the connection is dead and abort. we avoid additional delays this way
bool m_bEncounteredError;
DECLARE_DYNAMIC_CLASS_NO_COPY(wxFTP) DECLARE_DYNAMIC_CLASS_NO_COPY(wxFTP)
DECLARE_PROTOCOL(wxFTP) DECLARE_PROTOCOL(wxFTP)
}; };

View File

@@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
// Name: ftp.cpp // Name: common/ftp.cpp
// Purpose: FTP protocol // Purpose: FTP protocol
// Author: Guilhem Lavaux // Author: Guilhem Lavaux
// Modified by: Mark Johnson, wxWindows@mj10777.de // Modified by: Mark Johnson, wxWindows@mj10777.de
@@ -7,9 +7,11 @@
// Vadim Zeitlin (numerous fixes and rewrites to all part of the // Vadim Zeitlin (numerous fixes and rewrites to all part of the
// code, support ASCII/Binary modes, better error reporting, more // code, support ASCII/Binary modes, better error reporting, more
// robust Abort(), support for arbitrary FTP commands, ...) // robust Abort(), support for arbitrary FTP commands, ...)
// Randall Fox (support for active mode)
// Created: 07/07/1997 // Created: 07/07/1997
// RCS-ID: $Id$ // RCS-ID: $Id$
// Copyright: (c) 1997, 1998 Guilhem Lavaux // Copyright: (c) 1997, 1998 Guilhem Lavaux
// (c) 1998-2004 wxWidgets team
// Licence: wxWindows licence // Licence: wxWindows licence
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
@@ -90,15 +92,21 @@ wxFTP::wxFTP()
SetNotify(0); SetNotify(0);
SetFlags(wxSOCKET_NONE); SetFlags(wxSOCKET_NONE);
m_bPassive = true;
SetDefaultTimeout(60); // Default is Sixty Seconds
m_bEncounteredError = false;
} }
wxFTP::~wxFTP() wxFTP::~wxFTP()
{ {
if ( m_streaming ) if ( m_streaming )
{ {
// if we are streaming, this will issue
// an FTP ABORT command, to tell the server we are aborting
(void)Abort(); (void)Abort();
} }
// now this issues a "QUIT" command to tell the server we are
Close(); Close();
} }
@@ -228,6 +236,11 @@ char wxFTP::SendCommand(const wxString& command)
char wxFTP::GetResult() char wxFTP::GetResult()
{ {
// if we've already had a read or write timeout error, the connection is
// probably toast, so don't bother, it just wastes the users time
if ( m_bEncounteredError )
return 0;
wxString code; wxString code;
// m_lastResult will contain the entire server response, possibly on // m_lastResult will contain the entire server response, possibly on
@@ -247,9 +260,12 @@ char wxFTP::GetResult()
while ( !endOfReply && !badReply ) while ( !endOfReply && !badReply )
{ {
wxString line; wxString line;
m_lastError = ReadLine(line); m_lastError = ReadLine(this,line);
if ( m_lastError ) if ( m_lastError )
{
m_bEncounteredError = true;
return 0; return 0;
}
if ( !m_lastResult.empty() ) if ( !m_lastResult.empty() )
{ {
@@ -494,36 +510,43 @@ public:
: wxSocketInputStream(*sock) : wxSocketInputStream(*sock)
{ {
m_ftp = ftp; m_ftp = ftp;
// socket timeout automatically set in GetPort function
// FIXME make the timeout configurable
// set a shorter than default timeout
m_i_socket->SetTimeout(60); // 1 minute
} }
size_t GetSize() const { return m_ftpsize; }
virtual ~wxInputFTPStream() virtual ~wxInputFTPStream()
{ {
delete m_i_socket; delete m_i_socket; // keep at top
if ( IsOk() ) // when checking the result, the stream will
// almost always show an error, even if the file was
// properly transfered, thus, lets just grab the result
// we are looking for "226 transfer completed"
char code = m_ftp->GetResult();
if ('2' == code)
{ {
// wait for "226 transfer completed" // it was a good transfer.
m_ftp->CheckResult('2'); // we're done!
m_ftp->m_streaming = false;
m_ftp->m_streaming = false; return;
} }
else // did we timeout?
if (0 == code)
{ {
// the connection is probably toast. issue an abort, and
// then a close. there won't be any more waiting
// for this connection
m_ftp->Abort(); m_ftp->Abort();
m_ftp->Close();
return;
} }
// There was a problem with the transfer and the server
// delete m_i_socket; // moved to top of destructor to accomodate wu-FTPd >= 2.6.0 // has acknowledged it. If we issue an "ABORT" now, the user
// would get the "226" for the abort and think the xfer was
// complete, thus, don't do anything here, just return
} }
wxFTP *m_ftp; wxFTP *m_ftp;
size_t m_ftpsize;
DECLARE_NO_COPY_CLASS(wxInputFTPStream) DECLARE_NO_COPY_CLASS(wxInputFTPStream)
}; };
@@ -545,7 +568,7 @@ public:
delete m_o_socket; delete m_o_socket;
// read this reply // read this reply
m_ftp->CheckResult('2'); m_ftp->GetResult(); // save result so user can get to it
m_ftp->m_streaming = false; m_ftp->m_streaming = false;
} }
@@ -564,26 +587,130 @@ public:
DECLARE_NO_COPY_CLASS(wxOutputFTPStream) DECLARE_NO_COPY_CLASS(wxOutputFTPStream)
}; };
wxSocketClient *wxFTP::GetPort() void wxFTP::SetDefaultTimeout(wxUint32 Value)
{ {
int a[6]; m_uiDefaultTimeout = Value;
SetTimeout(Value); // sets it for this socket
}
wxSocketBase *wxFTP::GetPort()
{
/*
PASSIVE: Client sends a "PASV" to the server. The server responds with
an address and port number which it will be listening on. Then
the client connects to the server at the specified address and
port.
ACTIVE: Client sends the server a PORT command which includes an
address and port number which the client will be listening on.
The server then connects to the client at that address and
port.
*/
wxSocketBase *socket = m_bPassive ? GetPassivePort() : GetActivePort();
if ( !socket )
{
m_bEncounteredError = true;
return NULL;
}
// Now set the time for the new socket to the default or user selected
// timeout period
socket->SetTimeout(m_uiDefaultTimeout);
return socket;
}
wxSocketBase *wxFTP::AcceptIfActive(wxSocketBase *sock)
{
if ( m_bPassive )
return sock;
// now wait for a connection from server
wxSocketServer *sockSrv = (wxSocketServer *)sock;
if ( !sockSrv->WaitForAccept() )
{
m_lastError = wxPROTO_CONNERR;
wxLogError(_("Timeout while waiting for FTP server to connect, try passive mode."));
delete sock;
sock = NULL;
}
else
{
sock = sockSrv->Accept(true);
delete sockSrv;
}
return sock;
}
wxString wxFTP::GetPortCmdArgument(wxIPV4address addrLocal,
wxIPV4address addrNew)
{
// Just fills in the return value with the local IP
// address of the current socket. Also it fill in the
// PORT which the client will be listening on
wxString addrIP = addrLocal.IPAddress();
int portNew = addrNew.Service();
// We need to break the PORT number in bytes
addrIP.Replace(_T("."), _T(","));
addrIP << _T(',')
<< wxString::Format(_T("%d"), portNew >> 8) << _T(',')
<< wxString::Format(_T("%d"), portNew & 0xff);
// Now we have a value like "10,0,0,1,5,23"
return addrIP;
}
wxSocketBase *wxFTP::GetActivePort()
{
// we need an address to listen on
wxIPV4address addrNew, addrLocal;
GetLocal(addrLocal);
addrNew.AnyAddress();
addrNew.Service(0); // pick an open port number.
wxSocketServer *sockSrv = new wxSocketServer(addrNew);
if (!sockSrv->Ok())
{
// We use Ok() here to see if everything is ok
m_lastError = wxPROTO_PROTERR;
delete sockSrv;
return NULL;
}
//gets the new address, actually it is just the port number
sockSrv->GetLocal(addrNew);
// Now we create the argument of the PORT command, we send in both
// addresses because the addrNew has an IP of "0.0.0.0", so we need the
// value in addrLocal
wxString port = GetPortCmdArgument(addrLocal, addrNew);
if ( !DoSimpleCommand(_T("PORT "), port) )
{
m_lastError = wxPROTO_PROTERR;
delete sockSrv;
wxLogError(_("The FTP server doesn't support the PORT command."));
return NULL;
}
sockSrv->Notify(false); // Don't send any events
return sockSrv;
}
wxSocketBase *wxFTP::GetPassivePort()
{
if ( !DoSimpleCommand(_T("PASV")) ) if ( !DoSimpleCommand(_T("PASV")) )
{ {
wxLogError(_("The FTP server doesn't support passive mode.")); wxLogError(_("The FTP server doesn't support passive mode."));
return NULL; return NULL;
} }
const wxChar *addrStart = wxStrchr(m_lastResult, _T('(')); const wxChar *addrStart = wxStrchr(m_lastResult, _T('('));
if ( !addrStart ) const wxChar *addrEnd = addrStart ? wxStrchr(addrStart, _T(')')) : NULL;
{
m_lastError = wxPROTO_PROTERR;
return NULL;
}
const wxChar *addrEnd = wxStrchr(addrStart, _T(')'));
if ( !addrEnd ) if ( !addrEnd )
{ {
m_lastError = wxPROTO_PROTERR; m_lastError = wxPROTO_PROTERR;
@@ -591,8 +718,9 @@ wxSocketClient *wxFTP::GetPort()
return NULL; return NULL;
} }
// get the port number and address
int a[6];
wxString straddr(addrStart + 1, addrEnd); wxString straddr(addrStart + 1, addrEnd);
wxSscanf(straddr, wxT("%d,%d,%d,%d,%d,%d"), wxSscanf(straddr, wxT("%d,%d,%d,%d,%d,%d"),
&a[2],&a[3],&a[4],&a[5],&a[0],&a[1]); &a[2],&a[3],&a[4],&a[5],&a[0],&a[1]);
@@ -632,13 +760,10 @@ bool wxFTP::Abort()
wxInputStream *wxFTP::GetInputStream(const wxString& path) wxInputStream *wxFTP::GetInputStream(const wxString& path)
{ {
int pos_size;
wxInputFTPStream *in_stream;
if ( ( m_currentTransfermode == NONE ) && !SetTransferMode(BINARY) ) if ( ( m_currentTransfermode == NONE ) && !SetTransferMode(BINARY) )
return NULL; return NULL;
wxSocketClient *sock = GetPort(); wxSocketBase *sock = GetPort();
if ( !sock ) if ( !sock )
{ {
@@ -650,20 +775,16 @@ wxInputStream *wxFTP::GetInputStream(const wxString& path)
if ( !CheckCommand(tmp_str, '1') ) if ( !CheckCommand(tmp_str, '1') )
return NULL; return NULL;
m_streaming = true; sock = AcceptIfActive(sock);
if ( !sock )
in_stream = new wxInputFTPStream(this, sock); return NULL;
pos_size = m_lastResult.Index(wxT('('));
if ( pos_size != wxNOT_FOUND )
{
wxString str_size = m_lastResult(pos_size+1, m_lastResult.Index(wxT(')'))-1);
in_stream->m_ftpsize = wxAtoi(WXSTRINGCAST str_size);
}
sock->SetFlags(wxSOCKET_WAITALL); sock->SetFlags(wxSOCKET_WAITALL);
m_streaming = true;
wxInputFTPStream *in_stream = new wxInputFTPStream(this, sock);
return in_stream; return in_stream;
} }
@@ -672,12 +793,14 @@ wxOutputStream *wxFTP::GetOutputStream(const wxString& path)
if ( ( m_currentTransfermode == NONE ) && !SetTransferMode(BINARY) ) if ( ( m_currentTransfermode == NONE ) && !SetTransferMode(BINARY) )
return NULL; return NULL;
wxSocketClient *sock = GetPort(); wxSocketBase *sock = GetPort();
wxString tmp_str = wxT("STOR ") + path; wxString tmp_str = wxT("STOR ") + path;
if ( !CheckCommand(tmp_str, '1') ) if ( !CheckCommand(tmp_str, '1') )
return NULL; return NULL;
sock = AcceptIfActive(sock);
m_streaming = true; m_streaming = true;
return new wxOutputFTPStream(this, sock); return new wxOutputFTPStream(this, sock);
@@ -706,22 +829,28 @@ bool wxFTP::GetList(wxArrayString& files,
line << _T(' ') << wildcard; line << _T(' ') << wildcard;
} }
if (!CheckCommand(line, '1')) if ( !CheckCommand(line, '1') )
{ {
m_lastError = wxPROTO_PROTERR;
wxLogDebug("FTP 'LIST' command returned unexpected result from server");
delete sock;
return false; return false;
} }
sock = AcceptIfActive(sock);
if ( !sock )
return false;
files.Empty(); files.Empty();
while ( ReadLine(sock, line) == wxPROTO_NOERR ) while (ReadLine(sock, line) == wxPROTO_NOERR )
{ {
files.Add(line); files.Add(line);
} }
delete sock; delete sock;
// the file list should be terminated by "226 Transfer complete"" // the file list should be terminated by "226 Transfer complete""
if ( !CheckResult('2') ) return CheckResult('2');
return false;
return true;
} }
bool wxFTP::FileExists(const wxString& fileName) bool wxFTP::FileExists(const wxString& fileName)