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