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