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