inlib  1.2.0
Classes | Public Member Functions | Static Public Member Functions | Protected Member Functions | Static Protected Member Functions
inlib::net::ftp Class Reference
Inheritance diagram for inlib::net::ftp:
Inheritance graph
[legend]
Collaboration diagram for inlib::net::ftp:
Collaboration graph
[legend]

List of all members.

Classes

struct  bind_infos
class  xxx

Public Member Functions

 ftp (std::ostream &a_out, bool a_verbose)
virtual ~ftp ()
bool start (const std::string &a_host, const std::string &a_user, const std::string &a_pwd)
bool fetch_file (const std::string &a_file, const std::string &a_local, unsigned int a_BLOCK=65536, bool a_active=true)
bool fetch_dir (const std::string &a_dir, const std::string &a_local, bool a_active=true)

Static Public Member Functions

static bool parse (const std::string &a_url, std::string &a_host, std::string &a_path)
static const std::string & s_anonymous ()

Protected Member Functions

 ftp (const ftp &a_from)
ftpoperator= (const ftp &)
bool get_answer (std::string &a_answer)
bool send_command (const std::string &a_cmd, std::string &a_answer)
bool host_port_from_answer (std::string &a_answer, std::string &a_host, unsigned short &a_port)

Static Protected Member Functions

static char LF ()
static char CR ()
static bool data_after_bind (const inet_socket::bind_info &a_info, void *a_tag)

Detailed Description

Definition at line 21 of file ftp.


Constructor & Destructor Documentation

inlib::net::ftp::ftp ( std::ostream &  a_out,
bool  a_verbose 
) [inline]

Definition at line 35 of file ftp.

  : inet_socket(a_out,a_verbose)
  {}
virtual inlib::net::ftp::~ftp ( ) [inline, virtual]

Definition at line 38 of file ftp.

{}
inlib::net::ftp::ftp ( const ftp a_from) [inline, protected]

Definition at line 40 of file ftp.

: inet_socket(a_from){}

Member Function Documentation

static char inlib::net::ftp::CR ( ) [inline, static, protected]

Definition at line 407 of file ftp.

{return 13;}
static bool inlib::net::ftp::data_after_bind ( const inet_socket::bind_info a_info,
void *  a_tag 
) [inline, static, protected]

Definition at line 414 of file ftp.

                                                                              {
    bind_infos* tag = (bind_infos*)a_tag;
    tag->m_sin_addr = a_info.m_sin_addr;
    tag->m_sin_port = a_info.m_sin_port;
    return true;
  }
bool inlib::net::ftp::fetch_dir ( const std::string &  a_dir,
const std::string &  a_local,
bool  a_active = true 
) [inline]

