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