]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/common/ftp.cpp
moved wxDash typedef to gdicmn.h
[wxWidgets.git] / src / common / ftp.cpp
... / ...
CommitLineData
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#ifdef __BORLANDC__
20 #pragma hdrstop
21#endif
22
23#if wxUSE_SOCKETS
24
25#ifndef __MWERKS__
26#include <memory.h>
27#endif
28#if defined(__WXMAC__)
29#include "/wx/mac/macsock.h"
30#endif
31
32#include <stdlib.h>
33#include "wx/string.h"
34#include "wx/utils.h"
35#include "wx/sckaddr.h"
36#include "wx/socket.h"
37#include "wx/url.h"
38#include "wx/sckstrm.h"
39#include "wx/protocol/protocol.h"
40#include "wx/protocol/ftp.h"
41
42#ifdef __BORLANDC__
43#pragma hdrstop
44#endif
45
46#define FTP_BSIZE 1024
47
48IMPLEMENT_DYNAMIC_CLASS(wxFTP, wxProtocol)
49IMPLEMENT_PROTOCOL(wxFTP, wxT("ftp"), wxT("ftp"), TRUE)
50
51////////////////////////////////////////////////////////////////
52////// wxFTP constructor and destructor ////////////////////////
53////////////////////////////////////////////////////////////////
54
55wxFTP::wxFTP()
56 : wxProtocol()
57{
58 m_lastError = wxPROTO_NOERR;
59 m_streaming = FALSE;
60
61 m_user = wxT("anonymous");
62 m_passwd = wxGetUserId();
63 m_passwd += wxT('@');
64 m_passwd += wxGetHostName();
65
66 SetNotify(0);
67 SetFlags(wxSOCKET_NONE);
68}
69
70wxFTP::~wxFTP()
71{
72 SendCommand("QUIT", '2');
73}
74
75////////////////////////////////////////////////////////////////
76////// wxFTP connect and login methods /////////////////////////
77////////////////////////////////////////////////////////////////
78bool wxFTP::Connect(wxSockAddress& addr, bool WXUNUSED(wait))
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(wxT("USER %s"), (const wxChar *)m_user);
98 if (!SendCommand(command, '3')) {
99 Close();
100 return FALSE;
101 }
102
103 command.sprintf(wxT("PASS %s"), (const wxChar *)m_passwd);
104 if (!SendCommand(command, '2')) {
105 Close();
106 return FALSE;
107 }
108
109 return TRUE;
110}
111
112bool wxFTP::Connect(const wxString& host)
113{
114 wxIPV4address addr;
115 wxString my_host = host;
116
117 addr.Hostname(my_host);
118 addr.Service(wxT("ftp"));
119
120 return Connect(addr);
121}
122
123bool wxFTP::Close()
124{
125 if (m_streaming) {
126 m_lastError = wxPROTO_STREAMING;
127 return FALSE;
128 }
129 if (IsConnected())
130 SendCommand(wxString(wxT("QUIT")), '2');
131
132 return wxSocketClient::Close();
133}
134
135////////////////////////////////////////////////////////////////
136////// wxFTP low-level methods /////////////////////////////////
137////////////////////////////////////////////////////////////////
138bool wxFTP::SendCommand(const wxString& command, char exp_ret)
139{
140 wxString tmp_str;
141
142 if (m_streaming) {
143 m_lastError = wxPROTO_STREAMING;
144 return FALSE;
145 }
146 tmp_str = command + wxT("\r\n");
147 const wxWX2MBbuf tmp_buf = tmp_str.mb_str();
148 if (Write(wxMBSTRINGCAST tmp_buf, strlen(tmp_buf)).Error()) {
149 m_lastError = wxPROTO_NETERR;
150 return FALSE;
151 }
152 return GetResult(exp_ret);
153}
154
155bool wxFTP::GetResult(char exp)
156{
157 m_lastError = GetLine(this, m_lastResult);
158 if ( m_lastError )
159 return FALSE;
160 if (m_lastResult.GetChar(0) != exp) {
161 m_lastError = wxPROTO_PROTERR;
162 return FALSE;
163 }
164
165 if (m_lastResult.GetChar(3) == '-') {
166 wxString key = m_lastResult.Left((size_t)3);
167
168 key += wxT(' ');
169
170 while (m_lastResult.Index(key) != 0) {
171 m_lastError = GetLine(this, m_lastResult);
172 if ( m_lastError )
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(wxT("CWD "));
187 return SendCommand(str, '2');
188}
189
190bool wxFTP::MkDir(const wxString& dir)
191{
192 wxString str = dir;
193 str.Prepend(wxT("MKD "));
194 return SendCommand(str, '2');
195}
196
197bool wxFTP::RmDir(const wxString& dir)
198{
199 wxString str = dir;
200
201 str.Prepend(wxT("PWD "));
202 return SendCommand(str, '2');
203}
204
205wxString wxFTP::Pwd()
206{
207 int beg, end;
208
209 if (!SendCommand(wxT("PWD"), '2'))
210 return wxString((char *)NULL);
211
212 beg = m_lastResult.Find(wxT('\"'),FALSE);
213 end = m_lastResult.Find(wxT('\"'),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 = wxT("RNFR ") + src;
223 if (!SendCommand(str, '3'))
224 return FALSE;
225
226 str = wxT("RNTO ") + dst;
227 return SendCommand(str, '2');
228}
229
230bool wxFTP::RmFile(const wxString& path)
231{
232 wxString str;
233
234 str = wxT("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 size_t m_ftpsize;
247
248 wxInputFTPStream(wxFTP *ftp_clt, wxSocketBase *sock)
249 : wxSocketInputStream(*sock), m_ftp(ftp_clt) {}
250 size_t GetSize() const { return m_ftpsize; }
251 virtual ~wxInputFTPStream(void)
252 {
253 if (LastError() == wxStream_NOERROR)
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 {
269 if (LastError() != wxStream_NOERROR)
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 int a[6];
282 wxString straddr;
283 int addr_pos;
284 wxUint16 port;
285 wxUint32 hostaddr;
286
287 if (!SendCommand(wxT("PASV"), '2'))
288 return NULL;
289
290 addr_pos = m_lastResult.Find(wxT('('));
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 wxSscanf((const wxChar *)straddr,wxT("%d,%d,%d,%d,%d,%d"),&a[2],&a[3],&a[4],&a[5],&a[0],&a[1]);
297
298 hostaddr = (wxUint16)a[5] << 24 | (wxUint16)a[4] << 16 |
299 (wxUint16)a[3] << 8 | a[2];
300 addr.Hostname(hostaddr);
301
302 port = (wxUint16)a[0] << 8 | a[1];
303 addr.Service(port);
304
305 client = new wxSocketClient();
306 if (!client->Connect(addr)) {
307 delete client;
308 return NULL;
309 }
310 client->Notify(FALSE);
311
312 return client;
313}
314
315bool wxFTP::Abort(void)
316{
317 m_streaming = FALSE;
318 if (!SendCommand(wxT("ABOR"), '4'))
319 return FALSE;
320 return GetResult('2');
321}
322
323wxInputStream *wxFTP::GetInputStream(const wxString& path)
324{
325 wxString tmp_str;
326 int pos_size;
327 wxInputFTPStream *in_stream;
328
329 if (!SendCommand(wxT("TYPE I"), '2'))
330 return NULL;
331
332 wxSocketClient *sock = GetPort();
333
334 if (!sock) {
335 m_lastError = wxPROTO_NETERR;
336 return NULL;
337 }
338
339 tmp_str = wxT("RETR ") + wxURL::ConvertFromURI(path);
340 if (!SendCommand(tmp_str, '1'))
341 return NULL;
342
343 in_stream = new wxInputFTPStream(this, sock);
344
345 pos_size = m_lastResult.Index(wxT('('));
346 if (pos_size != wxNOT_FOUND) {
347 wxString str_size = m_lastResult(pos_size+1, m_lastResult.Index(wxT(')'))-1);
348
349 in_stream->m_ftpsize = wxAtoi(WXSTRINGCAST str_size);
350 }
351 sock->SetFlags(wxSOCKET_WAITALL);
352
353 return in_stream;
354}
355
356wxOutputStream *wxFTP::GetOutputStream(const wxString& path)
357{
358 wxString tmp_str;
359
360 if (!SendCommand(wxT("TYPE I"), '2'))
361 return NULL;
362
363 wxSocketClient *sock = GetPort();
364
365 tmp_str = wxT("STOR ") + path;
366 if (!SendCommand(tmp_str, '1'))
367 return FALSE;
368
369 return new wxOutputFTPStream(this, sock);
370}
371
372wxList *wxFTP::GetList(const wxString& wildcard)
373{
374 wxList *file_list = new wxList;
375 wxSocketBase *sock = GetPort();
376 wxString tmp_str = wxT("NLST");
377
378 if (!wildcard.IsNull())
379 tmp_str += wildcard;
380
381 if (!SendCommand(tmp_str, '1')) {
382 delete sock;
383 delete file_list;
384 return NULL;
385 }
386
387 while (GetLine(sock, tmp_str) == wxPROTO_NOERR) {
388 file_list->Append((wxObject *)(new wxString(tmp_str)));
389 }
390
391 if (!GetResult('2')) {
392 delete sock;
393 file_list->DeleteContents(TRUE);
394 delete file_list;
395 return NULL;
396 }
397
398 return file_list;
399}
400#endif
401 // wxUSE_SOCKETS