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

📄 ftpclient.cpp

📁 实现了wince 客户端上传下载查看文件及目录的功能接口d
💻 CPP
📖 第 1 页 / 共 5 页
字号:
}

/// Analyse the repy code of a ftp-server-response.
/// @param[in] Reply Reply of a ftp server.
/// @retval FTP_OK    All runs perfect.
/// @retval FTP_ERROR Something went wrong. An other response was expected.
/// @retval NOT_OK    The command was not accepted.
int CFTPClient::SimpleErrorCheck(const CReply& Reply) const
{
   if( Reply.Code().IsNegativeReply() )
      return FTP_NOTOK;
   else if( Reply.Code().IsPositiveCompletionReply() )
      return FTP_OK;

   ASSERT( Reply.Code().IsPositiveReply() );

   return FTP_ERROR;
}

/// Logs on to an ftp-server.
/// @param[in] logonInfo Structure with logon information.
bool CFTPClient::Login(const CLogonInfo& logonInfo)
{
   m_LastLogonInfo = logonInfo;

   enum {LO=-2,      ///< Logged On
         ER=-1,      ///< Error
         NUMLOGIN=9, ///< currently supports 9 different login sequences
    };

   int iLogonSeq[NUMLOGIN][18] = {
      // this array stores all of the logon sequences for the various firewalls 
      // in blocks of 3 nums.
      // 1st num is command to send, 
      // 2nd num is next point in logon sequence array if 200 series response  
      //         is rec'd from server as the result of the command,
      // 3rd num is next point in logon sequence if 300 series rec'd
      { 0,LO,3,    1,LO, 6,   2,LO,ER                                  }, // no firewall
      { 3, 6,3,    4, 6,ER,   5,ER, 9,   0,LO,12,   1,LO,15,   2,LO,ER }, // SITE hostname
      { 3, 6,3,    4, 6,ER,   6,LO, 9,   1,LO,12,   2,LO,ER            }, // USER after logon
      { 7, 3,3,    0,LO, 6,   1,LO, 9,   2,LO,ER                       }, // proxy OPEN
      { 3, 6,3,    4, 6,ER,   0,LO, 9,   1,LO,12,   2,LO,ER            }, // Transparent
      { 6,LO,3,    1,LO, 6,   2,LO,ER                                  }, // USER with no logon
      { 8, 6,3,    4, 6,ER,   0,LO, 9,   1,LO,12,   2,LO,ER            }, // USER fireID@remotehost
      { 9,ER,3,    1,LO, 6,   2,LO,ER                                  }, // USER remoteID@remotehost fireID
      {10,LO,3,   11,LO, 6,   2,LO,ER                                  }  // USER remoteID@fireID@remotehost
   };
   
   // are we connecting directly to the host (logon type 0) or via a firewall? (logon type>0)
   tstring   strTemp;
   USHORT    ushPort=0;

   if( logonInfo.FwType() == CFirewallType::None())
   {
      strTemp = logonInfo.Hostname();
      ushPort = logonInfo.Hostport();
   }
   else
   {
      strTemp = logonInfo.FwHost();
      ushPort = logonInfo.FwPort();
   }
   
   tstring strHostnamePort(logonInfo.Hostname());
   if( logonInfo.Hostport()!=DEFAULT_FTP_PORT )
      strHostnamePort = CMakeString() << logonInfo.Hostname() << _T(":") << logonInfo.Hostport(); // add port to hostname (only if port is not 21)

   if( IsConnected() )
      Logout();

   if( !OpenControlChannel(strTemp, ushPort) )
      return false;

   // get initial connect msg off server
   CReply Reply;
   if( !GetResponse(Reply) || !Reply.Code().IsPositiveCompletionReply() )
      return false;
   
   int iLogonPoint=0;

   // go through appropriate logon procedure
#pragma warning(disable:4127)
   while( true )
#pragma warning(default:4127)
   {
      switch(iLogonSeq[logonInfo.FwType().AsEnum()][iLogonPoint])
      {
      case 0:
         strTemp=_T("USER ") + logonInfo.Username();
         break;
      case 1:
         strTemp=_T("PASS ") + logonInfo.Password();
         break;
      case 2:
         strTemp=_T("ACCT ") + logonInfo.Account();
         break;
      case 3:
         strTemp=_T("USER ") + logonInfo.FwUsername();
         break;
      case 4:
         strTemp=_T("PASS ") + logonInfo.FwPassword();
         break;
      case 5:
         strTemp=_T("SITE ") + strHostnamePort;
         break;
      case 6:
         strTemp=_T("USER ") + logonInfo.Username() + _T("@") + strHostnamePort;
         break;
      case 7:
         strTemp=_T("OPEN ") + strHostnamePort;
         break;
      case 8:
         strTemp=_T("USER ") + logonInfo.FwUsername() + _T("@") + strHostnamePort;
         break;
      case 9:
         strTemp=_T("USER ") + logonInfo.Username() + _T("@") + strHostnamePort + _T(" ") + logonInfo.FwUsername();
         break;
      case 10:
         strTemp=_T("USER ") + logonInfo.Username() + _T("@") + logonInfo.FwUsername() + _T("@") + strHostnamePort;
         break;
      case 11:
         strTemp=_T("PASS ") + logonInfo.Password() + _T("@") + logonInfo.FwPassword();
         break;
      }
      
      // send command, get response
      CReply Reply;
      if( !SendCommand(strTemp, Reply) )
         return false;

      if( !Reply.Code().IsPositiveCompletionReply() && !Reply.Code().IsPositiveIntermediateReply() )
         return false;

      const unsigned int uiFirstDigitOfReplyCode = CCnv::TStringToLong(Reply.Code().Value())/100;
      iLogonPoint=iLogonSeq[logonInfo.FwType().AsEnum()][iLogonPoint + uiFirstDigitOfReplyCode-1]; //get next command from array
      switch(iLogonPoint)
      {
      case ER: // ER means somewhat has gone wrong
         {
            ReportError(_T("Logon failed."), CCnv::ConvertToTString(__FILE__), __LINE__);
         }
         return false;
      case LO: // LO means we're fully logged on
         if( ChangeWorkingDirectory(_T("/"))!=FTP_OK )
            return false;
         return true;
      }
   }
   return false;
}

