]> git.saurik.com Git - wxWidgets.git/blame - src/common/ftp.cpp
Added Property List classes to main library; added proplist sample; merged
[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
469e1e5c 23#ifndef __MWERKS__
f4ada568 24#include <memory.h>
469e1e5c 25#endif
f4ada568
GL
26#include <stdlib.h>
27#include "wx/string.h"
28#include "wx/utils.h"
29// #include "wx/data.h"
30#define WXSOCK_INTERNAL
31#include "wx/sckaddr.h"
32#undef WXSOCK_INTERNAL
33#include "wx/socket.h"
34#include "wx/url.h"
35#include "wx/sckstrm.h"
36#include "wx/protocol/protocol.h"
37#include "wx/protocol/ftp.h"
38
39#ifdef __BORLANDC__
40#pragma hdrstop
41#endif
42
43#define FTP_BSIZE 1024
44
45#if !USE_SHARED_LIBRARY
46IMPLEMENT_DYNAMIC_CLASS(wxFTP, wxProtocol)
47IMPLEMENT_PROTOCOL(wxFTP, "ftp", "ftp", TRUE)
48#endif
49
50////////////////////////////////////////////////////////////////
51////// wxFTP constructor and destructor ////////////////////////
52////////////////////////////////////////////////////////////////
53
54wxFTP::wxFTP()
55 : wxProtocol()
56{
57 char tmp[256];
58
59 m_lastError = wxPROTO_NOERR;
60 m_streaming = FALSE;
61
62 m_user = "anonymous";
63 wxGetUserName(tmp, 256);
64 m_passwd.sprintf("%s@",tmp);
65 wxGetHostName(tmp, 256);
66 m_passwd += tmp;
67
68 SetNotify(0);
69}
70
71wxFTP::~wxFTP()
72{
73 SendCommand("QUIT", '2');
74}
75
76////////////////////////////////////////////////////////////////
77////// wxFTP connect and login methods /////////////////////////
78////////////////////////////////////////////////////////////////
79bool wxFTP::Connect(wxSockAddress& addr)
80{
81 if (!m_handler) {
82 m_lastError = wxPROTO_NOHNDLR;
83 return FALSE;
84 }
85
86 if (!wxProtocol::Connect(addr)) {
87 m_lastError = wxPROTO_NETERR;
88 return FALSE;
89 }
90
91 if (!m_user || !m_passwd) {
92 m_lastError = wxPROTO_CONNERR;
93 return FALSE;
94 }
95
96 wxString command;
97
98 if (!GetResult('2')) {
99 Close();
100 return FALSE;
101 }
102
103 command.sprintf("USER %s", (const char *)m_user);
104 if (!SendCommand(command, '3')) {
105 Close();
106 return FALSE;
107 }
108
109 command.sprintf("PASS %s", (const char *)m_passwd);
110 if (!SendCommand(command, '2')) {
111 Close();
112 return FALSE;
113 }
114
115 return TRUE;
116}
117
118bool wxFTP::Connect(const wxString& host)
119{
120 wxIPV4address addr;
121 wxString my_host = host;
122
123 addr.Hostname(my_host);
124 addr.Service("ftp");
125
126 return Connect(addr);
127}
128
129bool wxFTP::Close()
130{
131 if (m_streaming) {
132 m_lastError = wxPROTO_STREAMING;
133 return FALSE;
134 }
135 if (m_connected)
136 SendCommand(wxString("QUIT"), '2');
137 return wxSocketClient::Close();
138}
139
140////////////////////////////////////////////////////////////////
141////// wxFTP low-level methods /////////////////////////////////
142////////////////////////////////////////////////////////////////
143bool wxFTP::SendCommand(const wxString& command, char exp_ret)
144{
145 wxString tmp_str;
146
147 if (m_streaming) {
148 m_lastError = wxPROTO_STREAMING;
149 return FALSE;
150 }
151 tmp_str = command + "\r\n";
152 if (Write((char *)tmp_str.GetData(), tmp_str.Length()).Error()) {
153 m_lastError = wxPROTO_NETERR;
154 return FALSE;
155 }
156 return GetResult(exp_ret);
157}
158
159bool wxFTP::GetResult(char exp)
160{
161 if ((m_lastError = GetLine(this, m_lastResult)))
162 return FALSE;
4b5f3fe6 163 if (m_lastResult.GetChar(0) != exp) {
f4ada568
GL
164 m_lastError = wxPROTO_PROTERR;
165 return FALSE;
166 }
167
4b5f3fe6 168 if (m_lastResult.GetChar(3) == '-') {
f4ada568
GL
169 wxString key = m_lastResult.Left((size_t)3);
170
171 key += ' ';
172
173 while (m_lastResult.Index(key) != 0) {
174 if ((m_lastError = GetLine(this, m_lastResult)))
175 return FALSE;
176 }
177 }
178 return TRUE;
179}
180
181////////////////////////////////////////////////////////////////
182////// wxFTP low-level methods /////////////////////////////////
183////////////////////////////////////////////////////////////////
184bool wxFTP::ChDir(const wxString& dir)
185{
186 wxString str = dir;
187
188 str.Prepend("CWD ");
189 return SendCommand(str, '2');
190}
191
192bool wxFTP::MkDir(const wxString& dir)
193{
194 wxString str = dir;
195 str.Prepend("MKD ");
196 return SendCommand(str, '2');
197}
198
199bool wxFTP::RmDir(const wxString& dir)
200{
201 wxString str = dir;
202
203 str.Prepend("PWD ");
204 return SendCommand(str, '2');
205}
206
207wxString wxFTP::Pwd()
208{
209 int beg, end;
210
211 if (!SendCommand("PWD", '2'))
212 return wxString((char *)NULL);
213
214 beg = m_lastResult.Find('\"',FALSE);
215 end = m_lastResult.Find('\"',TRUE);
216
217 return wxString(beg+1, end);
218}
219
220bool wxFTP::Rename(const wxString& src, const wxString& dst)
221{
222 wxString str;
223
224 str = "RNFR " + src;
225 if (!SendCommand(str, '3'))
226 return FALSE;
227
228 str = "RNTO " + dst;
229 return SendCommand(str, '2');
230}
231
232bool wxFTP::RmFile(const wxString& path)
233{
234 wxString str;
235
236 str = "DELE ";
237 str += path;
238 return SendCommand(str, '2');
239}
240
241////////////////////////////////////////////////////////////////
242////// wxFTP download*upload ///////////////////////////////////
243////////////////////////////////////////////////////////////////
244
245class wxInputFTPStream : public wxSocketInputStream {
246public:
247 wxFTP *m_ftp;
248
249 wxInputFTPStream(wxFTP *ftp_clt, wxSocketBase *sock)
250 : wxSocketInputStream(*sock), m_ftp(ftp_clt) {}
251 virtual ~wxInputFTPStream(void)
252 {
75ed1d15 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;
281 struct sockaddr sin;
282 int a[6];
283 wxString straddr;
284 int addr_pos;
285
286 if (!SendCommand("PASV", '2'))
287 return NULL;
288
289 sin.sa_family = AF_INET;
290 addr_pos = m_lastResult.Find('(');
291 if (addr_pos == -1) {
292 m_lastError = wxPROTO_PROTERR;
293 return NULL;
294 }
295 straddr = m_lastResult(addr_pos+1, m_lastResult.Length());
296 sscanf((const char *)straddr,"%d,%d,%d,%d,%d,%d",&a[2],&a[3],&a[4],&a[5],&a[0],&a[1]);
297 sin.sa_data[2] = (char)a[2];
298 sin.sa_data[3] = (char)a[3];
299 sin.sa_data[4] = (char)a[4];
300 sin.sa_data[5] = (char)a[5];
301 sin.sa_data[0] = (char)a[0];
302 sin.sa_data[1] = (char)a[1];
303
304 addr.Disassemble(&sin, sizeof(sin));
305
306 client = m_handler->CreateClient();
307 if (!client->Connect(addr)) {
308 delete client;
309 return NULL;
310 }
311 client->Notify(FALSE);
312
313 return client;
314}
315
316bool wxFTP::Abort(void)
317{
318 m_streaming = FALSE;
319 if (!SendCommand("ABOR", '4'))
320 return FALSE;
321 return GetResult('2');
322}
323
324wxInputStream *wxFTP::GetInputStream(const wxString& path)
325{
326 wxString tmp_str;
327
328 if (!SendCommand("TYPE I", '2'))
329 return NULL;
330
331 wxSocketClient *sock = GetPort();
332
333 if (!sock) {
334 m_lastError = wxPROTO_NETERR;
335 return NULL;
336 }
337
338 tmp_str = "RETR " + path;
339 if (!SendCommand(tmp_str, '1'))
340 return NULL;
341
342 return new wxInputFTPStream(this, sock);
343}
344
345wxOutputStream *wxFTP::GetOutputStream(const wxString& path)
346{
347 wxString tmp_str;
348
349 if (!SendCommand("TYPE I", '2'))
350 return NULL;
351
352 wxSocketClient *sock = GetPort();
353
354 tmp_str = "STOR " + path;
355 if (!SendCommand(tmp_str, '1'))
356 return FALSE;
357
358 return new wxOutputFTPStream(this, sock);
359}
360
361wxList *wxFTP::GetList(const wxString& wildcard)
362{
363 wxList *file_list = new wxList;
364 wxSocketBase *sock = GetPort();
365 wxString tmp_str = "NLST";
366
367 if (!wildcard.IsNull())
368 tmp_str += wildcard;
369
370 if (!SendCommand(tmp_str, '1')) {
371 delete sock;
372 delete file_list;
373 return NULL;
374 }
375
376 while (GetLine(sock, tmp_str) == wxPROTO_NOERR) {
377 file_list->Append((wxObject *)(new wxString(tmp_str)));
378 }
379
380 if (!GetResult('2')) {
381 delete sock;
382 file_list->DeleteContents(TRUE);
383 delete file_list;
384 return NULL;
385 }
386
387 return file_list;
388}