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