]> git.saurik.com Git - wxWidgets.git/blame - src/common/ftp.cpp
don't log empty status messages in wxLogWindow
[wxWidgets.git] / src / common / ftp.cpp
CommitLineData
f4ada568
GL
1/////////////////////////////////////////////////////////////////////////////
2// Name: ftp.cpp
3// Purpose: FTP protocol
4// Author: Guilhem Lavaux
5// Modified by:
6// Created: 07/07/1997
7// RCS-ID: $Id$
8// Copyright: (c) 1997, 1998 Guilhem Lavaux
9// Licence: wxWindows license
10/////////////////////////////////////////////////////////////////////////////
11
12#ifdef __GNUG__
13#pragma implementation "ftp.h"
14#endif
ec45f8ee
UU
15
16// For compilers that support precompilation, includes "wx.h".
17#include "wx/wxprec.h"
18
19ae5cf0
UU
19#ifdef __BORLANDC__
20#pragma hdrstop
21#endif
22
35a4dab7
GL
23#if wxUSE_SOCKETS
24
469e1e5c 25#ifndef __MWERKS__
f4ada568 26#include <memory.h>
469e1e5c 27#endif
17dff81c
SC
28#if defined(__WXMAC__)
29#include "/wx/mac/macsock.h"
30#endif
31
f4ada568
GL
32#include <stdlib.h>
33#include "wx/string.h"
34#include "wx/utils.h"
35// #include "wx/data.h"
36#define WXSOCK_INTERNAL
37#include "wx/sckaddr.h"
38#undef WXSOCK_INTERNAL
39#include "wx/socket.h"
40#include "wx/url.h"
41#include "wx/sckstrm.h"
42#include "wx/protocol/protocol.h"
43#include "wx/protocol/ftp.h"
44
45#ifdef __BORLANDC__
46#pragma hdrstop
47#endif
48
49#define FTP_BSIZE 1024
50
51#if !USE_SHARED_LIBRARY
52IMPLEMENT_DYNAMIC_CLASS(wxFTP, wxProtocol)
4846abaf 53IMPLEMENT_PROTOCOL(wxFTP, _T("ftp"), _T("ftp"), TRUE)
f4ada568
GL
54#endif
55
56////////////////////////////////////////////////////////////////
57////// wxFTP constructor and destructor ////////////////////////
58////////////////////////////////////////////////////////////////
59
60wxFTP::wxFTP()
61 : wxProtocol()
62{
4846abaf 63 wxChar tmp[256];
f4ada568
GL
64
65 m_lastError = wxPROTO_NOERR;
66 m_streaming = FALSE;
67
4846abaf 68 m_user = _T("anonymous");
f4ada568 69 wxGetUserName(tmp, 256);
4846abaf 70 m_passwd.sprintf(_T("%s@"),tmp);
f4ada568
GL
71 wxGetHostName(tmp, 256);
72 m_passwd += tmp;
73
74 SetNotify(0);
75}
76
77wxFTP::~wxFTP()
78{
79 SendCommand("QUIT", '2');
80}
81
82////////////////////////////////////////////////////////////////
83////// wxFTP connect and login methods /////////////////////////
84////////////////////////////////////////////////////////////////
8a2c6ef8 85bool wxFTP::Connect(wxSockAddress& addr, bool WXUNUSED(wait))
f4ada568
GL
86{
87 if (!m_handler) {
88 m_lastError = wxPROTO_NOHNDLR;
89 return FALSE;
90 }
91
92 if (!wxProtocol::Connect(addr)) {
93 m_lastError = wxPROTO_NETERR;
94 return FALSE;
95 }
96
97 if (!m_user || !m_passwd) {
98 m_lastError = wxPROTO_CONNERR;
99 return FALSE;
100 }
101
102 wxString command;
103
104 if (!GetResult('2')) {
105 Close();
106 return FALSE;
107 }
108
4846abaf 109 command.sprintf(_T("USER %s"), (const wxChar *)m_user);
f4ada568
GL
110 if (!SendCommand(command, '3')) {
111 Close();
112 return FALSE;
113 }
114
4846abaf 115 command.sprintf(_T("PASS %s"), (const wxChar *)m_passwd);
f4ada568
GL
116 if (!SendCommand(command, '2')) {
117 Close();
118 return FALSE;
119 }
120
121 return TRUE;
122}
123
124bool wxFTP::Connect(const wxString& host)
125{
126 wxIPV4address addr;
127 wxString my_host = host;
128
129 addr.Hostname(my_host);
4846abaf 130 addr.Service(_T("ftp"));
f4ada568
GL
131
132 return Connect(addr);
133}
134
135bool wxFTP::Close()
136{
137 if (m_streaming) {
138 m_lastError = wxPROTO_STREAMING;
139 return FALSE;
140 }
141 if (m_connected)
4846abaf 142 SendCommand(wxString(_T("QUIT")), '2');
f4ada568
GL
143 return wxSocketClient::Close();
144}
145
146////////////////////////////////////////////////////////////////
147////// wxFTP low-level methods /////////////////////////////////
148////////////////////////////////////////////////////////////////
149bool wxFTP::SendCommand(const wxString& command, char exp_ret)
150{
151 wxString tmp_str;
152
153 if (m_streaming) {
154 m_lastError = wxPROTO_STREAMING;
155 return FALSE;
156 }
4846abaf 157 tmp_str = command + _T("\r\n");
fde7d98e 158 const wxWX2MBbuf tmp_buf = tmp_str.mb_str();
4846abaf 159 if (Write(MBSTRINGCAST tmp_buf, strlen(tmp_buf)).Error()) {
f4ada568
GL
160 m_lastError = wxPROTO_NETERR;
161 return FALSE;
162 }
163 return GetResult(exp_ret);
164}
165
166bool wxFTP::GetResult(char exp)
167{
168 if ((m_lastError = GetLine(this, m_lastResult)))
169 return FALSE;
4b5f3fe6 170 if (m_lastResult.GetChar(0) != exp) {
f4ada568
GL
171 m_lastError = wxPROTO_PROTERR;
172 return FALSE;
173 }
174
4b5f3fe6 175 if (m_lastResult.GetChar(3) == '-') {
f4ada568
GL
176 wxString key = m_lastResult.Left((size_t)3);
177
4846abaf 178 key += _T(' ');
f4ada568
GL
179
180 while (m_lastResult.Index(key) != 0) {
181 if ((m_lastError = GetLine(this, m_lastResult)))
182 return FALSE;
183 }
184 }
185 return TRUE;
186}
187
188////////////////////////////////////////////////////////////////
189////// wxFTP low-level methods /////////////////////////////////
190////////////////////////////////////////////////////////////////
191bool wxFTP::ChDir(const wxString& dir)
192{
193 wxString str = dir;
194
4846abaf 195 str.Prepend(_T("CWD "));
f4ada568
GL
196 return SendCommand(str, '2');
197}
198
199bool wxFTP::MkDir(const wxString& dir)
200{
201 wxString str = dir;
4846abaf 202 str.Prepend(_T("MKD "));
f4ada568
GL
203 return SendCommand(str, '2');
204}
205
206bool wxFTP::RmDir(const wxString& dir)
207{
208 wxString str = dir;
209
4846abaf 210 str.Prepend(_T("PWD "));
f4ada568
GL
211 return SendCommand(str, '2');
212}
213
214wxString wxFTP::Pwd()
215{
216 int beg, end;
217
4846abaf 218 if (!SendCommand(_T("PWD"), '2'))
f4ada568
GL
219 return wxString((char *)NULL);
220
4846abaf
OK
221 beg = m_lastResult.Find(_T('\"'),FALSE);
222 end = m_lastResult.Find(_T('\"'),TRUE);
f4ada568
GL
223
224 return wxString(beg+1, end);
225}
226
227bool wxFTP::Rename(const wxString& src, const wxString& dst)
228{
229 wxString str;
230
4846abaf 231 str = _T("RNFR ") + src;
f4ada568
GL
232 if (!SendCommand(str, '3'))
233 return FALSE;
234
4846abaf 235 str = _T("RNTO ") + dst;
f4ada568
GL
236 return SendCommand(str, '2');
237}
238
239bool wxFTP::RmFile(const wxString& path)
240{
241 wxString str;
242
4846abaf 243 str = _T("DELE ");
f4ada568
GL
244 str += path;
245 return SendCommand(str, '2');
246}
247
248////////////////////////////////////////////////////////////////
249////// wxFTP download*upload ///////////////////////////////////
250////////////////////////////////////////////////////////////////
251
252class wxInputFTPStream : public wxSocketInputStream {
253public:
254 wxFTP *m_ftp;
9a1b2c28 255 size_t m_ftpsize;
f4ada568
GL
256
257 wxInputFTPStream(wxFTP *ftp_clt, wxSocketBase *sock)
258 : wxSocketInputStream(*sock), m_ftp(ftp_clt) {}
375abe3d 259 size_t StreamSize() const { return m_ftpsize; }
f4ada568
GL
260 virtual ~wxInputFTPStream(void)
261 {
75ed1d15 262 if (LastError() != wxStream_NOERROR)
f4ada568
GL
263 m_ftp->GetResult('2');
264 else
265 m_ftp->Abort();
266 delete m_i_socket;
267 }
268};
269
270class wxOutputFTPStream : public wxSocketOutputStream {
271public:
272 wxFTP *m_ftp;
273
274 wxOutputFTPStream(wxFTP *ftp_clt, wxSocketBase *sock)
275 : wxSocketOutputStream(*sock), m_ftp(ftp_clt) {}
276 virtual ~wxOutputFTPStream(void)
277 {
75ed1d15 278 if (LastError() != wxStream_NOERROR)
f4ada568
GL
279 m_ftp->GetResult('2');
280 else
281 m_ftp->Abort();
282 delete m_o_socket;
283 }
284};
285
286wxSocketClient *wxFTP::GetPort()
287{
288 wxIPV4address addr;
289 wxSocketClient *client;
290 struct sockaddr sin;
291 int a[6];
292 wxString straddr;
293 int addr_pos;
294
4846abaf 295 if (!SendCommand(_T("PASV"), '2'))
f4ada568
GL
296 return NULL;
297
298 sin.sa_family = AF_INET;
4846abaf 299 addr_pos = m_lastResult.Find(_T('('));
f4ada568
GL
300 if (addr_pos == -1) {
301 m_lastError = wxPROTO_PROTERR;
302 return NULL;
303 }
304 straddr = m_lastResult(addr_pos+1, m_lastResult.Length());
4846abaf 305 wxSscanf((const wxChar *)straddr,_T("%d,%d,%d,%d,%d,%d"),&a[2],&a[3],&a[4],&a[5],&a[0],&a[1]);
f4ada568
GL
306 sin.sa_data[2] = (char)a[2];
307 sin.sa_data[3] = (char)a[3];
308 sin.sa_data[4] = (char)a[4];
309 sin.sa_data[5] = (char)a[5];
310 sin.sa_data[0] = (char)a[0];
311 sin.sa_data[1] = (char)a[1];
312
313 addr.Disassemble(&sin, sizeof(sin));
314
315 client = m_handler->CreateClient();
316 if (!client->Connect(addr)) {
317 delete client;
318 return NULL;
319 }
320 client->Notify(FALSE);
321
322 return client;
323}
324
325bool wxFTP::Abort(void)
326{
327 m_streaming = FALSE;
4846abaf 328 if (!SendCommand(_T("ABOR"), '4'))
f4ada568
GL
329 return FALSE;
330 return GetResult('2');
331}
332
333wxInputStream *wxFTP::GetInputStream(const wxString& path)
334{
335 wxString tmp_str;
9a1b2c28
GL
336 int pos_size;
337 wxInputFTPStream *in_stream;
f4ada568 338
4846abaf 339 if (!SendCommand(_T("TYPE I"), '2'))
f4ada568
GL
340 return NULL;
341
342 wxSocketClient *sock = GetPort();
343
344 if (!sock) {
345 m_lastError = wxPROTO_NETERR;
346 return NULL;
347 }
348
4846abaf 349 tmp_str = _T("RETR ") + path;
f4ada568
GL
350 if (!SendCommand(tmp_str, '1'))
351 return NULL;
352
9a1b2c28
GL
353 in_stream = new wxInputFTPStream(this, sock);
354
4846abaf 355 pos_size = m_lastResult.Index(_T('('));
9a1b2c28 356 if (pos_size != wxNOT_FOUND) {
4846abaf 357 wxString str_size = m_lastResult(pos_size+1, m_lastResult.Index(_T(')'))-1);
9a1b2c28 358
4846abaf 359 in_stream->m_ftpsize = wxAtoi(WXSTRINGCAST str_size);
9a1b2c28
GL
360 }
361
362 return in_stream;
f4ada568
GL
363}
364
365wxOutputStream *wxFTP::GetOutputStream(const wxString& path)
366{
367 wxString tmp_str;
368
4846abaf 369 if (!SendCommand(_T("TYPE I"), '2'))
f4ada568
GL
370 return NULL;
371
372 wxSocketClient *sock = GetPort();
373
4846abaf 374 tmp_str = _T("STOR ") + path;
f4ada568
GL
375 if (!SendCommand(tmp_str, '1'))
376 return FALSE;
377
378 return new wxOutputFTPStream(this, sock);
379}
380
381wxList *wxFTP::GetList(const wxString& wildcard)
382{
383 wxList *file_list = new wxList;
384 wxSocketBase *sock = GetPort();
4846abaf 385 wxString tmp_str = _T("NLST");
f4ada568
GL
386
387 if (!wildcard.IsNull())
388 tmp_str += wildcard;
389
390 if (!SendCommand(tmp_str, '1')) {
391 delete sock;
392 delete file_list;
393 return NULL;
394 }
395
396 while (GetLine(sock, tmp_str) == wxPROTO_NOERR) {
397 file_list->Append((wxObject *)(new wxString(tmp_str)));
398 }
399
400 if (!GetResult('2')) {
401 delete sock;
402 file_list->DeleteContents(TRUE);
403 delete file_list;
404 return NULL;
405 }
406
375abe3d
GL
407 sock->SetEventHandler(*GetNextHandler(), m_id);
408 sock->Notify(m_notifyme);
409 sock->SetNotify(m_neededreq);
410
f4ada568
GL
411 return file_list;
412}
35a4dab7
GL
413#endif
414 // wxUSE_SOCKETS