FtpClient.cpp (546208a53940a26c6379c48a7854ade1a8250fc5) FtpClient.cpp (dba5824b)
1#include "FtpClient.h"
2
1#include "FtpClient.h"
2
3#include <stdlib.h>
4#include <string.h>
5
6#include <Catalog.h>
7#include <Locale.h>
8
9
10#undef B_TRANSLATION_CONTEXT
11#define B_TRANSLATION_CONTEXT "FtpClient"
12
13
14FtpClient::FtpClient()
3FtpClient::FtpClient()
15 : FileUploadClient(),
16 fState(0),
17 fControl(NULL),
18 fData(NULL)
19{
4{
5 m_control = 0;
6 m_state = 0;
7 m_data = 0;
20}
21
22
8}
9
10
11
23FtpClient::~FtpClient()
24{
12FtpClient::~FtpClient()
13{
25 delete fControl;
26 delete fData;
14 delete m_control;
15 delete m_data;
27}
28
29
16}
17
18
30bool
31FtpClient::ChangeDir(const string& dir)
19bool FtpClient::cd(const string &dir)
32{
33 bool rc = false;
20{
21 bool rc = false;
34 int code, codeType;
35 string cmd = "CWD ", replyString;
22 int code, codetype;
23 string cmd = "CWD ", replystr;
36
24
25
37 cmd += dir;
26 cmd += dir;
38
39 if (dir.length() == 0)
27
28 if(dir.length() == 0)
40 cmd += '/';
29 cmd += '/';
41
42 if (_SendRequest(cmd) == true) {
43 if (_GetReply(replyString, code, codeType) == true) {
44 if (codeType == 2)
30
31 if(p_sendRequest(cmd) == true)
32 {
33 if(p_getReply(replystr, code, codetype) == true)
34 {
35 if(codetype == 2)
45 rc = true;
46 }
47 }
48 return rc;
49}
50
51
36 rc = true;
37 }
38 }
39 return rc;
40}
41
42
52bool
53FtpClient::ListDirContents(string& listing)
43bool FtpClient::ls(string &listing)
54{
55 bool rc = false;
44{
45 bool rc = false;
56 string cmd, replyString;
57 int code, codeType, numRead;
46 string cmd, replystr;
47 int code, codetype, i, numread;
58 char buf[513];
48 char buf[513];
59
49
60 cmd = "TYPE A";
50 cmd = "TYPE A";
51
52 if(p_sendRequest(cmd))
53 p_getReply(replystr, code, codetype);
61
54
62 if (_SendRequest(cmd))
63 _GetReply(replyString, code, codeType);
64
65 if (_OpenDataConnection()) {
55 if(p_openDataConnection())
56 {
66 cmd = "LIST";
57 cmd = "LIST";
67
68 if (_SendRequest(cmd)) {
69 if (_GetReply(replyString, code, codeType)) {
70 if (codeType <= 2) {
71 if (_AcceptDataConnection()) {
72 numRead = 1;
73 while (numRead > 0) {
58
59 if(p_sendRequest(cmd))
60 {
61 if(p_getReply(replystr, code, codetype))
62 {
63 if(codetype <= 2)
64 {
65 if(p_acceptDataConnection())
66 {
67 numread = 1;
68 while(numread > 0)
69 {
74 memset(buf, 0, sizeof(buf));
70 memset(buf, 0, sizeof(buf));
75 numRead = fData->Receive(buf, sizeof(buf) - 1);
71 numread = m_data->Receive(buf, sizeof(buf) - 1);
76 listing += buf;
77 printf(buf);
78 }
72 listing += buf;
73 printf(buf);
74 }
79 if (_GetReply(replyString, code, codeType)) {
80 if (codeType <= 2)
75 if(p_getReply(replystr, code, codetype))
76 {
77 if(codetype <= 2)
78 {
81 rc = true;
79 rc = true;
80 }
82 }
83 }
84 }
85 }
86 }
87 }
88
81 }
82 }
83 }
84 }
85 }
86 }
87
89 delete fData;
90 fData = 0;
88 delete m_data;
89 m_data = 0;
91
92 return rc;
93}
94
95
90
91 return rc;
92}
93
94
96bool
97FtpClient::PrintWorkingDir(string& dir)
95bool FtpClient::pwd(string &dir)
98{
99 bool rc = false;
96{
97 bool rc = false;
100 int code, codeType;
101 string cmd = "PWD", replyString;
98 int code, codetype;
99 string cmd = "PWD", replystr;
102 long i;
100 long i;
103
104 if (_SendRequest(cmd) == true) {
105 if (_GetReply(replyString, code, codeType) == true) {
106 if (codeType == 2) {
107 i = replyString.find('"');
108 if (i != -1) {
101
102 if(p_sendRequest(cmd) == true)
103 {
104 if(p_getReply(replystr, code, codetype) == true)
105 {
106 if(codetype == 2)
107 {
108 i = replystr.find('"');
109 if(i != -1)
110 {
109 i++;
111 i++;
110 dir = replyString.substr(i, replyString.find('"') - i);
112 dir = replystr.substr(i, replystr.find('"') - i);
111 rc = true;
112 }
113 }
114 }
115 }
116
117 return rc;
118}
119
120
113 rc = true;
114 }
115 }
116 }
117 }
118
119 return rc;
120}
121
122
121bool
122FtpClient::Connect(const string& server, const string& login, const string& passwd)
123bool FtpClient::connect(const string &server, const string &login, const string &passwd)
123{
124 bool rc = false;
124{
125 bool rc = false;
125 int code, codeType;
126 string cmd, replyString;
126 int code, codetype;
127 string cmd, replystr;
127 BNetAddress addr;
128 BNetAddress addr;
128
129 delete fControl;
130 delete fData;
131
132 fControl = new BNetEndpoint;
133
134 if (fControl->InitCheck() != B_NO_ERROR)
129
130 delete m_control;
131 delete m_data;
132
133
134 m_control = new BNetEndpoint;
135
136 if(m_control->InitCheck() != B_NO_ERROR)
135 return false;
137 return false;
136
138
137 addr.SetTo(server.c_str(), "tcp", "ftp");
139 addr.SetTo(server.c_str(), "tcp", "ftp");
138 if (fControl->Connect(addr) == B_NO_ERROR) {
140 if(m_control->Connect(addr) == B_NO_ERROR)
141 {
142 //
139 // read the welcome message, do the login
143 // read the welcome message, do the login
140
141 if (_GetReply(replyString, code, codeType)) {
142 if (code != 421 && codeType != 5) {
143 cmd = "USER ";
144 cmd += login;
145 _SendRequest(cmd);
146
147 if (_GetReply(replyString, code, codeType)) {
148 switch (code) {
149 case 230:
150 case 202:
144 //
145
146 if(p_getReply(replystr, code, codetype))
147 {
148 if(code != 421 && codetype != 5)
149 {
150 cmd = "USER "; cmd += login;
151 p_sendRequest(cmd);
152 if(p_getReply(replystr, code, codetype))
153 {
154 switch(code)
155 {
156 case 230:
157 case 202:
151 rc = true;
158 rc = true;
152 break;
153
159 break;
160
154 case 331: // password needed
161 case 331: // password needed
155 cmd = "PASS ";
156 cmd += passwd;
157 _SendRequest(cmd);
158 if (_GetReply(replyString, code, codeType)) {
159 if (codeType == 2)
162 cmd = "PASS "; cmd += passwd;
163 p_sendRequest(cmd);
164 if(p_getReply(replystr, code, codetype))
165 {
166 if(codetype == 2)
167 {
160 rc = true;
168 rc = true;
169 }
161 }
170 }
162 break;
163
171 break;
172
164 default:
173 default:
165 break;
166
174 break;
175
167 }
168 }
169 }
170 }
176 }
177 }
178 }
179 }
171 }
180 }
181
182 if(rc == true)
183 {
184 p_setState(ftp_connected);
172
185
173 if (rc == true)
174 _SetState(ftp_connected);
175 else {
176 delete fControl;
177 fControl = 0;
186 } else {
187 delete m_control;
188 m_control = 0;
178 }
189 }
179
190
180 return rc;
181}
182
183
191 return rc;
192}
193
194
184bool
185FtpClient::PutFile(const string& local, const string& remote, ftp_mode mode)
195
196bool FtpClient::putFile(const string &local, const string &remote, ftp_mode mode)
186{
187 bool rc = false;
197{
198 bool rc = false;
188 string cmd, replyString;
189 int code, codeType, rlen, slen, i;
199 string cmd, replystr;
200 int code, codetype, rlen, slen, i;
190 BFile infile(local.c_str(), B_READ_ONLY);
191 char buf[8192], sbuf[16384], *stmp;
201 BFile infile(local.c_str(), B_READ_ONLY);
202 char buf[8192], sbuf[16384], *stmp;
192
193 if (infile.InitCheck() != B_NO_ERROR)
203
204 if(infile.InitCheck() != B_NO_ERROR)
194 return false;
205 return false;
195
196 if (mode == binary_mode)
206
207 if(mode == binary_mode)
197 cmd = "TYPE I";
198 else
199 cmd = "TYPE A";
208 cmd = "TYPE I";
209 else
210 cmd = "TYPE A";
211
212 if(p_sendRequest(cmd))
213 p_getReply(replystr, code, codetype);
200
214
201 if (_SendRequest(cmd))
202 _GetReply(replyString, code, codeType);
203
204 try {
205 if (_OpenDataConnection()) {
215 try
216 {
217 if(p_openDataConnection())
218 {
206 cmd = "STOR ";
207 cmd += remote;
219 cmd = "STOR ";
220 cmd += remote;
208
209 if (_SendRequest(cmd)) {
210 if (_GetReply(replyString, code, codeType)) {
211 if (codeType <= 2) {
212 if (_AcceptDataConnection()) {
221
222 if(p_sendRequest(cmd))
223 {
224 if(p_getReply(replystr, code, codetype))
225 {
226 if(codetype <= 2)
227 {
228 if(p_acceptDataConnection())
229 {
213 rlen = 1;
230 rlen = 1;
214 while (rlen > 0) {
231 while(rlen > 0)
232 {
215 memset(buf, 0, sizeof(buf));
216 memset(sbuf, 0, sizeof(sbuf));
233 memset(buf, 0, sizeof(buf));
234 memset(sbuf, 0, sizeof(sbuf));
217 rlen = infile.Read((void*)buf, sizeof(buf));
235 rlen = infile.Read((void *) buf, sizeof(buf));
218 slen = rlen;
219 stmp = buf;
236 slen = rlen;
237 stmp = buf;
220 if (mode == ascii_mode) {
238 if(mode == ascii_mode)
239 {
221 stmp = sbuf;
222 slen = 0;
240 stmp = sbuf;
241 slen = 0;
223 for (i = 0; i < rlen; i++) {
224 if (buf[i] == '\n') {
242 for(i=0;i<rlen;i++)
243 {
244 if(buf[i] == '\n')
245 {
225 *stmp = '\r';
226 stmp++;
227 slen++;
228 }
229 *stmp = buf[i];
230 stmp++;
231 slen++;
232 }
233 stmp = sbuf;
234 }
246 *stmp = '\r';
247 stmp++;
248 slen++;
249 }
250 *stmp = buf[i];
251 stmp++;
252 slen++;
253 }
254 stmp = sbuf;
255 }
235 if (slen > 0) {
236 if (fData->Send(stmp, slen) < 0)
256 if(slen > 0)
257 {
258 if(m_data->Send(stmp, slen) < 0)
237 throw "bail";
238 }
239 }
259 throw "bail";
260 }
261 }
240
262
241 rc = true;
242 }
243 }
244 }
245 }
246 }
247 }
263 rc = true;
264 }
265 }
266 }
267 }
268 }
269 }
248
249 catch(const char* errorString)
270
271 catch(const char *errstr)
250 {
272 {
273
251 }
274 }
252
253 delete fData;
254 fData = 0;
255
256 if (rc) {
257 _GetReply(replyString, code, codeType);
258 rc = codeType <= 2;
275
276 delete m_data;
277 m_data = 0;
278
279 if(rc == true)
280 {
281 p_getReply(replystr, code, codetype);
282 rc = (bool) codetype <= 2;
259 }
283 }
260
284
261 return rc;
262}
263
264
285 return rc;
286}
287
288
265bool
266FtpClient::GetFile(const string& remote, const string& local, ftp_mode mode)
289
290bool FtpClient::getFile(const string &remote, const string &local, ftp_mode mode)
267{
268 bool rc = false;
291{
292 bool rc = false;
269 string cmd, replyString;
270 int code, codeType, rlen, slen, i;
293 string cmd, replystr;
294 int code, codetype, rlen, slen, i;
271 BFile outfile(local.c_str(), B_READ_WRITE | B_CREATE_FILE);
272 char buf[8192], sbuf[16384], *stmp;
295 BFile outfile(local.c_str(), B_READ_WRITE | B_CREATE_FILE);
296 char buf[8192], sbuf[16384], *stmp;
273 bool writeError = false;
274
275 if (outfile.InitCheck() != B_NO_ERROR)
297 bool writeerr = false;
298
299 if(outfile.InitCheck() != B_NO_ERROR)
276 return false;
300 return false;
277
278 if (mode == binary_mode)
301
302 if(mode == binary_mode)
279 cmd = "TYPE I";
280 else
281 cmd = "TYPE A";
303 cmd = "TYPE I";
304 else
305 cmd = "TYPE A";
306
307 if(p_sendRequest(cmd))
308 p_getReply(replystr, code, codetype);
282
309
283 if (_SendRequest(cmd))
284 _GetReply(replyString, code, codeType);
285
286 if (_OpenDataConnection()) {
310
311 if(p_openDataConnection())
312 {
287 cmd = "RETR ";
288 cmd += remote;
313 cmd = "RETR ";
314 cmd += remote;
289
290 if (_SendRequest(cmd)) {
291 if (_GetReply(replyString, code, codeType)) {
292 if (codeType <= 2) {
293 if (_AcceptDataConnection()) {
315
316 if(p_sendRequest(cmd))
317 {
318 if(p_getReply(replystr, code, codetype))
319 {
320 if(codetype <= 2)
321 {
322 if(p_acceptDataConnection())
323 {
294 rlen = 1;
295 rc = true;
324 rlen = 1;
325 rc = true;
296 while (rlen > 0) {
326 while(rlen > 0)
327 {
297 memset(buf, 0, sizeof(buf));
298 memset(sbuf, 0, sizeof(sbuf));
328 memset(buf, 0, sizeof(buf));
329 memset(sbuf, 0, sizeof(sbuf));
299 rlen = fData->Receive(buf, sizeof(buf));
300
301 if (rlen > 0) {
302
330 rlen = m_data->Receive(buf, sizeof(buf));
331
332 if(rlen > 0)
333 {
334
303 slen = rlen;
304 stmp = buf;
335 slen = rlen;
336 stmp = buf;
305 if (mode == ascii_mode) {
337 if(mode == ascii_mode)
338 {
306 stmp = sbuf;
307 slen = 0;
339 stmp = sbuf;
340 slen = 0;
308 for (i = 0; i < rlen; i++) {
309 if (buf[i] == '\r')
341 for(i=0;i<rlen;i++)
342 {
343 if(buf[i] == '\r')
344 {
310 i++;
345 i++;
346 }
311 *stmp = buf[i];
312 stmp++;
313 slen++;
314 }
315 stmp = sbuf;
316 }
347 *stmp = buf[i];
348 stmp++;
349 slen++;
350 }
351 stmp = sbuf;
352 }
317
318 if (slen > 0) {
319 if (outfile.Write(stmp, slen) < 0)
320 writeError = true;
353
354 if(slen > 0)
355 {
356 if(outfile.Write(stmp, slen) < 0)
357 {
358 writeerr = true;
359 }
321 }
322 }
323 }
360 }
361 }
362 }
363
324 }
325 }
326 }
327 }
328 }
364 }
365 }
366 }
367 }
368 }
329
330 delete fData;
331 fData = 0;
332
333 if (rc) {
334 _GetReply(replyString, code, codeType);
335 rc = (codeType <= 2 && writeError == false);
336 }
369
370 delete m_data;
371 m_data = 0;
372
373 if(rc == true)
374 {
375 p_getReply(replystr, code, codetype);
376 rc = (bool) ((codetype <= 2) && (writeerr == false));
377 }
337 return rc;
338}
339
378 return rc;
379}
380
340
381//
341// Note: this only works for local remote moves, cross filesystem moves
342// will not work
382// Note: this only works for local remote moves, cross filesystem moves
383// will not work
343bool
344FtpClient::MoveFile(const string& oldPath, const string& newPath)
384//
385bool FtpClient::moveFile(const string &oldpath, const string &newpath)
345{
346 bool rc = false;
347 string from = "RNFR ";
348 string to = "RNTO ";
386{
387 bool rc = false;
388 string from = "RNFR ";
389 string to = "RNTO ";
349 string replyString;
350 int code, codeType;
390 string replystr;
391 int code, codetype;
351
392
352 from += oldPath;
353 to += newPath;
354
355 if (_SendRequest(from)) {
356 if (_GetReply(replyString, code, codeType)) {
357 if (codeType == 3) {
358 if (_SendRequest(to)) {
359 if (_GetReply(replyString, code, codeType)) {
360 if(codeType == 2)
393 from += oldpath;
394 to += newpath;
395
396 if(p_sendRequest(from))
397 {
398 if(p_getReply(replystr, code, codetype))
399 {
400 if(codetype == 3)
401 {
402 if(p_sendRequest(to))
403 {
404 if(p_getReply(replystr, code, codetype))
405 {
406 if(codetype == 2)
361 rc = true;
362 }
363 }
364 }
365 }
366 }
367 return rc;
368}
369
370
407 rc = true;
408 }
409 }
410 }
411 }
412 }
413 return rc;
414}
415
416
371bool
372FtpClient::Chmod(const string& path, const string& mod)
417void FtpClient::setPassive(bool on)
373{
418{
374 bool rc = false;
375 int code, codeType;
376 string cmd = "SITE CHMOD ", replyString;
377
378 cmd += mod;
379 cmd += " ";
380 cmd += path;
381
382 if (path.length() == 0)
383 cmd += '/';
384printf(B_TRANSLATE("cmd: '%s'\n"), cmd.c_str());
385 if (_SendRequest(cmd) == true) {
386 if (_GetReply(replyString, code, codeType) == true) {
387printf(B_TRANSLATE("reply: %d, %d\n"), code, codeType);
388 if (codeType == 2)
389 rc = true;
390 }
391 }
392 return rc;
419 if(on)
420 p_setState(ftp_passive);
421 else
422 p_clearState(ftp_passive);
393}
394
395
423}
424
425
396void
397FtpClient::SetPassive(bool on)
426
427bool FtpClient::p_testState(unsigned long state)
398{
428{
399 if (on)
400 _SetState(ftp_passive);
401 else
402 _ClearState(ftp_passive);
429 return (bool) ((m_state & state) != 0);
403}
404
405
430}
431
432
406bool
407FtpClient::_TestState(unsigned long state)
433
434void FtpClient::p_setState(unsigned long state)
408{
435{
409 return ((fState & state) != 0);
436 m_state |= state;
410}
411
412
437}
438
439
413void
414FtpClient::_SetState(unsigned long state)
440
441void FtpClient::p_clearState(unsigned long state)
415{
442{
416 fState |= state;
443 m_state &= ~state;
417}
418
419
444}
445
446
420void
421FtpClient::_ClearState(unsigned long state)
422{
423 fState &= ~state;
424}
425
426
447
448
427bool
428FtpClient::_SendRequest(const string& cmd)
449bool FtpClient::p_sendRequest(const string &cmd)
429{
430 bool rc = false;
431 string ccmd = cmd;
450{
451 bool rc = false;
452 string ccmd = cmd;
432
433 if (fControl != 0) {
434 if (cmd.find("PASS") != string::npos)
435 printf(B_TRANSLATE("PASS <suppressed> (real password sent)\n"));
453
454 if(m_control != 0)
455 {
456 if(cmd.find("PASS") != -1)
457 printf("PASS <suppressed> (real password sent)\n");
436 else
437 printf("%s\n", ccmd.c_str());
458 else
459 printf("%s\n", ccmd.c_str());
438
439 ccmd += "\r\n";
460 ccmd += "\r\n";
440 if (fControl->Send(ccmd.c_str(), ccmd.length()) >= 0)
461 if(m_control->Send(ccmd.c_str(), ccmd.length()) >= 0)
462 {
441 rc = true;
463 rc = true;
464 }
442 }
465 }
443
466
444 return rc;
445}
446
447
467 return rc;
468}
469
470
448bool
449FtpClient::_GetReplyLine(string& line)
471
472bool FtpClient::p_getReplyLine(string &line)
450{
451 bool rc = false;
452 int c = 0;
453 bool done = false;
454
455 line = ""; // Thanks to Stephen van Egmond for catching a bug here
473{
474 bool rc = false;
475 int c = 0;
476 bool done = false;
477
478 line = ""; // Thanks to Stephen van Egmond for catching a bug here
456
457 if (fControl != 0) {
479
480 if(m_control != 0)
481 {
458 rc = true;
482 rc = true;
459 while (done == false && fControl->Receive(&c, 1) > 0) {
460 if (c == EOF || c == xEOF || c == '\n') {
483 while(done == false && (m_control->Receive(&c, 1) > 0))
484 {
485 if(c == EOF || c == xEOF || c == '\n')
486 {
461 done = true;
462 } else {
487 done = true;
488 } else {
463 if (c == IAC) {
464 fControl->Receive(&c, 1);
465 switch (c) {
489 if(c == IAC)
490 {
491 m_control->Receive(&c, 1);
492 switch(c)
493 {
466 unsigned char treply[3];
467 case WILL:
468 case WONT:
494 unsigned char treply[3];
495 case WILL:
496 case WONT:
469 fControl->Receive(&c, 1);
497 m_control->Receive(&c, 1);
470 treply[0] = IAC;
471 treply[1] = DONT;
472 treply[2] = c;
498 treply[0] = IAC;
499 treply[1] = DONT;
500 treply[2] = c;
473 fControl->Send(treply, 3);
501 m_control->Send(treply, 3);
474 break;
502 break;
475
503
476 case DO:
477 case DONT:
504 case DO:
505 case DONT:
478 fControl->Receive(&c, 1);
479 fControl->Receive(&c, 1);
506 m_control->Receive(&c, 1);
507 m_control->Receive(&c, 1);
480 treply[0] = IAC;
481 treply[1] = WONT;
482 treply[2] = c;
508 treply[0] = IAC;
509 treply[1] = WONT;
510 treply[2] = c;
483 fControl->Send(treply, 3);
511 m_control->Send(treply, 3);
484 break;
512 break;
485
513
486 case EOF:
487 case xEOF:
488 done = true;
489 break;
514 case EOF:
515 case xEOF:
516 done = true;
517 break;
490
518
491 default:
492 line += c;
493 break;
494 }
495 } else {
519 default:
520 line += c;
521 break;
522 }
523 } else {
524 //
496 // normal char
525 // normal char
497 if (c != '\r')
526 //
527 if(c != '\r')
498 line += c;
499 }
500 }
528 line += c;
529 }
530 }
501 }
531 }
502 }
532 }
503
533
504 return rc;
505}
506
507
534 return rc;
535}
536
537
508bool
509FtpClient::_GetReply(string& outString, int& outCode, int& codeType)
538bool FtpClient::p_getReply(string &outstr, int &outcode, int &codetype)
510{
511 bool rc = false;
539{
540 bool rc = false;
512 string line, tempString;
513
541 string line, tempstr;
542
514 //
515 // comment from the ncftp source:
516 //
543 //
544 // comment from the ncftp source:
545 //
517
546
518 /* RFC 959 states that a reply may span multiple lines. A single
519 * line message would have the 3-digit code <space> then the msg.
520 * A multi-line message would have the code <dash> and the first
521 * line of the msg, then additional lines, until the last line,
522 * which has the code <space> and last line of the msg.
523 *
524 * For example:
525 * 123-First line
526 * Second line
527 * 234 A line beginning with numbers
528 * 123 The last line
529 */
547 /* RFC 959 states that a reply may span multiple lines. A single
548 * line message would have the 3-digit code <space> then the msg.
549 * A multi-line message would have the code <dash> and the first
550 * line of the msg, then additional lines, until the last line,
551 * which has the code <space> and last line of the msg.
552 *
553 * For example:
554 * 123-First line
555 * Second line
556 * 234 A line beginning with numbers
557 * 123 The last line
558 */
530
531 if ((rc = _GetReplyLine(line)) == true) {
532 outString = line;
533 outString += '\n';
534 printf(outString.c_str());
535 tempString = line.substr(0, 3);
536 outCode = atoi(tempString.c_str());
537
538 if (line[3] == '-') {
539 while ((rc = _GetReplyLine(line)) == true) {
540 outString += line;
541 outString += '\n';
542 printf(outString.c_str());
559
560 if((rc = p_getReplyLine(line)) == true)
561 {
562 outstr = line;
563 outstr += '\n';
564 printf(outstr.c_str());
565 tempstr = line.substr(0, 3);
566 outcode = atoi(tempstr.c_str());
567
568 if(line[3] == '-')
569 {
570 while((rc = p_getReplyLine(line)) == true)
571 {
572 outstr += line;
573 outstr += '\n';
574 printf(outstr.c_str());
575 //
543 // we're done with nnn when we get to a "nnn blahblahblah"
576 // we're done with nnn when we get to a "nnn blahblahblah"
544 if ((line.find(tempString) == 0) && line[3] == ' ')
577 //
578 if((line.find(tempstr) == 0) && line[3] == ' ')
545 break;
546 }
547 }
548 }
579 break;
580 }
581 }
582 }
549
550 if (!rc && outCode != 421) {
551 outString += B_TRANSLATE("Remote host has closed the connection.\n");
552 outCode = 421;
583
584 if(rc == false && outcode != 421)
585 {
586 outstr += "Remote host has closed the connection.\n";
587 outcode = 421;
553 }
554
588 }
589
555 if (outCode == 421) {
556 delete fControl;
557 fControl = 0;
558 _ClearState(ftp_connected);
590 if(outcode == 421)
591 {
592 delete m_control;
593 m_control = 0;
594 p_clearState(ftp_connected);
559 }
595 }
560
561 codeType = outCode / 100;
562
596
597 codetype = outcode / 100;
598
563 return rc;
564}
565
566
599 return rc;
600}
601
602
567bool
568FtpClient::_OpenDataConnection()
603
604bool FtpClient::p_openDataConnection()
569{
605{
570 string host, cmd, replyString;
606 string host, cmd, repstr;
571 unsigned short port;
572 BNetAddress addr;
607 unsigned short port;
608 BNetAddress addr;
573 int i, code, codeType;
609 int i, code, codetype;
610 char buf[32];
574 bool rc = false;
575 struct sockaddr_in sa;
611 bool rc = false;
612 struct sockaddr_in sa;
576
577 delete fData;
578 fData = 0;
579
580 fData = new BNetEndpoint;
581
582 if (_TestState(ftp_passive)) {
613
614 delete m_data;
615 m_data = 0;
616
617 m_data = new BNetEndpoint;
618
619 if(p_testState(ftp_passive))
620 {
621 //
583 // Here we send a "pasv" command and connect to the remote server
584 // on the port it sends back to us
622 // Here we send a "pasv" command and connect to the remote server
623 // on the port it sends back to us
624 //
585 cmd = "PASV";
625 cmd = "PASV";
586 if (_SendRequest(cmd)) {
587 if (_GetReply(replyString, code, codeType)) {
588
589 if (codeType == 2) {
626 if(p_sendRequest(cmd))
627 {
628 if(p_getReply(repstr, code, codetype))
629 {
630
631 if(codetype == 2)
632 {
590 // It should give us something like:
591 // "227 Entering Passive Mode (192,168,1,1,10,187)"
592 int paddr[6];
593 unsigned char ucaddr[6];
633 // It should give us something like:
634 // "227 Entering Passive Mode (192,168,1,1,10,187)"
635 int paddr[6];
636 unsigned char ucaddr[6];
594
595 i = replyString.find('(');
637
638 i = repstr.find('(');
596 i++;
597
639 i++;
640
598 replyString = replyString.substr(i, replyString.find(')') - i);
599 if (sscanf(replyString.c_str(), "%d,%d,%d,%d,%d,%d",
600 &paddr[0], &paddr[1], &paddr[2], &paddr[3],
601 &paddr[4], &paddr[5]) != 6) {
602 // cannot do passive. Do a little harmless rercursion here
603 _ClearState(ftp_passive);
604 return _OpenDataConnection();
641 repstr = repstr.substr(i, repstr.find(')') - i);
642 if (sscanf(repstr.c_str(), "%d,%d,%d,%d,%d,%d",
643 &paddr[0], &paddr[1], &paddr[2], &paddr[3],
644 &paddr[4], &paddr[5]) != 6)
645 {
646 //
647 // cannot do passive. Do a little harmless rercursion here
648 //
649 p_clearState(ftp_passive);
650 return p_openDataConnection();
605 }
651 }
606
607 for (i = 0; i < 6; i++)
608 ucaddr[i] = (unsigned char)(paddr[i] & 0xff);
609
652 for(i=0;i<6;i++)
653 {
654 ucaddr[i] = (unsigned char) (paddr[i] & 0xff);
655 }
610 memcpy(&sa.sin_addr, &ucaddr[0], (size_t) 4);
611 memcpy(&sa.sin_port, &ucaddr[4], (size_t) 2);
612 addr.SetTo(sa);
656 memcpy(&sa.sin_addr, &ucaddr[0], (size_t) 4);
657 memcpy(&sa.sin_port, &ucaddr[4], (size_t) 2);
658 addr.SetTo(sa);
613 if (fData->Connect(addr) == B_NO_ERROR)
659 if(m_data->Connect(addr) == B_NO_ERROR)
660 {
614 rc = true;
661 rc = true;
615
662 }
616 }
617 }
618 } else {
663 }
664 }
665 } else {
666 //
619 // cannot do passive. Do a little harmless rercursion here
667 // cannot do passive. Do a little harmless rercursion here
620 _ClearState(ftp_passive);
621 rc = _OpenDataConnection();
668 //
669 p_clearState(ftp_passive);
670 rc = p_openDataConnection();
622 }
623
624 } else {
671 }
672
673 } else {
674 //
625 // Here we bind to a local port and send a PORT command
675 // Here we bind to a local port and send a PORT command
626 if (fData->Bind() == B_NO_ERROR) {
676 //
677 if(m_data->Bind() == B_NO_ERROR)
678 {
627 char buf[255];
679 char buf[255];
628
629 fData->Listen();
630 addr = fData->LocalAddr();
680
681 m_data->Listen();
682 addr = m_data->LocalAddr();
631 addr.GetAddr(buf, &port);
632 host = buf;
683 addr.GetAddr(buf, &port);
684 host = buf;
633
634 i = 0;
635 while (i >= 0) {
685
686 i=0;
687 while(i >= 0)
688 {
636 i = host.find('.', i);
689 i = host.find('.', i);
637 if (i >= 0)
690 if(i >= 0)
638 host[i] = ',';
639 }
691 host[i] = ',';
692 }
640
693
641 sprintf(buf, ",%d,%d", (port & 0xff00) >> 8, port & 0x00ff);
642 cmd = "PORT ";
694 sprintf(buf, ",%d,%d", (port & 0xff00) >> 8, port & 0x00ff);
695 cmd = "PORT ";
643 cmd += host;
644 cmd += buf;
645 _SendRequest(cmd);
646 _GetReply(replyString, code, codeType);
696 cmd += host; cmd += buf;
697 p_sendRequest(cmd);
698 p_getReply(repstr, code, codetype);
699 //
647 // PORT failure is in the 500-range
700 // PORT failure is in the 500-range
648 if (codeType == 2)
701 //
702 if(codetype == 2)
649 rc = true;
650 }
651 }
703 rc = true;
704 }
705 }
652
706
653 return rc;
654}
655
656
707 return rc;
708}
709
710
657bool
658FtpClient::_AcceptDataConnection()
711bool FtpClient::p_acceptDataConnection()
659{
712{
660 BNetEndpoint* endPoint;
713 BNetEndpoint *ep;
661 bool rc = false;
662
714 bool rc = false;
715
663 if (_TestState(ftp_passive) == false) {
664 if (fData != 0) {
665 endPoint = fData->Accept();
666 if (endPoint != 0) {
667 delete fData;
668 fData = endPoint;
716 if(p_testState(ftp_passive) == false)
717 {
718 if(m_data != 0)
719 {
720 ep = m_data->Accept();
721 if(ep != 0)
722 {
723 delete m_data;
724 m_data = ep;
669 rc = true;
725 rc = true;
670 }
726 }
671 }
727 }
672
673 }
674 else
728
729 } else {
675 rc = true;
730 rc = true;
676
677 return rc;
731 }
732
733 return rc;
678}
734}
735
736
737
738
739