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

📄 ftpclient.cpp

📁 实现了wince 客户端上传下载查看文件及目录的功能接口d
💻 CPP
📖 第 1 页 / 共 5 页
字号:
      tstring strSingleLine(strResponse);
      const int iRetCode=CCnv::TStringToLong(strResponse);
      // handle multi-line server responses
      while( !(strSingleLine.length()>3 && 
               strSingleLine.at(3)==_T(' ') &&
               CCnv::TStringToLong(strSingleLine)==iRetCode) )
      { 
         if( !GetSingleResponseLine(strSingleLine) )
            return false;
         strResponse += _T("\r\n") + strSingleLine;
      }
   }

   bool fRet = Reply.Set(strResponse);

   for( TObserverSet::const_iterator it=m_setObserver.begin(); it!=m_setObserver.end(); it++ )
      (*it)->OnResponse(Reply);

   return fRet;
}

/// Reads a single response line from the server control channel.
/// @param[out] strResponse Response of the server as string.
bool CFTPClient::GetSingleResponseLine(tstring& strResponse) const
{
   if( !IsConnected() )
      return false;

   try
   {
      if( m_qResponseBuffer.empty() )
      {
         // internal buffer is empty ==> get response from ftp-server
         int iNum=0;
         std::string strTemp;

         do
         {
            iNum=m_apSckControlConnection->Receive(&(*m_vBuffer.begin()), static_cast<int>(m_vBuffer.size())-1, mc_uiTimeout);
            if( mc_uiResponseWait !=0 )
               Sleep(mc_uiResponseWait);
            m_vBuffer[iNum] = '\0';
            strTemp+=&(*m_vBuffer.begin());
         } while( iNum==static_cast<int>(m_vBuffer.size())-1 && m_apSckControlConnection->CheckReadability() );

         // each line in response is a separate entry in the internal buffer
         while( strTemp.length() )
         {
            size_t iCRLF=strTemp.find('\n');
            if( iCRLF != std::string::npos )
            {
               m_qResponseBuffer.push(strTemp.substr(0, iCRLF+1));
               strTemp.erase(0, iCRLF+1);
            }
            else
            {
               // this is not rfc standard; normally each command must end with CRLF
               // in this case it doesn't
               m_qResponseBuffer.push(strTemp);
               strTemp.clear();
            }
         }

         if( m_qResponseBuffer.empty() )
            return false;
      }

      // get first response-line from buffer
      strResponse = CCnv::ConvertToTString(m_qResponseBuffer.front().c_str());
      m_qResponseBuffer.pop();

      // remove CrLf if exists
      if( strResponse.length()> 1 && strResponse.substr(strResponse.length()-2)==_T("\r\n") )
         strResponse.erase(strResponse.length()-2, 2);
   }
   catch(CBlockingSocketException& blockingException)
   {
      ReportError(blockingException.GetErrorMessage(), CCnv::ConvertToTString(__FILE__), __LINE__);
      const_cast<CFTPClient*>(this)->m_apSckControlConnection->Cleanup();
      return false;
   }

   return true;
}

/// Executes the ftp command CDUP (change to parent directory).
/// This command is a special case of CFTPClient::ChangeWorkingDirectory 
/// (CWD), and is  included to simplify the implementation of programs for 
/// transferring directory trees between operating systems having different 
/// syntaxes for naming the parent directory.
/// @return see return values of CFTPClient::SimpleErrorCheck
int CFTPClient::ChangeToParentDirectory() const
{
   CReply Reply;
   if( !SendCommand(_T("CDUP"), Reply) )
      return FTP_ERROR;
   return SimpleErrorCheck(Reply);
}

/// Executes the ftp command QUIT.
/// This command terminates a USER and if file transfer is not in progress, 
/// the server closes the control connection. If  file transfer is in progress, 
/// the connection will remain open for result response and the server will 
/// then close it.
/// If the user-process is transferring files for several USERs but does not 
/// wish to close and then reopen connections for each, then the REIN command 
/// should be used instead of QUIT.
/// An unexpected close on the control connection will cause the server to take 
/// the effective action of an abort (ABOR) and a logout.
/// @return see return values of CFTPClient::SimpleErrorCheck
int CFTPClient::Logout()
{
   CReply Reply;
   if( !SendCommand(_T("QUIT"), Reply) )
      return FTP_ERROR;

   CloseControlChannel();

   return SimpleErrorCheck(Reply);
}