Definition at line 249 of file ftp.

                                              {
  
    inet_socket bind(m_out,m_verbose);
    inet_socket data(m_out,m_verbose);

    std::string answer;
  
    if(a_active) {

      std::string this_host;
      if(!inet_host(m_out,this_host)){
        m_out << "inlib::ftp::fetch_dir :" 
              << " cannot get computer name."
              << std::endl;
        return false;
      }

      bind_infos tag;
      bind.set_after_bind_func(data_after_bind,&tag);
      if(!bind.bind(this_host,0,10,1,true)) return false;
    
     {char cmd[256];
#ifdef WIN32
      _snprintf
#else
      ::snprintf
#endif
          (cmd,sizeof(cmd),"PORT %d,%d,%d,%d,%d,%d",
              (int)*((unsigned char *)(&tag.m_sin_addr)+0),
              (int)*((unsigned char *)(&tag.m_sin_addr)+1),
              (int)*((unsigned char *)(&tag.m_sin_addr)+2),
              (int)*((unsigned char *)(&tag.m_sin_addr)+3),
              (int)*((unsigned char *)(&tag.m_sin_port)+0),
              (int)*((unsigned char *)(&tag.m_sin_port)+1));
      if(!send_command(cmd,answer)) return false;
      if(answer.substr(0,3)=="500"){
        m_out << "inlib::ftp::fetch_dir :" 
              << " for cmd " << sout(std::string(cmd))
              << ", received a " << sout(answer)
              << std::endl;
        return false;
      }}

    } else {
    
      std::string cmd = "PASV";
      if(!send_command(cmd,answer)) return false;
      if(answer.substr(0,3)!="227"){
        m_out << "inlib::ftp::fetch_dir :" 
              << " for cmd " << sout(std::string(cmd))
              << ", received a " << sout(answer)
              << std::endl;
        return false;
      }
      //We receive something as :
      //227 Entering Passive Mode (134,158,91,15,80,72)

      //Get the port from the two last number :
     
      std::string host;
      unsigned short svr_port;
      if(!host_port_from_answer(answer,host,svr_port)) {
        m_out << "inlib::ftp::fetch_dir :" 
              << " can't get port from " << sout(answer) 
              << std::endl;
        return false;
      }

      if(m_verbose) {
        m_out << "inlib::ftp::fetch_dir :" 
              << " server host " << host
              << " server port " << sout(svr_port) 
              << std::endl;
      }

      if(!data.connect(host,svr_port,10,1)) return false;

      if(m_verbose) {
        m_out << "inlib::ftp::fetch_dir :" 
              << " connected to server."
              << std::endl;
      }
    }
    
    if(!send_command("TYPE I",answer)) return false;
  
    if(!send_command(std::string("CWD ")+a_dir,answer)) return false;

    if(answer.substr(0,3)=="550"){
      m_out << "inlib::ftp::fetch_dir :" 
            << " failed to change directory " << sout(a_dir) << "."
            << std::endl;
      return false;
    }
  
    if(!send_command("LIST",answer)) return false;
  
    if(answer.substr(0,3)=="425"){
      m_out << "inlib::ftp::fetch_dir :" 
            << " failed with " << sout(answer) << "."
            << std::endl;
      return false;
    }

    // sometime we receive here the answer of TYPE or RETR !
    //if(answer.substr(0,3)!="150"){
    //  m_out << "inlib::ftp::fetch_dir :" 
    //        << " answer is not 150. " << sout(answer) << "."
    //        << std::endl;
    //  return false;
    //}
  
    if(a_active) {
      int data_sock_id = bind.socket();
      if(!data.accept(data_sock_id,true)) {
        m_out << "inlib::ftp::fetch_dir :" 
              << " data.accept() failed." 
              << std::endl;
        return false;
      }
      bind.disconnect();
    }

    if(m_verbose) {
      m_out << "start transfer..." << std::endl;
    }
  
    inlib::uint64 length;
   {char* buffer;
    if(!data.fetch_upto_end(buffer,length)) {
      m_out << "inlib::ftp::fetch_dir :" 
            << " fetch_upto_end failed."
            << std::endl;
      return false;
    }
    if(m_verbose) {
      m_out << "end transfer."
            << " Got " << length << " bytes." 
            << std::endl;
    }
    ::remove(a_local.c_str());
    if(!inlib::file::write_bytes(a_local,buffer,(size_t)length)) {
      m_out << "inlib::ftp::fetch_dir :" 
            << " can't write local file " << inlib::sout(a_local) 
            << std::endl;
      delete [] buffer;
      return false;
    }
    delete [] buffer;}
  
    if(length) if(!get_answer(answer)) return false;

    return true;
  }    
bool inlib::net::ftp::fetch_file ( const std::string &  a_file,
const std::string &  a_local,
unsigned int  a_BLOCK = 65536,
bool  a_active = true 
) [inline]

Definition at line 93 of file ftp.

                                               {

    FILE* file = ::fopen(a_local.c_str(),"wb");
    if(!file) return false;

    inet_socket bind(m_out,m_verbose);
    xxx data(m_out,m_verbose,*this);

    std::string answer;

    if(a_active) {

      std::string this_host;
      if(!inet_host(m_out,this_host)){
        m_out << "inlib::ftp::fetch_file :" 
              << " cannot get computer name."
              << std::endl;
        ::fclose(file);
        return false;
      }

      bind_infos tag;
      bind.set_after_bind_func(data_after_bind,&tag);
      if(!bind.bind(this_host,0,10,1,true)) {::fclose(file);return false;}

    //m_out << "debug : inlib::ftp::fetch_file : sin_port " << tag.m_sin_port 
    //      << std::endl; 

     {char cmd[256];
#ifdef WIN32
      _snprintf
#else
      ::snprintf
#endif
          (cmd,sizeof(cmd),"PORT %d,%d,%d,%d,%d,%d",
              (int)*((unsigned char *)(&tag.m_sin_addr)+0),
              (int)*((unsigned char *)(&tag.m_sin_addr)+1),
              (int)*((unsigned char *)(&tag.m_sin_addr)+2),
              (int)*((unsigned char *)(&tag.m_sin_addr)+3),
              (int)*((unsigned char *)(&tag.m_sin_port)+0),
              (int)*((unsigned char *)(&tag.m_sin_port)+1));
      if(!send_command(cmd,answer)) {::fclose(file);return false;}
      if(answer.substr(0,3)=="500"){
        m_out << "inlib::ftp::fetch_file :" 
              << " for cmd " << sout(std::string(cmd))
              << ", received a " << sout(answer)
              << std::endl;
        ::fclose(file);
        return false;
      }}
  
    } else {

      std::string cmd = "PASV";
      if(!send_command(cmd,answer)) return false;
      if(answer.substr(0,3)!="227"){
        m_out << "inlib::ftp::fetch_file :" 
              << " for cmd " << sout(std::string(cmd))
              << ", received a " << sout(answer)
              << std::endl;
        return false;
      }
      //We receive something as :
      //227 Entering Passive Mode (134,158,91,15,80,72)

      //Get the port from the two last number :
     
      std::string host;
      unsigned short svr_port;
      if(!host_port_from_answer(answer,host,svr_port)) {
        m_out << "inlib::ftp::fetch_file :" 
              << " can't get port from " << sout(answer) 
              << std::endl;
        return false;
      }

      if(m_verbose) {
        m_out << "inlib::ftp::fetch_file :" 
              << " server host " << host
              << " server port " << sout(svr_port) 
              << std::endl;
      }

      if(!data.connect(host,svr_port,10,1)) return false;

      if(m_verbose) {
        m_out << "inlib::ftp::fetch_file :" 
              << " connected to server."
              << std::endl;
      }

    } 

    if(!send_command("TYPE I",answer)) {::fclose(file);return false;}
  
    if(!send_command(std::string("RETR ")+a_file,answer)) {
      ::fclose(file);
      return false;
    }

    if(answer.substr(0,3)=="550"){
      m_out << "inlib::ftp::fetch_file :" 
            << " failed to open file " << sout(a_file) << "."
            << std::endl;
      ::fclose(file);
      return false;
    }
  
    // sometime we receive here the answer of TYPE or RETR !
    //if(answer.substr(0,3)!="150"){
    //  m_out << "inlib::ftp::fetch_file :" 
    //        << " answer is not 150. " << sout(answer) << "."
    //        << std::endl;
    //  ::fclose(file);
    //  return false;
    //}
  
    if(a_active) {
      int data_sock_id = bind.socket();
      if(!data.accept(data_sock_id,true)) {
        m_out << "inlib::ftp::fetch_dir :" 
              << " data.accept() failed." 
              << std::endl;
        return false;
      }
      bind.disconnect();
    }

    if(m_verbose) {
      m_out << "start transfer..." << std::endl;
    }
  
    inlib::uint64 length;
   {if(!data.fetch_upto_end(file,length,a_BLOCK)) {
      m_out << "inlib::ftp::fetch_file :" 
            << " fetch_upto_end failed." 
            << std::endl;
      ::fclose(file);
      return false;
    }
    if(m_verbose) {
      m_out << "end transfer."
            << " Got " << length << " bytes." 
            << std::endl;
    }}
  
    if(length) if(!get_answer(answer)) {::fclose(file);return false;}

    ::fclose(file);

    return true;
  }
bool inlib::net::ftp::get_answer ( std::string &  a_answer) [inline, protected]

