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