/// Executes the ftp command PASV. Set the passive mode.
/// This command requests the server-DTP (data transfer process) on a data to 
/// "listen"  port (which is not its default data port) and to wait for a 
/// connection rather than initiate one upon receipt of a transfer command. 
/// The response to this command includes the host and port address this 
/// server is listening on.
/// @param[out] ulIpAddress IP address the server is listening on.
/// @param[out] ushPort Port the server is listening on.
/// @return see return values of CFTPClient::SimpleErrorCheck
int CFTPClient::Passive(ULONG& ulIpAddress, USHORT& ushPort) const
{
   CReply Reply;
   if( !SendCommand(_T("PASV"), Reply) )
      return FTP_ERROR;

   if( Reply.Code().IsPositiveCompletionReply() )
   {
      if( !GetIpAddressFromResponse(Reply.Value(), ulIpAddress, ushPort) )
         return FTP_ERROR;
   }

   return SimpleErrorCheck(Reply);
}

/// Parses a response string and extracts the ip address and port information.
/// @param[in]  strResponse The response string of a ftp server which holds 
///                         the ip address and port information.
/// @param[out] ulIpAddress Buffer for the ip address.
/// @param[out] ushPort     Buffer for the port information.
/// @retval true  Everything went ok.
/// @retval false An error occurred (invalid format).
bool CFTPClient::GetIpAddressFromResponse(const tstring& strResponse, ULONG& ulIpAddress, USHORT& ushPort) const
{
   // parsing of ip-address and port implemented with a finite state machine
   // ...(192,168,1,1,3,44)...
   enum T_enState { state0, state1, state2, state3, state4 } enState = state0;
   
   tstring strIpAddress, strPort;
   USHORT ushTempPort = 0;
   ULONG  ulTempIpAddress = 0;
   int iCommaCnt = 4;
   for( tstring::const_iterator it=strResponse.begin(); it!=strResponse.end(); ++it )
   {
      switch( enState )
      {
      case state0:
         if( *it == _T('(') )
            enState = state1;
         break;
      case state1:
         if( *it == _T(',') )
         {
            if( --iCommaCnt == 0 )
            {
               enState = state2;
               ulTempIpAddress += CCnv::TStringToLong(strIpAddress.c_str());
            }
            else
            {
               ulTempIpAddress += CCnv::TStringToLong(strIpAddress.c_str())<<8*iCommaCnt;
               strIpAddress.clear();
            }
         }
         else
         {
            if( !tisdigit(*it) )
               return false;
            strIpAddress += *it;
         }
         break;
      case state2:
         if( *it == _T(',') )
         {
            ushTempPort = static_cast<USHORT>(CCnv::TStringToLong(strPort.c_str())<<8);
            strPort.clear();
            enState = state3;
         }
         else
         {
            if( !tisdigit(*it) )
               return false;
            strPort += *it;
         }
         break;
      case state3:
         if( *it == _T(')') )
         {
            // compiler warning if using +=operator
            ushTempPort = ushTempPort + static_cast<USHORT>(CCnv::TStringToLong(strPort.c_str()));
            enState = state4;
         }
         else
         {
            if( !tisdigit(*it) )
               return false;
            strPort += *it;
         }
      }
   }

   if( enState==state4 )
   {
      ulIpAddress = ulTempIpAddress;
      ushPort = ushTempPort;
   }

   return enState==state4;
}

