⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ftp.cc

📁 将konqueror浏览器移植到ARM9 2410中
💻 CC
📖 第 1 页 / 共 4 页
字号:
  // Get the current working directory  kdDebug(7102) << "Searching for pwd" << endl;  if ( !ftpSendCmd( "pwd", '2' ) )  {    kdDebug(7102) << "Couldn't issue pwd command" << endl;    error( ERR_COULD_NOT_LOGIN, i18n("Could not login to %1.").arg(m_host) ); // or anything better ?    return false;  }  kdDebug(7102) << "2> " << rspbuf << endl;  char *p = strchr( rspbuf+3, '"' ); // Look for first "  if ( p != 0 )  {    char *p2 = strchr( p + 1, '"' ); // Look for second "    if ( p2 != 0 )    {        *p2 = '\0';        m_initialPath = p + 1;        if ( *(p+1) != '/' ) // safety check, for servers that return C:/TEMP/          m_initialPath.prepend('/');        kdDebug(7102) << "Initial path set to: " << m_initialPath << endl;    }  }  return true;}/** * ftpSendCmd - send a command (@p cmd) and read response * * @param expresp the expected first char. '\001' for no check * @param maxretries number of time it should retry. Since it recursively * calls itself if it can't read the answer (this happens especially after * timeouts), we need to limit the recursiveness ;-) * * return true if proper response received, false on error * or if @p expresp doesn't match */bool Ftp::ftpSendCmd( const QCString& cmd, char expresp, int maxretries ){  assert( sControl > 0 );  QCString buf = cmd;  buf += "\r\n";  if ( cmd.left(4).lower() != "pass" ) // don't print out the password    kdDebug(7102) << cmd.data() << endl;  if ( KSocks::self()->write( sControl, buf.data(), buf.length() ) <= 0 )  {    error( ERR_COULD_NOT_WRITE, QString::null );    return false;  }  char rsp = readresp();  if (!rsp || ( rsp == '4' && rspbuf[1] == '2' && rspbuf[2] == '1' ))  {      kdDebug() << "got 421 -> timeout" << endl;    // 421 is "421 No Transfer Timeout (300 seconds): closing control connection"    if ( cmd=="list" && maxretries > 0 ) // Only retry for "list". retr/stor/... need to redo the whole thing    {      // It might mean a timeout occured, let's try logging in again      m_bLoggedOn = false;      kdDebug(7102) << "Couldn't read answer - perhaps timeout - trying logging in again" << endl;      openConnection();      if (!m_bLoggedOn)      {        kdDebug(7102) << "Login failure, aborting" << endl;        return false;      }      kdDebug(7102) << "Logged back in, reissuing command" << endl;      // On success, try the command again      return ftpSendCmd( cmd, expresp, maxretries - 1 );    } else    {      error( ERR_SERVER_TIMEOUT, m_host );      return false;    }  }  return (expresp == 0) || (rsp == expresp);}/* * ftpOpenPASVDataConnection - set up data connection, using PASV mode * * return 1 if successful, 0 otherwise * doesn't set error message, since non-pasv mode will always be tried if * this one fails */bool Ftp::ftpOpenPASVDataConnection(){  int i[6], j;  unsigned char n[6];  int on=1;  struct linger lng = { 1, 120 };  KExtendedSocket ks;  const KSocketAddress *sa = ksControl->peerAddress();  QString host;  // Check that we can do PASV  if (sa != NULL && sa->family() != PF_INET)    return false;		// no PASV for non-PF_INET connections  m_bPasv = true;  /* Let's PASsiVe*/  if (!(ftpSendCmd("PASV",'2')))  {    return false;  }  // The usual answer is '227 Entering Passive Mode. (160,39,200,55,6,245)'  // but anonftpd gives '227 =160,39,200,55,6,245'  char *start = strchr(rspbuf,'(');  if ( !start )    start = strchr(rspbuf,'=');  if ( !start ||       ( sscanf(start, "(%d,%d,%d,%d,%d,%d)",&i[0], &i[1], &i[2], &i[3], &i[4], &i[5]) != 6 &&         sscanf(start, "=%d,%d,%d,%d,%d,%d", &i[0], &i[1], &i[2], &i[3], &i[4], &i[5]) != 6 ) )  {    kdError(7102) << "parsing IP and port numbers failed. String parsed: " << start << endl;    return false;  }  for (j=0; j<6; j++)  {    n[j] = (unsigned char) (i[j] & 0xff);  }  // Make hostname  host.sprintf("%d.%d.%d.%d", i[0], i[1], i[2], i[3]);  // port number is given in network byte order  ks.setAddress(host, ntohs(i[5] << 8 | i[4]));  ks.setSocketFlags(KExtendedSocket::noResolve);  if (ks.connect() < 0)    {      return false;    }  sDatal = ks.fd();  if ( (setsockopt( sDatal,SOL_SOCKET,SO_REUSEADDR,(char*)&on, sizeof(on) ) == -1)       || (sDatal < 0) )  {    return false;  }  if ( setsockopt(sDatal, SOL_SOCKET,SO_KEEPALIVE, (char *) &on, (int) sizeof(on)) < 0 )    kdError(7102) << "Keepalive not allowed" << endl;  if ( setsockopt(sDatal, SOL_SOCKET,SO_LINGER, (char *) &lng,(int) sizeof (lng)) < 0 )    kdError(7102) << "Linger mode was not allowed." << endl;  ks.release();  return true;}/* * ftpOpenEPSVDataConnection - opens a data connection via EPSV */bool Ftp::ftpOpenEPSVDataConnection(){  // for SO_LINGER  int on=1;  struct linger lng = { 1, 120 };  KExtendedSocket ks;  const KSocketAddress *sa = ksControl->peerAddress();  int portnum;  // we are sure sa is a KInetSocketAddress, because we asked for KExtendedSocket::inetSocket  // when we connected  const KInetSocketAddress *sin = static_cast<const KInetSocketAddress*>(sa);  if (m_extControl & epsvUnknown || sa == NULL)    return false;  m_bPasv = true;  if (!(ftpSendCmd("EPSV", '2')))    {      // unknown command?      if (rspbuf[0] == '5')	{	  kdDebug(7102) << "disabling use of EPSV" << endl;	  m_extControl |= epsvUnknown;	}      return false;    }  char *start = strchr(rspbuf,'|');  if ( !start ||       sscanf(rspbuf, "|||%d|", &portnum) != 1)    {      // invalid response?      return false;    }  ks.setSocketFlags(KExtendedSocket::noResolve);  ks.setAddress(sin->nodeName(), portnum);  if (ks.connect() < 0)    {      return false;    }  sDatal = ks.fd();  if ( (setsockopt( sDatal,SOL_SOCKET,SO_REUSEADDR,(char*)&on, sizeof(on) ) == -1)       || (sDatal < 0) )  {    return false;  }  if ( setsockopt(sDatal, SOL_SOCKET,SO_KEEPALIVE, (char *) &on, (int) sizeof(on)) < 0 )    kdError(7102) << "Keepalive not allowed" << endl;  if ( setsockopt(sDatal, SOL_SOCKET,SO_LINGER, (char *) &lng,(int) sizeof (lng)) < 0 )    kdError(7102) << "Linger mode was not allowed." << endl;  ks.release();  return true;}/* * ftpOpenEPRTDataConnection */bool Ftp::ftpOpenEPRTDataConnection(){  KExtendedSocket ks;  // yes, we are sure this is a KInetSocketAddress  const KInetSocketAddress *sin = static_cast<const KInetSocketAddress*>(ksControl->localAddress());  m_bPasv = false;  if (m_extControl & eprtUnknown || sin == NULL)    return false;  ks.setHost(sin->nodeName());  ks.setPort(0);		// setting port to 0 will make us bind to a random, free port  ks.setSocketFlags(KExtendedSocket::noResolve | KExtendedSocket::passiveSocket |		    KExtendedSocket::inetSocket);  if (ks.listen(1) < 0)    {      error(ERR_COULD_NOT_LISTEN, m_host);      return false;    }  sin = static_cast<const KInetSocketAddress*>(ks.localAddress());  if (sin == NULL)    // error ?    return false;  //  QString command = QString::fromLatin1("eprt |%1|%2|%3|").arg(sin->ianaFamily())  //  .arg(sin->nodeName())  //  .arg(sin->port());  QCString command;  command.sprintf("eprt |%d|%s|%d|", sin->ianaFamily(),		  sin->nodeName().latin1(), sin->port());  // FIXME! Encoding for hostnames?  if (!ftpSendCmd(command, '2'))    {      // unknown command?      if (rspbuf[0] == '5')	{	  kdDebug(7102) << "disabling use of EPRT" << endl;	  m_extControl |= eprtUnknown;	}      return false;    }  sDatal = ks.fd();  ks.release();  return true;}/* * ftpOpenDataConnection - set up data connection * * return 1 if successful, 0 otherwise */bool Ftp::ftpOpenDataConnection(){  assert( m_bLoggedOn );  union  {    struct sockaddr sa;    struct sockaddr_in in;  } sin;  struct linger lng = { 0, 0 };  socklen_t l;  char buf[64];  int on = 1;  ////////////// First try passive (EPSV & PASV) modes  if ( config()->readBoolEntry( "DisablePassiveMode", false ) == false )  {    if (ftpOpenEPSVDataConnection())      return true;    if (ftpOpenPASVDataConnection())      return true;    // if we sent EPSV ALL already and it was accepted, then we can't    // use active connections any more    if (m_extControl & epsvAllSent)      return false;    if (ftpOpenEPRTDataConnection())      return true;  }  ////////////// Fallback : PORT mode  m_bPasv = false;  l = sizeof(sin);  if ( getsockname( sControl, &sin.sa, &l ) < 0 )    return false;  if (sin.sa.sa_family != PF_INET)    return false;		// wrong family  sDatal = socket( PF_INET, SOCK_STREAM, IPPROTO_TCP );  if ( sDatal == 0 )  {    error( ERR_COULD_NOT_CREATE_SOCKET, QString::null );    return false;  }  if ( setsockopt( sDatal, SOL_SOCKET, SO_REUSEADDR, (char*)&on, sizeof(on) ) == -1 )  {    ::close( sDatal );    error( ERR_COULD_NOT_CREATE_SOCKET, QString::null );    return false;  }  if ( setsockopt( sDatal, SOL_SOCKET, SO_LINGER, (char*)&lng, sizeof(lng) ) == -1 )  {    ::close( sDatal );    error( ERR_COULD_NOT_CREATE_SOCKET, QString::null );    return false;  }  sin.in.sin_port = 0;  if ( bind( sDatal, &sin.sa, sizeof(sin) ) == -1 )  {    ::close( sDatal );    sDatal = 0;    error( ERR_COULD_NOT_BIND, m_host );    return false;  }  if ( listen( sDatal, 1 ) < 0 )  {    error( ERR_COULD_NOT_LISTEN, m_host );    ::close( sDatal );    sDatal = 0;    return 0;  }  if ( getsockname( sDatal, &sin.sa, &l ) < 0 )    // error ?    return false;  sprintf(buf,"port %d,%d,%d,%d,%d,%d",          (unsigned char)sin.sa.sa_data[2],(unsigned char)sin.sa.sa_data[3],          (unsigned char)sin.sa.sa_data[4],(unsigned char)sin.sa.sa_data[5],          (unsigned char)sin.sa.sa_data[0],(unsigned char)sin.sa.sa_data[1]);  return ftpSendCmd( buf, '2' );}/* * ftpAcceptConnect - wait for incoming connection * Used by @ref ftpOpenCommand * * return -2 on error or timeout * otherwise returns socket descriptor */int Ftp::ftpAcceptConnect(){  struct sockaddr addr;  int sData;  socklen_t l;  fd_set mask;  FD_ZERO(&mask);  FD_SET(sDatal,&mask);  if ( m_bPasv )    return sDatal;  if ( select( sDatal + 1, &mask, NULL, NULL, 0L ) == 0)  {    ::close( sDatal );    return -2;  }  l = sizeof(addr);  if ( ( sData = accept( sDatal, &addr, &l ) ) > 0 )    return sData;  ::close( sDatal );  return -2;}bool Ftp::ftpOpenCommand( const char *_command, const QString & _path, char _mode,                          int errorcode, unsigned long _offset ){  QCString buf = "type ";  buf += _mode;  if ( !ftpSendCmd( buf, '2' ) )  {    error( ERR_COULD_NOT_CONNECT, QString::null );    return false;  }  if ( !ftpOpenDataConnection() )  {    error( ERR_COULD_NOT_CONNECT, QString::null );    return false;  }  if ( _offset > 0 ) {    // send rest command if offset > 0, this applies to retr and stor commands    char buf[100];    sprintf(buf, "rest %ld", _offset);    if ( !ftpSendCmd( buf, '3' ) ) {      if ( rspbuf[0] != '3' ) // other errors were already emitted        {          error( ERR_CANNOT_RESUME, _path ); // should never happen          return false;        }    }  }  QCString tmp = _command;  if ( !_path.isEmpty() ) {    tmp += " ";    tmp += _path.ascii();  }  if ( !ftpSendCmd( tmp, '1' ) ) {    if ( _offset > 0 && strcmp(_command, "retr") == 0 && rspbuf[0] == '4')    {      // Failed to resume      errorcode = ERR_CANNOT_RESUME;    }    // The error here depends on the command    error( errorcode, _path );    return false;  }  // Only now we know for sure that we can resume  if ( _offset > 0 && strcmp(_command, "retr") == 0 )    canResume();  if ( ( sData = ftpAcceptConnect() ) < 0 )  {    error( ERR_COULD_NOT_ACCEPT, QString::null );    return false;  }  return true;}void Ftp::closeSockets(){  if( sData != 0 )  {    shutdown( sData, 2 );    ::close( sData );    sData = 0;  }  if( sDatal != 0 )  {    ::close( sDatal );    sDatal = 0;  }}bool Ftp::ftpCloseCommand(){  kdDebug(7102) << "Ftp::ftpCloseCommand" << endl;  // first close data sockets (if opened), then read response that  // we got for whatever was used in ftpOpenCommand ( should be 226 )  closeSockets();  if ( readresp() != '2' )  {    kdDebug(7102) << "Did not get transfer complete message" << endl;    return false;  }  return true;}void Ftp::mkdir( const KURL & url, int permissions ){  QString path = url.path();  if (!m_bLoggedOn)  {      openConnection();      if (!m_bLoggedOn)      {        kdDebug(7102) << "Login failure, aborting" << endl;        return;      }  }  assert( m_bLoggedOn );  QCString buf = "mkd ";  buf += path.latin1();  if ( ! ftpSendCmd( buf, '2' ) )  {    error( ERR_COULD_NOT_MKDIR, path );    return;  }  if ( permissions != -1 )  {    // chmod the dir we just created, ignoring errors.    (void) ftpChmod( path, permissions );  }  finished();}void Ftp::rename( const KURL& src, const KURL& dst, bool overwrite ){  if (!m_bLoggedOn)  {      openConnection();      if (!m_bLoggedOn)      {        kdDebug(7102) << "Login failure, aborting" << endl;        return;      }  }  // The actual functionality is in ftpRename because put needs it  if ( ftpRename( src.path(), dst.path(), overwrite ) )    finished();  else    error( ERR_CANNOT_RENAME, src.path() );}bool Ftp::ftpRename( const QString & src, const QString & dst, bool /* overwrite */ ){  // TODO honor overwrite  assert( m_bLoggedOn );  QCString cmd;  cmd = "RNFR ";  cmd += src.ascii();  if ( !ftpSendCmd( cmd, '3') )    return false;  cmd = "RNTO ";

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -