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

📄 ftp.cc

📁 将konqueror浏览器移植到ARM9 2410中
💻 CC
📖 第 1 页 / 共 4 页
字号:
/*  This file is part of the KDE libraries    Copyright (C) 2000 David Faure <faure@kde.org>    This library is free software; you can redistribute it and/or    modify it under the terms of the GNU Library General Public    License as published by the Free Software Foundation; either    version 2 of the License, or (at your option) any later version.    This library is distributed in the hope that it will be useful,    but WITHOUT ANY WARRANTY; without even the implied warranty of    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU    Library General Public License for more details.    You should have received a copy of the GNU Library General Public License    along with this library; see the file COPYING.LIB.  If not, write to    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,    Boston, MA 02111-1307, USA.*/// $Id: ftp.cc,v 1.147.2.2 2002/12/11 22:03:47 waba Exp $#include "ftp.h"#include <sys/types.h>#include <sys/stat.h>#include <sys/socket.h>#ifdef HAVE_SYS_TIME_H#include <sys/time.h>#endif#ifdef HAVE_SYS_SELECT_H#include <sys/select.h>#endif#include <netinet/in.h>#include <assert.h>#include <ctype.h>#include <errno.h>#include <netdb.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#if TIME_WITH_SYS_TIME#include <time.h>#endif#include <qdir.h>#include <kdebug.h>#include <klocale.h>#include <kinstance.h>#include <kmimemagic.h>#include <kmimetype.h>#include <kextsock.h>#include <ksockaddr.h>#include <ksocks.h>#include <kio/ioslave_defaults.h>#include <kio/slaveconfig.h>#define FTP_LOGIN QString::fromLatin1("anonymous")#define FTP_PASSWD QString::fromLatin1("kde-user@kde.org")using namespace KIO;extern "C" { int ftp_kdemain(int argc, char **argv); }int ftp_kdemain( int argc, char **argv ){  KLocale::setMainCatalogue("kdelibs");  KInstance instance( "kio_ftp" );  ( void ) KGlobal::locale();  kdDebug(7102) << "Starting " << getpid() << endl;  if (argc != 4)  {     fprintf(stderr, "Usage: kio_ftp protocol domain-socket1 domain-socket2\n");     exit(-1);  }  Ftp slave(argv[2], argv[3]);  slave.dispatchLoop();  kdDebug(7102) << "Done" << endl;  return 0;}Ftp::Ftp( const QCString &pool, const QCString &app )    : SlaveBase( "ftp", pool, app ){  dirfile = 0L;  m_extControl = sData = sDatal = 0;  sControl = -1;  ksControl = NULL;  m_bLoggedOn = false;  m_bFtpStarted = false;  setMultipleAuthCaching( true );  kdDebug(7102) << "Ftp::Ftp()" << endl;}Ftp::~Ftp(){  closeConnection();}/* memccpy appeared first in BSD4.4 */void *mymemccpy(void *dest, const void *src, int c, size_t n){    char *d = (char*)dest;    const char *s = (const char*)src;    while (n-- > 0)    if ((*d++ = *s++) == c)      return d;  return NULL;}/* * read a line of text * * return -1 on error, bytecount otherwise */int Ftp::ftpReadline(char *buf,int max,netbuf *ctl){  int x,retval = 0;  char *end;  int eof = 0;  if ( max == 0 )    return 0;  do  {    if (ctl->cavail > 0)    {      x = (max >= ctl->cavail) ? ctl->cavail : max-1;      end = (char*)mymemccpy(buf,ctl->cget,'\n',x);      if (end != NULL)        x = end - buf;      retval += x;      buf += x;      *buf = '\0';      max -= x;      ctl->cget += x;      ctl->cavail -= x;      if (end != NULL)        break;    }    if (max == 1)    {      *buf = '\0';      break;    }    if (ctl->cput == ctl->cget)    {      ctl->cput = ctl->cget = ctl->buf;      ctl->cavail = 0;      ctl->cleft = FTP_BUFSIZ;    }    if (eof)    {      if (retval == 0)        retval = -1;      break;    }    if ((x = KSocks::self()->read(ctl->handle,ctl->cput,ctl->cleft)) == -1)    {      kdError(7102) << "read failed: " << strerror(errno) << endl;      retval = -1;      break;    }    if (x == 0)      eof = 1;    ctl->cleft -= x;    ctl->cavail += x;    ctl->cput += x;  }  while (1);  return retval;}/** * read a response from the server, into rspbuf * @return first char of response (rspbuf[0]), '\0' if we couldn't read the response */char Ftp::readresp(){  char match[5];  if ( ftpReadline( rspbuf, 256, nControl ) == -1 )  {    // This can happen after the server closed the connection (after a timeout)    kdWarning(7102) << "Could not read" << endl;    //error( ERR_COULD_NOT_READ, QString::null );    return '\0';  }  kdDebug(7102) << "resp> " << rspbuf << endl;  if ( rspbuf[3] == '-' )  {    strncpy( match, rspbuf, 3 );    match[3] = ' ';    match[4] = '\0';    do {      if ( ftpReadline( rspbuf, 256, nControl ) == -1 ) {          kdWarning(7102) << "Could not read" << endl;          //error( ERR_COULD_NOT_READ, QString::null );          return '\0';      }      kdDebug(7102) << rspbuf << endl;    }    while ( strncmp( rspbuf, match, 4 ) );  }  return rspbuf[0];}void Ftp::closeConnection(){  kdDebug(7102) << "Ftp::closeConnection() m_bLoggedOn=" << m_bLoggedOn << " m_bFtpStarted=" << m_bFtpStarted << endl;  if ( m_bLoggedOn || m_bFtpStarted )  {    ASSERT( m_bFtpStarted ); // can't see how it could be false is loggedon is true    if( sControl != 0 )    {      kdDebug(7102) << "Ftp::closeConnection() sending quit" << endl;      if ( !ftpSendCmd( "quit", '2' ) )        kdWarning(7102) << "Ftp::closeConnection() 'quit' failed with err=" << rspbuf[0] << rspbuf[1] << rspbuf[2] << endl;      free( nControl );      if (ksControl != NULL)	delete ksControl;      //      ::close( sControl );      sControl = 0;    }  }  m_extControl = 0;  m_bLoggedOn = false;  m_bFtpStarted = false;  //ready()}void Ftp::setHost( const QString& _host, int _port, const QString& _user,                   const QString& _pass ){  kdDebug(7102) << "Ftp::setHost " << _host << endl;  QString user = _user;  QString pass = _pass;  if ( !_user.isEmpty() )  {      user = _user;      pass = _pass.isEmpty() ? QString::null:_pass;  }  else  {      user = FTP_LOGIN;      pass = FTP_PASSWD;  }  m_proxyURL = metaData("UseProxy");  kdDebug(7102) << "Proxy URL: " << m_proxyURL.url() << endl;  m_bUseProxy = ( m_proxyURL.isValid() &&                  m_proxyURL.protocol() == QString::fromLatin1("ftp") );  if ( m_host != _host || m_port != _port ||       m_user != user || m_pass != pass )      closeConnection( );  m_host = _host;  m_port = _port;  m_user = user;  m_pass = pass;}void Ftp::openConnection(){  kdDebug(7102) << "openConnection " << m_host << ":" << m_port << " " << m_user << " [password hidden]" << endl;  infoMessage( i18n("Opening connection to host <b>%1</b>").arg(m_host) );  if ( m_host.isEmpty() )  {    error( ERR_UNKNOWN_HOST, QString::null );    return;  }  assert( !m_bLoggedOn );  m_initialPath = QString::null;  QString host = m_bUseProxy ? m_proxyURL.host() : m_host;  unsigned short int port = m_bUseProxy ? m_proxyURL.port() : m_port;  if (!connect( host, port ))    return; // error emitted by connect  m_bFtpStarted = true;  infoMessage( i18n("Connected to host <b>%1</b>").arg(m_host) );  kdDebug(7102) << "Connected ...." << endl;  m_bLoggedOn = ftpLogin();  if ( !m_bLoggedOn )    return; // error emitted by ftpLogin  connected();}/** * Called by @ref openConnection. It opens the control connection to the ftp server. * * @return true on success. */bool Ftp::connect( const QString &host, unsigned short int port ){  if ( port == 0 ) {      struct servent *pse;      if ( ( pse = getservbyname( "ftp", "tcp" ) ) == NULL )          port = 21;      else          port = ntohs(pse->s_port);  }  int on = 1;  // require an Internet Socket  ksControl = new KExtendedSocket(host, port, KExtendedSocket::inetSocket);  if (ksControl == NULL)    {      error( ERR_OUT_OF_MEMORY, QString::null );      return false;    }  if (ksControl->connect() < 0)    {      if (ksControl->status() == IO_LookupError)	error(ERR_UNKNOWN_HOST, host);      else	error(ERR_COULD_NOT_CONNECT, host);      delete ksControl;      ksControl = NULL;      return false;    }  sControl = ksControl->fd();  if ( setsockopt( sControl, SOL_SOCKET, SO_REUSEADDR, (char*)&on, sizeof(on) ) == -1 )  {    //    ::close( sControl );    delete ksControl;    ksControl = NULL;    error( ERR_COULD_NOT_CREATE_SOCKET, host );    return false;  }  nControl = (netbuf*)calloc(1,sizeof(netbuf));  if (nControl == NULL)  {    //    ::close( sControl );    delete ksControl;    ksControl = NULL;    error( ERR_OUT_OF_MEMORY, QString::null );    return false;  }  nControl->handle = sControl;  if ( readresp() != '2' )  {    //    ::close( sControl );    delete ksControl;    ksControl = NULL;    free( nControl );    error( ERR_COULD_NOT_CONNECT, host );    return false;  }  return true;}/** * Called by @ref openConnection. It logs us in. * @ref m_initialPath is set to the current working directory * if logging on was successfull. * * @return true on success. */bool Ftp::ftpLogin(){  infoMessage( i18n("Sending login information") );  assert( !m_bLoggedOn );  QString user = m_user;  QString pass = m_pass;  if ( config()->readBoolEntry("EnableAutoLogin") )  {    QString au = config()->readEntry("autoLoginUser");    if ( !au.isEmpty() )    {        user = au;        pass = config()->readEntry("autoLoginPass");    }  }  kdDebug(7102) << "ftpLogin " << user << endl;  if ( !user.isEmpty() )  {    AuthInfo info;    QCString tempbuf;    int failedAuth = 0;    // Construct the URL to be used as key for caching.    info.url.setProtocol( QString::fromLatin1("ftp") );    info.url.setHost( m_host );    info.url.setPort( m_port );    while ( ++failedAuth )    {      // Ask user if we should retry after login failure.      if( failedAuth > 2 )      {        info.prompt = i18n("Login Failed! Do you want to retry ?");        if( messageBox(QuestionYesNo, info.prompt, i18n("Authorization")) != 3 )        {          kdDebug(7102) << "Login aborted by user!" << endl;          error( ERR_USER_CANCELED, QString::null);          return false;        }      }      // Check the cache and/or prompt user for password if 1st      // login attempt failed OR the user supplied a login name,      // but no password.      if ( failedAuth > 1 || (!user.isEmpty() && pass.isEmpty()) )      {        if ( user != FTP_LOGIN && pass != FTP_PASSWD )            info.username = m_user;        if ( failedAuth < 3 && checkCachedAuthentication( info ) )        {          user = info.username;          pass = info.password;        }        else        {          info.prompt = i18n("You need to supply a username and a password "                             "to access this site.");          info.commentLabel = i18n( "Site:" );          info.comment = i18n("<b>%1</b>").arg( m_host );          bool disablePassDlg = config()->readBoolEntry( "DisablePassDlg", false );          if ( disablePassDlg || !openPassDlg( info ) )          {            error( ERR_USER_CANCELED, m_host );            return false;          }          else          {            user = info.username;            pass = info.password;          }        }      }      tempbuf = "user ";      tempbuf += user.latin1();      if ( m_bUseProxy )      {        tempbuf += '@';        tempbuf += m_host.latin1();        if ( m_port > 0 && m_port != DEFAULT_FTP_PORT )        {          tempbuf += ':';          tempbuf += QString::number(m_port).latin1();        }      }      kdDebug(7102) << "Sending Login name: " << user << endl;      bool loggedIn = (ftpSendCmd( tempbuf, '2' ) &&                       !strncmp( rspbuf, "230", 3));      bool needPass = !strncmp( rspbuf, "331", 3);      // Prompt user for login info if we do not      // get back a "230" or "331".      if ( !loggedIn && !needPass )      {        kdDebug(7102) << "1> " << rspbuf << endl;        continue;  // Well we failed, prompt the user please!!      }      if( needPass )      {        tempbuf = "pass ";        tempbuf += pass.latin1();        kdDebug(7102) << "Sending Login password: " << "[protected]" << endl;        loggedIn = (ftpSendCmd( tempbuf, '2' ) && !strncmp(rspbuf, "230", 3));      }      if ( loggedIn )      {        // Do not cache the default login!!        if( user != FTP_LOGIN && pass != FTP_PASSWD )          cacheAuthentication( info );        failedAuth = -1;      }    }  }  kdDebug(7102) << "Login OK" << endl;  infoMessage( i18n("Login OK") );  // Okay, we're logged in. If this is IIS 4, switch dir listing style to Unix:  // Thanks to jk@soegaard.net (Jens Kristian S鴊aard) for this hint  if( ftpSendCmd( "syst", '2' ) )  {    if( !strncmp( rspbuf, "215 Windows_NT version", 22 ) ) // should do for any version    {      (void)ftpSendCmd( "site dirstyle", '2' );      // Check if it was already in Unix style      // Patch from Keith Refson <Keith.Refson@earth.ox.ac.uk>      if( !strncmp( rspbuf, "200 MSDOS-like directory output is on", 37 ))         //It was in Unix style already!         (void)ftpSendCmd( "site dirstyle", '2' );    }  }  else    kdWarning(7102) << "syst failed" << endl;  QString macro = metaData( "autoLoginMacro" );  if ( !macro.isEmpty() && config()->readBoolEntry("EnableAutoLoginMacro") )  {      QStringList list = QStringList::split('\n', macro);      if ( !list.isEmpty() )      {          QStringList::Iterator it = list.begin();          for( ; it != list.end() ; ++it )          {              if ( (*it).find("init") == 0 )              {                  list = QStringList::split( '\\', macro);                  it = list.begin();                  ++it;  // ignore the macro name                  for( ; it != list.end() ; ++it )                  {                      // TODO: Add support for arbitrary commands                      // besides simply changing directory!!                      if ( (*it).startsWith( "cwd" ) )                          ftpSendCmd( (*it).latin1(), '2' );                  }                  break;              }          }      }  }

⌨️ 快捷键说明

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