首页 运维 正文
FileZilla FTP 兼容FtpAnywhere

 2022-10-23    310  

  让FileZilla兼容FtpAnywhere

  FileZilla FTP是一个著名的开源标准FTP客户端软件,但是它的目前版本与FtpAnywhere提供的网格FTP有兼容问题,而且,目前无法通过它提供的那些设置模块来实现兼容,因此,我特地下载了它的源代码快照 [2009.4.16] ,看看是否有可能通过修改源代码来让它兼容.

FileZilla FTP 兼容FtpAnywhere

  解压缩它的源代码,转到子目录\src\engine下,打开ftpcontrolsocket.cpp文件,这个文件就是FileZilla用来支持标准FTP指令的核心,需要改造的是它的列表模式以及对PASV反馈的分析代码 [包括IPV6下的EPSV指令,但是暂时因为没有IPV6,所以没必要动它],改造它的PASV解析代码

  让FileZilla兼容FtpAnywhere

  boolCFtpControlSocket::ParsePasvResponse(CRawTransferOpData*pData) 
  •   {
  •   //Validateipaddress
  •   wxStringdigit=_T("0*[0-9]{1,3}");
  •   constwxChar*dot=_T(",");
  •   wxStringexp=_T("(|\\()(")+digit+dot+digit+dot+digit+dot+digit+dot+digit+dot+digit+_T(")(|\\)|$)");
  •   wxRegExregex;
  •   regex.Compile(exp);
  •   if(!regex.Matches(m_Response))
  •   returnfalse;
  •   pData->host=regex.GetMatch(m_Response,2);
  •   inti=pData->host.Find(',',true);
  •   longnumber;
  •   if(i==-1||!pData->host.Mid(i+1).ToLong(&number))
  •   returnfalse;
  •   pData->port=number;//getlsbyteofserversocket
  •   pData->host=pData->host.Left(i);
  •   i=pData->host.Find(',',true);
  •   if(i==-1||!pData->host.Mid(i+1).ToLong(&number))
  •   returnfalse;
  •   pData->port+=256*number;//addmsbyteofserversocket
  •   pData->host=pData->host.Left(i);
  •   pData->host.Replace(_T(","),_T("."));
  •   if(m_pProxyBackend)
  •   {
  •   //Wedonothaveanyinformationabouttheproxy'sinnerworkings
  •   returntrue;
  •   }
  •   constwxStringpeerIP=m_pSocket->GetPeerIP();
  •   if(!IsRoutableAddress(pData->host,m_pSocket->GetAddressFamily())&&IsRoutableAddress(peerIP,m_pSocket->GetAddressFamily()))
  •   {
  •   if(!m_pEngine->GetOptions()->GetOptionVal(OPTION_PASVREPLYFALLBACKMODE)||pData->bTriedActive)
  •   {
  •   LogMessage(Status,_("Serversentpassivereplywithunroutableaddress.Usingserveraddressinstead."));
  •   LogMessage(Debug_Info,_T("Reply:%s,peer:%s"),pData->host.c_str(),peerIP.c_str());
  •   pData->host=peerIP;
  •   }
  •   else
  •   {
  •   LogMessage(Status,_("Serversentpassivereplywithunroutableaddress.Passivemodefailed."));
  •   LogMessage(Debug_Info,_T("Reply:%s,peer:%s"),pData->host.c_str(),peerIP.c_str());
  •   returnfalse;
  •   }
  •   }
  •   returntrue;
  •   }
  •   这里是它原先的代码,导致PASV模式下无法下载的问题就出在它不知道有P2P传输这么个东西,因此加了个安全判断功能,只要把它注销就可以适合FtpAnywhere了,一般来说,只要FTP服务器是正规的服务器,那么这些代码完全是白费蜡,注销后的代码

      让FileZilla兼容FtpAnywhere

      boolCFtpControlSocket::ParsePasvResponse(CRawTransferOpData*pData) 
  •   {
  •   //Validateipaddress
  •   wxStringdigit=_T("0*[0-9]{1,3}");
  •   constwxChar*dot=_T(",");
  •   wxStringexp=_T("(|\\()(")+digit+dot+digit+dot+digit+dot+digit+dot+digit+dot+digit+_T(")(|\\)|$)");
  •   wxRegExregex;
  •   regex.Compile(exp);
  •   if(!regex.Matches(m_Response))
  •   returnfalse;
  •   pData->host=regex.GetMatch(m_Response,2);
  •   inti=pData->host.Find(',',true);
  •   longnumber;
  •   if(i==-1||!pData->host.Mid(i+1).ToLong(&number))
  •   returnfalse;
  •   pData->port=number;//getlsbyteofserversocket
  •   pData->host=pData->host.Left(i);
  •   i=pData->host.Find(',',true);
  •   if(i==-1||!pData->host.Mid(i+1).ToLong(&number))
  •   returnfalse;
  •   pData->port+=256*number;//addmsbyteofserversocket
  •   pData->host=pData->host.Left(i);
  •   pData->host.Replace(_T(","),_T("."));
  •   if(m_pProxyBackend)
  •   {
  •   //Wedonothaveanyinformationabouttheproxy'sinnerworkings
  •   returntrue;
  •   }
  •   //注意,把下面的代码注销,就可以支持P2PPASV模式下的连接传输了
  •   //constwxStringpeerIP=m_pSocket->GetPeerIP();
  •   //if(!IsRoutableAddress(pData->host,m_pSocket->GetAddressFamily())&&IsRoutableAddress(peerIP,m_pSocket->GetAddressFamily()))
  •   //{
  •   //if(!m_pEngine->GetOptions()->GetOptionVal(OPTION_PASVREPLYFALLBACKMODE)||pData->bTriedActive)
  •   //{
  •   //LogMessage(Status,_("Serversentpassivereplywithunroutableaddress.Usingserveraddressinstead."));
  •   //LogMessage(Debug_Info,_T("Reply:%s,peer:%s"),pData->host.c_str(),peerIP.c_str());
  •   //pData->host=peerIP;
  •   //}
  •   //else
  •   //{
  •   //LogMessage(Status,_("Serversentpassivereplywithunroutableaddress.Passivemodefailed."));
  •   //LogMessage(Debug_Info,_T("Reply:%s,peer:%s"),pData->host.c_str(),peerIP.c_str());
  •   //returnfalse;
  •   //}
  •   //}
  •   returntrue;
  •   }
  • #p#

      那么现在的代码,只要在站点属性的连接模式里,指定PORT为优先,在PORT模式连接失败后,设置自动切换到PASV模式,已经可以有条件兼容,只是***次下载会失败而已,下面我们改造它的列表模式,让它具备更好的兼容性. 当然,你可以在FtpAnywhere服务器里,设置禁止根目录下PASV列表,来让FileZilla自动判断连接模式,但是从它的代码看,它的判断还是存在一点兼容问题.因此,将LIST改造成主动模式优先,是***的选择.

      问题在这里

      CRawTransferOpData::CRawTransferOpData() 
  •   :COpData(cmd_rawtransfer)
  •   {
  •   bTriedPasv=bTriedActive=false;
  •   bPasv=true;
  •   }
  •   它的初始化是被动模式优先,这样,列表的时候将发生问题,但是下载可以成功,但是我阅读代码,发现除非额外指定一个列表时优先使用的模式变量,否则很难修改代码,因为它的代码中列表和文件传输的优先模式是一致的,还要适应其他标准FTP站点,毕竟我不可以能让它为我的FtpAnywhere进行优化,方法是,在FtpControlSocket.h里定义的类

      classCRawTransferOpData:publicCOpData 
  •   {
  •   public:
  •   CRawTransferOpData();
  •   wxStringcmd;
  •   CFtpTransferOpData*pOldData;
  •   boolbPasv;
  •   boolbTriedPasv;
  •   boolbTriedActive;
  •   wxStringhost;
  •   intport;
  •   };
  •   给它加个额外的变量,例如 bool bFtpAnywhere;然后,在List指令前,确定首先采用PASV或者PORT前,判断 bFtpAnywhere是否为真,如果为真,那么列表应该优先采用PORT模式,否则继续执行默认的动作;而bFtpAnywhere的初始化应该从给服务器发送 VDSI指令是否返回2XX来判断,是否是一个FtpAnywhere服务器,因为这里涉及的修改太多,除非FileZilla代码维护人员同意,否则没有意义,因此,最简单最快的方法还是直接注销我上面给出的代码,虽然无法获得100%兼容,但是基本可以兼容,而且通过设置项目,可以做到手动兼容.

    原文链接:https://77isp.com/post/8612.html

    =========================================

    https://77isp.com/ 为 “云服务器技术网” 唯一官方服务平台,请勿相信其他任何渠道。