/// Rename a file on the ftp server.
/// @param[in] strOldName Name of the file to rename.
/// @param[in] strNewName The new name for the file.
/// @return see return values of CFTPClient::SimpleErrorCheck
int CFTPClient::Rename(const tstring& strOldName, const tstring& strNewName) const
{
   CReply Reply;
   if( !SendCommand(_T("RNFR ")+strOldName, Reply) )
      return FTP_ERROR;

   if( Reply.Code().IsNegativeReply() )
      return FTP_NOTOK;
   else if( !Reply.Code().IsPositiveIntermediateReply() )
   {
      ASSERT( Reply.Code().IsPositiveCompletionReply() || Reply.Code().IsPositivePreliminaryReply() );
      return FTP_ERROR;
   }

   if( !SendCommand(_T("RNTO ")+strNewName, Reply) )
      return FTP_ERROR;

   return SimpleErrorCheck(Reply);
}
/// Gets the directory listing of the ftp-server. Sends the LIST command to
/// the ftp-server.
/// @param[in] strPath Starting path for the list command.
/// @param[out] vstrFileList Returns a simple list of the files and folders of the specified directory.
/// @param[in] fPasv see documentation of CFTPClient::Passive
bool CFTPClient::List(const tstring& strPath, TStringVector& vstrFileList, bool fPasv) const
{
   COutputStream outputStream(mc_strEolCharacterSequence);
   //if( !ExecuteDatachannelCommand(CDatachannelCmd::LIST(), strPath, CRepresentation(CType::ASCII()), fPasv, 0, &outputStream) )
   if( !ExecuteDatachannelCommand(CDatachannelCmd::LIST(), strPath, CRepresentation(CType::ASCII()), true, 0, &outputStream) )
      return false;

   vstrFileList.clear();
   tstring strLine;
   outputStream.SetStartPosition();
   while( outputStream.GetNextLine(strLine) )
      vstrFileList.push_back(strPath + strLine.c_str());

   return true;
}

