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