root/_FtpPanel/FtpClient.cpp

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. mLooper
  2. cd
  3. ls
  4. pwd
  5. connect
  6. putFile
  7. getFile
  8. moveFile
  9. makeDir
  10. setPassive
  11. p_testState
  12. p_setState
  13. p_clearState
  14. p_sendRequest
  15. p_getReplyLine
  16. p_getReply
  17. p_openDataConnection
  18. p_acceptDataConnection

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

/* [previous][next][first][last][top][bottom][index][help] */