/// Gets the directory listing of the ftp-server. Sends the NLST command to
/// the ftp-server.
/// @param[in] strPath Starting path for the list command.
/// @param[out] vstrFileList Returns a simple list of the files and folders of the specified the directory.
/// @param[in] fPasv see documentation of CFTPClient::Passive
bool CFTPClient::NameList(const tstring& strPath, TStringVector& vstrFileList, bool fPasv) const
{
   COutputStream outputStream(mc_strEolCharacterSequence);
   if( !ExecuteDatachannelCommand(CDatachannelCmd::NLST(), strPath, CRepresentation(CType::ASCII()), fPasv, 0, &outputStream) )
      return false;

   vstrFileList.clear();
   tstring strLine;
   outputStream.SetStartPosition();
   while( outputStream.GetNextLine(strLine) )
      vstrFileList.push_back(strPath + strLine.c_str());

   return true;
}

/// Gets the directory listing of the ftp-server. Sends the LIST command to
/// the ftp-server.
/// @param[in] strPath Starting path for the list command.
/// @param[out] vFileList Returns a detailed list of the files and folders of the specified directory.
///                       vFileList contains CFTPFileStatus-Objects. These Objects provide a lot of
///                       information about the file/folder.
/// @param[in] fPasv see documentation of CFTPClient::Passive
bool CFTPClient::List(const tstring& strPath, TSpFTPFileStatusVector& vFileList, bool fPasv) const
{
   COutputStream outputStream(mc_strEolCharacterSequence);
   //if( !ExecuteDatachannelCommand(CDatachannelCmd::LIST(), strPath, CRepresentation(CType::ASCII()), fPasv, 0, &outputStream) )
   if( !ExecuteDatachannelCommand(CDatachannelCmd::LIST(), strPath, CRepresentation(CType::ASCII()), true, 0, &outputStream) )
      return false;

   vFileList.clear();
   tstring strLine;
   CFTPListParse ftpListParser;
   outputStream.SetStartPosition();
   while( outputStream.GetNextLine(strLine) )
   {
      std::auto_ptr<CFTPFileStatus> pFtpFileStatus(new CFTPFileStatus());
      if( ftpListParser.Parse(*pFtpFileStatus, strLine) )
      {
         pFtpFileStatus->Path() = strPath;
         vFileList.push_back(pFtpFileStatus.release());
      }
   }

   return true;
}

/// Gets the directory listing of the ftp-server. Sends the NLST command to
/// the ftp-server.
/// @param[in] strPath Starting path for the list command.
/// @param[out] vFileList Returns a simple list of the files and folders of the specified directory.
///                       vFileList contains CFTPFileStatus-Objects. Normally these Objects provide 
///                       a lot of information about the file/folder. But the NLST-command provide 
///                       only a simple list of the directory content (no specific information).
/// @param[in] fPasv see documentation of CFTPClient::Passive
bool CFTPClient::NameList(const tstring& strPath, TSpFTPFileStatusVector& vFileList, bool fPasv) const
{
   COutputStream outputStream(mc_strEolCharacterSequence);
   if( !ExecuteDatachannelCommand(CDatachannelCmd::NLST(), strPath, CRepresentation(CType::ASCII()), fPasv, 0, &outputStream) )
      return false;

   vFileList.clear();
   tstring strLine;
   CFTPListParse ftpListParser;
   outputStream.SetStartPosition();
   while( outputStream.GetNextLine(strLine) )
   {
      std::auto_ptr<CFTPFileStatus> pFtpFileStatus(new CFTPFileStatus());
      pFtpFileStatus->Path() = strPath;
      pFtpFileStatus->Name() = strLine;
      vFileList.push_back(pFtpFileStatus.release());
   }

   return true;
}

