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