/// Executes the ftp command ABOR.
/// This command tells the server to abort the previous FTP service command 
/// and any associated transfer of data.  The abort command may require 
/// "special action", as discussed in the Section on FTP Commands, to force 
/// recognition by the server.  No action is to be taken if the previous 
/// command has been completed (including data transfer).  The control
/// connection is not to be closed by the server, but the data connection 
/// must be closed.
/// There are two cases for the server upon receipt of this command:<BR>
/// (1) the FTP service command was already completed, or <BR>
/// (2) the FTP service command is still in progress.<BR>
/// In the first case, the server closes the data connection (if it is open)
/// and responds with a 226 reply, indicating that the abort command was 
/// successfully processed.
/// In the second case, the server aborts the FTP service in progress and 
/// closes the data connection, returning a 426 reply to indicate that the 
/// service request terminated abnormally.  The server then sends a 226 reply,
/// indicating that the abort command was successfully processed.
/// @return see return values of CFTPClient::SimpleErrorCheck
int CFTPClient::Abort() const
{
   if( m_fTransferInProgress )
   {
      m_fAbortTransfer = true;
      return FTP_OK;
   }

   m_fAbortTransfer = false;
   CReply Reply;
   if( !SendCommand(_T("ABOR"), Reply) )
      return FTP_ERROR;
   return SimpleErrorCheck(Reply);
}
/// Executes the ftp command PWD (PRINT WORKING DIRECTORY)
/// This command causes the name of the current working directory 
/// to be returned in the reply.
int CFTPClient::PrintWorkingDirectory() const
{
   CReply Reply;
   if( !SendCommand(_T("PWD"), Reply) )
      return FTP_ERROR;
   return SimpleErrorCheck(Reply);
}

/// Executes the ftp command SYST (SYSTEM)
/// This command is used to find out the type of operating system at the server.
/// The reply shall have as its first word one of the system names listed in the 
/// current version of the Assigned Numbers document [Reynolds, Joyce, and 
/// Jon Postel, "Assigned Numbers", RFC 943, ISI, April 1985.].
/// @return see return values of CFTPClient::SimpleErrorCheck
int CFTPClient::System() const
{
   CReply Reply;
   if( !SendCommand(_T("SYST"), Reply) )
      return FTP_ERROR;
   return SimpleErrorCheck(Reply);
}

/// Executes the ftp command NOOP
/// This command does not affect any parameters or previously entered commands. 
/// It specifies no action other than that the server send an FTP_OK reply.
/// @return see return values of CFTPClient::SimpleErrorCheck
int CFTPClient::Noop() const
{
   CReply Reply;
   if( !SendCommand(_T("NOOP"), Reply) )
      return FTP_ERROR;
   return SimpleErrorCheck(Reply);
}

/// Executes the ftp command PORT (DATA PORT)
/// The argument is a HOST-PORT specification for the data port to be used in data 
/// connection. There are defaults for both the user and server data ports, and 
/// under normal circumstances this command and its reply are not needed.  If
/// this command is used, the argument is the concatenation of a 32-bit internet 
/// host address and a 16-bit TCP port address.
/// @param[in] strHostIP IP-address like xxx.xxx.xxx.xxx
/// @param[in] uiPort 16-bit TCP port address.
/// @return see return values of CFTPClient::SimpleErrorCheck
int CFTPClient::DataPort(const tstring& strHostIP, USHORT ushPort) const
{
   tstring strPortCmd;
   // convert the port number to 2 bytes + add to the local IP
   strPortCmd = CMakeString() << _T("PORT ") << strHostIP << _T(",") << (ushPort>>8) << _T(",") << (ushPort&0xFF);

   ReplaceStr(strPortCmd, _T("."), _T(","));

   CReply Reply;
   if( !SendCommand(strPortCmd, Reply) )
      return FTP_ERROR;
   return SimpleErrorCheck(Reply);
}

/// Executes the ftp command TYPE (REPRESENTATION TYPE)
/// see Documentation of nsFTP::CRepresentation
/// @param[in] representation see Documentation of nsFTP::CRepresentation
/// @param[in] iSize Indicates Bytesize for type LocalByte.
/// @return see return values of CFTPClient::SimpleErrorCheck
int CFTPClient::RepresentationType(const CRepresentation& representation, DWORD dwSize) const
{
   tstring strCmd;
   switch( representation.Type().AsEnum() )
   {
   case CType::tyASCII:     strCmd = _T("TYPE A");                             break;
   case CType::tyEBCDIC:    strCmd = _T("TYPE E");                             break;
   case CType::tyImage:     strCmd = _T("TYPE I");                             break;
   case CType::tyLocalByte: strCmd = CMakeString() << _T("TYPE L ") << dwSize; break;
   default:
      ASSERT( false );
      return FTP_ERROR;
   }

   if( representation.Type()==CType::tyASCII || 
       representation.Type()==CType::tyEBCDIC )

⌨️ 快捷键说明

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