/// Gets a file from the ftp-server.
/// Uses C functions for file access (very fast).
/// @param[in] strRemoteFile Filename of the sourcefile on the ftp-server.
/// @param[in] strLocalFile Filename of the targetfile on the local computer.
/// @param[in] repType Representation Type (see documentation of CRepresentation)
/// @param[in] fPasv see documentation of CFTPClient::Passive
bool CFTPClient::DownloadFile(const tstring& strRemoteFile, const tstring& strLocalFile, const CRepresentation& repType, bool fPasv) const
{
   CFile file;
   if( !file.Open(strLocalFile, m_fResumeIfPossible?_T("ab"):_T("wb")) )
   {
      ReportError(CError::GetErrorDescription(), CCnv::ConvertToTString(__FILE__), __LINE__);
      return false;
   }
   file.Seek(0, CFile::orEnd);

   long lRemoteFileSize = 0;
   FileSize(strRemoteFile, lRemoteFileSize);

   for( TObserverSet::const_iterator it=m_setObserver.begin(); it!=m_setObserver.end(); it++ )
      (*it)->OnPreReceiveFile(strRemoteFile, strLocalFile, lRemoteFileSize);

   const bool fRet=ExecuteDatachannelCommand(CDatachannelCmd::RETR(), strRemoteFile, repType, fPasv, file.Tell(), &file);

   for( TObserverSet::const_iterator it2=m_setObserver.begin(); it2!=m_setObserver.end(); it2++ )
      (*it2)->OnPostReceiveFile(strRemoteFile, strLocalFile, lRemoteFileSize);

   return fRet;
}

/// Puts a file on the ftp-server.
/// Uses C functions for file access (very fast).
/// @param[in] strLocalFile Filename of the the local sourcefile which to put on the ftp-server.
/// @param[in] strRemoteFile Filename of the targetfile on the ftp-server.
/// @param[in] fStoreUnique if true, the ftp command STOU is used for saving
///                         else the ftp command STOR is used.
/// @param[in] repType Representation Type (see documentation of CRepresentation)
/// @param[in] fPasv see documentation of CFTPClient::Passive
bool CFTPClient::UploadFile(const tstring& strLocalFile, const tstring& strRemoteFile, bool fStoreUnique, const CRepresentation& repType, bool fPasv) const
{
   CFile file;
   if( !file.Open(strLocalFile, L"rb") )
   {
      ReportError(CError::GetErrorDescription(), CCnv::ConvertToTString(__FILE__), __LINE__);
      return false;
   }

   long lRemoteFileSize = 0;
   if( m_fResumeIfPossible )
      FileSize(strRemoteFile, lRemoteFileSize);

   CDatachannelCmd cmd(CDatachannelCmd::STOR());
   if( lRemoteFileSize > 0 )
      cmd = CDatachannelCmd::APPE();
   else if( fStoreUnique )
      cmd = CDatachannelCmd::STOU();

   file.Seek(0, CFile::orEnd);
   long lLocalFileSize = file.Tell();
   file.Seek(lRemoteFileSize, CFile::orBegin);

   TObserverSet::const_iterator it;
   for( it=m_setObserver.begin(); it!=m_setObserver.end(); it++ )
      (*it)->OnPreSendFile(strLocalFile, strRemoteFile, lLocalFileSize);

   const bool fRet=ExecuteDatachannelCommand(cmd, strRemoteFile, repType, fPasv, 0, &file);
   //const bool fRet=ExecuteDatachannelCommand(cmd, strRemoteFile, repType, true, 0, &file);

   for( it=m_setObserver.begin(); it!=m_setObserver.end(); it++ )

⌨️ 快捷键说明

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