Definition at line 421 of file ftp.

                                       {
    char* buffer;
    inlib::uint64 length;
    if(!fetch_upto_char(CR(),buffer,length)) {
      m_out << "fetch_upto_char failed." << std::endl; 
      a_answer.clear();
      return false;
    }
    //m_out << "length : " << length << std::endl;
    *(buffer+length-1) = 0;
    a_answer = buffer;
    delete [] buffer;
    if(m_verbose) {
      m_out << "get_answer : " << sout(a_answer) << std::endl;
    }
    return true;
  }
bool inlib::net::ftp::host_port_from_answer ( std::string &  a_answer,
std::string &  a_host,
unsigned short &  a_port 
) [inline, protected]

Definition at line 462 of file ftp.

                                                                         {
    //for exa from :
    //  227 Entering Passive Mode (134,158,91,15,80,72)
    //get the port from last two ints.

    a_host.clear();
    a_port = 0;
    std::string::size_type lb = a_answer.find('(');
    std::string::size_type rb = a_answer.rfind(')');
    if((lb==std::string::npos) || (rb==std::string::npos) ) return false;
    std::string s = a_answer.substr(lb+1,rb-lb-1);

    std::vector<std::string> args;
    inlib::words(s,",",true,args);
    if(args.size()!=6) return false;

    unsigned short c5; //first byte
    if(!inlib::to<unsigned short>(args[4],c5)) return false;
    unsigned short c6; //second byte.
    if(!inlib::to<unsigned short>(args[5],c6)) return false;

    a_host = args[0];
    a_host += ".";
    a_host += args[1];
    a_host += ".";
    a_host += args[2];
    a_host += ".";
    a_host += args[3];

    a_port = c5*256+c6;

    return true;
  }
static char inlib::net::ftp::LF ( ) [inline, static, protected]

Definition at line 406 of file ftp.

{return 10;}
ftp& inlib::net::ftp::operator= ( const ftp ) [inline, protected]

Definition at line 41 of file ftp.

{return *this;}
static bool inlib::net::ftp::parse ( const std::string &  a_url,
std::string &  a_host,
std::string &  a_path 
) [inline, static]

Definition at line 23 of file ftp.

                                                                                {
    if(a_url.substr(0,6)!="ftp://") return false;
    //012345
    //   ^
    std::string s = a_url.substr(6,a_url.size()-6);
    std::string::size_type pos = s.find('/');
    if(pos==std::string::npos) return false;
    a_host = s.substr(0,pos);
    a_path = s.substr(pos,s.size()-pos);
    return true;
  }
static const std::string& inlib::net::ftp::s_anonymous ( ) [inline, static]

Definition at line 43 of file ftp.

                                        {
    static const std::string s_v("anonymous");
    return s_v;
  }
bool inlib::net::ftp::send_command ( const std::string &  a_cmd,
std::string &  a_answer 
) [inline, protected]

Definition at line 439 of file ftp.

                                                                {
    if(a_cmd.empty()) {
      a_answer.clear();
      return false;
    }
    if(m_verbose) {
      m_out << "send_command : " << sout(a_cmd) << std::endl;
    }
    //NOTE : use C str. std::string don't like CR,LF.
    char* cmd = inlib::str_new();    
    inlib::str_cat(cmd,a_cmd.c_str());
    inlib::str_cat(cmd,CR());
    inlib::str_cat(cmd,LF());
    if(!send_buffer(cmd,::strlen(cmd))) {
      m_out << "send_buffer failed." << std::endl;
      inlib::str_del(cmd);
      a_answer.clear();
      return false;
    }
    inlib::str_del(cmd);
    return get_answer(a_answer);
  }
bool inlib::net::ftp::start ( const std::string &  a_host,
const std::string &  a_user,
const std::string &  a_pwd 
) [inline]

Definition at line 48 of file ftp.

                                            { //empty string if anonymous
    int port = 21;
    if(!connect(a_host,port,10,1)) return false;

    //wait greeting. 220 (vsFTPd 2.0.1)
    std::string answer;
    if(!get_answer(answer)) return false;

   {std::string cmd = "USER "+a_user;
    if(!send_command(cmd,answer)) return false;}

   {std::string cmd = "PASS "+a_pwd;
    if(!send_command(cmd,answer)) return false;}

    return true;
  }

The documentation for this class was generated from the following file:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines